Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@forwardimpact/libmacos

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@forwardimpact/libmacos - npm Package Compare versions

Comparing version
0.1.2
to
0.1.3
+4
-1
package.json
{
"name": "@forwardimpact/libmacos",
"version": "0.1.2",
"version": "0.1.3",
"description": "macOS bundle assembly, code signing, and OS permission helpers — desktop delivery without platform ceremony.",

@@ -34,2 +34,5 @@ "keywords": [

},
"dependencies": {
"@forwardimpact/libutil": "^0.1.60"
},
"devDependencies": {

@@ -36,0 +39,0 @@ "@forwardimpact/libmock": "^0.1.0"

+37
-16

@@ -9,6 +9,8 @@ // @ts-check

import { dlopen, ptr } from "bun:ffi";
import { openSync, closeSync, readFileSync, unlinkSync } from "node:fs";
import { randomUUID } from "node:crypto";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { createDefaultRuntime } from "@forwardimpact/libutil/runtime";
// responsibility_spawnattrs_setdisclaim makes the spawned child disclaim

@@ -100,7 +102,9 @@ // TCC "responsible process" status, so macOS checks the parent's responsible

* @param {string} filePath
* @param {object} [runtime] - Runtime collaborator bag
* @returns {string}
*/
export function readOutput(filePath) {
export function readOutput(filePath, runtime = createDefaultRuntime()) {
const { fsSync } = runtime;
try {
return readFileSync(filePath, "utf-8");
return fsSync.readFileSync(filePath, "utf-8");
} catch {

@@ -110,3 +114,3 @@ return "";

try {
unlinkSync(filePath);
fsSync.unlinkSync(filePath);
} catch {

@@ -129,7 +133,15 @@ // temp file may already be gone

* @param {string} [cwd] - Working directory for the child process
* @param {object} [runtime] - Runtime collaborator bag
* @returns {{ pid: number, stdoutFile: string, stderrFile: string }}
*/
export function spawn(executable, args, env, cwd) {
export function spawn(
executable,
args,
env,
cwd,
runtime = createDefaultRuntime(),
) {
const { proc, clock, fsSync } = runtime;
const argv = buildStringArray([executable, ...args]);
const envObj = env ?? { ...process.env };
const envObj = env ?? { ...proc.env };
const envStrings = Object.entries(envObj)

@@ -140,8 +152,11 @@ .filter(([, v]) => typeof v === "string")

// Capture stdout/stderr via temp files instead of pipes.
const tag = `outpost-${process.pid}-${Date.now()}`;
// Capture stdout/stderr via temp files instead of pipes. The tag must be
// unique across concurrent spawns; `runtime.proc` exposes no pid, so a
// random UUID replaces the former `${pid}-${Date.now()}` scheme (clock.now()
// alone is not unique within a millisecond).
const tag = `outpost-${clock.now()}-${randomUUID()}`;
const stdoutFile = join(tmpdir(), `${tag}-stdout`);
const stderrFile = join(tmpdir(), `${tag}-stderr`);
const stdoutFd = openSync(stdoutFile, "w", 0o600);
const stderrFd = openSync(stderrFile, "w", 0o600);
const stdoutFd = fsSync.openSync(stdoutFile, "w", 0o600);
const stderrFd = fsSync.openSync(stderrFile, "w", 0o600);

@@ -183,4 +198,4 @@ // Allocate attr and file_actions on the heap

// Close file fds in the parent (child has its own copies)
closeSync(stdoutFd);
closeSync(stderrFd);
fsSync.closeSync(stdoutFd);
fsSync.closeSync(stderrFd);

@@ -192,3 +207,3 @@ libc.symbols.posix_spawnattr_destroy(attr);

try {
unlinkSync(stdoutFile);
fsSync.unlinkSync(stdoutFile);
} catch {

@@ -198,3 +213,3 @@ // cleanup best-effort

try {
unlinkSync(stderrFile);
fsSync.unlinkSync(stderrFile);
} catch {

@@ -214,5 +229,11 @@ // cleanup best-effort

* @param {number} [pollIntervalMs=100] - Polling interval in milliseconds
* @param {object} [runtime] - Runtime collaborator bag
* @returns {Promise<number>} Exit status
*/
export async function waitForExit(pid, pollIntervalMs = 100) {
export async function waitForExit(
pid,
pollIntervalMs = 100,
runtime = createDefaultRuntime(),
) {
const { clock } = runtime;
const status = new Int32Array(1);

@@ -226,4 +247,4 @@ while (true) {

// Child not yet exited — yield to event loop
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
await clock.sleep(pollIntervalMs);
}
}