0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

refactor(toolkit,core,connector): add connector switch for WIP features

This commit is contained in:
Darcy Ye 2023-07-08 14:19:04 +08:00
parent 3efd6485fc
commit 26466e6542
No known key found for this signature in database
GPG key ID: B46F4C07EDEFC610
10 changed files with 51 additions and 27 deletions

View file

@ -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';

View file

@ -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({
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();
});
});

View file

@ -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<LogtoEmailConfig>(config, logtoEmailConfigGuard);
const emailEndpoint = isDevelopment ? oldEmailEndpoint : newEmailEndpoint;
const {
endpoint,

View file

@ -15,7 +15,8 @@ export type ConnectorLibrary = ReturnType<typeof createConnectorLibrary>;
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 {}
})

View file

@ -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({
const response = await sendMessage(
{
to: emailOrPhone,
type: messageTypeResult.data,
payload: {
code: passcode.code,
},
});
},
undefined,
isDevelopment
);
return { dbEntry, metadata, response };
};

View file

@ -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<T extends AuthedRouter>(
code: '000000',
},
},
config
config,
ServiceConnector.Email === connectorFactory.metadata.id && EnvSet.values.isProduction
);
ctx.status = 204;

View file

@ -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;

View file

@ -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);

View file

@ -9,7 +9,7 @@ export { ConnectorType } from '@logto/schemas';
*/
export type LogtoConnector<T extends AllConnector = AllConnector> = T & {
validateConfig: (config: unknown) => void;
} & { dbEntry: Connector };
} & { dbEntry: Connector; isDevelopment: boolean };
export const connectorWellKnownGuard = Connectors.guard.pick({
id: true,

View file

@ -240,7 +240,11 @@ export const sendMessagePayloadGuard = z.object({
export type SendMessagePayload = z.infer<typeof sendMessagePayloadGuard>;
export type SendMessageFunction = (data: SendMessagePayload, config?: unknown) => Promise<unknown>;
export type SendMessageFunction = (
data: SendMessagePayload,
config?: unknown,
isDevelopment?: boolean
) => Promise<unknown>;
export type GetUsageFunction = (startFrom?: Date) => Promise<number>;