diff --git a/packages/connector-alipay-native/src/index.ts b/packages/connector-alipay-native/src/index.ts index 992f799fc..501d90f23 100644 --- a/packages/connector-alipay-native/src/index.ts +++ b/packages/connector-alipay-native/src/index.ts @@ -10,10 +10,9 @@ */ import { + AuthResponseParser, ConnectorError, ConnectorErrorCodes, - ConnectorMetadata, - Connector, GetAuthorizationUri, GetUserInfo, SocialConnectorInstance, @@ -22,7 +21,6 @@ import { import { assert } from '@silverhand/essentials'; import dayjs from 'dayjs'; import got from 'got'; -import { z } from 'zod'; import { alipayEndpoint, @@ -37,7 +35,9 @@ import { } from './constant'; import { alipayNativeConfigGuard, + authResponseGuard, AlipayNativeConfig, + AuthResponse, accessTokenResponseGuard, userInfoResponseGuard, ErrorHandler, @@ -46,25 +46,17 @@ import { signingParameters } from './utils'; export type { AlipayNativeConfig } from './types'; -export default class AlipayNativeConnector implements SocialConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; - } - - public set connector(input: Connector) { - this._connector = input; - } - +export default class AlipayNativeConnector extends SocialConnectorInstance< + AlipayNativeConfig, + T +> { private readonly signingParameters = signingParameters; - constructor(public readonly getConfig: GetConnectorConfig) {} + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); + } public validateConfig(config: unknown): asserts config is AlipayNativeConfig { const result = alipayNativeConfigGuard.safeParse(config); @@ -125,7 +117,7 @@ export default class AlipayNativeConnector implements SocialConnectorInstance { - const { auth_code } = await this.authorizationCallbackHandler(data); + const { auth_code } = await this.authResponseParser(data); const config = await this.getConfig(this.metadata.id); this.validateConfig(config); @@ -174,6 +166,18 @@ export default class AlipayNativeConnector implements SocialConnectorInstance = async ( + parameterObject: unknown + ) => { + const result = authResponseGuard.safeParse(parameterObject); + + if (!result.success) { + throw new ConnectorError(ConnectorErrorCodes.General, JSON.stringify(parameterObject)); + } + + return result.data; + }; + private readonly errorHandler: ErrorHandler = ({ code, msg, sub_code, sub_msg }) => { if (invalidAccessTokenCode.includes(code)) { throw new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid, msg); @@ -193,17 +197,5 @@ export default class AlipayNativeConnector implements SocialConnectorInstance { - const dataGuard = z.object({ auth_code: z.string() }); - - const result = dataGuard.safeParse(parameterObject); - - if (!result.success) { - throw new ConnectorError(ConnectorErrorCodes.General, JSON.stringify(parameterObject)); - } - - return result.data; - }; } /* eslint-enable unicorn/text-encoding-identifier-case */ diff --git a/packages/connector-alipay-native/src/types.ts b/packages/connector-alipay-native/src/types.ts index d0eddb9eb..27b6af6c7 100644 --- a/packages/connector-alipay-native/src/types.ts +++ b/packages/connector-alipay-native/src/types.ts @@ -57,3 +57,7 @@ export const userInfoResponseGuard = z.object({ export type UserInfoResponse = z.infer; export type ErrorHandler = (response: AlipayUserInfoShareResponseGuard) => void; + +export const authResponseGuard = z.object({ auth_code: z.string() }); + +export type AuthResponse = z.infer; diff --git a/packages/connector-alipay-web/src/index.ts b/packages/connector-alipay-web/src/index.ts index cc9f966e6..1c4ec0b4d 100644 --- a/packages/connector-alipay-web/src/index.ts +++ b/packages/connector-alipay-web/src/index.ts @@ -6,10 +6,9 @@ */ import { + AuthResponseParser, ConnectorError, ConnectorErrorCodes, - ConnectorMetadata, - Connector, GetAuthorizationUri, GetUserInfo, SocialConnectorInstance, @@ -18,7 +17,6 @@ import { import { assert } from '@silverhand/essentials'; import dayjs from 'dayjs'; import got from 'got'; -import { z } from 'zod'; import { alipayEndpoint, @@ -35,7 +33,9 @@ import { } from './constant'; import { alipayConfigGuard, + authResponseGuard, AlipayConfig, + AuthResponse, accessTokenResponseGuard, userInfoResponseGuard, ErrorHandler, @@ -44,25 +44,14 @@ import { signingParameters } from './utils'; export type { AlipayConfig } from './types'; -export default class AlipayConnector implements SocialConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; - } - - public set connector(input: Connector) { - this._connector = input; - } - +export default class AlipayConnector extends SocialConnectorInstance { private readonly signingParameters = signingParameters; - constructor(public readonly getConfig: GetConnectorConfig) {} + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); + } public validateConfig(config: unknown): asserts config is AlipayConfig { const result = alipayConfigGuard.safeParse(config); @@ -131,7 +120,7 @@ export default class AlipayConnector implements SocialConnectorInstance { - const { auth_code } = await this.authorizationCallbackHandler(data); + const { auth_code } = await this.authResponseParser(data); const config = await this.getConfig(this.metadata.id); this.validateConfig(config); @@ -183,6 +172,21 @@ export default class AlipayConnector implements SocialConnectorInstance = async ( + parameterObject: unknown + ) => { + const result = authResponseGuard.safeParse(parameterObject); + + if (!result.success) { + throw new ConnectorError( + ConnectorErrorCodes.InvalidResponse, + JSON.stringify(parameterObject) + ); + } + + return result.data; + }; + private readonly errorHandler: ErrorHandler = ({ code, msg, sub_code, sub_msg }) => { if (invalidAccessTokenCode.includes(code)) { throw new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid, msg); @@ -202,19 +206,4 @@ export default class AlipayConnector implements SocialConnectorInstance { - const dataGuard = z.object({ auth_code: z.string() }); - - const result = dataGuard.safeParse(parameterObject); - - if (!result.success) { - throw new ConnectorError( - ConnectorErrorCodes.InvalidResponse, - JSON.stringify(parameterObject) - ); - } - - return result.data; - }; } diff --git a/packages/connector-alipay-web/src/types.ts b/packages/connector-alipay-web/src/types.ts index 33972b96a..46de6968e 100644 --- a/packages/connector-alipay-web/src/types.ts +++ b/packages/connector-alipay-web/src/types.ts @@ -58,3 +58,7 @@ export const userInfoResponseGuard = z.object({ export type UserInfoResponse = z.infer; export type ErrorHandler = (response: AlipayUserInfoShareResponse) => void; + +export const authResponseGuard = z.object({ auth_code: z.string() }); + +export type AuthResponse = z.infer; diff --git a/packages/connector-aliyun-dm/src/index.ts b/packages/connector-aliyun-dm/src/index.ts index 3fd92b7c5..6bf6c4681 100644 --- a/packages/connector-aliyun-dm/src/index.ts +++ b/packages/connector-aliyun-dm/src/index.ts @@ -1,13 +1,9 @@ import { ConnectorError, ConnectorErrorCodes, - ConnectorMetadata, - Connector, - EmailSendMessageFunction, - EmailSendTestMessageFunction, + EmailSendMessageByFunction, EmailConnectorInstance, GetConnectorConfig, - EmailMessageTypes, } from '@logto/connector-types'; import { assert } from '@silverhand/essentials'; import { HTTPError } from 'got'; @@ -21,24 +17,13 @@ import { sendMailErrorResponseGuard, } from './types'; -export default class AliyunDmConnector implements EmailConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class AliyunDmConnector extends EmailConnectorInstance { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is AliyunDmConfig { const result = aliyunDmConfigGuard.safeParse(config); @@ -47,25 +32,11 @@ export default class AliyunDmConnector implements EmailConnectorInstance { - const emailConfig = await this.getConfig(this.metadata.id); - - this.validateConfig(emailConfig); - - return this.sendMessageBy(emailConfig, address, type, data); - }; - - public sendTestMessage: EmailSendTestMessageFunction = async (config, address, type, data) => { - this.validateConfig(config); - - return this.sendMessageBy(config, address, type, data); - }; - - private readonly sendMessageBy = async ( - config: AliyunDmConfig, - address: string, - type: keyof EmailMessageTypes, - data: EmailMessageTypes[typeof type] + public readonly sendMessageBy: EmailSendMessageByFunction = async ( + config, + address, + type, + data ) => { const { accessKeyId, accessKeySecret, accountName, fromAlias, templates } = config; const template = templates.find((template) => template.usageType === type); diff --git a/packages/connector-aliyun-sms/src/index.ts b/packages/connector-aliyun-sms/src/index.ts index 01214c87a..f5ef423e7 100644 --- a/packages/connector-aliyun-sms/src/index.ts +++ b/packages/connector-aliyun-sms/src/index.ts @@ -1,13 +1,9 @@ import { ConnectorError, ConnectorErrorCodes, - ConnectorMetadata, - Connector, - SmsSendMessageFunction, - SmsSendTestMessageFunction, + SmsSendMessageByFunction, SmsConnectorInstance, GetConnectorConfig, - SmsMessageTypes, } from '@logto/connector-types'; import { assert } from '@silverhand/essentials'; import { HTTPError } from 'got'; @@ -16,24 +12,13 @@ import { defaultMetadata } from './constant'; import { sendSms } from './single-send-text'; import { aliyunSmsConfigGuard, AliyunSmsConfig, sendSmsResponseGuard } from './types'; -export default class AliyunSmsConnector implements SmsConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class AliyunSmsConnector extends SmsConnectorInstance { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is AliyunSmsConfig { const result = aliyunSmsConfigGuard.safeParse(config); @@ -42,25 +27,11 @@ export default class AliyunSmsConnector implements SmsConnectorInstance { - const smsConfig = await this.getConfig(this.metadata.id); - - this.validateConfig(smsConfig); - - return this.sendMessageBy(smsConfig, phone, type, data); - }; - - public sendTestMessage: SmsSendTestMessageFunction = async (config, phone, type, data) => { - this.validateConfig(config); - - return this.sendMessageBy(config, phone, type, data); - }; - - private readonly sendMessageBy = async ( - config: AliyunSmsConfig, - phone: string, - type: keyof SmsMessageTypes, - data: SmsMessageTypes[typeof type] + public readonly sendMessageBy: SmsSendMessageByFunction = async ( + config, + phone, + type, + data ) => { const { accessKeyId, accessKeySecret, signName, templates } = config; const template = templates.find(({ usageType }) => usageType === type); diff --git a/packages/connector-apple/src/index.ts b/packages/connector-apple/src/index.ts index 569d0197f..256abd462 100644 --- a/packages/connector-apple/src/index.ts +++ b/packages/connector-apple/src/index.ts @@ -1,37 +1,25 @@ import { - ConnectorMetadata, + AuthResponseParser, GetAuthorizationUri, GetUserInfo, ConnectorError, ConnectorErrorCodes, - Connector, SocialConnectorInstance, GetConnectorConfig, } from '@logto/connector-types'; import { createRemoteJWKSet, jwtVerify } from 'jose'; import { scope, defaultMetadata, jwksUri, issuer, authorizationEndpoint } from './constant'; -import { appleConfigGuard, AppleConfig, dataGuard } from './types'; +import { appleConfigGuard, authResponseGuard, AppleConfig, AuthResponse } from './types'; // TO-DO: support nonce validation -export default class AppleConnector implements SocialConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class AppleConnector extends SocialConnectorInstance { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is AppleConfig { const result = appleConfigGuard.safeParse(config); @@ -59,7 +47,7 @@ export default class AppleConnector implements SocialConnectorInstance { - const { id_token: idToken } = await this.authorizationCallbackHandler(data); + const { id_token: idToken } = await this.authResponseParser(data); if (!idToken) { throw new ConnectorError(ConnectorErrorCodes.SocialIdTokenInvalid); @@ -89,8 +77,10 @@ export default class AppleConnector implements SocialConnectorInstance { - const result = dataGuard.safeParse(parameterObject); + protected readonly authResponseParser: AuthResponseParser = async ( + parameterObject: unknown + ) => { + const result = authResponseGuard.safeParse(parameterObject); if (!result.success) { throw new ConnectorError(ConnectorErrorCodes.General, JSON.stringify(parameterObject)); diff --git a/packages/connector-apple/src/types.ts b/packages/connector-apple/src/types.ts index 70c5175db..d00f4ed67 100644 --- a/packages/connector-apple/src/types.ts +++ b/packages/connector-apple/src/types.ts @@ -7,6 +7,8 @@ export const appleConfigGuard = z.object({ export type AppleConfig = z.infer; // https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/configuring_your_webpage_for_sign_in_with_apple#3331292 -export const dataGuard = z.object({ +export const authResponseGuard = z.object({ id_token: z.string(), }); + +export type AuthResponse = z.infer; diff --git a/packages/connector-azuread/src/index.ts b/packages/connector-azuread/src/index.ts index d118c42b5..1df832ce9 100644 --- a/packages/connector-azuread/src/index.ts +++ b/packages/connector-azuread/src/index.ts @@ -11,16 +11,15 @@ import { ConnectorErrorCodes, GetAuthorizationUri, GetUserInfo, - ConnectorMetadata, - Connector, SocialConnectorInstance, - GetConnectorConfig, codeWithRedirectDataGuard, + CodeWithRedirectData, + GetConnectorConfig, } from '@logto/connector-types'; import { assert, conditional } from '@silverhand/essentials'; import got, { HTTPError } from 'got'; -import { scopes, defaultMetadata, defaultTimeout, graphAPIEndpoint } from './constant'; +import { scopes, defaultTimeout, graphAPIEndpoint, defaultMetadata } from './constant'; import { azureADConfigGuard, AzureADConfig, @@ -28,31 +27,19 @@ import { userInfoResponseGuard, } from './types'; -export default class AzureADConnector implements SocialConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - +export default class AzureADConnector extends SocialConnectorInstance { public clientApplication!: ConfidentialClientApplication; public authCodeUrlParams!: AuthorizationUrlRequest; cryptoProvider = new CryptoProvider(); private readonly authCodeRequest!: AuthorizationCodeRequest; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is AzureADConfig { const result = azureADConfigGuard.safeParse(config); @@ -114,7 +101,7 @@ export default class AzureADConnector implements SocialConnectorInstance { - const { code, redirectUri } = await this.authorizationCallbackHandler(data); + const { code, redirectUri } = await this.authResponseParser(data); const { accessToken } = await this.getAccessToken(code, redirectUri); const config = await this.getConfig(this.metadata.id); @@ -157,7 +144,7 @@ export default class AzureADConnector implements SocialConnectorInstance { + public authResponseParser = async (parameterObject: unknown): Promise => { const result = codeWithRedirectDataGuard.safeParse(parameterObject); if (!result.success) { diff --git a/packages/connector-facebook/src/index.ts b/packages/connector-facebook/src/index.ts index 05eb70516..889b031c6 100644 --- a/packages/connector-facebook/src/index.ts +++ b/packages/connector-facebook/src/index.ts @@ -4,15 +4,15 @@ */ import { + AuthResponseParser, ConnectorError, ConnectorErrorCodes, - ConnectorMetadata, - Connector, GetAuthorizationUri, GetUserInfo, SocialConnectorInstance, GetConnectorConfig, codeWithRedirectDataGuard, + CodeWithRedirectData, } from '@logto/connector-types'; import { assert } from '@silverhand/essentials'; import got, { HTTPError } from 'got'; @@ -33,24 +33,13 @@ import { userInfoResponseGuard, } from './types'; -export default class FacebookConnector implements SocialConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class FacebookConnector extends SocialConnectorInstance { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is FacebookConfig { const result = facebookConfigGuard.safeParse(config); @@ -106,7 +95,7 @@ export default class FacebookConnector implements SocialConnectorInstance { - const { code, redirectUri } = await this.authorizationCallbackHandler(data); + const { code, redirectUri } = await this.authResponseParser(data); const { accessToken } = await this.getAccessToken(code, redirectUri); try { @@ -149,7 +138,9 @@ export default class FacebookConnector implements SocialConnectorInstance { + public readonly authResponseParser: AuthResponseParser = async ( + parameterObject: unknown + ) => { const result = codeWithRedirectDataGuard.safeParse(parameterObject); if (result.success) { diff --git a/packages/connector-github/src/index.ts b/packages/connector-github/src/index.ts index 6c04ea7d5..b7353320b 100644 --- a/packages/connector-github/src/index.ts +++ b/packages/connector-github/src/index.ts @@ -1,13 +1,13 @@ import { - ConnectorMetadata, + AuthResponseParser, GetAuthorizationUri, GetUserInfo, ConnectorError, ConnectorErrorCodes, - Connector, SocialConnectorInstance, GetConnectorConfig, codeDataGuard, + CodeData, } from '@logto/connector-types'; import { assert, conditional } from '@silverhand/essentials'; import got, { HTTPError } from 'got'; @@ -29,24 +29,13 @@ import { userInfoResponseGuard, } from './types'; -export default class GithubConnector implements SocialConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class GithubConnector extends SocialConnectorInstance { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is GithubConfig { const result = githubConfigGuard.safeParse(config); @@ -101,7 +90,7 @@ export default class GithubConnector implements SocialConnectorInstance { - const { code } = await this.authorizationCallbackHandler(data); + const { code } = await this.authResponseParser(data); const { accessToken } = await this.getAccessToken(code); try { @@ -141,7 +130,9 @@ export default class GithubConnector implements SocialConnectorInstance { + public readonly authResponseParser: AuthResponseParser = async ( + parameterObject: unknown + ) => { const result = codeDataGuard.safeParse(parameterObject); if (result.success) { diff --git a/packages/connector-google/src/index.ts b/packages/connector-google/src/index.ts index 2355f223c..4a2d8c916 100644 --- a/packages/connector-google/src/index.ts +++ b/packages/connector-google/src/index.ts @@ -3,15 +3,15 @@ * https://developers.google.com/identity/protocols/oauth2/openid-connect */ import { + AuthResponseParser, ConnectorError, ConnectorErrorCodes, GetAuthorizationUri, GetUserInfo, - ConnectorMetadata, - Connector, SocialConnectorInstance, GetConnectorConfig, codeWithRedirectDataGuard, + CodeWithRedirectData, } from '@logto/connector-types'; import { conditional, assert } from '@silverhand/essentials'; import got, { HTTPError } from 'got'; @@ -31,24 +31,13 @@ import { userInfoResponseGuard, } from './types'; -export default class GoogleConnector implements SocialConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class GoogleConnector extends SocialConnectorInstance { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is GoogleConfig { const result = googleConfigGuard.safeParse(config); @@ -107,7 +96,7 @@ export default class GoogleConnector implements SocialConnectorInstance { - const { code, redirectUri } = await this.authorizationCallbackHandler(data); + const { code, redirectUri } = await this.authResponseParser(data); const { accessToken } = await this.getAccessToken(code, redirectUri); try { @@ -137,7 +126,9 @@ export default class GoogleConnector implements SocialConnectorInstance { + public readonly authResponseParser: AuthResponseParser = async ( + parameterObject: unknown + ) => { const result = codeWithRedirectDataGuard.safeParse(parameterObject); if (!result.success) { diff --git a/packages/connector-mock-email/src/index.ts b/packages/connector-mock-email/src/index.ts index 99bed289e..50dd79e3e 100644 --- a/packages/connector-mock-email/src/index.ts +++ b/packages/connector-mock-email/src/index.ts @@ -4,37 +4,22 @@ import path from 'path'; import { ConnectorError, ConnectorErrorCodes, - ConnectorMetadata, - Connector, - EmailSendMessageFunction, - EmailSendTestMessageFunction, + EmailSendMessageByFunction, EmailConnectorInstance, GetConnectorConfig, - EmailMessageTypes, } from '@logto/connector-types'; import { assert } from '@silverhand/essentials'; import { defaultMetadata } from './constant'; import { mockMailConfigGuard, MockMailConfig } from './types'; -export default class MockMailConnector implements EmailConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class MockMailConnector extends EmailConnectorInstance { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is MockMailConfig { const result = mockMailConfigGuard.safeParse(config); @@ -43,25 +28,11 @@ export default class MockMailConnector implements EmailConnectorInstance { - const config = await this.getConfig(this.metadata.id); - - this.validateConfig(config); - - return this.sendMessageBy(config, address, type, data); - }; - - public sendTestMessage: EmailSendTestMessageFunction = async (config, address, type, data) => { - this.validateConfig(config); - - return this.sendMessageBy(config, address, type, data); - }; - - private readonly sendMessageBy = async ( - config: MockMailConfig, - address: string, - type: keyof EmailMessageTypes, - data: EmailMessageTypes[typeof type] + public readonly sendMessageBy: EmailSendMessageByFunction = async ( + config, + address, + type, + data ) => { const { templates } = config; const template = templates.find((template) => template.usageType === type); diff --git a/packages/connector-mock-sms/src/index.ts b/packages/connector-mock-sms/src/index.ts index cb1481714..33d369406 100644 --- a/packages/connector-mock-sms/src/index.ts +++ b/packages/connector-mock-sms/src/index.ts @@ -4,37 +4,22 @@ import path from 'path'; import { ConnectorError, ConnectorErrorCodes, - ConnectorMetadata, - Connector, - SmsSendMessageFunction, - SmsSendTestMessageFunction, + SmsSendMessageByFunction, SmsConnectorInstance, GetConnectorConfig, - SmsMessageTypes, } from '@logto/connector-types'; import { assert } from '@silverhand/essentials'; import { defaultMetadata } from './constant'; import { mockSmsConfigGuard, MockSmsConfig } from './types'; -export default class MockSmsConnector implements SmsConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class MockSmsConnector extends SmsConnectorInstance { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is MockSmsConfig { const result = mockSmsConfigGuard.safeParse(config); @@ -43,25 +28,11 @@ export default class MockSmsConnector implements SmsConnectorInstance { - const config = await this.getConfig(this.metadata.id); - - this.validateConfig(config); - - return this.sendMessageBy(config, phone, type, data); - }; - - public sendTestMessage: SmsSendTestMessageFunction = async (config, phone, type, data) => { - this.validateConfig(config); - - return this.sendMessageBy(config, phone, type, data); - }; - - private readonly sendMessageBy = async ( - config: MockSmsConfig, - phone: string, - type: keyof SmsMessageTypes, - data: SmsMessageTypes[typeof type] + public readonly sendMessageBy: SmsSendMessageByFunction = async ( + config, + phone, + type, + data ) => { const { templates } = config; const template = templates.find((template) => template.usageType === type); diff --git a/packages/connector-mock-social/src/index.ts b/packages/connector-mock-social/src/index.ts index e8c75df7a..c342a40c4 100644 --- a/packages/connector-mock-social/src/index.ts +++ b/packages/connector-mock-social/src/index.ts @@ -5,8 +5,6 @@ import { ConnectorErrorCodes, GetAuthorizationUri, GetUserInfo, - ConnectorMetadata, - Connector, SocialConnectorInstance, GetConnectorConfig, } from '@logto/connector-types'; @@ -15,24 +13,13 @@ import { z } from 'zod'; import { defaultMetadata } from './constant'; import { mockSocialConfigGuard, MockSocialConfig } from './types'; -export default class MockSocialConnector implements SocialConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class MockSocialConnector extends SocialConnectorInstance { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is MockSocialConfig { const result = mockSocialConfigGuard.safeParse(config); diff --git a/packages/connector-sendgrid-mail/src/index.ts b/packages/connector-sendgrid-mail/src/index.ts index 022451aa8..68df55cc9 100644 --- a/packages/connector-sendgrid-mail/src/index.ts +++ b/packages/connector-sendgrid-mail/src/index.ts @@ -1,13 +1,9 @@ import { ConnectorError, ConnectorErrorCodes, - ConnectorMetadata, - Connector, - EmailSendMessageFunction, - EmailSendTestMessageFunction, + EmailSendMessageByFunction, EmailConnectorInstance, GetConnectorConfig, - EmailMessageTypes, } from '@logto/connector-types'; import { assert } from '@silverhand/essentials'; import got, { HTTPError } from 'got'; @@ -22,24 +18,16 @@ import { PublicParameters, } from './types'; -export default class SendGridMailConnector implements EmailConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class SendGridMailConnector extends EmailConnectorInstance< + SendGridMailConfig, + T +> { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is SendGridMailConfig { const result = sendGridMailConfigGuard.safeParse(config); @@ -48,25 +36,11 @@ export default class SendGridMailConnector implements EmailConnectorInstance { - const config = await this.getConfig(this.metadata.id); - - this.validateConfig(config); - - return this.sendMessageBy(config, address, type, data); - }; - - public sendTestMessage: EmailSendTestMessageFunction = async (config, address, type, data) => { - this.validateConfig(config); - - return this.sendMessageBy(config, address, type, data); - }; - - private readonly sendMessageBy = async ( - config: SendGridMailConfig, - address: string, - type: keyof EmailMessageTypes, - data: EmailMessageTypes[typeof type] + public readonly sendMessageBy: EmailSendMessageByFunction = async ( + config, + address, + type, + data ) => { const { apiKey, fromEmail, fromName, templates } = config; const template = templates.find((template) => template.usageType === type); diff --git a/packages/connector-smtp/src/index.ts b/packages/connector-smtp/src/index.ts index 9254d69f8..55b483a2e 100644 --- a/packages/connector-smtp/src/index.ts +++ b/packages/connector-smtp/src/index.ts @@ -1,13 +1,9 @@ import { ConnectorError, ConnectorErrorCodes, - ConnectorMetadata, - Connector, - EmailSendMessageFunction, - EmailSendTestMessageFunction, + EmailSendMessageByFunction, EmailConnectorInstance, GetConnectorConfig, - EmailMessageTypes, } from '@logto/connector-types'; import { assert } from '@silverhand/essentials'; import nodemailer from 'nodemailer'; @@ -16,24 +12,13 @@ import SMTPTransport from 'nodemailer/lib/smtp-transport'; import { defaultMetadata } from './constant'; import { ContextType, smtpConfigGuard, SmtpConfig } from './types'; -export default class SmtpConnector implements EmailConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class SmtpConnector extends EmailConnectorInstance { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is SmtpConfig { const result = smtpConfigGuard.safeParse(config); @@ -42,25 +27,11 @@ export default class SmtpConnector implements EmailConnectorInstance } } - public sendMessage: EmailSendMessageFunction = async (address, type, data) => { - const config = await this.getConfig(this.metadata.id); - - this.validateConfig(config); - - return this.sendMessageBy(config, address, type, data); - }; - - public sendTestMessage: EmailSendTestMessageFunction = async (config, address, type, data) => { - this.validateConfig(config); - - return this.sendMessageBy(config, address, type, data); - }; - - private readonly sendMessageBy = async ( - config: SmtpConfig, - address: string, - type: keyof EmailMessageTypes, - data: EmailMessageTypes[typeof type] + public readonly sendMessageBy: EmailSendMessageByFunction = async ( + config, + address, + type, + data ) => { const { host, port, username, password, fromEmail, replyTo, templates } = config; const template = templates.find((template) => template.usageType === type); diff --git a/packages/connector-twilio-sms/src/index.ts b/packages/connector-twilio-sms/src/index.ts index 86f92af1d..ad5196240 100644 --- a/packages/connector-twilio-sms/src/index.ts +++ b/packages/connector-twilio-sms/src/index.ts @@ -1,13 +1,9 @@ import { ConnectorError, ConnectorErrorCodes, - ConnectorMetadata, - Connector, - SmsSendMessageFunction, - SmsSendTestMessageFunction, + SmsSendMessageByFunction, SmsConnectorInstance, GetConnectorConfig, - SmsMessageTypes, } from '@logto/connector-types'; import { assert } from '@silverhand/essentials'; import got, { HTTPError } from 'got'; @@ -15,24 +11,13 @@ import got, { HTTPError } from 'got'; import { defaultMetadata, endpoint } from './constant'; import { twilioSmsConfigGuard, TwilioSmsConfig, PublicParameters } from './types'; -export default class TwilioSmsConnector implements SmsConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class TwilioSmsConnector extends SmsConnectorInstance { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is TwilioSmsConfig { const result = twilioSmsConfigGuard.safeParse(config); @@ -41,25 +26,11 @@ export default class TwilioSmsConnector implements SmsConnectorInstance { - const config = await this.getConfig(this.metadata.id); - - this.validateConfig(config); - - return this.sendMessageBy(config, phone, type, data); - }; - - public sendTestMessage: SmsSendTestMessageFunction = async (config, phone, type, data) => { - this.validateConfig(config); - - return this.sendMessageBy(config, phone, type, data); - }; - - private readonly sendMessageBy = async ( - config: TwilioSmsConfig, - phone: string, - type: keyof SmsMessageTypes, - data: SmsMessageTypes[typeof type] + public readonly sendMessageBy: SmsSendMessageByFunction = async ( + config, + phone, + type, + data ) => { const { accountSID, authToken, fromMessagingServiceSID, templates } = config; const template = templates.find((template) => template.usageType === type); diff --git a/packages/connector-types/src/index.ts b/packages/connector-types/src/index.ts index 7d6986761..741b5508f 100644 --- a/packages/connector-types/src/index.ts +++ b/packages/connector-types/src/index.ts @@ -1,26 +1,9 @@ // FIXME: @Darcy -/* eslint-disable @typescript-eslint/consistent-type-definitions */ import type { Language } from '@logto/phrases'; import { Nullable } from '@silverhand/essentials'; import { z } from 'zod'; -/** - * Connector is auto-generated in @logto/schemas according to sql file. - * As @logto/schemas depends on this repo (@logto/connector-types), we manually define Connector type again as a temporary solution. - */ - -export const arbitraryObjectGuard = z.union([z.object({}).catchall(z.unknown()), z.object({})]); - -export type ArbitraryObject = z.infer; - -export type Connector = { - id: string; - enabled: boolean; - config: ArbitraryObject; - createdAt: number; -}; - export enum ConnectorType { Email = 'Email', SMS = 'SMS', @@ -103,6 +86,13 @@ export type EmailSendTestMessageFunction = ( payload: EmailMessageTypes[typeof type] ) => Promise; +export type EmailSendMessageByFunction = ( + config: T, + address: string, + type: keyof EmailMessageTypes, + payload: EmailMessageTypes[typeof type] +) => Promise; + export type SmsSendMessageFunction = ( phone: string, type: keyof SmsMessageTypes, @@ -116,45 +106,14 @@ export type SmsSendTestMessageFunction = ( payload: SmsMessageTypes[typeof type] ) => Promise; -export interface BaseConnector { - metadata: ConnectorMetadata; - getConfig: GetConnectorConfig; - validateConfig: ValidateConfig; -} +export type SmsSendMessageByFunction = ( + config: T, + phone: string, + type: keyof SmsMessageTypes, + payload: SmsMessageTypes[typeof type] +) => Promise; -export interface SmsConnector extends BaseConnector { - sendMessage: SmsSendMessageFunction; - sendTestMessage?: SmsSendTestMessageFunction; -} - -export interface SmsConnectorInstance extends SmsConnector { - connector: Connector; -} - -export interface EmailConnector extends BaseConnector { - sendMessage: EmailSendMessageFunction; - sendTestMessage?: EmailSendTestMessageFunction; -} - -export interface EmailConnectorInstance extends EmailConnector { - connector: Connector; -} - -export interface SocialConnector extends BaseConnector { - getAuthorizationUri: GetAuthorizationUri; - getUserInfo: GetUserInfo; -} - -export interface SocialConnectorInstance extends SocialConnector { - connector: Connector; -} - -export type ConnectorInstance = - | SmsConnectorInstance - | EmailConnectorInstance - | SocialConnectorInstance; - -export type ValidateConfig = (config: unknown) => asserts config is T; +export type ValidateConfig = (config: unknown) => asserts config is T; export type GetAuthorizationUri = (payload: { state: string; @@ -167,6 +126,8 @@ export type GetUserInfo = ( export type GetConnectorConfig = (id: string) => Promise; +export type AuthResponseParser> = (response: unknown) => Promise; + export const codeDataGuard = z.object({ code: z.string(), }); diff --git a/packages/connector-types/tsconfig.json b/packages/connector-types/tsconfig.json index f333e0b36..a22774ad3 100644 --- a/packages/connector-types/tsconfig.json +++ b/packages/connector-types/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "@silverhand/ts-config/tsconfig.base", "compilerOptions": { + "types": ["node"], "outDir": "lib", "baseUrl": ".", "paths": { diff --git a/packages/connector-wechat-native/src/index.ts b/packages/connector-wechat-native/src/index.ts index 97c77764e..ad51adcca 100644 --- a/packages/connector-wechat-native/src/index.ts +++ b/packages/connector-wechat-native/src/index.ts @@ -4,15 +4,15 @@ */ import { - ConnectorMetadata, GetAuthorizationUri, GetUserInfo, ConnectorError, ConnectorErrorCodes, - Connector, SocialConnectorInstance, GetConnectorConfig, + AuthResponseParser, codeDataGuard, + CodeData, } from '@logto/connector-types'; import { assert } from '@silverhand/essentials'; import got, { HTTPError } from 'got'; @@ -35,24 +35,16 @@ import { WechatNativeConfig, } from './types'; -export default class WechatNativeConnector implements SocialConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class WechatNativeConnector extends SocialConnectorInstance< + WechatNativeConfig, + T +> { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is WechatNativeConfig { const result = wechatNativeConfigGuard.safeParse(config); @@ -108,7 +100,7 @@ export default class WechatNativeConnector implements SocialConnectorInstance { - const { code } = await this.authorizationCallbackHandler(data); + const { code } = await this.authResponseParser(data); const { accessToken, openid } = await this.getAccessToken(code); try { @@ -136,6 +128,16 @@ export default class WechatNativeConnector implements SocialConnectorInstance = async (parameterObject: unknown) => { + const result = codeDataGuard.safeParse(parameterObject); + + if (!result.success) { + throw new ConnectorError(ConnectorErrorCodes.General, JSON.stringify(parameterObject)); + } + + return result.data; + }; + // See https://developers.weixin.qq.com/doc/oplatform/Return_codes/Return_code_descriptions_new.html private readonly getAccessTokenErrorHandler: GetAccessTokenErrorHandler = (accessToken) => { const { errcode, errmsg } = accessToken; @@ -176,14 +178,4 @@ export default class WechatNativeConnector implements SocialConnectorInstance { - const result = codeDataGuard.safeParse(parameterObject); - - if (!result.success) { - throw new ConnectorError(ConnectorErrorCodes.General, JSON.stringify(parameterObject)); - } - - return result.data; - }; } diff --git a/packages/connector-wechat-web/src/index.ts b/packages/connector-wechat-web/src/index.ts index 7e9e38492..c08aeaecf 100644 --- a/packages/connector-wechat-web/src/index.ts +++ b/packages/connector-wechat-web/src/index.ts @@ -4,15 +4,15 @@ */ import { - ConnectorMetadata, + AuthResponseParser, GetAuthorizationUri, GetUserInfo, ConnectorError, ConnectorErrorCodes, - Connector, SocialConnectorInstance, GetConnectorConfig, codeDataGuard, + CodeData, } from '@logto/connector-types'; import { assert } from '@silverhand/essentials'; import got, { HTTPError } from 'got'; @@ -36,24 +36,13 @@ import { WechatConfig, } from './types'; -export default class WechatConnector implements SocialConnectorInstance { - public metadata: ConnectorMetadata = defaultMetadata; - private _connector?: Connector; - - public get connector() { - if (!this._connector) { - throw new ConnectorError(ConnectorErrorCodes.General); - } - - return this._connector; +export default class WechatConnector extends SocialConnectorInstance { + constructor(getConnectorConfig: GetConnectorConfig) { + super(getConnectorConfig); + this.metadata = defaultMetadata; + this.metadataParser(); } - public set connector(input: Connector) { - this._connector = input; - } - - constructor(public readonly getConfig: GetConnectorConfig) {} - public validateConfig(config: unknown): asserts config is WechatConfig { const result = wechatConfigGuard.safeParse(config); @@ -110,7 +99,7 @@ export default class WechatConnector implements SocialConnectorInstance { - const { code } = await this.authorizationCallbackHandler(data); + const { code } = await this.authResponseParser(data); const { accessToken, openid } = await this.getAccessToken(code); try { @@ -138,6 +127,16 @@ export default class WechatConnector implements SocialConnectorInstance = async (parameterObject: unknown) => { + const result = codeDataGuard.safeParse(parameterObject); + + if (!result.success) { + throw new ConnectorError(ConnectorErrorCodes.General, JSON.stringify(parameterObject)); + } + + return result.data; + }; + // See https://developers.weixin.qq.com/doc/oplatform/Return_codes/Return_code_descriptions_new.html private readonly getAccessTokenErrorHandler: GetAccessTokenErrorHandler = (accessToken) => { const { errcode, errmsg } = accessToken; @@ -178,14 +177,4 @@ export default class WechatConnector implements SocialConnectorInstance { - const result = codeDataGuard.safeParse(parameterObject); - - if (!result.success) { - throw new ConnectorError(ConnectorErrorCodes.General, JSON.stringify(parameterObject)); - } - - return result.data; - }; } diff --git a/packages/core/src/connectors/index.ts b/packages/core/src/connectors/index.ts index 0b33cd3d7..e447a721f 100644 --- a/packages/core/src/connectors/index.ts +++ b/packages/core/src/connectors/index.ts @@ -1,8 +1,5 @@ -import { existsSync, readFileSync } from 'fs'; -import path from 'path'; - import { ConnectorInstance, SocialConnectorInstance } from '@logto/connector-types'; -import resolvePackagePath from 'resolve-package-path'; +import { Connector } from '@logto/schemas'; import envSet from '@/env-set'; import RequestError from '@/errors/RequestError'; @@ -32,55 +29,7 @@ const loadConnectors = async () => { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const { default: Builder } = await import(packageName); // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment - const instance: ConnectorInstance = new Builder(getConnectorConfig); - // eslint-disable-next-line unicorn/prefer-module - const packagePath = resolvePackagePath(packageName, __dirname); - - // For relative path logo url, try to read local asset. - if ( - packagePath && - !instance.metadata.logo.startsWith('http') && - existsSync(path.join(packagePath, '..', instance.metadata.logo)) - ) { - const data = readFileSync(path.join(packagePath, '..', instance.metadata.logo)); - // eslint-disable-next-line @silverhand/fp/no-mutation - instance.metadata.logo = `data:image/svg+xml;base64,${data.toString('base64')}`; - } - - if ( - packagePath && - instance.metadata.logoDark && - !instance.metadata.logoDark.startsWith('http') && - existsSync(path.join(packagePath, '..', instance.metadata.logoDark)) - ) { - const data = readFileSync(path.join(packagePath, '..', instance.metadata.logoDark)); - // eslint-disable-next-line @silverhand/fp/no-mutation - instance.metadata.logoDark = `data:image/svg+xml;base64,${data.toString('base64')}`; - } - - if ( - packagePath && - instance.metadata.readme && - existsSync(path.join(packagePath, '..', instance.metadata.readme)) - ) { - // eslint-disable-next-line @silverhand/fp/no-mutation - instance.metadata.readme = readFileSync( - path.join(packagePath, '..', instance.metadata.readme), - 'utf8' - ); - } - - if ( - packagePath && - instance.metadata.configTemplate && - existsSync(path.join(packagePath, '..', instance.metadata.configTemplate)) - ) { - // eslint-disable-next-line @silverhand/fp/no-mutation - instance.metadata.configTemplate = readFileSync( - path.join(packagePath, '..', instance.metadata.configTemplate), - 'utf8' - ); - } + const instance: ConnectorInstance = new Builder(getConnectorConfig); return instance; }) @@ -127,13 +76,13 @@ export const getConnectorInstanceById = async (id: string): Promise { +): connector is InstanceType => { return connector.metadata.type === ConnectorType.Social; }; export const getSocialConnectorInstanceById = async ( id: string -): Promise => { +): Promise> => { const connector = await getConnectorInstanceById(id); if (!isSocialConnectorInstance(connector)) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 497b8d7e3..16b31d320 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -660,10 +660,18 @@ importers: '@shopify/jest-koa-mocks': ^5.0.0 '@silverhand/eslint-config': 1.0.0-rc.2 '@silverhand/essentials': ^1.1.6 +<<<<<<< HEAD '@silverhand/ts-config': 1.0.0-rc.2 '@types/jest': ^28.1.6 eslint: ^8.21.0 jest: ^28.1.3 +======= + '@silverhand/ts-config': ^0.17.0 + '@types/jest': ^27.4.1 + '@types/node': ^16.3.1 + eslint: ^8.19.0 + jest: ^27.5.1 +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) lint-staged: ^13.0.0 prettier: ^2.7.1 typescript: ^4.7.4 @@ -676,10 +684,18 @@ importers: '@shopify/jest-koa-mocks': 5.0.0 '@silverhand/eslint-config': 1.0.0-rc.2_swk2g7ygmfleszo5c33j4vooni '@silverhand/essentials': 1.1.7 +<<<<<<< HEAD '@silverhand/ts-config': 1.0.0-rc.2_typescript@4.7.4 '@types/jest': 28.1.6 eslint: 8.21.0 jest: 28.1.3 +======= + '@silverhand/ts-config': 0.17.0_typescript@4.6.3 + '@types/jest': 27.4.1 + '@types/node': 16.11.12 + eslint: 8.19.0 + jest: 27.5.1 +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) lint-staged: 13.0.0 prettier: 2.7.1 typescript: 4.7.4 @@ -2065,8 +2081,13 @@ packages: resolution: {integrity: sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: +<<<<<<< HEAD '@jest/types': 28.1.3 '@types/node': 17.0.23 +======= + '@jest/types': 27.5.1 + '@types/node': 18.6.3 +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) chalk: 4.1.2 jest-message-util: 28.1.3 jest-util: 28.1.3 @@ -2081,12 +2102,21 @@ packages: node-notifier: optional: true dependencies: +<<<<<<< HEAD '@jest/console': 28.1.3 '@jest/reporters': 28.1.3 '@jest/test-result': 28.1.3 '@jest/transform': 28.1.3 '@jest/types': 28.1.3 '@types/node': 17.0.23 +======= + '@jest/console': 27.5.1 + '@jest/reporters': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 18.6.3 +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.3.2 @@ -2123,12 +2153,21 @@ packages: node-notifier: optional: true dependencies: +<<<<<<< HEAD '@jest/console': 28.1.3 '@jest/reporters': 28.1.3 '@jest/test-result': 28.1.3 '@jest/transform': 28.1.3 '@jest/types': 28.1.3 '@types/node': 17.0.23 +======= + '@jest/console': 27.5.1 + '@jest/reporters': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 18.6.3 +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.3.2 @@ -2161,10 +2200,18 @@ packages: resolution: {integrity: sha512-1bf40cMFTEkKyEf585R9Iz1WayDjHoHqvts0XFYEqyKM3cFWDpeMoqKKTAF9LSYQModPUlh8FKptoM2YcMWAXA==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: +<<<<<<< HEAD '@jest/fake-timers': 28.1.3 '@jest/types': 28.1.3 '@types/node': 17.0.23 jest-mock: 28.1.3 +======= + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 18.6.3 + jest-mock: 27.5.1 + dev: true +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) /@jest/expect-utils/28.1.3: resolution: {integrity: sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==} @@ -2185,12 +2232,22 @@ packages: resolution: {integrity: sha512-D/wOkL2POHv52h+ok5Oj/1gOG9HSywdoPtFsRCUmlCILXNn5eIWmcnd3DIiWlJnpGvQtmajqBP95Ei0EimxfLw==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: +<<<<<<< HEAD '@jest/types': 28.1.3 '@sinonjs/fake-timers': 9.1.2 '@types/node': 17.0.23 jest-message-util: 28.1.3 jest-mock: 28.1.3 jest-util: 28.1.3 +======= + '@jest/types': 27.5.1 + '@sinonjs/fake-timers': 8.1.0 + '@types/node': 18.6.3 + jest-message-util: 27.5.1 + jest-mock: 27.5.1 + jest-util: 27.5.1 + dev: true +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) /@jest/globals/28.1.3: resolution: {integrity: sha512-XFU4P4phyryCXu1pbcqMO0GSQcYe1IsalYCDzRNyhetyeyxMcIxa11qPNDpVNLeretItNqEmYYQn1UYz/5x1NA==} @@ -2212,12 +2269,20 @@ packages: optional: true dependencies: '@bcoe/v8-coverage': 0.2.3 +<<<<<<< HEAD '@jest/console': 28.1.3 '@jest/test-result': 28.1.3 '@jest/transform': 28.1.3 '@jest/types': 28.1.3 '@jridgewell/trace-mapping': 0.3.14 '@types/node': 17.0.23 +======= + '@jest/console': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 18.6.3 +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) chalk: 4.1.2 collect-v8-coverage: 1.0.1 exit: 0.1.2 @@ -2300,8 +2365,13 @@ packages: '@jest/schemas': 28.1.3 '@types/istanbul-lib-coverage': 2.0.3 '@types/istanbul-reports': 3.0.1 +<<<<<<< HEAD '@types/node': 17.0.23 '@types/yargs': 17.0.10 +======= + '@types/node': 18.6.3 + '@types/yargs': 16.0.4 +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) chalk: 4.1.2 /@jridgewell/resolve-uri/3.0.5: @@ -4941,7 +5011,12 @@ packages: /@types/graceful-fs/4.1.5: resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} dependencies: +<<<<<<< HEAD '@types/node': 17.0.23 +======= + '@types/node': 18.6.3 + dev: true +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) /@types/hast/2.3.4: resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==} @@ -5125,6 +5200,9 @@ packages: /@types/node/17.0.23: resolution: {integrity: sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==} + /@types/node/18.6.3: + resolution: {integrity: sha512-6qKpDtoaYLM+5+AFChLhHermMQxc3TOEFIDzrZLPRGHPrLEwqFkkT5Kx3ju05g6X7uDPazz3jHbKPX0KzCjntg==} + /@types/nodemailer/6.4.4: resolution: {integrity: sha512-Ksw4t7iliXeYGvIQcSIgWQ5BLuC/mljIEbjf615svhZL10PE9t+ei8O9gDaD3FPCasUJn9KTLwz2JFJyiiyuqw==} dependencies: @@ -9363,11 +9441,18 @@ packages: resolution: {integrity: sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: +<<<<<<< HEAD '@jest/environment': 28.1.3 '@jest/expect': 28.1.3 '@jest/test-result': 28.1.3 '@jest/types': 28.1.3 '@types/node': 17.0.23 +======= + '@jest/environment': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 18.6.3 +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 @@ -9666,6 +9751,7 @@ packages: resolution: {integrity: sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: +<<<<<<< HEAD chalk: 4.1.2 diff-sequences: 28.1.1 jest-get-type: 28.0.2 @@ -9699,6 +9785,15 @@ packages: jest-mock: 28.1.3 jest-util: 28.1.3 jsdom: 19.0.0 +======= + '@jest/environment': 27.5.1 + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 18.6.3 + jest-mock: 27.5.1 + jest-util: 27.5.1 + jsdom: 16.7.0 +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) transitivePeerDependencies: - bufferutil - canvas @@ -9710,12 +9805,22 @@ packages: resolution: {integrity: sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: +<<<<<<< HEAD '@jest/environment': 28.1.3 '@jest/fake-timers': 28.1.3 '@jest/types': 28.1.3 '@types/node': 17.0.23 jest-mock: 28.1.3 jest-util: 28.1.3 +======= + '@jest/environment': 27.5.1 + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 18.6.3 + jest-mock: 27.5.1 + jest-util: 27.5.1 + dev: true +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) /jest-get-type/28.0.2: resolution: {integrity: sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==} @@ -9727,7 +9832,7 @@ packages: dependencies: '@jest/types': 28.1.3 '@types/graceful-fs': 4.1.5 - '@types/node': 17.0.23 + '@types/node': 18.6.3 anymatch: 3.1.2 fb-watchman: 2.0.1 graceful-fs: 4.2.9 @@ -9738,6 +9843,35 @@ packages: walker: 1.0.8 optionalDependencies: fsevents: 2.3.2 +<<<<<<< HEAD +======= + dev: true + + /jest-jasmine2/27.5.1: + resolution: {integrity: sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@jest/environment': 27.5.1 + '@jest/source-map': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 18.6.3 + chalk: 4.1.2 + co: 4.6.0 + expect: 27.5.1 + is-generator-fn: 2.1.0 + jest-each: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + jest-runtime: 27.5.1 + jest-snapshot: 27.5.1 + jest-util: 27.5.1 + pretty-format: 27.5.1 + throat: 6.0.1 + transitivePeerDependencies: + - supports-color + dev: true +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) /jest-leak-detector/28.1.3: resolution: {integrity: sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA==} @@ -9776,8 +9910,14 @@ packages: resolution: {integrity: sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: +<<<<<<< HEAD '@jest/types': 28.1.3 '@types/node': 17.0.23 +======= + '@jest/types': 27.5.1 + '@types/node': 18.6.3 + dev: true +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) /jest-pnp-resolver/1.2.2_jest-resolve@28.1.3: resolution: {integrity: sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==} @@ -9821,12 +9961,21 @@ packages: resolution: {integrity: sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: +<<<<<<< HEAD '@jest/console': 28.1.3 '@jest/environment': 28.1.3 '@jest/test-result': 28.1.3 '@jest/transform': 28.1.3 '@jest/types': 28.1.3 '@types/node': 17.0.23 +======= + '@jest/console': 27.5.1 + '@jest/environment': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 18.6.3 +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) chalk: 4.1.2 emittery: 0.10.2 graceful-fs: 4.2.9 @@ -9873,6 +10022,18 @@ packages: strip-bom: 4.0.0 transitivePeerDependencies: - supports-color +<<<<<<< HEAD +======= + dev: true + + /jest-serializer/27.5.1: + resolution: {integrity: sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@types/node': 18.6.3 + graceful-fs: 4.2.9 + dev: true +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) /jest-snapshot/28.1.3: resolution: {integrity: sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg==} @@ -9921,8 +10082,13 @@ packages: resolution: {integrity: sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: +<<<<<<< HEAD '@jest/types': 28.1.3 '@types/node': 17.0.23 +======= + '@jest/types': 27.5.1 + '@types/node': 18.6.3 +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) chalk: 4.1.2 ci-info: 3.3.2 graceful-fs: 4.2.9 @@ -9943,9 +10109,15 @@ packages: resolution: {integrity: sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: +<<<<<<< HEAD '@jest/test-result': 28.1.3 '@jest/types': 28.1.3 '@types/node': 17.0.23 +======= + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 18.6.3 +>>>>>>> f04cfcf3 (refactor(connector): refactor connector) ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.10.2 @@ -9956,7 +10128,7 @@ packages: resolution: {integrity: sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: - '@types/node': 17.0.23 + '@types/node': 18.6.3 merge-stream: 2.0.0 supports-color: 8.1.1