react-native-test-app
Version:
react-native-test-app provides a test app for all supported platforms as a package
191 lines (175 loc) • 5 kB
JavaScript
// @ts-check
import { isMain } from "../helpers.js";
import { main, warn } from "./main.mjs";
const INDENT = " ";
/**
* @param {number} i
* @returns {string}
*/
function num(i) {
const value = i.toString();
return value.includes(".") ? value : "INT64_C(" + value + ")";
}
/**
* @param {unknown} s
* @returns {string}
*/
function str(s, literal = "") {
return typeof s === "string" ? '"' + s + `"${literal}` : "std::nullopt";
}
/**
* @param {unknown[]} items
* @param {number} level
* @returns {string}
*/
function array(items, level) {
if (items.length === 0) {
return "std::vector<std::any>{}";
}
const innerIndent = INDENT.repeat(level + 1);
const lines = [];
for (const value of items) {
switch (typeof value) {
case "boolean":
lines.push(innerIndent + value.toString());
break;
case "number":
lines.push(innerIndent + num(value));
break;
case "string":
lines.push(innerIndent + str(value, "sv"));
break;
case "object":
if (Array.isArray(value)) {
lines.push(innerIndent + array(value, level + 1));
} else if (value) {
lines.push(innerIndent + object(value, level + 1));
} else {
lines.push(innerIndent + "nullptr");
}
break;
default:
warn(`Unexpected JSON type while parsing: ${value}`);
break;
}
}
lines.push(INDENT.repeat(level) + "}");
return "std::vector<std::any>{\n" + lines.join(",\n");
}
/**
* @param {unknown} props
* @param {number} level
* @returns {string}
*/
function object(props, level) {
if (typeof props !== "object" || !props) {
return "std::nullopt";
}
const entries = Object.entries(props);
if (entries.length === 0) {
return "JSONObject{}";
}
const innerIndent = INDENT.repeat(level + 1);
const lines = ["JSONObject{"];
for (const [key, value] of entries) {
switch (typeof value) {
case "boolean":
lines.push(`${innerIndent}{${str(key)}, ${value}},`);
break;
case "number":
lines.push(`${innerIndent}{${str(key)}, ${num(value)}},`);
break;
case "string":
lines.push(`${innerIndent}{${str(key)}, ${str(value, "sv")}},`);
break;
case "object":
if (Array.isArray(value)) {
lines.push(
`${innerIndent}{`,
`${innerIndent}${INDENT}${str(key)},`,
`${innerIndent}${INDENT}${array(value, level + 2)}`,
`${innerIndent}},`
);
} else if (value) {
lines.push(
`${innerIndent}{`,
`${innerIndent}${INDENT}${str(key)},`,
`${innerIndent}${INDENT}${object(value, level + 2)}`,
`${innerIndent}},`
);
} else {
lines.push(`${innerIndent}{${str(key)}, nullptr},`);
}
break;
default:
warn(`Unexpected JSON type while parsing '${key}': ${value}`);
break;
}
}
lines.push(INDENT.repeat(level) + "}");
return lines.join("\n");
}
/**
* @param {unknown} components
* @param {number} level
* @returns {string}
*/
function components(components, level) {
if (!Array.isArray(components) || components.length === 0) {
return "std::make_optional<std::vector<Component>>({})";
}
const outerIndent = INDENT.repeat(level + 1);
const innerIndent = INDENT.repeat(level + 2);
const lines = ["std::make_optional<std::vector<Component>>({"];
for (const c of components) {
lines.push(outerIndent + "Component{");
lines.push(innerIndent + str(c.appKey) + ",");
lines.push(innerIndent + str(c.displayName ?? c.appKey) + ",");
lines.push(innerIndent + object(c.initialProperties, level + 2) + ",");
lines.push(innerIndent + str(c.presentationStyle) + ",");
lines.push(innerIndent + str(c.slug));
lines.push(outerIndent + "},");
}
lines.push(INDENT.repeat(level) + "})");
return lines.join("\n");
}
/**
* @param {Record<string, unknown>} json
* @param {string} checksum
* @returns {string}
*/
export function generate(json, checksum) {
return [
"// clang-format off",
'#include "Manifest.h"',
"",
"#include <cstdint>",
"",
"using ReactApp::Component;",
"using ReactApp::JSONObject;",
"using ReactApp::Manifest;",
"",
"Manifest ReactApp::GetManifest()",
"{",
" using namespace std::literals::string_view_literals;",
"",
" return Manifest{",
" " + str(json.name) + ",",
" " + str(json.displayName ?? json.name) + ",",
" " + str(json.version) + ",",
" " + str(json.bundleRoot) + ",",
" " + str(json.singleApp) + ",",
" " + components(json.components, 2),
" };",
"}",
"",
"std::string_view ReactApp::GetManifestChecksum()",
"{",
` return "${checksum}";`,
"}",
"",
].join("\n");
}
if (isMain(import.meta.url)) {
process.exitCode = main(generate);
}