Skip to content

Programmatic SEA blob generation API #52777

Description

@james-pre

Currently, CLI commands and many files are involved in generating a SEA using Javascript.

For example:

import { execSync } from 'node:child_process';
import { copyFileSync, readFileSync, writeFileSync } from 'node:fs';
import { inject } from 'postject';

const blobPath = 'path/to/sea.blob',
	configPath = 'path/to/sea.json',
	outputPath = 'path/to/executable';

writeFileSync(
	configPath,
	JSON.stringify({
		main: 'path/to/main.js',
		output: blobPath,
		disableExperimentalSEAWarning: true,
	})
);
execSync('node --experimental-sea-config ' + configPath, { stdio: 'inherit' });
copyFileSync(process.execPath, outputPath);
await inject(outputPath, 'NODE_SEA_BLOB', readFileSync(blobPath), {
	machoSegmentName: 'NODE_SEA',
	sentinelFuse: 'NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2',
});

It would be nice if Node.js provided a Javascript API for generating SEA blobs. This would eliminate extra file creation and streamline the SEA creation process. I propose adding a function to the node:sea module/API (Typescript used for clarity):

/**
 * Configuration options for generating a SEA blob
 * @see https://nodejs.org/api/single-executable-applications.html#generating-single-executable-preparation-blobs
 */
interface BlobConfiguration {
	main: string;
	disableExperimentalSEAWarning?: boolean;
	useSnapshot?: boolean;
	useCodeCache?: boolean;
	assets?: Record<string, string>;
}

/**
 * Generates a SEA blob to be injected into an executable
 * @param config configuration options for the blob
 * @returns The blob contents in a buffer
 */
function generateBlob(config: BlobConfiguration): Buffer;

This new function in the SEA API would allow for more streamlined and readable code:

import { copyFileSync } from 'node:fs';
import { generateBlob } from 'node:sea';
import { inject } from 'postject';

const outputPath = 'path/to/executable';

const blob = generateBlob({
	main: 'path/to/main.js',
	disableExperimentalSEAWarning: true,
});
copyFileSync(process.execPath, outputPath);
await inject(outputPath, 'NODE_SEA_BLOB', blob, {
	machoSegmentName: 'NODE_SEA',
	sentinelFuse: 'NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2',
});

Which could even be inlined:

import { copyFileSync } from 'node:fs';
import { generateBlob } from 'node:sea';
import { inject } from 'postject';

const outputPath = 'path/to/executable';

copyFileSync(process.execPath, outputPath);
await inject(
	outputPath,
	'NODE_SEA_BLOB',
	generateBlob({
		main: 'path/to/main.js',
		disableExperimentalSEAWarning: true,
	}),
	{
		machoSegmentName: 'NODE_SEA',
		sentinelFuse: 'NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2',
	}
);

Discussion
Issue on nodejs/single-executable

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestIssues requesting new Node.js features.single-executableIssues and PRs related to single-executable applications.staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions