mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 00:18:19 +01:00
Full CLI rework and repair
This commit is contained in:
parent
cbc6f46103
commit
28c73bc62a
|
|
@ -9,7 +9,7 @@ module.exports = {
|
|||
parserOptions: {
|
||||
project: "./tsconfig.json",
|
||||
},
|
||||
ignorePatterns: ["node_modules/", "dist/", ".eslintrc.cjs", "cli.ts"],
|
||||
ignorePatterns: ["node_modules/", "dist/", ".eslintrc.cjs"],
|
||||
plugins: ["@typescript-eslint"],
|
||||
root: true,
|
||||
rules: {
|
||||
|
|
|
|||
|
|
@ -152,22 +152,19 @@ bun start
|
|||
|
||||
### Using the CLI
|
||||
|
||||
> [!WARNING]
|
||||
> The CLI is currently broken due to unknown bugs that are actively being investigated. The following instructions are for when this is fixed.
|
||||
|
||||
Lysand includes a built-in CLI for managing the server. To use it, simply run the following command:
|
||||
|
||||
```bash
|
||||
bun cli
|
||||
bun cli help
|
||||
```
|
||||
|
||||
If you are running a production build, you will need to run `bun run dist/cli.js` or `./entrypoint.sh cli` instead.
|
||||
|
||||
You can use the `help` command to see a list of available commands. These include creating users, deleting users and more.
|
||||
You can use the `help` command to see a list of available commands. These include creating users, deleting users and more. Each command also has a `--help,-h` flag that you can use to see more information about the command.
|
||||
|
||||
#### Scripting with the CLI
|
||||
|
||||
Some CLI commands that return data as tables can be used in scripts. To do so, you can use the `--json` flag to output the data as JSON instead of a table, or even `--csv` to output the data as CSV. See `bun cli help` for more information.
|
||||
Some CLI commands that return data as tables can be used in scripts. To convert them to JSON or CSV, some commands allow you to specify a `--format` flag that can be either `"json"` or `"csv"`. See `bun cli help` or `bun cli <command> -h` for more information.
|
||||
|
||||
Flags can be used in any order and anywhere in the script (except for the `bun cli` command itself). The command arguments themselves must be in the correct order, however.
|
||||
|
||||
|
|
|
|||
13
package.json
13
package.json
|
|
@ -84,11 +84,14 @@
|
|||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.461.0",
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"@json2csv/plainjs": "^7.0.6",
|
||||
"@prisma/client": "^5.6.0",
|
||||
"blurhash": "^2.0.5",
|
||||
"bullmq": "latest",
|
||||
"chalk": "^5.3.0",
|
||||
"cli-parser": "file:packages/cli-parser",
|
||||
"cli-table": "^0.3.11",
|
||||
"config-manager": "file:packages/config-manager",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"extract-zip": "^2.0.1",
|
||||
"html-to-text": "^9.0.5",
|
||||
|
|
@ -100,7 +103,9 @@
|
|||
"linkify-html": "^4.1.3",
|
||||
"linkify-string": "^4.1.3",
|
||||
"linkifyjs": "^4.1.3",
|
||||
"log-manager": "file:packages/log-manager",
|
||||
"marked": "latest",
|
||||
"media-manager": "file:packages/media-manager",
|
||||
"megalodon": "^9.1.1",
|
||||
"meilisearch": "latest",
|
||||
"merge-deep-ts": "^1.2.6",
|
||||
|
|
@ -108,12 +113,8 @@
|
|||
"oauth4webapi": "^2.4.0",
|
||||
"prisma": "^5.6.0",
|
||||
"prisma-redis-middleware": "^4.8.0",
|
||||
"semver": "^7.5.4",
|
||||
"sharp": "^0.33.0-rc.2",
|
||||
"request-parser": "file:packages/request-parser",
|
||||
"config-manager": "file:packages/config-manager",
|
||||
"cli-parser": "file:packages/cli-parser",
|
||||
"log-manager": "file:packages/log-manager",
|
||||
"media-manager": "file:packages/media-manager"
|
||||
"semver": "^7.5.4",
|
||||
"sharp": "^0.33.0-rc.2"
|
||||
}
|
||||
}
|
||||
|
|
@ -117,7 +117,9 @@ export class CliBuilder {
|
|||
prev.categories.length > current.categories.length ? prev : current
|
||||
);
|
||||
|
||||
const argsWithoutCategories = revelantArgs.slice(command.categories.length);
|
||||
const argsWithoutCategories = revelantArgs.slice(
|
||||
command.categories.length
|
||||
);
|
||||
|
||||
return await command.run(argsWithoutCategories);
|
||||
}
|
||||
|
|
@ -243,8 +245,6 @@ export class CliBuilder {
|
|||
})
|
||||
);
|
||||
|
||||
console.log(optimal_length)
|
||||
|
||||
for (const line of writeBuffer.split("\n")) {
|
||||
const [left, right] = line.split("|");
|
||||
if (!right) {
|
||||
|
|
@ -261,6 +261,7 @@ export class CliBuilder {
|
|||
type ExecuteFunction<T> = (
|
||||
instance: CliCommand,
|
||||
args: Partial<T>
|
||||
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
||||
) => Promise<number> | Promise<void> | number | void;
|
||||
|
||||
/**
|
||||
|
|
@ -364,7 +365,7 @@ ${unpositionedArgs
|
|||
currentParameter = null;
|
||||
} else {
|
||||
const positionedArgType = this.argTypes.find(
|
||||
argType => argType.positioned
|
||||
argType => argType.positioned && !parsedArgs[argType.name]
|
||||
);
|
||||
if (positionedArgType) {
|
||||
parsedArgs[positionedArgType.name] = this.castArgValue(
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ describe("CliCommand", () => {
|
|||
).toEqual(["value1", "value2"]);
|
||||
});
|
||||
|
||||
it("should run the execute function with the parsed parameters", () => {
|
||||
it("should run the execute function with the parsed parameters", async () => {
|
||||
const mockExecute = jest.fn();
|
||||
cliCommand = new CliCommand(
|
||||
["category1", "category2"],
|
||||
|
|
@ -142,7 +142,7 @@ describe("CliCommand", () => {
|
|||
mockExecute
|
||||
);
|
||||
|
||||
cliCommand.run([
|
||||
await cliCommand.run([
|
||||
"--arg1",
|
||||
"value1",
|
||||
"--arg2",
|
||||
|
|
@ -159,7 +159,7 @@ describe("CliCommand", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("should work with a mix of positioned and non-positioned arguments", () => {
|
||||
it("should work with a mix of positioned and non-positioned arguments", async () => {
|
||||
const mockExecute = jest.fn();
|
||||
cliCommand = new CliCommand(
|
||||
["category1", "category2"],
|
||||
|
|
@ -194,7 +194,7 @@ describe("CliCommand", () => {
|
|||
mockExecute
|
||||
);
|
||||
|
||||
cliCommand.run([
|
||||
await cliCommand.run([
|
||||
"--arg1",
|
||||
"value1",
|
||||
"--arg2",
|
||||
|
|
@ -324,7 +324,7 @@ describe("CliBuilder", () => {
|
|||
expect(cliBuilder.commands).not.toContain(mockCommand2);
|
||||
});
|
||||
|
||||
it("should process args correctly", () => {
|
||||
it("should process args correctly", async () => {
|
||||
const mockExecute = jest.fn();
|
||||
const mockCommand = new CliCommand(
|
||||
["category1", "sub1"],
|
||||
|
|
@ -339,7 +339,7 @@ describe("CliBuilder", () => {
|
|||
mockExecute
|
||||
);
|
||||
cliBuilder.registerCommand(mockCommand);
|
||||
cliBuilder.processArgs([
|
||||
await cliBuilder.processArgs([
|
||||
"./cli.ts",
|
||||
"category1",
|
||||
"sub1",
|
||||
|
|
|
|||
|
|
@ -32,6 +32,24 @@ export class MediaBackend {
|
|||
public backend: MediaBackendType
|
||||
) {}
|
||||
|
||||
static async fromBackendType(
|
||||
backend: MediaBackendType,
|
||||
config: ConfigType
|
||||
): Promise<MediaBackend> {
|
||||
switch (backend) {
|
||||
case MediaBackendType.LOCAL:
|
||||
return new (await import("./backends/local")).LocalMediaBackend(
|
||||
config
|
||||
);
|
||||
case MediaBackendType.S3:
|
||||
return new (await import("./backends/s3")).S3MediaBackend(
|
||||
config
|
||||
);
|
||||
default:
|
||||
throw new Error(`Unknown backend type: ${backend as any}`);
|
||||
}
|
||||
}
|
||||
|
||||
public getBackendType() {
|
||||
return this.backend;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,39 @@ describe("MediaBackend", () => {
|
|||
expect(mediaBackend.getBackendType()).toEqual(MediaBackendType.S3);
|
||||
});
|
||||
|
||||
describe("fromBackendType", () => {
|
||||
it("should return a LocalMediaBackend instance for LOCAL backend type", async () => {
|
||||
const backend = await MediaBackend.fromBackendType(
|
||||
MediaBackendType.LOCAL,
|
||||
mockConfig
|
||||
);
|
||||
expect(backend).toBeInstanceOf(LocalMediaBackend);
|
||||
});
|
||||
|
||||
it("should return a S3MediaBackend instance for S3 backend type", async () => {
|
||||
const backend = await MediaBackend.fromBackendType(
|
||||
MediaBackendType.S3,
|
||||
{
|
||||
s3: {
|
||||
endpoint: "localhost:4566",
|
||||
region: "us-east-1",
|
||||
bucket_name: "test-bucket",
|
||||
access_key: "test-access",
|
||||
public_url: "test",
|
||||
secret_access_key: "test-secret",
|
||||
},
|
||||
} as ConfigType
|
||||
);
|
||||
expect(backend).toBeInstanceOf(S3MediaBackend);
|
||||
});
|
||||
|
||||
it("should throw an error for unknown backend type", () => {
|
||||
expect(
|
||||
MediaBackend.fromBackendType("unknown" as any, mockConfig)
|
||||
).rejects.toThrow("Unknown backend type: unknown");
|
||||
});
|
||||
});
|
||||
|
||||
it("should check if images should be converted", () => {
|
||||
expect(mediaBackend.shouldConvertImages(mockConfig)).toBe(true);
|
||||
mockConfig.media.conversion.convert_images = false;
|
||||
|
|
|
|||
Loading…
Reference in a new issue