Skip to content

Commit 15546be

Browse files
authored
Merge pull request #80 from fedify-dev/create-account
Add create account cli, `geneate:account`
2 parents 52b7443 + fa5adf4 commit 15546be

5 files changed

Lines changed: 135 additions & 13 deletions

File tree

‎.github/workflows/main.yaml‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ on:
66
branches: ["**"]
77
tags: ["*.*.*"]
88

9-
env:
10-
AUBE_ALLOWED_UNPOPULAR_PACKAGES: pglite-cli
11-
129
jobs:
1310
check:
1411
runs-on: ubuntu-latest

‎mise.toml‎

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ experimental = true
77
"aqua:dahlia/hongdown" = "0.4.3"
88
"github:nushell/nushell" = "0.114.1"
99
node = "26"
10-
"npm:@fedify/cli" = "2.4.0-dev.1758"
10+
"npm:@fedify/cli" = { version = "2.4.0-dev.1758", allow_low_downloads = true }
1111
"npm:oxlint" = "1.75.0"
1212
"npm:oxlint-tsgolint" = "7.0.2001"
13-
"npm:pglite-cli" = "0.0.1"
13+
"npm:pglite-cli" = { version = "0.0.1", allow_low_downloads = true }
1414
oxfmt = "0.55.0"
1515
pnpm = "11"
1616

@@ -124,6 +124,20 @@ run = """
124124
node scripts/bump-versions.mts $env.usage_version
125125
"""
126126

127+
[tasks."generate:account"]
128+
description = "Create an account in the development PGlite database"
129+
depends = ["build:server"]
130+
usage = '''
131+
arg "<email>" help="Account email address"
132+
arg "<name>" help="Account display name"
133+
'''
134+
run = '''
135+
#!/usr/bin/env nu
136+
$env.email = $env.usage_email
137+
$env.name = $env.usage_name
138+
node scripts/create-account.mts
139+
'''
140+
127141
[tasks."generate:migrate"]
128142
description = "Generate database migration files"
129143
usage = """

‎package.json‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
{
22
"private": true,
33
"devDependencies": {
4-
"skills-npm": "catalog:"
4+
"skills-npm": "catalog:",
5+
"@drfed/models": "workspace:*",
6+
"@electric-sql/pglite": "catalog:",
7+
"@logtape/logtape": "catalog:",
8+
"drizzle-orm": "catalog:"
59
},
610
"scripts": {
711
"prepare": "skills-npm --recursive --yes --force"

‎pnpm-lock.yaml‎

Lines changed: 20 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎scripts/create-account.mts‎

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// DrFed: A web-based platform for developing and debugging ActivityPub apps
2+
// Copyright (C) 2026 DrFed team
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
// oxlint-disable no-console
17+
import process from "node:process";
18+
19+
import { normalizeEmail } from "@drfed/models/email";
20+
import { accounts } from "@drfed/models/schema";
21+
import { uuidV7 } from "@drfed/models/uuid";
22+
import { PGlite } from "@electric-sql/pglite";
23+
import { configure, getConsoleSink, getLogger } from "@logtape/logtape";
24+
import { drizzle } from "drizzle-orm/pglite";
25+
26+
await configure({
27+
sinks: {
28+
console: getConsoleSink(),
29+
},
30+
loggers: [
31+
{
32+
category: ["drfed"],
33+
lowestLevel: "info",
34+
sinks: ["console"],
35+
},
36+
{
37+
category: ["logtape", "meta"],
38+
lowestLevel: "warning",
39+
sinks: ["console"],
40+
},
41+
],
42+
});
43+
44+
const logger = getLogger(["drfed", "create-account"]);
45+
46+
async function main(): Promise<void> {
47+
const email = normalizeEmail(process.env.email ?? "");
48+
const name = (process.env.name ?? "").trim();
49+
const created = new Date();
50+
const accountId = uuidV7();
51+
52+
if (email.length > 255 || !/^[^@]+@[^@]+\.[^@]+$/u.test(email)) {
53+
throw new Error("Invalid email address (maximum 255 characters).");
54+
}
55+
if (name === "" || name.length > 100) {
56+
throw new Error("Name must contain 1 to 100 characters.");
57+
}
58+
59+
const pgData = ".pgdata";
60+
const client = new PGlite(pgData);
61+
62+
try {
63+
const [account] = await drizzle({ client })
64+
.insert(accounts)
65+
.values([
66+
{
67+
id: accountId,
68+
email,
69+
name,
70+
created,
71+
},
72+
])
73+
.onConflictDoNothing({ target: accounts.email })
74+
.returning({ id: accounts.id });
75+
76+
if (account) {
77+
logger.info("Created account {email} {accountId}", {
78+
email,
79+
accountId: account.id,
80+
});
81+
} else {
82+
logger.warn("Account already exists");
83+
}
84+
} finally {
85+
await client.close();
86+
}
87+
}
88+
89+
try {
90+
await main();
91+
} catch (error) {
92+
logger.error("Failed to create account: {error}", { error });
93+
process.exitCode = 1;
94+
}

0 commit comments

Comments
 (0)