Skip to content

Commit

Permalink
feat: implement user client
Browse files Browse the repository at this point in the history
  • Loading branch information
aldy505 committed May 28, 2023
1 parent 6740af6 commit faac653
Show file tree
Hide file tree
Showing 16 changed files with 320 additions and 100 deletions.
17 changes: 17 additions & 0 deletions application/ddl/error_log.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- See https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/mergetree#table_engine-mergetree-creating-a-table
CREATE TABLE error_logs
(
id UUID,
project UUID,
environment String,
level String,
title String,
status UInt8,
platform Nullable(String),
language Nullable(String),
payload String,
timestamp DateTime
) Engine = MergeTree()
ORDER BY (id, timestamp)
TTL timestamp + INTERVAL 3 MONTH
DELETE;
10 changes: 10 additions & 0 deletions application/ddl/project.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CREATE TABLE IF NOT EXISTS project
(
id UUID PRIMARY KEY,
name VARCHAR(255) NOT NULL,
repository_url TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
created_by UUID NOT NULL,
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_by UUID NOT NULL
);
18 changes: 18 additions & 0 deletions application/ddl/user.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
CREATE TABLE human_users
(
id UUID PRIMARY KEY,
github_id INTEGER NOT NULL,
github_node_id VARCHAR(255) NOT NULL,
username VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
avatar_url TEXT DEFAULT NULL,
profile_url TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
created_by UUID NOT NULL,
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_by UUID NOT NULL
);

CREATE UNIQUE INDEX human_users_github_id_unique ON human_users (github_id);

CREATE INDEX human_users_username_search ON human_users (username NULLS LAST);
2 changes: 1 addition & 1 deletion application/interfaces/IAuthentication.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Project} from "~/primitives/Project";
import {Token} from "~/primitives/Token";
import { User } from "~~/primitives/User";
import {User} from "~~/primitives/User";

export interface IAuthentication {
validateProjectToken(token: string): Promise<Project>;
Expand Down
11 changes: 3 additions & 8 deletions application/internal/clickhouse-ts/src/clickhouse/Clickhouse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,10 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import {
JSONFormatRow,
Connection,
Options,
QueryOptions
} from './interface'
import {Connection, JSONFormatRow, Options, QueryOptions} from './interface'

import { HttpClientResponse } from '../httpClient'
import { jsonInsertFormatToSqlValues, jsonRowsToInsertFormat } from '../utils'
import {HttpClientResponse} from '../httpClient'
import {jsonInsertFormatToSqlValues, jsonRowsToInsertFormat} from '../utils'
import {HttpFetchClient} from "../httpClient/http-fetch-client";

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { URL, URLSearchParams } from "node:url";
import {
HttpClientConstructor,
HttpClientRequest,
HttpClientResponse
} from './interface'
import { HttpClickhouseAxiosError } from '../errors'
import {URL, URLSearchParams} from "node:url";
import {HttpClientConstructor, HttpClientRequest, HttpClientResponse} from './interface'
import {HttpClickhouseAxiosError} from '../errors'

/**
* HttpClient wraps fetch and provides transparent data transferring between your code and clickhouse server
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { QueryOptions } from '../clickhouse'
import {QueryOptions} from '../clickhouse'

export interface RequestParams {
query: string
Expand Down
8 changes: 4 additions & 4 deletions application/internal/clickhouse-ts/src/utils/format.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* eslint-disable no-tabs */
import ss from 'sqlstring'
import { JSONFormatRow } from '../clickhouse'
import { PreprocessInsertQueryError } from '../errors'
import { isNull, isObject } from './common'
import { OptimizedJSONInsertFormat } from './interface'
import {JSONFormatRow} from '../clickhouse'
import {PreprocessInsertQueryError} from '../errors'
import {isNull, isObject} from './common'
import {OptimizedJSONInsertFormat} from './interface'

/**
* Get optimized and validated insert format for http insert request
Expand Down
4 changes: 2 additions & 2 deletions application/internal/clickhouse-ts/tests/clickhouse.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {describe, it, expect, beforeAll, afterAll} from "vitest";
import { Clickhouse } from '../src/clickhouse'
import {afterAll, beforeAll, describe, expect, it} from "vitest";
import {Clickhouse} from '../src/clickhouse'

const instance = new Clickhouse({
url: process.env.CLICKHOUSE_URL ?? "localhost",
Expand Down
37 changes: 19 additions & 18 deletions application/repositories/ErrorLogClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@ import {UUID} from "~/primitives/UUID";
import {IErrorLogRepository} from "~/application/interfaces/IErrorLogRepository";

export class ErrorLogClient implements IErrorLogRepository {
constructor(private readonly client: Clickhouse) { }
constructor(private readonly client: Clickhouse) {
}

async migrate(): Promise<void> {
await this.client.query(
`CREATE TABLE IF NOT EXISTS error_logs (
id UUID NOT NULL,
project UUID NOT NULL,
environment String NOT NULL,
level String NOT NULL,
title String NOT NULL,
status UInt8 NOT NULL,
platform Nullable(String),
language Nullable(String),
payload String NOT NULL,
timestamp DateTime NOT NULL,
PRIMARY KEY(timestamp)
)
Engine = MergeTree
ORDER BY timestamp
TTL timestamp + INTERVAL 3 MONTH DELETE`,
`CREATE TABLE error_logs
(
id UUID,
project UUID,
environment String,
level String,
title String,
status UInt8,
platform Nullable(String),
language Nullable(String),
payload String,
timestamp DateTime
) Engine = MergeTree()
ORDER BY (id, timestamp)
TTL timestamp + INTERVAL 3 MONTH
DELETE;`,
);
}

Expand All @@ -44,4 +45,4 @@ export class ErrorLogClient implements IErrorLogRepository {
}],
);
}
}
}
6 changes: 5 additions & 1 deletion application/repositories/GithubClient.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import {type GithubOrganization, type GithubUser, type IGithub} from "~/application/interfaces/IGithub";
import {GithubApiError} from "~/errors/GithubApiError";
import {InvalidArgumentError} from "~/errors/InvalidArgumentError";

export class GithubClient implements IGithub {
constructor(
private readonly clientId: string,
private readonly clientSecret: string
) {}
) {
if (clientId === "") throw new InvalidArgumentError("clientId is empty");
if (clientSecret === "") throw new InvalidArgumentError("clientSecret is empty");
}

async accessToken(code: string): Promise<string> {
const response = await fetch("https://github.com/login/oauth/access_token", {
Expand Down
76 changes: 35 additions & 41 deletions application/repositories/ProjectClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,14 @@ export class ProjectClient implements IProjectRepository {
try {
await conn.query("BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED");

await conn.query(`INSERT INTO
project
(
id,
name,
repository_url,
created_at,
created_by,
updated_at,
updated_by
)`,
await conn.query(`INSERT INTO project
(id,
name,
repository_url,
created_at,
created_by,
updated_at,
updated_by)`,
[
project.id.toString(),
project.name,
Expand Down Expand Up @@ -53,7 +50,7 @@ export class ProjectClient implements IProjectRepository {
const conn = await this.client.connect();

try {
const queryResult = await conn.query(`SELECT EXISTS(SELECT * FROM project WHERE id = ?) AS exists`,[id.toString()]);
const queryResult = await conn.query(`SELECT EXISTS(SELECT * FROM project WHERE id = ?) AS exists`, [id.toString()]);

return queryResult.rows[0].exists;

Expand All @@ -68,17 +65,14 @@ export class ProjectClient implements IProjectRepository {
const conn = await this.client.connect();

try {
const queryResult = await conn.query(`SELECT
id,
name,
repository_url,
created_at,
created_by
FROM
project
WHERE
id = $1
LIMIT 1`,
const queryResult = await conn.query(`SELECT id,
name,
repository_url,
created_at,
created_by
FROM project
WHERE id = $1
LIMIT 1`,
[id.toString()],
);

Expand Down Expand Up @@ -125,14 +119,12 @@ export class ProjectClient implements IProjectRepository {
const conn = await this.client.connect();

try {
const queryResult = conn.query(new Cursor(`SELECT
id,
name,
repository_url,
created_at,
created_by
FROM
project`));
const queryResult = conn.query(new Cursor(`SELECT id,
name,
repository_url,
created_at,
created_by
FROM project`));

const rows = await queryResult.read(500);

Expand All @@ -145,7 +137,8 @@ export class ProjectClient implements IProjectRepository {
for (const row of rows) {
if (row === undefined) continue;

let createdAt: Date = new Date(0);;
let createdAt: Date = new Date(0);

if (row.created_at !== undefined) {
if (typeof row.created_at === "string") {
createdAt = new Date(row.created_at);
Expand Down Expand Up @@ -179,15 +172,16 @@ export class ProjectClient implements IProjectRepository {
try {
await conn.query("BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;");

await conn.query(`CREATE TABLE IF NOT EXISTS project (
id UUID PRIMARY KEY,
name VARCHAR(255) NOT NULL,
repository_url TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
created_by UUID NOT NULL,
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_by UUID NOT NULL
)`);
await conn.query(`CREATE TABLE IF NOT EXISTS project
(
id UUID PRIMARY KEY,
name VARCHAR(255) NOT NULL,
repository_url TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
created_by UUID NOT NULL,
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_by UUID NOT NULL
)`);

await conn.query("COMMIT;");
} catch (error: unknown) {
Expand Down
2 changes: 1 addition & 1 deletion application/repositories/TokenClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class TokenClient implements ITokenRepository {

generate(user: User): Token {
// Generate a UUID.
const id = new UUID();
const id = UUID.v7();

// Check if the id is being used
if (this.store.has(id.toString())) {
Expand Down
Loading

0 comments on commit faac653

Please sign in to comment.