mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
fix(core): resolve some core no-restricted-syntax lint error (#1606)
* fix(core): resolve some core no-restricted-syntax lint error resolve some core no-restricted-syntax lint error * fix(core): cr fix
This commit is contained in:
parent
28b2861de8
commit
c56ddec84a
11 changed files with 68 additions and 55 deletions
|
@ -115,8 +115,7 @@
|
|||
"eslintConfig": {
|
||||
"extends": "@silverhand",
|
||||
"rules": {
|
||||
"complexity": "off",
|
||||
"no-restricted-syntax": "off"
|
||||
"complexity": "off"
|
||||
}
|
||||
},
|
||||
"prettier": "@silverhand/eslint-config/.prettierrc"
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
@ -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)
|
||||
)
|
||||
);
|
||||
|
@ -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})`;
|
||||
|
||||
|
|
|
@ -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(() => {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -123,6 +123,7 @@ 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;
|
||||
|
@ -130,11 +131,11 @@ export default function swaggerRoutes<T extends AnonymousRouter, R extends Route
|
|||
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import {
|
|||
ZodOptional,
|
||||
ZodString,
|
||||
ZodStringDef,
|
||||
ZodType,
|
||||
ZodUnion,
|
||||
ZodUnknown,
|
||||
} from 'zod';
|
||||
|
@ -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)),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue