Skip to content

Commit a2c4fff

Browse files
committed
fix: restore package.json when encryption fails
1 parent 1952f36 commit a2c4fff

File tree

2 files changed

+173
-164
lines changed

2 files changed

+173
-164
lines changed

playground/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "electron-builder-encryptor-demo",
33
"version": "1.0.0",
44
"description": "",
5-
"type": "commonjs",
5+
"type": "module",
66
"keywords": [],
77
"license": "MIT",
88
"homepage": "https://github.com/dusionlike/electron-builder-encryptor#readme",

src/index.ts

Lines changed: 172 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -27,203 +27,212 @@ export interface RunOptions {
2727
export async function run(context: AfterPackContext, options: RunOptions = {}) {
2828
const time = Date.now()
2929

30+
let isPorjectEsm = false
31+
3032
const porjectPackageJsonStr = await fs.promises.readFile(
3133
'package.json',
3234
'utf8'
3335
)
34-
const porjectPackageJson = JSON.parse(porjectPackageJsonStr)
35-
const isPorjectEsm = porjectPackageJson.type === 'module'
36-
if (isPorjectEsm) {
37-
// 先改为commonjs,使用正则修改,防止格式化
38-
const newPorjectPackageJsonStr = porjectPackageJsonStr.replace(
39-
/"type":\s*"module"/,
40-
'"type": "commonjs"'
41-
)
42-
await fs.promises.writeFile(
43-
'package.json',
44-
newPorjectPackageJsonStr,
45-
'utf8'
46-
)
47-
}
4836

49-
const outConfigPath = await buildConfig()
50-
const encryptorConfig = await loadConfig(outConfigPath)
37+
try {
38+
const porjectPackageJson = JSON.parse(porjectPackageJsonStr)
39+
isPorjectEsm = porjectPackageJson.type === 'module'
40+
if (isPorjectEsm) {
41+
// 先改为commonjs,使用正则修改,防止格式化
42+
const newPorjectPackageJsonStr = porjectPackageJsonStr.replace(
43+
/"type":\s*"module"/,
44+
'"type": "commonjs"'
45+
)
46+
await fs.promises.writeFile(
47+
'package.json',
48+
newPorjectPackageJsonStr,
49+
'utf8'
50+
)
51+
}
5152

52-
let appOutDir = context.appOutDir
53+
const outConfigPath = await buildConfig()
54+
const encryptorConfig = await loadConfig(outConfigPath)
5355

54-
if (context.packager.platform.name === 'mac') {
55-
appOutDir = path.join(
56-
appOutDir,
57-
`${context.packager.appInfo.productFilename}.app`,
58-
'Contents'
59-
)
60-
}
56+
let appOutDir = context.appOutDir
6157

62-
const tempAppDir = path.join(appOutDir, '../', 'app')
58+
if (context.packager.platform.name === 'mac') {
59+
appOutDir = path.join(
60+
appOutDir,
61+
`${context.packager.appInfo.productFilename}.app`,
62+
'Contents'
63+
)
64+
}
6365

64-
const resourcesDir = path.join(appOutDir, 'resources')
65-
const appAsarPath = path.join(resourcesDir, 'app.asar')
66+
const tempAppDir = path.join(appOutDir, '../', 'app')
6667

67-
// 先解压到缓存目录
68-
asar.extractAll(appAsarPath, tempAppDir)
68+
const resourcesDir = path.join(appOutDir, 'resources')
69+
const appAsarPath = path.join(resourcesDir, 'app.asar')
6970

70-
const packageJson = JSON.parse(
71-
await fs.promises.readFile(path.join(tempAppDir, 'package.json'), 'utf8')
72-
)
73-
if (packageJson.type === 'module') {
74-
// 如果是esm,将type改为commonjs,再打包回去先
75-
packageJson.type = 'commonjs'
76-
await fs.promises.writeFile(
77-
path.join(tempAppDir, 'package.json'),
78-
JSON.stringify(packageJson, null, 2),
79-
'utf8'
71+
// 先解压到缓存目录
72+
asar.extractAll(appAsarPath, tempAppDir)
73+
74+
const packageJson = JSON.parse(
75+
await fs.promises.readFile(path.join(tempAppDir, 'package.json'), 'utf8')
8076
)
77+
if (packageJson.type === 'module') {
78+
// 如果是esm,将type改为commonjs,再打包回去先
79+
packageJson.type = 'commonjs'
80+
await fs.promises.writeFile(
81+
path.join(tempAppDir, 'package.json'),
82+
JSON.stringify(packageJson, null, 2),
83+
'utf8'
84+
)
85+
await asar.createPackage(tempAppDir, appAsarPath)
86+
}
87+
const mainJsPath = path.join(tempAppDir, packageJson.main)
88+
const mainDir = path.dirname(mainJsPath)
89+
90+
// 将入口改为编译器
91+
fs.renameSync(mainJsPath, `${mainJsPath}.tmp`)
92+
await fs.promises.writeFile(mainJsPath, 'require(process.argv[1])', 'utf-8')
8193
await asar.createPackage(tempAppDir, appAsarPath)
82-
}
83-
const mainJsPath = path.join(tempAppDir, packageJson.main)
84-
const mainDir = path.dirname(mainJsPath)
85-
86-
// 将入口改为编译器
87-
fs.renameSync(mainJsPath, `${mainJsPath}.tmp`)
88-
await fs.promises.writeFile(mainJsPath, 'require(process.argv[1])', 'utf-8')
89-
await asar.createPackage(tempAppDir, appAsarPath)
90-
fs.renameSync(`${mainJsPath}.tmp`, mainJsPath)
91-
92-
// 可执行文件
93-
let execPath = path.join(
94-
appOutDir,
95-
context.packager.platform.name === 'mac' ? 'MacOS' : '',
96-
context.packager.appInfo.productFilename
97-
)
98-
if (context.packager.platform.name === 'windows') {
99-
execPath = `${execPath}.exe`
100-
}
94+
fs.renameSync(`${mainJsPath}.tmp`, mainJsPath)
10195

102-
const mainJsCPath = path.join(mainDir, 'main-c.jsc')
96+
// 可执行文件
97+
let execPath = path.join(
98+
appOutDir,
99+
context.packager.platform.name === 'mac' ? 'MacOS' : '',
100+
context.packager.appInfo.productFilename
101+
)
102+
if (context.packager.platform.name === 'windows') {
103+
execPath = `${execPath}.exe`
104+
}
103105

104-
// 往main.js添加preload.js
105-
const preloadJsPath = path.join(__dirname, 'preload.js').replace(/\\/g, '/')
106-
let code = await fs.promises.readFile(mainJsPath, 'utf-8')
107-
code = `const { encryptorConfig: __encryptorConfig, runRenderer: __runRenderer } = require('${preloadJsPath}');${code}`
108-
await fs.promises.writeFile(mainJsPath, code, 'utf-8')
106+
const mainJsCPath = path.join(mainDir, 'main-c.jsc')
109107

110-
const cwd = process.cwd()
111-
const shuldCleanFiles = new Set<string>()
108+
// 往main.js添加preload.js
109+
const preloadJsPath = path.join(__dirname, 'preload.js').replace(/\\/g, '/')
110+
let code = await fs.promises.readFile(mainJsPath, 'utf-8')
111+
code = `const { encryptorConfig: __encryptorConfig, runRenderer: __runRenderer } = require('${preloadJsPath}');${code}`
112+
await fs.promises.writeFile(mainJsPath, code, 'utf-8')
112113

113-
const mainBundlePath = await buildBundle(
114-
path.relative(cwd, mainJsPath),
115-
shuldCleanFiles,
116-
outConfigPath
117-
)
114+
const cwd = process.cwd()
115+
const shuldCleanFiles = new Set<string>()
118116

119-
// 将main.js加密
120-
await compileToBytenode(path.join(cwd, mainBundlePath), mainJsCPath, execPath)
117+
const mainBundlePath = await buildBundle(
118+
path.relative(cwd, mainJsPath),
119+
shuldCleanFiles,
120+
outConfigPath
121+
)
121122

122-
// 修改入口文件
123-
await fs.promises.writeFile(
124-
mainJsPath,
125-
`"use strict";require('bytenode');require('v8').setFlagsFromString('--no-lazy');require('./main-c.jsc');`,
126-
'utf-8'
127-
)
123+
// 将main.js加密
124+
await compileToBytenode(
125+
path.join(cwd, mainBundlePath),
126+
mainJsCPath,
127+
execPath
128+
)
128129

129-
// 将renderer preload.js加密
130-
const preloadJsPaths =
131-
typeof encryptorConfig.preload === 'string'
132-
? [encryptorConfig.preload]
133-
: encryptorConfig.preload
134-
135-
for (const _preloadJsPath of preloadJsPaths) {
136-
const preloadJsName = path.basename(_preloadJsPath, '.js')
137-
const rendererPreloadJsPath = path.join(mainDir, _preloadJsPath)
138-
const preloadJsDir = path.dirname(rendererPreloadJsPath)
139-
if (fs.existsSync(rendererPreloadJsPath)) {
140-
const rendererPreloadJsCPath = path.join(
141-
preloadJsDir,
142-
`${preloadJsName}-c.jsc`
143-
)
144-
const preloadBundlePath = await buildBundle(
145-
path.relative(cwd, rendererPreloadJsPath),
146-
shuldCleanFiles,
147-
outConfigPath
148-
)
130+
// 修改入口文件
131+
await fs.promises.writeFile(
132+
mainJsPath,
133+
`"use strict";require('bytenode');require('v8').setFlagsFromString('--no-lazy');require('./main-c.jsc');`,
134+
'utf-8'
135+
)
149136

150-
await compileToBytenode(
151-
path.join(cwd, preloadBundlePath),
152-
rendererPreloadJsCPath,
153-
execPath
154-
)
155-
await fs.promises.writeFile(
156-
rendererPreloadJsPath,
157-
`"use strict";require('bytenode');require('v8').setFlagsFromString('--no-lazy');require('./${preloadJsName}-c.jsc');`,
158-
'utf-8'
159-
)
137+
// 将renderer preload.js加密
138+
const preloadJsPaths =
139+
typeof encryptorConfig.preload === 'string'
140+
? [encryptorConfig.preload]
141+
: encryptorConfig.preload
142+
143+
for (const _preloadJsPath of preloadJsPaths) {
144+
const preloadJsName = path.basename(_preloadJsPath, '.js')
145+
const rendererPreloadJsPath = path.join(mainDir, _preloadJsPath)
146+
const preloadJsDir = path.dirname(rendererPreloadJsPath)
147+
if (fs.existsSync(rendererPreloadJsPath)) {
148+
const rendererPreloadJsCPath = path.join(
149+
preloadJsDir,
150+
`${preloadJsName}-c.jsc`
151+
)
152+
const preloadBundlePath = await buildBundle(
153+
path.relative(cwd, rendererPreloadJsPath),
154+
shuldCleanFiles,
155+
outConfigPath
156+
)
157+
158+
await compileToBytenode(
159+
path.join(cwd, preloadBundlePath),
160+
rendererPreloadJsCPath,
161+
execPath
162+
)
163+
await fs.promises.writeFile(
164+
rendererPreloadJsPath,
165+
`"use strict";require('bytenode');require('v8').setFlagsFromString('--no-lazy');require('./${preloadJsName}-c.jsc');`,
166+
'utf-8'
167+
)
168+
}
160169
}
161-
}
162170

163-
// shuldCleanFiles 筛选,仅保留 tempAppDir 下面的文件
164-
Array.from(shuldCleanFiles).forEach(item => {
165-
if (!item.startsWith(tempAppDir)) {
166-
shuldCleanFiles.delete(item)
167-
}
168-
})
171+
// shuldCleanFiles 筛选,仅保留 tempAppDir 下面的文件
172+
Array.from(shuldCleanFiles).forEach(item => {
173+
if (!item.startsWith(tempAppDir)) {
174+
shuldCleanFiles.delete(item)
175+
}
176+
})
169177

170-
// 清理
171-
for (const item of shuldCleanFiles) {
172-
await fs.promises.rm(item, { recursive: true })
173-
}
174-
// 删除空目录
175-
cleanEmptyDir(tempAppDir, [encryptorConfig.renderer.entry, 'node_modules'])
178+
// 清理
179+
for (const item of shuldCleanFiles) {
180+
await fs.promises.rm(item, { recursive: true })
181+
}
182+
// 删除空目录
183+
cleanEmptyDir(tempAppDir, [encryptorConfig.renderer.entry, 'node_modules'])
176184

177-
const rendererDir = path.join(mainDir, encryptorConfig.renderer.entry)
178-
const entryBaseName = path.basename(encryptorConfig.renderer.entry)
179-
const rendererTempPath = path.join(mainDir, `${entryBaseName}.pkg`)
185+
const rendererDir = path.join(mainDir, encryptorConfig.renderer.entry)
186+
const entryBaseName = path.basename(encryptorConfig.renderer.entry)
187+
const rendererTempPath = path.join(mainDir, `${entryBaseName}.pkg`)
180188

181-
// 加密渲染进程
182-
await buidMainApp(rendererDir, rendererTempPath, encryptorConfig.key)
189+
// 加密渲染进程
190+
await buidMainApp(rendererDir, rendererTempPath, encryptorConfig.key)
183191

184-
if (encryptorConfig.renderer.output) {
185-
const rendererOutPath = path.join(
186-
appOutDir,
187-
encryptorConfig.renderer.output
188-
)
189-
const rendererOutDir = path.dirname(rendererOutPath)
190-
if (!fs.existsSync(rendererOutDir)) {
191-
await fs.promises.mkdir(rendererOutDir, { recursive: true })
192-
}
193-
await fs.promises.rename(rendererTempPath, rendererOutPath)
194-
195-
const rendererPackageJsonPath = path.join(rendererDir, 'package.json')
196-
if (fs.existsSync(rendererPackageJsonPath)) {
197-
await writeLicense(
198-
rendererOutPath,
199-
path.resolve(process.cwd(), 'package.json'),
200-
path.join(rendererOutDir, `${entryBaseName}.yml`),
201-
encryptorConfig.key
192+
if (encryptorConfig.renderer.output) {
193+
const rendererOutPath = path.join(
194+
appOutDir,
195+
encryptorConfig.renderer.output
202196
)
197+
const rendererOutDir = path.dirname(rendererOutPath)
198+
if (!fs.existsSync(rendererOutDir)) {
199+
await fs.promises.mkdir(rendererOutDir, { recursive: true })
200+
}
201+
await fs.promises.rename(rendererTempPath, rendererOutPath)
202+
203+
const rendererPackageJsonPath = path.join(rendererDir, 'package.json')
204+
if (fs.existsSync(rendererPackageJsonPath)) {
205+
await writeLicense(
206+
rendererOutPath,
207+
path.resolve(process.cwd(), 'package.json'),
208+
path.join(rendererOutDir, `${entryBaseName}.yml`),
209+
encryptorConfig.key
210+
)
211+
}
203212
}
204-
}
205213

206-
await fs.promises.rm(rendererDir, { recursive: true })
214+
await fs.promises.rm(rendererDir, { recursive: true })
207215

208-
if (options.beforeRePackAsar) {
209-
await options.beforeRePackAsar({ tempAppDir })
210-
}
211-
212-
// 搞回去
213-
await asar.createPackage(tempAppDir, appAsarPath)
216+
if (options.beforeRePackAsar) {
217+
await options.beforeRePackAsar({ tempAppDir })
218+
}
214219

215-
await writeLicense(
216-
appAsarPath,
217-
path.resolve(process.cwd(), 'package.json'),
218-
path.join(resourcesDir, 'app.yml'),
219-
encryptorConfig.key
220-
)
220+
// 搞回去
221+
await asar.createPackage(tempAppDir, appAsarPath)
221222

222-
await fs.promises.rm(tempAppDir, { recursive: true })
223+
await writeLicense(
224+
appAsarPath,
225+
path.resolve(process.cwd(), 'package.json'),
226+
path.join(resourcesDir, 'app.yml'),
227+
encryptorConfig.key
228+
)
223229

224-
if (isPorjectEsm) {
225-
// 恢复package.json
226-
await fs.promises.writeFile('package.json', porjectPackageJsonStr, 'utf8')
230+
await fs.promises.rm(tempAppDir, { recursive: true })
231+
} finally {
232+
if (isPorjectEsm) {
233+
// 恢复package.json
234+
await fs.promises.writeFile('package.json', porjectPackageJsonStr, 'utf8')
235+
}
227236
}
228237

229238
log.info(`encrypt success! takes ${Date.now() - time}ms.`)

0 commit comments

Comments
 (0)