add build.ts
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,6 +6,7 @@
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
bundles/*.bundle.ts
|
||||
bundles/*.bundle.ts.source-meta
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
#!/usr/bin/env runts -- --allow-import
|
||||
#!/usr/bin/env runts -- --allow-all
|
||||
|
||||
import {log} from "../libraries/deno-commons-mod.ts";
|
||||
import {log, term} from "../libraries/deno-commons-mod.ts";
|
||||
|
||||
// deno bundle --allow-import hello_world.ts -o helloworld-bundle-2.bundle.ts
|
||||
async function main() {
|
||||
log.info("Hello World!");
|
||||
log.success("Hello World!");
|
||||
console.log(term.auto("\n[bg_white][black]Message:\n"));
|
||||
console.log(
|
||||
term.auto(
|
||||
"[[[[bg_green][bold][red] MESSAGE [///] [green][bold]Hello[//] [red]world[/]. [under] under [/] [bold]BOLD[/]]]]",
|
||||
),
|
||||
);
|
||||
console.log(term.auto("\n[bg_white][black]Prints as:\n"));
|
||||
console.log(
|
||||
term.auto(
|
||||
"[bg_green][bold][red] MESSAGE [///] [green][bold]Hello[//] [red]world[/]. [under] under [/] [bold]BOLD[/]",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
"publish_time": 1758209484774,
|
||||
"update_time": 1758209484774
|
||||
},
|
||||
"build.ts": {
|
||||
"script_name": "build.ts",
|
||||
"script_length": 4555,
|
||||
"script_sha256": "b70337218e8e164ba58c47ede81fdd9015ae81dd7c2658214720cf3e6fd27794",
|
||||
"script_full_url": "https://git.hatter.ink/hatter/ts-scripts/raw/branch/main/single-scripts/build.ts",
|
||||
"single_script_file": true,
|
||||
"publish_time": 1770564482429,
|
||||
"update_time": 1770564482429
|
||||
},
|
||||
"cal-bun.ts": {
|
||||
"script_name": "cal-bun.ts",
|
||||
"script_length": 427,
|
||||
|
||||
147
single-scripts/build.ts
Executable file
147
single-scripts/build.ts
Executable file
@@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env runts -- --allow-all
|
||||
|
||||
import {execCommandShell, log, term, uint8ArrayToHexString,} from "https://script.hatter.ink/@35/deno-commons-mod.ts";
|
||||
import {parseArgs} from "jsr:@std/cli/parse-args";
|
||||
import {existsPath, stringifyPretty, writeStringToFile,} from "../libraries/deno-commons-mod.ts";
|
||||
import {readFileToString} from "https://global.hatter.ink/script/get/@1/deno-commons-1.6.0-mod.ts";
|
||||
|
||||
async function main() {
|
||||
const flags = parseArgs(Deno.args, {
|
||||
boolean: [
|
||||
"help",
|
||||
"no-min",
|
||||
"skip-sign",
|
||||
"force",
|
||||
],
|
||||
alias: {
|
||||
S: "skip-sign",
|
||||
M: "no-min",
|
||||
F: "force",
|
||||
},
|
||||
});
|
||||
|
||||
if (flags.help) {
|
||||
console.log(term.auto(`Usage:
|
||||
[blue][bold]build.ts[//] --help
|
||||
[blue][bold]build.ts[//] [--no-min] FILES`));
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags._.length === 0) {
|
||||
log.error(`No files specified`);
|
||||
return;
|
||||
}
|
||||
flags.min = !flags["no-min"];
|
||||
|
||||
const filesCount = flags._.length;
|
||||
log.info(`Total ${filesCount} file(s)`);
|
||||
for (let i = 0; i < filesCount; i++) {
|
||||
const file = flags._[i];
|
||||
if (file.includes(".bundle.")) {
|
||||
log.warn(`Skip bundle file: ${file} #${i + 1} of ${filesCount}`);
|
||||
continue;
|
||||
}
|
||||
log.info(`Building file: ${file} #${i + 1} of ${filesCount}`);
|
||||
await buildFile(file, flags);
|
||||
}
|
||||
}
|
||||
|
||||
function getBundleFilename(file: string): string {
|
||||
const lastIndexOfDot = file.lastIndexOf(".");
|
||||
if (lastIndexOfDot === -1) {
|
||||
return `${file}.bundle.ts`;
|
||||
}
|
||||
return `${file.substring(0, lastIndexOfDot)}.bundle.${
|
||||
file.substring(lastIndexOfDot + 1)
|
||||
}`;
|
||||
}
|
||||
|
||||
async function sha256OfString(input: string): Promise<string> {
|
||||
const data = new TextEncoder().encode(input);
|
||||
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
||||
return uint8ArrayToHexString(new Uint8Array(hashBuffer));
|
||||
}
|
||||
|
||||
interface SourceFileMeta {
|
||||
sha256: string;
|
||||
builtTime: number;
|
||||
min: boolean;
|
||||
}
|
||||
|
||||
async function writeBundleSourceSha256(
|
||||
sourceFile: string,
|
||||
bundleFile: string,
|
||||
flags: any,
|
||||
) {
|
||||
const sourceFileSha256 = `${bundleFile}.source-meta`;
|
||||
const sourceFileContent = await readFileToString(sourceFile);
|
||||
const sourceFileContentSha256 = await sha256OfString(sourceFileContent);
|
||||
await writeStringToFile(
|
||||
sourceFileSha256,
|
||||
stringifyPretty({
|
||||
sha256: sourceFileContentSha256,
|
||||
builtTime: Date.now(),
|
||||
min: flags.min,
|
||||
} as SourceFileMeta),
|
||||
);
|
||||
}
|
||||
|
||||
async function checkBundleSourceSha256(
|
||||
sourceFile: string,
|
||||
bundleFile: string,
|
||||
flags: any,
|
||||
) {
|
||||
const sourceFileSha256 = `${bundleFile}.source-meta`;
|
||||
if (!await existsPath(sourceFileSha256)) {
|
||||
return false;
|
||||
}
|
||||
const sourceFileSha256Content = await readFileToString(sourceFileSha256);
|
||||
const sourceFileSha256Meta = JSON.parse(
|
||||
sourceFileSha256Content,
|
||||
) as SourceFileMeta;
|
||||
if (sourceFileSha256Meta.min !== flags.min) {
|
||||
return false;
|
||||
}
|
||||
const sourceFileContent = await readFileToString(sourceFile);
|
||||
const sourceFileContentSha256 = await sha256OfString(sourceFileContent);
|
||||
return sourceFileContentSha256 === sourceFileSha256Meta.sha256;
|
||||
}
|
||||
|
||||
async function buildFile(file: string, flags: any) {
|
||||
const denoCmd = "deno";
|
||||
const bundleFile = getBundleFilename(file);
|
||||
const denoBundleArgs = ["bundle"];
|
||||
if (flags.min) {
|
||||
denoBundleArgs.push("--minify");
|
||||
}
|
||||
denoBundleArgs.push(file);
|
||||
denoBundleArgs.push("-o");
|
||||
denoBundleArgs.push(bundleFile);
|
||||
|
||||
const isSourceFileMatches = await checkBundleSourceSha256(
|
||||
file,
|
||||
bundleFile,
|
||||
flags,
|
||||
);
|
||||
if (isSourceFileMatches && !flags.force) {
|
||||
log.info(`Check file ${file} sha256 matches, skip build`);
|
||||
return;
|
||||
}
|
||||
if (isSourceFileMatches) {
|
||||
log.info(`Force build file is on`);
|
||||
}
|
||||
log.debug("Run deno build: ", denoCmd, denoBundleArgs);
|
||||
await execCommandShell(denoCmd, denoBundleArgs);
|
||||
if (flags["skip-sign"]) {
|
||||
log.warn(`Skip signature for file: ${bundleFile}`);
|
||||
} else {
|
||||
await execCommandShell("script-sign.rs", [bundleFile]);
|
||||
}
|
||||
await execCommandShell("chmod", ["+x", bundleFile]);
|
||||
await writeBundleSourceSha256(file, bundleFile, flags);
|
||||
}
|
||||
|
||||
await main();
|
||||
|
||||
// @SCRIPT-SIGNATURE-V1: yk-r1.ES256.20260208T232753+08:00.MEQCIDKxUBkD92GrszyWM6gC
|
||||
// jCNOVqcEMUdDKgs6TJlFhRbXAiBzlvmlHCXGFZBCcjjKBjmXDYqdbnfTp6D1wlSFyhK/sA==
|
||||
Reference in New Issue
Block a user