mirror of
https://github.com/morten-olsen/mini-loader.git
synced 2026-02-08 01:36:26 +01:00
qa: add e2e tests
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import 'source-map-support/register.js';
|
||||
import '../dist/esm/index.js';
|
||||
import '../dist/esm/bin.js';
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
"rollup": "^4.9.4",
|
||||
"rollup-plugin-node-polyfills": "^0.2.1",
|
||||
"source-map-support": "^0.5.21",
|
||||
"superjson": "^2.2.1"
|
||||
"superjson": "^2.2.1",
|
||||
"typedi": "^0.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@morten-olsen/mini-loader-configs": "workspace:^",
|
||||
|
||||
46
packages/cli/src/api/api.ts
Normal file
46
packages/cli/src/api/api.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { ContainerInstance, Service } from 'typedi';
|
||||
import { Context } from '../context/context.js';
|
||||
import { Config } from '../config/config.js';
|
||||
import { Client, createClient } from '../client/client.js';
|
||||
import type { Runtime } from '@morten-olsen/mini-loader-server';
|
||||
import { Terminal } from './output.js';
|
||||
|
||||
@Service()
|
||||
class CliApi {
|
||||
#container: ContainerInstance;
|
||||
#client?: Client;
|
||||
|
||||
constructor(container: ContainerInstance) {
|
||||
this.#container = container;
|
||||
}
|
||||
|
||||
public get log() {
|
||||
return this.#container.get(Terminal).log;
|
||||
}
|
||||
|
||||
public get step() {
|
||||
return this.#container.get(Terminal).step;
|
||||
}
|
||||
|
||||
public get output() {
|
||||
return this.#container.get(Terminal).output;
|
||||
}
|
||||
|
||||
public get config() {
|
||||
return this.#container.get(Config);
|
||||
}
|
||||
|
||||
public get client() {
|
||||
if (!this.#client) {
|
||||
this.#client = createClient(this.context);
|
||||
}
|
||||
return this.#client;
|
||||
}
|
||||
|
||||
public get context() {
|
||||
return new Context(this.config);
|
||||
}
|
||||
}
|
||||
|
||||
export type { Runtime };
|
||||
export { CliApi };
|
||||
27
packages/cli/src/api/output.ts
Normal file
27
packages/cli/src/api/output.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import ora from 'ora';
|
||||
import { Service } from 'typedi';
|
||||
|
||||
@Service()
|
||||
class Terminal {
|
||||
public log = (message: string) => {
|
||||
console.log(message);
|
||||
};
|
||||
|
||||
public output = (data: unknown) => {
|
||||
console.table(data);
|
||||
};
|
||||
|
||||
public step = async <T>(message: string, action: () => Promise<T>) => {
|
||||
const spinner = ora(message).start();
|
||||
try {
|
||||
const result = await action();
|
||||
await spinner.succeed();
|
||||
return result;
|
||||
} catch (err) {
|
||||
await spinner.fail();
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export { Terminal };
|
||||
7
packages/cli/src/bin.ts
Normal file
7
packages/cli/src/bin.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { ContainerInstance } from 'typedi';
|
||||
import { createClientCli } from './index.js';
|
||||
|
||||
const container = new ContainerInstance('client');
|
||||
const program = createClientCli(container);
|
||||
|
||||
await program.parseAsync();
|
||||
@@ -1,14 +1,9 @@
|
||||
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
|
||||
import superjson from 'superjson';
|
||||
import { createRequire } from 'module';
|
||||
import type { Runtime } from '@morten-olsen/mini-loader-server';
|
||||
import type { RootRouter } from '@morten-olsen/mini-loader-server';
|
||||
import { Context } from '../context/context.js';
|
||||
import { readFile } from 'fs/promises';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
const pkg = JSON.parse(await readFile(require.resolve('#pkg'), 'utf-8'));
|
||||
const createClient = (context: Context) => {
|
||||
if (!context.host || !context.token) {
|
||||
throw new Error('Not signed in');
|
||||
@@ -19,7 +14,6 @@ const createClient = (context: Context) => {
|
||||
httpBatchLink({
|
||||
url: `${context.host}/trpc`,
|
||||
headers: {
|
||||
'x-version': pkg.version,
|
||||
authorization: `Bearer ${context.token}`,
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const list = new Command('list');
|
||||
|
||||
@@ -22,11 +19,7 @@ list
|
||||
.option('-a, --limit <limit>', 'Limit', '1000')
|
||||
.action(async () => {
|
||||
const { runId, loadId, offset, limit } = list.opts();
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const { step, client } = getApi(list);
|
||||
const artifacts = await step('Getting artifacts', async () => {
|
||||
return await client.artifacts.find.query({
|
||||
runId,
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { dirname, resolve } from 'path';
|
||||
import { mkdir, writeFile } from 'fs/promises';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const pull = new Command('pull');
|
||||
|
||||
@@ -13,12 +10,8 @@ pull
|
||||
.argument('<artifact-id>', 'Artifact ID')
|
||||
.argument('<file>', 'File to save')
|
||||
.action(async (id, file) => {
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const { step, client } = getApi(pull);
|
||||
const target = resolve(file);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const artifact = await step('Getting artifact', async () => {
|
||||
const result = await client.artifacts.get.query(id);
|
||||
if (!result) {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import inquirer from 'inquirer';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const remove = new Command('remove');
|
||||
|
||||
@@ -22,12 +19,8 @@ remove
|
||||
.option('-o, --offset <offset>', 'Offset')
|
||||
.option('-a, --limit <limit>', 'Limit', '1000')
|
||||
.action(async () => {
|
||||
const { step, client } = getApi(remove);
|
||||
const { runId, loadId, offset, limit } = remove.opts();
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const response = await step('Preparing to delete', async () => {
|
||||
return await client.artifacts.prepareRemove.query({
|
||||
runId,
|
||||
|
||||
@@ -1,28 +1,37 @@
|
||||
import { Command } from 'commander';
|
||||
import inquerer from 'inquirer';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const login = new Command('login');
|
||||
|
||||
login.description('Login to your account');
|
||||
login.option('--host <host>', 'The host of your server');
|
||||
login.option('--token <token>', 'The token of your account');
|
||||
login.action(async () => {
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const { host, token } = await inquerer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'host',
|
||||
message: 'Enter the host of your server',
|
||||
default: context.host ?? 'http://localhost:4500',
|
||||
},
|
||||
{
|
||||
type: 'password',
|
||||
name: 'token',
|
||||
message: 'Enter your token',
|
||||
},
|
||||
]);
|
||||
let { host, token } = login.opts();
|
||||
const { step, context } = getApi(login);
|
||||
if (!host) {
|
||||
const answers = await inquerer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'host',
|
||||
message: 'Enter the host of your server',
|
||||
default: context.host || 'http://localhost:4500',
|
||||
},
|
||||
]);
|
||||
host = answers.host;
|
||||
}
|
||||
|
||||
if (!token) {
|
||||
const answers = await inquerer.prompt([
|
||||
{
|
||||
type: 'password',
|
||||
name: 'token',
|
||||
message: 'Enter your token',
|
||||
},
|
||||
]);
|
||||
token = answers.token;
|
||||
}
|
||||
|
||||
const healthResponse = await step('Getting auth status', async () => {
|
||||
return await fetch(`${host}/health`, {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Command } from 'commander';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const current = new Command('current');
|
||||
current.action(async () => {
|
||||
const config = new Config();
|
||||
const { config } = getApi(current);
|
||||
console.log(config.context);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Command } from 'commander';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const use = new Command('use');
|
||||
|
||||
use.argument('<name>').action(async (name) => {
|
||||
const config = new Config();
|
||||
const { config } = getApi(use);
|
||||
await config.setContext(name);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const list = new Command('list');
|
||||
|
||||
@@ -10,15 +7,11 @@ list
|
||||
.alias('ls')
|
||||
.description('List loads')
|
||||
.action(async () => {
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const { output, step, client } = getApi(list);
|
||||
const loads = await step('Getting data', async () => {
|
||||
return await client.loads.find.query({});
|
||||
});
|
||||
console.table(loads);
|
||||
await output(loads);
|
||||
});
|
||||
|
||||
export { list };
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import { Command } from 'commander';
|
||||
import { resolve } from 'path';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { bundle } from '../../bundler/bundler.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const push = new Command('push');
|
||||
|
||||
@@ -16,12 +13,8 @@ push
|
||||
.option('-ai, --auto-install', 'Auto install dependencies', false)
|
||||
.action(async (script) => {
|
||||
const opts = push.opts();
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const { step, log, client } = getApi(push);
|
||||
const location = resolve(script);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const code = await step('Bundling', async () => {
|
||||
return await bundle({ entry: location, autoInstall: opts.autoInstall });
|
||||
});
|
||||
@@ -32,12 +25,12 @@ push
|
||||
script: code,
|
||||
});
|
||||
});
|
||||
console.log('created load with id', id);
|
||||
await log(`created load with id ${id}`);
|
||||
if (opts.run) {
|
||||
const runId = await step('Creating run', async () => {
|
||||
return await client.runs.create.mutate({ loadId: id });
|
||||
});
|
||||
console.log('created run with id', runId);
|
||||
await log(`created run with id ${runId}`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -2,9 +2,8 @@ import { Command } from 'commander';
|
||||
import { resolve } from 'path';
|
||||
import { run as runLoad } from '@morten-olsen/mini-loader-runner';
|
||||
import { bundle } from '../../bundler/bundler.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { readSecrets } from './local.utils.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const run = new Command('run');
|
||||
|
||||
@@ -12,8 +11,8 @@ run
|
||||
.option('-ai, --auto-install', 'Auto install dependencies', false)
|
||||
.argument('script')
|
||||
.action(async (script) => {
|
||||
const { step, config } = getApi(run);
|
||||
const location = resolve(script);
|
||||
const config = new Config();
|
||||
const { autoInstall } = run.opts();
|
||||
const secrets = await readSecrets();
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const list = new Command('list');
|
||||
|
||||
@@ -24,11 +21,7 @@ list
|
||||
.option('-s, --sort <order>', 'Sort', 'desc')
|
||||
.action(async () => {
|
||||
const { runId, loadId, severities, offset, limit, order } = list.opts();
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const { step, output, client } = getApi(list);
|
||||
const logs = await step('Getting logs', async () => {
|
||||
return await client.logs.find.query({
|
||||
runId,
|
||||
@@ -39,7 +32,7 @@ list
|
||||
order,
|
||||
});
|
||||
});
|
||||
console.table(logs);
|
||||
output(logs);
|
||||
});
|
||||
|
||||
export { list };
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import inquirer from 'inquirer';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const remove = new Command('remove');
|
||||
|
||||
@@ -24,12 +21,8 @@ remove
|
||||
.option('-a, --limit <limit>', 'Limit', '1000')
|
||||
.option('-s, --sort <order>', 'Sort', 'desc')
|
||||
.action(async () => {
|
||||
const { step, client } = getApi(remove);
|
||||
const { runId, loadId, severities, offset, limit, order } = remove.opts();
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const response = await step('Preparing to delete', async () => {
|
||||
return await client.logs.prepareRemove.query({
|
||||
runId,
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const create = new Command('create');
|
||||
|
||||
@@ -10,11 +7,7 @@ create
|
||||
.description('Create a new run')
|
||||
.argument('load-id', 'Load ID')
|
||||
.action(async (loadId) => {
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const { step, client } = getApi(create);
|
||||
await step('Creating run', async () => {
|
||||
await client.runs.create.mutate({ loadId });
|
||||
});
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const list = new Command('list');
|
||||
|
||||
@@ -11,15 +8,11 @@ list
|
||||
.description('Find a run')
|
||||
.argument('[load-id]', 'Load ID')
|
||||
.action(async (loadId) => {
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const { step, output, client } = getApi(list);
|
||||
const runs = await step('Getting runs', async () => {
|
||||
return await client.runs.find.query({ loadId });
|
||||
});
|
||||
console.table(runs);
|
||||
await output(runs);
|
||||
});
|
||||
|
||||
export { list };
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import inquirer from 'inquirer';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const remove = new Command('remove');
|
||||
|
||||
@@ -21,12 +18,8 @@ remove
|
||||
.option('-o, --offset <offset>', 'Offset')
|
||||
.option('-a, --limit <limit>', 'Limit', '1000')
|
||||
.action(async () => {
|
||||
const { step, client } = getApi(remove);
|
||||
const { loadId, offset, limit } = remove.opts();
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const response = await step('Preparing to delete', async () => {
|
||||
return await client.runs.prepareRemove.query({
|
||||
loadId,
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const terminate = new Command('terminate');
|
||||
|
||||
@@ -10,11 +7,7 @@ terminate
|
||||
.description('Terminate an in progress run')
|
||||
.argument('run-id', 'Run ID')
|
||||
.action(async (runId) => {
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const { step, client } = getApi(terminate);
|
||||
await step('Terminating run', async () => {
|
||||
await client.runs.terminate.mutate(runId);
|
||||
});
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const add = new Command('add');
|
||||
|
||||
@@ -12,12 +9,8 @@ add
|
||||
.argument('<cron>', 'Cron')
|
||||
.option('-n, --name <name>', 'Name')
|
||||
.action(async (loadId, cron) => {
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const { step, client } = getApi(add);
|
||||
const { name } = add.opts();
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const id = await step('Adding schedule', async () => {
|
||||
return await client.schedules.add.mutate({
|
||||
name,
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const list = new Command('list');
|
||||
|
||||
@@ -20,12 +17,8 @@ list
|
||||
.option('-o, --offset <offset>', 'Offset')
|
||||
.option('-a, --limit <limit>', 'Limit', '1000')
|
||||
.action(async () => {
|
||||
const { step, output, client } = getApi(list);
|
||||
const { loadIds, offset, limit } = list.opts();
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const schedules = await step('Getting schedules', async () => {
|
||||
return await client.schedules.find.query({
|
||||
loadIds,
|
||||
@@ -33,7 +26,7 @@ list
|
||||
limit: toInt(limit),
|
||||
});
|
||||
});
|
||||
console.table(schedules);
|
||||
output(schedules);
|
||||
});
|
||||
|
||||
export { list };
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import inquirer from 'inquirer';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const remove = new Command('remove');
|
||||
|
||||
@@ -22,12 +19,8 @@ remove
|
||||
.option('-o, --offset <offset>', 'Offset')
|
||||
.option('-a, --limit <limit>', 'Limit', '1000')
|
||||
.action(async () => {
|
||||
const { step, client } = getApi(remove);
|
||||
const { ids, loadIds, offset, limit } = remove.opts();
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const response = await step('Preparing to delete', async () => {
|
||||
return await client.schedules.prepareRemove.query({
|
||||
ids,
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const list = new Command('list');
|
||||
|
||||
@@ -15,16 +12,12 @@ const toInt = (value?: string) => {
|
||||
|
||||
list
|
||||
.alias('ls')
|
||||
.description('List logs')
|
||||
.description('List secrets')
|
||||
.option('-o, --offset <offset>', 'Offset')
|
||||
.option('-a, --limit <limit>', 'Limit', '1000')
|
||||
.action(async () => {
|
||||
const { step, client } = getApi(list);
|
||||
const { offset, limit } = list.opts();
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const secrets = await step('Getting secrets', async () => {
|
||||
return await client.secrets.find.query({
|
||||
offset: toInt(offset),
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const remove = new Command('remove');
|
||||
|
||||
@@ -10,11 +7,7 @@ remove
|
||||
.alias('rm')
|
||||
.argument('<id>')
|
||||
.action(async (id) => {
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const { step, client } = getApi(remove);
|
||||
await step('Removing', async () => {
|
||||
await client.secrets.remove.mutate({
|
||||
id,
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { Command } from 'commander';
|
||||
import { createClient } from '../../client/client.js';
|
||||
import { step } from '../../utils/step.js';
|
||||
import { Context } from '../../context/context.js';
|
||||
import { Config } from '../../config/config.js';
|
||||
import { getApi } from '../../utils/command.js';
|
||||
|
||||
const set = new Command('set');
|
||||
|
||||
@@ -10,11 +7,7 @@ set
|
||||
.argument('<id>')
|
||||
.argument('[value]')
|
||||
.action(async (id, value) => {
|
||||
const config = new Config();
|
||||
const context = new Context(config.context);
|
||||
const client = await step('Connecting to server', async () => {
|
||||
return createClient(context);
|
||||
});
|
||||
const { step, client } = getApi(set);
|
||||
await step('Setting secret', async () => {
|
||||
await client.secrets.set.mutate({
|
||||
id,
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import envPaths from 'env-paths';
|
||||
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
||||
import { mkdir } from 'fs/promises';
|
||||
import { existsSync, readFileSync } from 'fs';
|
||||
import { mkdir, writeFile } from 'fs/promises';
|
||||
import { join, dirname } from 'path';
|
||||
import { ContainerInstance, Service } from 'typedi';
|
||||
import { Paths } from '../paths/paths.js';
|
||||
|
||||
type ConfigValues = {
|
||||
context?: string;
|
||||
};
|
||||
|
||||
const paths = envPaths('mini-loader');
|
||||
|
||||
@Service()
|
||||
class Config {
|
||||
#paths: Paths;
|
||||
#location: string;
|
||||
#config?: ConfigValues;
|
||||
|
||||
constructor() {
|
||||
this.#location = join(paths.config, 'config.json');
|
||||
constructor(contianer: ContainerInstance) {
|
||||
this.#paths = contianer.get(Paths);
|
||||
this.#location = join(this.#paths.config, 'config.json');
|
||||
if (existsSync(this.#location)) {
|
||||
this.#config = JSON.parse(readFileSync(this.#location, 'utf-8'));
|
||||
}
|
||||
@@ -24,8 +26,12 @@ class Config {
|
||||
return this.#config?.context || 'default';
|
||||
}
|
||||
|
||||
public get location() {
|
||||
return this.#paths.config;
|
||||
}
|
||||
|
||||
public get cacheLocation() {
|
||||
return join(paths.cache, this.context);
|
||||
return join(this.#paths.cache, this.context);
|
||||
}
|
||||
|
||||
public setContext = (context: string) => {
|
||||
@@ -42,7 +48,7 @@ class Config {
|
||||
}
|
||||
const json = JSON.stringify(this.#config);
|
||||
mkdir(dirname(this.#location), { recursive: true });
|
||||
writeFileSync(this.#location, json);
|
||||
writeFile(this.#location, json);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import envPaths from 'env-paths';
|
||||
import { existsSync, readFileSync } from 'fs';
|
||||
import { mkdir, readdir, writeFile } from 'fs/promises';
|
||||
import { dirname, join } from 'path';
|
||||
import { Config } from '../config/config.js';
|
||||
|
||||
type ContextValues = {
|
||||
host: string;
|
||||
@@ -12,9 +13,8 @@ class Context {
|
||||
#location: string;
|
||||
#config?: ContextValues;
|
||||
|
||||
constructor(name: string) {
|
||||
const paths = envPaths('mini-loader');
|
||||
this.#location = join(paths.config, 'contexts', name);
|
||||
constructor(config: Config) {
|
||||
this.#location = join(config.location, 'contexts', config.context);
|
||||
if (existsSync(this.#location)) {
|
||||
this.#config = JSON.parse(readFileSync(this.#location, 'utf-8'));
|
||||
}
|
||||
@@ -28,13 +28,13 @@ class Context {
|
||||
return this.#config?.token;
|
||||
}
|
||||
|
||||
public saveLogin = (host: string, token: string) => {
|
||||
public saveLogin = async (host: string, token: string) => {
|
||||
this.#config = {
|
||||
...(this.#config || {}),
|
||||
host,
|
||||
token,
|
||||
};
|
||||
this.save();
|
||||
await this.save();
|
||||
};
|
||||
|
||||
public save = async () => {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Command, program } from 'commander';
|
||||
import { createRequire } from 'module';
|
||||
import { Command } from 'commander';
|
||||
import { loads } from './commands/loads/loads.js';
|
||||
import { runs } from './commands/runs/runs.js';
|
||||
import { logs } from './commands/logs/logs.js';
|
||||
@@ -9,28 +8,27 @@ import { local } from './commands/local/local.js';
|
||||
import { auth } from './commands/auth/auth.js';
|
||||
import { contexts } from './commands/contexts/contexts.js';
|
||||
import { schedules } from './commands/schedules/schedules.js';
|
||||
import { readFile } from 'fs/promises';
|
||||
import { ContainerInstance } from 'typedi';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const createClientCli = (container: ContainerInstance) => {
|
||||
const program = new Command();
|
||||
program.exitOverride();
|
||||
program.setOptionValue('_container', container);
|
||||
program.addCommand(loads);
|
||||
program.addCommand(runs);
|
||||
program.addCommand(logs);
|
||||
program.addCommand(artifacts);
|
||||
program.addCommand(secrets);
|
||||
program.addCommand(local);
|
||||
program.addCommand(auth);
|
||||
program.addCommand(contexts);
|
||||
program.addCommand(schedules);
|
||||
|
||||
const pkg = JSON.parse(await readFile(require.resolve('#pkg'), 'utf-8'));
|
||||
return program;
|
||||
};
|
||||
|
||||
program.addCommand(loads);
|
||||
program.addCommand(runs);
|
||||
program.addCommand(logs);
|
||||
program.addCommand(artifacts);
|
||||
program.addCommand(secrets);
|
||||
program.addCommand(local);
|
||||
program.addCommand(auth);
|
||||
program.addCommand(contexts);
|
||||
program.addCommand(schedules);
|
||||
|
||||
program.version(pkg.version);
|
||||
|
||||
const version = new Command('version');
|
||||
version.action(() => {
|
||||
console.log(pkg.version);
|
||||
});
|
||||
program.addCommand(version);
|
||||
|
||||
await program.parseAsync();
|
||||
export { CliApi } from './api/api.js';
|
||||
export { Context } from './context/context.js';
|
||||
export { Terminal } from './api/output.js';
|
||||
export { Paths } from './paths/paths.js';
|
||||
export { createClientCli };
|
||||
|
||||
17
packages/cli/src/paths/paths.ts
Normal file
17
packages/cli/src/paths/paths.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import envPaths from 'env-paths';
|
||||
import { Service } from 'typedi';
|
||||
|
||||
const paths = envPaths('mini-loader');
|
||||
|
||||
@Service()
|
||||
class Paths {
|
||||
public get config() {
|
||||
return paths.config;
|
||||
}
|
||||
|
||||
public get cache() {
|
||||
return paths.cache;
|
||||
}
|
||||
}
|
||||
|
||||
export { Paths };
|
||||
11
packages/cli/src/utils/command.ts
Normal file
11
packages/cli/src/utils/command.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Command } from 'commander';
|
||||
import { ContainerInstance } from 'typedi';
|
||||
import { CliApi } from '../api/api.js';
|
||||
|
||||
const getApi = (command: Command) => {
|
||||
const { _container } = command.optsWithGlobals() as { _container: ContainerInstance };
|
||||
const api = _container.get(CliApi);
|
||||
return api;
|
||||
};
|
||||
|
||||
export { getApi };
|
||||
@@ -1,15 +0,0 @@
|
||||
import ora from 'ora';
|
||||
|
||||
const step = async <T>(message: string, fn: () => Promise<T>): Promise<T> => {
|
||||
const spinner = ora(message).start();
|
||||
try {
|
||||
const result = await fn();
|
||||
await spinner.succeed();
|
||||
return result;
|
||||
} catch (err) {
|
||||
await spinner.fail();
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
export { step };
|
||||
Reference in New Issue
Block a user