Sign In

@flashcatcloud/flashcat-cli

Package Overview
Dependencies
Maintainers
3
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@flashcatcloud/flashcat-cli - npm Package Compare versions

Comparing version
0.2.0
to
0.3.0
+1
dist/commands/electron-symbols/__tests__/upload.test.d.ts
export {};
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
const advanced_1 = require("clipanion/lib/advanced");
const upload_1 = require("../../../helpers/upload");
const version_1 = require("../../../helpers/version");
const upload_2 = require("../upload");
jest.mock('../../../helpers/upload', () => {
const actual = jest.requireActual('../../../helpers/upload');
return Object.assign(Object.assign({}, actual), { upload: jest.fn() });
});
// A minimal but well-formed Breakpad symbol file. The module name is the remainder of the
// MODULE line, so the macOS case deliberately carries a space.
const symFile = (osName, arch, debugId, name) => [`MODULE ${osName} ${arch} ${debugId} ${name}`, 'FILE 0 /src/a.cc', 'FUNC 1000 100 0 some_function', '1000 10 42 0', ''].join('\n');
const MAC_SYM = symFile('mac', 'arm64', '1A2B3C4D5E6F70819AC0DE00000000000', 'Electron Framework');
const WIN_SYM = symFile('windows', 'x86_64', 'E3A1B2C4D5E6F708192A3B4C5D6E7F801', 'electron.exe.pdb');
describe('electron-symbols upload', () => {
const mockedUpload = upload_1.upload;
beforeEach(() => {
mockedUpload.mockReset();
process.env = { FLASHCAT_API_KEY: 'PLACEHOLDER' };
});
test('uploads each .sym under the symbol_file field with the event metadata', () => __awaiter(void 0, void 0, void 0, function* () {
const dir = createFixture({ 'ElectronFramework.sym': MAC_SYM, 'electron.exe.sym': WIN_SYM });
const uploadImplementation = jest.fn().mockResolvedValue(upload_1.UploadStatus.Success);
mockedUpload.mockReturnValue(uploadImplementation);
const { code } = yield runCLI(['electron-symbols', 'upload', dir, '--service', 'my-app', '--release-version', '1.2.3']);
expect(code).toBe(0);
expect(uploadImplementation).toHaveBeenCalledTimes(2);
const events = uploadImplementation.mock.calls.map(([payload]) => {
const event = payload.content.get('event');
if ((event === null || event === void 0 ? void 0 : event.type) !== 'string') {
throw new Error('event should be a string multipart value');
}
expect(event.options).toEqual({ contentType: 'application/json' });
const file = payload.content.get('symbol_file');
expect(file === null || file === void 0 ? void 0 : file.type).toBe('file');
return JSON.parse(event.value);
});
// Every upload carries the same metadata: the platform, architecture and module id all
// come from the file itself on the server side, so they are deliberately absent here.
for (const event of events) {
expect(event).toEqual({
cli_version: version_1.version,
service: 'my-app',
type: 'electron_symbol_file',
version: '1.2.3',
});
}
const [, options] = uploadImplementation.mock.calls[0];
expect(options).toMatchObject({ retries: 5, useGzip: true });
}));
test('finds symbol files in nested directories', () => __awaiter(void 0, void 0, void 0, function* () {
const dir = createFixture({ 'breakpad_symbols/Electron Framework/ABC/ElectronFramework.sym': MAC_SYM });
const uploadImplementation = jest.fn().mockResolvedValue(upload_1.UploadStatus.Success);
mockedUpload.mockReturnValue(uploadImplementation);
const { code } = yield runCLI(['electron-symbols', 'upload', dir, '--service', 'my-app', '--release-version', '1.0.0']);
expect(code).toBe(0);
expect(uploadImplementation).toHaveBeenCalledTimes(1);
}));
test('dry-run reports the parsed module without uploading', () => __awaiter(void 0, void 0, void 0, function* () {
const dir = createFixture({ 'ElectronFramework.sym': MAC_SYM });
const uploadImplementation = jest.fn().mockResolvedValue(upload_1.UploadStatus.Success);
mockedUpload.mockReturnValue(uploadImplementation);
const { code, context } = yield runCLI([
'electron-symbols',
'upload',
dir,
'--service',
'my-app',
'--release-version',
'1.2.3',
'--dry-run',
]);
expect(code).toBe(0);
expect(uploadImplementation).not.toHaveBeenCalled();
expect(context.stdout.toString()).toContain('[DRYRUN]');
expect(context.stdout.toString()).toContain('module=Electron Framework');
expect(context.stdout.toString()).toContain('os=mac');
}));
// A .sym extension is not proof of a Breakpad file. Skipping locally turns a directory of
// stray files into a clear message instead of a run of server-side rejections.
test('skips files that are not Breakpad symbol files but uploads the rest', () => __awaiter(void 0, void 0, void 0, function* () {
const dir = createFixture({
'ElectronFramework.sym': MAC_SYM,
'notes.sym': 'this is not a symbol file\n',
});
const uploadImplementation = jest.fn().mockResolvedValue(upload_1.UploadStatus.Success);
mockedUpload.mockReturnValue(uploadImplementation);
const { code, context } = yield runCLI(['electron-symbols', 'upload', dir, '--service', 'my-app', '--release-version', '1.0.0']);
expect(code).toBe(0);
expect(uploadImplementation).toHaveBeenCalledTimes(1);
expect(context.stdout.toString()).toContain('Skipping notes.sym');
expect(context.stdout.toString()).toContain('1 skipped');
}));
test('errors when the directory holds no .sym files', () => __awaiter(void 0, void 0, void 0, function* () {
const dir = createFixture({ 'readme.txt': 'nothing here' });
const { code, context } = yield runCLI(['electron-symbols', 'upload', dir, '--service', 'my-app', '--release-version', '1.0.0']);
expect(code).toBe(1);
expect(context.stderr.toString()).toContain('No .sym files found');
expect(mockedUpload).not.toHaveBeenCalled();
}));
test('errors when every .sym turns out not to be a symbol file', () => __awaiter(void 0, void 0, void 0, function* () {
const dir = createFixture({ 'notes.sym': 'this is not a symbol file\n' });
const { code, context } = yield runCLI(['electron-symbols', 'upload', dir, '--service', 'my-app', '--release-version', '1.0.0']);
expect(code).toBe(1);
expect(context.stderr.toString()).toContain('MODULE header');
expect(mockedUpload).not.toHaveBeenCalled();
}));
test('requires --service and --release-version', () => __awaiter(void 0, void 0, void 0, function* () {
const dir = createFixture({ 'ElectronFramework.sym': MAC_SYM });
expect((yield runCLI(['electron-symbols', 'upload', dir])).code).toBe(1);
expect((yield runCLI(['electron-symbols', 'upload', dir, '--service', 'my-app'])).code).toBe(1);
expect((yield runCLI(['electron-symbols', 'upload', dir, '--release-version', '1.0.0'])).code).toBe(1);
}));
});
describe('readModuleHeader', () => {
test('parses a module name containing spaces', () => __awaiter(void 0, void 0, void 0, function* () {
const dir = createFixture({ 'a.sym': MAC_SYM });
const parsed = yield (0, upload_2.readModuleHeader)(path_1.default.join(dir, 'a.sym'));
expect(parsed).toEqual({
arch: 'arm64',
moduleName: 'Electron Framework',
os: 'mac',
path: path_1.default.join(dir, 'a.sym'),
});
}));
test('parses a windows module', () => __awaiter(void 0, void 0, void 0, function* () {
const dir = createFixture({ 'b.sym': WIN_SYM });
const parsed = yield (0, upload_2.readModuleHeader)(path_1.default.join(dir, 'b.sym'));
expect(parsed === null || parsed === void 0 ? void 0 : parsed.os).toBe('windows');
expect(parsed === null || parsed === void 0 ? void 0 : parsed.moduleName).toBe('electron.exe.pdb');
}));
test('tolerates CRLF line endings', () => __awaiter(void 0, void 0, void 0, function* () {
const dir = createFixture({ 'c.sym': MAC_SYM.split('\n').join('\r\n') });
const parsed = yield (0, upload_2.readModuleHeader)(path_1.default.join(dir, 'c.sym'));
expect(parsed === null || parsed === void 0 ? void 0 : parsed.moduleName).toBe('Electron Framework');
}));
test('returns undefined for a file that is not a symbol file', () => __awaiter(void 0, void 0, void 0, function* () {
const dir = createFixture({ 'd.sym': 'MODULE\n', 'e.sym': '', 'f.sym': '\x7fELF\x02\x01binary' });
expect(yield (0, upload_2.readModuleHeader)(path_1.default.join(dir, 'd.sym'))).toBeUndefined();
expect(yield (0, upload_2.readModuleHeader)(path_1.default.join(dir, 'e.sym'))).toBeUndefined();
expect(yield (0, upload_2.readModuleHeader)(path_1.default.join(dir, 'f.sym'))).toBeUndefined();
}));
test('returns undefined for a missing file rather than throwing', () => __awaiter(void 0, void 0, void 0, function* () {
expect(yield (0, upload_2.readModuleHeader)(path_1.default.join(os_1.default.tmpdir(), 'definitely-absent.sym'))).toBeUndefined();
}));
});
const runCLI = (args) => __awaiter(void 0, void 0, void 0, function* () {
const cli = new advanced_1.Cli();
cli.register(upload_2.UploadCommand);
const context = createMockContext();
const code = yield cli.run(args, context);
return { code, context };
});
const createFixture = (files) => {
const dir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'flashcat-electron-test-'));
for (const [name, content] of Object.entries(files)) {
const target = path_1.default.join(dir, name);
fs_1.default.mkdirSync(path_1.default.dirname(target), { recursive: true });
fs_1.default.writeFileSync(target, content);
}
return dir;
};
const createMockContext = () => {
let stdout = '';
let stderr = '';
return {
stderr: {
toString: () => stderr,
write: (input) => {
stderr += input;
},
},
stdout: {
toString: () => stdout,
write: (input) => {
stdout += input;
},
},
};
};
//# sourceMappingURL=upload.test.js.map
{"version":3,"file":"upload.test.js","sourceRoot":"","sources":["../../../../src/commands/electron-symbols/__tests__/upload.test.ts"],"names":[],"mappings":"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"}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const upload_1 = require("./upload");
module.exports = [upload_1.UploadCommand];
//# sourceMappingURL=cli.js.map
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/commands/electron-symbols/cli.ts"],"names":[],"mappings":";;AAAA,qCAAsC;AAEtC,MAAM,CAAC,OAAO,GAAG,CAAC,sBAAa,CAAC,CAAA"}
import { Command } from 'clipanion';
export interface ElectronSymbolFile {
path: string;
os: string;
arch: string;
moduleName: string;
}
/**
* Reads the MODULE header of a Breakpad symbol file.
*
* This is only used to skip files that are not symbol files and to label progress output.
* The debug id is deliberately NOT sent to the server: the server reads it from the file
* it actually stores, so there is no way for a mismatch between what we claim and what
* gets indexed.
*/
export declare const readModuleHeader: (filePath: string) => Promise<ElectronSymbolFile | undefined>;
export declare class UploadCommand extends Command {
static paths: string[][];
static usage: import("clipanion").Usage;
private basePath;
private service;
private releaseVersion;
private maxConcurrency;
private dryRun;
private quiet;
private cliVersion;
private config;
execute(): Promise<0 | 1>;
private asMultipartPayload;
private getRequestBuilder;
private uploadSymbolFile;
}
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __asyncValues = (this && this.__asyncValues) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UploadCommand = exports.readModuleHeader = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const readline_1 = __importDefault(require("readline"));
const chalk_1 = __importDefault(require("chalk"));
const clipanion_1 = require("clipanion");
const glob_1 = require("glob");
const apikey_1 = require("../../helpers/apikey");
const base_intake_url_1 = require("../../helpers/base-intake-url");
const concurrency_1 = require("../../helpers/concurrency");
const errors_1 = require("../../helpers/errors");
const upload_1 = require("../../helpers/upload");
const utils_1 = require("../../helpers/utils");
const version_1 = require("../../helpers/version");
// A Breakpad symbol file opens with:
// MODULE <os> <arch> <debug_id> <name>
// The name may contain spaces (on macOS the most common module is "Electron Framework"),
// so it is the whole remainder of the line.
const MODULE_LINE_RE = /^MODULE (\S+) (\S+) ([0-9a-fA-F]{32,}) (.+)$/;
// Reading a few hundred bytes is enough to reach the end of the first line of any
// well-formed symbol file. A file that needs more than this is not one.
const MAX_HEADER_BYTES = 4096;
/**
* Reads the MODULE header of a Breakpad symbol file.
*
* This is only used to skip files that are not symbol files and to label progress output.
* The debug id is deliberately NOT sent to the server: the server reads it from the file
* it actually stores, so there is no way for a mismatch between what we claim and what
* gets indexed.
*/
const readModuleHeader = (filePath) => __awaiter(void 0, void 0, void 0, function* () {
var _a, e_1, _b, _c;
let stream;
try {
stream = fs_1.default.createReadStream(filePath, { encoding: 'utf8', end: MAX_HEADER_BYTES, start: 0 });
const lines = readline_1.default.createInterface({ crlfDelay: Infinity, input: stream });
try {
for (var _d = true, lines_1 = __asyncValues(lines), lines_1_1; lines_1_1 = yield lines_1.next(), _a = lines_1_1.done, !_a; _d = true) {
_c = lines_1_1.value;
_d = false;
const line = _c;
lines.close();
const match = MODULE_LINE_RE.exec(line.trim());
if (!match) {
return undefined;
}
return { arch: match[2], moduleName: match[4], os: match[1], path: filePath };
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (!_d && !_a && (_b = lines_1.return)) yield _b.call(lines_1);
}
finally { if (e_1) throw e_1.error; }
}
return undefined;
}
catch (_e) {
return undefined;
}
finally {
stream === null || stream === void 0 ? void 0 : stream.destroy();
}
});
exports.readModuleHeader = readModuleHeader;
class UploadCommand extends clipanion_1.Command {
constructor() {
super(...arguments);
this.basePath = clipanion_1.Option.String({ required: true });
this.service = clipanion_1.Option.String('--service');
this.releaseVersion = clipanion_1.Option.String('--release-version');
// The intake serializes native symbol uploads per service, so requests beyond the first
// are rejected rather than queued. Default to one at a time; raising this trades a
// successful upload for a faster failure.
this.maxConcurrency = clipanion_1.Option.String('--max-concurrency', '1');
this.dryRun = clipanion_1.Option.Boolean('--dry-run', false);
this.quiet = clipanion_1.Option.Boolean('--quiet', false);
this.cliVersion = version_1.version;
this.config = {
apiKey: process.env.FLASHCAT_API_KEY,
flashcatSite: process.env.FLASHCAT_SITE || 'flashcat.cloud',
};
}
execute() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.service) {
this.context.stderr.write('Missing --service\n');
return 1;
}
if (!this.releaseVersion) {
this.context.stderr.write('Missing --release-version\n');
return 1;
}
const candidates = glob_1.glob.sync((0, utils_1.buildPath)(this.basePath, '**/*.sym'));
if (candidates.length === 0) {
this.context.stderr.write(`No .sym files found under ${path_1.default.resolve(this.basePath)}. ` +
`Unpack Electron's electron-v<version>-<platform>-<arch>-symbols.zip and point at that directory.\n`);
return 1;
}
const files = [];
let skipped = 0;
for (const candidate of candidates) {
const parsed = yield (0, exports.readModuleHeader)(candidate);
if (parsed) {
files.push(parsed);
}
else {
skipped++;
if (!this.quiet) {
this.context.stdout.write(`Skipping ${path_1.default.basename(candidate)}: not a Breakpad symbol file.\n`);
}
}
}
if (files.length === 0) {
this.context.stderr.write(`None of the ${candidates.length} .sym file(s) under ${path_1.default.resolve(this.basePath)} start with a ` +
`MODULE header, so none of them are Breakpad symbol files.\n`);
return 1;
}
if (this.dryRun) {
for (const f of files) {
this.context.stdout.write(`[DRYRUN] would upload ${f.path} (module=${f.moduleName}, os=${f.os}, arch=${f.arch}, ` +
`service=${this.service}, version=${this.releaseVersion})\n`);
}
return 0;
}
const apiKeyValidator = (0, apikey_1.newApiKeyValidator)({
apiKey: this.config.apiKey,
flashcatSite: this.config.flashcatSite,
});
const requestBuilder = this.getRequestBuilder();
try {
const results = yield (0, concurrency_1.doWithMaxConcurrency)(Math.max(1, parseInt(this.maxConcurrency, 10) || 1), files, (f) => this.uploadSymbolFile(requestBuilder, apiKeyValidator)(f));
if (results.some((r) => r !== upload_1.UploadStatus.Success)) {
return 1;
}
if (!this.quiet) {
const skippedNote = skipped > 0 ? ` (${skipped} skipped)` : '';
this.context.stdout.write(`Uploaded ${files.length} Electron symbol file(s)${skippedNote}.\n`);
}
return 0;
}
catch (error) {
if (error instanceof errors_1.InvalidConfigurationError) {
this.context.stderr.write(`${error.message}\n`);
return 1;
}
throw error;
}
});
}
asMultipartPayload(file) {
const eventMeta = {
cli_version: this.cliVersion,
service: this.service,
type: 'electron_symbol_file',
version: this.releaseVersion,
};
const content = new Map([
[
'event',
{
type: 'string',
options: { contentType: 'application/json' },
value: JSON.stringify(eventMeta),
},
],
[
'symbol_file',
{
type: 'file',
path: file.path,
options: { filename: path_1.default.basename(file.path) },
},
],
]);
return { content };
}
getRequestBuilder() {
if (!this.config.apiKey) {
throw new errors_1.InvalidConfigurationError(`Missing ${chalk_1.default.bold('FLASHCAT_API_KEY')} in your environment.`);
}
return (0, utils_1.getRequestBuilder)({
apiKey: this.config.apiKey,
baseUrl: (0, base_intake_url_1.getBaseSourcemapIntakeUrl)(this.config.flashcatSite),
headers: new Map([
['DD-EVP-ORIGIN', 'flashcat-cli_electron'],
['DD-EVP-ORIGIN-VERSION', this.cliVersion],
]),
overrideUrl: '/sourcemap/upload',
});
}
uploadSymbolFile(requestBuilder, apiKeyValidator) {
return (file) => __awaiter(this, void 0, void 0, function* () {
return (0, upload_1.upload)(requestBuilder)(this.asMultipartPayload(file), {
apiKeyValidator,
onError: (e) => {
this.context.stderr.write(`Upload failed for ${path_1.default.basename(file.path)}: ${e.message}\n`);
},
onRetry: (e, attempts) => {
if (!this.quiet) {
this.context.stdout.write(`Retry ${attempts} for ${path_1.default.basename(file.path)}: ${e.message}\n`);
}
},
onUpload: () => {
if (!this.quiet) {
this.context.stdout.write(`Uploading ${file.moduleName} (${file.os}/${file.arch})...\n`);
}
},
retries: 5,
useGzip: true,
});
});
}
}
exports.UploadCommand = UploadCommand;
UploadCommand.paths = [['electron-symbols', 'upload']];
UploadCommand.usage = clipanion_1.Command.Usage({
category: 'RUM',
description: 'Upload Electron Breakpad symbols to Flashcat for native crash symbolication.',
details: `
Point this at a directory of Breakpad symbol files (.sym). Every file found is
uploaded; the server reads each file's own module id and uses it to symbolicate
matching native crash stacks at query time.
Most frames in an Electron crash land in Electron's own binaries rather than in your
code, so start with the symbols Electron publishes for the exact version, platform
and architecture you ship:
electron-v<version>-<platform>-<arch>-symbols.zip
For your own native modules or .node addons, generate a .sym with dump_syms and put
it in the same directory.
Symbols are matched on the module id alone. --service and --release-version only
label the upload so it can be found in the console later; they do not affect whether
a symbol file matches a crash.
`,
examples: [
[
'Upload Electron symbols for a release',
'flashcat-cli electron-symbols upload ./breakpad_symbols --service my-app --release-version 1.2.3',
],
],
});
//# sourceMappingURL=upload.js.map
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../../src/commands/electron-symbols/upload.ts"],"names":[],"mappings":"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"}
+1
-1
{
"name": "@flashcatcloud/flashcat-cli",
"version": "0.2.0",
"version": "0.3.0",
"description": "CLI tool for Flashcat Cloud",

@@ -5,0 +5,0 @@ "main": "dist/index.js",