mirror of
https://github.com/Start9Labs/start-sdk.git
synced 2026-03-30 12:21:57 +00:00
chore: Add in the converter for the newest of the builder.
This commit is contained in:
@@ -35,12 +35,7 @@ const username = Value.string({
|
|||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
export class Value<A extends ValueSpec> extends IBuilder<A> {
|
export class Value<A extends ValueSpec> extends IBuilder<A> {
|
||||||
static boolean(a: {
|
static boolean(a: { name: string; description?: string | null; warning?: string | null; default?: boolean | null }) {
|
||||||
name: string;
|
|
||||||
description?: string | null;
|
|
||||||
warning?: string | null;
|
|
||||||
default?: boolean | null;
|
|
||||||
}) {
|
|
||||||
return new Value({
|
return new Value({
|
||||||
description: null,
|
description: null,
|
||||||
warning: null,
|
warning: null,
|
||||||
@@ -148,27 +143,24 @@ export class Value<A extends ValueSpec> extends IBuilder<A> {
|
|||||||
...a,
|
...a,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
static object<Spec extends Config<InputSpec>>(a: {
|
static object<Spec extends Config<InputSpec>>(
|
||||||
name: string;
|
a: {
|
||||||
description?: string | null;
|
name: string;
|
||||||
warning?: string | null;
|
description?: string | null;
|
||||||
default?: null | { [k: string]: unknown };
|
warning?: string | null;
|
||||||
spec: Spec;
|
},
|
||||||
}) {
|
previousSpec: Spec
|
||||||
const { spec: previousSpec, ...rest } = a;
|
) {
|
||||||
const spec = previousSpec.build() as BuilderExtract<Spec>;
|
const spec = previousSpec.build() as BuilderExtract<Spec>;
|
||||||
return new Value({
|
return new Value({
|
||||||
type: "object" as const,
|
type: "object" as const,
|
||||||
description: null,
|
description: null,
|
||||||
warning: null,
|
warning: null,
|
||||||
default: null,
|
...a,
|
||||||
...rest,
|
|
||||||
spec,
|
spec,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
static union<
|
static union<V extends Variants<{ [key: string]: { name: string; spec: InputSpec } }>>(
|
||||||
V extends Variants<{ [key: string]: { name: string; spec: InputSpec } }>
|
|
||||||
>(
|
|
||||||
a: {
|
a: {
|
||||||
name: string;
|
name: string;
|
||||||
description?: string | null;
|
description?: string | null;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Effects } from "../../types";
|
import { Effects } from "../../types";
|
||||||
import { parseCommand } from "../../util/parseCommand";
|
|
||||||
import { CheckResult } from "./CheckResult";
|
import { CheckResult } from "./CheckResult";
|
||||||
export function containsAddress(x: string, port: number) {
|
export function containsAddress(x: string, port: number) {
|
||||||
const readPorts = x
|
const readPorts = x
|
||||||
@@ -26,14 +25,8 @@ export async function checkPortListening(
|
|||||||
} = {}
|
} = {}
|
||||||
): Promise<CheckResult> {
|
): Promise<CheckResult> {
|
||||||
const hasAddress =
|
const hasAddress =
|
||||||
containsAddress(
|
containsAddress(await effects.runCommand(`cat /proc/net/tcp`), port) ||
|
||||||
await effects.runCommand(parseCommand("cat /proc/net/tcp")),
|
containsAddress(await effects.runCommand("cat /proc/net/udp"), port);
|
||||||
port
|
|
||||||
) ||
|
|
||||||
containsAddress(
|
|
||||||
await effects.runCommand(parseCommand("cat /proc/net/udp")),
|
|
||||||
port
|
|
||||||
);
|
|
||||||
if (hasAddress) {
|
if (hasAddress) {
|
||||||
return { status: "passing", message };
|
return { status: "passing", message };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Effects } from "../../types";
|
import { CommandType, Effects } from "../../types";
|
||||||
import { CheckResult } from "./CheckResult";
|
import { CheckResult } from "./CheckResult";
|
||||||
import { timeoutPromise } from "./index";
|
import { timeoutPromise } from "./index";
|
||||||
|
|
||||||
@@ -9,18 +9,18 @@ import { timeoutPromise } from "./index";
|
|||||||
* @param param0
|
* @param param0
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const runHealthScript = async (
|
export const runHealthScript = async <A extends string>(
|
||||||
effects: Effects,
|
effects: Effects,
|
||||||
runCommand: Parameters<Effects["runCommand"]>[0],
|
runCommand: CommandType<A>,
|
||||||
{
|
{
|
||||||
timeout = 30000,
|
timeout = 30000,
|
||||||
errorMessage = `Error while running command: ${runCommand}`,
|
errorMessage = `Error while running command: ${runCommand}`,
|
||||||
message = (res: string) =>
|
message = (res: string) =>
|
||||||
`Have ran script ${runCommand} and the result: ${res}`,
|
`Have ran script ${runCommand} and the result: ${res}`,
|
||||||
}
|
} = {}
|
||||||
): Promise<CheckResult> => {
|
): Promise<CheckResult> => {
|
||||||
const res = await Promise.race([
|
const res = await Promise.race([
|
||||||
effects.runCommand(runCommand),
|
effects.runCommand(runCommand, { timeoutMillis: timeout }),
|
||||||
timeoutPromise(timeout),
|
timeoutPromise(timeout),
|
||||||
]).catch((e) => {
|
]).catch((e) => {
|
||||||
effects.warn(errorMessage);
|
effects.warn(errorMessage);
|
||||||
|
|||||||
164
lib/test/builder.specToBuilder.ts
Normal file
164
lib/test/builder.specToBuilder.ts
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
import camelCase from "lodash/camelCase";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { string } from "ts-matches";
|
||||||
|
import { InputSpecRaw } from "../config/configTypesRaw";
|
||||||
|
import * as C from "../config/configTypesRaw";
|
||||||
|
|
||||||
|
export async function writeConvertedFile(
|
||||||
|
file: string,
|
||||||
|
inputData: Promise<InputSpecRaw> | InputSpecRaw,
|
||||||
|
options: Parameters<typeof makeFileContent>[1]
|
||||||
|
) {
|
||||||
|
await fs.writeFile(file, await makeFileContent(inputData, options), (err) => console.error(err));
|
||||||
|
}
|
||||||
|
export default async function makeFileContent(
|
||||||
|
inputData: Promise<InputSpecRaw> | InputSpecRaw,
|
||||||
|
{ startSdk = "start-sdk" } = {}
|
||||||
|
) {
|
||||||
|
const outputLines: string[] = [];
|
||||||
|
outputLines.push(`
|
||||||
|
import {Config, Value, List, Variants} from '${startSdk}/config/builder';
|
||||||
|
`);
|
||||||
|
const data = await inputData;
|
||||||
|
|
||||||
|
const namedConsts = new Set(["Config", "Value", "List"]);
|
||||||
|
const configName = newConst("InputSpec", convertInputSpec(data));
|
||||||
|
const configMatcherName = newConst("matchInputSpec", `${configName}.validator()`);
|
||||||
|
outputLines.push(`export type InputSpec = typeof ${configMatcherName}._TYPE;`);
|
||||||
|
|
||||||
|
return outputLines.join("\n");
|
||||||
|
|
||||||
|
function newConst(key: string, data: string) {
|
||||||
|
const variableName = getNextConstName(camelCase(key));
|
||||||
|
outputLines.push(`export const ${variableName} = ${data};`);
|
||||||
|
return variableName;
|
||||||
|
}
|
||||||
|
function convertInputSpec(data: C.InputSpecRaw) {
|
||||||
|
let answer = "Config.of({";
|
||||||
|
for (const [key, value] of Object.entries(data)) {
|
||||||
|
const variableName = newConst(key, convertValueSpec(value));
|
||||||
|
|
||||||
|
answer += `${JSON.stringify(key)}: ${variableName},`;
|
||||||
|
}
|
||||||
|
return `${answer}});`;
|
||||||
|
}
|
||||||
|
function convertValueSpec(value: C.ValueSpec): string {
|
||||||
|
switch (value.type) {
|
||||||
|
case "string":
|
||||||
|
case "textarea":
|
||||||
|
case "number":
|
||||||
|
case "boolean":
|
||||||
|
case "select":
|
||||||
|
case "multiselect": {
|
||||||
|
const { type, ...rest } = value;
|
||||||
|
return `Value.${type}(${JSON.stringify(rest, null, 2)})`;
|
||||||
|
}
|
||||||
|
case "object": {
|
||||||
|
const { type, spec, ...rest } = value;
|
||||||
|
const specName = newConst(value.name + "_spec", convertInputSpec(spec));
|
||||||
|
return `Value.object({
|
||||||
|
name: ${JSON.stringify(rest.name || null)},
|
||||||
|
description: ${JSON.stringify(rest.description || null)},
|
||||||
|
warning: ${JSON.stringify(rest.warning || null)},
|
||||||
|
spec: ,
|
||||||
|
}, ${specName})`;
|
||||||
|
}
|
||||||
|
case "union": {
|
||||||
|
const { variants, type, ...rest } = value;
|
||||||
|
const variantVariable = newConst(value.name + "_variants", convertVariants(variants));
|
||||||
|
|
||||||
|
return `Value.union(${JSON.stringify(rest)}, ${variantVariable})`;
|
||||||
|
}
|
||||||
|
case "list": {
|
||||||
|
const list = newConst(value.name + "_list", convertList(value));
|
||||||
|
return `Value.list(${list})`;
|
||||||
|
}
|
||||||
|
case "file": {
|
||||||
|
throw new Error("File not implemented yet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertList(valueSpecList: C.ValueSpecList) {
|
||||||
|
const { spec, ...value } = valueSpecList;
|
||||||
|
switch (spec.type) {
|
||||||
|
case "string": {
|
||||||
|
return `List.string(${JSON.stringify(
|
||||||
|
{
|
||||||
|
name: value.name || null,
|
||||||
|
range: value.range || null,
|
||||||
|
default: value.default || null,
|
||||||
|
description: value.description || null,
|
||||||
|
warning: value.warning || null,
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)}, ${JSON.stringify({
|
||||||
|
masked: spec?.masked || false,
|
||||||
|
placeholder: spec?.placeholder || null,
|
||||||
|
pattern: spec?.pattern || null,
|
||||||
|
patternDescription: spec?.patternDescription || null,
|
||||||
|
inputMode: spec?.inputmode || null,
|
||||||
|
})})`;
|
||||||
|
}
|
||||||
|
case "number": {
|
||||||
|
return `List.number(${JSON.stringify(
|
||||||
|
{
|
||||||
|
name: value.name || null,
|
||||||
|
range: value.range || null,
|
||||||
|
default: value.default || null,
|
||||||
|
description: value.description || null,
|
||||||
|
warning: value.warning || null,
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)}, ${JSON.stringify({
|
||||||
|
range: spec?.range || null,
|
||||||
|
integral: spec?.integral || false,
|
||||||
|
units: spec?.units || null,
|
||||||
|
placeholder: spec?.placeholder || null,
|
||||||
|
})})`;
|
||||||
|
}
|
||||||
|
case "object": {
|
||||||
|
const specName = newConst(value.name + "_spec", convertInputSpec(spec.spec));
|
||||||
|
return `List.obj({
|
||||||
|
name: ${JSON.stringify(value.name || null)},
|
||||||
|
range: ${JSON.stringify(value.range || null)},
|
||||||
|
default: ${JSON.stringify(value.default || null)},
|
||||||
|
description: ${JSON.stringify(value.description || null)},
|
||||||
|
warning: ${JSON.stringify(value.warning || null)},
|
||||||
|
}, {
|
||||||
|
spec: ${specName},
|
||||||
|
displayAs: ${JSON.stringify(spec?.displayAs || null)},
|
||||||
|
uniqueBy: ${JSON.stringify(spec?.uniqueBy || null)},
|
||||||
|
})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertVariants(
|
||||||
|
variants: Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
name: string;
|
||||||
|
spec: C.InputSpecRaw;
|
||||||
|
}
|
||||||
|
>
|
||||||
|
): string {
|
||||||
|
let answer = "Variants.of({";
|
||||||
|
for (const [key, { name, spec }] of Object.entries(variants)) {
|
||||||
|
const variantSpec = newConst(key, convertInputSpec(spec));
|
||||||
|
answer += `"${key}": {name: "${name}", spec: ${variantSpec}},`;
|
||||||
|
}
|
||||||
|
return `${answer}})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNextConstName(name: string, i = 0): string {
|
||||||
|
const newName = !i ? name : name + i;
|
||||||
|
if (namedConsts.has(newName)) {
|
||||||
|
return getNextConstName(name, i + 1);
|
||||||
|
}
|
||||||
|
namedConsts.add(newName);
|
||||||
|
return newName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import { sh } from "../util";
|
|
||||||
|
|
||||||
describe("Util shell values bluj ", () => {
|
|
||||||
test("simple", () => {
|
|
||||||
expect(sh("echo hello")).toEqual({ command: "echo", args: ["hello"] });
|
|
||||||
}, 1);
|
|
||||||
test("simple 2", () => {
|
|
||||||
expect(sh("echo hello world")).toEqual({
|
|
||||||
command: "echo",
|
|
||||||
args: ["hello", "world"],
|
|
||||||
});
|
|
||||||
}, 1);
|
|
||||||
test("simple A double quote", () => {
|
|
||||||
expect(sh('echo "hello world" ')).toEqual({
|
|
||||||
command: "echo",
|
|
||||||
args: ["hello world"],
|
|
||||||
});
|
|
||||||
}, 1);
|
|
||||||
test("simple A sing quote", () => {
|
|
||||||
expect(sh("echo 'hello world' ")).toEqual({
|
|
||||||
command: "echo",
|
|
||||||
args: ["hello world"],
|
|
||||||
});
|
|
||||||
}, 1);
|
|
||||||
test("simple complex", () => {
|
|
||||||
expect(sh("echo arg1 'arg2 and' arg3 \"arg4 \" ")).toEqual({
|
|
||||||
command: "echo",
|
|
||||||
args: ["arg1", "arg2 and", "arg3", "arg4 "],
|
|
||||||
});
|
|
||||||
}, 1);
|
|
||||||
test("nested", () => {
|
|
||||||
expect(
|
|
||||||
sh(`echo " 'arg1 ' " ' " arg2" ' arg4'"`)
|
|
||||||
).toEqual({
|
|
||||||
command: "echo",
|
|
||||||
args: [` 'arg1 ' `, ` " arg2" `, `arg4'"`],
|
|
||||||
});
|
|
||||||
}, 1);
|
|
||||||
});
|
|
||||||
27
lib/types.ts
27
lib/types.ts
@@ -79,6 +79,14 @@ export namespace ExpectedExports {
|
|||||||
export type TimeMs = number;
|
export type TimeMs = number;
|
||||||
export type VersionString = string;
|
export type VersionString = string;
|
||||||
|
|
||||||
|
type ValidIfNoStupidEscape<A> = A extends
|
||||||
|
| `${string}'"'"'${string}`
|
||||||
|
| `${string}\\"${string}`
|
||||||
|
? never
|
||||||
|
: "" extends A & ""
|
||||||
|
? never
|
||||||
|
: A;
|
||||||
|
|
||||||
export type ConfigRes = {
|
export type ConfigRes = {
|
||||||
/** This should be the previous config, that way during set config we start with the previous */
|
/** This should be the previous config, that way during set config we start with the previous */
|
||||||
config?: null | Record<string, unknown>;
|
config?: null | Record<string, unknown>;
|
||||||
@@ -98,6 +106,10 @@ export type Daemon = {
|
|||||||
|
|
||||||
export type HealthStatus = "passing" | "warning" | "failing" | "disabled";
|
export type HealthStatus = "passing" | "warning" | "failing" | "disabled";
|
||||||
|
|
||||||
|
export type CommandType<A extends string> =
|
||||||
|
| ValidIfNoStupidEscape<A>
|
||||||
|
| [string, ...string[]];
|
||||||
|
|
||||||
/** Used to reach out from the pure js runtime */
|
/** Used to reach out from the pure js runtime */
|
||||||
export type Effects = {
|
export type Effects = {
|
||||||
/** Usable when not sandboxed */
|
/** Usable when not sandboxed */
|
||||||
@@ -129,16 +141,19 @@ export type Effects = {
|
|||||||
path: string;
|
path: string;
|
||||||
}): Promise<Record<string, unknown>>;
|
}): Promise<Record<string, unknown>>;
|
||||||
|
|
||||||
runCommand(input: {
|
runCommand<A extends string>(
|
||||||
command: string;
|
command: ValidIfNoStupidEscape<A> | [string, ...string[]],
|
||||||
args?: string[];
|
input?: {
|
||||||
timeoutMillis?: number;
|
timeoutMillis?: number;
|
||||||
}): Promise<string>;
|
}
|
||||||
|
): Promise<string>;
|
||||||
runShellDaemon(command: string): {
|
runShellDaemon(command: string): {
|
||||||
wait(): Promise<string>;
|
wait(): Promise<string>;
|
||||||
term(): Promise<void>;
|
term(): Promise<void>;
|
||||||
};
|
};
|
||||||
runDaemon(input: { command: string; args?: string[] }): {
|
runDaemon<A extends string>(
|
||||||
|
command: ValidIfNoStupidEscape<A> | [string, ...string[]]
|
||||||
|
): {
|
||||||
wait(): Promise<string>;
|
wait(): Promise<string>;
|
||||||
term(): Promise<void>;
|
term(): Promise<void>;
|
||||||
[DaemonProof]: never;
|
[DaemonProof]: never;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import * as T from "../types";
|
|||||||
export { guardAll, typeFromProps } from "./propertiesMatcher";
|
export { guardAll, typeFromProps } from "./propertiesMatcher";
|
||||||
export { default as nullIfEmpty } from "./nullIfEmpty";
|
export { default as nullIfEmpty } from "./nullIfEmpty";
|
||||||
export { FileHelper } from "./fileHelper";
|
export { FileHelper } from "./fileHelper";
|
||||||
export { parseCommand as sh } from "./parseCommand";
|
|
||||||
|
|
||||||
/** Used to check if the file exists before hand */
|
/** Used to check if the file exists before hand */
|
||||||
export const exists = (
|
export const exists = (
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
import { Effects } from "../types";
|
|
||||||
|
|
||||||
const match =
|
|
||||||
(regex: RegExp) =>
|
|
||||||
(s: string): [string, string, string] => {
|
|
||||||
const matched = s.match(regex);
|
|
||||||
if (matched === null) {
|
|
||||||
return [s, "", ""];
|
|
||||||
}
|
|
||||||
const [
|
|
||||||
_all,
|
|
||||||
_firstSet,
|
|
||||||
notQuote,
|
|
||||||
_maybeQuote,
|
|
||||||
doubleQuoted,
|
|
||||||
singleQuoted,
|
|
||||||
rest,
|
|
||||||
noQuotes,
|
|
||||||
] = matched;
|
|
||||||
const quoted = doubleQuoted || singleQuoted;
|
|
||||||
if (!!noQuotes) {
|
|
||||||
return [noQuotes || "", "", ""];
|
|
||||||
}
|
|
||||||
if (!notQuote && !quoted) {
|
|
||||||
return [rest || "", "", ""];
|
|
||||||
}
|
|
||||||
return [notQuote || "", quoted || "", rest || ""];
|
|
||||||
};
|
|
||||||
const quotes = match(/^((.*?)("([^\"]*)"|'([^\']*)')(.*)|(.*))$/);
|
|
||||||
const quoteSeperated = (s: string, quote: typeof quotes) => {
|
|
||||||
const values = [];
|
|
||||||
|
|
||||||
let value = quote(s);
|
|
||||||
while (true) {
|
|
||||||
if (value[0].length) {
|
|
||||||
values.push(...value[0].split(" "));
|
|
||||||
}
|
|
||||||
if (value[1].length) {
|
|
||||||
values.push(value[1]);
|
|
||||||
}
|
|
||||||
if (!value[2].length) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
value = quote(value[2]);
|
|
||||||
}
|
|
||||||
return values;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ValidIfNoStupidEscape<A> = A extends `${string}'"'"'${string}` ? never : A;
|
|
||||||
export function parseCommand<T extends string>(
|
|
||||||
shellCommand: ValidIfNoStupidEscape<T>
|
|
||||||
) {
|
|
||||||
const [command, ...args] = quoteSeperated(shellCommand, quotes).filter(
|
|
||||||
Boolean
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
command,
|
|
||||||
args,
|
|
||||||
} satisfies Parameters<Effects["runCommand"]>[0];
|
|
||||||
}
|
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "start-sdk",
|
"name": "start-sdk",
|
||||||
"version": "0.4.0-lib0.charlie9",
|
"version": "0.4.0-lib0.charlie10",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "start-sdk",
|
"name": "start-sdk",
|
||||||
"version": "0.4.0-lib0.charlie9",
|
"version": "0.4.0-lib0.charlie10",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "start-sdk",
|
"name": "start-sdk",
|
||||||
"version": "0.4.0-lib0.charlie9",
|
"version": "0.4.0-lib0.charlie10",
|
||||||
"description": "For making the patterns that are wanted in making services for the startOS.",
|
"description": "For making the patterns that are wanted in making services for the startOS.",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"types": "./lib/index.d.ts",
|
"types": "./lib/index.d.ts",
|
||||||
|
|||||||
@@ -8,15 +8,10 @@ export async function writeConvertedFile(
|
|||||||
inputData: Promise<any> | any,
|
inputData: Promise<any> | any,
|
||||||
options: Parameters<typeof makeFileContent>[1]
|
options: Parameters<typeof makeFileContent>[1]
|
||||||
) {
|
) {
|
||||||
await fs.writeFile(file, await makeFileContent(inputData, options), (err) =>
|
await fs.writeFile(file, await makeFileContent(inputData, options), (err) => console.error(err));
|
||||||
console.error(err)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function makeFileContent(
|
export default async function makeFileContent(inputData: Promise<any> | any, { startSdk = "start-sdk" } = {}) {
|
||||||
inputData: Promise<any> | any,
|
|
||||||
{ startSdk = "start-sdk" } = {}
|
|
||||||
) {
|
|
||||||
const outputLines: string[] = [];
|
const outputLines: string[] = [];
|
||||||
outputLines.push(`
|
outputLines.push(`
|
||||||
import {Config, Value, List, Variants} from '${startSdk}/config/builder';
|
import {Config, Value, List, Variants} from '${startSdk}/config/builder';
|
||||||
@@ -25,13 +20,8 @@ export default async function makeFileContent(
|
|||||||
|
|
||||||
const namedConsts = new Set(["Config", "Value", "List"]);
|
const namedConsts = new Set(["Config", "Value", "List"]);
|
||||||
const configName = newConst("InputSpec", convertInputSpec(data));
|
const configName = newConst("InputSpec", convertInputSpec(data));
|
||||||
const configMatcherName = newConst(
|
const configMatcherName = newConst("matchInputSpec", `${configName}.validator()`);
|
||||||
"matchInputSpec",
|
outputLines.push(`export type InputSpec = typeof ${configMatcherName}._TYPE;`);
|
||||||
`${configName}.validator()`
|
|
||||||
);
|
|
||||||
outputLines.push(
|
|
||||||
`export type InputSpec = typeof ${configMatcherName}._TYPE;`
|
|
||||||
);
|
|
||||||
|
|
||||||
return outputLines.join("\n");
|
return outputLines.join("\n");
|
||||||
|
|
||||||
@@ -111,10 +101,7 @@ export default async function makeFileContent(
|
|||||||
)})`;
|
)})`;
|
||||||
}
|
}
|
||||||
case "enum": {
|
case "enum": {
|
||||||
const allValueNames = new Set([
|
const allValueNames = new Set([...(value?.["values"] || []), ...Object.keys(value?.["value-names"] || {})]);
|
||||||
...(value?.["values"] || []),
|
|
||||||
...Object.keys(value?.["value-names"] || {}),
|
|
||||||
]);
|
|
||||||
const values = Object.fromEntries(
|
const values = Object.fromEntries(
|
||||||
Array.from(allValueNames)
|
Array.from(allValueNames)
|
||||||
.filter(string.test)
|
.filter(string.test)
|
||||||
@@ -134,17 +121,13 @@ export default async function makeFileContent(
|
|||||||
)} as const)`;
|
)} as const)`;
|
||||||
}
|
}
|
||||||
case "object": {
|
case "object": {
|
||||||
const specName = newConst(
|
const specName = newConst(value.name + "_spec", convertInputSpec(value.spec));
|
||||||
value.name + "_spec",
|
|
||||||
convertInputSpec(value.spec)
|
|
||||||
);
|
|
||||||
return `Value.object({
|
return `Value.object({
|
||||||
name: ${JSON.stringify(value.name || null)},
|
name: ${JSON.stringify(value.name || null)},
|
||||||
description: ${JSON.stringify(value.description || null)},
|
description: ${JSON.stringify(value.description || null)},
|
||||||
warning: ${JSON.stringify(value.warning || null)},
|
warning: ${JSON.stringify(value.warning || null)},
|
||||||
default: ${JSON.stringify(value.default || null)},
|
default: ${JSON.stringify(value.default || null)},
|
||||||
spec: ${specName},
|
}, ${specName})`;
|
||||||
})`;
|
|
||||||
}
|
}
|
||||||
case "union": {
|
case "union": {
|
||||||
const variants = newConst(
|
const variants = newConst(
|
||||||
@@ -174,9 +157,7 @@ export default async function makeFileContent(
|
|||||||
function convertList(value: any) {
|
function convertList(value: any) {
|
||||||
switch (value.subtype) {
|
switch (value.subtype) {
|
||||||
case "string": {
|
case "string": {
|
||||||
return `List.${
|
return `List.${value?.spec?.textarea === true ? "textarea" : "string"}(${JSON.stringify(
|
||||||
value?.spec?.textarea === true ? "textarea" : "string"
|
|
||||||
}(${JSON.stringify(
|
|
||||||
{
|
{
|
||||||
name: value.name || null,
|
name: value.name || null,
|
||||||
range: value.range || null,
|
range: value.range || null,
|
||||||
@@ -235,10 +216,7 @@ export default async function makeFileContent(
|
|||||||
)})`;
|
)})`;
|
||||||
}
|
}
|
||||||
case "object": {
|
case "object": {
|
||||||
const specName = newConst(
|
const specName = newConst(value.name + "_spec", convertInputSpec(value.spec.spec));
|
||||||
value.name + "_spec",
|
|
||||||
convertInputSpec(value.spec.spec)
|
|
||||||
);
|
|
||||||
return `List.obj({
|
return `List.obj({
|
||||||
name: ${JSON.stringify(value.name || null)},
|
name: ${JSON.stringify(value.name || null)},
|
||||||
range: ${JSON.stringify(value.range || null)},
|
range: ${JSON.stringify(value.range || null)},
|
||||||
@@ -254,19 +232,14 @@ export default async function makeFileContent(
|
|||||||
case "union": {
|
case "union": {
|
||||||
const variants = newConst(
|
const variants = newConst(
|
||||||
value.name + "_variants",
|
value.name + "_variants",
|
||||||
convertVariants(
|
convertVariants(value.spec.variants, value.spec["variant-names"] || {})
|
||||||
value.spec.variants,
|
|
||||||
value.spec["variant-names"] || {}
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
const unionValueName = newConst(
|
const unionValueName = newConst(
|
||||||
value.name + "_union",
|
value.name + "_union",
|
||||||
`
|
`
|
||||||
Value.union({
|
Value.union({
|
||||||
name: ${JSON.stringify(value?.spec?.tag?.name || null)},
|
name: ${JSON.stringify(value?.spec?.tag?.name || null)},
|
||||||
description: ${JSON.stringify(
|
description: ${JSON.stringify(value?.spec?.tag?.description || null)},
|
||||||
value?.spec?.tag?.description || null
|
|
||||||
)},
|
|
||||||
warning: ${JSON.stringify(value?.spec?.tag?.warning || null)},
|
warning: ${JSON.stringify(value?.spec?.tag?.warning || null)},
|
||||||
required: ${JSON.stringify(!(value?.spec?.tag?.nullable || false))},
|
required: ${JSON.stringify(!(value?.spec?.tag?.nullable || false))},
|
||||||
default: ${JSON.stringify(value?.spec?.default || null)},
|
default: ${JSON.stringify(value?.spec?.default || null)},
|
||||||
@@ -297,16 +270,11 @@ export default async function makeFileContent(
|
|||||||
throw new Error(`Unknown subtype "${value.subtype}"`);
|
throw new Error(`Unknown subtype "${value.subtype}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertVariants(
|
function convertVariants(variants: Record<string, unknown>, variantNames: Record<string, string>): string {
|
||||||
variants: Record<string, unknown>,
|
|
||||||
variantNames: Record<string, string>
|
|
||||||
): string {
|
|
||||||
let answer = "Variants.of({";
|
let answer = "Variants.of({";
|
||||||
for (const [key, value] of Object.entries(variants)) {
|
for (const [key, value] of Object.entries(variants)) {
|
||||||
const variantSpec = newConst(key, convertInputSpec(value));
|
const variantSpec = newConst(key, convertInputSpec(value));
|
||||||
answer += `"${key}": {name: "${
|
answer += `"${key}": {name: "${variantNames[key] || key}", spec: ${variantSpec}},`;
|
||||||
variantNames[key] || key
|
|
||||||
}", spec: ${variantSpec}},`;
|
|
||||||
}
|
}
|
||||||
return `${answer}})`;
|
return `${answer}})`;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user