@cparra/apex-reflection 2.22.0 → 2.23.2

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 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,93 @@
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.reflectTriggerAsync = exports.reflectTrigger = exports.reflectAsync = exports.reflect = void 0;
4
- require("./out.js");
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
+ }
5
44
  function reflect(declarationBody) {
6
- // @ts-expect-error "reflect" is added to self by the "out" module
7
- return JSON.parse(self.reflect(declarationBody));
45
+ const binaryPath = resolveNativeBinaryPath();
46
+ const result = (0, child_process_1.spawnSync)(binaryPath, ["--type=reflectType"], {
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
+ try {
62
+ return JSON.parse(stdout);
63
+ }
64
+ catch (e) {
65
+ throw new Error(`apex-reflection native binary output was not valid JSON.\nstdout:\n${stdout}\nerror: ${String(e)}`);
66
+ }
8
67
  }
9
68
  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
69
  function reflectTrigger(declarationBody) {
17
- // @ts-expect-error "reflectTrigger" is added to self by the "out" module
18
- return JSON.parse(self.reflectTrigger(declarationBody));
70
+ const binaryPath = resolveNativeBinaryPath();
71
+ const result = (0, child_process_1.spawnSync)(binaryPath, ["--type=reflectTrigger"], {
72
+ input: declarationBody,
73
+ encoding: "utf8",
74
+ maxBuffer: 1024 * 1024 * 50,
75
+ });
76
+ if (result.error) {
77
+ throw new Error(`apex-reflection native binary failed to start. error:\n${String(result.error)}`);
78
+ }
79
+ if (result.status !== 0) {
80
+ throw new Error(`apex-reflection native binary failed (code=${result.status}). stderr:\n${result.stderr ?? ""}`);
81
+ }
82
+ const stdout = (result.stdout ?? "").toString().trim();
83
+ if (!stdout) {
84
+ throw new Error("apex-reflection native binary produced no output on stdout.");
85
+ }
86
+ try {
87
+ return JSON.parse(stdout);
88
+ }
89
+ catch (e) {
90
+ throw new Error(`apex-reflection native binary output was not valid JSON.\nstdout:\n${stdout}\nerror: ${String(e)}`);
91
+ }
19
92
  }
20
93
  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.22.0",
3
+ "version": "2.23.2",
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
@@ -1,3 +0,0 @@
1
- declare var dartNodeIsActuallyNode: boolean;
2
- declare var self: any;
3
- declare var url: any;