From 24392d9ac1419f4c7204e0c7a889306a3d6ffd4f Mon Sep 17 00:00:00 2001 From: Revenity Date: Sun, 15 Oct 2023 09:25:39 +0700 Subject: [PATCH 1/4] Update loader.ts --- src/loader.ts | 54 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/src/loader.ts b/src/loader.ts index e59ef3f..24e6422 100644 --- a/src/loader.ts +++ b/src/loader.ts @@ -31,9 +31,16 @@ export default class { * By default asks for the build command and output directory from the user on importing the source file for the first time. */ async initConfigPre() { - console.log(`\x1b[33m[HYPERIMPORT]\x1b[39m: ${this.name}\nNo configuration was found for "${this.config.importPath}"\nEnter the build command and output directory to configure it.\nPress enter to use the default values.\n`); + console.log( + `\x1b[33m[HYPERIMPORT]\x1b[39m: ${this.name}\n` + + `No configuration was found for "${this.config.importPath}"\n` + + `Enter the build command and output directory to configure it.\n` + + `Press enter to use the default values.\n` + ); + this.config.buildCommand = prompt("build command: (default)")?.split(" ") ?? this.config.buildCommand; this.config.outDir = prompt(`output directory: (${this.config.outDir})`) ?? this.config.outDir; + mkdirSync(this.config.outDir, { recursive: true }); } @@ -42,20 +49,32 @@ export default class { */ async initConfigTypes() { const filename = basename(this.config.importPath); + mkdirSync(`${this.cwd}/@types/${filename}`, { recursive: true }); Bun.write(`${this.cwd}/@types/${filename}/lastModified`, lastModified(this.config.importPath)); + const configWriter = Bun.file(`${this.cwd}/@types/${filename}/config.ts`).writer(); - configWriter.write(`import { LoaderConfig, T } from "hyperimport";\nexport default {\n\tbuildCommand: ${JSON.stringify(this.config.buildCommand)},\n\toutDir: "${this.config.outDir}",\n\tsymbols: {`); - for (const symbol of nm(this.config.libPath)) { + + configWriter.write( + `import { LoaderConfig, T } from "hyperimport";\n` + + `export default {\n\tbuildCommand: ${JSON.stringify(this.config.buildCommand)},\n\toutDir: "${this.config.outDir}",\n\tsymbols: {` + ); + + for (const symbol of nm(this.config.libPath)) configWriter.write(`\n\t\t${symbol}: {\n\t\t\targs: [],\n\t\t\treturns: T.void\n\t\t},`); - } + configWriter.write(`\n\t}\n} satisfies LoaderConfig.Main;`); configWriter.end(); + Bun.write( `${this.cwd}/@types/${filename}/types.d.ts`, `declare module "*/${filename}" {\n\tconst symbols: import("bun:ffi").ConvertFns;\n\texport = symbols;\n}` ); - console.log(`\n\x1b[32mConfig file has been generated at "${this.cwd}/@types/${filename}/config.ts"\x1b[39m\nEdit the config.ts and set the argument and return types, then rerun the script.`); + + console.log( + `\n\x1b[32mConfig file has been generated at "${this.cwd}/@types/${filename}/config.ts"\x1b[39m\n` + + `Edit the config.ts and set the argument and return types, then rerun the script.` + ); } /** @@ -63,8 +82,10 @@ export default class { */ async initConfig() { await this.initConfigPre(); + console.log("\nBuilding the source file..."); await this.build(); + console.log("The source file has been built."); await this.initConfigTypes(); } @@ -73,8 +94,9 @@ export default class { * Checks if the source file was modified, if it is, then `build()` is executed to rebuild the changed source file. */ async ifSourceModify() { - const lm = lastModified(this.config.importPath); - const lmfile = `${this.cwd}/@types/${basename(this.config.importPath)}/lastModified`; + const lm = lastModified(this.config.importPath), + lmfile = `${this.cwd}/@types/${basename(this.config.importPath)}/lastModified`; + if (lm !== await Bun.file(lmfile).text()) { await this.build(); Bun.write(lmfile, lm); @@ -110,20 +132,20 @@ export default class { * @returns A `BunPlugin` instance. */ async toPlugin(): Promise { - const parentThis = this; return { - name: parentThis.name, - setup(build) { - build.onLoad({ filter: new RegExp(`\.(${parentThis._config.extension})$`) }, async args => { - parentThis.config.importPath = args.path; - await parentThis.preload(); + name: this.name, + // Arrow function does not have a scope so it can access parent this + setup: build => { + build.onLoad({ filter: new RegExp(`\.(${this._config.extension})$`) }, async args => { + this.config.importPath = args.path; + await this.preload(); + return { - exports: dlopen(parentThis.config.libPath, await parentThis.getSymbols()).symbols, + exports: dlopen(this.config.libPath, await this.getSymbols()).symbols, loader: "object" }; }); } }; } - -} \ No newline at end of file +} From cb39a72eacc666bc82dbffced78ee8dd50c1f135 Mon Sep 17 00:00:00 2001 From: Revenity Date: Sun, 15 Oct 2023 09:27:50 +0700 Subject: [PATCH 2/4] Update preload.ts --- preload.ts | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/preload.ts b/preload.ts index e0d9a9a..41c7651 100644 --- a/preload.ts +++ b/preload.ts @@ -1,23 +1,30 @@ import { HyperImportConfig } from "./src/types"; import { debugLog } from "./src/utils"; -const cwd = process.cwd(); -const config: HyperImportConfig = (await import(`${cwd}/bunfig.toml`)).default.hyperimport; +const cwd = process.cwd(), + config: HyperImportConfig = (await import(`${cwd}/bunfig.toml`)).default.hyperimport; debugLog(config.debug, 3, "registering loaders..."); -for (const loader of config.loaders ?? []) { - await import(`./src/loaders/${loader}.ts`).then(async l => { - const plugin = await new l.default(cwd).toPlugin(); +for (const loader of config.loaders ?? []) + try { + const l = await import(`./src/loaders/${loader}.ts`), + plugin = await new l.default(cwd).toPlugin(); + Bun.plugin(plugin); debugLog(config.debug, 2, plugin.name, "has been registered."); - }).catch(() => debugLog(config.debug, 1, "loader not found:", loader)); -} + } catch (e) { + debugLog(config.debug, 1, "loader not found:", loader); + } -for (const loader of config.custom ?? []) { - await import(`${cwd}/${loader}`).then(async l => { - const plugin = await new l.default(cwd).toPlugin(); + +for (const loader of config.custom ?? []) + try { + const l = await import(`${cwd}/${loader}`), + plugin = await new l.default(cwd).toPlugin(); + Bun.plugin(plugin); debugLog(config.debug, 2, "[CUSTOM]", plugin.name, "has been registered."); - }).catch(() => debugLog(config.debug, 1, "[CUSTOM] loader not found:", loader)); -} \ No newline at end of file + } catch (e) { + debugLog(config.debug, 1, "[CUSTOM] loader not found:", loader); + } From 50c90ffefead3a735946e5acf9b41921c4af26d2 Mon Sep 17 00:00:00 2001 From: Revenity Date: Sun, 15 Oct 2023 15:57:43 +0700 Subject: [PATCH 3/4] Update preload.ts --- preload.ts | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/preload.ts b/preload.ts index 41c7651..5b4279d 100644 --- a/preload.ts +++ b/preload.ts @@ -1,30 +1,34 @@ import { HyperImportConfig } from "./src/types"; import { debugLog } from "./src/utils"; -const cwd = process.cwd(), - config: HyperImportConfig = (await import(`${cwd}/bunfig.toml`)).default.hyperimport; +const cwd = process.cwd(); +const config: HyperImportConfig = (await import(`${cwd}/bunfig.toml`)).default.hyperimport; debugLog(config.debug, 3, "registering loaders..."); -for (const loader of config.loaders ?? []) - try { - const l = await import(`./src/loaders/${loader}.ts`), - plugin = await new l.default(cwd).toPlugin(); +/** + * Register a plugin + * @param loader + * @param path A path to register + * @param custom Whether it is a custom plugin + */ +async function register(loader, path: string, custom: boolean) { + const isCustom = custom ? "[CUSTOM] " : ""; + try { + const l = await import(path); + const plugin = await new l.default(cwd).toPlugin(); + Bun.plugin(plugin); - debugLog(config.debug, 2, plugin.name, "has been registered."); + debugLog(config.debug, 2, isCustom + plugin.name, "has been registered."); } catch (e) { - debugLog(config.debug, 1, "loader not found:", loader); + debugLog(config.debug, 1, isCustom + "loader not found:", loader); } +// Register default loader +for (const loader of config.loaders ?? []) + register(loader, `./src/loaders/${loader}.ts`, false); +// Register custom loader for (const loader of config.custom ?? []) - try { - const l = await import(`${cwd}/${loader}`), - plugin = await new l.default(cwd).toPlugin(); - - Bun.plugin(plugin); - debugLog(config.debug, 2, "[CUSTOM]", plugin.name, "has been registered."); - } catch (e) { - debugLog(config.debug, 1, "[CUSTOM] loader not found:", loader); - } + register(loader, `${cwd}/${loader}`, true); From cd447c48bfbbbbbd054751f805a170584c2e0cfa Mon Sep 17 00:00:00 2001 From: Revenity Date: Sun, 15 Oct 2023 16:09:13 +0700 Subject: [PATCH 4/4] Update loader.ts --- src/loader.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/loader.ts b/src/loader.ts index 24e6422..37cb448 100644 --- a/src/loader.ts +++ b/src/loader.ts @@ -49,11 +49,13 @@ export default class { */ async initConfigTypes() { const filename = basename(this.config.importPath); + const targetFile = `${this.cwd}/@types/${filename}`; + const configFile = `${targetFile}/config.ts`; - mkdirSync(`${this.cwd}/@types/${filename}`, { recursive: true }); - Bun.write(`${this.cwd}/@types/${filename}/lastModified`, lastModified(this.config.importPath)); + mkdirSync(targetFile, { recursive: true }); + Bun.write(`${targetFile}/lastModified`, lastModified(this.config.importPath)); - const configWriter = Bun.file(`${this.cwd}/@types/${filename}/config.ts`).writer(); + const configWriter = Bun.file(configFile).writer(); configWriter.write( `import { LoaderConfig, T } from "hyperimport";\n` @@ -67,12 +69,11 @@ export default class { configWriter.end(); Bun.write( - `${this.cwd}/@types/${filename}/types.d.ts`, + `${targetFile}/types.d.ts`, `declare module "*/${filename}" {\n\tconst symbols: import("bun:ffi").ConvertFns;\n\texport = symbols;\n}` ); - console.log( - `\n\x1b[32mConfig file has been generated at "${this.cwd}/@types/${filename}/config.ts"\x1b[39m\n` + `\n\x1b[32mConfig file has been generated at "${configFile}"\x1b[39m\n` + `Edit the config.ts and set the argument and return types, then rerun the script.` ); } @@ -94,8 +95,8 @@ export default class { * Checks if the source file was modified, if it is, then `build()` is executed to rebuild the changed source file. */ async ifSourceModify() { - const lm = lastModified(this.config.importPath), - lmfile = `${this.cwd}/@types/${basename(this.config.importPath)}/lastModified`; + const lm = lastModified(this.config.importPath); + const lmfile = `${this.cwd}/@types/${basename(this.config.importPath)}/lastModified`; if (lm !== await Bun.file(lmfile).text()) { await this.build(); @@ -134,7 +135,6 @@ export default class { async toPlugin(): Promise { return { name: this.name, - // Arrow function does not have a scope so it can access parent this setup: build => { build.onLoad({ filter: new RegExp(`\.(${this._config.extension})$`) }, async args => { this.config.importPath = args.path;