mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
refactor(connector): add @logto/connector-schemas
This commit is contained in:
parent
6c423a8207
commit
c16f49cb2f
8 changed files with 258 additions and 0 deletions
37
packages/connector-schemas/package.json
Normal file
37
packages/connector-schemas/package.json
Normal file
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"name": "@logto/connector-schemas",
|
||||
"version": "1.0.0-beta.4",
|
||||
"main": "lib/index.js",
|
||||
"author": "Silverhand Inc. <contact@silverhand.io>",
|
||||
"license": "MPL-2.0",
|
||||
"private": true,
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"scripts": {
|
||||
"precommit": "lint-staged",
|
||||
"build": "rm -rf lib/ && tsc --p tsconfig.build.json",
|
||||
"lint": "eslint --ext .ts src",
|
||||
"lint:report": "pnpm lint --format json --output-file report.json",
|
||||
"prepack": "pnpm build"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/phrases": "^1.0.0-beta.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@silverhand/eslint-config": "1.0.0-rc.2",
|
||||
"@silverhand/essentials": "^1.1.6",
|
||||
"@silverhand/ts-config": "1.0.0-rc.2",
|
||||
"eslint": "^8.21.0",
|
||||
"lint-staged": "^13.0.0",
|
||||
"prettier": "^2.7.1",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "@silverhand"
|
||||
},
|
||||
"prettier": "@silverhand/eslint-config/.prettierrc"
|
||||
}
|
124
packages/connector-schemas/src/class.ts
Normal file
124
packages/connector-schemas/src/class.ts
Normal file
|
@ -0,0 +1,124 @@
|
|||
import { ConnectorMetadata } from './types';
|
||||
|
||||
export type EmailMessageTypes = {
|
||||
SignIn: {
|
||||
code: string;
|
||||
};
|
||||
Register: {
|
||||
code: string;
|
||||
};
|
||||
ForgotPassword: {
|
||||
code: string;
|
||||
};
|
||||
Test: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type SmsMessageTypes = EmailMessageTypes;
|
||||
|
||||
export type EmailSendMessageFunction<T = unknown> = (
|
||||
address: string,
|
||||
type: keyof EmailMessageTypes,
|
||||
payload: EmailMessageTypes[typeof type]
|
||||
) => Promise<T>;
|
||||
|
||||
export type EmailSendTestMessageFunction<T = unknown> = (
|
||||
config: Record<string, unknown>,
|
||||
address: string,
|
||||
type: keyof EmailMessageTypes,
|
||||
payload: EmailMessageTypes[typeof type]
|
||||
) => Promise<T>;
|
||||
|
||||
export type EmailSendMessageByFunction<T> = (
|
||||
config: T,
|
||||
address: string,
|
||||
type: keyof EmailMessageTypes,
|
||||
payload: EmailMessageTypes[typeof type]
|
||||
) => Promise<unknown>;
|
||||
|
||||
export type SmsSendMessageFunction<T = unknown> = (
|
||||
phone: string,
|
||||
type: keyof SmsMessageTypes,
|
||||
payload: SmsMessageTypes[typeof type]
|
||||
) => Promise<T>;
|
||||
|
||||
export type SmsSendTestMessageFunction<T = unknown> = (
|
||||
config: Record<string, unknown>,
|
||||
phone: string,
|
||||
type: keyof SmsMessageTypes,
|
||||
payload: SmsMessageTypes[typeof type]
|
||||
) => Promise<T>;
|
||||
|
||||
export type SmsSendMessageByFunction<T> = (
|
||||
config: T,
|
||||
phone: string,
|
||||
type: keyof SmsMessageTypes,
|
||||
payload: SmsMessageTypes[typeof type]
|
||||
) => Promise<unknown>;
|
||||
|
||||
export type ValidateConfig<T> = (config: unknown) => asserts config is T;
|
||||
|
||||
export type GetAuthorizationUri = (payload: {
|
||||
state: string;
|
||||
redirectUri: string;
|
||||
}) => Promise<string>;
|
||||
|
||||
export type GetUserInfo = (
|
||||
data: unknown
|
||||
) => Promise<{ id: string } & Record<string, string | undefined>>;
|
||||
|
||||
export type GetConnectorConfig = (id: string) => Promise<unknown>;
|
||||
|
||||
export type AuthResponseParser<T = Record<string, unknown>> = (response: unknown) => Promise<T>;
|
||||
|
||||
abstract class BaseConnector<T> {
|
||||
public getConfig: GetConnectorConfig;
|
||||
public metadata!: ConnectorMetadata;
|
||||
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
this.getConfig = getConnectorConfig;
|
||||
}
|
||||
|
||||
public abstract validateConfig(config: unknown): asserts config is T;
|
||||
}
|
||||
|
||||
export abstract class SmsConnector<T> extends BaseConnector<T> {
|
||||
protected abstract readonly sendMessageBy: EmailSendMessageByFunction<T>;
|
||||
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
||||
export abstract class EmailConnector<T> extends BaseConnector<T> {
|
||||
protected abstract readonly sendMessageBy: SmsSendMessageByFunction<T>;
|
||||
|
||||
public sendMessage: SmsSendMessageFunction = async (address, type, data) => {
|
||||
const config = await this.getConfig(this.metadata.id);
|
||||
this.validateConfig(config);
|
||||
|
||||
return this.sendMessageBy(config, address, type, data);
|
||||
};
|
||||
|
||||
public sendTestMessage?: SmsSendTestMessageFunction = async (config, address, type, data) => {
|
||||
this.validateConfig(config);
|
||||
|
||||
return this.sendMessageBy(config, address, type, data);
|
||||
};
|
||||
}
|
||||
|
||||
export abstract class SocialConnector<T> extends BaseConnector<T> {
|
||||
public abstract getAuthorizationUri: GetAuthorizationUri;
|
||||
|
||||
public abstract getUserInfo: GetUserInfo;
|
||||
|
||||
protected authResponseParser?: AuthResponseParser;
|
||||
}
|
13
packages/connector-schemas/src/error.ts
Normal file
13
packages/connector-schemas/src/error.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { ConnectorErrorCodes } from './types';
|
||||
|
||||
export class ConnectorError extends Error {
|
||||
public code: ConnectorErrorCodes;
|
||||
public data: unknown;
|
||||
|
||||
constructor(code: ConnectorErrorCodes, data?: unknown) {
|
||||
const message = typeof data === 'string' ? data : 'Connector error occurred.';
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.data = typeof data === 'string' ? { message: data } : data;
|
||||
}
|
||||
}
|
3
packages/connector-schemas/src/index.ts
Normal file
3
packages/connector-schemas/src/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export * from './types';
|
||||
export * from './error';
|
||||
export * from './class';
|
44
packages/connector-schemas/src/types.ts
Normal file
44
packages/connector-schemas/src/types.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
import type { Language } from '@logto/phrases';
|
||||
import { Nullable } from '@silverhand/essentials';
|
||||
|
||||
export enum ConnectorType {
|
||||
Email = 'Email',
|
||||
SMS = 'SMS',
|
||||
Social = 'Social',
|
||||
}
|
||||
|
||||
export enum ConnectorPlatform {
|
||||
Native = 'Native',
|
||||
Universal = 'Universal',
|
||||
Web = 'Web',
|
||||
}
|
||||
|
||||
export enum ConnectorErrorCodes {
|
||||
General,
|
||||
InsufficientRequestParameters,
|
||||
InvalidConfig,
|
||||
InvalidResponse,
|
||||
TemplateNotFound,
|
||||
NotImplemented,
|
||||
SocialAuthCodeInvalid,
|
||||
SocialAccessTokenInvalid,
|
||||
SocialIdTokenInvalid,
|
||||
AuthorizationFailed,
|
||||
}
|
||||
|
||||
type i18nPhrases = { [Language.English]: string } & {
|
||||
[key in Exclude<Language, Language.English>]?: string;
|
||||
};
|
||||
|
||||
export type ConnectorMetadata = {
|
||||
id: string;
|
||||
target: string;
|
||||
type: ConnectorType;
|
||||
platform: Nullable<ConnectorPlatform>;
|
||||
name: i18nPhrases;
|
||||
logo: string;
|
||||
logoDark: Nullable<string>;
|
||||
description: i18nPhrases;
|
||||
readme: string;
|
||||
configTemplate: string;
|
||||
};
|
5
packages/connector-schemas/tsconfig.build.json
Normal file
5
packages/connector-schemas/tsconfig.build.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"extends": "./tsconfig",
|
||||
"include": ["src"],
|
||||
"exclude": ["src/**/*.test.ts"]
|
||||
}
|
11
packages/connector-schemas/tsconfig.json
Normal file
11
packages/connector-schemas/tsconfig.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"extends": "@silverhand/ts-config/tsconfig.base",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
|
@ -534,6 +534,27 @@ importers:
|
|||
tsc-watch: 5.0.3_typescript@4.7.4
|
||||
typescript: 4.7.4
|
||||
|
||||
packages/connector-schemas:
|
||||
specifiers:
|
||||
'@logto/phrases': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
'@silverhand/essentials': ^1.1.6
|
||||
'@silverhand/ts-config': 1.0.0-rc.2
|
||||
eslint: ^8.21.0
|
||||
lint-staged: ^13.0.0
|
||||
prettier: ^2.7.1
|
||||
typescript: ^4.7.4
|
||||
dependencies:
|
||||
'@logto/phrases': link:../phrases
|
||||
devDependencies:
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2_swk2g7ygmfleszo5c33j4vooni
|
||||
'@silverhand/essentials': 1.1.7
|
||||
'@silverhand/ts-config': 1.0.0-rc.2_typescript@4.7.4
|
||||
eslint: 8.21.0
|
||||
lint-staged: 13.0.0
|
||||
prettier: 2.7.1
|
||||
typescript: 4.7.4
|
||||
|
||||
packages/connector-sendgrid-mail:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
|
|
Loading…
Reference in a new issue