react-native-test-app
Version:
react-native-test-app provides a test app for all supported platforms as a package
180 lines (165 loc) • 4.78 kB
JavaScript
// @ts-check
import { isMain } from "../helpers.js";
import { main, warn } from "./main.mjs";
const INDENT = " ";
/**
* @param {unknown} s
* @returns {string}
*/
function str(s) {
return typeof s === "string" ? '"' + s + '"' : "null";
}
/**
* @param {unknown[]} items
* @param {number} level
* @returns {string}
*/
function array(items, level) {
if (items.length === 0) {
return "arrayListOf<Any>()";
}
const innerIndent = INDENT.repeat(level + 1);
const lines = [];
for (const value of items) {
switch (typeof value) {
case "boolean":
case "number":
lines.push(innerIndent + value.toString());
break;
case "string":
lines.push(innerIndent + str(value));
break;
case "object":
if (Array.isArray(value)) {
lines.push(innerIndent + array(value, level + 1));
} else if (value) {
lines.push(innerIndent + bundle(value, level + 1));
} else {
lines.push(innerIndent + "null");
}
break;
default:
warn(`Unexpected JSON type while parsing: ${value}`);
break;
}
}
return (
"arrayListOf(\n" + lines.join(",\n") + "\n" + INDENT.repeat(level) + ")"
);
}
/**
* @param {unknown} props
* @param {number} level
* @returns {string}
*/
function bundle(props, level) {
if (typeof props !== "object" || !props) {
return "null";
}
const entries = Object.entries(props);
if (entries.length === 0) {
return "Bundle()";
}
const innerIndent = INDENT.repeat(level + 1);
const lines = ["Bundle().apply {"];
for (const [key, value] of entries) {
switch (typeof value) {
case "boolean":
lines.push(`${innerIndent}putBoolean(${str(key)}, ${value})`);
break;
case "number":
lines.push(
value.toString().includes(".")
? `${innerIndent}putDouble(${str(key)}, ${value})`
: `${innerIndent}putInt(${str(key)}, ${value})`
);
break;
case "string":
lines.push(`${innerIndent}putString(${str(key)}, ${str(value)})`);
break;
case "object":
if (Array.isArray(value)) {
lines.push(
`${innerIndent}putSerializable(`,
`${innerIndent}${INDENT}${str(key)},`,
`${innerIndent}${INDENT}${array(value, level + 2)}`,
`${innerIndent})`
);
} else if (value) {
lines.push(
`${innerIndent}putBundle(`,
`${innerIndent}${INDENT}${str(key)},`,
`${innerIndent}${INDENT}${bundle(value, level + 2)}`,
`${innerIndent})`
);
} else {
lines.push(`${innerIndent}putString(${str(key)}, null)`);
}
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 "arrayListOf<Any>()";
}
const outerIndent = INDENT.repeat(level + 1);
const innerIndent = INDENT.repeat(level + 2);
const lines = ["arrayListOf("];
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 + bundle(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 [
"package com.microsoft.reacttestapp.manifest",
"",
"import android.os.Bundle",
"",
"class ManifestProvider {",
" companion object {",
" fun checksum(): String {",
` return "${checksum}"`,
" }",
"",
" fun manifest(): Manifest {",
" return Manifest(",
" " + str(json.name) + ",",
" " + str(json.displayName ?? json.name) + ",",
" " + str(json.version) + ",",
" " + str(json.bundleRoot) + ",",
" " + str(json.singleApp) + ",",
" " + components(json.components, 4),
" )",
" }",
" }",
"}",
"",
].join("\n");
}
if (isMain(import.meta.url)) {
process.exitCode = main(generate);
}