@ejunz/ea-core 0.1.2-rc.5 → 0.1.3
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/lib/bin.js +82 -45
- package/lib/cli-paths-Cpxmk9zd.js +21 -0
- package/lib/dump-config-DxXgKDVl.js +52 -0
- package/lib/dump-config-dI1g8Og5.js +52 -0
- package/lib/embed.js +5543 -184
- package/lib/host-tools-BVh5Ga7o.js +20 -0
- package/lib/plugin-BPeOtCDm.js +129 -0
- package/lib/plugin-CUTzbaEG.js +129 -0
- package/lib/profile-boot-BqakeoCE.js +317 -0
- package/lib/profile-boot-CSZwEw6O.js +2 -0
- package/lib/profile-boot-DRHYAiGs.js +317 -0
- package/lib/profile-boot-GNxf7vG_.js +2 -0
- package/package.json +2 -2
package/lib/bin.js
CHANGED
|
@@ -1,10 +1,42 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as cliManifestPath } from "./cli-paths-
|
|
3
|
-
import { t as installHostToolBridge } from "./host-tools-
|
|
4
|
-
import { readFileSync } from "node:fs";
|
|
5
|
-
import {
|
|
2
|
+
import { n as cliManifestPath } from "./cli-paths-Cpxmk9zd.js";
|
|
3
|
+
import { t as installHostToolBridge } from "./host-tools-BVh5Ga7o.js";
|
|
4
|
+
import { copyFileSync, existsSync, readFileSync } from "node:fs";
|
|
5
|
+
import { resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { load } from "js-yaml";
|
|
8
|
+
import { loadLayeredEnv, loadProfile } from "@ejunz/ea-core/app-boot";
|
|
6
9
|
import { Command, CommanderError } from "commander";
|
|
7
|
-
//#region
|
|
10
|
+
//#region packages/profile-ejunz/lib/index.js
|
|
11
|
+
/** Standalone Ejunz profile configuration file. */
|
|
12
|
+
const EXAMPLE_PATH = fileURLToPath(new URL("../config.agent.example.yaml", import.meta.url));
|
|
13
|
+
function record(value) {
|
|
14
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
15
|
+
}
|
|
16
|
+
/** Create config.agent.yaml from the shipped example, then validate its bridge values. */
|
|
17
|
+
function loadEjunzAgentConfig(cwd = process.cwd()) {
|
|
18
|
+
const configPath = resolve(cwd, "config.agent.yaml");
|
|
19
|
+
if (!existsSync(configPath)) {
|
|
20
|
+
copyFileSync(EXAMPLE_PATH, configPath);
|
|
21
|
+
console.info(`Created ${configPath} from ${EXAMPLE_PATH}; fill bridge.origin and bridge.token, then retry.`);
|
|
22
|
+
}
|
|
23
|
+
let document;
|
|
24
|
+
try {
|
|
25
|
+
document = load(readFileSync(configPath, "utf8"));
|
|
26
|
+
} catch (error) {
|
|
27
|
+
throw new Error(`profile-ejunz: ${configPath} is not valid YAML: ${String(error)}`);
|
|
28
|
+
}
|
|
29
|
+
const bridge = record(record(document)?.bridge);
|
|
30
|
+
const origin = typeof bridge?.origin === "string" ? bridge.origin.trim() : "";
|
|
31
|
+
const token = typeof bridge?.token === "string" ? bridge.token.trim() : "";
|
|
32
|
+
if (origin === "" || token === "") throw new Error(`profile-ejunz: fill bridge.origin and bridge.token in ${configPath}`);
|
|
33
|
+
return {
|
|
34
|
+
origin,
|
|
35
|
+
token
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/commands/args.ts
|
|
8
40
|
/**
|
|
9
41
|
* Commander adapter for the `ea` command line.
|
|
10
42
|
*
|
|
@@ -12,10 +44,10 @@ import { Command, CommanderError } from "commander";
|
|
|
12
44
|
* patch overlays to apply, and the config dumps — and hands **everything after
|
|
13
45
|
* its own flags** to the booted tree verbatim, where injected app plugins parse
|
|
14
46
|
* their own flag families and print their own `--help` (see
|
|
15
|
-
* `@ejunz/cmdline`). Launcher flags therefore come first: the first
|
|
47
|
+
* `@ejunz/ea-core/cmdline`). Launcher flags therefore come first: the first
|
|
16
48
|
* token this parser does not recognize starts the inner arguments, so
|
|
17
|
-
* `ea --profile
|
|
18
|
-
* `plugin` manages a profile's
|
|
49
|
+
* `ea --profile web --port 8080` boots the web profile with `--port 8080`,
|
|
50
|
+
* and `plugin` manages a profile's dependencies by forwarding to yarn.
|
|
19
51
|
* @module @ejunz/ea-core/args
|
|
20
52
|
*/
|
|
21
53
|
/**
|
|
@@ -26,11 +58,11 @@ const collect = (value, previous = []) => [...previous, value];
|
|
|
26
58
|
/** The launcher's own help text; each app prints its own. */
|
|
27
59
|
const HELP_EXAMPLES = `
|
|
28
60
|
Examples:
|
|
29
|
-
ea --profile
|
|
30
|
-
ea --profile
|
|
31
|
-
ea --profile
|
|
32
|
-
ea
|
|
33
|
-
ea plugin --profile
|
|
61
|
+
ea --profile web boot the generic Web profile
|
|
62
|
+
ea --profile web --debug include Cordis plugin activation logs
|
|
63
|
+
ea --profile ejunz boot with Ejunz-hosted services
|
|
64
|
+
ea --profile web --port 8080 pass app arguments after launcher flags
|
|
65
|
+
ea plugin --profile web add <package> install a plugin into the web profile
|
|
34
66
|
`;
|
|
35
67
|
/**
|
|
36
68
|
* Resolve a boot or dump invocation from the launcher flags and the leftover
|
|
@@ -48,7 +80,8 @@ function resolveBoot(program, profile, options, args) {
|
|
|
48
80
|
mode: "profile",
|
|
49
81
|
profile,
|
|
50
82
|
patches,
|
|
51
|
-
args
|
|
83
|
+
args,
|
|
84
|
+
debug: options.debug === true
|
|
52
85
|
};
|
|
53
86
|
if (options.dumpConfig === true && options.dumpDefaultConfig === true) program.error("error: --dump-config and --dump-default-config are mutually exclusive");
|
|
54
87
|
if (args.length > 0) program.error(`error: config dumps take no app arguments, got ${args.map((argument) => JSON.stringify(argument)).join(" ")}`);
|
|
@@ -71,7 +104,7 @@ function resolveBoot(program, profile, options, args) {
|
|
|
71
104
|
function parseEaArgs(argv, version) {
|
|
72
105
|
let resolved;
|
|
73
106
|
const program = new Command();
|
|
74
|
-
program.name("ea").version(version, "-V, --version", "output the version number").description("ea: boot a EjunzAgent profile — an ordered stack of plugin-bundle patch layers under your own overrides.").addHelpText("after", HELP_EXAMPLES).exitOverride().helpOption(false).allowUnknownOption().passThroughOptions().enablePositionalOptions().argument("[args...]", "arguments for the booted profile's app (see: ea --profile <name> --help)").option("--profile <name>", "the profile under $EA_HOME/profiles to boot").option("--patch <path>", "extra patch-list overlay applied after the profile layer (repeatable)", collect).option("--dump-config", "print the composed profile tree and exit").option("--dump-default-config", "print the profile tree without its user layer or --patch overlays and exit").action((args, options) => {
|
|
107
|
+
program.name("ea").version(version, "-V, --version", "output the version number").description("ea: boot a EjunzAgent profile — an ordered stack of plugin-bundle patch layers under your own overrides.").addHelpText("after", HELP_EXAMPLES).exitOverride().helpOption(false).allowUnknownOption().passThroughOptions().enablePositionalOptions().argument("[args...]", "arguments for the booted profile's app (see: ea --profile <name> --help)").option("--profile <name>", "the profile under $EA_HOME/profiles to boot").option("--debug", "log profile plugin activation and lifecycle events").option("--patch <path>", "extra patch-list overlay applied after the profile layer (repeatable)", collect).option("--dump-config", "print the composed profile tree and exit").option("--dump-default-config", "print the profile tree without its user layer or --patch overlays and exit").action((args, options) => {
|
|
75
108
|
if (options.profile === void 0) {
|
|
76
109
|
if (args.some((argument) => argument === "-h" || argument === "--help")) program.help();
|
|
77
110
|
program.error("error: --profile <name> is required");
|
|
@@ -83,15 +116,8 @@ function parseEaArgs(argv, version) {
|
|
|
83
116
|
/** Reject parent options supplied before a subcommand. */
|
|
84
117
|
const rejectParentOptions = (command) => {
|
|
85
118
|
const parent = program.opts();
|
|
86
|
-
if (parent.profile !== void 0 || parent.patch !== void 0 || parent.dumpConfig !== void 0 || parent.dumpDefaultConfig !== void 0) program.error(`error: ${command} takes none of parent --profile, --patch, --dump-config, or --dump-default-config`);
|
|
119
|
+
if (parent.profile !== void 0 || parent.patch !== void 0 || parent.debug !== void 0 || parent.dumpConfig !== void 0 || parent.dumpDefaultConfig !== void 0) program.error(`error: ${command} takes none of parent --profile, --debug, --patch, --dump-config, or --dump-default-config`);
|
|
87
120
|
};
|
|
88
|
-
program.command("node").description("join a server that runs elsewhere, reading $EA_HOME/agent.yaml; the node surface's own flags follow").helpOption(false).allowUnknownOption().passThroughOptions().enablePositionalOptions().argument("[args...]", "arguments for the node surface (e.g. --url <server>, --label <name>)").action((args) => {
|
|
89
|
-
rejectParentOptions("node");
|
|
90
|
-
resolved = {
|
|
91
|
-
mode: "node",
|
|
92
|
-
args
|
|
93
|
-
};
|
|
94
|
-
});
|
|
95
121
|
program.command("plugin").description("manage a profile's plugins by forwarding the remaining arguments to yarn in the profile directory").requiredOption("--profile <name>", "the profile whose plugins to manage (initialized on first use)").allowUnknownOption().argument("[args...]", "yarn arguments, forwarded verbatim (add <pkg>, remove <pkg>, why <pkg>, ...)").action((args, options) => {
|
|
96
122
|
rejectParentOptions("plugin");
|
|
97
123
|
if (options.profile === "") program.error("error: --profile needs a name");
|
|
@@ -112,7 +138,7 @@ function parseEaArgs(argv, version) {
|
|
|
112
138
|
return resolved;
|
|
113
139
|
}
|
|
114
140
|
//#endregion
|
|
115
|
-
//#region
|
|
141
|
+
//#region src/entry/bin.ts
|
|
116
142
|
/**
|
|
117
143
|
* ea — command-line entry. Dynamic imports per mode keep unrelated modes out
|
|
118
144
|
* of each dispatch path; the adapter prints and exits for
|
|
@@ -120,6 +146,11 @@ function parseEaArgs(argv, version) {
|
|
|
120
146
|
* @module @ejunz/ea-core/bin
|
|
121
147
|
*/
|
|
122
148
|
/* v8 ignore file -- built-bin acceptance exercises this self-executing dispatch. */
|
|
149
|
+
function configText(config, key) {
|
|
150
|
+
if (typeof config !== "object" || config === null) return void 0;
|
|
151
|
+
const value = config[key];
|
|
152
|
+
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
153
|
+
}
|
|
123
154
|
/** This app's version, read from its checked-in package.json. */
|
|
124
155
|
function readVersion() {
|
|
125
156
|
const manifest = JSON.parse(readFileSync(cliManifestPath(), "utf8"));
|
|
@@ -128,44 +159,50 @@ function readVersion() {
|
|
|
128
159
|
const invocation = parseEaArgs(process.argv.slice(2), readVersion());
|
|
129
160
|
switch (invocation.mode) {
|
|
130
161
|
case "profile": {
|
|
131
|
-
const { runProfile } = await import("./profile-boot-
|
|
162
|
+
const { runProfile } = await import("./profile-boot-CSZwEw6O.js");
|
|
163
|
+
const ejunzConfig = loadProfile("ea", invocation.profile, cliManifestPath()).layers.some((layer) => layer.packageName === "@ejunz/profile-ejunz") ? loadEjunzAgentConfig() : void 0;
|
|
164
|
+
const profileConfigPatches = ejunzConfig === void 0 ? [] : [{
|
|
165
|
+
id: "storage-ejunz",
|
|
166
|
+
config: ejunzConfig
|
|
167
|
+
}, {
|
|
168
|
+
id: "session-persistence-ejunz",
|
|
169
|
+
config: ejunzConfig
|
|
170
|
+
}];
|
|
132
171
|
await runProfile({
|
|
133
172
|
environment: loadLayeredEnv("ea"),
|
|
134
173
|
profile: invocation.profile,
|
|
135
174
|
patchFiles: invocation.patches,
|
|
175
|
+
profileConfigPatches,
|
|
136
176
|
args: invocation.args,
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
177
|
+
debug: invocation.debug,
|
|
178
|
+
prepare: async (ctx, composed) => {
|
|
179
|
+
if (!["storage-ejunz", "session-persistence-ejunz"].some((id) => {
|
|
180
|
+
const row = composed.rows.get(id);
|
|
181
|
+
return row !== void 0 && row.disabled !== true;
|
|
182
|
+
})) return;
|
|
183
|
+
const storageConfig = composed.rows.get("storage-ejunz")?.config;
|
|
184
|
+
const persistenceConfig = composed.rows.get("session-persistence-ejunz")?.config;
|
|
185
|
+
const origin = configText(storageConfig, "origin");
|
|
186
|
+
const token = configText(storageConfig, "token");
|
|
187
|
+
const persistenceOrigin = configText(persistenceConfig, "origin");
|
|
188
|
+
const persistenceToken = configText(persistenceConfig, "token");
|
|
189
|
+
if (!origin || !token || !persistenceOrigin || !persistenceToken) throw new Error("ea: config.agent.yaml must provide the Ejunz bridge for storage-ejunz and session-persistence-ejunz");
|
|
190
|
+
if (origin !== persistenceOrigin || token !== persistenceToken) throw new Error("ea: storage-ejunz and session-persistence-ejunz must use the same Ejunz bridge origin and token");
|
|
191
|
+
await installHostToolBridge(ctx, {
|
|
141
192
|
origin,
|
|
142
193
|
token
|
|
143
194
|
});
|
|
144
|
-
else console.warn(`[host-tools] bridge unavailable origin=${origin ? "set" : "missing"} token=${token ? "set" : "missing"}`);
|
|
145
195
|
}
|
|
146
196
|
});
|
|
147
197
|
break;
|
|
148
198
|
}
|
|
149
|
-
case "node": {
|
|
150
|
-
const { runNode, parseNodeArgs } = await import("./node-DzoSnntW.js");
|
|
151
|
-
const { surfaceLogger } = await import("./surface-log-fjX8orGn.js");
|
|
152
|
-
try {
|
|
153
|
-
await runNode(parseNodeArgs(invocation.args));
|
|
154
|
-
} catch (error) {
|
|
155
|
-
const logger = surfaceLogger("ea-node");
|
|
156
|
-
if (error instanceof Error) logger.error(error.stack ?? error.message);
|
|
157
|
-
else logger.error(String(error));
|
|
158
|
-
process.exitCode = 1;
|
|
159
|
-
}
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
199
|
case "plugin": {
|
|
163
|
-
const { runPlugin } = await import("./plugin-
|
|
200
|
+
const { runPlugin } = await import("./plugin-CUTzbaEG.js");
|
|
164
201
|
process.exit(runPlugin(invocation.profile, invocation.args));
|
|
165
202
|
break;
|
|
166
203
|
}
|
|
167
204
|
case "dump-config": {
|
|
168
|
-
const { runDumpConfig } = await import("./dump-config-
|
|
205
|
+
const { runDumpConfig } = await import("./dump-config-DxXgKDVl.js");
|
|
169
206
|
runDumpConfig(invocation.profile, invocation.defaultOnly, invocation.patches);
|
|
170
207
|
break;
|
|
171
208
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
//#region src/lib/cli-paths.ts
|
|
5
|
+
const moduleDirectory = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const sourceAppDirectory = join(moduleDirectory, "../..");
|
|
7
|
+
const bundledAppDirectory = join(moduleDirectory, "..");
|
|
8
|
+
/** Resolve an asset owned by the CLI package from source or bundled execution. */
|
|
9
|
+
function cliAssetPath(relativePath) {
|
|
10
|
+
const sourcePath = join(sourceAppDirectory, relativePath);
|
|
11
|
+
if (existsSync(sourcePath)) return sourcePath;
|
|
12
|
+
const bundledPath = join(bundledAppDirectory, relativePath);
|
|
13
|
+
if (existsSync(bundledPath)) return bundledPath;
|
|
14
|
+
return sourcePath;
|
|
15
|
+
}
|
|
16
|
+
/** Resolve the CLI package manifest from source or bundled execution. */
|
|
17
|
+
function cliManifestPath() {
|
|
18
|
+
return cliAssetPath("package.json");
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { cliManifestPath as n, cliAssetPath as t };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { a as homePatchPath, n as PROFILE_ROOT_FILENAME, o as prepareProfile } from "./profile-boot-DRHYAiGs.js";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { loadOptionalPatches, loadOverlayPatches, renderConfigDump } from "@ejunz/ea-core/app-boot";
|
|
5
|
+
//#region src/commands/dump-config.ts
|
|
6
|
+
/**
|
|
7
|
+
* Config-dump entry for `ea --profile <name> --dump-config`: compose the
|
|
8
|
+
* profile's patch layers through the include plugin's patch algorithm without
|
|
9
|
+
* booting or evaluating `!!js`, with one source layer per bundle, the
|
|
10
|
+
* profile's own patch file, and each `--patch` overlay.
|
|
11
|
+
* @module @ejunz/ea-core/dump-config
|
|
12
|
+
*/
|
|
13
|
+
const NAME = "ea";
|
|
14
|
+
/* v8 ignore start -- built-bin acceptance drives this boot-free dispatch */
|
|
15
|
+
/**
|
|
16
|
+
* Print a profile composition with comments naming each source file and patch layer.
|
|
17
|
+
* @param profile - the profile name.
|
|
18
|
+
* @param defaultOnly - omit the profile's user layer and `--patch` overlays
|
|
19
|
+
* (the recovery diagnostic for a broken `cordis.patch.yml`, which is then
|
|
20
|
+
* never parsed).
|
|
21
|
+
* @param patches - `--patch` overlay paths, in argv order.
|
|
22
|
+
*/
|
|
23
|
+
function runDumpConfig(profile, defaultOnly, patches) {
|
|
24
|
+
const loaded = prepareProfile(profile, !defaultOnly);
|
|
25
|
+
const layers = loaded.layers.map((layer) => ({
|
|
26
|
+
label: layer.packageName,
|
|
27
|
+
patches: layer.patches
|
|
28
|
+
}));
|
|
29
|
+
if (!defaultOnly) {
|
|
30
|
+
if (existsSync(loaded.patchPath)) layers.push({
|
|
31
|
+
label: loaded.patchPath,
|
|
32
|
+
patches: loaded.patches
|
|
33
|
+
});
|
|
34
|
+
const homePatchFile = homePatchPath();
|
|
35
|
+
const homePatches = loadOptionalPatches(NAME, homePatchFile);
|
|
36
|
+
if (homePatches !== void 0) layers.push({
|
|
37
|
+
label: homePatchFile,
|
|
38
|
+
patches: homePatches
|
|
39
|
+
});
|
|
40
|
+
for (const file of patches) {
|
|
41
|
+
const absolute = resolve(file);
|
|
42
|
+
layers.push({
|
|
43
|
+
label: absolute,
|
|
44
|
+
patches: loadOverlayPatches(NAME, absolute)
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
process.stdout.write(renderConfigDump(NAME, join(loaded.dir, PROFILE_ROOT_FILENAME), layers));
|
|
49
|
+
}
|
|
50
|
+
/* v8 ignore stop */
|
|
51
|
+
//#endregion
|
|
52
|
+
export { runDumpConfig };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { a as homePatchPath, n as PROFILE_ROOT_FILENAME, o as prepareProfile } from "./profile-boot-BqakeoCE.js";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { loadOptionalPatches, loadOverlayPatches, renderConfigDump } from "@ejunz/ea-core/app-boot";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
//#region src/commands/dump-config.ts
|
|
6
|
+
/**
|
|
7
|
+
* Config-dump entry for `ea --profile <name> --dump-config`: compose the
|
|
8
|
+
* profile's patch layers through the include plugin's patch algorithm without
|
|
9
|
+
* booting or evaluating `!!js`, with one source layer per bundle, the
|
|
10
|
+
* profile's own patch file, and each `--patch` overlay.
|
|
11
|
+
* @module @ejunz/ea-core/dump-config
|
|
12
|
+
*/
|
|
13
|
+
const NAME = "ea";
|
|
14
|
+
/* v8 ignore start -- built-bin acceptance drives this boot-free dispatch */
|
|
15
|
+
/**
|
|
16
|
+
* Print a profile composition with comments naming each source file and patch layer.
|
|
17
|
+
* @param profile - the profile name.
|
|
18
|
+
* @param defaultOnly - omit the profile's user layer and `--patch` overlays
|
|
19
|
+
* (the recovery diagnostic for a broken `cordis.patch.yml`, which is then
|
|
20
|
+
* never parsed).
|
|
21
|
+
* @param patches - `--patch` overlay paths, in argv order.
|
|
22
|
+
*/
|
|
23
|
+
function runDumpConfig(profile, defaultOnly, patches) {
|
|
24
|
+
const loaded = prepareProfile(profile, !defaultOnly);
|
|
25
|
+
const layers = loaded.layers.map((layer) => ({
|
|
26
|
+
label: layer.packageName,
|
|
27
|
+
patches: layer.patches
|
|
28
|
+
}));
|
|
29
|
+
if (!defaultOnly) {
|
|
30
|
+
if (existsSync(loaded.patchPath)) layers.push({
|
|
31
|
+
label: loaded.patchPath,
|
|
32
|
+
patches: loaded.patches
|
|
33
|
+
});
|
|
34
|
+
const homePatchFile = homePatchPath();
|
|
35
|
+
const homePatches = loadOptionalPatches(NAME, homePatchFile);
|
|
36
|
+
if (homePatches !== void 0) layers.push({
|
|
37
|
+
label: homePatchFile,
|
|
38
|
+
patches: homePatches
|
|
39
|
+
});
|
|
40
|
+
for (const file of patches) {
|
|
41
|
+
const absolute = resolve(file);
|
|
42
|
+
layers.push({
|
|
43
|
+
label: absolute,
|
|
44
|
+
patches: loadOverlayPatches(NAME, absolute)
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
process.stdout.write(renderConfigDump(NAME, join(loaded.dir, PROFILE_ROOT_FILENAME), layers));
|
|
49
|
+
}
|
|
50
|
+
/* v8 ignore stop */
|
|
51
|
+
//#endregion
|
|
52
|
+
export { runDumpConfig };
|