@cparra/apex-reflection 2.22.0 → 2.23.1
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/README.md +0 -7
- package/dist/index.d.ts +0 -2
- package/dist/index.js +74 -17
- package/package.json +11 -2
- package/publish-scripts/postinstall.js +273 -0
- package/dist/out.d.ts +0 -3
- package/dist/out.js +0 -31506
package/README.md
CHANGED
|
@@ -42,13 +42,6 @@ body was not parsed successfully, with a message indicating where the error occu
|
|
|
42
42
|
Even though this library is exposed as a Node.js library, the project's source code is written in Dart. The source can
|
|
43
43
|
be found in the `lib/src` directory.
|
|
44
44
|
|
|
45
|
-
The Dart source code is transpiled to JS by `dart2js` through the default [grinder](https://pub.dev/packages/grinder)
|
|
46
|
-
workflow within `tool/grind.dart`.
|
|
47
|
-
|
|
48
|
-
To generate the JS files first set up `grinder` locally by following that package's instructions through its pub.dev
|
|
49
|
-
listing, and then you can simply run `grind`. That build takes care of combining the output with `preamble/preamble.js`
|
|
50
|
-
to achieve compatibility with Node.js. The resulting file is `js/apex-reflection-node/out.js`.
|
|
51
|
-
|
|
52
45
|
### Tests
|
|
53
46
|
|
|
54
47
|
Both the Dart source code and the JS output must be tested.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export declare function reflect(declarationBody: string): ReflectionResult;
|
|
2
|
-
export declare function reflectAsync(declarationBody: string): Promise<ReflectionResult>;
|
|
3
2
|
export declare function reflectTrigger(declarationBody: string): TriggerReflectionResult;
|
|
4
|
-
export declare function reflectTriggerAsync(declarationBody: string): Promise<TriggerReflectionResult>;
|
|
5
3
|
export interface ParamAnnotation {
|
|
6
4
|
bodyLines: string[];
|
|
7
5
|
paramName: string;
|
package/dist/index.js
CHANGED
|
@@ -1,25 +1,82 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
require("
|
|
6
|
+
exports.reflectTrigger = exports.reflect = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const child_process_1 = require("child_process");
|
|
10
|
+
function resolveNativeBinaryPath() {
|
|
11
|
+
const platform = process.platform;
|
|
12
|
+
const arch = process.arch;
|
|
13
|
+
let folderName;
|
|
14
|
+
if (platform === "darwin" && arch === "arm64") {
|
|
15
|
+
folderName = "darwin-arm64";
|
|
16
|
+
}
|
|
17
|
+
else if (platform === "darwin" && arch === "x64") {
|
|
18
|
+
folderName = "darwin-x64";
|
|
19
|
+
}
|
|
20
|
+
else if (platform === "linux" && arch === "x64") {
|
|
21
|
+
folderName = "linux-x64";
|
|
22
|
+
}
|
|
23
|
+
else if (platform === "win32" && arch === "x64") {
|
|
24
|
+
folderName = "windows-x64";
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
throw new Error(`Unsupported platform/arch combination: ${platform}/${arch}`);
|
|
28
|
+
}
|
|
29
|
+
const fileName = platform === "win32" ? "apex-reflection.exe" : "apex-reflection";
|
|
30
|
+
// At runtime, this file is `dist/index.js`, so `__dirname` points to `dist/`.
|
|
31
|
+
// postinstall installs to: dist/native/<platform-arch>/<fileName>
|
|
32
|
+
const downloadedPath = path_1.default.join(__dirname, "native", folderName, fileName);
|
|
33
|
+
// dev flow builds to: dist/native/<platform-arch>/<fileName>
|
|
34
|
+
// (same place), but keep this explicit so we can evolve paths later.
|
|
35
|
+
const devBuiltPath = downloadedPath;
|
|
36
|
+
if (fs_1.default.existsSync(downloadedPath)) {
|
|
37
|
+
return downloadedPath;
|
|
38
|
+
}
|
|
39
|
+
if (fs_1.default.existsSync(devBuiltPath)) {
|
|
40
|
+
return devBuiltPath;
|
|
41
|
+
}
|
|
42
|
+
throw new Error(`Native binary not found. Expected one of:\n- ${downloadedPath}\n- ${devBuiltPath}\n\nIf you just installed this package, ensure postinstall succeeded.\nIf you're developing locally, run the dev build to create the host binary.`);
|
|
43
|
+
}
|
|
44
|
+
function reflectFor(type, declarationBody) {
|
|
45
|
+
const binaryPath = resolveNativeBinaryPath();
|
|
46
|
+
const result = (0, child_process_1.spawnSync)(binaryPath, [`--type=${type}`], {
|
|
47
|
+
input: declarationBody,
|
|
48
|
+
encoding: "utf8",
|
|
49
|
+
maxBuffer: 1024 * 1024 * 50,
|
|
50
|
+
});
|
|
51
|
+
if (result.error) {
|
|
52
|
+
throw new Error(`apex-reflection native binary failed to start. error:\n${String(result.error)}`);
|
|
53
|
+
}
|
|
54
|
+
if (result.status !== 0) {
|
|
55
|
+
throw new Error(`apex-reflection native binary failed (code=${result.status}). stderr:\n${result.stderr ?? ""}`);
|
|
56
|
+
}
|
|
57
|
+
const stdout = (result.stdout ?? "").toString().trim();
|
|
58
|
+
if (!stdout) {
|
|
59
|
+
throw new Error("apex-reflection native binary produced no output on stdout.");
|
|
60
|
+
}
|
|
61
|
+
return stdout;
|
|
62
|
+
}
|
|
5
63
|
function reflect(declarationBody) {
|
|
6
|
-
|
|
7
|
-
|
|
64
|
+
const stdout = reflectFor("reflectType", declarationBody);
|
|
65
|
+
try {
|
|
66
|
+
return JSON.parse(stdout);
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
throw new Error(`apex-reflection native binary output was not valid JSON.\nstdout:\n${stdout}\nerror: ${String(e)}`);
|
|
70
|
+
}
|
|
8
71
|
}
|
|
9
72
|
exports.reflect = reflect;
|
|
10
|
-
async function reflectAsync(declarationBody) {
|
|
11
|
-
// @ts-expect-error "reflectAsync" is added to self by the "out" module
|
|
12
|
-
const result = await self.reflectAsync(declarationBody);
|
|
13
|
-
return JSON.parse(result);
|
|
14
|
-
}
|
|
15
|
-
exports.reflectAsync = reflectAsync;
|
|
16
73
|
function reflectTrigger(declarationBody) {
|
|
17
|
-
|
|
18
|
-
|
|
74
|
+
const stdout = reflectFor("reflectTrigger", declarationBody);
|
|
75
|
+
try {
|
|
76
|
+
return JSON.parse(stdout);
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
throw new Error(`apex-reflection native binary output was not valid JSON.\nstdout:\n${stdout}\nerror: ${String(e)}`);
|
|
80
|
+
}
|
|
19
81
|
}
|
|
20
82
|
exports.reflectTrigger = reflectTrigger;
|
|
21
|
-
function reflectTriggerAsync(declarationBody) {
|
|
22
|
-
// @ts-expect-error "reflectTriggerAsync" is added to self by the "out" module
|
|
23
|
-
return self.reflectTriggerAsync(declarationBody).then((result) => JSON.parse(result));
|
|
24
|
-
}
|
|
25
|
-
exports.reflectTriggerAsync = reflectTriggerAsync;
|
package/package.json
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cparra/apex-reflection",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.23.1",
|
|
4
4
|
"description": "Provides tools for reflecting Apex code, the language used in Salesforce development.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"clean": "rimraf dist",
|
|
8
8
|
"build": "npm run clean && tsc",
|
|
9
|
+
"postinstall": "node publish-scripts/postinstall.js",
|
|
10
|
+
"dev:build": "npm run build && npm run dev:build:native:host && npm run dev:chmod:native:host",
|
|
11
|
+
"dev:build:native:host": "node scripts/build-natives.js --host",
|
|
12
|
+
"dev:chmod:native:host": "node scripts/dev-chmod-native-host.js",
|
|
13
|
+
"dev:version:prerelease": "node scripts/dev-bump-version-prerelease.js",
|
|
14
|
+
"dev:github:release": "node scripts/dev-github-release.js",
|
|
15
|
+
"dev:publish": "node scripts/dev-publish.js",
|
|
9
16
|
"test": "jest"
|
|
10
17
|
},
|
|
11
18
|
"keywords": [
|
|
@@ -28,6 +35,8 @@
|
|
|
28
35
|
},
|
|
29
36
|
"types": "dist/index.d.ts",
|
|
30
37
|
"files": [
|
|
31
|
-
"dist"
|
|
38
|
+
"dist/index.js",
|
|
39
|
+
"dist/index.d.ts",
|
|
40
|
+
"publish-scripts/postinstall.js"
|
|
32
41
|
]
|
|
33
42
|
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Postinstall script.
|
|
5
|
+
* - Downloads the correct native binary for the current platform/arch from GitHub Releases
|
|
6
|
+
* - Stores it inside this package at: dist/native/<platform-arch>/<binaryName>
|
|
7
|
+
* - Ensures executable permissions on Unix-like systems
|
|
8
|
+
*
|
|
9
|
+
* Asset naming convention (GitHub Release assets):
|
|
10
|
+
* apex-reflection-<platform>-<arch>[.exe]
|
|
11
|
+
*
|
|
12
|
+
* Where:
|
|
13
|
+
* platform: darwin | linux | windows
|
|
14
|
+
* arch: x64 | arm64 (darwin supports both; linux/windows only x64 in this setup)
|
|
15
|
+
*
|
|
16
|
+
* The GitHub release tag is expected to be:
|
|
17
|
+
* v<version> (version taken from this package's package.json)
|
|
18
|
+
*
|
|
19
|
+
* Note:
|
|
20
|
+
* - To make installs resilient (especially for dev releases), we try multiple possible asset names.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const https = require("https");
|
|
24
|
+
const fs = require("fs");
|
|
25
|
+
const path = require("path");
|
|
26
|
+
const stream = require("stream");
|
|
27
|
+
const { promisify } = require("util");
|
|
28
|
+
|
|
29
|
+
const pipeline = promisify(stream.pipeline);
|
|
30
|
+
|
|
31
|
+
const REPO_OWNER = "cesarParra";
|
|
32
|
+
const REPO_NAME = "apex-reflection";
|
|
33
|
+
|
|
34
|
+
function main() {
|
|
35
|
+
console.log("[apex-reflection] postinstall: installing native binary...");
|
|
36
|
+
|
|
37
|
+
const pkg = readPackageJson();
|
|
38
|
+
const version = pkg.version;
|
|
39
|
+
if (!version || typeof version !== "string") {
|
|
40
|
+
fail("package.json missing a valid `version` field.");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const target = resolveTarget(process.platform, process.arch);
|
|
44
|
+
const tag = `v${version}`;
|
|
45
|
+
|
|
46
|
+
const outDir = path.join(
|
|
47
|
+
__dirname,
|
|
48
|
+
"..",
|
|
49
|
+
"dist",
|
|
50
|
+
"native",
|
|
51
|
+
target.folderName,
|
|
52
|
+
);
|
|
53
|
+
const outPath = path.join(outDir, target.binaryFileName);
|
|
54
|
+
|
|
55
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
56
|
+
|
|
57
|
+
const candidateAssetNames = buildCandidateAssetNames(target);
|
|
58
|
+
|
|
59
|
+
return downloadFirstAvailableAsset(tag, candidateAssetNames, outPath)
|
|
60
|
+
.then(({ assetName }) => {
|
|
61
|
+
if (process.platform !== "win32") {
|
|
62
|
+
try {
|
|
63
|
+
fs.chmodSync(outPath, 0o755);
|
|
64
|
+
} catch (e) {
|
|
65
|
+
console.warn(
|
|
66
|
+
`[apex-reflection] postinstall: could not chmod +x ${outPath}: ${stringifyErr(e)}`,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.log(
|
|
72
|
+
`[apex-reflection] postinstall: native binary installed at: ${outPath} (asset: ${assetName})`,
|
|
73
|
+
);
|
|
74
|
+
})
|
|
75
|
+
.catch((err) => {
|
|
76
|
+
console.error(
|
|
77
|
+
"[apex-reflection] postinstall: failed to install native binary.",
|
|
78
|
+
);
|
|
79
|
+
console.error(`[apex-reflection] postinstall: ${stringifyErr(err)}`);
|
|
80
|
+
console.error(
|
|
81
|
+
"[apex-reflection] postinstall: Verify the release assets here:",
|
|
82
|
+
);
|
|
83
|
+
console.error(
|
|
84
|
+
`https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/tag/${tag}`,
|
|
85
|
+
);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function readPackageJson() {
|
|
91
|
+
const pkgPath = path.join(__dirname, "..", "package.json");
|
|
92
|
+
const raw = fs.readFileSync(pkgPath, "utf8");
|
|
93
|
+
return JSON.parse(raw);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function resolveTarget(nodePlatform, nodeArch) {
|
|
97
|
+
const platformMap = {
|
|
98
|
+
darwin: "darwin",
|
|
99
|
+
linux: "linux",
|
|
100
|
+
win32: "windows",
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const releasePlatform = platformMap[nodePlatform];
|
|
104
|
+
if (!releasePlatform) {
|
|
105
|
+
throw new Error(`Unsupported platform: ${nodePlatform}`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const supportedArch = new Set(["x64", "arm64"]);
|
|
109
|
+
if (!supportedArch.has(nodeArch)) {
|
|
110
|
+
throw new Error(`Unsupported architecture: ${nodeArch}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (releasePlatform === "linux" && nodeArch !== "x64") {
|
|
114
|
+
throw new Error(`Unsupported architecture for linux: ${nodeArch}`);
|
|
115
|
+
}
|
|
116
|
+
if (releasePlatform === "windows" && nodeArch !== "x64") {
|
|
117
|
+
throw new Error(`Unsupported architecture for windows: ${nodeArch}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const folderName = `${releasePlatform}-${nodeArch}`;
|
|
121
|
+
const exeExt = releasePlatform === "windows" ? ".exe" : "";
|
|
122
|
+
const binaryFileName = `apex-reflection${exeExt}`;
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
releasePlatform,
|
|
126
|
+
releaseArch: nodeArch,
|
|
127
|
+
folderName,
|
|
128
|
+
exeExt,
|
|
129
|
+
binaryFileName,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function buildCandidateAssetNames(target) {
|
|
134
|
+
// Primary convention (expected):
|
|
135
|
+
// apex-reflection-<platform>-<arch>[.exe]
|
|
136
|
+
const primary = `apex-reflection-${target.releasePlatform}-${target.releaseArch}${target.exeExt}`;
|
|
137
|
+
|
|
138
|
+
// Fallbacks (mainly for dev flows / edge cases):
|
|
139
|
+
const fallbacks = [];
|
|
140
|
+
|
|
141
|
+
// Unsuffixed name (no arch/platform)
|
|
142
|
+
// - For windows, prefer .exe and then without extension (just in case).
|
|
143
|
+
if (target.releasePlatform === "windows") {
|
|
144
|
+
fallbacks.push("apex-reflection.exe");
|
|
145
|
+
fallbacks.push("apex-reflection");
|
|
146
|
+
} else {
|
|
147
|
+
fallbacks.push("apex-reflection");
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// De-dup while preserving order
|
|
151
|
+
const seen = new Set();
|
|
152
|
+
return [primary, ...fallbacks].filter((name) => {
|
|
153
|
+
if (seen.has(name)) return false;
|
|
154
|
+
seen.add(name);
|
|
155
|
+
return true;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function downloadFirstAvailableAsset(tag, assetNames, destPath) {
|
|
160
|
+
const base = `https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/download/${tag}/`;
|
|
161
|
+
|
|
162
|
+
let lastErr = null;
|
|
163
|
+
|
|
164
|
+
// Try sequentially until one downloads successfully
|
|
165
|
+
return assetNames
|
|
166
|
+
.reduce(
|
|
167
|
+
(p, assetName) => {
|
|
168
|
+
return p.catch((_) => {
|
|
169
|
+
const url = `${base}${assetName}`;
|
|
170
|
+
process.stdout.write(
|
|
171
|
+
`[apex-reflection] postinstall: trying ${url}\n`,
|
|
172
|
+
);
|
|
173
|
+
return downloadFile(url, destPath).then(() => ({ assetName }));
|
|
174
|
+
});
|
|
175
|
+
},
|
|
176
|
+
Promise.reject(new Error("No candidate asset attempted yet.")),
|
|
177
|
+
)
|
|
178
|
+
.catch((err) => {
|
|
179
|
+
lastErr = err;
|
|
180
|
+
const tried = assetNames.map((n) => `${base}${n}`).join("\n");
|
|
181
|
+
const msg =
|
|
182
|
+
`Unable to download any matching binary asset for ${process.platform}/${process.arch}.\n` +
|
|
183
|
+
`Tried:\n${tried}\n` +
|
|
184
|
+
`Last error: ${stringifyErr(lastErr)}`;
|
|
185
|
+
throw new Error(msg);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function downloadFile(url, destPath) {
|
|
190
|
+
return new Promise((resolve, reject) => {
|
|
191
|
+
const tmpPath = `${destPath}.tmp`;
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath);
|
|
195
|
+
} catch (_) {
|
|
196
|
+
// ignore
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const request = https.get(url, (response) => {
|
|
200
|
+
if (response.statusCode === 301 || response.statusCode === 302) {
|
|
201
|
+
const next = response.headers.location;
|
|
202
|
+
response.resume();
|
|
203
|
+
if (!next)
|
|
204
|
+
return reject(new Error(`Redirect with no location for ${url}`));
|
|
205
|
+
return downloadFile(next, destPath).then(resolve, reject);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (response.statusCode !== 200) {
|
|
209
|
+
response.resume();
|
|
210
|
+
return reject(
|
|
211
|
+
new Error(`HTTP ${response.statusCode} while downloading ${url}`),
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const totalSize = Number(response.headers["content-length"] || 0);
|
|
216
|
+
let downloaded = 0;
|
|
217
|
+
|
|
218
|
+
response.on("data", (chunk) => {
|
|
219
|
+
downloaded += chunk.length;
|
|
220
|
+
if (totalSize > 0) {
|
|
221
|
+
const pct = Math.floor((downloaded / totalSize) * 100);
|
|
222
|
+
process.stdout.write(
|
|
223
|
+
`\r[apex-reflection] postinstall: downloading... ${pct}%`,
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
const file = fs.createWriteStream(tmpPath);
|
|
229
|
+
|
|
230
|
+
pipeline(response, file)
|
|
231
|
+
.then(() => {
|
|
232
|
+
process.stdout.write("\n");
|
|
233
|
+
fs.renameSync(tmpPath, destPath);
|
|
234
|
+
resolve();
|
|
235
|
+
})
|
|
236
|
+
.catch((err) => {
|
|
237
|
+
try {
|
|
238
|
+
if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath);
|
|
239
|
+
} catch (_) {
|
|
240
|
+
// ignore
|
|
241
|
+
}
|
|
242
|
+
reject(err);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
request.on("error", (err) => {
|
|
247
|
+
try {
|
|
248
|
+
if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath);
|
|
249
|
+
} catch (_) {
|
|
250
|
+
// ignore
|
|
251
|
+
}
|
|
252
|
+
reject(err);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function stringifyErr(e) {
|
|
258
|
+
if (!e) return "unknown error";
|
|
259
|
+
if (typeof e === "string") return e;
|
|
260
|
+
if (e && e.message) return e.message;
|
|
261
|
+
try {
|
|
262
|
+
return JSON.stringify(e);
|
|
263
|
+
} catch (_) {
|
|
264
|
+
return String(e);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function fail(msg) {
|
|
269
|
+
console.error(`[apex-reflection] postinstall: ${msg}`);
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
Promise.resolve(main());
|
package/dist/out.d.ts
DELETED