Gisle Aune
3 years ago
23 changed files with 103 additions and 462 deletions
-
4api/items.go
-
4api/projects.go
-
6api/scope.go
-
4api/stats.go
-
1frontend/src/app.d.ts
-
7frontend/src/hooks.ts
-
2frontend/src/lib/components/frontpage/ScopeLink.svelte
-
17frontend/src/lib/config.ts
-
37frontend/src/lib/database/interfaces.ts
-
48frontend/src/lib/database/mysql/database.ts
-
84frontend/src/lib/database/mysql/scopes.ts
-
10frontend/src/lib/models/item.ts
-
7frontend/src/lib/models/project.ts
-
14frontend/src/lib/models/scope.ts
-
32frontend/src/lib/models/stat.ts
-
13frontend/src/lib/utils/slugify.ts
-
31frontend/src/routes/[scope].json.ts
-
23frontend/src/routes/[scope]/__layout.svelte
-
30frontend/src/routes/api/[...any]/index.ts
-
171frontend/src/routes/indexdata.json.ts
-
4internal/database/mysql/scopes.go
-
2internal/models/item.go
-
8internal/models/scope.go
@ -1,18 +1,3 @@ |
|||
import type { Database } from "./database/interfaces"; |
|||
import MysqlDB from "./database/mysql/database"; |
|||
|
|||
let databasePromise: Promise<Database> | null = null; |
|||
let databaseTime: number = 0; |
|||
|
|||
const config = { |
|||
database() { |
|||
if (databasePromise == null || Date.now() < (databaseTime - 60000)) { |
|||
databasePromise = MysqlDB.connectEnv(); |
|||
databaseTime = Date.now(); |
|||
} |
|||
|
|||
return databasePromise; |
|||
} |
|||
}; |
|||
const config = {}; |
|||
|
|||
export default config; |
@ -1,37 +0,0 @@ |
|||
import type { ScopeEntry, ScopeInput } from "$lib/models/scope"; |
|||
import type Scope from "$lib/models/scope"; |
|||
import type { StatEntry } from "$lib/models/stat"; |
|||
import type Stat from "$lib/models/stat"; |
|||
|
|||
export class NotFoundError extends Error { |
|||
constructor(subject: string) { |
|||
super(`${subject} not found`); |
|||
} |
|||
} |
|||
|
|||
export interface Database { |
|||
userId: string |
|||
|
|||
scopes(): ScopeRepo |
|||
stats(scopeId: number): StatRepo |
|||
withUser(userId: string): Database |
|||
} |
|||
|
|||
export interface ScopeRepo { |
|||
userId: string |
|||
|
|||
find(id: number): Promise<Scope> |
|||
list(): Promise<ScopeEntry[]> |
|||
create(input: ScopeInput): Promise<Scope> |
|||
update(id: number, input: Partial<ScopeInput>): Promise<Scope> |
|||
delete(id: number): Promise<void> |
|||
} |
|||
|
|||
export interface StatRepo { |
|||
userId: string |
|||
scopeId: number |
|||
|
|||
find(id: number): Promise<Stat> |
|||
findEntries(...ids: number[]): Promise<StatEntry[]> |
|||
list(): Promise<Stat[]> |
|||
} |
@ -1,48 +0,0 @@ |
|||
import {createPool} from "mysql2/promise" |
|||
import type {Pool} from "mysql2/promise"; |
|||
|
|||
import type { Database, ScopeRepo, StatRepo } from "../interfaces"; |
|||
import MysqlDBScopes from "./scopes"; |
|||
|
|||
|
|||
export default class MysqlDB implements Database { |
|||
connection: Pool |
|||
userId: string; |
|||
|
|||
private constructor(userId: string, connection: Pool) { |
|||
this.userId = userId; |
|||
this.connection = connection; |
|||
} |
|||
|
|||
scopes(): ScopeRepo { |
|||
return new MysqlDBScopes(this.connection, this.userId); |
|||
} |
|||
stats(scopeId: number): StatRepo { |
|||
throw new Error("Method not implemented."); |
|||
} |
|||
|
|||
withUser(userId: string): Database { |
|||
return new MysqlDB(userId, this.connection); |
|||
} |
|||
|
|||
static async connectEnv(): Promise<MysqlDB> { |
|||
return this.connect( |
|||
process.env.STUFFLOG3_MYSQL_HOST, |
|||
parseInt(process.env.STUFFLOG3_MYSQL_PORT), |
|||
process.env.STUFFLOG3_MYSQL_USERNAME, |
|||
process.env.STUFFLOG3_MYSQL_PASSWORD, |
|||
process.env.STUFFLOG3_MYSQL_SCHEMA, |
|||
) |
|||
} |
|||
|
|||
static async connect(host: string, port: number, user: string, password: string, database: string): Promise<MysqlDB> { |
|||
const connection = await createPool({ |
|||
host, user, database, password, port, |
|||
waitForConnections: true, |
|||
connectionLimit: 20, |
|||
queueLimit: 0, |
|||
}); |
|||
|
|||
return new MysqlDB("", connection); |
|||
} |
|||
} |
@ -1,84 +0,0 @@ |
|||
import type {Pool} from "mysql2/promise"; |
|||
|
|||
import type Scope from "$lib/models/scope"; |
|||
import type { ScopeEntry, ScopeInput } from "$lib/models/scope"; |
|||
import type { ScopeRepo } from "../interfaces"; |
|||
|
|||
export default class MysqlDBScopes implements ScopeRepo { |
|||
userId: string; |
|||
connection: Pool; |
|||
|
|||
constructor(connection: Pool, userId: string) { |
|||
this.connection = connection; |
|||
this.userId = userId; |
|||
} |
|||
|
|||
async find(id: number): Promise<Scope> { |
|||
const [[scopeRows], [projectRows], [statRows]] = await Promise.all([ |
|||
this.connection.execute(`
|
|||
SELECT scope.*, scope_member.name as display_name |
|||
FROM scope |
|||
INNER JOIN scope_member ON scope.id = scope_member.scope_id |
|||
WHERE scope.id = ? |
|||
`, [id]),
|
|||
this.connection.execute(`
|
|||
SELECT id,name,status |
|||
FROM project |
|||
WHERE scope_id = ? |
|||
`, [id]).catch(() => []),
|
|||
this.connection.execute(`
|
|||
SELECT * |
|||
FROM stats |
|||
WHERE scope_id = ? |
|||
`, [id]).catch(() => []),
|
|||
]); |
|||
|
|||
const r = scopeRows[0] as any; |
|||
if (!r) { |
|||
return null; |
|||
} |
|||
|
|||
return { |
|||
id: r.id, |
|||
name: r.name, |
|||
abbreviation: r.abbreviation, |
|||
displayName: r.display_name, |
|||
projects: ((projectRows||[]) as any[]).map((p:any) => ({ |
|||
id: p.id, |
|||
name: p.name, |
|||
status: p.status, |
|||
})), |
|||
stats: ((statRows||[]) as any[]).map((s:any) => ({ |
|||
id: s.id, |
|||
name: s.name, |
|||
weight: s.weight, |
|||
description: s.description, |
|||
allowedAmounts: s.allowed_amounts || void(0), |
|||
})), |
|||
} |
|||
} |
|||
async list(): Promise<ScopeEntry[]> { |
|||
const [rows] = await this.connection.execute(`
|
|||
SELECT scope.*, scope_member.name as display_name |
|||
FROM scope |
|||
INNER JOIN scope_member ON id = scope_id |
|||
WHERE user_id = ? |
|||
`, [this.userId]);
|
|||
|
|||
return (rows as any[]).map(r => ({ |
|||
id: r.id, |
|||
name: r.name, |
|||
abbreviation: r.abbreviation, |
|||
displayName: r.display_name, |
|||
})) |
|||
} |
|||
create(input: ScopeInput): Promise<Scope> { |
|||
throw new Error("Method not implemented."); |
|||
} |
|||
update(id: number, input: Partial<ScopeInput>): Promise<Scope> { |
|||
throw new Error("Method not implemented."); |
|||
} |
|||
delete(id: number): Promise<void> { |
|||
throw new Error("Method not implemented."); |
|||
} |
|||
} |
@ -0,0 +1,13 @@ |
|||
export default function sluggify(s: string): string { |
|||
let out = ""; |
|||
|
|||
for (const c of s.toLocaleLowerCase()) { |
|||
if (c >= 'a' && c <= 'z') { |
|||
out += c; |
|||
} else if (!":'".includes(c)) { |
|||
out += "-"; |
|||
} |
|||
} |
|||
|
|||
return out; |
|||
} |
@ -1,31 +0,0 @@ |
|||
import type { RequestHandler } from "@sveltejs/kit"; |
|||
|
|||
import config from "$lib/config"; |
|||
|
|||
export const get: RequestHandler = async({params, locals}) => { |
|||
const scopeId = parseInt(params.scope); |
|||
|
|||
const db = await config.database(); |
|||
const scope = await db.withUser(locals.user.id).scopes().find(scopeId) |
|||
if (scope === null) { |
|||
return { |
|||
status: 404, |
|||
headers: { |
|||
"Content-Type": "application/json" |
|||
}, |
|||
body: JSON.stringify({ |
|||
message: "Scope not found", |
|||
}), |
|||
} |
|||
} |
|||
|
|||
return { |
|||
status: 200, |
|||
headers: { |
|||
"Content-Type": "application/json" |
|||
}, |
|||
body: JSON.stringify({ |
|||
scope |
|||
}), |
|||
} |
|||
} |
@ -0,0 +1,30 @@ |
|||
import type { RequestHandler } from "@sveltejs/kit"; |
|||
|
|||
export const get: RequestHandler = async({ request, params }) => { |
|||
const proxyUrl = `${process.env.STUFFLOG3_API}/api/${params.any}`; |
|||
|
|||
console.log("PRX", proxyUrl); |
|||
const res = await fetch(proxyUrl, { |
|||
method: request.method, |
|||
headers: { |
|||
...request.headers, |
|||
}, |
|||
body: request.body, |
|||
}); |
|||
|
|||
const result = { |
|||
status: res.status, |
|||
body: await res.text(), |
|||
headers: {}, |
|||
} |
|||
res.headers.forEach((v, k) => { |
|||
result.headers[k] = v; |
|||
}) |
|||
|
|||
return result; |
|||
} |
|||
|
|||
export const options = get; |
|||
export const post = get; |
|||
export const put = get; |
|||
export const del = get; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue