Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@salesforce/apex-node

Package Overview
Dependencies
Maintainers
42
Versions
115
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@salesforce/apex-node - npm Package Compare versions

Comparing version 0.0.3 to 0.0.4

lib/utils/fileSystemHandler.d.ts

2

lib/execute/executeService.d.ts

@@ -9,2 +9,4 @@ import { Connection } from '@salesforce/core';

executeAnonymous(options: ApexExecuteOptions): Promise<ExecuteAnonymousResponse>;
getApexCode(options: ApexExecuteOptions): Promise<string>;
getUserInput(): Promise<string>;
private buildExecRequest;

@@ -11,0 +13,0 @@ jsonFormat(soapResponse: SoapResponse): ExecuteAnonymousResponse;

@@ -16,2 +16,3 @@ "use strict";

const utils_1 = require("./utils");
const readline = require("readline");
class ExecuteService {

@@ -23,12 +24,3 @@ constructor(connection) {

return __awaiter(this, void 0, void 0, function* () {
let data;
if (options.apexFilePath) {
if (!fs_1.existsSync(options.apexFilePath)) {
throw new Error(i18n_1.nls.localize('file_not_found_error', options.apexFilePath));
}
data = fs_1.readFileSync(options.apexFilePath, 'utf8');
}
else {
data = String(options.apexCode);
}
const data = yield this.getApexCode(options);
let count = 0;

@@ -55,2 +47,44 @@ while (count < 2) {

}
getApexCode(options) {
return __awaiter(this, void 0, void 0, function* () {
if (options.apexCode) {
return String(options.apexCode);
}
else if (options.apexFilePath) {
if (!fs_1.existsSync(options.apexFilePath)) {
throw new Error(i18n_1.nls.localize('file_not_found_error', options.apexFilePath));
}
return fs_1.readFileSync(options.apexFilePath, 'utf8');
}
else if (options.userInput) {
return yield this.getUserInput();
}
else {
throw new Error(i18n_1.nls.localize('option_exec_anon_error'));
}
});
}
getUserInput() {
return __awaiter(this, void 0, void 0, function* () {
process.stdout.write(i18n_1.nls.localize('exec_anon_input_prompt'));
return new Promise((resolve, reject) => {
const readInterface = readline.createInterface(process.stdin, process.stdout);
const timeout = setTimeout(() => {
reject(new Error(i18n_1.nls.localize('exec_anon_input_timeout')));
readInterface.close();
}, 10000);
let apexCode = '';
readInterface.on('line', (input) => {
timeout.refresh();
apexCode = apexCode + input + '\n';
});
readInterface.on('close', () => {
resolve(apexCode);
});
readInterface.on('error', (err) => {
reject(new Error(i18n_1.nls.localize('unexpected_exec_anon_input_error', err.message)));
});
});
});
}
// Tooling API execute anonymous apex REST endpoint was not used because

@@ -89,2 +123,3 @@ // it requires multiple api calls to turn on trace flag, execute anonymous apex, and get the generated debug log

}
// TODO: make these general utils accessible to other classes
connectionRequest(requestData) {

@@ -91,0 +126,0 @@ return __awaiter(this, void 0, void 0, function* () {

@@ -16,2 +16,8 @@ /**

num_logs_error: string;
option_exec_anon_error: string;
unexpected_exec_anon_input_error: string;
exec_anon_input_prompt: string;
exec_anon_input_timeout: string;
no_test_result_summary: string;
no_test_queue_results: string;
};

@@ -23,4 +23,10 @@ "use strict";

unexpected_log_get_command_error: 'Unexpected error while getting logs. %s',
num_logs_error: 'Expected number of logs to be greater than 0.'
num_logs_error: 'Expected number of logs to be greater than 0.',
option_exec_anon_error: 'Please specify an option to execute anonymous Apex.',
unexpected_exec_anon_input_error: 'Unexpected error while reading user input. %s',
exec_anon_input_prompt: 'Start typing Apex code. Press the Enter key after each line, then press CTRL+D when finished.\n',
exec_anon_input_timeout: 'Timed out while waiting for user input.',
no_test_result_summary: 'No test results were found for test run %s',
no_test_queue_results: 'No test results were found in the queue for test run %s'
};
//# sourceMappingURL=i18n.js.map

@@ -54,2 +54,3 @@ "use strict";

args.unshift(possibleLabel);
// eslint-disable-next-line prefer-spread
return util.format.apply(util, args);

@@ -56,0 +57,0 @@ }

4

lib/logs/logService.d.ts
import { Connection } from '@salesforce/core';
import { ApexLogGetOptions } from '../types';
import { AnyJson } from '@salesforce/ts-types';
export declare class LogService {

@@ -7,5 +8,4 @@ readonly connection: Connection;

getLogs(options: ApexLogGetOptions): Promise<string[]>;
writeLog(outputDir: string, logRecord: string, id: string): Promise<void>;
getLogIds(numberOfLogs: number): Promise<string[]>;
toolingRequest(url: string): Promise<string>;
toolingRequest(url: string): Promise<AnyJson>;
}

@@ -13,4 +13,4 @@ "use strict";

const i18n_1 = require("../i18n");
const fs = require("fs");
const path = require("path");
const utils_1 = require("../utils");
const MAX_NUM_LOGS = 25;

@@ -35,5 +35,5 @@ class LogService {

if (options.outputDir) {
this.writeLog(options.outputDir, logRecord, id);
utils_1.createFile(path.join(options.outputDir, `${id}.log`), logRecord);
}
return logRecord;
return JSON.stringify(logRecord);
}));

@@ -44,13 +44,2 @@ const result = yield Promise.all(connectionRequests);

}
writeLog(outputDir, logRecord, id) {
return __awaiter(this, void 0, void 0, function* () {
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const filePath = path.join(`${outputDir}`, `${id}.txt`);
const stream = fs.createWriteStream(filePath);
stream.write(logRecord);
stream.end();
});
}
getLogIds(numberOfLogs) {

@@ -69,4 +58,4 @@ return __awaiter(this, void 0, void 0, function* () {

return __awaiter(this, void 0, void 0, function* () {
const log = yield this.connection.tooling.request(url);
return JSON.stringify(log);
const log = (yield this.connection.tooling.request(url));
return log;
});

@@ -73,0 +62,0 @@ }

import { Connection } from '@salesforce/core';
import { SyncTestConfiguration, SyncTestResult, SyncTestErrorResult } from './types';
import { SyncTestConfiguration, SyncTestResult, SyncTestErrorResult, AsyncTestConfiguration, AsyncTestArrayConfiguration, ApexTestQueueItem, AsyncTestResult } from './types';
export declare class TestService {

@@ -7,2 +7,5 @@ readonly connection: Connection;

runTestSynchronous(options: SyncTestConfiguration): Promise<SyncTestResult | SyncTestErrorResult[]>;
runTestAsynchronous(options: AsyncTestConfiguration | AsyncTestArrayConfiguration): Promise<AsyncTestResult>;
getTestResultData(testQueueResult: ApexTestQueueItem, testRunId: string): Promise<AsyncTestResult>;
testRunQueueStatusPoll(testRunId: string, timeout?: number, interval?: number): Promise<ApexTestQueueItem>;
}

@@ -12,2 +12,4 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const util = require("util");
const i18n_1 = require("../i18n");
class TestService {

@@ -30,4 +32,113 @@ constructor(connection) {

}
runTestAsynchronous(options) {
return __awaiter(this, void 0, void 0, function* () {
const url = `${this.connection.tooling._baseUrl()}/runTestsAsynchronous`;
const request = {
method: 'POST',
url,
body: JSON.stringify(options),
headers: { 'content-type': 'application/json' }
};
const testRunId = (yield this.connection.tooling.request(request));
// NOTE: we need to replace polling with a streaming api subscription.
// we will poll for 10-20 seconds, if the tests are still running then we'll use
// streaming api to get the results.
const testQueueResult = yield this.testRunQueueStatusPoll(testRunId);
return yield this.getTestResultData(testQueueResult, testRunId);
});
}
getTestResultData(testQueueResult, testRunId) {
return __awaiter(this, void 0, void 0, function* () {
let testRunSummaryQuery = 'SELECT AsyncApexJobId, Status, ClassesCompleted, ClassesEnqueued, ';
testRunSummaryQuery +=
'MethodsEnqueued, StartTime, EndTime, TestTime, UserId ';
testRunSummaryQuery += `FROM ApexTestRunResult WHERE AsyncApexJobId = '${testRunId}'`;
const testRunSummaryResults = (yield this.connection.tooling.query(testRunSummaryQuery));
let apexTestResultQuery = 'SELECT Id, QueueItemId, StackTrace, Message, ';
apexTestResultQuery +=
'RunTime, TestTimestamp, AsyncApexJobId, MethodName, Outcome, ApexLogId, ';
apexTestResultQuery +=
'ApexClass.Id, ApexClass.Name, ApexClass.NamespacePrefix, ApexClass.FullName ';
apexTestResultQuery += 'FROM ApexTestResult WHERE QueueItemId IN (%s)';
// TODO: this needs to iterate and create a comma separated string of ids
// and check for query length
const apexResultId = testQueueResult.records[0].Id;
const apexTestResults = (yield this.connection.tooling.query(util.format(apexTestResultQuery, `'${apexResultId}'`)));
// Iterate over test results, format and add them as results.tests
const testResults = apexTestResults.records.map(item => {
return {
Id: item.Id,
QueueItemId: item.QueueItemId,
StackTrace: item.StackTrace,
Message: item.Message,
AsyncApexJobId: item.AsyncApexJobId,
MethodName: item.MethodName,
Outcome: item.Outcome,
ApexLogId: item.ApexLogId,
ApexClass: {
Id: item.ApexClass.Id,
Name: item.ApexClass.Name,
NamespacePrefix: item.ApexClass.NamespacePrefix,
FullName: item.ApexClass.FullName
},
RunTime: item.RunTime,
TestTimestamp: item.TestTimestamp,
FullName: `${item.ApexClass.FullName}.${item.MethodName}`
};
});
if (testRunSummaryResults.records.length === 0) {
throw new Error(i18n_1.nls.localize('no_test_result_summary', testRunId));
}
const summaryRecord = testRunSummaryResults.records[0];
// TODO: add code coverage
const result = {
summary: {
outcome: summaryRecord.Status,
testStartTime: summaryRecord.StartTime,
testExecutionTime: summaryRecord.TestTime,
testRunId,
userId: summaryRecord.UserId
},
tests: testResults
};
return result;
});
}
testRunQueueStatusPoll(testRunId, timeout = 15000, interval = 500) {
return __awaiter(this, void 0, void 0, function* () {
let result;
let triedOnce = false;
const queryApexTestQueueItem = `SELECT Id, Status, ApexClassId, TestRunResultId FROM ApexTestQueueItem WHERE ParentJobId = '${testRunId}'`;
const endTime = Date.now() + timeout;
const wait = (interval) => {
return new Promise(resolve => {
setTimeout(resolve, interval);
});
};
do {
if (triedOnce) {
yield wait(interval);
}
try {
result = (yield this.connection.tooling.query(queryApexTestQueueItem));
}
catch (e) {
throw new Error(e.message);
}
if (result.records.length === 0) {
throw new Error(i18n_1.nls.localize('no_test_queue_results', testRunId));
}
switch (result.records[0].Status) {
case "Completed" /* Completed */:
case "Failed" /* Failed */:
case "Aborted" /* Aborted */:
return result;
}
triedOnce = true;
} while (Date.now() < endTime);
return result;
});
}
}
exports.TestService = TestService;
//# sourceMappingURL=testService.js.map

@@ -15,3 +15,3 @@ export declare const enum TestLogLevel {

}
export declare enum TestLevel {
export declare const enum TestLevel {
/**

@@ -32,15 +32,15 @@ * All tests in your org are run, except the ones that originate from installed managed packages

/**
* comma-separated list of class names
* Comma-separated list of class names
*/
classNames?: string;
/**
* comma-separated list of class IDs
* Comma-separated list of class IDs
*/
classids?: string;
/**
* comma-separated list of test suite names
* Comma-separated list of test suite names
*/
suiteNames?: string;
/**
* comma-separated list of test suite IDs
* Comma-separated list of test suite IDs
*/

@@ -77,14 +77,12 @@ suiteids?: string;

export declare type AsyncTestArrayConfiguration = {
tests: [TestItem[], {
/**
* Limits the test run from executing new tests after a given number of tests fail.
* Valid value ranges from 0 to 1,000,000. A value of 0 causes the test run to stop if any failure occurs.
*/
maxFailedTests?: number;
}, {
/**
* Specifies which tests to run, default level is RunSpecifiedTests
*/
testLevel: TestLevel;
}];
tests: [TestItem];
/**
* Limits the test run from executing new tests after a given number of tests fail.
* Valid value ranges from 0 to 1,000,000. A value of 0 causes the test run to stop if any failure occurs.
*/
maxFailedTests?: number;
/**
* Specifies which tests to run, default level is RunSpecifiedTests
*/
testLevel: TestLevel;
};

@@ -134,1 +132,141 @@ export declare type SyncTestConfiguration = {

};
export declare const enum ApexTestResultOutcome {
Pass = "Pass",
Fail = "Fail",
CompileFail = "CompileFail",
Skip = "Skip"
}
export declare type ApexTestResultRecord = {
Id: string;
/**
* Points to the ApexTestQueueItem which is the class that this test method is part of
*/
QueueItemId: string;
/**
* The Apex stack trace if the test failed; otherwise, null.
*/
StackTrace: string | null;
/**
* The exception error message if a test failure occurs; otherwise, null.
*/
Message: string | null;
/**
* Points to the AsyncApexJob that represents the entire test run
*/
AsyncApexJobId: string;
/**
* The name of the test method.
*/
MethodName: string;
/**
* The result of the test
*/
Outcome: ApexTestResultOutcome;
/**
* Points to the ApexLog for this test method execution if debug logging is enabled; otherwise, null.
*/
ApexLogId: string | null;
ApexClass: {
Id: string;
/**
* Name of the class (up to 255 characters)
*/
Name: string;
/**
* The namespace prefix associated with this ApexClass
*/
NamespacePrefix: string;
/**
* The full name of the associated ApexClass
*/
FullName: string;
};
/**
* The time it took the test method to run, in seconds.
*/
RunTime: number;
/**
* The start time of the test method.
*/
TestTimestamp: number;
/**
* The full name of the associated ApexClass method
*/
FullName?: string;
};
export declare type ApexTestResult = {
done: boolean;
totalSize: number;
records: ApexTestResultRecord[];
};
export declare const enum ApexTestRunResultStatus {
Queued = "Queued",
Processing = "Processing",
Aborted = "Aborted",
Completed = "Completed",
Failed = "Failed"
}
export declare type ApexTestRunResultRecord = {
/**
* The parent Apex job ID for the result
*/
AsyncApexJobId: string;
/**
* The status of the test run
*/
Status: ApexTestRunResultStatus;
/**
* The time at which the test run started.
*/
StartTime: string;
/**
* The time it took the test to run, in seconds.
*/
TestTime: number;
/**
* The user who ran the test run
*/
UserId: string;
};
export declare type ApexTestRunResult = {
done: boolean;
totalSize: number;
records: ApexTestRunResultRecord[];
};
export declare const enum ApexTestQueueItemStatus {
Holding = "Holding",
Queued = "Queued",
Preparing = "Preparing",
Processing = "Processing",
Aborted = "Aborted",
Completed = "Completed",
Failed = "Failed"
}
export declare type ApexTestQueueItemRecord = {
Id: string;
/**
* The status of the job
*/
Status: ApexTestQueueItemStatus;
ApexClassId: string;
/**
* The ID of the associated ApexTestRunResult object
*/
TestRunResultId: string;
};
export declare type ApexTestQueueItem = {
done: boolean;
totalSize: number;
records: ApexTestQueueItemRecord[];
};
export declare type AsyncTestResult = {
summary: {
outcome: string;
testStartTime: string;
testExecutionTime: number;
testRunId: string;
userId: string;
};
tests: ApexTestResultRecord[];
codecoverage?: [];
};

@@ -40,2 +40,27 @@ "use strict";

})(TestLevel = exports.TestLevel || (exports.TestLevel = {}));
var ApexTestResultOutcome;
(function (ApexTestResultOutcome) {
ApexTestResultOutcome["Pass"] = "Pass";
ApexTestResultOutcome["Fail"] = "Fail";
ApexTestResultOutcome["CompileFail"] = "CompileFail";
ApexTestResultOutcome["Skip"] = "Skip";
})(ApexTestResultOutcome = exports.ApexTestResultOutcome || (exports.ApexTestResultOutcome = {}));
var ApexTestRunResultStatus;
(function (ApexTestRunResultStatus) {
ApexTestRunResultStatus["Queued"] = "Queued";
ApexTestRunResultStatus["Processing"] = "Processing";
ApexTestRunResultStatus["Aborted"] = "Aborted";
ApexTestRunResultStatus["Completed"] = "Completed";
ApexTestRunResultStatus["Failed"] = "Failed";
})(ApexTestRunResultStatus = exports.ApexTestRunResultStatus || (exports.ApexTestRunResultStatus = {}));
var ApexTestQueueItemStatus;
(function (ApexTestQueueItemStatus) {
ApexTestQueueItemStatus["Holding"] = "Holding";
ApexTestQueueItemStatus["Queued"] = "Queued";
ApexTestQueueItemStatus["Preparing"] = "Preparing";
ApexTestQueueItemStatus["Processing"] = "Processing";
ApexTestQueueItemStatus["Aborted"] = "Aborted";
ApexTestQueueItemStatus["Completed"] = "Completed";
ApexTestQueueItemStatus["Failed"] = "Failed";
})(ApexTestQueueItemStatus = exports.ApexTestQueueItemStatus || (exports.ApexTestQueueItemStatus = {}));
//# sourceMappingURL=types.js.map

@@ -7,2 +7,3 @@ /// <reference types="node" />

apexCode?: string | Buffer;
userInput?: boolean;
};

@@ -9,0 +10,0 @@ export declare const soapEnv = "soapenv:Envelope";

{
"name": "@salesforce/apex-node",
"description": "Salesforce js library for Apex",
"version": "0.0.3",
"version": "0.0.4",
"author": "Salesforce",

@@ -18,18 +18,9 @@ "bugs": "https://github.com/forcedotcom/salesforcedx-apex/issues",

"@types/sinon": "^7.5.2",
"@typescript-eslint/eslint-plugin": "^2.22.0",
"@typescript-eslint/parser": "^2.22.0",
"chai": "^4",
"eslint": "^6.8.0",
"eslint-config-prettier": "6.11.0",
"eslint-plugin-jsdoc": "^19.1.0",
"eslint-plugin-prettier": "3.1.4",
"husky": "4.2.5",
"lint-staged": "10.2.11",
"mocha": "^5",
"nyc": "^14.1.1",
"prettier": "1.16.4",
"shx": "0.2.2",
"sinon": "^7.3.1",
"ts-node": "^8.7.0",
"typescript": "3.7"
"typescript": "3.7.5"
},

@@ -51,3 +42,4 @@ "homepage": "https://github.com/forcedotcom/salesforcedx-apex",

"lint": "eslint -c .eslintrc.json --ext .ts ./src ./test",
"test": "mocha --recursive \"./test/**/*.test.ts\" --full-trace"
"test": "mocha --recursive \"./test/**/*.test.ts\" --full-trace",
"publish-apex": "yarn publish --non-interactive"
},

@@ -54,0 +46,0 @@ "husky": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc