@cartesi/cli 1.4.0 → 2.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/baseCommand.d.ts +2 -0
- package/dist/baseCommand.d.ts.map +1 -1
- package/dist/baseCommand.js +10 -5
- package/dist/builder/directory.d.ts +3 -0
- package/dist/builder/directory.d.ts.map +1 -0
- package/dist/builder/directory.js +37 -0
- package/dist/builder/docker.d.ts +10 -0
- package/dist/builder/docker.d.ts.map +1 -0
- package/dist/builder/docker.js +103 -0
- package/dist/builder/empty.d.ts +3 -0
- package/dist/builder/empty.d.ts.map +1 -0
- package/dist/builder/empty.js +21 -0
- package/dist/builder/index.d.ts +6 -0
- package/dist/builder/index.d.ts.map +1 -0
- package/dist/builder/index.js +5 -0
- package/dist/builder/none.d.ts +3 -0
- package/dist/builder/none.d.ts.map +1 -0
- package/dist/builder/none.js +11 -0
- package/dist/builder/tar.d.ts +3 -0
- package/dist/builder/tar.d.ts.map +1 -0
- package/dist/builder/tar.js +30 -0
- package/dist/commands/build.d.ts +3 -15
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +53 -194
- package/dist/commands/shell.d.ts +2 -1
- package/dist/commands/shell.d.ts.map +1 -1
- package/dist/commands/shell.js +41 -41
- package/dist/config.d.ts +102 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +378 -0
- package/dist/contracts.d.ts +492 -1038
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +223 -498
- package/dist/exec/cartesi-machine.d.ts +9 -0
- package/dist/exec/cartesi-machine.d.ts.map +1 -0
- package/dist/exec/cartesi-machine.js +20 -0
- package/dist/exec/crane.d.ts +15 -0
- package/dist/exec/crane.d.ts.map +1 -0
- package/dist/exec/crane.js +17 -0
- package/dist/exec/genext2fs.d.ts +28 -0
- package/dist/exec/genext2fs.d.ts.map +1 -0
- package/dist/exec/genext2fs.js +44 -0
- package/dist/exec/index.d.ts +5 -0
- package/dist/exec/index.d.ts.map +1 -0
- package/dist/exec/index.js +4 -0
- package/dist/exec/mksquashfs.d.ts +21 -0
- package/dist/exec/mksquashfs.d.ts.map +1 -0
- package/dist/exec/mksquashfs.js +45 -0
- package/dist/exec/util.d.ts +36 -0
- package/dist/exec/util.d.ts.map +1 -0
- package/dist/exec/util.js +78 -0
- package/dist/machine.d.ts +6 -0
- package/dist/machine.d.ts.map +1 -0
- package/dist/machine.js +80 -0
- package/dist/node/docker-compose-anvil.yaml +4 -3
- package/dist/node/docker-compose-bundler.yaml +1 -1
- package/dist/node/docker-compose-paymaster.yaml +1 -1
- package/oclif.manifest.json +32 -95
- package/package.json +5 -5
- package/dist/commands/send/dapp-address.d.ts +0 -9
- package/dist/commands/send/dapp-address.d.ts.map +0 -1
- package/dist/commands/send/dapp-address.js +0 -20
package/dist/commands/shell.d.ts
CHANGED
|
@@ -6,9 +6,10 @@ export default class Shell extends BaseCommand<typeof Shell> {
|
|
|
6
6
|
image: import("@oclif/core/lib/interfaces/parser.js").Arg<string | undefined, Record<string, unknown>>;
|
|
7
7
|
};
|
|
8
8
|
static flags: {
|
|
9
|
+
command: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
10
|
+
config: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
9
11
|
"run-as-root": import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
10
12
|
};
|
|
11
|
-
private startShell;
|
|
12
13
|
run(): Promise<void>;
|
|
13
14
|
}
|
|
14
15
|
//# sourceMappingURL=shell.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/commands/shell.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/commands/shell.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIhD,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,WAAW,CAAC,OAAO,KAAK,CAAC;IACxD,MAAM,CAAC,WAAW,SAAqD;IAEvE,MAAM,CAAC,QAAQ,WAA2C;IAE1D,MAAM,CAAC,IAAI;;MAKT;IAEF,MAAM,CAAC,KAAK;;;;MAgBV;IAEW,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA2CpC"}
|
package/dist/commands/shell.js
CHANGED
|
@@ -1,51 +1,40 @@
|
|
|
1
1
|
import { Args, Flags } from "@oclif/core";
|
|
2
|
-
import { execa } from "execa";
|
|
3
2
|
import fs from "fs-extra";
|
|
4
|
-
import { lookpath } from "lookpath";
|
|
5
3
|
import path from "path";
|
|
6
4
|
import { BaseCommand } from "../baseCommand.js";
|
|
5
|
+
import { bootMachine } from "../machine.js";
|
|
7
6
|
class Shell extends BaseCommand {
|
|
8
|
-
async startShell(ext2Path, runAsRoot) {
|
|
9
|
-
const containerDir = "/mnt";
|
|
10
|
-
const bind = `${path.resolve(path.dirname(ext2Path))}:${containerDir}`;
|
|
11
|
-
const ext2 = path.join(containerDir, path.basename(ext2Path));
|
|
12
|
-
const ramSize = "128Mi";
|
|
13
|
-
const driveLabel = "root";
|
|
14
|
-
const sdkImage = "cartesi/sdk:0.10.0"; // XXX: how to resolve sdk version?
|
|
15
|
-
const args = [
|
|
16
|
-
"run",
|
|
17
|
-
"--interactive",
|
|
18
|
-
"--tty",
|
|
19
|
-
"--volume",
|
|
20
|
-
bind,
|
|
21
|
-
sdkImage,
|
|
22
|
-
"cartesi-machine",
|
|
23
|
-
`--ram-length=${ramSize}`,
|
|
24
|
-
"--append-bootargs=no4lvl",
|
|
25
|
-
`--flash-drive=label:${driveLabel},filename:${ext2}`,
|
|
26
|
-
];
|
|
27
|
-
if (runAsRoot) {
|
|
28
|
-
args.push("--append-init=USER=root");
|
|
29
|
-
}
|
|
30
|
-
if (!(await lookpath("stty"))) {
|
|
31
|
-
args.push("-i");
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
args.push("-it");
|
|
35
|
-
}
|
|
36
|
-
await execa("docker", [...args, "--", "/bin/bash"], {
|
|
37
|
-
stdio: "inherit",
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
7
|
async run() {
|
|
41
8
|
const { flags } = await this.parse(Shell);
|
|
42
|
-
//
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
9
|
+
// get application configuration from 'cartesi.toml'
|
|
10
|
+
const config = this.getApplicationConfig(flags.config);
|
|
11
|
+
// destination directory for image and intermediate files
|
|
12
|
+
const destination = path.resolve(this.getContextPath());
|
|
13
|
+
// check if all drives are built
|
|
14
|
+
for (const [name, drive] of Object.entries(config.drives)) {
|
|
15
|
+
const filename = `${name}.${drive.format}`;
|
|
16
|
+
const pathname = this.getContextPath(filename);
|
|
17
|
+
if (!fs.existsSync(pathname)) {
|
|
18
|
+
throw new Error(`drive '${name}' not built, run '${this.config.bin} build'`);
|
|
19
|
+
}
|
|
46
20
|
}
|
|
47
|
-
//
|
|
48
|
-
|
|
21
|
+
// create shell entrypoint
|
|
22
|
+
const info = {
|
|
23
|
+
cmd: [],
|
|
24
|
+
entrypoint: [this.flags.command],
|
|
25
|
+
env: [],
|
|
26
|
+
workdir: "/",
|
|
27
|
+
};
|
|
28
|
+
// start with interactive mode on
|
|
29
|
+
config.machine.interactive = true;
|
|
30
|
+
// interactive mode can't have final hash
|
|
31
|
+
config.machine.finalHash = false;
|
|
32
|
+
// do not store machine in interactive mode
|
|
33
|
+
config.machine.store = undefined;
|
|
34
|
+
// run as root if flag is set
|
|
35
|
+
config.machine.user = flags["run-as-root"] ? "root" : undefined;
|
|
36
|
+
// boot machine
|
|
37
|
+
await bootMachine(config, info, destination);
|
|
49
38
|
}
|
|
50
39
|
}
|
|
51
40
|
Shell.description = "Start a shell in cartesi machine of application";
|
|
@@ -57,9 +46,20 @@ Shell.args = {
|
|
|
57
46
|
}),
|
|
58
47
|
};
|
|
59
48
|
Shell.flags = {
|
|
49
|
+
command: Flags.string({
|
|
50
|
+
default: "/bin/sh",
|
|
51
|
+
description: "shell command to run",
|
|
52
|
+
summary: "shell to run",
|
|
53
|
+
}),
|
|
54
|
+
config: Flags.file({
|
|
55
|
+
char: "c",
|
|
56
|
+
default: "cartesi.toml",
|
|
57
|
+
summary: "path to the configuration file",
|
|
58
|
+
}),
|
|
60
59
|
"run-as-root": Flags.boolean({
|
|
61
|
-
description: "run as root user",
|
|
62
60
|
default: false,
|
|
61
|
+
description: "run as root user",
|
|
62
|
+
summary: "run the cartesi machine as the root user",
|
|
63
63
|
}),
|
|
64
64
|
};
|
|
65
65
|
export default Shell;
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { TomlPrimitive } from "smol-toml";
|
|
2
|
+
/**
|
|
3
|
+
* Typed Errors
|
|
4
|
+
*/
|
|
5
|
+
export declare class InvalidBuilderError extends Error {
|
|
6
|
+
constructor(builder: TomlPrimitive);
|
|
7
|
+
}
|
|
8
|
+
export declare class InvalidDriveFormatError extends Error {
|
|
9
|
+
constructor(format: TomlPrimitive);
|
|
10
|
+
}
|
|
11
|
+
export declare class InvalidEmptyDriveFormatError extends Error {
|
|
12
|
+
constructor(format: TomlPrimitive);
|
|
13
|
+
}
|
|
14
|
+
export declare class InvalidStringValueError extends Error {
|
|
15
|
+
constructor(value: TomlPrimitive);
|
|
16
|
+
}
|
|
17
|
+
export declare class InvalidBooleanValueError extends Error {
|
|
18
|
+
constructor(value: TomlPrimitive);
|
|
19
|
+
}
|
|
20
|
+
export declare class InvalidNumberValueError extends Error {
|
|
21
|
+
constructor(value: TomlPrimitive);
|
|
22
|
+
}
|
|
23
|
+
export declare class InvalidBytesValueError extends Error {
|
|
24
|
+
constructor(value: TomlPrimitive);
|
|
25
|
+
}
|
|
26
|
+
export declare class RequiredFieldError extends Error {
|
|
27
|
+
constructor(key: TomlPrimitive);
|
|
28
|
+
}
|
|
29
|
+
export declare class InvalidStringArrayError extends Error {
|
|
30
|
+
constructor();
|
|
31
|
+
}
|
|
32
|
+
type DriveFormat = "ext2" | "sqfs";
|
|
33
|
+
export type ImageInfo = {
|
|
34
|
+
cmd: string[];
|
|
35
|
+
entrypoint: string[];
|
|
36
|
+
env: string[];
|
|
37
|
+
workdir: string;
|
|
38
|
+
};
|
|
39
|
+
export type DriveResult = ImageInfo | undefined | void;
|
|
40
|
+
export type DirectoryDriveConfig = {
|
|
41
|
+
builder: "directory";
|
|
42
|
+
extraSize: number;
|
|
43
|
+
format: DriveFormat;
|
|
44
|
+
directory: string;
|
|
45
|
+
};
|
|
46
|
+
export type DockerDriveConfig = {
|
|
47
|
+
builder: "docker";
|
|
48
|
+
context: string;
|
|
49
|
+
dockerfile: string;
|
|
50
|
+
extraSize: number;
|
|
51
|
+
format: DriveFormat;
|
|
52
|
+
image?: string;
|
|
53
|
+
tags: string[];
|
|
54
|
+
target?: string;
|
|
55
|
+
};
|
|
56
|
+
export type EmptyDriveConfig = {
|
|
57
|
+
builder: "empty";
|
|
58
|
+
format: "ext2" | "raw";
|
|
59
|
+
size: number;
|
|
60
|
+
};
|
|
61
|
+
export type ExistingDriveConfig = {
|
|
62
|
+
builder: "none";
|
|
63
|
+
filename: string;
|
|
64
|
+
format: DriveFormat;
|
|
65
|
+
};
|
|
66
|
+
export type TarDriveConfig = {
|
|
67
|
+
builder: "tar";
|
|
68
|
+
filename: string;
|
|
69
|
+
format: DriveFormat;
|
|
70
|
+
extraSize: number;
|
|
71
|
+
};
|
|
72
|
+
export type DriveConfig = (DirectoryDriveConfig | DockerDriveConfig | EmptyDriveConfig | ExistingDriveConfig | TarDriveConfig) & {
|
|
73
|
+
mount?: string | boolean;
|
|
74
|
+
shared?: boolean;
|
|
75
|
+
user?: string;
|
|
76
|
+
};
|
|
77
|
+
export type MachineConfig = {
|
|
78
|
+
assertRollingTemplate?: boolean;
|
|
79
|
+
bootargs: string[];
|
|
80
|
+
entrypoint?: string;
|
|
81
|
+
finalHash: boolean;
|
|
82
|
+
interactive?: boolean;
|
|
83
|
+
maxMCycle?: bigint;
|
|
84
|
+
noRollup?: boolean;
|
|
85
|
+
ramLength: string;
|
|
86
|
+
ramImage: string;
|
|
87
|
+
store?: string;
|
|
88
|
+
user?: string;
|
|
89
|
+
};
|
|
90
|
+
export type Config = {
|
|
91
|
+
drives: Record<string, DriveConfig>;
|
|
92
|
+
machine: MachineConfig;
|
|
93
|
+
sdk: string;
|
|
94
|
+
};
|
|
95
|
+
export declare const defaultRootDriveConfig: () => DriveConfig;
|
|
96
|
+
export declare const defaultRamImage: () => string;
|
|
97
|
+
export declare const defaultMachineConfig: () => MachineConfig;
|
|
98
|
+
export declare const defaultConfig: () => Config;
|
|
99
|
+
export declare const getDriveFormat: (filename: string) => DriveFormat;
|
|
100
|
+
export declare const parse: (str: string) => Config;
|
|
101
|
+
export {};
|
|
102
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import bytes from "bytes";
|
|
2
|
+
import os from "os";
|
|
3
|
+
import { extname } from "path";
|
|
4
|
+
import { parse as parseToml } from "smol-toml";
|
|
5
|
+
/**
|
|
6
|
+
* Typed Errors
|
|
7
|
+
*/
|
|
8
|
+
export class InvalidBuilderError extends Error {
|
|
9
|
+
constructor(builder) {
|
|
10
|
+
super(`Invalid builder: ${builder}`);
|
|
11
|
+
this.name = "InvalidBuilder";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class InvalidDriveFormatError extends Error {
|
|
15
|
+
constructor(format) {
|
|
16
|
+
super(`Invalid drive format: ${format}`);
|
|
17
|
+
this.name = "InvalidDriveFormatError";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class InvalidEmptyDriveFormatError extends Error {
|
|
21
|
+
constructor(format) {
|
|
22
|
+
super(`Invalid empty drive format: ${format}`);
|
|
23
|
+
this.name = "InvalidEmptyDriveFormatError";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export class InvalidStringValueError extends Error {
|
|
27
|
+
constructor(value) {
|
|
28
|
+
super(`Invalid string value: ${value}`);
|
|
29
|
+
this.name = "InvalidStringValueError";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export class InvalidBooleanValueError extends Error {
|
|
33
|
+
constructor(value) {
|
|
34
|
+
super(`Invalid boolean value: ${value}`);
|
|
35
|
+
this.name = "InvalidBooleanValueError";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class InvalidNumberValueError extends Error {
|
|
39
|
+
constructor(value) {
|
|
40
|
+
super(`Invalid number value: ${value}`);
|
|
41
|
+
this.name = "InvalidNumberValueError";
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export class InvalidBytesValueError extends Error {
|
|
45
|
+
constructor(value) {
|
|
46
|
+
super(`Invalid bytes value: ${value}`);
|
|
47
|
+
this.name = "InvalidBytesValueError";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export class RequiredFieldError extends Error {
|
|
51
|
+
constructor(key) {
|
|
52
|
+
super(`Missing required field: ${key}`);
|
|
53
|
+
this.name = "RequiredFieldError";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export class InvalidStringArrayError extends Error {
|
|
57
|
+
constructor() {
|
|
58
|
+
super(`Invalid string array`);
|
|
59
|
+
this.name = "InvalidStringArrayError";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Configuration for drives of a Cartesi Machine. A drive may already exist or be built by a builder
|
|
64
|
+
*/
|
|
65
|
+
const DEFAULT_FORMAT = "ext2";
|
|
66
|
+
const DEFAULT_RAM = "128Mi";
|
|
67
|
+
const DEFAULT_RAM_IMAGE_DOCKER = "/usr/share/cartesi-machine/images/linux.bin";
|
|
68
|
+
const DEFAULT_RAM_IMAGE_LINUX = "/usr/share/cartesi-machine/images/linux.bin";
|
|
69
|
+
const DEFAULT_RAM_IMAGE_MAC = "/opt/homebrew/share/cartesi-machine/images/linux.bin";
|
|
70
|
+
const DEFAULT_SDK = "cartesi/sdk:0.12.0-alpha.0";
|
|
71
|
+
export const defaultRootDriveConfig = () => ({
|
|
72
|
+
builder: "docker",
|
|
73
|
+
context: ".",
|
|
74
|
+
dockerfile: "Dockerfile", // file on current working directory
|
|
75
|
+
extraSize: 0,
|
|
76
|
+
format: DEFAULT_FORMAT,
|
|
77
|
+
tags: [],
|
|
78
|
+
});
|
|
79
|
+
export const defaultRamImage = () => {
|
|
80
|
+
switch (os.platform()) {
|
|
81
|
+
case "darwin":
|
|
82
|
+
return DEFAULT_RAM_IMAGE_MAC;
|
|
83
|
+
default:
|
|
84
|
+
return DEFAULT_RAM_IMAGE_LINUX;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
export const defaultMachineConfig = () => ({
|
|
88
|
+
assertRollingTemplate: undefined,
|
|
89
|
+
bootargs: [],
|
|
90
|
+
entrypoint: undefined,
|
|
91
|
+
finalHash: true,
|
|
92
|
+
interactive: undefined,
|
|
93
|
+
maxMCycle: undefined,
|
|
94
|
+
noRollup: undefined,
|
|
95
|
+
ramLength: DEFAULT_RAM,
|
|
96
|
+
ramImage: defaultRamImage(),
|
|
97
|
+
store: "image",
|
|
98
|
+
user: undefined,
|
|
99
|
+
});
|
|
100
|
+
export const defaultConfig = () => ({
|
|
101
|
+
drives: { root: defaultRootDriveConfig() },
|
|
102
|
+
machine: defaultMachineConfig(),
|
|
103
|
+
sdk: DEFAULT_SDK,
|
|
104
|
+
});
|
|
105
|
+
const parseBoolean = (value, defaultValue) => {
|
|
106
|
+
if (value === undefined) {
|
|
107
|
+
return defaultValue;
|
|
108
|
+
}
|
|
109
|
+
else if (typeof value === "boolean") {
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
throw new InvalidBooleanValueError(value);
|
|
113
|
+
};
|
|
114
|
+
const parseOptionalBoolean = (value) => {
|
|
115
|
+
if (value === undefined) {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
else if (typeof value === "boolean") {
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
throw new InvalidBooleanValueError(value);
|
|
122
|
+
};
|
|
123
|
+
const parseString = (value, defaultValue) => {
|
|
124
|
+
if (value === undefined) {
|
|
125
|
+
return defaultValue;
|
|
126
|
+
}
|
|
127
|
+
else if (typeof value === "string") {
|
|
128
|
+
return value;
|
|
129
|
+
}
|
|
130
|
+
throw new InvalidStringValueError(value);
|
|
131
|
+
};
|
|
132
|
+
const parseStringArray = (value) => {
|
|
133
|
+
if (value === undefined) {
|
|
134
|
+
return [];
|
|
135
|
+
}
|
|
136
|
+
else if (typeof value === "string") {
|
|
137
|
+
return [value];
|
|
138
|
+
}
|
|
139
|
+
else if (typeof value === "object" && Array.isArray(value)) {
|
|
140
|
+
return value.map((v) => {
|
|
141
|
+
if (typeof v === "string") {
|
|
142
|
+
return v;
|
|
143
|
+
}
|
|
144
|
+
throw new InvalidStringValueError(v);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
throw new InvalidStringArrayError();
|
|
148
|
+
};
|
|
149
|
+
const parseRequiredString = (value, key) => {
|
|
150
|
+
if (value === undefined) {
|
|
151
|
+
throw new RequiredFieldError(key);
|
|
152
|
+
}
|
|
153
|
+
else if (typeof value === "string") {
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
156
|
+
throw new InvalidStringValueError(value);
|
|
157
|
+
};
|
|
158
|
+
const parseOptionalString = (value) => {
|
|
159
|
+
if (value === undefined) {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
else if (typeof value === "string") {
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
throw new InvalidStringValueError(value);
|
|
166
|
+
};
|
|
167
|
+
const parseOptionalStringBoolean = (value) => {
|
|
168
|
+
if (value === undefined) {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
else if (typeof value === "string") {
|
|
172
|
+
return value;
|
|
173
|
+
}
|
|
174
|
+
else if (typeof value === "boolean") {
|
|
175
|
+
return value;
|
|
176
|
+
}
|
|
177
|
+
throw new InvalidStringValueError(value);
|
|
178
|
+
};
|
|
179
|
+
const parseOptionalNumber = (value) => {
|
|
180
|
+
if (value === undefined) {
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
else if (typeof value === "bigint") {
|
|
184
|
+
return value;
|
|
185
|
+
}
|
|
186
|
+
else if (typeof value === "number") {
|
|
187
|
+
return BigInt(value);
|
|
188
|
+
}
|
|
189
|
+
throw new InvalidNumberValueError(value);
|
|
190
|
+
};
|
|
191
|
+
const parseBytes = (value, defaultValue) => {
|
|
192
|
+
if (value === undefined) {
|
|
193
|
+
return defaultValue;
|
|
194
|
+
}
|
|
195
|
+
else if (typeof value === "bigint") {
|
|
196
|
+
return Number(value);
|
|
197
|
+
}
|
|
198
|
+
else if (typeof value === "number" || typeof value === "string") {
|
|
199
|
+
const output = bytes.parse(value);
|
|
200
|
+
if (output !== null) {
|
|
201
|
+
return output;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
throw new InvalidBytesValueError(value);
|
|
205
|
+
};
|
|
206
|
+
const parseBuilder = (value) => {
|
|
207
|
+
if (value === undefined) {
|
|
208
|
+
return "docker";
|
|
209
|
+
}
|
|
210
|
+
else if (typeof value === "string") {
|
|
211
|
+
switch (value) {
|
|
212
|
+
case "directory":
|
|
213
|
+
return "directory";
|
|
214
|
+
case "docker":
|
|
215
|
+
return "docker";
|
|
216
|
+
case "empty":
|
|
217
|
+
return "empty";
|
|
218
|
+
case "none":
|
|
219
|
+
return "none";
|
|
220
|
+
case "tar":
|
|
221
|
+
return "tar";
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
throw new InvalidBuilderError(value);
|
|
225
|
+
};
|
|
226
|
+
const parseFormat = (value) => {
|
|
227
|
+
if (value === undefined) {
|
|
228
|
+
return DEFAULT_FORMAT;
|
|
229
|
+
}
|
|
230
|
+
else if (typeof value === "string") {
|
|
231
|
+
switch (value) {
|
|
232
|
+
case "ext2":
|
|
233
|
+
return "ext2";
|
|
234
|
+
case "sqfs":
|
|
235
|
+
return "sqfs";
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
throw new InvalidDriveFormatError(value);
|
|
239
|
+
};
|
|
240
|
+
const parseEmptyFormat = (value) => {
|
|
241
|
+
if (value === undefined) {
|
|
242
|
+
return DEFAULT_FORMAT;
|
|
243
|
+
}
|
|
244
|
+
else if (typeof value === "string") {
|
|
245
|
+
switch (value) {
|
|
246
|
+
case "ext2":
|
|
247
|
+
return "ext2";
|
|
248
|
+
case "raw":
|
|
249
|
+
return "raw";
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
throw new InvalidEmptyDriveFormatError(value);
|
|
253
|
+
};
|
|
254
|
+
const parseMachine = (value) => {
|
|
255
|
+
if (value === undefined) {
|
|
256
|
+
// default machine
|
|
257
|
+
return defaultMachineConfig();
|
|
258
|
+
}
|
|
259
|
+
if (typeof value !== "object") {
|
|
260
|
+
throw new Error(`Invalid machine configuration: ${value}`);
|
|
261
|
+
}
|
|
262
|
+
const toml = value;
|
|
263
|
+
return {
|
|
264
|
+
assertRollingTemplate: parseOptionalBoolean(toml["assert-rolling-template"]),
|
|
265
|
+
bootargs: parseStringArray(toml.bootargs),
|
|
266
|
+
finalHash: parseBoolean(toml["final-hash"], true),
|
|
267
|
+
interactive: undefined,
|
|
268
|
+
maxMCycle: parseOptionalNumber(toml["max-mcycle"]),
|
|
269
|
+
noRollup: parseBoolean(toml["no-rollup"], false),
|
|
270
|
+
ramLength: parseString(toml["ram-length"], DEFAULT_RAM),
|
|
271
|
+
ramImage: parseString(toml["ram-image"], defaultRamImage()),
|
|
272
|
+
store: "image",
|
|
273
|
+
user: parseOptionalString(toml.user),
|
|
274
|
+
};
|
|
275
|
+
};
|
|
276
|
+
export const getDriveFormat = (filename) => {
|
|
277
|
+
const extension = extname(filename);
|
|
278
|
+
switch (extension) {
|
|
279
|
+
case ".ext2":
|
|
280
|
+
return "ext2";
|
|
281
|
+
case ".sqfs":
|
|
282
|
+
return "sqfs";
|
|
283
|
+
default:
|
|
284
|
+
throw new InvalidDriveFormatError(extension);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
const parseDrive = (drive) => {
|
|
288
|
+
const builder = parseBuilder(drive.builder);
|
|
289
|
+
switch (builder) {
|
|
290
|
+
case "directory": {
|
|
291
|
+
const { extraSize, format, mount, directory, shared, user } = drive;
|
|
292
|
+
return {
|
|
293
|
+
builder: "directory",
|
|
294
|
+
extraSize: parseBytes(extraSize, 0),
|
|
295
|
+
format: parseFormat(format),
|
|
296
|
+
mount: parseOptionalStringBoolean(mount),
|
|
297
|
+
directory: parseRequiredString(directory, "directory"),
|
|
298
|
+
shared: parseOptionalBoolean(shared),
|
|
299
|
+
user: parseOptionalString(user),
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
case "docker": {
|
|
303
|
+
const { context, dockerfile, extraSize, format, image, mount, shared, tags, target, user, } = drive;
|
|
304
|
+
return {
|
|
305
|
+
builder: "docker",
|
|
306
|
+
image: parseOptionalString(image),
|
|
307
|
+
context: parseString(context, "."),
|
|
308
|
+
dockerfile: parseString(dockerfile, "Dockerfile"),
|
|
309
|
+
extraSize: parseBytes(extraSize, 0),
|
|
310
|
+
format: parseFormat(format),
|
|
311
|
+
mount: parseOptionalStringBoolean(mount),
|
|
312
|
+
shared: parseOptionalBoolean(shared),
|
|
313
|
+
user: parseOptionalString(user),
|
|
314
|
+
tags: parseStringArray(tags),
|
|
315
|
+
target: parseOptionalString(target),
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
case "empty": {
|
|
319
|
+
const { format, mount, size, shared, user } = drive;
|
|
320
|
+
return {
|
|
321
|
+
builder: "empty",
|
|
322
|
+
format: parseEmptyFormat(format),
|
|
323
|
+
mount: parseOptionalStringBoolean(mount),
|
|
324
|
+
shared: parseOptionalBoolean(shared),
|
|
325
|
+
size: parseBytes(size, 0),
|
|
326
|
+
user: parseOptionalString(user),
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
case "tar": {
|
|
330
|
+
const { extraSize, filename, format, mount, shared, user } = drive;
|
|
331
|
+
return {
|
|
332
|
+
builder: "tar",
|
|
333
|
+
extraSize: parseBytes(extraSize, 0),
|
|
334
|
+
filename: parseRequiredString(filename, "filename"),
|
|
335
|
+
format: parseFormat(format),
|
|
336
|
+
mount: parseOptionalStringBoolean(mount),
|
|
337
|
+
shared: parseOptionalBoolean(shared),
|
|
338
|
+
user: parseOptionalString(user),
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
case "none": {
|
|
342
|
+
const { shared, mount, user } = drive;
|
|
343
|
+
const filename = parseRequiredString(drive.filename, "filename");
|
|
344
|
+
const format = getDriveFormat(filename);
|
|
345
|
+
return {
|
|
346
|
+
builder: "none",
|
|
347
|
+
filename,
|
|
348
|
+
format,
|
|
349
|
+
mount: parseOptionalStringBoolean(mount),
|
|
350
|
+
shared: parseOptionalBoolean(shared),
|
|
351
|
+
user: parseOptionalString(user),
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
const parseDrives = (config) => {
|
|
357
|
+
// load drives from configuration
|
|
358
|
+
const drives = Object.entries(config ?? {}).reduce((acc, [name, drive]) => {
|
|
359
|
+
acc[name] = parseDrive(drive);
|
|
360
|
+
return acc;
|
|
361
|
+
}, {});
|
|
362
|
+
// check if there is a root drive
|
|
363
|
+
const hasRoot = drives.root !== undefined;
|
|
364
|
+
if (!hasRoot) {
|
|
365
|
+
// there is no root drive, add a default one
|
|
366
|
+
drives.root = defaultRootDriveConfig();
|
|
367
|
+
}
|
|
368
|
+
return drives;
|
|
369
|
+
};
|
|
370
|
+
export const parse = (str) => {
|
|
371
|
+
const toml = parseToml(str);
|
|
372
|
+
const config = {
|
|
373
|
+
drives: parseDrives(toml.drives),
|
|
374
|
+
machine: parseMachine(toml.machine),
|
|
375
|
+
sdk: parseString(toml.sdk, DEFAULT_SDK),
|
|
376
|
+
};
|
|
377
|
+
return config;
|
|
378
|
+
};
|