Implemented count feature

This commit is contained in:
Space-Banane
2026-03-18 16:33:03 +01:00
parent fdcf3d06e0
commit 9aec36d0e8
8 changed files with 305 additions and 6 deletions
+8 -2
View File
@@ -74,12 +74,18 @@ jobs:
with: with:
name: dist-artifact name: dist-artifact
- name: Get version from package.json
id: package_version
run: |
pkg_version=$(node -p "require('./package.json').version")
echo "VERSION=$pkg_version" >> $GITHUB_OUTPUT
- name: Create Release - name: Create Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
with: with:
files: dist.zip files: dist.zip
tag_name: v${{ github.run_number }} tag_name: v${{ steps.package_version.outputs.VERSION }}
name: Release v${{ github.run_number }} name: Release v${{ steps.package_version.outputs.VERSION }}
draft: false draft: false
prerelease: false prerelease: false
env: env:
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "shsf-cli", "name": "shsf-cli",
"version": "2.0.1", "version": "2.0.2",
"description": "", "description": "",
"type": "module", "type": "module",
"files": [ "files": [
+14 -3
View File
@@ -55,10 +55,21 @@ export async function resolveCommands() {
const definition = module.default || Object.values(module).find((val: any) => val && val.name && val.action); const definition = module.default || Object.values(module).find((val: any) => val && val.name && val.action);
if (definition && definition.name && definition.action) { if (definition && definition.name && definition.action) {
currentParent const command = currentParent
.command(definition.name) .command(definition.name)
.description(definition.description || '') .description(definition.description || '');
.action(definition.action);
if (definition.options) {
definition.options.forEach((opt: any) => {
if (opt.required) {
command.requiredOption(opt.name, opt.description);
} else {
command.option(opt.name, opt.description);
}
});
}
command.action(definition.action);
} }
} }
} }
+59
View File
@@ -0,0 +1,59 @@
import chalk from "chalk";
import { getApiClient } from "../../api.js";
export const functionsCountDefinition = {
name: "functions",
description: "Counts the amount of functions the current user has.",
action: async () => {
await countFunctions();
},
};
async function countFunctions() {
const client = await getApiClient();
try {
const response = await client.get("/api/functions");
if (response.status === 200 && response.data.data) {
const functions = response.data.data;
const count = functions.length;
if (count > 0) {
console.log(chalk.blue("Functions List:"));
functions.forEach((f: any) => {
const namespaceInfo = f.namespace ? chalk.gray(` [NS: ${f.namespace.id}]`) : "";
console.log(`- ${chalk.cyan(f.name)} ${chalk.gray(`(${f.id})`)}${namespaceInfo}`);
if (f.description) {
console.log(` ${chalk.italic.gray(f.description)}`);
}
});
console.log("");
}
console.log(
`${chalk.green("✓")} You have ${chalk.bgGreen.black(` ${count} `)} functions.`,
);
} else {
console.log(
`${chalk.yellow("!")} Unexpected response from server.`,
);
console.log(`Status Code: ${chalk.blue(response.status)}`);
}
} catch (error: any) {
if (error.response) {
console.error(
`${chalk.red("✗")} Failed to fetch function count.`,
);
console.error(`Status Code: ${chalk.red(error.response.status)}`);
console.error(
`Message: ${chalk.yellow(error.response.data.message || "Unknown error from server")}`,
);
} else {
console.error(
`${chalk.red("✗")} Local error occurred.`,
);
console.error(`Error: ${chalk.yellow(error.message)}`);
}
}
}
+54
View File
@@ -0,0 +1,54 @@
import chalk from "chalk";
import { getApiClient } from "../../api.js";
export const namespacesCountDefinition = {
name: "namespaces",
description: "Counts the amount of namespaces the current user has.",
action: async () => {
await countNamespaces();
},
};
async function countNamespaces() {
const client = await getApiClient();
try {
const response = await client.get("/api/namespaces");
if (response.status === 200 && response.data.data) {
const namespaces = response.data.data;
const count = namespaces.length;
if (count > 0) {
console.log(chalk.blue("Namespaces List:"));
namespaces.forEach((ns: any) => {
console.log(`- ${chalk.cyan(ns.name)} ${chalk.gray(`(${ns.id})`)}`);
});
console.log("");
}
console.log(
`${chalk.green("✓")} You have ${chalk.bgGreen.black(` ${count} `)} namespaces.`,
);
} else {
console.log(
`${chalk.yellow("!")} Unexpected response from server.`,
);
console.log(`Status Code: ${chalk.blue(response.status)}`);
}
} catch (error: any) {
if (error.response) {
console.error(
`${chalk.red("✗")} Failed to fetch namespace count.`,
);
console.error(`Status Code: ${chalk.red(error.response.status)}`);
console.error(
`Message: ${chalk.yellow(error.response.data.message || "Unknown error from server")}`,
);
} else if (error.request) {
console.error(`${chalk.red("✗")} No response received from server.`);
} else {
console.error(`${chalk.red("✗")} Error:`, error.message);
}
}
}
+55
View File
@@ -0,0 +1,55 @@
import chalk from "chalk";
import { getApiClient } from "../../api.js";
export const storagesCountDefinition = {
name: "storages",
description: "Counts the amount of storages the current user has.",
action: async () => {
await countStorages();
},
};
async function countStorages() {
const client = await getApiClient();
try {
const response = await client.get("/api/storage");
if (response.status === 200 && response.data.data) {
const storages = response.data.data;
const count = storages.length;
if (count > 0) {
console.log(chalk.blue("Storages List:"));
storages.forEach((s: any) => {
const purposeInfo = s.purpose ? chalk.gray(` - ${s.purpose}`) : "";
console.log(`- ${chalk.cyan(s.name)}${purposeInfo}`);
});
console.log("");
}
console.log(
`${chalk.green("✓")} You have ${chalk.bgGreen.black(` ${count} `)} storages.`,
);
} else {
console.log(
`${chalk.yellow("!")} Unexpected response from server.`,
);
console.log(`Status Code: ${chalk.blue(response.status)}`);
}
} catch (error: any) {
if (error.response) {
console.error(
`${chalk.red("✗")} Failed to fetch storage count.`,
);
console.error(`Status Code: ${chalk.red(error.response.status)}`);
console.error(
`Message: ${chalk.yellow(error.response.data.message || "Unknown error from server")}`,
);
} else if (error.request) {
console.error(`${chalk.red("✗")} No response received from server.`);
} else {
console.error(`${chalk.red("✗")} Error:`, error.message);
}
}
}
+59
View File
@@ -0,0 +1,59 @@
import chalk from "chalk";
import { getApiClient } from "../../api.js";
export const triggersCountDefinition = {
name: "triggers",
description: "Counts the amount of triggers the current user has.",
action: async () => {
await countTriggers();
},
};
async function countTriggers() {
const client = await getApiClient();
try {
const response = await client.get("/api/triggers");
if (response.status === 200 && response.data.data) {
const triggers = response.data.data;
const count = triggers.length;
if (count > 0) {
console.log(chalk.blue("Triggers List:"));
triggers.forEach((t: any) => {
const functionInfo = t.function ? chalk.gray(` [Func: ${t.function.name}]`) : "";
const cronInfo = t.cron ? chalk.yellow(` (Cron: ${t.cron})`) : "";
console.log(`- ${chalk.cyan(t.name)} ${chalk.gray(`(${t.id})`)}${functionInfo}${cronInfo}`);
if (t.description) {
console.log(` ${chalk.italic.gray(t.description)}`);
}
});
console.log("");
}
console.log(
`${chalk.green("✓")} You have ${chalk.bgGreen.black(` ${count} `)} triggers.`,
);
} else {
console.log(
`${chalk.yellow("!")} Unexpected response from server.`,
);
console.log(`Status Code: ${chalk.blue(response.status)}`);
}
} catch (error: any) {
if (error.response) {
console.error(
`${chalk.red("✗")} Failed to fetch trigger count.`,
);
console.error(`Status Code: ${chalk.red(error.response.status)}`);
console.error(
`Message: ${chalk.yellow(error.response.data.message || "Unknown error from server")}`,
);
} else if (error.request) {
console.error(`${chalk.red("✗")} No response received from server.`);
} else {
console.error(`${chalk.red("✗")} Error:`, error.message);
}
}
}
+55
View File
@@ -0,0 +1,55 @@
import chalk from "chalk";
import { getApiClient } from "../../api.js";
export const createFunctionDefinition = {
name: "function",
description: "Create a new serverless function.",
options: [
{ name: "--name <name>", description: "Function name", required: true },
{ name: "--description <description>", description: "Function description", required: true },
{ name: "--image <image>", description: "Docker image tag", required: true },
{ name: "--startup-file <file>", description: "Startup file name", required: true },
{ name: "--namespace-id <id>", description: "Namespace ID", required: true },
{ name: "--execution-alias <alias>", description: "Custom execution alias" },
{ name: "--docker-mount", description: "Enable Docker mount", type: "boolean" },
{ name: "--ffmpeg-install", description: "Install ffmpeg in container", type: "boolean" },
{ name: "--imported", description: "Marks the function as imported", type: "boolean" },
],
action: async (options: any) => {
const data = {
name: options.name,
description: options.description,
image: options.image,
startup_file: options.startupFile,
namespaceId: parseInt(options.namespaceId),
executionAlias: options.executionAlias,
docker_mount: !!options.dockerMount,
ffmpeg_install: !!options.ffmpegInstall,
imported: !!options.imported,
};
const client = await getApiClient();
try {
const response = await client.post("/api/function", data);
if (response.status === 200) {
console.log(
`${chalk.green("✓")} Function ${chalk.cyan(data.name)} created successfully! ID: ${chalk.bgGreen.black(` ${response.data.data.id} `)}`,
);
} else {
console.log(
`${chalk.yellow("!")} Unexpected response from server: ${response.status}`,
);
}
} catch (error: any) {
if (error.response) {
console.error(
`${chalk.red("✗")} Failed to create function: ${chalk.yellow(error.response.data.message || "Unknown error")}`,
);
} else {
console.error(`${chalk.red("✗")} Error: ${error.message}`);
}
}
},
};