@depup/nexe 5.0.0-beta.4-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +40 -0
- package/changes.json +46 -0
- package/index.js +32 -0
- package/lib/compiler.d.ts +105 -0
- package/lib/compiler.js +289 -0
- package/lib/fs/README.md +40 -0
- package/lib/fs/SnapshotZipFS.d.ts +228 -0
- package/lib/fs/SnapshotZipFS.js +283 -0
- package/lib/fs/bootstrap.js +20 -0
- package/lib/fs/bundle.d.ts +17 -0
- package/lib/fs/bundle.js +51 -0
- package/lib/fs/package.json +15 -0
- package/lib/fs/patch.bundle.js +7823 -0
- package/lib/fs/patch.bundle.js.map +1 -0
- package/lib/fs/patch.d.ts +12 -0
- package/lib/fs/patch.js +122 -0
- package/lib/logger.d.ts +18 -0
- package/lib/logger.js +60 -0
- package/lib/nexe.d.ts +5 -0
- package/lib/nexe.js +53 -0
- package/lib/options.d.ts +56 -0
- package/lib/options.js +244 -0
- package/lib/patches/boot-nexe.d.ts +5 -0
- package/lib/patches/boot-nexe.js +38 -0
- package/lib/patches/build-fixes.d.ts +2 -0
- package/lib/patches/build-fixes.js +22 -0
- package/lib/patches/disable-node-cli.d.ts +2 -0
- package/lib/patches/disable-node-cli.js +48 -0
- package/lib/patches/flags.d.ts +2 -0
- package/lib/patches/flags.js +22 -0
- package/lib/patches/gyp.d.ts +2 -0
- package/lib/patches/gyp.js +25 -0
- package/lib/patches/ico.d.ts +2 -0
- package/lib/patches/ico.js +24 -0
- package/lib/patches/index.d.ts +3 -0
- package/lib/patches/index.js +15 -0
- package/lib/patches/node-rc.d.ts +2 -0
- package/lib/patches/node-rc.js +37 -0
- package/lib/patches/snapshot.d.ts +2 -0
- package/lib/patches/snapshot.js +25 -0
- package/lib/patches/third-party-main.d.ts +2 -0
- package/lib/patches/third-party-main.js +99 -0
- package/lib/releases.d.ts +15 -0
- package/lib/releases.js +57 -0
- package/lib/steps/artifacts.d.ts +11 -0
- package/lib/steps/artifacts.js +89 -0
- package/lib/steps/bundle.d.ts +2 -0
- package/lib/steps/bundle.js +104 -0
- package/lib/steps/clean.d.ts +2 -0
- package/lib/steps/clean.js +30 -0
- package/lib/steps/cli.d.ts +12 -0
- package/lib/steps/cli.js +55 -0
- package/lib/steps/download.d.ts +7 -0
- package/lib/steps/download.js +76 -0
- package/lib/steps/resource.d.ts +2 -0
- package/lib/steps/resource.js +38 -0
- package/lib/steps/shim.d.ts +2 -0
- package/lib/steps/shim.js +45 -0
- package/lib/target.d.ts +11 -0
- package/lib/target.js +82 -0
- package/lib/util.d.ts +29 -0
- package/lib/util.js +104 -0
- package/package.json +148 -0
package/lib/target.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type NodePlatform = 'windows' | 'mac' | 'alpine' | 'linux';
|
|
2
|
+
export type NodeArch = 'x86' | 'x64' | 'arm' | 'arm64';
|
|
3
|
+
declare const platforms: NodePlatform[], architectures: NodeArch[];
|
|
4
|
+
export { platforms, architectures };
|
|
5
|
+
export interface NexeTarget {
|
|
6
|
+
version: string;
|
|
7
|
+
platform: NodePlatform | string;
|
|
8
|
+
arch: NodeArch | string;
|
|
9
|
+
}
|
|
10
|
+
export declare function targetsEqual(a: NexeTarget, b: NexeTarget): boolean;
|
|
11
|
+
export declare function getTarget(target?: string | Partial<NexeTarget>): NexeTarget;
|
package/lib/target.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTarget = exports.targetsEqual = exports.architectures = exports.platforms = void 0;
|
|
4
|
+
const platforms = ['windows', 'mac', 'alpine', 'linux'], architectures = ['x86', 'x64', 'arm', 'arm64'];
|
|
5
|
+
exports.platforms = platforms;
|
|
6
|
+
exports.architectures = architectures;
|
|
7
|
+
const prettyPlatform = {
|
|
8
|
+
win32: 'windows',
|
|
9
|
+
windows: 'windows',
|
|
10
|
+
win: 'windows',
|
|
11
|
+
darwin: 'mac',
|
|
12
|
+
macos: 'mac',
|
|
13
|
+
mac: 'mac',
|
|
14
|
+
linux: 'linux',
|
|
15
|
+
static: 'alpine',
|
|
16
|
+
alpine: 'alpine',
|
|
17
|
+
};
|
|
18
|
+
const prettyArch = {
|
|
19
|
+
x86: 'x86',
|
|
20
|
+
arm6: 'arm',
|
|
21
|
+
arm64: 'arm64',
|
|
22
|
+
arm6l: 'arm',
|
|
23
|
+
arm: 'arm',
|
|
24
|
+
arm7: 'arm',
|
|
25
|
+
arm7l: 'arm',
|
|
26
|
+
amd64: 'x64',
|
|
27
|
+
ia32: 'x86',
|
|
28
|
+
x32: 'x86',
|
|
29
|
+
x64: 'x64',
|
|
30
|
+
};
|
|
31
|
+
function isVersion(x) {
|
|
32
|
+
if (!x) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return /^[\d]+$/.test(x.replace(/v|\.|\s+/g, ''));
|
|
36
|
+
}
|
|
37
|
+
function isPlatform(x) {
|
|
38
|
+
return x in prettyPlatform;
|
|
39
|
+
}
|
|
40
|
+
function isArch(x) {
|
|
41
|
+
return x in prettyArch;
|
|
42
|
+
}
|
|
43
|
+
class Target {
|
|
44
|
+
constructor(arch, platform, version) {
|
|
45
|
+
this.arch = arch;
|
|
46
|
+
this.platform = platform;
|
|
47
|
+
this.version = version;
|
|
48
|
+
}
|
|
49
|
+
toJSON() {
|
|
50
|
+
return this.toString();
|
|
51
|
+
}
|
|
52
|
+
toString() {
|
|
53
|
+
return `${this.platform}-${this.arch}-${this.version}`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function targetsEqual(a, b) {
|
|
57
|
+
return a.arch === b.arch && a.platform === b.platform && a.version === b.version;
|
|
58
|
+
}
|
|
59
|
+
exports.targetsEqual = targetsEqual;
|
|
60
|
+
function getTarget(target = '') {
|
|
61
|
+
const currentArch = process.arch;
|
|
62
|
+
let arch = currentArch in prettyArch ? prettyArch[process.arch] : process.arch, platform = prettyPlatform[process.platform], version = process.version.slice(1);
|
|
63
|
+
if (typeof target !== 'string') {
|
|
64
|
+
target = `${target.platform}-${target.arch}-${target.version}`;
|
|
65
|
+
}
|
|
66
|
+
target
|
|
67
|
+
.toLowerCase()
|
|
68
|
+
.split('-')
|
|
69
|
+
.forEach((x) => {
|
|
70
|
+
if (isVersion(x)) {
|
|
71
|
+
version = x.replace(/v/g, '');
|
|
72
|
+
}
|
|
73
|
+
if (isPlatform(x)) {
|
|
74
|
+
platform = prettyPlatform[x];
|
|
75
|
+
}
|
|
76
|
+
if (isArch(x)) {
|
|
77
|
+
arch = prettyArch[x];
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return new Target(arch, platform, version);
|
|
81
|
+
}
|
|
82
|
+
exports.getTarget = getTarget;
|
package/lib/util.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
/// <reference types="node" />
|
|
4
|
+
import { readFile, writeFile, stat } from 'fs';
|
|
5
|
+
import { execFile } from 'child_process';
|
|
6
|
+
declare const rimrafAsync: (arg1: string) => Promise<void>;
|
|
7
|
+
export declare const STDIN_FLAG = "[stdin]";
|
|
8
|
+
export declare function each<T>(list: T[] | Promise<T[]>, action: (item: T, index: number, list: T[]) => Promise<any>): Promise<any[]>;
|
|
9
|
+
export declare function wrap(code: string): string;
|
|
10
|
+
declare function padRight(str: string, l: number): string;
|
|
11
|
+
declare const bound: MethodDecorator;
|
|
12
|
+
declare function dequote(input: string): string;
|
|
13
|
+
export interface ReadFileAsync {
|
|
14
|
+
(path: string): Promise<Buffer>;
|
|
15
|
+
(path: string, encoding: string): Promise<string>;
|
|
16
|
+
}
|
|
17
|
+
declare const readFileAsync: typeof readFile.__promisify__;
|
|
18
|
+
declare const writeFileAsync: typeof writeFile.__promisify__;
|
|
19
|
+
declare const statAsync: typeof stat.__promisify__;
|
|
20
|
+
declare const execFileAsync: typeof execFile.__promisify__;
|
|
21
|
+
declare const isWindows: boolean;
|
|
22
|
+
declare function pathExistsAsync(path: string): Promise<boolean>;
|
|
23
|
+
declare function isDirectoryAsync(path: string): Promise<boolean>;
|
|
24
|
+
/**
|
|
25
|
+
* @param version See if this version is greather than the second one
|
|
26
|
+
* @param operand Version to compare against
|
|
27
|
+
*/
|
|
28
|
+
declare function semverGt(version: string, operand: string): boolean;
|
|
29
|
+
export { dequote, padRight, semverGt, bound, isWindows, rimrafAsync, statAsync, execFileAsync, readFileAsync, pathExistsAsync, isDirectoryAsync, writeFileAsync, };
|
package/lib/util.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.writeFileAsync = exports.isDirectoryAsync = exports.pathExistsAsync = exports.readFileAsync = exports.execFileAsync = exports.statAsync = exports.rimrafAsync = exports.isWindows = exports.bound = exports.semverGt = exports.padRight = exports.dequote = exports.wrap = exports.each = exports.STDIN_FLAG = void 0;
|
|
13
|
+
const fs_1 = require("fs");
|
|
14
|
+
const child_process_1 = require("child_process");
|
|
15
|
+
const util_1 = require("util");
|
|
16
|
+
const rimraf = require("rimraf");
|
|
17
|
+
const rimrafAsync = (0, util_1.promisify)(rimraf);
|
|
18
|
+
exports.rimrafAsync = rimrafAsync;
|
|
19
|
+
exports.STDIN_FLAG = '[stdin]';
|
|
20
|
+
function each(list, action) {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
const l = yield list;
|
|
23
|
+
return Promise.all(l.map(action));
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
exports.each = each;
|
|
27
|
+
function wrap(code) {
|
|
28
|
+
return '!(function () {' + code + '})();';
|
|
29
|
+
}
|
|
30
|
+
exports.wrap = wrap;
|
|
31
|
+
function falseOnEnoent(e) {
|
|
32
|
+
if (e.code === 'ENOENT') {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
throw e;
|
|
36
|
+
}
|
|
37
|
+
function padRight(str, l) {
|
|
38
|
+
return (str + ' '.repeat(l)).slice(0, l);
|
|
39
|
+
}
|
|
40
|
+
exports.padRight = padRight;
|
|
41
|
+
const bound = function bound(target, propertyKey, descriptor) {
|
|
42
|
+
const configurable = true;
|
|
43
|
+
return {
|
|
44
|
+
configurable,
|
|
45
|
+
get() {
|
|
46
|
+
const value = descriptor.value.bind(this);
|
|
47
|
+
Object.defineProperty(this, propertyKey, {
|
|
48
|
+
configurable,
|
|
49
|
+
value,
|
|
50
|
+
writable: true,
|
|
51
|
+
});
|
|
52
|
+
return value;
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
exports.bound = bound;
|
|
57
|
+
function dequote(input) {
|
|
58
|
+
input = input.trim();
|
|
59
|
+
const singleQuote = input.startsWith("'") && input.endsWith("'");
|
|
60
|
+
const doubleQuote = input.startsWith('"') && input.endsWith('"');
|
|
61
|
+
if (singleQuote || doubleQuote) {
|
|
62
|
+
return input.slice(1).slice(0, -1);
|
|
63
|
+
}
|
|
64
|
+
return input;
|
|
65
|
+
}
|
|
66
|
+
exports.dequote = dequote;
|
|
67
|
+
const readFileAsync = (0, util_1.promisify)(fs_1.readFile);
|
|
68
|
+
exports.readFileAsync = readFileAsync;
|
|
69
|
+
const writeFileAsync = (0, util_1.promisify)(fs_1.writeFile);
|
|
70
|
+
exports.writeFileAsync = writeFileAsync;
|
|
71
|
+
const statAsync = (0, util_1.promisify)(fs_1.stat);
|
|
72
|
+
exports.statAsync = statAsync;
|
|
73
|
+
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
74
|
+
exports.execFileAsync = execFileAsync;
|
|
75
|
+
const isWindows = process.platform === 'win32';
|
|
76
|
+
exports.isWindows = isWindows;
|
|
77
|
+
function pathExistsAsync(path) {
|
|
78
|
+
return statAsync(path)
|
|
79
|
+
.then((x) => true)
|
|
80
|
+
.catch(falseOnEnoent);
|
|
81
|
+
}
|
|
82
|
+
exports.pathExistsAsync = pathExistsAsync;
|
|
83
|
+
function isDirectoryAsync(path) {
|
|
84
|
+
return statAsync(path)
|
|
85
|
+
.then((x) => x.isDirectory())
|
|
86
|
+
.catch(falseOnEnoent);
|
|
87
|
+
}
|
|
88
|
+
exports.isDirectoryAsync = isDirectoryAsync;
|
|
89
|
+
/**
|
|
90
|
+
* @param version See if this version is greather than the second one
|
|
91
|
+
* @param operand Version to compare against
|
|
92
|
+
*/
|
|
93
|
+
function semverGt(version, operand) {
|
|
94
|
+
const [cMajor, cMinor, cPatch] = version.split('.').map(Number);
|
|
95
|
+
let [major, minor, patch] = operand.split('.').map(Number);
|
|
96
|
+
if (!minor)
|
|
97
|
+
minor = 0;
|
|
98
|
+
if (!patch)
|
|
99
|
+
patch = 0;
|
|
100
|
+
return (cMajor > major ||
|
|
101
|
+
(cMajor === major && cMinor > minor) ||
|
|
102
|
+
(cMajor === major && cMinor === minor && cPatch > patch));
|
|
103
|
+
}
|
|
104
|
+
exports.semverGt = semverGt;
|
package/package.json
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@depup/nexe",
|
|
3
|
+
"description": "[DepUp] Create a single executable out of your Node.js application",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"version": "5.0.0-beta.4-depup.0",
|
|
6
|
+
"contributors": [
|
|
7
|
+
"Craig Condon <craig.j.condon@gmail.com> (http://crcn.io)",
|
|
8
|
+
"Jared Allard <jaredallard@outlook.com>",
|
|
9
|
+
"Caleb Boyd <caleb.boyd@hotmail.com>"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"ci:build": "ts-node tasks/build",
|
|
13
|
+
"test": "mocha",
|
|
14
|
+
"test:integration": "node index.js --target 14.15.3 -i test/integration/index.js -o integration-tests --verbose -r test/integration -r node_modules/ && npm run test:integration:run",
|
|
15
|
+
"test:integration:run": "run-script-os",
|
|
16
|
+
"test:integration:run:win32": "integration-tests.exe",
|
|
17
|
+
"test:integration:run:default": "./integration-tests",
|
|
18
|
+
"lint": "tslint \"{src,plugins,tasks}/**/*.ts\" --fix",
|
|
19
|
+
"prebuild": "rimraf lib",
|
|
20
|
+
"build": "tsc --declaration && tsc -p tasks && webpack",
|
|
21
|
+
"postbuild": "ts-node tasks/post-build"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git://github.com/nexe/nexe.git"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"lib",
|
|
29
|
+
"changes.json",
|
|
30
|
+
"README.md"
|
|
31
|
+
],
|
|
32
|
+
"typings": "lib/nexe.d.ts",
|
|
33
|
+
"main": "index.js",
|
|
34
|
+
"bin": {
|
|
35
|
+
"nexe": "index.js"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=10"
|
|
39
|
+
},
|
|
40
|
+
"mocha": {
|
|
41
|
+
"spec": "./test/**/*.spec.ts",
|
|
42
|
+
"checkLeaks": true,
|
|
43
|
+
"require": [
|
|
44
|
+
"ts-node/register"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@calebboyd/semaphore": "^1.3.1",
|
|
49
|
+
"@yarnpkg/fslib": "^3.1.4",
|
|
50
|
+
"@yarnpkg/libzip": "^3.2.2",
|
|
51
|
+
"app-builder": "^7.0.4",
|
|
52
|
+
"archiver": "^7.0.1",
|
|
53
|
+
"caw": "^2.0.1",
|
|
54
|
+
"chalk": "^5.6.2",
|
|
55
|
+
"download": "^8.0.0",
|
|
56
|
+
"globby": "^16.1.1",
|
|
57
|
+
"got": "^14.6.6",
|
|
58
|
+
"meriyah": "^7.1.0",
|
|
59
|
+
"minimist": "^1.2.8",
|
|
60
|
+
"mkdirp": "^3.0.1",
|
|
61
|
+
"multistream": "^4.1.0",
|
|
62
|
+
"ora": "^9.3.0",
|
|
63
|
+
"resolve-dependencies": "^6.0.9",
|
|
64
|
+
"rimraf": "^6.1.3",
|
|
65
|
+
"run-script-os": "^1.1.6",
|
|
66
|
+
"webpack-config-prefabs": "0.0.5"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@types/archiver": "^5.3.2",
|
|
70
|
+
"@types/chai": "^4",
|
|
71
|
+
"@types/download": "^8",
|
|
72
|
+
"@types/globby": "^9",
|
|
73
|
+
"@types/lodash": "^4.14.192",
|
|
74
|
+
"@types/minimist": "^1.2.2",
|
|
75
|
+
"@types/mkdirp": "^1.0.2",
|
|
76
|
+
"@types/mocha": "^10.0.1",
|
|
77
|
+
"@types/multistream": "^4.1.0",
|
|
78
|
+
"@types/ora": "^3.2.0",
|
|
79
|
+
"@types/rimraf": "3.0.2",
|
|
80
|
+
"@types/semver": "^7.3.13",
|
|
81
|
+
"chai": "^4.3.7",
|
|
82
|
+
"execa": "^5.1.1",
|
|
83
|
+
"lodash": "^4.17.21",
|
|
84
|
+
"mocha": "^10.2.0",
|
|
85
|
+
"prettier": "^2.8.7",
|
|
86
|
+
"ts-node": "^10.9.1",
|
|
87
|
+
"tslint": "^6.1.1",
|
|
88
|
+
"tslint-config-prettier": "^1.18.0",
|
|
89
|
+
"tslint-plugin-prettier": "^2.3.0",
|
|
90
|
+
"typescript": "^5.0.3",
|
|
91
|
+
"webpack-cli": "^5.0.1"
|
|
92
|
+
},
|
|
93
|
+
"keywords": [
|
|
94
|
+
"depup",
|
|
95
|
+
"dependency-bumped",
|
|
96
|
+
"updated-deps",
|
|
97
|
+
"nexe"
|
|
98
|
+
],
|
|
99
|
+
"depup": {
|
|
100
|
+
"changes": {
|
|
101
|
+
"@yarnpkg/fslib": {
|
|
102
|
+
"from": "^3.0.0-rc.43",
|
|
103
|
+
"to": "^3.1.4"
|
|
104
|
+
},
|
|
105
|
+
"@yarnpkg/libzip": {
|
|
106
|
+
"from": "^3.0.0-rc.43",
|
|
107
|
+
"to": "^3.2.2"
|
|
108
|
+
},
|
|
109
|
+
"archiver": {
|
|
110
|
+
"from": "^5.3.1",
|
|
111
|
+
"to": "^7.0.1"
|
|
112
|
+
},
|
|
113
|
+
"chalk": {
|
|
114
|
+
"from": "^2.4.2",
|
|
115
|
+
"to": "^5.6.2"
|
|
116
|
+
},
|
|
117
|
+
"globby": {
|
|
118
|
+
"from": "^11.0.2",
|
|
119
|
+
"to": "^16.1.1"
|
|
120
|
+
},
|
|
121
|
+
"got": {
|
|
122
|
+
"from": "^12.6.0",
|
|
123
|
+
"to": "^14.6.6"
|
|
124
|
+
},
|
|
125
|
+
"meriyah": {
|
|
126
|
+
"from": "^4.3.5",
|
|
127
|
+
"to": "^7.1.0"
|
|
128
|
+
},
|
|
129
|
+
"mkdirp": {
|
|
130
|
+
"from": "^1.0.4",
|
|
131
|
+
"to": "^3.0.1"
|
|
132
|
+
},
|
|
133
|
+
"ora": {
|
|
134
|
+
"from": "^3.4.0",
|
|
135
|
+
"to": "^9.3.0"
|
|
136
|
+
},
|
|
137
|
+
"rimraf": {
|
|
138
|
+
"from": "^3.0.2",
|
|
139
|
+
"to": "^6.1.3"
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"depsUpdated": 10,
|
|
143
|
+
"originalPackage": "nexe",
|
|
144
|
+
"originalVersion": "5.0.0-beta.4",
|
|
145
|
+
"processedAt": "2026-03-17T19:30:28.575Z",
|
|
146
|
+
"smokeTest": "failed"
|
|
147
|
+
}
|
|
148
|
+
}
|