Skip to content

Commit 4df2104

Browse files
committed
feat: add type information to schema
1 parent e2677b8 commit 4df2104

37 files changed

+2574
-52
lines changed

src/common/QueryRunner.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ import {
1010
} from "@topcoder-framework/client-relational";
1111
import { TableColumn, TableColumns } from "./TableColumn";
1212

13-
export type Schema = {
13+
export type Schema<T extends Record<string, any>> = {
1414
dbSchema: string;
1515
tableName: string;
1616
idColumn?: string;
1717
idSequence?: string;
1818
idTable?: string;
19-
columns: TableColumns;
19+
columns: TableColumns<T>;
2020
};
2121

2222
interface ExecuteSqlQuery {
@@ -51,17 +51,17 @@ export interface InsertQuery<CreateInput> {
5151
}
5252

5353
export interface UpdateQuery<UpdateInput> {
54-
update(lookupCriteria: { [key: string]: unknown }, input: UpdateInput): ExecuteSqlQuery;
54+
update(lookupCriteria: Record<string, unknown>, input: UpdateInput): ExecuteSqlQuery;
5555
}
5656

5757
export interface DeleteQuery {
5858
delete(): ExecuteSqlQuery;
5959
}
6060

6161
export class QueryRunner<
62-
T,
63-
CreateInput extends { [key: string]: unknown },
64-
UpdateInput extends { [key: string]: unknown }
62+
T extends Record<string, unknown>,
63+
CreateInput extends Record<string, unknown>,
64+
UpdateInput extends Record<string, unknown>
6565
> implements
6666
SelectQuery,
6767
JoinClause,
@@ -76,7 +76,7 @@ export class QueryRunner<
7676
#query: Query | null = null;
7777
#client: RelationalClient;
7878

79-
constructor(private schema: Schema) {
79+
constructor(private schema: Schema<T>) {
8080
console.log("Connecting to GRPC server at", GRPC_RDB_SERVER_HOST, GRPC_RDB_SERVER_PORT, "...");
8181
this.#client = new RelationalClient(GRPC_RDB_SERVER_HOST!, parseInt(GRPC_RDB_SERVER_PORT!));
8282
}
@@ -167,7 +167,7 @@ export class QueryRunner<
167167
...Object.entries(input)
168168
.filter(([_key, value]) => value !== undefined)
169169
.map(([key, value]) => ({
170-
column: this.schema.columns[key].name,
170+
column: this.schema.columns[key]?.name ?? key,
171171
value: this.toValue(key, value),
172172
})),
173173
],
@@ -206,7 +206,7 @@ export class QueryRunner<
206206
throw new Error("Unexpected result type");
207207
}
208208
return queryResponse.result.selectResult.rows.map((row) => {
209-
return row as T;
209+
return row as unknown as T;
210210
});
211211
case "insert":
212212
if (queryResponse.result?.$case != "insertResult") {

src/common/TableColumn.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ export type TableColumn = {
55
type: ColumnType;
66
};
77

8-
export type TableColumns = {
9-
[key: string]: TableColumn;
8+
export type TableColumns<T extends Record<string, unknown>> = {
9+
[Property in keyof T]: TableColumn;
1010
};

src/domain/LegacyChallenge.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import { ColumnType, Operator, QueryRequest } from "@topcoder-framework/client-r
22
import { Value } from "@topcoder-framework/lib-common";
33
import { QueryRunner } from "../common/QueryRunner";
44
import { CheckChallengeExistsResponse } from "../models/domain-layer/legacy/challenge";
5-
import { Project } from "../schema/project/Project";
5+
import { ProjectSchema } from "../schema/project/Project";
66

77
class LegacyChallengeDomain {
88
public async checkChallengeExists(
99
legacyChallengeId: number
1010
): Promise<CheckChallengeExistsResponse> {
11-
const challenges = (await new QueryRunner(Project)
12-
.select([Project.columns.projectId])
11+
const challenges = (await new QueryRunner(ProjectSchema)
12+
.select([ProjectSchema.columns.projectId])
1313
.where({
1414
key: "project_id",
1515
operator: Operator.OPERATOR_EQUAL,

src/domain/LegacyChallengePhase.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { QueryRunner } from "../common/QueryRunner";
22
import { Value } from "@topcoder-framework/client-relational";
33
import { CreatePhaseInput, PhaseTypeList } from "../models/domain-layer/legacy/challenge_phase";
4-
import { PhaseType } from "../schema/project/PhaseType";
4+
import { PhaseTypeSchema } from "../schema/project/PhaseType";
55
import { ProjectPhaseSchema } from "../schema/project/ProjectPhase";
66
import { CreateResult } from "@topcoder-framework/lib-common";
77

@@ -26,8 +26,8 @@ class LegacyChallengePhaseDomain {
2626
}
2727

2828
public async getPhaseTypes(): Promise<PhaseTypeList> {
29-
const projectPhases = (await new QueryRunner(PhaseType)
30-
.select([PhaseType.columns.phaseTypeId, PhaseType.columns.name])
29+
const projectPhases = (await new QueryRunner(PhaseTypeSchema)
30+
.select([PhaseTypeSchema.columns.phaseTypeId, PhaseTypeSchema.columns.name])
3131
.limit(500)
3232
.offset(0)
3333
.exec()) as [

src/domain/Prize.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { CreateResult, ScanCriteria, Value } from "@topcoder-framework/lib-common";
2+
import { QueryRunner } from "../common/QueryRunner";
3+
import { CreatePrizeInput, Prize, PrizeList } from "../models/domain-layer/legacy/prize";
4+
import { PrizeSchema } from "../schema/project_payment/Prize";
5+
6+
class PrizeDomain {
7+
public async create(input: CreatePrizeInput): Promise<CreateResult> {
8+
const createInput: Partial<Prize> = {
9+
...input,
10+
createUser: 22838965, // tcwebservice | TODO: Get using grpc interceptor
11+
modifyUser: 22838965, // tcwebservice | TODO: Get using grpc interceptor
12+
};
13+
14+
const prizeId = (await new QueryRunner(PrizeSchema).insert(createInput).exec()) as number;
15+
return {
16+
kind: {
17+
$case: "integerId",
18+
integerId: prizeId,
19+
},
20+
};
21+
}
22+
23+
public async scan(criteria: ScanCriteria): Promise<PrizeList> {
24+
const prizes = (await new QueryRunner(PrizeSchema)
25+
.select([
26+
PrizeSchema.columns.prizeId,
27+
PrizeSchema.columns.prizeTypeId,
28+
PrizeSchema.columns.prizeAmount,
29+
PrizeSchema.columns.place,
30+
PrizeSchema.columns.numberOfSubmissions,
31+
PrizeSchema.columns.projectId,
32+
PrizeSchema.columns.createDate,
33+
PrizeSchema.columns.createUser,
34+
PrizeSchema.columns.modifyDate,
35+
PrizeSchema.columns.modifyUser,
36+
])
37+
.limit(10)
38+
.offset(0)
39+
.exec()) as [
40+
{
41+
values: {
42+
prize_id: Value;
43+
prize_type_id: number;
44+
prize_amount: Value;
45+
place: number;
46+
number_of_submissions: number;
47+
prize_description: string;
48+
project_id: number;
49+
create_date: number;
50+
create_user: number;
51+
modify_date: number;
52+
modify_user: number;
53+
};
54+
}
55+
];
56+
57+
console.log("prizes", prizes);
58+
59+
const list: PrizeList = {
60+
prizes: prizes.map(({ values }) => {
61+
return {
62+
prizeId:
63+
values.prize_id.kind?.$case === "numberValue" ? values.prize_id.kind.numberValue : 12,
64+
prizeTypeId: values.prize_type_id,
65+
prizeAmount:
66+
values.prize_amount.kind?.$case === "numberValue"
67+
? values.prize_amount.kind.numberValue
68+
: 12,
69+
place: values.place,
70+
numberOfSubmissions: values.number_of_submissions,
71+
prizeDescription: values.prize_description,
72+
projectId: values.project_id,
73+
createDate: values.create_date,
74+
createUser: values.create_user,
75+
modifyDate: values.modify_date,
76+
modifyUser: values.modify_user,
77+
};
78+
}),
79+
};
80+
81+
return list;
82+
}
83+
}
84+
85+
export default new PrizeDomain();

src/models/domain-layer/legacy/challenge.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ export interface CheckChallengeExistsResponse {
2525
exists: boolean;
2626
}
2727

28+
export interface CreateChallengeInput {
29+
projectStatusId: number;
30+
projectCategoryId: number;
31+
tcDirectProjectId: number;
32+
}
33+
2834
function createBaseLegacyChallenge(): LegacyChallenge {
2935
return {
3036
projectId: 0,
@@ -311,6 +317,77 @@ export const CheckChallengeExistsResponse = {
311317
},
312318
};
313319

320+
function createBaseCreateChallengeInput(): CreateChallengeInput {
321+
return { projectStatusId: 0, projectCategoryId: 0, tcDirectProjectId: 0 };
322+
}
323+
324+
export const CreateChallengeInput = {
325+
encode(message: CreateChallengeInput, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
326+
if (message.projectStatusId !== 0) {
327+
writer.uint32(8).int32(message.projectStatusId);
328+
}
329+
if (message.projectCategoryId !== 0) {
330+
writer.uint32(16).int32(message.projectCategoryId);
331+
}
332+
if (message.tcDirectProjectId !== 0) {
333+
writer.uint32(24).int64(message.tcDirectProjectId);
334+
}
335+
return writer;
336+
},
337+
338+
decode(input: _m0.Reader | Uint8Array, length?: number): CreateChallengeInput {
339+
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
340+
let end = length === undefined ? reader.len : reader.pos + length;
341+
const message = createBaseCreateChallengeInput();
342+
while (reader.pos < end) {
343+
const tag = reader.uint32();
344+
switch (tag >>> 3) {
345+
case 1:
346+
message.projectStatusId = reader.int32();
347+
break;
348+
case 2:
349+
message.projectCategoryId = reader.int32();
350+
break;
351+
case 3:
352+
message.tcDirectProjectId = longToNumber(reader.int64() as Long);
353+
break;
354+
default:
355+
reader.skipType(tag & 7);
356+
break;
357+
}
358+
}
359+
return message;
360+
},
361+
362+
fromJSON(object: any): CreateChallengeInput {
363+
return {
364+
projectStatusId: isSet(object.projectStatusId) ? Number(object.projectStatusId) : 0,
365+
projectCategoryId: isSet(object.projectCategoryId) ? Number(object.projectCategoryId) : 0,
366+
tcDirectProjectId: isSet(object.tcDirectProjectId) ? Number(object.tcDirectProjectId) : 0,
367+
};
368+
},
369+
370+
toJSON(message: CreateChallengeInput): unknown {
371+
const obj: any = {};
372+
message.projectStatusId !== undefined && (obj.projectStatusId = Math.round(message.projectStatusId));
373+
message.projectCategoryId !== undefined && (obj.projectCategoryId = Math.round(message.projectCategoryId));
374+
message.tcDirectProjectId !== undefined && (obj.tcDirectProjectId = Math.round(message.tcDirectProjectId));
375+
return obj;
376+
},
377+
378+
create<I extends Exact<DeepPartial<CreateChallengeInput>, I>>(base?: I): CreateChallengeInput {
379+
return CreateChallengeInput.fromPartial(base ?? {});
380+
},
381+
382+
fromPartial<I extends Exact<DeepPartial<CreateChallengeInput>, I>>(object: I): CreateChallengeInput {
383+
const message = createBaseCreateChallengeInput();
384+
message.projectStatusId = object.projectStatusId ?? 0;
385+
message.projectCategoryId = object.projectCategoryId ?? 0;
386+
message.tcDirectProjectId = object.tcDirectProjectId ?? 0;
387+
return message;
388+
},
389+
};
390+
314391
declare var self: any | undefined;
315392
declare var window: any | undefined;
316393
declare var global: any | undefined;

0 commit comments

Comments
 (0)