From 26466e65427680b48161590104f6d153c6e866c9 Mon Sep 17 00:00:00 2001 From: Darcy Ye Date: Sat, 8 Jul 2023 14:19:04 +0800 Subject: [PATCH] refactor(toolkit,core,connector): add connector switch for WIP features --- .../connector-logto-email/src/constant.ts | 6 +----- .../connector-logto-email/src/index.test.ts | 18 +++++++++++------- .../connector-logto-email/src/index.ts | 11 +++++++++-- packages/core/src/libraries/connector.ts | 4 +++- packages/core/src/libraries/passcode.ts | 18 +++++++++++------- .../src/routes/connector/config-testing.ts | 4 +++- packages/core/src/tenants/Tenant.ts | 6 +++++- packages/core/src/test-utils/tenant.ts | 3 ++- packages/core/src/utils/connectors/types.ts | 2 +- packages/toolkit/connector-kit/src/types.ts | 6 +++++- 10 files changed, 51 insertions(+), 27 deletions(-) diff --git a/packages/connectors/connector-logto-email/src/constant.ts b/packages/connectors/connector-logto-email/src/constant.ts index 633018d6d..b933846e1 100644 --- a/packages/connectors/connector-logto-email/src/constant.ts +++ b/packages/connectors/connector-logto-email/src/constant.ts @@ -1,5 +1,3 @@ -import { getEnv } from '@silverhand/essentials'; - import type { ConnectorMetadata } from '@logto/connector-kit'; import { ConnectorConfigFormItemType } from '@logto/connector-kit'; @@ -102,11 +100,9 @@ export const defaultMetadata: ConnectorMetadata = { export const scope = ['send:email']; -export const defaultTimeout = 5000; +export const defaultTimeout = 10_000; export const oldEmailEndpoint = '/services/send-email'; export const newEmailEndpoint = '/services/mails'; -export const emailEndpoint = - getEnv('NODE_ENV') === 'production' ? oldEmailEndpoint : newEmailEndpoint; export const usageEndpoint = '/services/mails/usage'; diff --git a/packages/connectors/connector-logto-email/src/index.test.ts b/packages/connectors/connector-logto-email/src/index.test.ts index d25fc86ed..f8165a98b 100644 --- a/packages/connectors/connector-logto-email/src/index.test.ts +++ b/packages/connectors/connector-logto-email/src/index.test.ts @@ -2,7 +2,7 @@ import nock from 'nock'; import { VerificationCodeType } from '@logto/connector-kit'; -import { emailEndpoint } from './constant.js'; +import { newEmailEndpoint } from './constant.js'; import { mockedAccessTokenResponse, mockedConfig } from './mock.js'; const { jest } = import.meta; @@ -17,14 +17,18 @@ describe('sendMessage()', () => { }); it('should send message successfully', async () => { - nock(mockedConfig.endpoint).post(emailEndpoint).reply(200); + nock(mockedConfig.endpoint).post(newEmailEndpoint).reply(200); const connector = await createConnector({ getConfig }); await expect( - connector.sendMessage({ - to: 'wangsijie94@gmail.com', - type: VerificationCodeType.SignIn, - payload: { code: '1234' }, - }) + connector.sendMessage( + { + to: 'wangsijie94@gmail.com', + type: VerificationCodeType.SignIn, + payload: { code: '1234' }, + }, + undefined, + false // Set to `false` since this is not production env. + ) ).resolves.not.toThrow(); }); }); diff --git a/packages/connectors/connector-logto-email/src/index.ts b/packages/connectors/connector-logto-email/src/index.ts index 25c3bc9e8..545a5c6ab 100644 --- a/packages/connectors/connector-logto-email/src/index.ts +++ b/packages/connectors/connector-logto-email/src/index.ts @@ -15,7 +15,13 @@ import { ConnectorErrorCodes, } from '@logto/connector-kit'; -import { defaultMetadata, defaultTimeout, emailEndpoint, usageEndpoint } from './constant.js'; +import { + defaultMetadata, + defaultTimeout, + oldEmailEndpoint, + newEmailEndpoint, + usageEndpoint, +} from './constant.js'; import { grantAccessToken } from './grant-access-token.js'; import type { LogtoEmailConfig } from './types.js'; import { logtoEmailConfigGuard } from './types.js'; @@ -24,9 +30,10 @@ export type { EmailServiceBasicConfig } from './types.js'; const sendMessage = (getConfig: GetConnectorConfig): SendMessageFunction => - async (data, inputConfig) => { + async (data, inputConfig, isDevelopment) => { const config = inputConfig ?? (await getConfig(defaultMetadata.id)); validateConfig(config, logtoEmailConfigGuard); + const emailEndpoint = isDevelopment ? oldEmailEndpoint : newEmailEndpoint; const { endpoint, diff --git a/packages/core/src/libraries/connector.ts b/packages/core/src/libraries/connector.ts index 7b2c0f1ed..4de01b8e6 100644 --- a/packages/core/src/libraries/connector.ts +++ b/packages/core/src/libraries/connector.ts @@ -15,7 +15,8 @@ export type ConnectorLibrary = ReturnType; export const createConnectorLibrary = ( queries: Queries, - cloudConnection: CloudConnectionLibrary + cloudConnection: CloudConnectionLibrary, + isProduction: boolean ) => { const { findAllConnectors, findAllConnectorsWellKnown } = queries.connectors; const { getCloudConnectionData } = cloudConnection; @@ -99,6 +100,7 @@ export const createConnectorLibrary = ( validateConfig(config, rawConnector.configGuard); }, dbEntry: databaseConnector, + isDevelopment: isProduction && ServiceConnector.Email === connectorFactory.metadata.id, }; } catch {} }) diff --git a/packages/core/src/libraries/passcode.ts b/packages/core/src/libraries/passcode.ts index b1534b1e6..7515105e4 100644 --- a/packages/core/src/libraries/passcode.ts +++ b/packages/core/src/libraries/passcode.ts @@ -83,7 +83,7 @@ export const createPasscodeLibrary = (queries: Queries, connectorLibrary: Connec }) ); - const { dbEntry, metadata, sendMessage } = connector; + const { dbEntry, metadata, sendMessage, isDevelopment } = connector; const messageTypeResult = verificationCodeTypeGuard.safeParse(passcode.type); @@ -91,13 +91,17 @@ export const createPasscodeLibrary = (queries: Queries, connectorLibrary: Connec throw new ConnectorError(ConnectorErrorCodes.InvalidConfig); } - const response = await sendMessage({ - to: emailOrPhone, - type: messageTypeResult.data, - payload: { - code: passcode.code, + const response = await sendMessage( + { + to: emailOrPhone, + type: messageTypeResult.data, + payload: { + code: passcode.code, + }, }, - }); + undefined, + isDevelopment + ); return { dbEntry, metadata, response }; }; diff --git a/packages/core/src/routes/connector/config-testing.ts b/packages/core/src/routes/connector/config-testing.ts index 6868aa237..dc99b36c6 100644 --- a/packages/core/src/routes/connector/config-testing.ts +++ b/packages/core/src/routes/connector/config-testing.ts @@ -11,6 +11,7 @@ import { phoneRegEx, emailRegEx } from '@logto/core-kit'; import { jsonObjectGuard, ConnectorType } from '@logto/schemas'; import { string, object } from 'zod'; +import { EnvSet } from '#src/env-set/index.js'; import RequestError from '#src/errors/RequestError/index.js'; import koaGuard from '#src/middleware/koa-guard.js'; import assertThat from '#src/utils/assert-that.js'; @@ -84,7 +85,8 @@ export default function connectorConfigTestingRoutes( code: '000000', }, }, - config + config, + ServiceConnector.Email === connectorFactory.metadata.id && EnvSet.values.isProduction ); ctx.status = 204; diff --git a/packages/core/src/tenants/Tenant.ts b/packages/core/src/tenants/Tenant.ts index 1b5609308..0a7da5831 100644 --- a/packages/core/src/tenants/Tenant.ts +++ b/packages/core/src/tenants/Tenant.ts @@ -56,7 +56,11 @@ export default class Tenant implements TenantContext { public readonly queries = new Queries(envSet.pool, wellKnownCache), public readonly logtoConfigs = createLogtoConfigLibrary(queries), public readonly cloudConnection = createCloudConnectionLibrary(logtoConfigs), - public readonly connectors = createConnectorLibrary(queries, cloudConnection), + public readonly connectors = createConnectorLibrary( + queries, + cloudConnection, + EnvSet.values.isProduction + ), public readonly libraries = new Libraries(id, queries, connectors) ) { const isAdminTenant = id === adminTenantId; diff --git a/packages/core/src/test-utils/tenant.ts b/packages/core/src/test-utils/tenant.ts index 002f547cd..7092d2d47 100644 --- a/packages/core/src/test-utils/tenant.ts +++ b/packages/core/src/test-utils/tenant.ts @@ -76,7 +76,8 @@ export class MockTenant implements TenantContext { this.logtoConfigs = createLogtoConfigLibrary(this.queries); this.cloudConnection = createCloudConnectionLibrary(this.logtoConfigs); this.connectors = { - ...createConnectorLibrary(this.queries, this.cloudConnection), + // Manually set the third argument `isDevelopment` to `false` since this is not a production environment. + ...createConnectorLibrary(this.queries, this.cloudConnection, false), ...connectorsOverride, }; this.libraries = new Libraries(this.id, this.queries, this.connectors); diff --git a/packages/core/src/utils/connectors/types.ts b/packages/core/src/utils/connectors/types.ts index 4d479dc54..ef1929173 100644 --- a/packages/core/src/utils/connectors/types.ts +++ b/packages/core/src/utils/connectors/types.ts @@ -9,7 +9,7 @@ export { ConnectorType } from '@logto/schemas'; */ export type LogtoConnector = T & { validateConfig: (config: unknown) => void; -} & { dbEntry: Connector }; +} & { dbEntry: Connector; isDevelopment: boolean }; export const connectorWellKnownGuard = Connectors.guard.pick({ id: true, diff --git a/packages/toolkit/connector-kit/src/types.ts b/packages/toolkit/connector-kit/src/types.ts index 03f726d91..65dd312c6 100644 --- a/packages/toolkit/connector-kit/src/types.ts +++ b/packages/toolkit/connector-kit/src/types.ts @@ -240,7 +240,11 @@ export const sendMessagePayloadGuard = z.object({ export type SendMessagePayload = z.infer; -export type SendMessageFunction = (data: SendMessagePayload, config?: unknown) => Promise; +export type SendMessageFunction = ( + data: SendMessagePayload, + config?: unknown, + isDevelopment?: boolean +) => Promise; export type GetUsageFunction = (startFrom?: Date) => Promise;