This repository has been archived by the owner on Apr 27, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
422f7b7
commit d42e8c8
Showing
8 changed files
with
348 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export { Command } from "https://deno.land/x/[email protected]/command/mod.ts"; | ||
export { | ||
Confirm, | ||
Input, | ||
Secret, | ||
Select, | ||
} from "https://deno.land/x/[email protected]/prompt/mod.ts"; | ||
export type { SelectOptionSettings } from "https://deno.land/x/[email protected]/prompt/select.ts"; | ||
export { colors } from "https://deno.land/x/[email protected]/ansi/colors.ts"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { IAuthResponse } from "./types/api.ts"; | ||
import { Auth } from "./ui/auth.ts"; | ||
import { MainMenu } from "./ui/main-menu.ts"; | ||
import { clear } from "./ui/utils.ts"; | ||
|
||
export let jwt = ""; | ||
export let user = {}; | ||
|
||
async function main() { | ||
clear(); | ||
|
||
const data = await Auth() as IAuthResponse; | ||
jwt = data.jwt; | ||
user = data.user; | ||
|
||
await MainMenu.show(); | ||
} | ||
|
||
await main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
export interface IAuthPayload { | ||
email: string; | ||
password: string; | ||
} | ||
|
||
export interface IAuthResponse { | ||
jwt: string; | ||
user: IUser; | ||
} | ||
|
||
export interface IUser { | ||
id: number; | ||
} | ||
|
||
export interface IGroup { | ||
id?: number; | ||
name?: string; | ||
owner?: number; | ||
} | ||
|
||
export interface IUserGroup { | ||
id?: number; | ||
confirmed?: boolean; | ||
createdAt?: string; | ||
updatedAt?: string; | ||
blocked?: boolean; | ||
group?: IGroup; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { colors, Input, Secret } from "../deps.ts"; | ||
import { clear } from "./utils.ts"; | ||
import { IAuthPayload, IAuthResponse } from "../types/api.ts"; | ||
|
||
let email: string, | ||
password: string; | ||
|
||
email = "[email protected]"; | ||
password = "Valentin74!"; | ||
|
||
async function authenticate({ email, password }: IAuthPayload) { | ||
const res = await fetch("http://localhost:1337/api/auth/local", { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ identifier: email, password }), | ||
}); | ||
|
||
const resJson = await res.json(); | ||
|
||
if (resJson.error) { | ||
const err = resJson.error; | ||
return { | ||
data: null, | ||
error: colors.bold.red(`${err.name} (${err.status}): ${err.message}`), | ||
}; | ||
} | ||
|
||
return { | ||
data: { jwt: resJson.jwt as string, user: resJson.user } as IAuthResponse, | ||
error: false, | ||
}; | ||
} | ||
|
||
export async function Auth( | ||
errorMessage?: string, | ||
): Promise<IAuthResponse | void> { | ||
clear(errorMessage); | ||
|
||
const emailInput = Input; | ||
emailInput.inject(email); | ||
email = await emailInput.prompt({ | ||
message: "📧 Enter your email", | ||
minLength: 1, | ||
}); | ||
|
||
password = password ?? await Secret.prompt({ | ||
message: "🔒 Enter you password", | ||
minLength: 1, | ||
}); | ||
|
||
const { data, error } = await authenticate({ email, password }); | ||
|
||
if (error && typeof error === "string") { | ||
password = ""; | ||
return await Auth(error); | ||
} | ||
|
||
return data as IAuthResponse; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import { Select, SelectOptionSettings } from "../deps.ts"; | ||
import { jwt } from "../mod.ts"; | ||
|
||
interface ICliViewOptions { | ||
title?: string; | ||
parent?: CliView; | ||
prefetch?: IPrefetch; | ||
options: (arg0: IOptionsOptions) => Promise<SelectOptionSettings[] | void>; | ||
handleValue?: (value: string) => Promise<void>; | ||
} | ||
|
||
type CliViewParams = Record<string, unknown>; | ||
|
||
interface IOptionsOptions { | ||
params?: CliViewParams; | ||
data: Record<string, unknown>; | ||
} | ||
|
||
interface IPrefetch { | ||
url: string | ((params: CliViewParams) => string); | ||
method?: string; | ||
body?: Record<string, unknown>; | ||
} | ||
|
||
export class CliView { | ||
title; | ||
parent; | ||
prefetch; | ||
options; | ||
handleValue; | ||
params = {}; | ||
|
||
constructor(options: ICliViewOptions) { | ||
this.title = options.title; | ||
this.parent = options?.parent; | ||
this.prefetch = options?.prefetch; | ||
this.options = options.options; | ||
this.handleValue = options?.handleValue; | ||
} | ||
|
||
async show(params?: CliViewParams) { | ||
this.params = params ?? {}; | ||
|
||
this.clear(); | ||
|
||
const rawResponse = await this.fetchData(params); | ||
|
||
const options = await this.options({ params, data: rawResponse }); | ||
|
||
const value = await Select.prompt({ | ||
message: this.getTitle(), | ||
options: [ | ||
...(options || []), | ||
...( | ||
this.parent | ||
? [ | ||
Select.separator("——————————"), | ||
{ name: "⬅️ Go back", value: "back" }, | ||
] | ||
: [] | ||
), | ||
], | ||
}); | ||
|
||
if (value === "back") { | ||
if (this.parent) { | ||
await this.parent?.show(this.parent?.params); | ||
} | ||
} | ||
|
||
if (typeof this.handleValue === "function") { | ||
await this.handleValue(value); | ||
} | ||
} | ||
|
||
async fetchData(params?: CliViewParams) { | ||
let rawResponse; | ||
|
||
if (this.prefetch) { | ||
const url = typeof this.prefetch.url === "function" | ||
? this.prefetch.url({ ...params }) | ||
: this.prefetch.url; | ||
|
||
const res = await fetch(url, { | ||
method: this.prefetch.method ?? "GET", | ||
headers: { | ||
"Content-Type": "application/json", | ||
"Authorization": `Bearer ${jwt}`, | ||
}, | ||
body: typeof this.prefetch.body === "object" | ||
? JSON.stringify({ ...this.prefetch.body }) | ||
: undefined, | ||
}); | ||
|
||
rawResponse = await res.json(); | ||
} | ||
|
||
return rawResponse; | ||
} | ||
|
||
getTitle() { | ||
let title = ""; | ||
|
||
if (this.parent) { | ||
title += this.parent.getTitle() + " 〉"; | ||
} | ||
|
||
return title + this.title; | ||
} | ||
|
||
clear(messages?: string | string[]) { | ||
console.log("\x1Bc"); | ||
|
||
if (messages) { | ||
if (typeof messages === "string") { | ||
messages = [messages]; | ||
} | ||
|
||
messages.forEach((msg) => { | ||
console.error(msg); | ||
}); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import { Confirm, Input, Select, SelectOptionSettings } from "../deps.ts"; | ||
import { IGroup, IUserGroup } from "../types/api.ts"; | ||
import { clear } from "./utils.ts"; | ||
import { jwt } from "../mod.ts"; | ||
import { CliView } from "./class.ts"; | ||
|
||
export const GroupMain = new CliView({ | ||
title: "Groups", | ||
prefetch: { | ||
url: "http://localhost:1337/api/user-groups", | ||
}, | ||
options: async ({ data }) => | ||
await [ | ||
// @ts-ignore Data comming from api | ||
...data.data.map((ug: IUserGroup) => ({ | ||
name: `- ${ug?.group?.name}`, | ||
value: `${ug?.group?.id}`, | ||
})), | ||
Select.separator("——————————"), | ||
{ name: "🔍 Join a Group", value: "search", disabled: true }, | ||
{ name: "➕ Create new Group", value: "new" }, | ||
], | ||
handleValue: async (value) => { | ||
if (typeof +value === "number" && !isNaN(+value)) { | ||
await GroupDetails.show({ groupId: +value }); | ||
} | ||
}, | ||
}); | ||
|
||
export const GroupDetails = new CliView({ | ||
title: "Users", | ||
parent: GroupMain, | ||
prefetch: { | ||
url: (params) => { | ||
return typeof params?.groupId === "number" | ||
? `http://localhost:1337/api/groups/${+params.groupId}` | ||
: ""; | ||
}, | ||
}, | ||
options: async ({ data }) => { | ||
// @ts-ignore Data comming from api | ||
const allUserGroups = data?.attributes["user-groups"]; | ||
if (!Array.isArray(allUserGroups)) return await GroupMain.show(); | ||
return allUserGroups.map((ug) => ({ | ||
name: ug?.user?.username, | ||
value: "" + ug?.user?.id, | ||
} as SelectOptionSettings)); | ||
}, | ||
}); | ||
|
||
export async function GroupForm(_group?: IGroup) { | ||
clear(); | ||
|
||
const name = await Input.prompt({ | ||
message: "Enter group name", | ||
minLength: 1, | ||
}); | ||
|
||
const confirmed = await Confirm.prompt( | ||
`Are you sure you want to create group ${name}?`, | ||
); | ||
|
||
if (confirmed) { | ||
const res = await fetch("http://localhost:1337/api/groups", { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
"Authorization": `Bearer ${jwt}`, | ||
}, | ||
body: JSON.stringify({ data: { name } }), | ||
}); | ||
|
||
const resJson = await res.json(); | ||
|
||
if (typeof resJson?.data?.id === "number") { | ||
await GroupMain.show(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { CliView } from "./class.ts"; | ||
import { GroupMain } from "./group.ts"; | ||
|
||
export const MainMenu = new CliView({ | ||
title: "Pronocup", | ||
options: async () => | ||
await [ | ||
{ name: "👥 Groups", value: "group", disabled: false }, | ||
{ name: "⚽ Predictions", value: "group", disabled: false }, | ||
], | ||
handleValue: async (value) => { | ||
const views = { group: GroupMain } as Record<string, CliView>; | ||
if (Object.keys(views).includes(value)) return await views[value].show(); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export function clear(messages?: string | string[]) { | ||
console.log("\x1Bc"); | ||
|
||
if (messages) { | ||
if (typeof messages === "string") { | ||
messages = [messages]; | ||
} | ||
|
||
messages.forEach((msg) => { | ||
console.error(msg); | ||
}); | ||
} | ||
} |