///|
/// Return user-provided Node.js command-line arguments.
extern "js" fn cli_arguments() -> Array[String] =
#| function() {
#| return typeof process === "undefined" ? [] : process.argv.slice(2);
#| }
///|
/// Stop the Node.js CLI with a failure status.
extern "js" fn exit_failure(code : Int) -> Unit =
#| function(code) {
#| if (typeof process !== "undefined") {
#| process.exit(code);
#| }
#| }
///|
/// Return true when a path exists.
extern "js" fn path_exists(path : String) -> Bool =
#| function(path) {
#| const fs = require("node:fs");
#| return fs.existsSync(path);
#| }
///|
/// Return true when a path exists and is a directory.
extern "js" fn is_directory(path : String) -> Bool =
#| function(path) {
#| const fs = require("node:fs");
#| try {
#| return fs.statSync(path).isDirectory();
#| } catch (_) {
#| return false;
#| }
#| }
///|
/// Return true when a path exists and is a file.
extern "js" fn is_file(path : String) -> Bool =
#| function(path) {
#| const fs = require("node:fs");
#| try {
#| return fs.statSync(path).isFile();
#| } catch (_) {
#| return false;
#| }
#| }
///|
/// Read a string-like field from a JSON configuration file.
extern "js" fn read_config_value(path : String, key : String) -> String =
#| function(path, key) {
#| if (!path) {
#| return "";
#| }
#| const fs = require("node:fs");
#| try {
#| const config = JSON.parse(fs.readFileSync(path, "utf8"));
#| const value = config[key];
#| if (value === undefined || value === null) {
#| return "";
#| }
#| if (typeof value === "string") {
#| return value;
#| }
#| if (typeof value === "number" || typeof value === "boolean") {
#| return String(value);
#| }
#| return "";
#| } catch (error) {
#| return "__MOONDOC_CONFIG_ERROR__" + error.message;
#| }
#| }
///|
/// Read sorted Markdown files as alternating name/content values.
extern "js" fn read_markdown_directory(path : String) -> Array[String] =
#| function(path) {
#| const fs = require("node:fs");
#| const nodePath = require("node:path");
#| const names = fs.readdirSync(path, { withFileTypes: true })
#| .filter((entry) => entry.isFile() && entry.name.toLowerCase().endsWith(".md"))
#| .map((entry) => entry.name)
#| .sort();
#| const result = [];
#| for (const name of names) {
#| result.push(name);
#| result.push(fs.readFileSync(nodePath.join(path, name), "utf8"));
#| }
#| return result;
#| }
///|
/// Read one UTF-8 text file.
extern "js" fn read_text_file(path : String) -> String =
#| function(path) {
#| const fs = require("node:fs");
#| return fs.readFileSync(path, "utf8");
#| }
///|
/// Write a generated output manifest to a directory.
extern "js" fn write_output_directory(
directory : String,
paths : Array[String],
contents : Array[String],
) -> Int =
#| function(directory, paths, contents) {
#| const fs = require("node:fs");
#| const nodePath = require("node:path");
#| fs.mkdirSync(directory, { recursive: true });
#| for (let i = 0; i < paths.length; i++) {
#| const target = nodePath.join(directory, paths[i]);
#| fs.mkdirSync(nodePath.dirname(target), { recursive: true });
#| fs.writeFileSync(target, contents[i], "utf8");
#| }
#| return paths.length;
#| }