mirror of
https://github.com/CompeyDev/bun-lune-loader.git
synced 2024-12-12 12:50:39 +00:00
feat: include initial implementation
This commit is contained in:
parent
4d9ebaaa6e
commit
f3d2226910
5 changed files with 165 additions and 0 deletions
6
examples/data.luau
Normal file
6
examples/data.luau
Normal file
|
@ -0,0 +1,6 @@
|
|||
return {
|
||||
SomeData = {
|
||||
"This is string data",
|
||||
69
|
||||
}
|
||||
}
|
3
examples/run.ts
Normal file
3
examples/run.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import { SomeData } from "./data.luau";
|
||||
|
||||
console.log("Received data: ", SomeData)
|
19
src/index.ts
Normal file
19
src/index.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { BunPlugin } from "bun";
|
||||
|
||||
const plugin: BunPlugin = {
|
||||
name: "lune",
|
||||
async setup(build) {
|
||||
const { importPath } = await import("./loader");
|
||||
|
||||
build.onLoad({ filter: /\.(luau|lua)$/ }, (args) => {
|
||||
const mod = importPath(args.path);
|
||||
|
||||
return {
|
||||
contents: mod,
|
||||
loader: "json",
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
41
src/loader.luau
Normal file
41
src/loader.luau
Normal file
|
@ -0,0 +1,41 @@
|
|||
local process = require("@lune/process")
|
||||
local jsonEncode = require("@lune/net").jsonEncode
|
||||
|
||||
local possibleErrors = {
|
||||
FILE_NOT_FOUND = "No file exist at the path",
|
||||
NOT_A_MODULE = "Module must return at least one value"
|
||||
}
|
||||
|
||||
local _, resolvedMod = xpcall(function()
|
||||
-- [1] - Path to import
|
||||
-- [2] - Whether module import or not
|
||||
|
||||
local mod = require(process.args[1])
|
||||
|
||||
if process.args[2] == "MODULE" and mod == nil then
|
||||
error(possibleErrors.NOT_A_MODULE)
|
||||
end
|
||||
|
||||
return mod
|
||||
end, function(err)
|
||||
-- We only need the msg, not trace
|
||||
local errMsg = tostring(err):split("stack traceback:")[1]
|
||||
|
||||
for id, msg in possibleErrors do
|
||||
if errMsg:match(msg) then
|
||||
print(`[bun-loader-lune::ImportError::{id}] ` .. errMsg)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
print("-- [ImportError] --")
|
||||
print(tostring(err))
|
||||
end)
|
||||
|
||||
if process.args[2] == "MODULE" and typeof(resolvedMod) == "table" then
|
||||
local modReprJson = jsonEncode(resolvedMod)
|
||||
|
||||
print("--start @generated JS compatible object--")
|
||||
print(modReprJson)
|
||||
print("--end @generated JS compatible object--")
|
||||
end
|
96
src/loader.ts
Normal file
96
src/loader.ts
Normal file
|
@ -0,0 +1,96 @@
|
|||
// We need to grab x.luau, then pass the return values of that to another
|
||||
// function in the luau side. This function parses the table and converts
|
||||
// it to a JSON object that we can then parse and serve back to the user.
|
||||
|
||||
import { spawnSync, which } from "bun";
|
||||
import { exit } from "process";
|
||||
|
||||
// - Execute lune and run loader script with args for source code
|
||||
// - return JSON
|
||||
|
||||
export function importPath(path: PathLike): string {
|
||||
const lunePath = which("lune");
|
||||
|
||||
if (!lunePath) {
|
||||
throw new Error(
|
||||
"[bun-plugin-lune::loader] Cannot find `lune` executable in path",
|
||||
);
|
||||
}
|
||||
|
||||
// Path to luau loader probs shouldnt be hardcoded
|
||||
const luneChild = spawnSync({
|
||||
cmd: [lunePath, "./loader.luau", path.toString(), "MODULE"],
|
||||
cwd: import.meta.dir,
|
||||
onExit(_proc, exitCode, _sigCode, err) {
|
||||
if (exitCode != 0 && exitCode != null) {
|
||||
console.warn(
|
||||
`[bun-plugin-lune::loader] \`lune\` process exited with code ${exitCode}`,
|
||||
);
|
||||
|
||||
err
|
||||
? () => {
|
||||
console.warn(
|
||||
"[bun-plugin-lune::loader] Internal error: ",
|
||||
err.message,
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
: {};
|
||||
}
|
||||
},
|
||||
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const luneStderr = luneChild.stderr.toString();
|
||||
|
||||
if (luneStderr != "") {
|
||||
const fmtTrace = luneStderr.split("\n")
|
||||
.map((l) => l = " " + l).join("");
|
||||
|
||||
console.warn("\nTRACE:");
|
||||
console.warn(fmtTrace, "\n");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
let luneStdout = luneChild.stdout.toString().split("\n");
|
||||
let generatedJSONObject: string;
|
||||
|
||||
// luneStdout format:
|
||||
// ...logs n' stuff
|
||||
// --start @generated JS compatible object--
|
||||
// ...object -- Always is in one line
|
||||
// --end @generated JS compatible object--
|
||||
// Additional newline (\n)
|
||||
|
||||
// Remove the last empty padding newline
|
||||
luneStdout = luneStdout.filter((v) => v != "");
|
||||
luneStdout.every((l, n) => {
|
||||
// If the stdout line doesn't start with `--`, that means
|
||||
// it must be a log, and not the generated output
|
||||
if (l.startsWith("--")) {
|
||||
if (
|
||||
l == "--start @generated JS compatible object--" &&
|
||||
luneStdout[n + 2] == "--end @generated JS compatible object--"
|
||||
) {
|
||||
// The third last index is the end of the generated object
|
||||
// The next index is the start of the generated object, after the comment
|
||||
generatedJSONObject = luneStdout.slice(n + 1, n + 2)[0];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
console.warn(
|
||||
"[bun-plugin-lune::loader] invalid JS object returned by internal loader.",
|
||||
);
|
||||
|
||||
exit(1);
|
||||
} else if (process.env.NODE_ENV == "dev") {
|
||||
console.log(l);
|
||||
}
|
||||
});
|
||||
|
||||
return generatedJSONObject!;
|
||||
}
|
Loading…
Reference in a new issue