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": {
|
"eslintConfig": {
|
||||||
"extends": "@silverhand",
|
"extends": "@silverhand",
|
||||||
"rules": {
|
"rules": {
|
||||||
"complexity": "off",
|
"complexity": "off"
|
||||||
"no-restricted-syntax": "off"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"prettier": "@silverhand/eslint-config/.prettierrc"
|
"prettier": "@silverhand/eslint-config/.prettierrc"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { SchemaValuePrimitive, SchemaValue } from '@logto/schemas';
|
import { SchemaValuePrimitive, SchemaValue } from '@logto/schemas';
|
||||||
import { Falsy, notFalsy } from '@silverhand/essentials';
|
import { Falsy, notFalsy } from '@silverhand/essentials';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { sql, SqlSqlToken, SqlToken, QueryResult } from 'slonik';
|
import { sql, SqlSqlToken, SqlToken, QueryResult, IdentifierSqlToken } from 'slonik';
|
||||||
|
|
||||||
import { FieldIdentifiers, Table } from './types';
|
import { FieldIdentifiers, Table } from './types';
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@ export const excludeAutoSetFields = <T extends string>(fields: readonly T[]) =>
|
||||||
Object.freeze(
|
Object.freeze(
|
||||||
fields.filter(
|
fields.filter(
|
||||||
(field): field is ExcludeAutoSetFields<T> =>
|
(field): field is ExcludeAutoSetFields<T> =>
|
||||||
|
// Read only string arrays
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
!(autoSetFields as readonly string[]).includes(field)
|
!(autoSetFields as readonly string[]).includes(field)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -52,20 +54,18 @@ export const convertToPrimitiveOrSql = (
|
||||||
throw new Error(`Cannot convert ${key} to primitive`);
|
throw new Error(`Cannot convert ${key} to primitive`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const convertToIdentifiers = <T extends Table>(
|
export const convertToIdentifiers = <T extends Table>({ table, fields }: T, withPrefix = false) => {
|
||||||
{ table, fields }: T,
|
const fieldsIdentifiers = Object.entries<string>(fields).map<
|
||||||
withPrefix = false
|
[keyof T['fields'], IdentifierSqlToken]
|
||||||
) => ({
|
>(([key, value]) => [key, sql.identifier(withPrefix ? [table, value] : [value])]);
|
||||||
|
|
||||||
|
return {
|
||||||
table: sql.identifier([table]),
|
table: sql.identifier([table]),
|
||||||
fields: Object.entries<string>(fields).reduce(
|
// Key value inferred from the original fields directly
|
||||||
(previous, [key, value]) => ({
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
...previous,
|
fields: Object.fromEntries(fieldsIdentifiers) as FieldIdentifiers<keyof T['fields']>,
|
||||||
[key]: sql.identifier(withPrefix ? [table, value] : [value]),
|
};
|
||||||
}),
|
};
|
||||||
// eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter
|
|
||||||
{} as FieldIdentifiers<keyof T['fields']>
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const convertToTimestamp = (time = dayjs()) => sql`to_timestamp(${time.valueOf() / 1000})`;
|
export const convertToTimestamp = (time = dayjs()) => sql`to_timestamp(${time.valueOf() / 1000})`;
|
||||||
|
|
||||||
|
|
|
@ -47,14 +47,16 @@ const mockedIncreasePasscodeTryCount = increasePasscodeTryCount as jest.MockedFu
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
mockedFindUnconsumedPasscodesByJtiAndType.mockResolvedValue([]);
|
mockedFindUnconsumedPasscodesByJtiAndType.mockResolvedValue([]);
|
||||||
mockedInsertPasscode.mockImplementation(async (data) => ({
|
mockedInsertPasscode.mockImplementation(async (data): Promise<Passcode> => {
|
||||||
|
return {
|
||||||
|
phone: null,
|
||||||
|
email: null,
|
||||||
|
consumed: false,
|
||||||
|
tryCount: 0,
|
||||||
...data,
|
...data,
|
||||||
createdAt: Date.now(),
|
createdAt: Date.now(),
|
||||||
phone: data.phone ?? null,
|
};
|
||||||
email: data.email ?? null,
|
});
|
||||||
consumed: data.consumed ?? false,
|
|
||||||
tryCount: data.tryCount ?? 0,
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|
|
@ -81,7 +81,7 @@ export default function koaGuard<
|
||||||
WithGuardedRequestContext<ContextT, GuardQueryT, GuardBodyT, GuardParametersT>,
|
WithGuardedRequestContext<ContextT, GuardQueryT, GuardBodyT, GuardParametersT>,
|
||||||
GuardResponseT
|
GuardResponseT
|
||||||
> = async (ctx, next) => {
|
> = 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 = {
|
ctx.guard = {
|
||||||
query: tryParse('query', query, ctx.request.query),
|
query: tryParse('query', query, ctx.request.query),
|
||||||
body: tryParse('body', body, ctx.request.body),
|
body: tryParse('body', body, ctx.request.body),
|
||||||
|
|
|
@ -22,6 +22,7 @@ export default function koaI18next<
|
||||||
return async (ctx, next) => {
|
return async (ctx, next) => {
|
||||||
const languages = detectLanguage(ctx);
|
const languages = detectLanguage(ctx);
|
||||||
// Cannot patch type def directly, see https://github.com/microsoft/TypeScript/issues/36146
|
// 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 languageUtils = i18next.services.languageUtils as LanguageUtils;
|
||||||
const foundLanguage = languages
|
const foundLanguage = languages
|
||||||
.map((code) => languageUtils.formatLanguageCode(code))
|
.map((code) => languageUtils.formatLanguageCode(code))
|
||||||
|
|
|
@ -45,6 +45,8 @@ export default function koaOIDCErrorHandler<StateT, ContextT>(): Middleware<Stat
|
||||||
case errors.InvalidGrant:
|
case errors.InvalidGrant:
|
||||||
throw new RequestError(
|
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,
|
code: `oidc.${decamelize(name)}` as LogtoErrorCode,
|
||||||
status,
|
status,
|
||||||
expose,
|
expose,
|
||||||
|
|
|
@ -35,26 +35,32 @@ export default function koaSlonikErrorHandler<StateT, ContextT>(): Middleware<St
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (error.constructor) {
|
if (error instanceof InsertionError) {
|
||||||
case InsertionError:
|
|
||||||
throw new RequestError({
|
throw new RequestError({
|
||||||
code: 'entity.create_failed',
|
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,
|
name: (error as InsertionError<SchemaLike>).schema.tableSingular,
|
||||||
});
|
});
|
||||||
case UpdateError:
|
}
|
||||||
|
|
||||||
|
if (error instanceof UpdateError) {
|
||||||
throw new RequestError({
|
throw new RequestError({
|
||||||
code: 'entity.not_exists',
|
code: 'entity.not_exists',
|
||||||
name: (error as InsertionError<SchemaLike>).schema.tableSingular,
|
// Assert generic type of the Class instance
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
|
name: (error as UpdateError<SchemaLike>).schema.tableSingular,
|
||||||
});
|
});
|
||||||
case DeletionError:
|
}
|
||||||
case NotFoundError:
|
|
||||||
|
if (error instanceof DeletionError || error instanceof NotFoundError) {
|
||||||
throw new RequestError({
|
throw new RequestError({
|
||||||
code: 'entity.not_found',
|
code: 'entity.not_found',
|
||||||
status: 404,
|
status: 404,
|
||||||
});
|
});
|
||||||
default:
|
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,7 @@ export default function swaggerRoutes<T extends AnonymousRouter, R extends Route
|
||||||
) {
|
) {
|
||||||
router.get('/swagger.json', async (ctx, next) => {
|
router.get('/swagger.json', async (ctx, next) => {
|
||||||
// Use `as` here since we'll check typing with integration tests
|
// Use `as` here since we'll check typing with integration tests
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
const additionalSwagger = load(
|
const additionalSwagger = load(
|
||||||
await readFile('static/yaml/additional-swagger.yaml', { encoding: 'utf-8' })
|
await readFile('static/yaml/additional-swagger.yaml', { encoding: 'utf-8' })
|
||||||
) as OpenAPIV3.Document;
|
) as OpenAPIV3.Document;
|
||||||
|
@ -130,11 +131,11 @@ export default function swaggerRoutes<T extends AnonymousRouter, R extends Route
|
||||||
const routes = allRouters.flatMap<RouteObject>((router) =>
|
const routes = allRouters.flatMap<RouteObject>((router) =>
|
||||||
router.stack.flatMap<RouteObject>(({ path: routerPath, stack, methods }) =>
|
router.stack.flatMap<RouteObject>(({ path: routerPath, stack, methods }) =>
|
||||||
methods
|
methods
|
||||||
|
.map((method) => method.toLowerCase())
|
||||||
// There is no need to show the HEAD method.
|
// There is no need to show the HEAD method.
|
||||||
.filter((method) => method !== 'HEAD')
|
.filter((method): method is OpenAPIV3.HttpMethods => method !== 'head')
|
||||||
.map((method) => {
|
.map((httpMethod) => {
|
||||||
const path = `/api${routerPath}`;
|
const path = `/api${routerPath}`;
|
||||||
const httpMethod = method.toLowerCase() as OpenAPIV3.HttpMethods;
|
|
||||||
|
|
||||||
const additionalPathItem = additionalSwagger.paths[path] ?? {};
|
const additionalPathItem = additionalSwagger.paths[path] ?? {};
|
||||||
const additionalResponses = additionalPathItem[httpMethod]?.responses;
|
const additionalResponses = additionalPathItem[httpMethod]?.responses;
|
||||||
|
|
|
@ -29,11 +29,10 @@ interface GrantBody {
|
||||||
}
|
}
|
||||||
|
|
||||||
const getLogType = (grantType: unknown) => {
|
const getLogType = (grantType: unknown) => {
|
||||||
if (
|
const allowedGrantType = new Set<unknown>([GrantType.AuthorizationCode, GrantType.RefreshToken]);
|
||||||
!grantType ||
|
|
||||||
![GrantType.AuthorizationCode, GrantType.RefreshToken].includes(grantType as GrantType)
|
|
||||||
) {
|
|
||||||
// Only log token exchange by authorization code or refresh token.
|
// Only log token exchange by authorization code or refresh token.
|
||||||
|
if (!grantType || !allowedGrantType.has(grantType)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,8 @@ export function createRequester({
|
||||||
if (provider) {
|
if (provider) {
|
||||||
route(anonymousRouter, provider);
|
route(anonymousRouter, provider);
|
||||||
} else {
|
} else {
|
||||||
|
// For test use only
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
(route as RouteLauncher<AnonymousRouter>)(anonymousRouter);
|
(route as RouteLauncher<AnonymousRouter>)(anonymousRouter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ import {
|
||||||
ZodOptional,
|
ZodOptional,
|
||||||
ZodString,
|
ZodString,
|
||||||
ZodStringDef,
|
ZodStringDef,
|
||||||
ZodType,
|
|
||||||
ZodUnion,
|
ZodUnion,
|
||||||
ZodUnknown,
|
ZodUnknown,
|
||||||
} from 'zod';
|
} from 'zod';
|
||||||
|
@ -129,7 +128,9 @@ export const zodTypeToSwagger = (config: unknown): OpenAPIV3.SchemaObject => {
|
||||||
|
|
||||||
if (config instanceof ZodUnion) {
|
if (config instanceof ZodUnion) {
|
||||||
return {
|
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