Skip to content

Commit

Permalink
feat: Enable ESM support for hooks by using dynamic import() when `…
Browse files Browse the repository at this point in the history
…package.json` is set to type `module` (#7936)
  • Loading branch information
lutzroeder committed Dec 13, 2023
1 parent 6c4d17c commit 664a09c
Show file tree
Hide file tree
Showing 8 changed files with 31 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/quick-rocks-cover.md
@@ -0,0 +1,5 @@
---
"app-builder-lib": minor
---

feat: Enable ESM support for hooks by using dynamic `import()` when `package.json` is set to type `module`.
2 changes: 2 additions & 0 deletions packages/app-builder-lib/src/appInfo.ts
Expand Up @@ -22,6 +22,7 @@ export function smarten(s: string): string {
export class AppInfo {
readonly description = smarten(this.info.metadata.description || "")
readonly version: string
readonly type: string | undefined
readonly shortVersion: string | undefined
readonly shortVersionWindows: string | undefined

Expand All @@ -39,6 +40,7 @@ export class AppInfo {
normalizeNfd = false
) {
this.version = info.metadata.version!
this.type = info.metadata.type

if (buildVersion == null) {
buildVersion = info.config.buildVersion
Expand Down
2 changes: 1 addition & 1 deletion packages/app-builder-lib/src/codeSign/windowsCodeSign.ts
Expand Up @@ -52,7 +52,7 @@ export async function sign(options: WindowsSignOptions, packager: WinPackager):
hashes = Array.isArray(hashes) ? hashes : [hashes]
}

const executor = resolveFunction(options.options.sign, "sign") || doSign
const executor = (await resolveFunction(packager.appInfo.type, options.options.sign, "sign")) || doSign
let isNest = false
for (const hash of hashes) {
const taskConfiguration: WindowsSignTaskConfiguration = { ...options, hash, isNest }
Expand Down
2 changes: 1 addition & 1 deletion packages/app-builder-lib/src/index.ts
Expand Up @@ -76,7 +76,7 @@ export function build(options: PackagerOptions & PublishOptions, packager: Packa
process.once("SIGINT", sigIntHandler)

const promise = packager.build().then(async buildResult => {
const afterAllArtifactBuild = resolveFunction(buildResult.configuration.afterAllArtifactBuild, "afterAllArtifactBuild")
const afterAllArtifactBuild = await resolveFunction(packager.appInfo.type, buildResult.configuration.afterAllArtifactBuild, "afterAllArtifactBuild")
if (afterAllArtifactBuild != null) {
const newArtifacts = asArray(await Promise.resolve(afterAllArtifactBuild(buildResult)))
if (newArtifacts.length === 0 || !publishManager.isPublish) {
Expand Down
2 changes: 2 additions & 0 deletions packages/app-builder-lib/src/options/metadata.ts
Expand Up @@ -41,6 +41,8 @@ export interface Metadata {
/** @private */
readonly version?: string
/** @private */
readonly type?: string
/** @private */
readonly shortVersion?: string | null
/** @private */
readonly shortVersionWindows?: string | null
Expand Down
12 changes: 6 additions & 6 deletions packages/app-builder-lib/src/packager.ts
Expand Up @@ -257,7 +257,7 @@ export class Packager {
},
"building"
)
const handler = resolveFunction(this.config.artifactBuildStarted, "artifactBuildStarted")
const handler = await resolveFunction(this.appInfo.type, this.config.artifactBuildStarted, "artifactBuildStarted")
if (handler != null) {
await Promise.resolve(handler(event))
}
Expand All @@ -271,7 +271,7 @@ export class Packager {
}

async callArtifactBuildCompleted(event: ArtifactCreated): Promise<void> {
const handler = resolveFunction(this.config.artifactBuildCompleted, "artifactBuildCompleted")
const handler = await resolveFunction(this.appInfo.type, this.config.artifactBuildCompleted, "artifactBuildCompleted")
if (handler != null) {
await Promise.resolve(handler(event))
}
Expand All @@ -280,14 +280,14 @@ export class Packager {
}

async callAppxManifestCreated(path: string): Promise<void> {
const handler = resolveFunction(this.config.appxManifestCreated, "appxManifestCreated")
const handler = await resolveFunction(this.appInfo.type, this.config.appxManifestCreated, "appxManifestCreated")
if (handler != null) {
await Promise.resolve(handler(path))
}
}

async callMsiProjectCreated(path: string): Promise<void> {
const handler = resolveFunction(this.config.msiProjectCreated, "msiProjectCreated")
const handler = await resolveFunction(this.appInfo.type, this.config.msiProjectCreated, "msiProjectCreated")
if (handler != null) {
await Promise.resolve(handler(path))
}
Expand Down Expand Up @@ -503,7 +503,7 @@ export class Packager {
return
}

const beforeBuild = resolveFunction(config.beforeBuild, "beforeBuild")
const beforeBuild = await resolveFunction(this.appInfo.type, config.beforeBuild, "beforeBuild")
if (beforeBuild != null) {
const performDependenciesInstallOrRebuild = await beforeBuild({
appDir: this.appDir,
Expand Down Expand Up @@ -532,7 +532,7 @@ export class Packager {
}

async afterPack(context: AfterPackContext): Promise<any> {
const afterPack = resolveFunction(this.config.afterPack, "afterPack")
const afterPack = await resolveFunction(this.appInfo.type, this.config.afterPack, "afterPack")
const handlers = this.afterPackHandlers.slice()
if (afterPack != null) {
// user handler should be last
Expand Down
18 changes: 13 additions & 5 deletions packages/app-builder-lib/src/platformPackager.ts
Expand Up @@ -204,7 +204,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
// Due to node-gyp rewriting GYP_MSVS_VERSION when reused across the same session, we must reset the env var: https://github.com/electron-userland/electron-builder/issues/7256
delete process.env.GYP_MSVS_VERSION

const beforePack = resolveFunction(this.config.beforePack, "beforePack")
const beforePack = await resolveFunction(this.appInfo.type, this.config.beforePack, "beforePack")
if (beforePack != null) {
await beforePack({
appOutDir,
Expand Down Expand Up @@ -330,7 +330,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
electronPlatformName: platformName,
}
const didSign = await this.signApp(packContext, isAsar)
const afterSign = resolveFunction(this.config.afterSign, "afterSign")
const afterSign = await resolveFunction(this.appInfo.type, this.config.afterSign, "afterSign")
if (afterSign != null) {
if (didSign) {
await Promise.resolve(afterSign(packContext))
Expand Down Expand Up @@ -753,7 +753,16 @@ export function normalizeExt(ext: string) {
return ext.startsWith(".") ? ext.substring(1) : ext
}

export function resolveFunction<T>(executor: T | string, name: string): T {
async function resolveModule<T>(type: string | undefined, name: string): Promise<T> {
const extension = path.extname(name).toLowerCase()
const isModuleType = type === "module"
if (extension === ".mjs" || (extension === ".js" && isModuleType)) {
return await eval("import('" + name + "')")
}
return require(name)
}

export async function resolveFunction<T>(type: string | undefined, executor: T | string, name: string): Promise<T> {
if (executor == null || typeof executor !== "string") {
return executor
}
Expand All @@ -770,8 +779,7 @@ export function resolveFunction<T>(executor: T | string, name: string): T {
p = path.resolve(p)
}

// eslint-disable-next-line @typescript-eslint/no-var-requires
const m = require(p)
const m: any = await resolveModule(type, p)
const namedExport = m[name]
if (namedExport == null) {
return m.default || m
Expand Down
2 changes: 1 addition & 1 deletion packages/app-builder-lib/src/util/NodeModuleCopyHelper.ts
Expand Up @@ -41,7 +41,7 @@ export class NodeModuleCopyHelper extends FileCopyHelper {
const filter = this.filter
const metadata = this.metadata

const onNodeModuleFile = resolveFunction(this.packager.config.onNodeModuleFile, "onNodeModuleFile")
const onNodeModuleFile = await resolveFunction(this.packager.appInfo.type, this.packager.config.onNodeModuleFile, "onNodeModuleFile")

const result: Array<string> = []
const queue: Array<string> = []
Expand Down

0 comments on commit 664a09c

Please sign in to comment.