diff --git a/docker/named_pipe/nohup.out b/docker/named_pipe/nohup.out new file mode 100644 index 0000000..64bc166 --- /dev/null +++ b/docker/named_pipe/nohup.out @@ -0,0 +1,196 @@ +1000 +Deleting... news.domains.mdgspace.org +rm: cannot remove '/etc/nginx/sites-available/news.domains.mdgspace.org.conf': No such file or directory +rm: cannot remove '/etc/nginx/sites-enabled/news.domains.mdgspace.org.conf': No such file or directory +Error response from daemon: No such container: news.domains.mdgspace.org +Error response from daemon: No such container: news.domains.mdgspace.org +Error response from daemon: No such image: news.domains.mdgspace.org:latest +1000 +Creating subdomain news.domains.mdgspace.org which redirects to https://news.ycombinator.com/ +Generating url.conf +url: https://news.ycombinator.com/ +1000 +Creating subdomain github.domains.mdgspace.org which redirects to https://github.com/ +Generating url.conf +url: https://github.com/ +1000 +Deleting... github.domains.mdgspace.org +Error response from daemon: No such container: github.domains.mdgspace.org +Error response from daemon: No such container: github.domains.mdgspace.org +Error response from daemon: No such image: github.domains.mdgspace.org:latest +1000 +Deleting... nik-55.domains.mdgspace.org +Error response from daemon: No such container: nik-55.domains.mdgspace.org +Error response from daemon: No such container: nik-55.domains.mdgspace.org +Error response from daemon: No such image: nik-55.domains.mdgspace.org:latest +1000 +Creating subdomain kituuu.mdgspace.org.domains.mdgspace.org which redirects to https://your-personal-gallery.vercel.app/ +Generating url.conf +url: https://your-personal-gallery.vercel.app/ +1000 +Deleting... kituuu.mdgspace.org.domains.mdgspace.org +Error response from daemon: No such container: kituuu.mdgspace.org.domains.mdgspace.org +Error response from daemon: No such container: kituuu.mdgspace.org.domains.mdgspace.org +Error response from daemon: No such image: kituuu.mdgspace.org.domains.mdgspace.org:latest +1000 +Creating subdomain kituuu.domains.mdgspace.org which redirects to https://your-personal-gallery.vercel.app/ +Generating url.conf +url: https://your-personal-gallery.vercel.app/ +1000 +Deleting... kituuu.domains.mdgspace.org +Error response from daemon: No such container: kituuu.domains.mdgspace.org +Error response from daemon: No such container: kituuu.domains.mdgspace.org +Error response from daemon: No such image: kituuu.domains.mdgspace.org:latest +1000 +Creating subdomain google.domains.mdgspace.org which redirects to https://www.google.com/ +Generating url.conf +url: https://www.google.com/ +1000 +Creating subdomain nano-test.domains.mdgspace.org which redirects to https://nanonish.github.io/ +Generating url.conf +url: https://nanonish.github.io/ +1000 +Creating subdomain wiki.domains.mdgspace.org which redirects to https://www.wikipedia.org/ +Generating url.conf +url: https://www.wikipedia.org/ +1000 +Creating subdomain wiki.domains.mdgspace.org which redirects to https://www.wikipedia.org/ +Generating url.conf +url: https://www.wikipedia.org/ +1000 +Deleting... todo.domains.mdgspace.org +Error response from daemon: No such container: todo.domains.mdgspace.org +Error response from daemon: No such container: todo.domains.mdgspace.org +Error response from daemon: No such image: todo.domains.mdgspace.org:latest +1000 +Deleting... hey.domains.mdgspace.org +Error response from daemon: No such container: hey.domains.mdgspace.org +Error response from daemon: No such container: hey.domains.mdgspace.org +Error response from daemon: No such image: hey.domains.mdgspace.org:latest +Available ports: 8067 +Creating subdomain hey.domains.mdgspace.org +Cloning into 'hey.domains.mdgspace.org'... +#0 building with "default" instance using docker driver + +#1 [internal] load build definition from Dockerfile +#1 transferring dockerfile: 225B done +#1 DONE 0.0s + +#2 [internal] load metadata for docker.io/library/python:latest +#2 DONE 2.2s + +#3 [internal] load .dockerignore +#3 transferring context: 2B done +#3 DONE 0.0s + +#4 [1/5] FROM docker.io/library/python:latest@sha256:7859853e7607927aa1d1b1a5a2f9e580ac90c2b66feeb1b77da97fed03b1ccbe +#4 resolve docker.io/library/python:latest@sha256:7859853e7607927aa1d1b1a5a2f9e580ac90c2b66feeb1b77da97fed03b1ccbe 0.0s done +#4 sha256:2e66a70da0bec13fb3d492fcdef60fd8a5ef0a1a65c4e8a4909e26742852f0f2 0B / 64.15MB 0.1s +#4 sha256:7859853e7607927aa1d1b1a5a2f9e580ac90c2b66feeb1b77da97fed03b1ccbe 9.72kB / 9.72kB done +#4 sha256:ea2ebd905ab246ece277be25520ca0cfe82758b3d2b369e2fd69b374c1d6c7fa 5.86kB / 5.86kB done +#4 sha256:2e6afa3f266c11e8960349e7866203a9df478a50362bb5488c45fe39d99b2707 0B / 24.05MB 0.1s +#4 sha256:f6b1cea9aa1bba7fdf508248d1ab303a4cb11274997f39c9a0d6646f221379da 2.32kB / 2.32kB done +#4 sha256:8cd46d290033f265db57fd808ac81c444ec5a5b3f189c3d6d85043b647336913 0B / 49.56MB 0.1s +#4 CANCELED + +#5 [internal] load build context +#5 transferring context: 16.77MB 0.2s done +#5 DONE 0.3s + +#6 [2/5] WORKDIR /app +#6 CACHED + +#7 [3/5] COPY requirements.txt . +#7 ERROR: failed to calculate checksum of ref 44b139ae-3131-4796-9538-e5f44b9c0408::pe7dzgi8kpgbwg9fr8gsw1js8: "/requirements.txt": not found +------ + > [3/5] COPY requirements.txt .: +------ +Dockerfile:3 +-------------------- + 1 | FROM python:latest + 2 | WORKDIR /app + 3 | >>> COPY requirements.txt . + 4 | RUN pip install --no-cache-dir -r requirements.txt + 5 | COPY . . +-------------------- +ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref 44b139ae-3131-4796-9538-e5f44b9c0408::pe7dzgi8kpgbwg9fr8gsw1js8: "/requirements.txt": not found +Unable to find image 'hey.domains.mdgspace.org:latest' locally +docker: Error response from daemon: pull access denied for hey.domains.mdgspace.org, repository does not exist or may require 'docker login': denied: requested access to the resource is denied. +See 'docker run --help'. +Available ports: 8067 +Creating subdomain hy.domains.mdgspace.org +Cloning into 'hy.domains.mdgspace.org'... +#0 building with "default" instance using docker driver + +#1 [internal] load build definition from Dockerfile +#1 transferring dockerfile: 225B done +#1 DONE 0.0s + +#2 [internal] load metadata for docker.io/library/python:latest +#2 DONE 0.7s + +#3 [internal] load .dockerignore +#3 transferring context: 2B done +#3 DONE 0.0s + +#4 [1/5] FROM docker.io/library/python:latest@sha256:7859853e7607927aa1d1b1a5a2f9e580ac90c2b66feeb1b77da97fed03b1ccbe +#4 resolve docker.io/library/python:latest@sha256:7859853e7607927aa1d1b1a5a2f9e580ac90c2b66feeb1b77da97fed03b1ccbe 0.0s done +#4 sha256:f6b1cea9aa1bba7fdf508248d1ab303a4cb11274997f39c9a0d6646f221379da 2.32kB / 2.32kB done +#4 sha256:ea2ebd905ab246ece277be25520ca0cfe82758b3d2b369e2fd69b374c1d6c7fa 5.86kB / 5.86kB done +#4 sha256:2e6afa3f266c11e8960349e7866203a9df478a50362bb5488c45fe39d99b2707 0B / 24.05MB 0.1s +#4 sha256:7859853e7607927aa1d1b1a5a2f9e580ac90c2b66feeb1b77da97fed03b1ccbe 9.72kB / 9.72kB done +#4 sha256:8cd46d290033f265db57fd808ac81c444ec5a5b3f189c3d6d85043b647336913 0B / 49.56MB 0.1s +#4 sha256:2e66a70da0bec13fb3d492fcdef60fd8a5ef0a1a65c4e8a4909e26742852f0f2 0B / 64.15MB 0.1s +#4 ... + +#5 [internal] load build context +#5 transferring context: 16.77MB 0.1s done +#5 DONE 0.2s + +#6 [2/5] WORKDIR /app +#6 CACHED + +#7 [3/5] COPY requirements.txt . +#7 ERROR: failed to calculate checksum of ref 44b139ae-3131-4796-9538-e5f44b9c0408::w1g4h9pt6iyidbf3u91xq1fq9: "/requirements.txt": not found +------ + > [3/5] COPY requirements.txt .: +------ +Dockerfile:3 +-------------------- + 1 | FROM python:latest + 2 | WORKDIR /app + 3 | >>> COPY requirements.txt . + 4 | RUN pip install --no-cache-dir -r requirements.txt + 5 | COPY . . +-------------------- +ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref 44b139ae-3131-4796-9538-e5f44b9c0408::w1g4h9pt6iyidbf3u91xq1fq9: "/requirements.txt": not found +Unable to find image 'hy.domains.mdgspace.org:latest' locally +docker: Error response from daemon: pull access denied for hy.domains.mdgspace.org, repository does not exist or may require 'docker login': denied: requested access to the resource is denied. +See 'docker run --help'. +1000 +Creating subdomain alpha.domains.mdgspace.org which redirects to https://github.com +Generating url.conf +url: https://github.com +1000 +Creating subdomain raj.domains.mdgspace.org which redirects to https://github.com/raj210809 +Generating url.conf +url: https://github.com/raj210809 +1000 +Deleting... tola.domains.mdgspace.org +Error response from daemon: No such container: tola.domains.mdgspace.org +Error response from daemon: No such container: tola.domains.mdgspace.org +Error response from daemon: No such image: tola.domains.mdgspace.org:latest +1000 +Creating subdomain toka.domains.mdgspace.org which redirects to https://github.com/amsorrytola +Generating url.conf +url: https://github.com/amsorrytola +1000 +Deleting... toka.domains.mdgspace.org +Error response from daemon: No such container: toka.domains.mdgspace.org +Error response from daemon: No such container: toka.domains.mdgspace.org +Error response from daemon: No such image: toka.domains.mdgspace.org:latest +1000 +Deleting... tola.domains.mdgspace.org +Error response from daemon: No such container: tola.domains.mdgspace.org +Error response from daemon: No such container: tola.domains.mdgspace.org +Error response from daemon: No such image: tola.domains.mdgspace.org:latest diff --git a/src/backend/auth/github.ts b/src/backend/auth/github.ts index 6044a97..6016eac 100644 --- a/src/backend/auth/github.ts +++ b/src/backend/auth/github.ts @@ -1,6 +1,7 @@ import { Context, Sentry } from "../dependencies.ts"; import { checkUser } from "../db.ts"; import { checkJWT, createJWT } from "../utils/jwt.ts"; +import { generateApiKey } from "../utils/apiKeyGen.ts"; async function githubAuth(ctx: Context, id: string, secret: string) { await authenticateAndCreateJWT(ctx, id, secret, "github"); @@ -94,7 +95,9 @@ async function handleJwtAuthentication(ctx: Context) { } const jwt_token = document.jwt_token; const provider = document.provider; - ctx.response.body = await checkJWT(provider, jwt_token); + const user = await checkJWT(provider, jwt_token); + const apiKey = generateApiKey(user) + ctx.response.body = {user , apiKey}; } export { githubAuth, gitlabAuth, handleJwtAuthentication }; diff --git a/src/backend/dependencies.ts b/src/backend/dependencies.ts index 3bf13fa..9a51434 100644 --- a/src/backend/dependencies.ts +++ b/src/backend/dependencies.ts @@ -8,7 +8,7 @@ import { import { Session } from "https://deno.land/x/oak_sessions@v4.1.9/mod.ts"; import { create, verify } from "https://deno.land/x/djwt@v2.9.1/mod.ts"; import { exec } from "https://deno.land/x/exec@0.0.5/mod.ts"; -import * as Sentry from "npm:@sentry/node"; +import * as Sentry from 'https://deno.land/x/sentry/index.mjs'; import { oakCors } from "https://deno.land/x/cors@v1.2.2/mod.ts"; export { diff --git a/src/backend/server.ts b/src/backend/server.ts index ccbd303..1805ba2 100644 --- a/src/backend/server.ts +++ b/src/backend/server.ts @@ -28,9 +28,6 @@ const frontend: string = Deno.env.get("FRONTEND")!; Sentry.init({ dsn: dsn, - integrations: [ - new Sentry.Integrations.Http({ tracing: true }), - ], debug: true, tracesSampleRate: 1.0, }); diff --git a/src/backend/utils/apiKeyGen.ts b/src/backend/utils/apiKeyGen.ts new file mode 100644 index 0000000..725f880 --- /dev/null +++ b/src/backend/utils/apiKeyGen.ts @@ -0,0 +1,35 @@ + +function encodePayload(payload: string): string { + const encoded = btoa(payload); // Convert payload to Base64 + return encoded; +} + +function generateRandomString(length: number): string { + const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let result = ""; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * characters.length)); + } + return result; +} + + +function getSimpleDateString(): string { + const now = new Date(); + const year = now.getFullYear(); + const month = String(now.getMonth() + 1).padStart(2, '0'); + const day = String(now.getDate()).padStart(2, '0'); + return `${year}${month}${day}`; +} + +function generateRandomPart(): string { + return generateRandomString(16); +} + +export function generateApiKey(payload: string): string { + const datePart = getSimpleDateString(); + const encodedPayload = encodePayload(payload); + const randomPart = generateRandomPart(); + const apiKey = `${datePart}.${encodedPayload}.${randomPart}`; + return apiKey; +} diff --git a/src/backend/utils/jwt.ts b/src/backend/utils/jwt.ts index 34e2779..df4607b 100644 --- a/src/backend/utils/jwt.ts +++ b/src/backend/utils/jwt.ts @@ -13,10 +13,30 @@ async function createJWT(provider: string, githubId: string) { return token; } +function decodePayload(encodedPayload: string): string { + const decoded = atob(encodedPayload); + return decoded; +} + +function decodeApiKey(apiKey: string) { + const parts = apiKey.split("."); + if (parts.length !== 3) { + return "not verified"; + } + + const [datePart, encodedPayload, randomPart] = parts; + const decodedPayload = decodePayload(encodedPayload); + return decodedPayload +} + async function checkJWT(provider: string, token: string) { try { - const payload = await verify(token, key); - return payload[`${provider}Id`]!; + if (provider === "CLI"){ + return decodeApiKey(token) + } else { + const payload = await verify(token, key); + return payload[`${provider}Id`]!; + } } catch (error) { return "not verified"; } diff --git a/src/cli/features/authUser.ts b/src/cli/features/authUser.ts new file mode 100644 index 0000000..a97bd21 --- /dev/null +++ b/src/cli/features/authUser.ts @@ -0,0 +1,15 @@ +import axios from 'axios'; +import chalk from 'chalk'; + +export async function verifyApiKey(apiKey: string, provider: string , backendUrl : string) { + try { + const response = await axios.post(`${backendUrl}/auth/jwt`, { + jwt_token: apiKey, + provider: provider, + }); + return response.data; + } catch (error) { + console.error(chalk.red('Error verifying API key:')); + return 'not verified'; + } + } \ No newline at end of file diff --git a/src/cli/features/createDomain.ts b/src/cli/features/createDomain.ts new file mode 100644 index 0000000..1fec2f4 --- /dev/null +++ b/src/cli/features/createDomain.ts @@ -0,0 +1,94 @@ +import axios from "axios" +import chalk from 'chalk' +import inquirer from 'inquirer' +import { promptUser } from '../utils/promptTaker.js'; + +let domain = 'domains.mdgspace.org'; + +async function selectResourceType() { + const { resourceType } = await inquirer.prompt([ + { + type: 'list', + name: 'resourceType', + message: 'Select the resource type:', + choices: ['URL', 'PORT', 'GITHUB'], + }, + ]); + return resourceType; + } + async function selectDockerPresent() { + const { resourceType } = await inquirer.prompt([ + { + type: 'list', + name: 'resourceType', + message: 'Is Dockerfile present?', + choices: ['No', 'Yes'], + }, + ]); + return resourceType; + } + + + async function selectStack() { + const { Stack } = await inquirer.prompt([ + { + type: 'list', + name: 'Stack', // Must match the key you destructure + message: 'Select the tech stack:', + choices: ['Python', 'NodeJS'], + }, + ]); + return Stack; + } + +export async function createDomain(userApiKey : string, user : string , provider : string , backendUrl : string) { + let subdomain : string = ''; + let resourceType : string = ''; + let resource : string= ''; + let envContent : string = ''; + let staticContent : string = ''; + let dockerfilePresent : string = ""; + let port : string = ''; + let stack : string = ''; + let buildCmds : string = ''; + + subdomain = await promptUser('Enter subdomain (subdomain.domains.mdgspace.org):'); + resourceType = await selectResourceType(); + resource = await promptUser('Enter resource:'); + + if (resourceType === 'GitHub') { + envContent = await promptUser('Enter environment content:'); + staticContent = await promptUser('Enter static content:'); + dockerfilePresent =await selectDockerPresent(); + port = await promptUser('Enter port:'); + stack = await promptUser('Enter stack (NodeJS/Python):'); + buildCmds = await promptUser('Enter build commands:'); + } + + const payload = { + subdomain: `${subdomain}.${domain}`, + resource_type: resourceType, + resource, + env_content: envContent, + static_content: staticContent, + dockerfile_present: dockerfilePresent, + port, + build_cmds: buildCmds, + stack, + author: user, + date: new Date().toLocaleDateString(), + token: userApiKey, + provider, + }; + try { + const response = await axios.post(`${backendUrl}/map`, payload); + if (response.data.status === 'success') { + console.log(`✅ Domain '${subdomain}.${domain}' created successfully!`); + } else { + console.log('❌ Domain creation failed!'); + console.log("Either the domain exist or the domain is not created"); + } + } catch (error) { + console.error(chalk.red('Error creating domain:')); + } +} \ No newline at end of file diff --git a/src/cli/features/deleteDomain.ts b/src/cli/features/deleteDomain.ts new file mode 100644 index 0000000..1221428 --- /dev/null +++ b/src/cli/features/deleteDomain.ts @@ -0,0 +1,25 @@ +const axios = require('axios'); +const chalk = require('chalk'); +import { promptUser } from '../utils/promptTaker.js'; +import { listDomains } from './listDomain.js'; + +export async function deleteDomain(userApiKey : string, user : string, provider : string , backendUrl : string) { + await listDomains(userApiKey, user, provider, backendUrl); + const domain = await promptUser('Enter domain name to delete:'); + try { + const response = await axios.post(`${backendUrl}/mapdel`, { + author: user, + token: userApiKey, + provider, + subdomain: domain, + }) + if (response.data.deletedCount === 1) { + console.log(`✅ Domain '${domain}' deleted successfully!`); + } + else { + console.log('❌ Domain deletion failed!'); + } + } catch (error) { + console.error(chalk.red('Error deleting domain:')); + } + } \ No newline at end of file diff --git a/src/cli/features/listDomain.ts b/src/cli/features/listDomain.ts new file mode 100644 index 0000000..6cba305 --- /dev/null +++ b/src/cli/features/listDomain.ts @@ -0,0 +1,45 @@ +import axios from 'axios'; +import chalk from 'chalk'; +import table from 'cli-table3'; + +interface domain { + _id: string, + date: string, + subdomain: string, + resource_type: string, + resource: string, + author: string, +} + +export async function listDomains(user : string , userApiKey : string, provider : string , backendUrl : string) { + try { + const response = await axios.get( + `${backendUrl}/map?user=${user}&token=${userApiKey}&provider=${provider}` + ); + const data = response.data; + + if (!data.length) { + console.log(chalk.yellow('No domains found!')); + return; + } + + const domainTable = new table({ + head: ['Date', 'Sub-Domain', 'Resource Type', 'Resource'], + colWidths: [15, 30, 15, 40], // Adjust column widths as needed + }); + + data.forEach((domain : domain) => { + domainTable.push([ + chalk.green(domain.date), + chalk.blue(domain.subdomain), + chalk.cyan(domain.resource_type), + chalk.magenta(domain.resource), + ]); + }); + + console.log(domainTable.toString()); // Display the table + + } catch (error) { + console.error(chalk.red('Error fetching domains:')); + } + } \ No newline at end of file diff --git a/src/cli/index.ts b/src/cli/index.ts new file mode 100644 index 0000000..46c7f94 --- /dev/null +++ b/src/cli/index.ts @@ -0,0 +1,87 @@ +#!/usr/bin/env node +import inquirer from 'inquirer'; +import dotenv from 'dotenv'; +import axios from 'axios'; +import chalk from 'chalk'; +import { Command } from 'commander'; +import { listDomains } from './features/listDomain.js'; +import { createDomain } from './features/createDomain.js'; +import { deleteDomain } from './features/deleteDomain.js'; +import { verifyApiKey } from './features/authUser.js'; + +dotenv.config(); + +const program = new Command(); + +let userApiKey = ''; +let user = ''; +let backendUrl = ''; +const provider = 'github'; + + +program + .name('domainforge') + .description('A CLI tool to manage domains') + .option('--backend ', 'Set the backend URL') + .option('--token ', 'Provide user API token') + .helpOption('-h, --help', 'Display help for command') + .action(async (options) => { + if (options.token && options.backend) { + userApiKey = await options.token; + backendUrl = await options.backend; + user = await verifyApiKey(userApiKey , provider , backendUrl); + console.log(user); + if (user === 'not verified') { + console.error('❌ Invalid API key! Please try again.'); + process.exit(1); + } else { + console.log('✅ API key verified!'); + } + await showOptions(); // Show options if the API key is valid + } else { + console.error('❌ Please provide a valid token using --token.'); + process.exit(1); + } + }); + +program.parse(process.argv); + +async function showOptions() { + const { option } = await inquirer.prompt({ + type: 'list', + name: 'option', + message: 'What would you like to do?', + choices: [ + { name: 'List all domains', value: 'list' }, + { name: 'Create a new domain', value: 'create' }, + { name: 'Delete a domain', value: 'delete' }, + { name: 'Exit', value: 'exit' }, + ], + }); + + switch (option) { + case 'create': + await createDomain(userApiKey, user, provider , backendUrl); + break; + case 'delete': + await deleteDomain(userApiKey, user, provider , backendUrl); + break; + case 'list': + await listDomains(user, userApiKey, provider , backendUrl); + break; + case 'exit': + console.log('Goodbye!'); + process.exit(0); + } + await showOptions(); +} + +process.on('SIGINT', () => { + console.log('Goodbye!'); + process.exit(0); +}); + +process.on('unhandledRejection', () => { + console.log('Goodbye - forced exit'); + process.exit(1); +}) diff --git a/src/cli/package-lock.json b/src/cli/package-lock.json new file mode 100644 index 0000000..dec4d88 --- /dev/null +++ b/src/cli/package-lock.json @@ -0,0 +1,837 @@ +{ + "name": "domainforge-cli", + "version": "1.0.2", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "domainforge-cli", + "version": "1.0.2", + "license": "ISC", + "dependencies": { + "axios": "^1.7.7", + "chalk": "^4.1.2", + "cli-table3": "^0.6.5", + "commander": "^12.1.0", + "dotenv": "^16.4.5", + "inquirer": "^12.0.1", + "node-fetch": "^3.3.2" + }, + "bin": { + "domainforge": "dist/index.js" + }, + "devDependencies": { + "@types/node": "^22.8.1", + "typescript": "^5.6.3" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@inquirer/checkbox": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.0.1.tgz", + "integrity": "sha512-ehJjmNPdguajc1hStvjN7DJNVjwG5LC1mgGMGFjCmdkn2fxB2GtULftMnlaqNmvMdPpqdaSoOFpl86VkLtG4pQ==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.0.1", + "@inquirer/figures": "^1.0.7", + "@inquirer/type": "^3.0.0", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.0.1.tgz", + "integrity": "sha512-6ycMm7k7NUApiMGfVc32yIPp28iPKxhGRMqoNDiUjq2RyTAkbs5Fx0TdzBqhabcKvniDdAAvHCmsRjnNfTsogw==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.0.1", + "@inquirer/type": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.0.1.tgz", + "integrity": "sha512-KKTgjViBQUi3AAssqjUFMnMO3CM3qwCHvePV9EW+zTKGKafFGFF01sc1yOIYjLJ7QU52G/FbzKc+c01WLzXmVQ==", + "license": "MIT", + "dependencies": { + "@inquirer/figures": "^1.0.7", + "@inquirer/type": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/editor": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.0.1.tgz", + "integrity": "sha512-qAHHJ6hs343eNtCKgV2wV5CImFxYG8J1pl/YCeI5w9VoW7QpulRUU26+4NsMhjR6zDRjKBsH/rRjCIcaAOHsrg==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.0.1", + "@inquirer/type": "^3.0.0", + "external-editor": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/expand": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.1.tgz", + "integrity": "sha512-9anjpdc802YInXekwePsa5LWySzVMHbhVS6v6n5IJxrl8w09mODOeP69wZ1d0WrOvot2buQSmYp4lW/pq8y+zQ==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.0.1", + "@inquirer/type": "^3.0.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.7.tgz", + "integrity": "sha512-m+Trk77mp54Zma6xLkLuY+mvanPxlE4A7yNKs2HBiyZ4UkVs28Mv5c/pgWrHeInx+USHeX/WEPzjrWrcJiQgjw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.0.1.tgz", + "integrity": "sha512-m+SliZ2m43cDRIpAdQxfv5QOeAQCuhS8TGLvtzEP1An4IH1kBES4RLMRgE/fC+z29aN8qYG8Tq/eXQQKTYwqAg==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.0.1", + "@inquirer/type": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/number": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.1.tgz", + "integrity": "sha512-gF3erqfm0snpwBjbyKXUUe17QJ7ebm49btXApajrM0rgCCoYX0o9W5NCuYNae87iPxaIJVjtuoQ42DX32IdbMA==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.0.1", + "@inquirer/type": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/password": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.1.tgz", + "integrity": "sha512-D7zUuX4l4ZpL3D7/SWu9ibijP09jigwHi/gfUHLx5GMS5oXzuMfPV2xPMG1tskco4enTx70HA0VtMXecerpvbg==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.0.1", + "@inquirer/type": "^3.0.0", + "ansi-escapes": "^4.3.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/prompts": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.0.1.tgz", + "integrity": "sha512-cu2CpGC2hz7WTt2VBvdkzahDvYice6vYA/8Dm7Fy3tRNzKuQTF2EY3CV4H2GamveWE6tA2XzyXtbWX8+t4WMQg==", + "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^4.0.1", + "@inquirer/confirm": "^5.0.1", + "@inquirer/editor": "^4.0.1", + "@inquirer/expand": "^4.0.1", + "@inquirer/input": "^4.0.1", + "@inquirer/number": "^3.0.1", + "@inquirer/password": "^4.0.1", + "@inquirer/rawlist": "^4.0.1", + "@inquirer/search": "^3.0.1", + "@inquirer/select": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/rawlist": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.0.1.tgz", + "integrity": "sha512-0LuMOgaWs7W8JNcbiKkoFwyWFDEeCmLqDCygF0hidQUVa6J5grFVRZxrpompiWDFM49Km2rf7WoZwRo1uf1yWQ==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.0.1", + "@inquirer/type": "^3.0.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/search": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.1.tgz", + "integrity": "sha512-ehMqjiO0pAf+KtdONKeCLVy4i3fy3feyRRhDrvzWhiwB8JccgKn7eHFr39l+Nx/FaZAhr0YxIJvkK5NuNvG+Ww==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.0.1", + "@inquirer/figures": "^1.0.7", + "@inquirer/type": "^3.0.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/select": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.0.1.tgz", + "integrity": "sha512-tVRatFRGU49bxFCKi/3P+C0E13KZduNFbWuHWRx0L2+jbiyKRpXgHp9qiRHWRk/KarhYBXzH/di6w3VQ5aJd5w==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.0.1", + "@inquirer/figures": "^1.0.7", + "@inquirer/type": "^3.0.0", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.0.tgz", + "integrity": "sha512-YYykfbw/lefC7yKj7nanzQXILM7r3suIvyFlCcMskc99axmsSewXWkAfXKwMbgxL76iAFVmRwmYdwNZNc8gjog==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@types/node": { + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "license": "MIT" + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.0.1.tgz", + "integrity": "sha512-o11Jc2Go6wDZA17SWofiJ6L8k7mB8lsdKB/QY0bI+8e+ATiAvQzmROjqoTd1iAY8RI6N/EDcQcxbQa4JYviDWg==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.0.1", + "@inquirer/prompts": "^7.0.1", + "@inquirer/type": "^3.0.0", + "ansi-escapes": "^4.3.2", + "mute-stream": "^2.0.0", + "run-async": "^3.0.0", + "rxjs": "^7.8.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/src/cli/package.json b/src/cli/package.json new file mode 100644 index 0000000..993ebfb --- /dev/null +++ b/src/cli/package.json @@ -0,0 +1,34 @@ +{ + "name": "domainforge-cli", + "version": "1.0.6", + "main": "dist/index.js", + "type": "commonjs", + "scripts": { + "build": "tsc", + "start": "node dist/index.js" + }, + "bin": { + "domainforge": "./dist/index.js" + }, + "keywords": [ + "CLI", + "DomainForge", + "domains" + ], + "author": ".mdgspace", + "license": "ISC", + "description": "It's a CLI tool to host or manage subdomains associated by the domainforge API", + "dependencies": { + "axios": "^1.7.7", + "chalk": "^4.1.2", + "cli-table3": "^0.6.5", + "commander": "^12.1.0", + "dotenv": "^16.4.5", + "inquirer": "^12.0.1", + "node-fetch": "^3.3.2" + }, + "devDependencies": { + "@types/node": "^22.8.1", + "typescript": "^5.6.3" + } +} diff --git a/src/cli/tsconfig.json b/src/cli/tsconfig.json new file mode 100644 index 0000000..a8bbb8d --- /dev/null +++ b/src/cli/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "outDir": "./dist", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["./**/*.ts"], // Includes all .ts files in the project. + "exclude": ["./node_modules", "./dist"] // Exclude unnecessary folders. + } \ No newline at end of file diff --git a/src/cli/utils/promptTaker.ts b/src/cli/utils/promptTaker.ts new file mode 100644 index 0000000..cb31d9b --- /dev/null +++ b/src/cli/utils/promptTaker.ts @@ -0,0 +1,25 @@ +import inquirer from 'inquirer'; + +function secureInput(input : string) { + const blockedPhrases = [ + ';', '&', '|', '&&', '||', '>', '>>', '<', '<<', '$', '(', ')', '{', '}', + '`', '"', '!', '~', '*', '?', '[', ']', '#', '%', '+', 'curl', 'wget', 'rm', + 'tail', 'cat', 'grep', 'nc', 'xxd', 'apt', 'echo', 'pwd', 'ping', 'more', + 'tail', 'usermod', 'bash', 'sudo', ',', + ]; + return !blockedPhrases.some((phrase) => input.includes(phrase)); + } + + export async function promptUser(question : string) { + const { userInput } = await inquirer.prompt({ + type: 'input', + name: 'userInput', + message: question, + }); + + if (!secureInput(userInput)) { + console.error('Invalid input detected! Please try again.'); + return promptUser(question); // Retry if input is invalid + } + return userInput; + } \ No newline at end of file diff --git a/src/frontend/src/components/ApiKeyModal.vue b/src/frontend/src/components/ApiKeyModal.vue new file mode 100644 index 0000000..72bd72d --- /dev/null +++ b/src/frontend/src/components/ApiKeyModal.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/src/frontend/src/components/Home.vue b/src/frontend/src/components/Home.vue index b9ebffe..0944796 100644 --- a/src/frontend/src/components/Home.vue +++ b/src/frontend/src/components/Home.vue @@ -1,9 +1,14 @@ @@ -18,6 +23,9 @@ const maps = await getMaps(user);