Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
node_modules
dist
entry-asar/*.js*
entry-asar/*.ts
entry-asar/cjs/*.js*
entry-asar/cjs/*.d.ts
entry-asar/esm/*.?js*
entry-asar/esm/*.d.?ts
*.app
test/fixtures/apps
coverage
File renamed without changes.
File renamed without changes.
11 changes: 11 additions & 0 deletions entry-asar/cjs/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": ".",
},
"include": [
".",
"../ambient.d.ts"
],
"exclude": []
}
28 changes: 28 additions & 0 deletions entry-asar/esm/has-asar.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { app } from 'electron';
import { createRequire } from 'node:module';
import path from 'node:path';

if (process.arch === 'arm64') {
await setPaths('arm64');
} else {
await setPaths('x64');
}

async function setPaths(platform: string) {
// This should return the full path, ending in something like
// Notion.app/Contents/Resources/app.asar
const appPath = app.getAppPath();
const asarFile = `app-${platform}.asar`;

// Maybe we'll handle this in Electron one day
if (path.basename(appPath) === 'app.asar') {
const platformAppPath = path.join(path.dirname(appPath), asarFile);

// This is an undocumented API. It exists.
app.setAppPath(platformAppPath);
}

const require = createRequire(import.meta.url);
process._archPath = require.resolve(`../${asarFile}`);
await import(process._archPath);
}
29 changes: 29 additions & 0 deletions entry-asar/esm/no-asar.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { app } from 'electron';
import { createRequire } from 'node:module';
import path from 'node:path';

if (process.arch === 'arm64') {
await setPaths('arm64');
} else {
await setPaths('x64');
}

async function setPaths(platform: string) {
// This should return the full path, ending in something like
// Notion.app/Contents/Resources/app
const appPath = app.getAppPath();
const appFolder = `app-${platform}`;

// Maybe we'll handle this in Electron one day
if (path.basename(appPath) === 'app') {
const platformAppPath = path.join(path.dirname(appPath), appFolder);

// This is an undocumented private API. It exists.
app.setAppPath(platformAppPath);
}

const require = createRequire(import.meta.url);
process._archPath = require.resolve(`../${appFolder}`);

await import(process._archPath);
}
13 changes: 13 additions & 0 deletions entry-asar/esm/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.esm.json",
"compilerOptions": {
"module": "ESNext",
"target":"ESNext",
"outDir": ".",
},
"include": [
".",
"../ambient.d.ts"
],
"exclude": []
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@
"dist/*",
"entry-asar/*",
"!entry-asar/**/*.ts",
"!entry-asar/**/tsconfig.json",
"README.md"
],
"author": "Samuel Attard",
"scripts": {
"build": "tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json && tsc -p tsconfig.entry-asar.json",
"build": "tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json && tsc -p entry-asar/esm/tsconfig.json && tsc -p entry-asar/cjs/tsconfig.json",
"lint": "prettier --check \"{src,entry-asar,test}/**/*.ts\" \"*.ts\"",
"prettier:write": "prettier --write \"{src,entry-asar,test}/**/*.ts\" \"*.ts\"",
"prepublishOnly": "npm run build",
Expand Down
45 changes: 35 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,14 +210,27 @@ export const makeUniversalApp = async (opts: MakeUniversalOpts): Promise<void> =

const entryAsar = path.resolve(tmpDir, 'entry-asar');
await fs.mkdir(entryAsar);
await fs.copy(
path.resolve(__dirname, '..', '..', 'entry-asar', 'no-asar.js'),
path.resolve(entryAsar, 'index.js'),
);

let pj = await fs.readJson(
path.resolve(opts.x64AppPath, 'Contents', 'Resources', 'app', 'package.json'),
);
pj.main = 'index.js';

// Load a shim that redirects to the correct folder for the architecture.
// This needs to be a different file depending on if the app entrypoint is CommonJS or ESM.
if (pj.type === 'module' || pj.main.endsWith('.mjs')) {
await fs.copy(
path.resolve(__dirname, '..', '..', 'entry-asar', 'esm', 'no-asar.mjs'),
path.resolve(entryAsar, 'index.mjs'),
);
pj.main = 'index.mjs';
} else {
await fs.copy(
path.resolve(__dirname, '..', '..', 'entry-asar', 'cjs', 'no-asar.js'),
path.resolve(entryAsar, 'index.js'),
);
pj.main = 'index.js';
}

await fs.writeJson(path.resolve(entryAsar, 'package.json'), pj);
await asar.createPackage(
entryAsar,
Expand Down Expand Up @@ -290,10 +303,6 @@ export const makeUniversalApp = async (opts: MakeUniversalOpts): Promise<void> =

const entryAsar = path.resolve(tmpDir, 'entry-asar');
await fs.mkdir(entryAsar);
await fs.copy(
path.resolve(__dirname, '..', '..', 'entry-asar', 'has-asar.js'),
path.resolve(entryAsar, 'index.js'),
);
let pj = JSON.parse(
(
await asar.extractFile(
Expand All @@ -302,7 +311,23 @@ export const makeUniversalApp = async (opts: MakeUniversalOpts): Promise<void> =
)
).toString('utf8'),
);
pj.main = 'index.js';

// Load a shim that redirects to the correct `app.asar` for the architecture.
// This needs to be a different file depending on if the app entrypoint is CommonJS or ESM.
if (pj.type === 'module' || pj.main.endsWith('.mjs')) {
await fs.copy(
path.resolve(__dirname, '..', '..', 'entry-asar', 'esm', 'has-asar.mjs'),
path.resolve(entryAsar, 'index.mjs'),
);
pj.main = 'index.mjs';
} else {
await fs.copy(
path.resolve(__dirname, '..', '..', 'entry-asar', 'cjs', 'has-asar.js'),
path.resolve(entryAsar, 'index.js'),
);
pj.main = 'index.js';
}

await fs.writeJson(path.resolve(entryAsar, 'package.json'), pj);
const asarPath = path.resolve(tmpApp, 'Contents', 'Resources', 'app.asar');
await asar.createPackage(entryAsar, asarPath);
Expand Down
10 changes: 0 additions & 10 deletions tsconfig.entry-asar.json

This file was deleted.

5 changes: 2 additions & 3 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"declaration": true
},
"include": [
"src",
"entry-asar"
]
"src"
],
}