1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 12:42:30 +04:00
Files
unleashed-firmware/applications/system/js_app/packages/fz-sdk/sdk.js
MX 79caf7bf72 Add js sdk changes
With type declarations and various missing parts added by Willy-JL
2024-11-05 09:49:46 +03:00

183 lines
5.9 KiB
JavaScript

#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { SerialPort } from "serialport";
import prompts from "prompts";
import esbuild from "esbuild";
import json5 from "json5";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const cfwSdkName = "@darkflippers/fz-sdk-ul/";
const ofwSdkName = "@flipperdevices/fz-sdk/";
async function build(config) {
await esbuild.build({
entryPoints: ["./dist/index.js"],
outfile: config.output,
tsconfig: "./tsconfig.json",
format: "cjs",
bundle: true,
minify: config.minify,
external: [
"@darkflippers/fz-sdk-ul/*"
],
supported: {
"array-spread": false,
"arrow": false,
"async-await": false,
"async-generator": false,
"bigint": false,
"class": false,
"const-and-let": true,
"decorators": false,
"default-argument": false,
"destructuring": false,
"dynamic-import": false,
"exponent-operator": false,
"export-star-as": false,
"for-await": false,
"for-of": false,
"function-name-configurable": false,
"function-or-class-property-access": false,
"generator": false,
"hashbang": false,
"import-assertions": false,
"import-meta": false,
"inline-script": false,
"logical-assignment": false,
"nested-rest-binding": false,
"new-target": false,
"node-colon-prefix-import": false,
"node-colon-prefix-require": false,
"nullish-coalescing": false,
"object-accessors": false,
"object-extensions": false,
"object-rest-spread": false,
"optional-catch-binding": false,
"optional-chain": false,
"regexp-dot-all-flag": false,
"regexp-lookbehind-assertions": false,
"regexp-match-indices": false,
"regexp-named-capture-groups": false,
"regexp-set-notation": false,
"regexp-sticky-and-unicode-flags": false,
"regexp-unicode-property-escapes": false,
"rest-argument": false,
"template-literal": false,
"top-level-await": false,
"typeof-exotic-object-is-object": false,
"unicode-escapes": false,
"using": false,
},
});
let outContents = fs.readFileSync(config.output, "utf8");
outContents = "let exports = {};\n" + outContents;
// Transform CFW SDK name to OFW SDK name so all firmwares understand it
outContents = outContents.replaceAll(`require("${cfwSdkName}`, `require("${ofwSdkName}`);
if (config.enforceSdkVersion) {
const version = json5.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8")).version;
let [major, minor, _] = version.split(".");
outContents = `checkSdkCompatibility(${major}, ${minor});\n${outContents}`;
}
fs.writeFileSync(config.output, outContents);
}
async function upload(config) {
const appFile = fs.readFileSync(config.input, "utf8");
const flippers = (await SerialPort.list()).filter(x => x.serialNumber?.startsWith("flip_"));
if (!flippers) {
console.error("No Flippers found");
process.exit(1);
}
let portPath = flippers[0].path;
if (flippers.length > 1) {
port = (await prompts([{
type: "select",
name: "port",
message: "Select Flipper to run the app on",
choices: flippers.map(x => ({ title: x.serialNumber.replace("flip_", ""), value: x.path })),
}])).port;
}
console.log(`Connecting to Flipper at ${portPath}`);
let port = new SerialPort({ path: portPath, baudRate: 230400 });
let received = "";
let lastMatch = 0;
async function waitFor(string, timeoutMs) {
return new Promise((resolve, _reject) => {
let timeout = undefined;
if (timeoutMs) {
timeout = setTimeout(() => {
console.error("Error: timeout");
process.exit(1);
}, timeoutMs);
}
setInterval(() => {
let idx = received.indexOf(string, lastMatch);
if (idx !== -1) {
lastMatch = idx;
if (timeoutMs)
clearTimeout(timeout);
resolve();
}
}, 50);
});
}
port.on("data", (data) => {
received += data.toString();
});
await waitFor(">: ", 1000);
console.log("Uploading application file");
port.write(`storage remove ${config.output}\x0d`);
port.drain();
await waitFor(">: ", 1000);
port.write(`storage write_chunk ${config.output} ${appFile.length}\x0d`);
await waitFor("Ready", 1000);
port.write(appFile);
port.drain();
await waitFor(">: ", 1000);
console.log("Launching application");
port.write(`js ${config.output}\x0d`);
port.drain();
await waitFor("Running", 1000);
process.stdout.write(received.slice(lastMatch));
port.on("data", (data) => {
process.stdout.write(data.toString());
});
process.on("exit", () => {
port.write("\x03");
});
await waitFor("Script done!", 0);
process.exit(0);
}
(async () => {
const commands = {
"build": build,
"upload": upload,
};
const config = json5.parse(fs.readFileSync("./fz-sdk.config.json5", "utf8"));
const command = process.argv[2];
if (!Object.keys(commands).includes(command)) {
console.error(`Unknown command ${command}. Supported: ${Object.keys(commands).join(", ")}`);
process.exit(1);
}
await commands[command](config[command]);
})();