Skip to content

Commit 6f1f66e

Browse files
committed
refactor(ts): enable strict type checking and tighten tsconfig rules
Updated tsconfig.json to enforce stricter type safety and modern module resolution. These changes align the project with TypeScript best practices and prevent common runtime errors. Key configuration changes: - Enabled `strict` mode for comprehensive type checking. - Added `noUncheckedIndexedAccess` to handle potentially undefined array/object lookups. - Added `noImplicitOverride` to ensure subclass methods are explicitly marked. - Set `moduleDetection` to 'force' to treat all files as modules. - Explicitly defined `include` and `exclude` patterns. Signed-off-by: Jeremy Ho <jujaga@gmail.com>
1 parent f8a3ff1 commit 6f1f66e

File tree

23 files changed

+116
-55
lines changed

23 files changed

+116
-55
lines changed

branch.helper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function getGitDir(): string {
2424
if (stats.isFile()) {
2525
const content = readFileSync(dotGitPath, 'utf-8');
2626
const match = /^gitdir:\s+(.*)$/m.exec(content);
27-
if (match) {
27+
if (match?.[1]) {
2828
const gitDir = match[1].trim();
2929
// If worktree path is relative, resolve it relative to the .git file location
3030
return isAbsolute(gitDir) ? gitDir : resolve(currentDir, gitDir);

src/docs/docs.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ export function getDocHTML(version = 'v1'): string {
5050
export function getSpec(): OpenAPISpec {
5151
const rawSpec = readFileSync('src/docs/openapi.yaml', 'utf8');
5252
const spec = load(rawSpec) as OpenAPISpec;
53-
spec.servers[0].url = '/api/v1';
54-
if (process.env.AUTH_ISSUER) {
53+
if (spec.servers?.[0]) spec.servers[0].url = '/api/v1';
54+
if (process.env.AUTH_ISSUER && spec.components.securitySchemes?.OpenID) {
5555
// eslint-disable-next-line max-len
56-
spec.components.securitySchemes!.OpenID.openIdConnectUrl = `${process.env.AUTH_ISSUER}/.well-known/openid-configuration`;
56+
spec.components.securitySchemes.OpenID.openIdConnectUrl = `${process.env.AUTH_ISSUER}/.well-known/openid-configuration`;
5757
}
5858
if (state.authMode && state.authMode === 'none') {
5959
delete spec.security;

src/middlewares/helpers/oauth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export function getBearerToken(req: Request): string | undefined | null {
2525
const [scheme, token] = parts;
2626
if (parts.length !== 2 || scheme !== 'Bearer') return null;
2727

28-
return /^[A-Za-z0-9\-._~+/]+=*$/.test(token) ? token : null; // RFC 6750 Section 2.1
28+
return token && /^[A-Za-z0-9\-._~+/]+=*$/.test(token) ? token : null; // RFC 6750 Section 2.1
2929
}
3030

3131
/**

src/repositories/base.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ export abstract class BaseRepository<TB extends keyof DB, C extends string = str
175175
*/
176176
upsert(data: InsertObject<DB, TB>, constraint?: C): InsertQueryBuilder<DB, TB, Selectable<DB[TB]>> {
177177
return this.create(data).onConflict((oc) => {
178-
if (this.constraints.length) return oc.constraint(constraint ?? this.constraints[0]).doNothing();
178+
if (this.constraints.length) return oc.constraint((constraint ?? this.constraints[0]) as string).doNothing();
179179
return oc.column(this.idColumn).doNothing();
180180
});
181181
}
@@ -188,7 +188,7 @@ export abstract class BaseRepository<TB extends keyof DB, C extends string = str
188188
*/
189189
upsertMany(data: readonly InsertObject<DB, TB>[], constraint?: C): InsertQueryBuilder<DB, TB, Selectable<DB[TB]>> {
190190
return this.createMany(data).onConflict((oc) => {
191-
if (this.constraints.length) return oc.constraint(constraint ?? this.constraints[0]).doNothing();
191+
if (this.constraints.length) return oc.constraint((constraint ?? this.constraints[0]) as string).doNothing();
192192
return oc.column(this.idColumn).doNothing();
193193
});
194194
}

src/services/helpers/event.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export function dateTimePartsToEvent(parts: {
3030
return {
3131
start_date: startDate.toISOString().split('T')[0],
3232
end_date: endDate ? endDate.toISOString().split('T')[0] : undefined
33-
};
33+
} as Event;
3434
}
3535
}
3636

@@ -50,9 +50,9 @@ export function eventToDateTimeParts(event: Event): {
5050
const eventEnd = end_datetime ?? end_date;
5151

5252
return {
53-
endDate: eventEnd?.split('T')[0],
54-
endTime: end_datetime ? eventEnd?.split('T')[1] : undefined,
55-
startDate: eventStart.split('T')[0],
53+
endDate: eventEnd?.split('T')[0] ?? undefined,
54+
endTime: end_datetime && eventEnd ? eventEnd.split('T')[1] : undefined,
55+
startDate: eventStart?.split('T')[0] ?? '',
5656
startTime: start_datetime ? eventStart.split('T')[1] : undefined
5757
};
5858
}
@@ -70,17 +70,17 @@ export function mergeDateAndTimeToISOString(date: Date, time: string): string {
7070
const day = date.getUTCDate();
7171

7272
// Strip anything after the time (Z, +00:00, etc.) and split
73-
const cleanTime = time.split(/[Z+-]/)[0];
73+
const cleanTime = time.split(/[Z+-]/)[0] ?? '';
7474
const timeParts = cleanTime.split(':');
7575
if (timeParts.length < 2) throw new Error(`Invalid time format: ${time}`);
7676

77-
const hour = Number.parseInt(timeParts[0], 10);
78-
const minute = Number.parseInt(timeParts[1], 10);
77+
const hour = Number.parseInt(timeParts[0] ?? '', 10);
78+
const minute = Number.parseInt(timeParts[1] ?? '', 10);
7979

8080
// Handle optional seconds and milliseconds
81-
const secondsPart = timeParts[2]?.split('.') || ['0', '0'];
82-
const second = Number.parseInt(secondsPart[0], 10);
83-
const ms = Number.parseInt(secondsPart[1] || '0', 10);
81+
const secondsPart = timeParts[2]?.split('.') ?? ['0', '0'];
82+
const second = Number.parseInt(secondsPart[0] ?? '', 10);
83+
const ms = Number.parseInt(secondsPart[1] ?? '0', 10);
8484
if ([hour, minute, second].some((num) => Number.isNaN(num))) {
8585
throw new Error(`Invalid numeric values in time: ${time}`);
8686
}

src/services/record.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ export const findRecordService = (systemRecord: Selectable<PiesSystemRecord>): P
6767

6868
const coding: Coding = {
6969
code: codingRaw.code,
70-
code_display: CodingDictionary[codingRaw.codeSystem][codingRaw.code].display,
71-
code_set: CodingDictionary[codingRaw.codeSystem][codingRaw.code].codeSet,
70+
code_display: CodingDictionary[codingRaw.codeSystem]?.[codingRaw.code]?.display ?? '',
71+
code_set: CodingDictionary[codingRaw.codeSystem]?.[codingRaw.code]?.codeSet ?? [codingRaw.code],
7272
code_system: codingRaw.codeSystem
7373
};
7474
return { coding, event } satisfies CodingEvent;
@@ -94,8 +94,8 @@ export const findRecordService = (systemRecord: Selectable<PiesSystemRecord>): P
9494

9595
const process: Process = {
9696
code: coding.code,
97-
code_display: CodingDictionary[coding.codeSystem][coding.code].display,
98-
code_set: CodingDictionary[coding.codeSystem][coding.code].codeSet,
97+
code_display: CodingDictionary[coding.codeSystem]?.[coding.code]?.display ?? '',
98+
code_set: CodingDictionary[coding.codeSystem]?.[coding.code]?.codeSet ?? [coding.code],
9999
code_system: coding.codeSystem,
100100
status: pe.status ?? undefined,
101101
status_code: pe.statusCode ?? undefined,
@@ -122,7 +122,7 @@ export const findRecordService = (systemRecord: Selectable<PiesSystemRecord>): P
122122
};
123123

124124
// eslint-disable-next-line @typescript-eslint/no-unused-vars
125-
export const mergeRecordService = (data: Record, principal?: string): Promise<void> => {
125+
export const mergeRecordService = (_data: Record, _principal?: string): Promise<void> => {
126126
throw new Error('mergeRecordService not implemented');
127127
};
128128

src/services/systemRecord.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export const findSingleSystemRecordService = async (
4949
);
5050
}
5151

52-
return systemRecords[0];
52+
return systemRecords[0] as Selectable<PiesSystemRecord>;
5353
},
5454
{ accessMode: 'read only' }
5555
);

src/utils/problem.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export default class Problem extends Error {
8080
* Converts the `Problem` instance to a string representation.
8181
* @returns A string in the format `[status] title (type)`.
8282
*/
83-
toString() {
83+
override toString() {
8484
return `[${this.status}] ${this.title} (${this.type})`;
8585
}
8686

src/utils/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export function getGitRevision(): string | undefined {
6868

6969
const content = readFileSync(gitPath, 'utf8').trim();
7070
const match = /^gitdir: (.+)$/.exec(content);
71-
return match ? join(cwd(), match[1]) : gitPath;
71+
return match?.[1] ? join(cwd(), match[1]) : gitPath;
7272
};
7373

7474
const readRef = (gitDir: string, ref: string): string | undefined => {

src/validators/integrity/auditor.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ const codeSystemCache = new Set<keyof typeof CodingDictionary>(Object.keys(Codin
66
/** Caches sets of codes for each code system. */
77
const codeSetCache: Record<string, Set<string>> = {};
88
for (const codeSystem of codeSystemCache) {
9-
codeSetCache[codeSystem] = new Set(Object.keys(CodingDictionary[codeSystem]));
9+
const codes = CodingDictionary[codeSystem];
10+
if (codes) codeSetCache[codeSystem] = new Set(Object.keys(codes));
1011
}
1112

1213
/**
@@ -66,7 +67,7 @@ export function auditProcess(data: Process, index: number): IntegrityError[] {
6667
value: data.code_system
6768
});
6869
}
69-
if (!codeSystemCache.has(data.code_system) || !codeSetCache[data.code_system].has(data.code)) {
70+
if (!codeSystemCache.has(data.code_system) || !codeSetCache[data.code_system]?.has(data.code)) {
7071
errors.push({
7172
instancePath: `/process_event/${index}/process`,
7273
message: `Invalid Process in ProcessEvent element at index ${index}`,

0 commit comments

Comments
 (0)