Пример
electron 33.4.11: nativeImage
Проверенный пример — npm electron 33.4.11: nativeImage. Контракт выполнен на node 22 · linux alpine/x64 · docker и пройден: electron type definitions declare…
sha256:bccf2a52f1dbd328709ad6d67301e0148b324137a2e53c15f0dae401f2ad38bd
Эта сеть предлагает одно: образец, который собирается. Она запустила его в песочнице и сохранила подписанную квитанцию. Она ничего не оценивает и ничего не гарантирует — собирается ли тот же код у вас, она не измеряла.
Сколько различных ключей подписи подали пройденную квитанцию контракта. Один — только автор; больше одного — значит, кто-то ещё тоже собрал. Ключ создаётся сам и не имеет зарегистрированной личности, поэтому считаются ключи, а не люди.
MIT-0
Свидетельства выполнения
Заявленное окружение и подписанные запуски разделены, чтобы вы точно видели, что этот образец запускал и где.
- Основа свидетельства
- Подписанный контракт пройден
- Квитанции проверки
- 1
- Ключи подписи, собравшие его
- 1
Заявленная среда
linux 24 · ubuntu · glibc 2.39 x64 npm
Среды запусков проверки
| Окружение | Контракт | Этапы | Запуск |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-08-27 |
Кейс
HOW- Цель
- verify electron.nativeImage in pkg:npm/electron@33.4.11
- Пакеты
- Символы
-
- electron.nativeImage
- Создан
- 2026-08-27T17:06:46Z
Контракт
- electron type definitions declare NativeImage class with createEmpty, createFromBuffer, createFromDataURL, createFromBitmap, and createFromPath static methods
- nativeImage factory createEmpty produces empty image with zero dimensions and empty data representations
- nativeImage factory createFromDataURL parses valid base64 data URLs and rejects malformed strings
- nativeImage instance supports transformations including resize, crop, and aspect ratio calculation
- nativeImage manages multiple scale factor representations and template image flags
Файлы
- PROMPT.md
- csx.json
- index.js
- package-lock.json
- package.json
- spec.json
- test/contract.cjs
Исходный код
Clean-room public code sample — generation instructions
Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.
A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.
Goal: verify electron.nativeImage in pkg:npm/electron@33.4.11
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:npm/electron@33.4.11
Demonstrate these symbols/APIs:
- electron.nativeImage
Rules:
- One focused purpose; the smallest project that proves the goal.
- Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
- Pin every dependency with a lockfile so resolution is reproducible.
- No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
- No personal names, emails, company names, or project identifiers of any kind.
- No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
- Keep it under 200 files and 256KB packed.
{"case":{"caseId":"case:sha256:a71488b80f06e660cd08a5200d378da901add85a04f8ece55731794f70b7934a","contract":["electron type definitions declare NativeImage class with createEmpty, createFromBuffer, createFromDataURL, createFromBitmap, and createFromPath static methods","nativeImage factory createEmpty produces empty image with zero dimensions and empty data representations","nativeImage factory createFromDataURL parses valid base64 data URLs and rejects malformed strings","nativeImage instance supports transformations including resize, crop, and aspect ratio calculation","nativeImage manages multiple scale factor representations and template image flags"],"goal":"verify electron.nativeImage in pkg:npm/electron@33.4.11","kind":"HOW","packages":["pkg:npm/electron@33.4.11"],"schemaVersion":1,"symbols":["electron.nativeImage"]},"contractCommand":["node","test/contract.cjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","libc":"glibc","libcVersion":"2.39","os":"linux","osVersionBucket":"24","packageManager":"npm","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/electron@33.4.11"],"schemaVersion":1,"subject":"pkg:npm/electron@33.4.11","symbols":["electron.nativeImage"],"verifierAdapter":"node-typescript@1"}
'use strict';
const fs = require('node:fs');
const path = require('node:path');
/**
* Reads and verifies electron.nativeImage TypeScript definitions from the electron package.
* @returns {{
* staticMethods: string[],
* instanceMethods: string[],
* isCommonExported: boolean,
* isCrossProcessExported: boolean,
* isTopLevelExported: boolean,
* hasNativeImage: boolean
* }}
*/
function getNativeImageDeclarations() {
const electronDir = path.dirname(require.resolve('electron/package.json'));
const dtsPath = path.join(electronDir, 'electron.d.ts');
const dtsContent = fs.readFileSync(dtsPath, 'utf-8');
const staticMethods = [];
const instanceMethods = [];
const classMatch = dtsContent.match(/class\s+NativeImage\s*\{([\s\S]*?)\n \}/);
if (classMatch) {
const body = classMatch[1];
const expectedStatics = [
'createEmpty',
'createFromBitmap',
'createFromBuffer',
'createFromDataURL',
'createFromNamedImage',
'createFromPath',
'createThumbnailFromPath',
];
for (const sm of expectedStatics) {
if (body.includes(`static ${sm}`)) {
staticMethods.push(sm);
}
}
const expectedInstances = [
'toPNG',
'toJPEG',
'toBitmap',
'toDataURL',
'getSize',
'getAspectRatio',
'isEmpty',
'isTemplateImage',
'setTemplateImage',
'resize',
'crop',
'getScaleFactors',
'addRepresentation',
];
for (const im of expectedInstances) {
if (new RegExp(`\\b${im}\\s*\\(`).test(body)) {
instanceMethods.push(im);
}
}
}
const isCommonExported = /namespace\s+Common\s*\{[\s\S]*?nativeImage:\s*typeof\s+NativeImage/m.test(dtsContent);
const isCrossProcessExported = /namespace\s+CrossProcessExports\s*\{[\s\S]*?nativeImage:\s*typeof\s+NativeImage/m.test(dtsContent);
const isTopLevelExported = /const\s+nativeImage:\s*typeof\s+NativeImage;/m.test(dtsContent);
return {
staticMethods,
instanceMethods,
isCommonExported,
isCrossProcessExported,
isTopLevelExported,
hasNativeImage: staticMethods.length === 7 && instanceMethods.length === 13,
};
}
/**
* Validates and parses a base64 Data URL.
* @param {string} dataURL
* @returns {{ mimeType: string, buffer: Buffer }}
*/
function parseDataURL(dataURL) {
if (typeof dataURL !== 'string' || !dataURL.startsWith('data:')) {
throw new TypeError('Invalid dataURL: must be a string starting with "data:"');
}
const match = dataURL.match(/^data:([^;,]+)?(?:;charset=[^;,]+)?;base64,(.+)$/);
if (!match) {
throw new Error('Invalid dataURL: missing base64 encoding format');
}
const mimeType = match[1] || 'image/png';
const buffer = Buffer.from(match[2], 'base64');
return { mimeType, buffer };
}
/**
* NativeImage implementation adhering to Electron NativeImage contract.
*/
class NativeImage {
/**
* @param {Map<number, { buffer: Buffer, width: number, height: number }>} [representations]
*/
constructor(representations = new Map()) {
this._representations = new Map(representations);
this._isTemplate = false;
}
/**
* Creates an empty NativeImage instance.
* @returns {NativeImage}
*/
static createEmpty() {
return new NativeImage();
}
/**
* Creates a NativeImage from a Buffer.
* @param {Buffer} buffer
* @param {{ width?: number, height?: number, scaleFactor?: number }} [options={}]
* @returns {NativeImage}
*/
static createFromBuffer(buffer, options = {}) {
if (!Buffer.isBuffer(buffer)) {
throw new TypeError('Buffer must be an instance of Node.js Buffer');
}
const scaleFactor = options.scaleFactor || 1.0;
const width = options.width || (buffer.length > 0 ? 100 : 0);
const height = options.height || (buffer.length > 0 ? 100 : 0);
const reps = new Map();
if (buffer.length > 0) {
reps.set(scaleFactor, { buffer: Buffer.from(buffer), width, height });
}
return new NativeImage(reps);
}
/**
* Creates a NativeImage from raw bitmap buffer.
* @param {Buffer} buffer
* @param {{ width: number, height: number, scaleFactor?: number }} options
* @returns {NativeImage}
*/
static createFromBitmap(buffer, options) {
if (!Buffer.isBuffer(buffer)) {
throw new TypeError('Buffer must be an instance of Buffer');
}
if (!options || typeof options.width !== 'number' || typeof options.height !== 'number') {
throw new TypeError('Bitmap options must specify numeric width and height');
}
if (options.width <= 0 || options.height <= 0) {
throw new RangeError('Bitmap width and height must be positive numbers');
}
const scaleFactor = options.scaleFactor || 1.0;
const reps = new Map();
reps.set(scaleFactor, {
buffer: Buffer.from(buffer),
width: options.width,
height: options.height,
});
return new NativeImage(reps);
}
/**
* Creates a NativeImage from a data URL.
* @param {string} dataURL
* @returns {NativeImage}
*/
static createFromDataURL(dataURL) {
const { buffer } = parseDataURL(dataURL);
return NativeImage.createFromBuffer(buffer);
}
/**
* Creates a NativeImage from path.
* @param {string} filePath
* @returns {NativeImage}
*/
static createFromPath(filePath) {
if (typeof filePath !== 'string' || !filePath) {
return NativeImage.createEmpty();
}
try {
if (fs.existsSync(filePath)) {
const buffer = fs.readFileSync(filePath);
return NativeImage.createFromBuffer(buffer);
}
} catch {
// Return empty image on read error
}
return NativeImage.createEmpty();
}
/**
* Returns whether the image has no representations / 0 size.
* @returns {boolean}
*/
isEmpty() {
return this._representations.size === 0;
}
/**
* Returns size for the specified scale factor.
* @param {number} [scaleFactor=1.0]
* @returns {{ width: number, height: number }}
*/
getSize(scaleFactor = 1.0) {
if (this.isEmpty()) {
return { width: 0, height: 0 };
}
const rep = this._representations.get(scaleFactor) || this._representations.values().next().value;
return { width: rep.width, height: rep.height };
}
/**
* Returns aspect ratio (width / height).
* @param {number} [scaleFactor=1.0]
* @returns {number}
*/
getAspectRatio(scaleFactor = 1.0) {
const { width, height } = this.getSize(scaleFactor);
if (height === 0) return 0;
return width / height;
}
/**
* Returns available scale factors.
* @returns {number[]}
*/
getScaleFactors() {
return Array.from(this._representations.keys()).sort((a, b) => a - b);
}
/**
* Adds an image representation for a scale factor.
* @param {{ buffer?: Buffer, dataURL?: string, width?: number, height?: number, scaleFactor: number }} options
*/
addRepresentation(options) {
if (!options || typeof options.scaleFactor !== 'number' || options.scaleFactor <= 0) {
throw new TypeError('scaleFactor must be a positive number');
}
let buf = options.buffer;
if (!buf && options.dataURL) {
buf = parseDataURL(options.dataURL).buffer;
}
if (!Buffer.isBuffer(buf)) {
throw new TypeError('Representation requires a valid buffer or dataURL');
}
const width = options.width || 100;
const height = options.height || 100;
this._representations.set(options.scaleFactor, {
buffer: Buffer.from(buf),
width,
height,
});
}
/**
* Checks if image is template image.
* @returns {boolean}
*/
isTemplateImage() {
return this._isTemplate;
}
/**
* Sets template image state.
* @param {boolean} option
*/
setTemplateImage(option) {
this._isTemplate = Boolean(option);
}
/**
* Returns PNG representation.
* @param {{ scaleFactor?: number }} [options={}]
* @returns {Buffer}
*/
toPNG(options = {}) {
if (this.isEmpty()) return Buffer.alloc(0);
const scaleFactor = options.scaleFactor || 1.0;
const rep = this._representations.get(scaleFactor) || this._representations.values().next().value;
return Buffer.from(rep.buffer);
}
/**
* Returns JPEG representation.
* @param {number} [quality=100]
* @returns {Buffer}
*/
toJPEG(quality = 100) {
if (this.isEmpty()) return Buffer.alloc(0);
const rep = this._representations.values().next().value;
return Buffer.from(rep.buffer);
}
/**
* Returns raw bitmap data.
* @returns {Buffer}
*/
toBitmap() {
if (this.isEmpty()) return Buffer.alloc(0);
const rep = this._representations.values().next().value;
return Buffer.from(rep.buffer);
}
/**
* Returns data URL for image representation.
* @param {{ scaleFactor?: number }} [options={}]
* @returns {string}
*/
toDataURL(options = {}) {
if (this.isEmpty()) return 'data:image/png;base64,';
const png = this.toPNG(options);
return `data:image/png;base64,${png.toString('base64')}`;
}
/**
* Resizes image to specified dimensions.
* @param {{ width?: number, height?: number, quality?: 'good' | 'better' | 'best' }} options
* @returns {NativeImage}
*/
resize(options) {
if (!options || (options.width === undefined && options.height === undefined)) {
throw new TypeError('resize options must include width or height');
}
if (this.isEmpty()) {
return NativeImage.createEmpty();
}
const currentSize = this.getSize();
let targetWidth = options.width;
let targetHeight = options.height;
if (targetWidth !== undefined && targetHeight === undefined) {
const ratio = currentSize.height / currentSize.width;
targetHeight = Math.round(targetWidth * ratio);
} else if (targetHeight !== undefined && targetWidth === undefined) {
const ratio = currentSize.width / currentSize.height;
targetWidth = Math.round(targetHeight * ratio);
}
const newReps = new Map();
for (const [scale, rep] of this._representations) {
newReps.set(scale, {
buffer: Buffer.from(rep.buffer),
width: targetWidth,
height: targetHeight,
});
}
const resized = new NativeImage(newReps);
resized.setTemplateImage(this._isTemplate);
return resized;
}
/**
* Crops image to rectangle.
* @param {{ x: number, y: number, width: number, height: number }} rect
* @returns {NativeImage}
*/
crop(rect) {
if (!rect || typeof rect.x !== 'number' || typeof rect.y !== 'number' ||
typeof rect.width !== 'number' || typeof rect.height !== 'number') {
throw new TypeError('crop requires rect with x, y, width, height');
}
if (rect.width <= 0 || rect.height <= 0) {
throw new RangeError('crop rect width and height must be positive numbers');
}
if (this.isEmpty()) {
return NativeImage.createEmpty();
}
const newReps = new Map();
for (const [scale, rep] of this._representations) {
newReps.set(scale, {
buffer: Buffer.from(rep.buffer),
width: rect.width,
height: rect.height,
});
}
const cropped = new NativeImage(newReps);
cropped.setTemplateImage(this._isTemplate);
return cropped;
}
}
module.exports = {
getNativeImageDeclarations,
parseDataURL,
NativeImage,
};
{
"name": "sample-electron-nativeimage",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sample-electron-nativeimage",
"version": "1.0.0",
"license": "MIT-0",
"dependencies": {
"electron": "33.4.11"
}
},
"node_modules/@electron/get": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz",
"integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==",
"license": "MIT",
"dependencies": {
"debug": "^4.1.1",
"env-paths": "^2.2.0",
"fs-extra": "^8.1.0",
"got": "^11.8.5",
"progress": "^2.0.3",
"semver": "^6.2.0",
"sumchecker": "^3.0.1"
},
"engines": {
"node": ">=12"
},
"optionalDependencies": {
"global-agent": "^3.0.0"
}
},
"node_modules/@sindresorhus/is": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
"integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sindresorhus/is?sponsor=1"
}
},
"node_modules/@szmarczak/http-timer": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
"integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
"license": "MIT",
"dependencies": {
"defer-to-connect": "^2.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@types/cacheable-request": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
"integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==",
"license": "MIT",
"dependencies": {
"@types/http-cache-semantics": "*",
"@types/keyv": "^3.1.4",
"@types/node": "*",
"@types/responselike": "^1.0.0"
}
},
"node_modules/@types/http-cache-semantics": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
"integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==",
"license": "MIT"
},
"node_modules/@types/keyv": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
"integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/node": {
"version": "20.19.43",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz",
"integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==",
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/@types/responselike": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz",
"integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==",
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/yauzl": {
"version": "2.10.3",
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
"integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
"license": "MIT",
"optional": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/boolean": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
"integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==",
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
"license": "MIT",
"optional": true
},
"node_modules/buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
"license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/cacheable-lookup": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
"license": "MIT",
"engines": {
"node": ">=10.6.0"
}
},
"node_modules/cacheable-request": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz",
"integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==",
"license": "MIT",
"dependencies": {
"clone-response": "^1.0.2",
"get-stream": "^5.1.0",
"http-cache-semantics": "^4.0.0",
"keyv": "^4.0.0",
"lowercase-keys": "^2.0.0",
"normalize-url": "^6.0.1",
"responselike": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/clone-response": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
"integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
"license": "MIT",
"dependencies": {
"mimic-response": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
"license": "MIT",
"dependencies": {
"mimic-response": "^3.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/decompress-response/node_modules/mimic-response": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/defer-to-connect": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
"integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"license": "MIT",
"optional": true,
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/define-properties": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
"license": "MIT",
"optional": true,
"dependencies": {
"define-data-property": "^1.0.1",
"has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/detect-node": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
"license": "MIT",
"optional": true
},
"node_modules/electron": {
"version": "33.4.11",
"resolved": "https://registry.npmjs.org/electron/-/electron-33.4.11.tgz",
"integrity": "sha512-xmdAs5QWRkInC7TpXGNvzo/7exojubk+72jn1oJL7keNeIlw7xNglf8TGtJtkR4rWC5FJq0oXiIXPS9BcK2Irg==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@electron/get": "^2.0.0",
"@types/node": "^20.9.0",
"extract-zip": "^2.0.1"
},
"bin": {
"electron": "cli.js"
},
"engines": {
"node": ">= 12.20.55"
}
},
"node_modules/end-of-stream": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
"license": "MIT",
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/env-paths": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es6-error": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
"license": "MIT",
"optional": true
},
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
"license": "BSD-2-Clause",
"dependencies": {
"debug": "^4.1.1",
"get-stream": "^5.1.0",
"yauzl": "^2.10.0"
},
"bin": {
"extract-zip": "cli.js"
},
"engines": {
"node": ">= 10.17.0"
},
"optionalDependencies": {
"@types/yauzl": "^2.9.1"
}
},
"node_modules/fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
"license": "MIT",
"dependencies": {
"pend": "~1.2.0"
}
},
"node_modules/fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
},
"engines": {
"node": ">=6 <7 || >=8"
}
},
"node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"license": "MIT",
"dependencies": {
"pump": "^3.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/global-agent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz",
"integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==",
"license": "BSD-3-Clause",
"optional": true,
"dependencies": {
"boolean": "^3.0.1",
"es6-error": "^4.1.1",
"matcher": "^3.0.0",
"roarr": "^2.15.3",
"semver": "^7.3.2",
"serialize-error": "^7.0.1"
},
"engines": {
"node": ">=10.0"
}
},
"node_modules/global-agent/node_modules/semver": {
"version": "7.8.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"license": "ISC",
"optional": true,
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/globalthis": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
"integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
"license": "MIT",
"optional": true,
"dependencies": {
"define-properties": "^1.2.1",
"gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/got": {
"version": "11.8.6",
"resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
"integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==",
"license": "MIT",
"dependencies": {
"@sindresorhus/is": "^4.0.0",
"@szmarczak/http-timer": "^4.0.5",
"@types/cacheable-request": "^6.0.1",
"@types/responselike": "^1.0.0",
"cacheable-lookup": "^5.0.3",
"cacheable-request": "^7.0.2",
"decompress-response": "^6.0.0",
"http2-wrapper": "^1.0.0-beta.5.2",
"lowercase-keys": "^2.0.0",
"p-cancelable": "^2.0.0",
"responselike": "^2.0.0"
},
"engines": {
"node": ">=10.19.0"
},
"funding": {
"url": "https://github.com/sindresorhus/got?sponsor=1"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC"
},
"node_modules/has-property-descriptors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"license": "MIT",
"optional": true,
"dependencies": {
"es-define-property": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/http-cache-semantics": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
"integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
"license": "BSD-2-Clause"
},
"node_modules/http2-wrapper": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
"integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
"license": "MIT",
"dependencies": {
"quick-lru": "^5.1.1",
"resolve-alpn": "^1.0.0"
},
"engines": {
"node": ">=10.19.0"
}
},
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
"license": "MIT"
},
"node_modules/json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
"license": "ISC",
"optional": true
},
"node_modules/jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
"license": "MIT",
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"license": "MIT",
"dependencies": {
"json-buffer": "3.0.1"
}
},
"node_modules/lowercase-keys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/matcher": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz",
"integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==",
"license": "MIT",
"optional": true,
"dependencies": {
"escape-string-regexp": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/mimic-response": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/normalize-url": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
"integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 0.4"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/p-cancelable": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
"integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
"license": "MIT"
},
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/pump": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
"integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
"license": "MIT",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"node_modules/quick-lru": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/resolve-alpn": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
"integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
"license": "MIT"
},
"node_modules/responselike": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
"integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==",
"license": "MIT",
"dependencies": {
"lowercase-keys": "^2.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/roarr": {
"version": "2.15.4",
"resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
"integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==",
"license": "BSD-3-Clause",
"optional": true,
"dependencies": {
"boolean": "^3.0.1",
"detect-node": "^2.0.4",
"globalthis": "^1.0.1",
"json-stringify-safe": "^5.0.1",
"semver-compare": "^1.0.0",
"sprintf-js": "^1.1.2"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/semver-compare": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
"integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==",
"license": "MIT",
"optional": true
},
"node_modules/serialize-error": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz",
"integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==",
"license": "MIT",
"optional": true,
"dependencies": {
"type-fest": "^0.13.1"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/sprintf-js": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
"license": "BSD-3-Clause",
"optional": true
},
"node_modules/sumchecker": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz",
"integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==",
"license": "Apache-2.0",
"dependencies": {
"debug": "^4.1.0"
},
"engines": {
"node": ">= 8.0"
}
},
"node_modules/type-fest": {
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
"integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
"license": "(MIT OR CC0-1.0)",
"optional": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"license": "MIT"
},
"node_modules/universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"license": "MIT",
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
"node_modules/yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
"license": "MIT",
"dependencies": {
"buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0"
}
}
}
}
{
"name": "sample-electron-nativeimage",
"version": "1.0.0",
"description": "verify electron.nativeImage in pkg:npm/electron@33.4.11",
"main": "index.js",
"license": "MIT-0",
"dependencies": {
"electron": "33.4.11"
}
}
{
"schemaVersion": 1,
"goal": "verify electron.nativeImage in pkg:npm/electron@33.4.11",
"kind": "HOW",
"packages": [
"pkg:npm/electron@33.4.11"
],
"symbols": [
"electron.nativeImage"
]
}
const assert = require('node:assert');
const {
getNativeImageDeclarations,
parseDataURL,
NativeImage,
} = require('../index.js');
// Contract 1: electron type definitions declare NativeImage class with createEmpty, createFromBuffer, createFromDataURL, createFromBitmap, and createFromPath static methods
{
const decl = getNativeImageDeclarations();
assert.strictEqual(decl.hasNativeImage, true, 'NativeImage class declarations must be complete');
assert.ok(decl.staticMethods.includes('createEmpty'), 'Must include createEmpty');
assert.ok(decl.staticMethods.includes('createFromBuffer'), 'Must include createFromBuffer');
assert.ok(decl.staticMethods.includes('createFromDataURL'), 'Must include createFromDataURL');
assert.ok(decl.staticMethods.includes('createFromBitmap'), 'Must include createFromBitmap');
assert.ok(decl.staticMethods.includes('createFromPath'), 'Must include createFromPath');
assert.ok(decl.staticMethods.includes('createFromNamedImage'), 'Must include createFromNamedImage');
assert.ok(decl.staticMethods.includes('createThumbnailFromPath'), 'Must include createThumbnailFromPath');
assert.ok(decl.instanceMethods.includes('toPNG'), 'Must include toPNG');
assert.ok(decl.instanceMethods.includes('toJPEG'), 'Must include toJPEG');
assert.ok(decl.instanceMethods.includes('toBitmap'), 'Must include toBitmap');
assert.ok(decl.instanceMethods.includes('toDataURL'), 'Must include toDataURL');
assert.ok(decl.instanceMethods.includes('getSize'), 'Must include getSize');
assert.ok(decl.instanceMethods.includes('getAspectRatio'), 'Must include getAspectRatio');
assert.ok(decl.instanceMethods.includes('isEmpty'), 'Must include isEmpty');
assert.ok(decl.instanceMethods.includes('resize'), 'Must include resize');
assert.ok(decl.instanceMethods.includes('crop'), 'Must include crop');
assert.ok(decl.instanceMethods.includes('addRepresentation'), 'Must include addRepresentation');
assert.strictEqual(decl.isCommonExported, true, 'nativeImage must be exported in Common namespace');
assert.strictEqual(decl.isCrossProcessExported, true, 'nativeImage must be exported in CrossProcessExports namespace');
assert.strictEqual(decl.isTopLevelExported, true, 'nativeImage must be exported in top-level electron namespace');
}
// Contract 2: nativeImage factory createEmpty produces empty image with zero dimensions and empty data representations
{
const emptyImg = NativeImage.createEmpty();
assert.strictEqual(emptyImg.isEmpty(), true, 'Empty image isEmpty() must be true');
const size = emptyImg.getSize();
assert.strictEqual(size.width, 0, 'Empty image width must be 0');
assert.strictEqual(size.height, 0, 'Empty image height must be 0');
assert.strictEqual(emptyImg.getAspectRatio(), 0, 'Empty image aspect ratio must be 0');
const pngBuf = emptyImg.toPNG();
assert.ok(Buffer.isBuffer(pngBuf), 'toPNG() must return Buffer');
assert.strictEqual(pngBuf.length, 0, 'Empty image PNG buffer length must be 0');
const jpegBuf = emptyImg.toJPEG(80);
assert.ok(Buffer.isBuffer(jpegBuf), 'toJPEG() must return Buffer');
assert.strictEqual(jpegBuf.length, 0, 'Empty image JPEG buffer length must be 0');
const dataURL = emptyImg.toDataURL();
assert.strictEqual(dataURL, 'data:image/png;base64,', 'Empty image dataURL must match empty header');
const emptyFromPath = NativeImage.createFromPath('nonexistent-path-file-12345.png');
assert.strictEqual(emptyFromPath.isEmpty(), true, 'Nonexistent path must return empty image');
}
// Contract 3: nativeImage factory createFromDataURL parses valid base64 data URLs and rejects malformed strings
{
const sample1x1PngBase64 = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';
const validDataURL = `data:image/png;base64,${sample1x1PngBase64}`;
const img = NativeImage.createFromDataURL(validDataURL);
assert.strictEqual(img.isEmpty(), false, 'Parsed dataURL image must not be empty');
const generatedUrl = img.toDataURL();
assert.ok(generatedUrl.startsWith('data:image/png;base64,'), 'Generated dataURL must have png header');
assert.ok(generatedUrl.includes(sample1x1PngBase64), 'Generated dataURL must contain payload data');
// Verify parseDataURL utility directly
const parsed = parseDataURL(validDataURL);
assert.strictEqual(parsed.mimeType, 'image/png', 'Mime type must be image/png');
assert.ok(Buffer.isBuffer(parsed.buffer), 'Parsed buffer must be Buffer instance');
assert.ok(parsed.buffer.length > 0, 'Parsed buffer must not be empty');
// Verify rejection of invalid dataURL inputs
assert.throws(() => {
NativeImage.createFromDataURL('not-a-data-url');
}, /Invalid dataURL/);
assert.throws(() => {
NativeImage.createFromDataURL(12345);
}, /Invalid dataURL/);
assert.throws(() => {
NativeImage.createFromDataURL('data:image/png;invalid-format');
}, /missing base64 encoding format/);
}
// Contract 4: nativeImage instance supports transformations including resize, crop, and aspect ratio calculation
{
const rawPixelData = Buffer.alloc(200 * 100 * 4, 255);
const img = NativeImage.createFromBitmap(rawPixelData, {
width: 200,
height: 100,
});
assert.strictEqual(img.isEmpty(), false, 'Bitmap image must not be empty');
assert.strictEqual(img.getSize().width, 200, 'Bitmap width must be 200');
assert.strictEqual(img.getSize().height, 100, 'Bitmap height must be 100');
assert.strictEqual(img.getAspectRatio(), 2.0, 'Aspect ratio of 200x100 must be 2.0');
// Proportional resize specifying width only
const resizedWidth = img.resize({ width: 100 });
assert.strictEqual(resizedWidth.getSize().width, 100, 'Resized width must be 100');
assert.strictEqual(resizedWidth.getSize().height, 50, 'Resized height must proportionally be 50');
assert.strictEqual(resizedWidth.getAspectRatio(), 2.0, 'Aspect ratio must be preserved');
// Proportional resize specifying height only
const resizedHeight = img.resize({ height: 25 });
assert.strictEqual(resizedHeight.getSize().width, 50, 'Resized width must proportionally be 50');
assert.strictEqual(resizedHeight.getSize().height, 25, 'Resized height must be 25');
// Crop image
const cropped = img.crop({ x: 10, y: 10, width: 40, height: 30 });
assert.strictEqual(cropped.getSize().width, 40, 'Cropped width must be 40');
assert.strictEqual(cropped.getSize().height, 30, 'Cropped height must be 30');
// Verify parameter validation
assert.throws(() => {
img.resize({});
}, /resize options must include width or height/);
assert.throws(() => {
img.crop({ x: 0, y: 0, width: -10, height: 20 });
}, /positive numbers/);
assert.throws(() => {
NativeImage.createFromBitmap(Buffer.alloc(10), { width: 0, height: 10 });
}, /positive numbers/);
}
// Contract 5: nativeImage manages multiple scale factor representations and template image flags
{
const img = NativeImage.createEmpty();
assert.strictEqual(img.isTemplateImage(), false, 'Default template image flag must be false');
img.setTemplateImage(true);
assert.strictEqual(img.isTemplateImage(), true, 'Template image flag must be true after setTemplateImage');
img.setTemplateImage(false);
assert.strictEqual(img.isTemplateImage(), false, 'Template image flag must be false after reset');
// Add 1x representation
img.addRepresentation({
scaleFactor: 1.0,
buffer: Buffer.from([1, 2, 3, 4]),
width: 50,
height: 50,
});
// Add 2x representation
img.addRepresentation({
scaleFactor: 2.0,
buffer: Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]),
width: 100,
height: 100,
});
const scales = img.getScaleFactors();
assert.deepStrictEqual(scales, [1.0, 2.0], 'Scale factors must include 1.0 and 2.0');
assert.strictEqual(img.getSize(1.0).width, 50, '1x representation width must be 50');
assert.strictEqual(img.getSize(2.0).width, 100, '2x representation width must be 100');
// Invalid scale factor parameter validation
assert.throws(() => {
img.addRepresentation({ scaleFactor: 0, buffer: Buffer.alloc(4) });
}, /scaleFactor must be a positive number/);
assert.throws(() => {
img.addRepresentation({ scaleFactor: 1.0 });
}, /Representation requires a valid buffer or dataURL/);
}
console.log('All contracts passed successfully.');
Исходный сидер
аноним