Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): resolve some core no-restricted-syntax lint error #1606

Merged
merged 3 commits into from
Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@
"eslintConfig": {
"extends": "@silverhand",
"rules": {
"complexity": "off",
"no-restricted-syntax": "off"
"complexity": "off"
}
},
"prettier": "@silverhand/eslint-config/.prettierrc"
Expand Down
30 changes: 15 additions & 15 deletions packages/core/src/database/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SchemaValuePrimitive, SchemaValue } from '@logto/schemas';
import { Falsy, notFalsy } from '@silverhand/essentials';
import dayjs from 'dayjs';
import { sql, SqlSqlToken, SqlToken, QueryResult } from 'slonik';
import { sql, SqlSqlToken, SqlToken, QueryResult, IdentifierSqlToken } from 'slonik';

import { FieldIdentifiers, Table } from './types';

Expand All @@ -15,6 +15,8 @@ export const excludeAutoSetFields = <T extends string>(fields: readonly T[]) =>
Object.freeze(
fields.filter(
(field): field is ExcludeAutoSetFields<T> =>
// Read only string arrays
// eslint-disable-next-line no-restricted-syntax
!(autoSetFields as readonly string[]).includes(field)
)
);
Expand Down Expand Up @@ -52,20 +54,18 @@ export const convertToPrimitiveOrSql = (
throw new Error(`Cannot convert ${key} to primitive`);
};

export const convertToIdentifiers = <T extends Table>(
{ table, fields }: T,
withPrefix = false
) => ({
table: sql.identifier([table]),
fields: Object.entries<string>(fields).reduce(
(previous, [key, value]) => ({
...previous,
[key]: sql.identifier(withPrefix ? [table, value] : [value]),
}),
// eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter
{} as FieldIdentifiers<keyof T['fields']>
),
});
export const convertToIdentifiers = <T extends Table>({ table, fields }: T, withPrefix = false) => {
const fieldsIdentifiers = Object.entries<string>(fields).map<
[keyof T['fields'], IdentifierSqlToken]
>(([key, value]) => [key, sql.identifier(withPrefix ? [table, value] : [value])]);

return {
table: sql.identifier([table]),
// Key value inferred from the original fields directly
// eslint-disable-next-line no-restricted-syntax
fields: Object.fromEntries(fieldsIdentifiers) as FieldIdentifiers<keyof T['fields']>,
};
};

export const convertToTimestamp = (time = dayjs()) => sql`to_timestamp(${time.valueOf() / 1000})`;

Expand Down
18 changes: 10 additions & 8 deletions packages/core/src/lib/passcode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,16 @@ const mockedIncreasePasscodeTryCount = increasePasscodeTryCount as jest.MockedFu

beforeAll(() => {
mockedFindUnconsumedPasscodesByJtiAndType.mockResolvedValue([]);
mockedInsertPasscode.mockImplementation(async (data) => ({
...data,
createdAt: Date.now(),
phone: data.phone ?? null,
email: data.email ?? null,
consumed: data.consumed ?? false,
tryCount: data.tryCount ?? 0,
}));
mockedInsertPasscode.mockImplementation(async (data): Promise<Passcode> => {
return {
phone: null,
email: null,
consumed: false,
tryCount: 0,
...data,
createdAt: Date.now(),
};
});
});

afterEach(() => {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/middleware/koa-guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export default function koaGuard<
WithGuardedRequestContext<ContextT, GuardQueryT, GuardBodyT, GuardParametersT>,
GuardResponseT
> = async (ctx, next) => {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, no-restricted-syntax
ctx.guard = {
query: tryParse('query', query, ctx.request.query),
body: tryParse('body', body, ctx.request.body),
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/middleware/koa-i18next.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default function koaI18next<
return async (ctx, next) => {
const languages = detectLanguage(ctx);
// Cannot patch type def directly, see https://github.com/microsoft/TypeScript/issues/36146
// eslint-disable-next-line no-restricted-syntax
const languageUtils = i18next.services.languageUtils as LanguageUtils;
const foundLanguage = languages
.map((code) => languageUtils.formatLanguageCode(code))
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/middleware/koa-oidc-error-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export default function koaOIDCErrorHandler<StateT, ContextT>(): Middleware<Stat
case errors.InvalidGrant:
throw new RequestError(
{
// Manually mapped all OIDC error name to the LogtoErrorCode
// eslint-disable-next-line no-restricted-syntax
code: `oidc.${decamelize(name)}` as LogtoErrorCode,
status,
expose,
Expand Down
44 changes: 25 additions & 19 deletions packages/core/src/middleware/koa-slonik-error-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,32 @@ export default function koaSlonikErrorHandler<StateT, ContextT>(): Middleware<St
throw error;
}

switch (error.constructor) {
case InsertionError:
throw new RequestError({
code: 'entity.create_failed',
name: (error as InsertionError<SchemaLike>).schema.tableSingular,
});
case UpdateError:
throw new RequestError({
code: 'entity.not_exists',
name: (error as InsertionError<SchemaLike>).schema.tableSingular,
});
case DeletionError:
case NotFoundError:
throw new RequestError({
code: 'entity.not_found',
status: 404,
});
default:
throw error;
if (error instanceof InsertionError) {
throw new RequestError({
code: 'entity.create_failed',
// Assert generic type of the Class instance
// eslint-disable-next-line no-restricted-syntax
name: (error as InsertionError<SchemaLike>).schema.tableSingular,
});
}

if (error instanceof UpdateError) {
throw new RequestError({
code: 'entity.not_exists',
// Assert generic type of the Class instance
// eslint-disable-next-line no-restricted-syntax
name: (error as UpdateError<SchemaLike>).schema.tableSingular,
});
}

if (error instanceof DeletionError || error instanceof NotFoundError) {
throw new RequestError({
code: 'entity.not_found',
status: 404,
});
}

throw error;
}
};
}
7 changes: 4 additions & 3 deletions packages/core/src/routes/swagger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,19 @@ export default function swaggerRoutes<T extends AnonymousRouter, R extends Route
) {
router.get('/swagger.json', async (ctx, next) => {
// Use `as` here since we'll check typing with integration tests
// eslint-disable-next-line no-restricted-syntax
const additionalSwagger = load(
await readFile('static/yaml/additional-swagger.yaml', { encoding: 'utf-8' })
) as OpenAPIV3.Document;

const routes = allRouters.flatMap<RouteObject>((router) =>
router.stack.flatMap<RouteObject>(({ path: routerPath, stack, methods }) =>
methods
.map((method) => method.toLowerCase())
// There is no need to show the HEAD method.
.filter((method) => method !== 'HEAD')
.map((method) => {
.filter((method): method is OpenAPIV3.HttpMethods => method !== 'head')
.map((httpMethod) => {
const path = `/api${routerPath}`;
const httpMethod = method.toLowerCase() as OpenAPIV3.HttpMethods;

const additionalPathItem = additionalSwagger.paths[path] ?? {};
const additionalResponses = additionalPathItem[httpMethod]?.responses;
Expand Down
9 changes: 4 additions & 5 deletions packages/core/src/utils/oidc-provider-event-listener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@ interface GrantBody {
}

const getLogType = (grantType: unknown) => {
if (
!grantType ||
![GrantType.AuthorizationCode, GrantType.RefreshToken].includes(grantType as GrantType)
) {
// Only log token exchange by authorization code or refresh token.
const allowedGrantType = new Set<unknown>([GrantType.AuthorizationCode, GrantType.RefreshToken]);

// Only log token exchange by authorization code or refresh token.
if (!grantType || !allowedGrantType.has(grantType)) {
return;
}

Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/utils/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ export function createRequester({
if (provider) {
route(anonymousRouter, provider);
} else {
// For test use only
// eslint-disable-next-line no-restricted-syntax
(route as RouteLauncher<AnonymousRouter>)(anonymousRouter);
}
}
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/utils/zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
ZodOptional,
ZodString,
ZodStringDef,
ZodType,
ZodUnion,
ZodUnknown,
} from 'zod';
Expand Down Expand Up @@ -129,7 +128,9 @@ export const zodTypeToSwagger = (config: unknown): OpenAPIV3.SchemaObject => {

if (config instanceof ZodUnion) {
return {
oneOf: (config.options as ZodType[]).map((option) => zodTypeToSwagger(option)),
// ZodUnion.options type is any
// eslint-disable-next-line no-restricted-syntax
oneOf: (config.options as unknown[]).map((option) => zodTypeToSwagger(option)),
};
}

Expand Down