@dashnex/cli 0.5.1
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/README.md +35 -0
- package/bin/dashnex +4 -0
- package/dist/cli.js +162 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.js +12 -0
- package/dist/client.js.map +1 -0
- package/dist/commands/create.js +134 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/delete.js +51 -0
- package/dist/commands/delete.js.map +1 -0
- package/dist/commands/index.js +68 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/login.js +262 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.js +16 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/pull.js +102 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/push.js +108 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/version.js +10 -0
- package/dist/commands/version.js.map +1 -0
- package/dist/commands/whoami.js +52 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/dashnex.json.js +5 -0
- package/dist/dashnex.json.js.map +1 -0
- package/dist/lib/api.js +23 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/debug.js +45 -0
- package/dist/lib/debug.js.map +1 -0
- package/dist/package.json.js +15 -0
- package/dist/package.json.js.map +1 -0
- package/dist/server.js +12 -0
- package/dist/server.js.map +1 -0
- package/dist/services/auth.js +116 -0
- package/dist/services/auth.js.map +1 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# @dashnex/cli
|
|
2
|
+
|
|
3
|
+
Command-line interface for the DashNex framework. This CLI tool provides essential commands for managing DashNex projects, including module building, database operations, and migrations. It searches for all @dashnex/* modules in node_modules folder, and loads commands from them.
|
|
4
|
+
|
|
5
|
+
Each module can add a command to CLI. [Read more here](https://github.com/dashnex/module-template/wiki/CLI-Commands)
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm install -D @dashnex/cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx dashnex <command> [options]
|
|
17
|
+
npx @dashnex/cli <command> [options]
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Commands
|
|
21
|
+
|
|
22
|
+
| Command | Description |
|
|
23
|
+
|---------|-------------|
|
|
24
|
+
| `version` | Display the version of the CLI |
|
|
25
|
+
| `login` | Log in to your DashNex account |
|
|
26
|
+
| `logout` | Log out and remove local credentials |
|
|
27
|
+
| `create` | Create a new DashNex application |
|
|
28
|
+
| `pull` | Pull existing application to current folder |
|
|
29
|
+
| `push` | Push local application to DashNex |
|
|
30
|
+
| `delete` | Delete application from DashNex |
|
|
31
|
+
| `whoami` | Show current logged-in business and user |
|
|
32
|
+
|
|
33
|
+
### Options
|
|
34
|
+
|
|
35
|
+
- **create**: `-t, --template <template>` — Template (name@branch-or-tag, default: webapp-base@live)
|
package/bin/dashnex
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import fs from "fs-extra";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import dotenv from "dotenv";
|
|
7
|
+
import packageJson from "./package.json.js";
|
|
8
|
+
const program = new Command();
|
|
9
|
+
const { name, version, description } = packageJson;
|
|
10
|
+
program.name(name).description(description).version(version);
|
|
11
|
+
function getModuleRoot(module, appDir) {
|
|
12
|
+
const appPackageJsonPath = path.join(appDir, "package.json");
|
|
13
|
+
if (fs.existsSync(appPackageJsonPath)) {
|
|
14
|
+
try {
|
|
15
|
+
const appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, "utf8"));
|
|
16
|
+
if (appPackageJson.name === module) {
|
|
17
|
+
return appDir;
|
|
18
|
+
}
|
|
19
|
+
} catch {
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return path.join(appDir, "node_modules", module);
|
|
23
|
+
}
|
|
24
|
+
async function discoverModuleCommands(module, appDir) {
|
|
25
|
+
const discoveredCommands = [];
|
|
26
|
+
try {
|
|
27
|
+
const moduleRoot = getModuleRoot(module, appDir);
|
|
28
|
+
const modulePath = path.join(moduleRoot, "dist", "commands", "index.js");
|
|
29
|
+
if (fs.existsSync(modulePath)) {
|
|
30
|
+
const module2 = await import(modulePath);
|
|
31
|
+
let moduleCommands = [];
|
|
32
|
+
if (module2.default) {
|
|
33
|
+
moduleCommands = Array.isArray(module2.default) ? module2.default : [];
|
|
34
|
+
} else if (module2.commands) {
|
|
35
|
+
moduleCommands = Array.isArray(module2.commands) ? module2.commands : [];
|
|
36
|
+
}
|
|
37
|
+
if (moduleCommands.length > 0) {
|
|
38
|
+
discoveredCommands.push(...moduleCommands);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (process.env.DEBUG) {
|
|
43
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
44
|
+
console.log(chalk.yellow(`Module ${module} has no commands or failed to load: ${errorMessage}`));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return discoveredCommands;
|
|
48
|
+
}
|
|
49
|
+
async function discoverDashnexModules(appDir) {
|
|
50
|
+
try {
|
|
51
|
+
const dashnexModules = [];
|
|
52
|
+
const seen = /* @__PURE__ */ new Set();
|
|
53
|
+
const addIfNew = (name2) => {
|
|
54
|
+
if (!seen.has(name2)) {
|
|
55
|
+
seen.add(name2);
|
|
56
|
+
dashnexModules.push(name2);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const appDashnexPath = path.join(appDir, "dashnex.json");
|
|
60
|
+
if (fs.existsSync(appDashnexPath)) {
|
|
61
|
+
const appPackageJsonPath2 = path.join(appDir, "package.json");
|
|
62
|
+
if (fs.existsSync(appPackageJsonPath2)) {
|
|
63
|
+
const appPackageJson2 = JSON.parse(fs.readFileSync(appPackageJsonPath2, "utf8"));
|
|
64
|
+
if (appPackageJson2.name) {
|
|
65
|
+
addIfNew(appPackageJson2.name);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const appPackageJsonPath = path.join(appDir, "package.json");
|
|
70
|
+
if (!fs.existsSync(appPackageJsonPath)) {
|
|
71
|
+
return dashnexModules;
|
|
72
|
+
}
|
|
73
|
+
const appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, "utf8"));
|
|
74
|
+
const allDependencies = {
|
|
75
|
+
...appPackageJson.dependencies,
|
|
76
|
+
...appPackageJson.devDependencies,
|
|
77
|
+
...appPackageJson.optionalDependencies
|
|
78
|
+
};
|
|
79
|
+
for (const [module] of Object.entries(allDependencies)) {
|
|
80
|
+
const moduleRoot = path.join(appDir, "node_modules", module);
|
|
81
|
+
if (fs.existsSync(path.join(moduleRoot, "dashnex.json"))) {
|
|
82
|
+
addIfNew(module);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return dashnexModules;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (process.env.DEBUG) {
|
|
88
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
89
|
+
console.log("⚠ Error reading app package.json:", errorMessage);
|
|
90
|
+
}
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function registerCommand(parentCommand, dashnexCommand, parentOptions = {}) {
|
|
95
|
+
const cmd = parentCommand.command(dashnexCommand.name).description(dashnexCommand.description);
|
|
96
|
+
if (dashnexCommand.options) {
|
|
97
|
+
dashnexCommand.options.forEach((option) => {
|
|
98
|
+
if (option.defaultValue !== void 0) {
|
|
99
|
+
if (typeof option.defaultValue === "number") {
|
|
100
|
+
cmd.option(option.flags, option.description, String(option.defaultValue));
|
|
101
|
+
} else {
|
|
102
|
+
cmd.option(option.flags, option.description, option.defaultValue);
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
cmd.option(option.flags, option.description);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (dashnexCommand.subcommands) {
|
|
110
|
+
dashnexCommand.subcommands.forEach((subcommand) => {
|
|
111
|
+
registerCommand(cmd, subcommand, { ...parentOptions, ...dashnexCommand.options });
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
cmd.action(async (options, actionCommand) => {
|
|
115
|
+
try {
|
|
116
|
+
const mergedOptions = { ...parentOptions, ...options };
|
|
117
|
+
await dashnexCommand.handler.execute(mergedOptions);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error(chalk.red(`❌ Command failed in ${dashnexCommand.name}:`), error);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
async function main() {
|
|
125
|
+
dotenv.config({ quiet: true });
|
|
126
|
+
process.env.DASHNEX_CLI = "1";
|
|
127
|
+
let appDir = process.cwd();
|
|
128
|
+
if (process.env.DEBUG) {
|
|
129
|
+
console.log(`CLI started from directory: ${appDir}`);
|
|
130
|
+
}
|
|
131
|
+
const moduleNames = await discoverDashnexModules(appDir);
|
|
132
|
+
if (process.env.DEBUG) {
|
|
133
|
+
console.log(`Discovered modules: ${moduleNames.join(", ")}`);
|
|
134
|
+
}
|
|
135
|
+
for (const moduleName of moduleNames) {
|
|
136
|
+
const moduleCommands = await discoverModuleCommands(moduleName, appDir);
|
|
137
|
+
for (const command of moduleCommands) {
|
|
138
|
+
registerCommand(program, command);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
const { default: applicationCommands } = await import(path.join(appDir, "dist", "commands", "index.js"));
|
|
143
|
+
if (applicationCommands && Array.isArray(applicationCommands)) {
|
|
144
|
+
for (const command of applicationCommands) {
|
|
145
|
+
registerCommand(program, command);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
} catch (error) {
|
|
149
|
+
if (process.env.DEBUG) {
|
|
150
|
+
console.error(chalk.yellow("⚠ Failed to discover application commands"));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
program.parse(process.argv);
|
|
154
|
+
if (!process.argv.slice(2).length) {
|
|
155
|
+
program.outputHelp();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
main().catch((error) => {
|
|
159
|
+
console.error(chalk.red("❌ CLI failed:"), error);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
});
|
|
162
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { CliCommandConfig, CliOption } from \"@dashnex/types\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport dotenv from \"dotenv\";\nimport packageJson from '../package.json' with { type: \"json\" };\n\nconst program = new Command();\n\nconst { name, version, description } = packageJson;\n\nprogram\n .name(name)\n .description(description)\n .version(version);\n\nfunction getModuleRoot(module: string, appDir: string): string {\n const appPackageJsonPath = path.join(appDir, \"package.json\");\n if (fs.existsSync(appPackageJsonPath)) {\n try {\n const appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, \"utf8\"));\n if (appPackageJson.name === module) {\n return appDir;\n }\n } catch {\n // ignore\n }\n }\n return path.join(appDir, \"node_modules\", module);\n}\n\nasync function discoverModuleCommands(module: string, appDir: string): Promise<CliCommandConfig[]> {\n\n const discoveredCommands: CliCommandConfig[] = [];\n\n try {\n const moduleRoot = getModuleRoot(module, appDir);\n const modulePath = path.join(moduleRoot, \"dist\", \"commands\", \"index.js\");\n\n if (fs.existsSync(modulePath)) {\n // Import from the full path\n const module = await import(modulePath);\n \n // Handle both named and default exports\n let moduleCommands: CliCommandConfig[] = [];\n \n if (module.default) {\n // Default export\n moduleCommands = Array.isArray(module.default) ? module.default : [];\n } else if (module.commands) {\n // Named export\n moduleCommands = Array.isArray(module.commands) ? module.commands : [];\n }\n \n if (moduleCommands.length > 0) {\n discoveredCommands.push(...moduleCommands);\n }\n }\n } catch (error) {\n // Module doesn't have commands or failed to load - this is expected for some modules\n if (process.env.DEBUG) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.log(chalk.yellow(`Module ${module} has no commands or failed to load: ${errorMessage}`));\n }\n }\n\n return discoveredCommands;\n}\n\n// Do it here, instead of importing from the core module to avoid circular dependencies\nasync function discoverDashnexModules(appDir: string): Promise<string[]> {\n try {\n const dashnexModules: string[] = [];\n const seen = new Set<string>();\n\n const addIfNew = (name: string) => {\n if (!seen.has(name)) {\n seen.add(name);\n dashnexModules.push(name);\n }\n };\n\n // Check if current directory is a dashnex module (running from module repo directly)\n const appDashnexPath = path.join(appDir, \"dashnex.json\");\n if (fs.existsSync(appDashnexPath)) {\n const appPackageJsonPath = path.join(appDir, \"package.json\");\n if (fs.existsSync(appPackageJsonPath)) {\n const appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, \"utf8\"));\n if (appPackageJson.name) {\n addIfNew(appPackageJson.name);\n }\n }\n }\n\n // Read the app's package.json to see which dashnex modules are installed in node_modules\n const appPackageJsonPath = path.join(appDir, \"package.json\");\n if (!fs.existsSync(appPackageJsonPath)) {\n return dashnexModules;\n }\n\n const appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, \"utf8\"));\n const allDependencies = {\n ...appPackageJson.dependencies,\n ...appPackageJson.devDependencies,\n ...appPackageJson.optionalDependencies\n };\n\n for (const [module] of Object.entries(allDependencies)) {\n const moduleRoot = path.join(appDir, \"node_modules\", module);\n if (fs.existsSync(path.join(moduleRoot, \"dashnex.json\"))) {\n addIfNew(module);\n }\n }\n\n return dashnexModules;\n } catch (error) {\n if (process.env.DEBUG) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.log(\"⚠ Error reading app package.json:\", errorMessage);\n }\n return [];\n }\n}\n\nfunction registerCommand(\n parentCommand: Command, \n dashnexCommand: CliCommandConfig, \n parentOptions: any = {}\n): void {\n const cmd = parentCommand\n .command(dashnexCommand.name)\n .description(dashnexCommand.description);\n\n // Add options if defined\n if (dashnexCommand.options) {\n dashnexCommand.options.forEach((option: CliOption) => {\n if (option.defaultValue !== undefined) {\n // Handle different types of default values\n if (typeof option.defaultValue === 'number') {\n cmd.option(option.flags, option.description, String(option.defaultValue));\n } else {\n cmd.option(option.flags, option.description, option.defaultValue as string | boolean);\n }\n } else {\n cmd.option(option.flags, option.description);\n }\n });\n }\n\n // Add subcommands if defined \n if (dashnexCommand.subcommands) {\n dashnexCommand.subcommands.forEach(subcommand => {\n registerCommand(cmd, subcommand, { ...parentOptions, ...dashnexCommand.options });\n });\n }\n\n // Register the command handler\n cmd.action(async (options, actionCommand) => {\n try {\n // Merge parent options with current command options\n const mergedOptions = { ...parentOptions, ...options };\n await dashnexCommand.handler.execute(mergedOptions);\n } catch (error) {\n console.error(chalk.red(`❌ Command failed in ${dashnexCommand.name}:`), error);\n process.exit(1);\n }\n });\n}\n\n// Main execution\nasync function main() {\n // Load environment variables from .env file\n dotenv.config({ quiet: true });\n\n process.env.DASHNEX_CLI = \"1\";\n \n // Find the app directory (where the CLI was called from) to ensure proper module resolution\n let appDir = process.cwd();\n \n if (process.env.DEBUG) {\n console.log(`CLI started from directory: ${appDir}`);\n }\n\n const moduleNames = await discoverDashnexModules(appDir);\n \n if (process.env.DEBUG) {\n console.log(`Discovered modules: ${moduleNames.join(', ')}`);\n }\n\n // Load the CLI commands from the dashnex modules\n for (const moduleName of moduleNames) {\n const moduleCommands = await discoverModuleCommands(moduleName, appDir);\n\n for (const command of moduleCommands) {\n registerCommand(program, command);\n }\n }\n\n // Load the CLI commands from the application\n try {\n const { default: applicationCommands } = await import(path.join(appDir, \"dist\", \"commands\", \"index.js\"));\n\n if (applicationCommands && Array.isArray(applicationCommands)) {\n for (const command of applicationCommands) {\n registerCommand(program, command);\n }\n }\n } catch (error) {\n if (process.env.DEBUG) {\n console.error(chalk.yellow(\"⚠ Failed to discover application commands\"));\n }\n }\n\n // Parse command line arguments\n program.parse(process.argv);\n\n // Show help if no command provided\n if (!process.argv.slice(2).length) {\n program.outputHelp();\n }\n}\n\n// Run the CLI\nmain().catch((error) => {\n console.error(chalk.red(\"❌ CLI failed:\"), error);\n process.exit(1);\n});\n"],"names":["module","name","appPackageJsonPath","appPackageJson"],"mappings":"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"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import packageJson from "./package.json.js";
|
|
2
|
+
import dashnexConfig from "./dashnex.json.js";
|
|
3
|
+
const client = {
|
|
4
|
+
name: packageJson.name,
|
|
5
|
+
version: packageJson.version,
|
|
6
|
+
description: packageJson.description,
|
|
7
|
+
...dashnexConfig
|
|
8
|
+
};
|
|
9
|
+
export {
|
|
10
|
+
client as default
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sources":["../src/client.ts"],"sourcesContent":["import { ModuleConfig } from '@dashnex/types';\n\nimport packageJson from '../package.json' with { type: \"json\" };\nimport dashnexConfig from '../dashnex.json' with { type: \"json\" };\n\nexport default {\n name: packageJson.name,\n version: packageJson.version,\n description: packageJson.description,\n ...dashnexConfig,\n} as ModuleConfig;"],"names":[],"mappings":";;AAKA,MAAA,SAAe;AAAA,EACX,MAAM,YAAY;AAAA,EAClB,SAAS,YAAY;AAAA,EACrB,aAAa,YAAY;AAAA,EACzB,GAAG;AACP;"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import inquirer from "inquirer";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { debug, debugError } from "../lib/debug.js";
|
|
4
|
+
import { getBusinessApiBase } from "../lib/api.js";
|
|
5
|
+
import { ensureLoggedIn } from "../services/auth.js";
|
|
6
|
+
const extractErrorMessage = (body) => {
|
|
7
|
+
if (Array.isArray(body.message) && body.message.length > 0) {
|
|
8
|
+
return body.message.join(" ");
|
|
9
|
+
}
|
|
10
|
+
if (typeof body.message === "string") return body.message;
|
|
11
|
+
if (typeof body.error === "string") return body.error;
|
|
12
|
+
return void 0;
|
|
13
|
+
};
|
|
14
|
+
const SUCCESS_MESSAGE = "Application is created successfully. Use 'npx dashnex pull' to pull it to your computer or 'npx dashnex deploy' to deploy it to the cloud.";
|
|
15
|
+
class CreateCommand {
|
|
16
|
+
async execute(options = {}) {
|
|
17
|
+
debug("Create flow started");
|
|
18
|
+
const session = await ensureLoggedIn();
|
|
19
|
+
if (!session) return;
|
|
20
|
+
debug("Auth valid, checking if business already has application");
|
|
21
|
+
const applicationsUrl = `${getBusinessApiBase()}/business/v1/applications`;
|
|
22
|
+
debug(`GET ${applicationsUrl}`);
|
|
23
|
+
try {
|
|
24
|
+
const appsResponse = await fetch(applicationsUrl, {
|
|
25
|
+
headers: { Authorization: `Bearer ${session.token}` }
|
|
26
|
+
});
|
|
27
|
+
debug(`Applications response: ${appsResponse.status}`);
|
|
28
|
+
if (appsResponse.status !== 404) {
|
|
29
|
+
console.error(
|
|
30
|
+
chalk.red(
|
|
31
|
+
"Business already has an application. Run 'npx dashnex pull' to pull the existing one."
|
|
32
|
+
)
|
|
33
|
+
);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
} catch (error) {
|
|
37
|
+
debugError(error);
|
|
38
|
+
if (error instanceof Error && error.message.startsWith("EXIT:")) throw error;
|
|
39
|
+
console.error(chalk.red("Could not reach DashNex API. Check your connection and try again."));
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
debug("No existing application, proceeding to subdomain prompt");
|
|
43
|
+
let subdomain;
|
|
44
|
+
const checkSubdomainUrl = (sub) => `${getBusinessApiBase()}/business/v1/applications/check-subdomain?subdomain=${encodeURIComponent(sub)}`;
|
|
45
|
+
while (true) {
|
|
46
|
+
const { sub } = await inquirer.prompt([
|
|
47
|
+
{
|
|
48
|
+
type: "input",
|
|
49
|
+
name: "sub",
|
|
50
|
+
message: "Pick your subdomain:",
|
|
51
|
+
validate: (input) => input.trim() ? true : "Subdomain is required"
|
|
52
|
+
}
|
|
53
|
+
]);
|
|
54
|
+
subdomain = sub.trim();
|
|
55
|
+
debug(`Checking subdomain: ${subdomain}`);
|
|
56
|
+
try {
|
|
57
|
+
const checkResponse = await fetch(checkSubdomainUrl(subdomain), {
|
|
58
|
+
headers: { Authorization: `Bearer ${session.token}` }
|
|
59
|
+
});
|
|
60
|
+
debug(`Check subdomain response: ${checkResponse.status}`);
|
|
61
|
+
if (!checkResponse.ok) {
|
|
62
|
+
const contentType = checkResponse.headers.get("content-type") ?? "";
|
|
63
|
+
let message = "Failed to check subdomain availability.";
|
|
64
|
+
if (checkResponse.status === 401 || checkResponse.status === 403) {
|
|
65
|
+
message = "Please run 'npx dashnex login' to authenticate.";
|
|
66
|
+
console.error(chalk.red(message));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
if (contentType.includes("application/json")) {
|
|
70
|
+
const body = await checkResponse.json().catch(() => ({}));
|
|
71
|
+
const apiMessage = extractErrorMessage(body);
|
|
72
|
+
if (apiMessage) message = apiMessage;
|
|
73
|
+
}
|
|
74
|
+
console.error(chalk.red(message));
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const checkBody = await checkResponse.json();
|
|
78
|
+
if (checkBody.available) {
|
|
79
|
+
debug(`Subdomain ${subdomain} is available`);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
console.error(chalk.red("Subdomain is not available. Please choose a different one."));
|
|
83
|
+
} catch (error) {
|
|
84
|
+
debugError(error);
|
|
85
|
+
if (error instanceof Error && error.message.startsWith("EXIT:")) throw error;
|
|
86
|
+
console.error(chalk.red("Could not reach DashNex API. Check your connection and try again."));
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const createUrl = `${getBusinessApiBase()}/business/v1/cli/create`;
|
|
91
|
+
debug(`POST ${createUrl}`);
|
|
92
|
+
const createBody = { subdomain };
|
|
93
|
+
if (options.template) {
|
|
94
|
+
createBody.template = options.template;
|
|
95
|
+
debug(`Template: ${options.template}`);
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
const createResponse = await fetch(createUrl, {
|
|
99
|
+
method: "POST",
|
|
100
|
+
headers: {
|
|
101
|
+
Authorization: `Bearer ${session.token}`,
|
|
102
|
+
"Content-Type": "application/json"
|
|
103
|
+
},
|
|
104
|
+
body: JSON.stringify(createBody)
|
|
105
|
+
});
|
|
106
|
+
debug(`Create response: ${createResponse.status}`);
|
|
107
|
+
if (!createResponse.ok) {
|
|
108
|
+
const contentType = createResponse.headers.get("content-type") ?? "";
|
|
109
|
+
let message = "Failed to create application.";
|
|
110
|
+
if (createResponse.status === 401 || createResponse.status === 403) {
|
|
111
|
+
message = "Please run 'npx dashnex login' to authenticate.";
|
|
112
|
+
} else if (contentType.includes("application/json")) {
|
|
113
|
+
const body = await createResponse.json().catch(() => ({}));
|
|
114
|
+
debug(`Create response body: ${JSON.stringify(body)}`);
|
|
115
|
+
const apiMessage = extractErrorMessage(body);
|
|
116
|
+
if (apiMessage) message = apiMessage;
|
|
117
|
+
}
|
|
118
|
+
console.error(chalk.red(message));
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
debug("Application created successfully");
|
|
122
|
+
console.log(chalk.green(SUCCESS_MESSAGE));
|
|
123
|
+
} catch (error) {
|
|
124
|
+
debugError(error);
|
|
125
|
+
if (error instanceof Error && error.message.startsWith("EXIT:")) throw error;
|
|
126
|
+
console.error(chalk.red("Could not reach DashNex API. Check your connection and try again."));
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
export {
|
|
132
|
+
CreateCommand
|
|
133
|
+
};
|
|
134
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.js","sources":["../../src/commands/create.ts"],"sourcesContent":["import inquirer from \"inquirer\";\nimport chalk from \"chalk\";\nimport type { CliCommand } from \"@dashnex/types\";\nimport { debug, debugError } from \"../lib/debug.js\";\nimport { getBusinessApiBase } from \"../lib/api.js\";\nimport { ensureLoggedIn } from \"../services/auth.js\";\n\nconst extractErrorMessage = (body: Record<string, unknown>): string | undefined => {\n if (Array.isArray(body.message) && body.message.length > 0) {\n return body.message.join(\" \");\n }\n if (typeof body.message === \"string\") return body.message;\n if (typeof body.error === \"string\") return body.error;\n return undefined;\n};\n\nconst SUCCESS_MESSAGE =\n \"Application is created successfully. Use 'npx dashnex pull' to pull it to your computer or 'npx dashnex deploy' to deploy it to the cloud.\";\n\nexport interface CreateCommandOptions {\n template?: string;\n}\n\nexport class CreateCommand implements CliCommand {\n async execute(options: CreateCommandOptions = {}): Promise<void> {\n debug(\"Create flow started\");\n\n const session = await ensureLoggedIn();\n if (!session) return;\n\n debug(\"Auth valid, checking if business already has application\");\n\n const applicationsUrl = `${getBusinessApiBase()}/business/v1/applications`;\n debug(`GET ${applicationsUrl}`);\n\n try {\n const appsResponse = await fetch(applicationsUrl, {\n headers: { Authorization: `Bearer ${session.token}` },\n });\n debug(`Applications response: ${appsResponse.status}`);\n\n if (appsResponse.status !== 404) {\n console.error(\n chalk.red(\n \"Business already has an application. Run 'npx dashnex pull' to pull the existing one.\"\n )\n );\n process.exit(1);\n }\n } catch (error) {\n debugError(error);\n if (error instanceof Error && error.message.startsWith(\"EXIT:\")) throw error;\n console.error(chalk.red(\"Could not reach DashNex API. Check your connection and try again.\"));\n process.exit(1);\n }\n\n debug(\"No existing application, proceeding to subdomain prompt\");\n\n let subdomain: string;\n const checkSubdomainUrl = (sub: string) =>\n `${getBusinessApiBase()}/business/v1/applications/check-subdomain?subdomain=${encodeURIComponent(sub)}`;\n\n while (true) {\n const { sub } = await inquirer.prompt<{ sub: string }>([\n {\n type: \"input\",\n name: \"sub\",\n message: \"Pick your subdomain:\",\n validate: (input: string) => (input.trim() ? true : \"Subdomain is required\"),\n },\n ]);\n\n subdomain = sub.trim();\n debug(`Checking subdomain: ${subdomain}`);\n\n try {\n const checkResponse = await fetch(checkSubdomainUrl(subdomain), {\n headers: { Authorization: `Bearer ${session.token}` },\n });\n debug(`Check subdomain response: ${checkResponse.status}`);\n\n if (!checkResponse.ok) {\n const contentType = checkResponse.headers.get(\"content-type\") ?? \"\";\n let message = \"Failed to check subdomain availability.\";\n if (checkResponse.status === 401 || checkResponse.status === 403) {\n message = \"Please run 'npx dashnex login' to authenticate.\";\n console.error(chalk.red(message));\n process.exit(1);\n }\n if (contentType.includes(\"application/json\")) {\n const body = (await checkResponse.json().catch(() => ({}))) as Record<string, unknown>;\n const apiMessage = extractErrorMessage(body);\n if (apiMessage) message = apiMessage;\n }\n console.error(chalk.red(message));\n continue;\n }\n\n const checkBody = (await checkResponse.json()) as { available?: boolean; subdomain?: string };\n if (checkBody.available) {\n debug(`Subdomain ${subdomain} is available`);\n break;\n }\n\n console.error(chalk.red(\"Subdomain is not available. Please choose a different one.\"));\n } catch (error) {\n debugError(error);\n if (error instanceof Error && error.message.startsWith(\"EXIT:\")) throw error;\n console.error(chalk.red(\"Could not reach DashNex API. Check your connection and try again.\"));\n process.exit(1);\n }\n }\n\n const createUrl = `${getBusinessApiBase()}/business/v1/cli/create`;\n debug(`POST ${createUrl}`);\n\n const createBody: Record<string, string> = { subdomain };\n if (options.template) {\n createBody.template = options.template;\n debug(`Template: ${options.template}`);\n }\n\n try {\n const createResponse = await fetch(createUrl, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${session.token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(createBody),\n });\n\n debug(`Create response: ${createResponse.status}`);\n\n if (!createResponse.ok) {\n const contentType = createResponse.headers.get(\"content-type\") ?? \"\";\n let message = \"Failed to create application.\";\n if (createResponse.status === 401 || createResponse.status === 403) {\n message = \"Please run 'npx dashnex login' to authenticate.\";\n } else if (contentType.includes(\"application/json\")) {\n const body = (await createResponse.json().catch(() => ({}))) as Record<string, unknown>;\n debug(`Create response body: ${JSON.stringify(body)}`);\n const apiMessage = extractErrorMessage(body);\n if (apiMessage) message = apiMessage;\n }\n console.error(chalk.red(message));\n process.exit(1);\n }\n\n debug(\"Application created successfully\");\n console.log(chalk.green(SUCCESS_MESSAGE));\n } catch (error) {\n debugError(error);\n if (error instanceof Error && error.message.startsWith(\"EXIT:\")) throw error;\n console.error(chalk.red(\"Could not reach DashNex API. Check your connection and try again.\"));\n process.exit(1);\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { debug, debugError } from "../lib/debug.js";
|
|
3
|
+
import { getBusinessApiBase } from "../lib/api.js";
|
|
4
|
+
import { ensureLoggedIn } from "../services/auth.js";
|
|
5
|
+
const extractErrorMessage = (body) => {
|
|
6
|
+
if (typeof body.error === "string") return body.error;
|
|
7
|
+
if (typeof body.message === "string") return body.message;
|
|
8
|
+
return void 0;
|
|
9
|
+
};
|
|
10
|
+
class DeleteCommand {
|
|
11
|
+
async execute() {
|
|
12
|
+
debug("Delete flow started");
|
|
13
|
+
const session = await ensureLoggedIn();
|
|
14
|
+
if (!session) return;
|
|
15
|
+
const url = `${getBusinessApiBase()}/business/v1/applications`;
|
|
16
|
+
debug(`DELETE ${url}`);
|
|
17
|
+
try {
|
|
18
|
+
const response = await fetch(url, {
|
|
19
|
+
method: "DELETE",
|
|
20
|
+
headers: { Authorization: `Bearer ${session.token}` }
|
|
21
|
+
});
|
|
22
|
+
debug(`Response: ${response.status}`);
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
25
|
+
let message = "Failed to delete application.";
|
|
26
|
+
if (response.status === 401 || response.status === 403) {
|
|
27
|
+
message = "Please run 'npx dashnex login' to authenticate.";
|
|
28
|
+
} else if (contentType.includes("application/json")) {
|
|
29
|
+
const body2 = await response.json().catch(() => ({}));
|
|
30
|
+
const apiMessage = extractErrorMessage(body2);
|
|
31
|
+
if (apiMessage) message = apiMessage;
|
|
32
|
+
}
|
|
33
|
+
console.error(chalk.red(message));
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
const body = await response.json().catch(() => ({}));
|
|
37
|
+
const successMessage = typeof body.message === "string" ? body.message : "Application deleted successfully.";
|
|
38
|
+
debug("Application deleted successfully");
|
|
39
|
+
console.log(chalk.green(successMessage));
|
|
40
|
+
} catch (error) {
|
|
41
|
+
debugError(error);
|
|
42
|
+
if (error instanceof Error && error.message.startsWith("EXIT:")) throw error;
|
|
43
|
+
console.error(chalk.red("Could not reach DashNex API. Check your connection and try again."));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
DeleteCommand
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=delete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.js","sources":["../../src/commands/delete.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport type { CliCommand } from \"@dashnex/types\";\nimport { debug, debugError } from \"../lib/debug.js\";\nimport { getBusinessApiBase } from \"../lib/api.js\";\nimport { ensureLoggedIn } from \"../services/auth.js\";\n\nconst extractErrorMessage = (body: Record<string, unknown>): string | undefined => {\n if (typeof body.error === \"string\") return body.error;\n if (typeof body.message === \"string\") return body.message;\n return undefined;\n};\n\nexport class DeleteCommand implements CliCommand {\n async execute(): Promise<void> {\n debug(\"Delete flow started\");\n\n const session = await ensureLoggedIn();\n if (!session) return;\n\n const url = `${getBusinessApiBase()}/business/v1/applications`;\n debug(`DELETE ${url}`);\n\n try {\n const response = await fetch(url, {\n method: \"DELETE\",\n headers: { Authorization: `Bearer ${session.token}` },\n });\n\n debug(`Response: ${response.status}`);\n\n if (!response.ok) {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n let message = \"Failed to delete application.\";\n if (response.status === 401 || response.status === 403) {\n message = \"Please run 'npx dashnex login' to authenticate.\";\n } else if (contentType.includes(\"application/json\")) {\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n const apiMessage = extractErrorMessage(body);\n if (apiMessage) message = apiMessage;\n }\n console.error(chalk.red(message));\n process.exit(1);\n }\n\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n const successMessage =\n typeof body.message === \"string\" ? body.message : \"Application deleted successfully.\";\n\n debug(\"Application deleted successfully\");\n console.log(chalk.green(successMessage));\n } catch (error) {\n debugError(error);\n if (error instanceof Error && error.message.startsWith(\"EXIT:\")) throw error;\n console.error(chalk.red(\"Could not reach DashNex API. Check your connection and try again.\"));\n process.exit(1);\n }\n }\n}\n"],"names":["body"],"mappings":";;;;AAMA,MAAM,sBAAsB,CAAC,SAAsD;AACjF,MAAI,OAAO,KAAK,UAAU,iBAAiB,KAAK;AAChD,MAAI,OAAO,KAAK,YAAY,iBAAiB,KAAK;AAClD,SAAO;AACT;AAEO,MAAM,cAAoC;AAAA,EAC/C,MAAM,UAAyB;AAC7B,UAAM,qBAAqB;AAE3B,UAAM,UAAU,MAAM,eAAA;AACtB,QAAI,CAAC,QAAS;AAEd,UAAM,MAAM,GAAG,mBAAA,CAAoB;AACnC,UAAM,UAAU,GAAG,EAAE;AAErB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QAChC,QAAQ;AAAA,QACR,SAAS,EAAE,eAAe,UAAU,QAAQ,KAAK,GAAA;AAAA,MAAG,CACrD;AAED,YAAM,aAAa,SAAS,MAAM,EAAE;AAEpC,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,YAAI,UAAU;AACd,YAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtD,oBAAU;AAAA,QACZ,WAAW,YAAY,SAAS,kBAAkB,GAAG;AACnD,gBAAMA,QAAQ,MAAM,SAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG;AACpD,gBAAM,aAAa,oBAAoBA,KAAI;AAC3C,cAAI,WAAY,WAAU;AAAA,QAC5B;AACA,gBAAQ,MAAM,MAAM,IAAI,OAAO,CAAC;AAChC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,OAAQ,MAAM,SAAS,KAAA,EAAO,MAAM,OAAO,CAAA,EAAG;AACpD,YAAM,iBACJ,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAEpD,YAAM,kCAAkC;AACxC,cAAQ,IAAI,MAAM,MAAM,cAAc,CAAC;AAAA,IACzC,SAAS,OAAO;AACd,iBAAW,KAAK;AAChB,UAAI,iBAAiB,SAAS,MAAM,QAAQ,WAAW,OAAO,EAAG,OAAM;AACvE,cAAQ,MAAM,MAAM,IAAI,mEAAmE,CAAC;AAC5F,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF;"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import VersionCommand from "./version.js";
|
|
2
|
+
import { LoginCommand } from "./login.js";
|
|
3
|
+
import { LogoutCommand } from "./logout.js";
|
|
4
|
+
import { CreateCommand } from "./create.js";
|
|
5
|
+
import { PullCommand } from "./pull.js";
|
|
6
|
+
import { PushCommand } from "./push.js";
|
|
7
|
+
import { DeleteCommand } from "./delete.js";
|
|
8
|
+
import { WhoamiCommand } from "./whoami.js";
|
|
9
|
+
const commands = [
|
|
10
|
+
{
|
|
11
|
+
name: "version",
|
|
12
|
+
description: "Display the version of the CLI",
|
|
13
|
+
handler: new VersionCommand(),
|
|
14
|
+
options: []
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "login",
|
|
18
|
+
description: "Log in to your DashNex account",
|
|
19
|
+
handler: new LoginCommand(),
|
|
20
|
+
options: []
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: "logout",
|
|
24
|
+
description: "Log out and remove local credentials",
|
|
25
|
+
handler: new LogoutCommand(),
|
|
26
|
+
options: []
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "create",
|
|
30
|
+
description: "Create a new DashNex application",
|
|
31
|
+
handler: new CreateCommand(),
|
|
32
|
+
options: [
|
|
33
|
+
{
|
|
34
|
+
flags: "-t, --template <template>",
|
|
35
|
+
description: "Template (name@branch-or-tag)",
|
|
36
|
+
defaultValue: "webapp-base@live"
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "pull",
|
|
42
|
+
description: "Pull existing application to current folder",
|
|
43
|
+
handler: new PullCommand(),
|
|
44
|
+
options: []
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "push",
|
|
48
|
+
description: "Push local application to DashNex",
|
|
49
|
+
handler: new PushCommand(),
|
|
50
|
+
options: []
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "delete",
|
|
54
|
+
description: "Delete application from DashNex",
|
|
55
|
+
handler: new DeleteCommand(),
|
|
56
|
+
options: []
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "whoami",
|
|
60
|
+
description: "Show current logged-in business and user",
|
|
61
|
+
handler: new WhoamiCommand(),
|
|
62
|
+
options: []
|
|
63
|
+
}
|
|
64
|
+
];
|
|
65
|
+
export {
|
|
66
|
+
commands as default
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/commands/index.ts"],"sourcesContent":["import { CliCommandConfig } from \"@dashnex/types\";\nimport VersionCommand from \"./version.js\";\nimport { LoginCommand } from \"./login.js\";\nimport { LogoutCommand } from \"./logout.js\";\nimport { CreateCommand } from \"./create.js\";\nimport { PullCommand } from \"./pull.js\";\nimport { PushCommand } from \"./push.js\";\nimport { DeleteCommand } from \"./delete.js\";\nimport { WhoamiCommand } from \"./whoami.js\";\n\nconst commands: CliCommandConfig[] = [\n {\n name: \"version\",\n description: \"Display the version of the CLI\",\n handler: new VersionCommand(),\n options: []\n },\n {\n name: \"login\",\n description: \"Log in to your DashNex account\",\n handler: new LoginCommand(),\n options: []\n },\n {\n name: \"logout\",\n description: \"Log out and remove local credentials\",\n handler: new LogoutCommand(),\n options: []\n },\n {\n name: \"create\",\n description: \"Create a new DashNex application\",\n handler: new CreateCommand(),\n options: [\n {\n flags: \"-t, --template <template>\",\n description: \"Template (name@branch-or-tag)\",\n defaultValue: \"webapp-base@live\",\n },\n ],\n },\n {\n name: \"pull\",\n description: \"Pull existing application to current folder\",\n handler: new PullCommand(),\n options: [],\n },\n {\n name: \"push\",\n description: \"Push local application to DashNex\",\n handler: new PushCommand(),\n options: [],\n },\n {\n name: \"delete\",\n description: \"Delete application from DashNex\",\n handler: new DeleteCommand(),\n options: [],\n },\n {\n name: \"whoami\",\n description: \"Show current logged-in business and user\",\n handler: new WhoamiCommand(),\n options: [],\n },\n];\n\nexport default commands;\n"],"names":[],"mappings":";;;;;;;;AAUA,MAAM,WAA+B;AAAA,EACnC;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,eAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,aAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,cAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,cAAA;AAAA,IACb,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,QACb,cAAc;AAAA,MAAA;AAAA,IAChB;AAAA,EACF;AAAA,EAEF;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,YAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,YAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,cAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS,IAAI,cAAA;AAAA,IACb,SAAS,CAAA;AAAA,EAAC;AAEd;"}
|