@smuzi/logger-ui 0.0.1 → 0.0.3
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/build/auth.d.ts +17 -0
- package/build/auth.js +104 -0
- package/build/commands.d.ts +7 -0
- package/build/commands.js +67 -0
- package/build/handlers.d.ts +8 -2
- package/build/handlers.js +108 -10
- package/build/index.d.ts +4 -0
- package/build/index.js +4 -0
- package/build/password.d.ts +4 -0
- package/build/password.js +33 -0
- package/build/query.js +6 -0
- package/build/routes.d.ts +7 -2
- package/build/routes.js +16 -6
- package/build/server.d.ts +3 -2
- package/build/server.js +4 -4
- package/build/ui/app.css +1 -1
- package/build/ui/app.js +2 -2
- package/build/ui/index.html +126 -15
- package/build/ui/login.html +37 -0
- package/build/users.d.ts +19 -0
- package/build/users.js +68 -0
- package/package.json +10 -4
package/build/users.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Migration, Migrations } from "@smuzi/database";
|
|
2
|
+
import { Err, None, Ok, panic, Some } from "@smuzi/std";
|
|
3
|
+
export const LOGGER_UI_USERS_DEFAULT_TABLE = "logger_ui_users";
|
|
4
|
+
// The table name is interpolated into SQL, so only plain identifiers are accepted.
|
|
5
|
+
function assertTableName(table) {
|
|
6
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(table)) {
|
|
7
|
+
panic(`Invalid logger UI users table name '${table}'`);
|
|
8
|
+
}
|
|
9
|
+
return table;
|
|
10
|
+
}
|
|
11
|
+
export function normalizeEmail(email) {
|
|
12
|
+
return email.trim().toLowerCase();
|
|
13
|
+
}
|
|
14
|
+
export const loggerUiMigrations = (users_table = LOGGER_UI_USERS_DEFAULT_TABLE) => {
|
|
15
|
+
const table = assertTableName(users_table);
|
|
16
|
+
const migrations = Migrations('smuzi:logger-ui:');
|
|
17
|
+
migrations.add('create_' + table, Migration({
|
|
18
|
+
up: () => (`
|
|
19
|
+
CREATE TABLE IF NOT EXISTS ${table} (
|
|
20
|
+
id SERIAL PRIMARY KEY,
|
|
21
|
+
email VARCHAR(255) NOT NULL UNIQUE,
|
|
22
|
+
password_hash VARCHAR(255) NOT NULL,
|
|
23
|
+
created_at TIMESTAMPTZ NOT NULL
|
|
24
|
+
);`),
|
|
25
|
+
down: () => `DROP TABLE IF EXISTS ${table};`
|
|
26
|
+
}));
|
|
27
|
+
return migrations;
|
|
28
|
+
};
|
|
29
|
+
export class LoggerUiUsersRepository {
|
|
30
|
+
#db_client;
|
|
31
|
+
#table;
|
|
32
|
+
constructor(table, db_client) {
|
|
33
|
+
this.#db_client = db_client;
|
|
34
|
+
this.#table = assertTableName(table);
|
|
35
|
+
}
|
|
36
|
+
async #findOne(where, value) {
|
|
37
|
+
const result = await this.#db_client.query(`SELECT id, email, password_hash, created_at FROM ${this.#table} WHERE ${where} = $1 LIMIT 1`, [value]);
|
|
38
|
+
if (result.isErr()) {
|
|
39
|
+
return Err(result.unsafeSource().toError());
|
|
40
|
+
}
|
|
41
|
+
const row = result.unwrap().rows.unsafeSource()[0];
|
|
42
|
+
return Ok(row === undefined ? None() : Some(row));
|
|
43
|
+
}
|
|
44
|
+
async findByEmail(email) {
|
|
45
|
+
return this.#findOne("email", normalizeEmail(email));
|
|
46
|
+
}
|
|
47
|
+
async findById(id) {
|
|
48
|
+
return this.#findOne("id", id);
|
|
49
|
+
}
|
|
50
|
+
async create(email, password_hash) {
|
|
51
|
+
const result = await this.#db_client.query(`INSERT INTO ${this.#table} (email, password_hash, created_at) VALUES ($1, $2, $3)
|
|
52
|
+
RETURNING id, email, password_hash, created_at`, [normalizeEmail(email), password_hash, new Date()]);
|
|
53
|
+
if (result.isErr()) {
|
|
54
|
+
return Err(result.unsafeSource().toError());
|
|
55
|
+
}
|
|
56
|
+
return Ok(result.unwrap().rows.unsafeSource()[0]);
|
|
57
|
+
}
|
|
58
|
+
// Updates only the single row matching this email; never touches any other row.
|
|
59
|
+
async updatePasswordByEmail(email, password_hash) {
|
|
60
|
+
const result = await this.#db_client.query(`UPDATE ${this.#table} SET password_hash = $2 WHERE email = $1
|
|
61
|
+
RETURNING id, email, password_hash, created_at`, [normalizeEmail(email), password_hash]);
|
|
62
|
+
if (result.isErr()) {
|
|
63
|
+
return Err(result.unsafeSource().toError());
|
|
64
|
+
}
|
|
65
|
+
const row = result.unwrap().rows.unsafeSource()[0];
|
|
66
|
+
return Ok(row === undefined ? None() : Some(row));
|
|
67
|
+
}
|
|
68
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smuzi/logger-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Web UI for browsing logs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./build/index.d.ts",
|
|
@@ -36,13 +36,18 @@
|
|
|
36
36
|
"#lib/*": "./src/*"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
+
"@smuzi/console": "^0.0.12",
|
|
40
|
+
"@smuzi/database": "^0.0.15",
|
|
41
|
+
"@smuzi/http-client": "^0.0.13",
|
|
39
42
|
"@smuzi/http-server": "^0.0.14",
|
|
40
|
-
"@smuzi/logger": "^0.0.
|
|
43
|
+
"@smuzi/logger": "^0.0.7",
|
|
41
44
|
"@smuzi/std": "^0.2.15"
|
|
42
45
|
},
|
|
43
46
|
"devDependencies": {
|
|
47
|
+
"@smuzi/console": "^0.0.12",
|
|
44
48
|
"@smuzi/database": "^0.0.15",
|
|
45
49
|
"@smuzi/db-postgres": "^0.0.13",
|
|
50
|
+
"@smuzi/http-client": "^0.0.13",
|
|
46
51
|
"@tailwindcss/cli": "^4.3.3",
|
|
47
52
|
"@types/alpinejs": "^3.13.11",
|
|
48
53
|
"@types/node": "^22.15.21",
|
|
@@ -54,11 +59,12 @@
|
|
|
54
59
|
},
|
|
55
60
|
"scripts": {
|
|
56
61
|
"build": "pnpm run build:ui && tsc --project tsconfig.build.json",
|
|
57
|
-
"build:ui": "pnpm run build:ui:js && pnpm run build:ui:css && cp ui/index.html build/ui/
|
|
62
|
+
"build:ui": "pnpm run build:ui:js && pnpm run build:ui:css && cp ui/index.html ui/login.html build/ui/",
|
|
58
63
|
"build:ui:js": "esbuild ui/src/main.ts --bundle --minify --format=iife --target=es2022 --outfile=build/ui/app.js",
|
|
59
64
|
"build:ui:css": "tailwindcss --input ui/src/app.css --output build/ui/app.css --minify",
|
|
60
65
|
"check:ui": "tsc --project tsconfig.ui.json",
|
|
61
|
-
"serve": "tsx --env-file=dev/.env dev/serve.ts"
|
|
66
|
+
"serve": "tsx --env-file=dev/.env dev/serve.ts",
|
|
67
|
+
"console": "tsx --env-file=dev/.env dev/console.ts"
|
|
62
68
|
},
|
|
63
69
|
"main": "./build/index.js"
|
|
64
70
|
}
|