Skip to content

Commit

Permalink
Add "prepare" mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Black-Platypus committed Oct 7, 2024
1 parent 63aa95b commit e045142
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 52 deletions.
119 changes: 75 additions & 44 deletions src/bld.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,44 +122,65 @@ async function bld({
nativeAddon = false,
zip = false,
releaseInfo = {},
mode = 'build'
}) {
const nwDir = path.resolve(
cacheDir,
`nwjs${flavor === 'sdk' ? '-sdk' : ''}-v${version}-${platform
}-${arch}`,
);

await fs.promises.rm(outDir, { force: true, recursive: true });
await fs.promises.cp(nwDir, outDir, { recursive: true, verbatimSymlinks: true });

const files = await util.globFiles({ srcDir, glob });
const manifest = await util.getNodeManifest({ srcDir, glob });

if (glob) {
for (let file of files) {

if(mode == "build"){
// TODO: Check if outDir is really a previous built dir (known files?) to avoid catastrophy on misconfiguration
await fs.promises.rm(outDir, { force: true, recursive: true });
await fs.promises.cp(nwDir, outDir, { recursive: true, verbatimSymlinks: true });

const files = await util.globFiles({ srcDir, glob });
const manifest = await util.getNodeManifest({ srcDir, glob });

if (glob) {
for (let file of files) {
await fs.promises.cp(
file,
path.resolve(
outDir,
platform !== 'osx'
? 'package.nw'
: 'nwjs.app/Contents/Resources/app.nw',
file,
),
{ recursive: true, verbatimSymlinks: true },
);
}
} else {
await fs.promises.cp(
file,
files,
path.resolve(
outDir,
platform !== 'osx'
? 'package.nw'
: 'nwjs.app/Contents/Resources/app.nw',
file,
),
{ recursive: true, verbatimSymlinks: true },
);
}
} else {
await fs.promises.cp(
files,
path.resolve(
outDir,
platform !== 'osx'
? 'package.nw'
: 'nwjs.app/Contents/Resources/app.nw',
),
{ recursive: true, verbatimSymlinks: true },
);
}

var appInfo = {version, flavor, platform, arch, srcDir, cacheDir, outDir, app, glob, managedManifest, nativeAddon, zip, releaseInfo, mode};
if (platform === 'linux') {
Object.assign(appInfo, prepareLinuxConfig(appInfo));
if(mode=='prepare')
return appInfo;
await applyLinuxConfig(appInfo);
} else if (platform === 'win') {
Object.assign(appInfo, prepareWinConfig(appInfo));
if(mode=='prepare')
return appInfo;
await applyWinConfig(appInfo);
} else if (platform === 'osx') {
Object.assign(appInfo, await setOsxConfig(appInfo));
if(mode=='prepare')
return appInfo;
}

const nodeVersion = releaseInfo.components.node;
Expand All @@ -172,21 +193,14 @@ async function bld({
await manageManifest({ nwPkg: manifest, managedManifest, outDir, platform });
}

if (platform === 'linux') {
await setLinuxConfig({ app, outDir });
} else if (platform === 'win') {
await setWinConfig({ app, outDir });
} else if (platform === 'osx') {
await setOsxConfig({ app, outDir, releaseInfo });
}

if (nativeAddon === 'gyp') {
buildNativeAddon({ cacheDir, version, platform, arch, outDir, nodeVersion });
}

if (zip !== false) {
await compress({ zip, outDir });
}
return appInfo;
}

const manageManifest = async ({ nwPkg, managedManifest, outDir, platform }) => {
Expand Down Expand Up @@ -237,7 +251,7 @@ const manageManifest = async ({ nwPkg, managedManifest, outDir, platform }) => {
}
};

const setLinuxConfig = async ({ app, outDir }) => {
const prepareLinuxConfig = async ({ app, outDir }) => {
if (process.platform === 'win32') {
console.warn(
'Linux apps built on Windows platform do not preserve all file permissions. See #716',
Expand Down Expand Up @@ -270,20 +284,34 @@ const setLinuxConfig = async ({ app, outDir }) => {
SingleMainWindow: app.singleMainWindow,
};

await fs.promises.rename(`${outDir}/nw`, `${outDir}/${app.name}`);
return {
outDir,
executablePath: `${outDir}/${app.name}`,
desktopEntryFile
};
};

const applyLinuxConfig = async ({ outDir, executablePath, desktopEntryFile }) => {
if (process.platform === 'win32') {
console.warn(
'Linux apps built on Windows platform do not preserve all file permissions. See #716',
);
}

await fs.promises.rename(`${outDir}/nw`, executablePath);

let fileContent = '[Desktop Entry]\n';
Object.keys(desktopEntryFile).forEach((key) => {
if (desktopEntryFile[key] !== undefined) {
fileContent += `${key}=${desktopEntryFile[key]}\n`;
}
});
let filePath = `${outDir}/${app.name}.desktop`;
let filePath = `${executablePath}.desktop`;
await fs.promises.writeFile(filePath, fileContent);
};

const setWinConfig = async ({ app, outDir }) => {
let versionString = {
const prepareWinConfig = ({ app, outDir }) => {
let versionInfo = {
Comments: app.comments,
CompanyName: app.company,
FileDescription: app.fileDescription,
Expand All @@ -298,15 +326,18 @@ const setWinConfig = async ({ app, outDir }) => {
SpecialBuild: app.specialBuild,
};

Object.keys(versionString).forEach((option) => {
if (versionString[option] === undefined) {
delete versionString[option];
Object.keys(versionInfo).forEach((option) => {
if (versionInfo[option] === undefined) {
delete versionInfo[option];
}
});

const outDirAppExe = path.resolve(outDir, `${app.name}.exe`);
await fs.promises.rename(path.resolve(outDir, 'nw.exe'), outDirAppExe);
const exe = peLibrary.NtExecutable.from(await fs.promises.readFile(outDirAppExe));
const executableName = app.name.replace(/[<>:"/\\|?*\u0000-\u001F]/g, "");
const executablePath = path.resolve(outDir, `${executableName}.exe`);
return { versionInfo, outDir, executablePath };
};
const applyWinConfig = async ({ app, versionInfo, outDir, executablePath }) => {
await fs.promises.rename(path.resolve(outDir, 'nw.exe'), executablePath);
const exe = peLibrary.NtExecutable.from(await fs.promises.readFile(executablePath));
const res = peLibrary.NtExecutableResource.from(exe);
// English (United States)
const EN_US = 1033;
Expand Down Expand Up @@ -335,11 +366,11 @@ const setWinConfig = async ({ app, outDir }) => {
vi.setStringValues({
lang: app.languageCode,
codepage: 1200
}, versionString);
}, versionInfo);
vi.outputToResourceEntries(res.entries);
res.outputResource(exe);
const outBuffer = Buffer.from(exe.generate());
await fs.promises.writeFile(outDirAppExe, outBuffer);
await fs.promises.writeFile(executablePath, outBuffer);
};

const buildNativeAddon = ({ cacheDir, version, platform, arch, outDir, nodeVersion }) => {
Expand Down
3 changes: 2 additions & 1 deletion src/bld/osx.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ async function updateHelperPlist (plistPath, helperName, helperId, appCFBundleId
* @param {string} options.releaseInfo - Release information.
* @returns {Promise<void>} - Promise.
*/
export default async function setOsxConfig({ app, outDir, releaseInfo }) {
// TODO: implement "prepare" mode
export default async function setOsxConfig({ app, outDir, releaseInfo, mode }) {
if (process.platform === 'win32') {
console.warn(
'MacOS apps built on Windows platform do not preserve all file permissions. See #716',
Expand Down
2 changes: 1 addition & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface Options<P extends SupportedPlatform = SupportedPlatform> {
/** String of space separated glob patterns which correspond to NW app code */
srcDir?: "./" | string,
/** Run or build application */
mode?: "build" | "get" | "run",
mode?: "build" | "get" | "run" | "prepare",
/** NW runtime version */
version?: "latest" | "stable" | string,
/** NW runtime flavor */
Expand Down
8 changes: 6 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ async function nwbuild(options) {
try {
// Parse options
// options = await util.parse(options, manifest); // Preserve user input for now, assign manifest overwrites, only then parse
var isPrepare = options.mode === 'prepare';

manifest = await util.getNodeManifest({ srcDir: options.srcDir, glob: options.glob });
if (typeof manifest?.nwbuild === 'object') {
Expand All @@ -53,6 +54,8 @@ async function nwbuild(options) {
Object.assign(options, manifest.nwbuild);
options.app = appOptions;
}
if(isPrepare)
options.mode = 'prepare';

options = await util.parse(options, manifest);

Expand Down Expand Up @@ -113,8 +116,9 @@ async function nwbuild(options) {
glob: options.glob,
argv: options.argv,
});
} else if (options.mode === 'build') {
await bld({
} else if (options.mode === 'build' || options.mode === 'prepare') {
return await bld({
mode: options.mode,
version: options.version,
flavor: options.flavor,
platform: options.platform,
Expand Down
8 changes: 4 additions & 4 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,8 @@ export const parse = async (options, pkg) => {

options.app = options.app ?? {};
options.app.name = options.app.name ?? pkg.name;
options.app.icon = options.app.icon ?? undefined;
options.app.name = options.app.name.replace(/[<>:"/\\|?*\u0000-\u001F]/g, "");
options.app.icon = options.app.icon ? path.resolve(options.app.icon) : undefined;

// TODO(#737): move this out
if (options.platform === 'linux') {
Expand Down Expand Up @@ -278,10 +279,9 @@ export const parse = async (options, pkg) => {
* @throws {Error} Throw error if options are invalid
*/
export const validate = async (options, releaseInfo) => {
if (!['get', 'run', 'build'].includes(options.mode)) {
if (!['get', 'run', 'build', 'prepare'].includes(options.mode)) {
throw new Error(
`Unknown mode ${options.mode}. Expected "get", "run" or "build".`,
);
`Unknown mode ${options.mode}. Expected "get", "run", "build" or "prepare".`);
}
if (typeof releaseInfo === 'undefined') {
throw new Error(
Expand Down

0 comments on commit e045142

Please sign in to comment.