@npio/cli
Version:
A free visual website editor, powered with your own SolidJS components.
177 lines (157 loc) • 4.33 kB
text/typescript
import {
cancel,
group,
intro,
log,
outro,
password,
spinner,
text,
} from "@clack/prompts";
import { hashPassword, useDatabase } from "nitropage/server";
import c from "picocolors";
import type sade from "sade";
const confirmedPassword = async function (): Promise<string> {
const result = await group(
{
pw: () =>
password({
message: "What is the password?",
validate(value) {
if (!value) return "Password is required!";
},
}),
pw2: () =>
password({
message: "Please confirm the password",
}),
},
{
onCancel(opts) {
cancel("Cancelled.");
process.exit();
},
},
);
if (result.pw !== result.pw2) {
log.error("The passwords did not match!");
return await confirmedPassword();
}
return result.pw;
};
export const userCommands = function (prog: sade.Sade) {
prog
.command("user list")
.describe("List up the registered users")
.action(async function () {
const client = useDatabase();
const users = await client.nitroUser.findMany({
select: {
id: true,
email: true,
username: true,
admin: true,
},
});
for (const { id, email, username, admin } of users) {
console.log({
id,
email,
username,
admin,
});
}
});
prog
.command("user set <id>")
.describe("Update fields of the specified user")
.option("--password, -p", "Provide new password")
.action(
async (id: string, { password }: { password: string | boolean }) => {
intro("Update user");
const data: { password?: string } = {};
if (password) {
if (typeof password === "boolean") {
password = await confirmedPassword();
}
data.password = await hashPassword(password);
}
const s = spinner();
s.start("Updating");
if (Object.keys(data).length === 0) {
s.stop("Nothing to update.");
outro("Done.");
return;
}
const client = useDatabase();
const result = await client.nitroUser.updateMany({
where: {
id,
},
data,
});
s.stop("Database query executed.");
if (!result.count) {
log.warn(`No user with id ${c.bold(id)} found.`);
outro("Done.");
process.exit(1);
}
outro(`Updated user ${c.bold(id)}.`);
},
);
prog
.command("user add")
.describe("Create a new user")
.action(async () => {
const client = useDatabase();
const users = await client.nitroUser.findMany({
select: {
username: true,
email: true,
},
});
const existingMails = users.map((user) => user.email);
const existingUsernames = users.map((user) => user.username);
intro("Let's create a new user!");
const result = await group(
{
username: () =>
text({
message: "What is the username?",
validate(value) {
if (value.length === 0) return "Username is required!";
if (existingUsernames.includes(value))
return "Username already exists!";
},
}),
email: () =>
text({
message: "What is the email address?",
validate(value) {
if (value.length === 0) return "Email address is required!";
if (!value.includes("@")) return "Email address is incorrect!";
if (existingMails.includes(value))
return "Email address already exists!";
},
}),
},
{
onCancel(opts) {
cancel("Creation cancelled.");
process.exit();
},
},
);
const { username, email } = result;
const pw = await confirmedPassword();
await client.nitroUser.create({
data: {
email,
username,
password: await hashPassword(pw),
admin: true,
},
});
outro(`User ${c.bold(username)} <${email}> created.`);
});
};