@ptkl/toolkit 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,27 @@
1
+ import { Command } from "commander";
2
+ import util from "../lib/util.js";
3
+ import Api from "protokol-sdk";
4
+ import OutputFormatCommand from "./outputCommand.js";
5
+ class FunctionsCommand {
6
+ register() {
7
+ return new Command('functions')
8
+ .description('Manage functions')
9
+ .version('0.1.0')
10
+ .addCommand(new OutputFormatCommand(new Command('list')
11
+ .description('List functions')).action(this.list))
12
+ .addCommand(new OutputFormatCommand(new Command('get')
13
+ .description('Get function')
14
+ .argument("<reference>", "Reference to the function which can be name, tag or uuid")).action(this.get));
15
+ }
16
+ async list() {
17
+ const profile = util.getCurrentProfile();
18
+ const client = new Api({ project: profile.project, token: profile.token, host: profile.host }).function();
19
+ return await client.list();
20
+ }
21
+ async get(reference) {
22
+ const profile = util.getCurrentProfile();
23
+ const client = new Api({ project: profile.project, token: profile.token, host: profile.host }).function();
24
+ return await client.get(reference);
25
+ }
26
+ }
27
+ export default new FunctionsCommand;
@@ -0,0 +1,22 @@
1
+ import { Command } from "commander";
2
+ // commands
3
+ import profile from "./profile.js";
4
+ import Util from "../lib/util.js";
5
+ import users from "./apiUsers.js";
6
+ import functions from "./functions.js";
7
+ import apps from "./apps.js";
8
+ import pull from "./pull.js";
9
+ import role from "./role.js";
10
+ import forge from "./forge.js";
11
+ export const commands = [
12
+ profile.register(),
13
+ users.register(),
14
+ functions.register(),
15
+ apps.register(),
16
+ pull.register(),
17
+ role.register(),
18
+ forge.register(),
19
+ new Command('init')
20
+ .description("Init protokol toolkit")
21
+ .action(Util.init)
22
+ ];
@@ -0,0 +1,34 @@
1
+ import CLI from "../lib/cli.js";
2
+ import { writeFileSync } from "fs";
3
+ export default class OutputFormatCommand {
4
+ command;
5
+ constructor(command) {
6
+ this.command = command;
7
+ this.command
8
+ .option("-f, --format <format>")
9
+ .option("-o, --output <file>");
10
+ }
11
+ action(fn) {
12
+ this.command.action(async (...args) => {
13
+ const results = await fn(...args);
14
+ const { format, output } = this.command.opts();
15
+ if (!output) {
16
+ switch (format) {
17
+ case 'json':
18
+ CLI.write(JSON.stringify(results, null, 4));
19
+ break;
20
+ case 'table':
21
+ CLI.writeTable(results);
22
+ break;
23
+ default: console.log(results);
24
+ }
25
+ return;
26
+ }
27
+ writeFileSync(output, results);
28
+ });
29
+ return this.command;
30
+ }
31
+ cmd() {
32
+ return this.command;
33
+ }
34
+ }
@@ -0,0 +1,119 @@
1
+ import { Command } from "commander";
2
+ import util from "../lib/util.js";
3
+ import cli from "../lib/cli.js";
4
+ import Api from "protokol-sdk";
5
+ class ProfileCommand {
6
+ register() {
7
+ return new Command('profile')
8
+ .description('Show current profile')
9
+ .version('0.1.0')
10
+ .action(this.action)
11
+ .addCommand(new Command('new')
12
+ .description('Create new profile')
13
+ .option("-n, --name <name>")
14
+ .option("-u, --username <username>")
15
+ .option("-p, --password <password>")
16
+ .option("-P, --project <project>")
17
+ .option("-h, --host <host>")
18
+ .action(this.new))
19
+ .addCommand(new Command('auth')
20
+ .description('Profile auth')
21
+ .option("-n, --name <name>")
22
+ .option("-u, --username <username>")
23
+ .option("-p, --password <password>")
24
+ .option("-P, --project <project>")
25
+ .action(this.auth))
26
+ .addCommand(new Command('list')
27
+ .description('List all available profiles')
28
+ .action(this.list))
29
+ .addCommand(new Command('delete')
30
+ .description('delete profile')
31
+ .argument('<name>')
32
+ .action(this.delete))
33
+ .addCommand(new Command('use')
34
+ .description('Set profile as active')
35
+ .argument('<name>')
36
+ .action(this.use))
37
+ .addCommand(new Command('inspect')
38
+ .description('Inspect profile')
39
+ .argument('<name>')
40
+ .action(this.inspect));
41
+ }
42
+ action() {
43
+ const currentProfile = util.getCurrentProfile();
44
+ cli.write(currentProfile?.name ?? "profile not selected");
45
+ }
46
+ async new(options) {
47
+ // try to find profile with the name
48
+ const { name, username, password, project, host } = options;
49
+ const profiles = util.getProfiles() ?? [];
50
+ // try to find that the profile with the name already exist
51
+ const profile = profiles.find((p) => p.name == name);
52
+ if (profile) {
53
+ throw new Error(`Profile with ${name} already exist`);
54
+ }
55
+ const user = new Api({ host, project }).apiUser();
56
+ // authenticate to protokol
57
+ const { data } = await user.apiAuth(username, password);
58
+ profiles.push({
59
+ name,
60
+ username,
61
+ project,
62
+ token: data.Token,
63
+ host
64
+ });
65
+ util.updateProfiles(profiles);
66
+ }
67
+ async auth(options) {
68
+ // try to find profile with the name
69
+ const { name, username, password, project, host } = options;
70
+ const profiles = util.getProfiles() ?? [];
71
+ // try to find that the profile with the name already exist
72
+ const profile = profiles.find((p) => p.name == name);
73
+ if (!profile) {
74
+ throw new Error(`Profile with ${name} doesn't exist`);
75
+ }
76
+ const user = new Api({ host, project }).apiUser();
77
+ // authenticate to protokol
78
+ const { data } = await user.apiAuth(username, password);
79
+ profile.token = data.Token;
80
+ util.updateProfiles(profiles);
81
+ }
82
+ list() {
83
+ const profiles = util.getProfiles() ?? [];
84
+ profiles.forEach((p) => {
85
+ let name = p.name;
86
+ if (p.current) {
87
+ name = `* ${p.name}`;
88
+ }
89
+ cli.write(name);
90
+ });
91
+ }
92
+ use(name) {
93
+ const profiles = util.getProfiles() ?? [];
94
+ // try to find that the profile with the name already exist
95
+ const profile = profiles.find((p) => p.name == name);
96
+ if (!profile) {
97
+ throw new Error(`Profile with ${name} doesn't exist`);
98
+ }
99
+ const prevCurrent = profiles.find((p) => p.current);
100
+ if (prevCurrent) {
101
+ prevCurrent.current = false;
102
+ }
103
+ profile.current = true;
104
+ util.updateProfiles(profiles);
105
+ }
106
+ delete(name) {
107
+ let profiles = util.getProfiles() ?? [];
108
+ // try to find that the profile with the name already exist
109
+ profiles = profiles.filter((p) => p.name != name);
110
+ util.updateProfiles(profiles);
111
+ }
112
+ inspect(name) {
113
+ let profiles = util.getProfiles() ?? [];
114
+ // try to find that the profile with the name already exist
115
+ const profile = profiles.find((p) => p.name == name);
116
+ console.log(profile);
117
+ }
118
+ }
119
+ export default new ProfileCommand;
@@ -0,0 +1,74 @@
1
+ import { Command } from "commander";
2
+ import { basename } from "path";
3
+ import * as readlinePromises from "readline/promises";
4
+ import { stdin, stdout } from "process";
5
+ import { existsSync, writeFileSync } from "fs";
6
+ class Pull {
7
+ register() {
8
+ return new Command("pull")
9
+ .description("Pull resources with latest api Verison")
10
+ .version("0.1.0")
11
+ .requiredOption("-r, --resource <resource>", "Resource to pull data from ")
12
+ .option("--ref <ref>", "Resource identifier")
13
+ .requiredOption("-o --output <output>", "file path to store output yaml")
14
+ .action((opts) => this.pull(opts));
15
+ }
16
+ async pull(opts) {
17
+ console.log("not implemented");
18
+ // const { ref, output, resource } = opts;
19
+ // const profile = util.getCurrentProfile();
20
+ // const client = new Api({ project: profile.project, token: profile.token, host: profile.host }).resource(resource);
21
+ // // await client.pull(ref,output)
22
+ // // const resourceConfig = (config as any).resources[this.resourceType];
23
+ // let data;
24
+ // let resData, modifiedDoc, modifiedDocsArr;
25
+ // let dirFlag = false;
26
+ // let pullCount = 0;
27
+ // if (ref) {
28
+ // resData = await client.single(ref);
29
+ // console.log(`Resource : ${resource} with Ref: ${ref} pulled`)
30
+ // modifiedDoc = client.modifyDoc(resData);
31
+ // data = yaml.dump(modifiedDoc);
32
+ // } else {
33
+ // resData = await client.all();
34
+ // pullCount= resData.length
35
+ // console.log(`Resource : ${resource}'s pulled with count: (${pullCount})`)
36
+ // modifiedDocsArr = resData.map((doc: any) => {
37
+ // let modifiedDoc = client.modifyDoc(doc);
38
+ // return yaml.dump(modifiedDoc);
39
+ // });
40
+ // if (extname(output) === ".yaml") {
41
+ // data = modifiedDocsArr.join("---\n");
42
+ // } else {
43
+ // if (!existsSync(output)) {
44
+ // mkdirSync(output, { recursive: true });
45
+ // }
46
+ // dirFlag = true;
47
+ // data = modifiedDocsArr;
48
+ // }
49
+ // }
50
+ // if (dirFlag) {
51
+ // for (const [index, doc] of data.entries()) {
52
+ // let filepath = join(output, `${resData[index].uuid}.yaml`);
53
+ // await this.writeToFile(filepath, doc);
54
+ // console.log(`Resource : ${resource} with UUID: ${resData[index].uuid} written to file` )
55
+ // }
56
+ // } else {
57
+ // await this.writeToFile(output, data);
58
+ // console.log(`Resource : ${resource}'s pulled and wriiten to file with count:(${pullCount})`)
59
+ // }
60
+ }
61
+ async writeToFile(path, doc) {
62
+ if (existsSync(path)) {
63
+ let rl = readlinePromises.createInterface(stdin, stdout);
64
+ let ans = await rl.question(`Do You want override the output file: ${basename(path)} -(y,n):`);
65
+ if (ans.trim() === "y")
66
+ writeFileSync(path, doc);
67
+ rl.close();
68
+ }
69
+ else {
70
+ writeFileSync(path, doc);
71
+ }
72
+ }
73
+ }
74
+ export default new Pull;
@@ -0,0 +1,63 @@
1
+ import { Command } from "commander";
2
+ import util from "../lib/util.js";
3
+ import Api from "protokol-sdk";
4
+ import OutputFormatCommand from "./outputCommand.js";
5
+ class RoleCommand {
6
+ register() {
7
+ return new Command("role")
8
+ .description("Manage roles")
9
+ .version("0.1.0")
10
+ .addCommand(new Command("create")
11
+ .description("Create role")
12
+ .requiredOption("-n, --name <name>", "name for the new role")
13
+ .requiredOption("-p, --permissions <permissions...>", "Permissions's array ")
14
+ .requiredOption("-w, --workspaces <workspaces...>", "Workspaces array ")
15
+ .option("-l --level <level>", "level of the role")
16
+ .action(this.create))
17
+ .addCommand(new Command("delete")
18
+ .description("Delete role")
19
+ .requiredOption("-u, --uuid <uuid>", "uuid of the role to delete")
20
+ .action(this.delete))
21
+ .addCommand(new OutputFormatCommand(new Command("list")
22
+ .description("list roles")).action(this.list))
23
+ .addCommand(new OutputFormatCommand(new Command("permissions-list")
24
+ .description("list permissions")).action(this.list))
25
+ .addCommand(new Command("edit")
26
+ .description("edit role")
27
+ .requiredOption("-u, --uuid <uuid>", "uuid of the role to edit")
28
+ .requiredOption("-p, --permissions <permissions...>", "Permissions's array ")
29
+ .requiredOption("-w, --workspaces <workspaces...>", "Workspaces array ")
30
+ .requiredOption("-l --level <level>", "level of the role")
31
+ .action(this.edit));
32
+ }
33
+ async create(options) {
34
+ let { name, permissions, workspaces, level } = options;
35
+ level = level ? Number(level) : 0;
36
+ const profile = util.getCurrentProfile();
37
+ const client = new Api({ project: profile.project, token: profile.token, host: profile.host }).role();
38
+ return await client.create({ name, workspaces, permissions, level });
39
+ }
40
+ async delete(opts) {
41
+ const { uuid } = opts;
42
+ const profile = util.getCurrentProfile();
43
+ const client = new Api({ project: profile.project, token: profile.token, host: profile.host }).role();
44
+ return await client.delete(uuid);
45
+ }
46
+ async list() {
47
+ const profile = util.getCurrentProfile();
48
+ const client = new Api({ project: profile.project, token: profile.token, host: profile.host }).role();
49
+ return await client.list();
50
+ }
51
+ async listPermissions() {
52
+ const profile = util.getCurrentProfile();
53
+ const client = new Api({ project: profile.project, token: profile.token, host: profile.host }).role();
54
+ return await client.list();
55
+ }
56
+ async edit(opts) {
57
+ let { uuid, permissions, workspaces, level } = opts;
58
+ const profile = util.getCurrentProfile();
59
+ const client = new Api({ project: profile.project, token: profile.token, host: profile.host }).role();
60
+ return await client.edit(permissions, workspaces, Number(level), uuid);
61
+ }
62
+ }
63
+ export default new RoleCommand();
@@ -0,0 +1,46 @@
1
+ import { Command } from "commander";
2
+ import util from "../lib/util.js";
3
+ import Api from "protokol-sdk";
4
+ class ApiUsersCommand {
5
+ register() {
6
+ return new Command("users")
7
+ .description("Manage users")
8
+ .version("0.1.0")
9
+ .addCommand(new Command("invite")
10
+ .description("invite a new user")
11
+ .requiredOption("-e, --email <email>", "user email ")
12
+ .requiredOption("-r, --roles <roles...>", "uuids of role seprated by space")
13
+ .action(this.invite))
14
+ .addCommand(new Command("delete")
15
+ .description("delete an existing user")
16
+ .requiredOption("-u, --uuid <uuid>", "UUID of the existing user")
17
+ .action(this.delete))
18
+ .addCommand(new Command("get-auth-token")
19
+ .description("Retrieve an auth token for an API user")
20
+ .requiredOption("-u, --user <user>", "Username or name of the API user")
21
+ .requiredOption("-p, --password <password>", "Password or secret for the API user")
22
+ .action(this.getAuthToken));
23
+ }
24
+ async invite(opts) {
25
+ const { email, roles } = opts;
26
+ const profile = util.getCurrentProfile();
27
+ const client = new Api({ project: profile.project, token: profile.token, host: profile.host }).user();
28
+ const secret = await client.invite(email, roles);
29
+ console.table([secret]);
30
+ }
31
+ async delete(opts) {
32
+ const { uuid } = opts;
33
+ const profile = util.getCurrentProfile();
34
+ const client = new Api({ project: profile.project, token: profile.token, host: profile.host }).user();
35
+ const status = await client.delete(uuid);
36
+ console.table([status]);
37
+ }
38
+ async getAuthToken(opts) {
39
+ const { user, password } = opts;
40
+ const profile = util.getCurrentProfile();
41
+ const client = new Api({ project: profile.project, token: profile.token, host: profile.host }).apiUser();
42
+ const auth = await client.apiAuth(user, password);
43
+ console.log(auth.data.Token);
44
+ }
45
+ }
46
+ export default new ApiUsersCommand();
package/dist/config.js ADDED
@@ -0,0 +1,69 @@
1
+ export default {
2
+ resources: {
3
+ function: {
4
+ latestVersion: 1,
5
+ schema: "v1.function", // used to store it in the yaml file
6
+ endpoints: {
7
+ all: "/v1/system/function", // method is always get
8
+ apply: `/v1/system/function/{ref}`, // method is always patch
9
+ // we will call single endpoint when pull command is provided with ref option
10
+ single: `/v1/system/function/{ref}`, // method is always get
11
+ },
12
+ },
13
+ component: {
14
+ latestVersion: 1,
15
+ schema: "v1.component",
16
+ endpoints: {
17
+ all: "/v1/system/components",
18
+ single: `/v1/system/components/{ref}`,
19
+ },
20
+ },
21
+ role: {
22
+ latestVersion: 1,
23
+ schema: "v1.role",
24
+ endpoints: {
25
+ all: "/v1/user/role/list",
26
+ apply: `/v1/user/role/edit/{ref}`,
27
+ single: `/v1/system/components/{ref}`,
28
+ },
29
+ methods: {
30
+ apply: "post",
31
+ },
32
+ handlers: {
33
+ all: async (client, resourceConfig) => {
34
+ const { data: roles } = await client.get(`/v1/user/role/list`);
35
+ const rolesWithPermissions = [];
36
+ return rolesWithPermissions;
37
+ },
38
+ },
39
+ },
40
+ apiuser: {
41
+ latestVersion: 1,
42
+ schema: "v1.apiuser",
43
+ endpoints: {
44
+ all: "/v1/user/api-user",
45
+ // apply: `/v1/user/api-user/{ref}`,
46
+ single: `/v1/user/api-user/{ref}`,
47
+ },
48
+ },
49
+ user: {
50
+ latestVersion: 1,
51
+ schema: "v1.user",
52
+ endpoints: {
53
+ all: "/v1/project/users",
54
+ apply: `/v1/project/user/{ref}`,
55
+ single: `/v1/project/user/{ref}`,
56
+ },
57
+ methods: {
58
+ apply: "put",
59
+ },
60
+ handlers: {
61
+ apply: async (client, doc) => {
62
+ const { data: roles } = await await client.get(`/v1/user/role/list`);
63
+ const rolesWithPermissions = [];
64
+ return rolesWithPermissions;
65
+ },
66
+ },
67
+ },
68
+ },
69
+ };
@@ -0,0 +1,9 @@
1
+ import chalk from "chalk";
2
+ export default class CLI {
3
+ static write(...args) {
4
+ console.log(chalk.white(args));
5
+ }
6
+ static writeTable(args) {
7
+ console.table(args);
8
+ }
9
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,46 @@
1
+ import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
2
+ import Api from 'protokol-sdk';
3
+ export default class Util {
4
+ static profilePath = `${process.env.HOME}/.ptkl`;
5
+ static fileName = "profiles.json";
6
+ static getProfiles() {
7
+ try {
8
+ const contents = JSON.parse(readFileSync(`${Util.profilePath}/${Util.fileName}`).toString());
9
+ return contents;
10
+ }
11
+ catch (err) {
12
+ throw new Error("There was a problem with getting profiles. Did you run 'init'?");
13
+ }
14
+ }
15
+ static updateProfiles(profiles) {
16
+ try {
17
+ const contents = JSON.stringify(profiles);
18
+ writeFileSync(`${Util.profilePath}/${Util.fileName}`, contents);
19
+ return profiles;
20
+ }
21
+ catch (err) {
22
+ throw new Error("There was a problem with updating profiles. Did you run 'init'?");
23
+ }
24
+ }
25
+ static init() {
26
+ try {
27
+ mkdirSync(Util.profilePath, { recursive: true });
28
+ writeFileSync(`${Util.profilePath}/${Util.fileName}`, '[]');
29
+ }
30
+ catch (err) {
31
+ throw new Error(`Failed to init: ${err.message}`);
32
+ }
33
+ }
34
+ static getCurrentProfile() {
35
+ const profiles = Util.getProfiles();
36
+ const profile = profiles?.find(p => p.current);
37
+ if (!profile) {
38
+ throw new Error("Current profile is not set. Run command `profile use {profile-name}`");
39
+ }
40
+ return profile;
41
+ }
42
+ static getClientForProfile() {
43
+ const profile = Util.getCurrentProfile();
44
+ return new Api({ project: profile.project, token: profile.token, host: profile.host });
45
+ }
46
+ }