tering-serieuze-cli 1.0.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.
package/.prettierrc ADDED
@@ -0,0 +1,2 @@
1
+ tabWidth: 4
2
+ printWidth: 120
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # Tering serieuze CLI
package/build.mjs ADDED
@@ -0,0 +1,19 @@
1
+ let makeAllPackagesExternalPlugin = {
2
+ name: "make-all-packages-external",
3
+ setup(build) {
4
+ let filter = /^[^.\/]|^\.[^.\/]|^\.\.[^\/]/; // Must not start with "/" or "./" or "../"
5
+ build.onResolve({ filter }, (args) => ({ path: args.path, external: true }));
6
+ },
7
+ };
8
+
9
+ import esbuild from "esbuild";
10
+
11
+ esbuild.build({
12
+ entryPoints: ["./src/index.ts"],
13
+ bundle: true,
14
+ sourcemap: true,
15
+ platform: "node",
16
+ outfile: "dist/index.mjs",
17
+ format: "esm",
18
+ plugins: [makeAllPackagesExternalPlugin],
19
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,141 @@
1
+ #! /usr/bin/env node --no-warnings
2
+
3
+ // src/index.ts
4
+ import { Command } from "commander";
5
+ import figlet from "figlet";
6
+ import inquirer from "inquirer";
7
+ import { TssApi, FilesystemCache, OnePasswordCache } from "tering-serieuze-sdk";
8
+
9
+ // src/completion.ts
10
+ import omelette from "omelette";
11
+ async function initCompletion(api2) {
12
+ const playCompletion = {};
13
+ const jingleFolders = await api2.jingle.getGrouped();
14
+ jingleFolders.forEach((jingleFolder) => {
15
+ playCompletion[jingleFolder.folder] = jingleFolder.jingles.map((jingle) => jingle.file);
16
+ });
17
+ const autocompletionTree = {
18
+ ["autocomplete" /* autocomplete */]: ["--install", "--uninstall"],
19
+ ["clearcache" /* clearcache */]: ["auth", "jingle", "all"],
20
+ ["login" /* login */]: [],
21
+ ["play" /* play */]: playCompletion,
22
+ ["jingles" /* jingles */]: [],
23
+ ["p" /* playShort */]: [],
24
+ ["version" /* version */]: []
25
+ };
26
+ const completion2 = omelette("tss").tree(autocompletionTree);
27
+ completion2.init();
28
+ return completion2;
29
+ }
30
+
31
+ // package.json
32
+ var version = "1.0.0";
33
+
34
+ // src/index.ts
35
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
36
+ var Commands = /* @__PURE__ */ ((Commands2) => {
37
+ Commands2["autocomplete"] = "autocomplete";
38
+ Commands2["clearcache"] = "clearcache";
39
+ Commands2["login"] = "login";
40
+ Commands2["play"] = "play";
41
+ Commands2["jingles"] = "jingles";
42
+ Commands2["playShort"] = "p";
43
+ Commands2["version"] = "version";
44
+ return Commands2;
45
+ })(Commands || {});
46
+ var api = new TssApi({
47
+ jingle: new FilesystemCache("jingle"),
48
+ auth: new OnePasswordCache("TSS-TOKEN")
49
+ });
50
+ var program = new Command();
51
+ var completion = await initCompletion(api);
52
+ if (process.argv.length <= 2 || process.argv[2] === "help") {
53
+ console.log(figlet.textSync("TSS CLI"));
54
+ }
55
+ program.name("tss").description("D\xE9 TSS CLI. Dit ding heeft alles.");
56
+ program.command("autocomplete" /* autocomplete */).description("Install or uninstall TSS CLI autocomplete").option("-i, --install", "Install TSS CLI autocomplete").option("-u, --uninstall", "Uninstall TSS CLI autocomplete").action(async (options) => {
57
+ if (options.install) {
58
+ console.log("TSS CLI autocomplete installed!");
59
+ completion.setupShellInitFile();
60
+ }
61
+ if (options.uninstall) {
62
+ console.log("TSS autocomplete uninstalled.");
63
+ completion.cleanupShellInitFile();
64
+ }
65
+ });
66
+ program.command("login" /* login */).description("Authenticate yourself so you can communicate with the TSS API").action(async () => {
67
+ const { token } = await inquirer.prompt([
68
+ {
69
+ type: "password",
70
+ name: "token",
71
+ message: "What is your token?"
72
+ }
73
+ ]);
74
+ try {
75
+ await api.auth.setToken(token);
76
+ } catch (e) {
77
+ console.error("Can't set the token");
78
+ return;
79
+ }
80
+ try {
81
+ const user = await api.user.get();
82
+ console.log("Logged in as " + user.email);
83
+ } catch (e) {
84
+ console.error("Invalid token!");
85
+ await api.auth.removeToken();
86
+ }
87
+ });
88
+ program.command("clearcache" /* clearcache */).description("Clear the cache").argument("[type]", "The type of cache to clear (jingle, auth, all)").action(async (type) => {
89
+ if (type === "jingle") {
90
+ await api.jingle.getCache().clear();
91
+ console.log("Cleared jingle cache");
92
+ } else if (type === "auth") {
93
+ await api.auth.removeToken();
94
+ console.log("Cleared auth cache");
95
+ } else if (type === "all" || !type) {
96
+ await api.auth.removeToken();
97
+ await api.jingle.getCache().clear();
98
+ console.log("Cleared all caches");
99
+ }
100
+ });
101
+ program.command("jingles" /* jingles */).description("Show all jingles").action(async () => {
102
+ const jingles = await api.jingle.getAll();
103
+ jingles.forEach((jingle) => {
104
+ console.log(jingle.folder + "/" + jingle.file);
105
+ });
106
+ });
107
+ program.command("play" /* play */).description("Play a jingle").argument("<folder>", "The folder of the jingle").argument("<file>", "The jingle to play").action(async (folder, file) => {
108
+ api.jingle.play(folder, file);
109
+ });
110
+ program.command("p" /* playShort */).description("Play a jingle by typing (some) parts of the name").argument("<query...>", "The query to search for").action(async (query) => {
111
+ const jingles = await api.jingle.getAll();
112
+ const matches = jingles.filter((jingle) => query.every((q) => (jingle.folder + "/" + jingle.file).includes(q)));
113
+ if (matches.length === 0) {
114
+ console.log("No matches found");
115
+ } else if (matches.length === 1) {
116
+ api.jingle.play(matches[0].folder, matches[0].file);
117
+ } else {
118
+ const sortedMatches = matches.sort((a, b) => {
119
+ const aScore = a.keywords.filter((k) => query.includes(k)).length;
120
+ const bScore = b.keywords.filter((k) => query.includes(k)).length;
121
+ return bScore - aScore;
122
+ });
123
+ const answers = await inquirer.prompt([
124
+ {
125
+ type: "list",
126
+ name: "jingle",
127
+ message: "Which jingle do you want to play?",
128
+ choices: sortedMatches.map((jingle) => jingle.folder + "/" + jingle.file)
129
+ }
130
+ ]);
131
+ const [folder, file] = answers.jingle.split("/");
132
+ api.jingle.play(folder, file);
133
+ }
134
+ });
135
+ program.command("version" /* version */).description("Show the TSS-CLI version").action(() => {
136
+ console.log(version);
137
+ });
138
+ program.parse();
139
+ export {
140
+ Commands
141
+ };
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts", "../../tering-serieuze-library/dist/index.mjs", "../src/completion.ts"],
4
+ "sourcesContent": ["#! /usr/bin/env node\n\nimport { Command } from \"commander\";\nimport figlet from \"figlet\";\n// import inquirer from \"inquirer\";\nimport { authModule, jingleModule, store } from \"tering-serieuze-library\";\nimport omelette from \"omelette\";\nimport fs from \"fs\";\nimport { initCompletion } from \"./completion\";\n\nconst inquirer = await import(\"inquirer\");\n\nprocess.env.NODE_TLS_REJECT_UNAUTHORIZED = \"0\";\n\nenum Commands {\n autocomplete = \"autocomplete\",\n login = \"login\",\n clearCache = \"clear-cache\",\n jingles = \"jingles\",\n}\n\nconst program = new Command();\nconst completion = initCompletion();\n\nif (process.argv.length <= 2 || process.argv[2] === \"help\") {\n console.log(figlet.textSync(\"TSS CLI\"));\n}\n\nprogram.name(\"tss\").description(\"D\u00E9 TSS CLI. Dit ding heeft alles.\");\n\nprogram\n .command(\"autocomplete\")\n .description(\"Install or uninstall TSS CLI autocomplete\")\n .option(\"-i, --install\", \"Install TSS CLI autocomplete\")\n .option(\"-u, --uninstall\", \"Uninstall TSS CLI autocomplete\")\n .action(async (options) => {\n if (options.install) {\n console.log(\"TSS CLI autocomplete installed!\");\n completion.setupShellInitFile();\n }\n\n if (options.uninstall) {\n console.log(\"TSS autocomplete uninstalled.\");\n completion.cleanupShellInitFile();\n }\n });\n\nprogram\n .command(\"login\")\n .description(\"Authenticate yourself so you can communicate with the TSS API\")\n .action(() => {\n inquirer\n .prompt([\n {\n type: \"input\",\n name: \"token\",\n message: \"What is your token?\",\n },\n ])\n .then(async (answers) => {\n await authModule.setToken(answers.token);\n });\n });\n\nprogram\n .command(\"clear-cache\")\n .description(\"Clear the cache\")\n .action(() => {\n store.reset();\n console.log(\"Cache cleared!\");\n });\n\nprogram\n .command(\"jingles\")\n .description(\"List al jingles\")\n .action(async () => {\n const jingles = await jingleModule.getAll();\n console.log(jingles);\n });\n\nprogram.parse();\n", "// src/api/auth.ts\nimport { promisify } from \"util\";\nimport { exec } from \"child_process\";\nvar asyncExec = promisify(exec);\nvar authModule = {\n async getToken() {\n const { stdout } = await asyncExec('op item get \"TSS-TOKEN\" --fields label=credential --format json');\n return JSON.parse(stdout).value;\n },\n async setToken(token) {\n const title = \"TSS-TOKEN\";\n let action = `op item edit '${title}' 'credential=${token}'`;\n try {\n const t = await this.getToken();\n console.log(t);\n } catch (e) {\n console.log(\"override action\");\n action = `op item create --category=\"API Credential\" --title ${title} 'credential=${token}'`;\n }\n const { stdout, stderr } = await asyncExec(action);\n console.log(stdout ?? stderr ?? \"Token set!\");\n }\n};\n\n// src/store/index.ts\nimport { readFileSync, existsSync, writeFileSync, mkdirSync } from \"fs\";\nimport path from \"path\";\nimport os from \"os\";\nvar filePath = path.join(os.homedir(), \"/.tss/state.json\");\nvar defaultState = { jingles: { items: [], expires: -1 } };\nvar store = {\n _state: defaultState,\n initialized: false,\n get state() {\n if (!this.initialized && existsSync(filePath)) {\n this.initialized = true;\n this._state = JSON.parse(readFileSync(filePath, \"utf8\"));\n }\n return this._state;\n },\n set state(state) {\n this._state = state;\n writeState(this._state);\n },\n setItem(key, value) {\n this._state[key] = value;\n writeState(this._state);\n },\n reset() {\n this.state = defaultState;\n }\n};\nfunction writeState(state) {\n if (!existsSync(path.dirname(filePath))) {\n mkdirSync(path.dirname(filePath));\n }\n writeFileSync(filePath, JSON.stringify(state));\n}\n\n// src/api/jingle.ts\nvar jingleModule = {\n async getAll() {\n if (store.state.jingles.items.length === 0 || store.state.jingles.expires <= Date.now()) {\n const items = await apiFetch(\"https://localhost:8081/api/jingle/grouped\");\n const oneWeek = 1e3 * 60 * 60 * 24 * 7;\n const expires = Date.now() + oneWeek;\n store.setItem(\"jingles\", { items, expires });\n }\n return store.state.jingles.items;\n },\n getForcedFromCache() {\n return store.state.jingles.items;\n }\n};\n\n// src/api/index.ts\nasync function apiFetch(url, config = {}) {\n config.method = config.method ?? \"GET\";\n config.headers = {\n ...config.headers,\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${await authModule.getToken()}`\n };\n const response = await fetch(url, config);\n return response.json();\n}\nexport {\n apiFetch,\n authModule,\n jingleModule,\n store\n};\n", "import { jingleModule } from \"../../tering-serieuze-library\";\nimport omelette from \"omelette\";\n\nexport function initCompletion() {\n const playCompletion: { [key: string]: string[] } = {};\n jingleModule.getForcedFromCache().forEach((jingleFolder) => {\n console.log(\"xxx\");\n if (!jingleFolder.jingles) {\n console.log(jingleFolder);\n }\n playCompletion[jingleFolder.folder] = jingleFolder.jingles.map((jingle) => jingle.file);\n });\n\n const completion = omelette(\"tss\").tree({\n play: playCompletion,\n });\n completion.init();\n\n return completion;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["authModule", "jingleModule", "store", "completion", "authModule", "store", "jingleModule"]
7
+ }
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "tering-serieuze-cli",
3
+ "version": "1.0.0",
4
+ "description": "Teringserieuze CLI",
5
+ "author": "Frank",
6
+ "main": "dist/index.mjs",
7
+ "type": "module",
8
+ "scripts": {
9
+ "dev": "esbuild src/index.ts --bundle --platform=node --outfile=dist/index.mjs --packages=external --format=esm --watch",
10
+ "build": "esbuild src/index.ts --bundle --platform=node --outfile=dist/index.mjs --packages=external --format=esm"
11
+ },
12
+ "bin": {
13
+ "tss": "dist/index.mjs"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+ssh://git@gitlab.com/tering-serieuze-shit/tering-serieuze-cli.git"
18
+ },
19
+ "license": "ISC",
20
+ "bugs": {
21
+ "url": "https://gitlab.com/tering-serieuze-shit/tering-serieuze-cli/issues"
22
+ },
23
+ "homepage": "https://gitlab.com/tering-serieuze-shit/tering-serieuze-cli#readme",
24
+ "dependencies": {
25
+ "@types/node": "^18.11.18",
26
+ "commander": "^9.4.1",
27
+ "completion": "^1.0.3",
28
+ "figlet": "^1.5.2",
29
+ "inquirer": "^9.1.4",
30
+ "omelette": "^0.4.17",
31
+ "tering-serieuze-sdk": "^1.0.1",
32
+ "tering-serieuze-types": "^1.8.4"
33
+ },
34
+ "devDependencies": {
35
+ "@types/figlet": "^1.5.5",
36
+ "@types/inquirer": "^9.0.3",
37
+ "@types/omelette": "^0.4.2",
38
+ "esbuild": "^0.16.12",
39
+ "prettier": "^2.8.1"
40
+ }
41
+ }
@@ -0,0 +1,26 @@
1
+ import omelette from "omelette";
2
+ import { Commands } from "./index";
3
+ import { TssApi } from "tering-serieuze-sdk";
4
+
5
+ export async function initCompletion(api: TssApi) {
6
+ const playCompletion: { [key: string]: string[] } = {};
7
+ const jingleFolders = await api.jingle.getGrouped();
8
+ jingleFolders.forEach((jingleFolder) => {
9
+ playCompletion[jingleFolder.folder] = jingleFolder.jingles.map((jingle) => jingle.file);
10
+ });
11
+
12
+ const autocompletionTree: { [key in Commands]: any } = {
13
+ [Commands.autocomplete]: ["--install", "--uninstall"],
14
+ [Commands.clearcache]: ["auth", "jingle", "all"],
15
+ [Commands.login]: [],
16
+ [Commands.play]: playCompletion,
17
+ [Commands.jingles]: [],
18
+ [Commands.playShort]: [],
19
+ [Commands.version]: [],
20
+ };
21
+
22
+ const completion = omelette("tss").tree(autocompletionTree);
23
+ completion.init();
24
+
25
+ return completion;
26
+ }
package/src/index.ts ADDED
@@ -0,0 +1,160 @@
1
+ #! /usr/bin/env node --no-warnings
2
+
3
+ import { Command } from "commander";
4
+ import figlet from "figlet";
5
+ import inquirer from "inquirer";
6
+ import { TssApi, FilesystemCache, OnePasswordCache } from "tering-serieuze-sdk";
7
+ import { initCompletion } from "./completion";
8
+ // @ts-ignore
9
+ import { version } from "../package.json";
10
+
11
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
12
+
13
+ export enum Commands {
14
+ autocomplete = "autocomplete",
15
+ clearcache = "clearcache",
16
+ login = "login",
17
+ play = "play",
18
+ jingles = "jingles",
19
+ playShort = "p",
20
+ version = "version",
21
+ }
22
+
23
+ const api = new TssApi({
24
+ jingle: new FilesystemCache("jingle"),
25
+ auth: new OnePasswordCache("TSS-TOKEN"),
26
+ });
27
+
28
+ const program = new Command();
29
+ const completion = await initCompletion(api);
30
+
31
+ if (process.argv.length <= 2 || process.argv[2] === "help") {
32
+ console.log(figlet.textSync("TSS CLI"));
33
+ }
34
+
35
+ program.name("tss").description("Dé TSS CLI. Dit ding heeft alles.");
36
+
37
+ program
38
+ .command(Commands.autocomplete)
39
+ .description("Install or uninstall TSS CLI autocomplete")
40
+ .option("-i, --install", "Install TSS CLI autocomplete")
41
+ .option("-u, --uninstall", "Uninstall TSS CLI autocomplete")
42
+ .action(async (options) => {
43
+ if (options.install) {
44
+ console.log("TSS CLI autocomplete installed!");
45
+ completion.setupShellInitFile();
46
+ }
47
+
48
+ if (options.uninstall) {
49
+ console.log("TSS autocomplete uninstalled.");
50
+ completion.cleanupShellInitFile();
51
+ }
52
+ });
53
+
54
+ program
55
+ .command(Commands.login)
56
+ .description("Authenticate yourself so you can communicate with the TSS API")
57
+ .action(async () => {
58
+ const { token } = await inquirer.prompt([
59
+ {
60
+ type: "password",
61
+ name: "token",
62
+ message: "What is your token?",
63
+ },
64
+ ]);
65
+
66
+ try {
67
+ await api.auth.setToken(token);
68
+ } catch (e) {
69
+ console.error("Can't set the token");
70
+ return;
71
+ }
72
+
73
+ try {
74
+ const user = await api.user.get();
75
+ console.log("Logged in as " + user.email);
76
+ } catch (e) {
77
+ console.error("Invalid token!");
78
+ await api.auth.removeToken();
79
+ }
80
+ });
81
+
82
+ program
83
+ .command(Commands.clearcache)
84
+ .description("Clear the cache")
85
+ .argument("[type]", "The type of cache to clear (jingle, auth, all)")
86
+ .action(async (type) => {
87
+ if (type === "jingle") {
88
+ await api.jingle.getCache().clear();
89
+ console.log("Cleared jingle cache");
90
+ } else if (type === "auth") {
91
+ await api.auth.removeToken();
92
+ console.log("Cleared auth cache");
93
+ } else if (type === "all" || !type) {
94
+ await api.auth.removeToken();
95
+ await api.jingle.getCache().clear();
96
+ console.log("Cleared all caches");
97
+ }
98
+ });
99
+
100
+ program
101
+ .command(Commands.jingles)
102
+ .description("Show all jingles")
103
+ .action(async () => {
104
+ const jingles = await api.jingle.getAll();
105
+ jingles.forEach((jingle) => {
106
+ console.log(jingle.folder + "/" + jingle.file);
107
+ });
108
+ });
109
+
110
+ program
111
+ .command(Commands.play)
112
+ .description("Play a jingle")
113
+ .argument("<folder>", "The folder of the jingle")
114
+ .argument("<file>", "The jingle to play")
115
+ .action(async (folder, file) => {
116
+ api.jingle.play(folder, file);
117
+ });
118
+
119
+ program
120
+ .command(Commands.playShort)
121
+ .description("Play a jingle by typing (some) parts of the name")
122
+ .argument("<query...>", "The query to search for")
123
+ .action(async (query: string[]) => {
124
+ const jingles = await api.jingle.getAll();
125
+ const matches = jingles.filter((jingle) => query.every((q) => (jingle.folder + "/" + jingle.file).includes(q)));
126
+
127
+ if (matches.length === 0) {
128
+ console.log("No matches found");
129
+ } else if (matches.length === 1) {
130
+ api.jingle.play(matches[0].folder, matches[0].file);
131
+ } else {
132
+ const sortedMatches = matches.sort((a, b) => {
133
+ const aScore = a.keywords.filter((k) => query.includes(k)).length;
134
+ const bScore = b.keywords.filter((k) => query.includes(k)).length;
135
+
136
+ return bScore - aScore;
137
+ });
138
+
139
+ const answers = await inquirer.prompt([
140
+ {
141
+ type: "list",
142
+ name: "jingle",
143
+ message: "Which jingle do you want to play?",
144
+ choices: sortedMatches.map((jingle) => jingle.folder + "/" + jingle.file),
145
+ },
146
+ ]);
147
+
148
+ const [folder, file] = answers.jingle.split("/");
149
+ api.jingle.play(folder, file);
150
+ }
151
+ });
152
+
153
+ program
154
+ .command(Commands.version)
155
+ .description("Show the TSS-CLI version")
156
+ .action(() => {
157
+ console.log(version);
158
+ });
159
+
160
+ program.parse();
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "rootDir": "src",
4
+ "outDir": "dist",
5
+ "strict": true,
6
+ "target": "ESNext",
7
+ "module": "ES2022",
8
+ "sourceMap": true,
9
+ "esModuleInterop": true,
10
+ "moduleResolution": "Node",
11
+ "experimentalDecorators": true,
12
+ "strictPropertyInitialization": false
13
+ }
14
+ }