mirror of
https://github.com/logto-io/logto.git
synced 2025-03-31 22:51:25 -05:00
refactor(connector): update per discussion
This commit is contained in:
parent
ff89c0b3a5
commit
d9560ae44e
99 changed files with 604 additions and 724 deletions
|
@ -24,7 +24,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.0",
|
||||
"@silverhand/jest-config": "1.0.0-rc.3",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorType, ConnectorMetadata, ConnectorPlatform } from '@logto/connector-types';
|
||||
import { ConnectorType, ConnectorMetadata, ConnectorPlatform } from '@logto/connector-schemas';
|
||||
|
||||
export const authorizationEndpoint = 'alipay://'; // This is used to arouse the native Alipay App
|
||||
export const alipayEndpoint = 'https://openapi.alipay.com/gateway.do';
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
ConnectorErrorCodes,
|
||||
GetConnectorConfig,
|
||||
ValidateConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import nock from 'nock';
|
||||
|
||||
import AlipayNativeConnector from '.';
|
||||
|
|
|
@ -9,15 +9,15 @@
|
|||
* https://opendocs.alipay.com/open/204/105296/
|
||||
*/
|
||||
|
||||
import { SocialConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
SocialConnector,
|
||||
AuthResponseParser,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
GetAuthorizationUri,
|
||||
GetUserInfo,
|
||||
GetConnectorConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
import dayjs from 'dayjs';
|
||||
import got from 'got';
|
||||
|
@ -45,6 +45,7 @@ import {
|
|||
import { signingParameters } from './utils';
|
||||
|
||||
export type { AlipayNativeConfig } from './types';
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class AlipayNativeConnector extends SocialConnector<AlipayNativeConfig> {
|
||||
private readonly signingParameters = signingParameters;
|
||||
|
@ -52,8 +53,6 @@ export default class AlipayNativeConnector extends SocialConnector<AlipayNativeC
|
|||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is AlipayNativeConfig {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.0",
|
||||
"@silverhand/jest-config": "1.0.0-rc.3",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// FIXME: @Darcy
|
||||
/* eslint-disable unicorn/text-encoding-identifier-case */
|
||||
import { ConnectorType, ConnectorMetadata, ConnectorPlatform } from '@logto/connector-types';
|
||||
import { ConnectorType, ConnectorMetadata, ConnectorPlatform } from '@logto/connector-schemas';
|
||||
|
||||
export const authorizationEndpoint = 'https://openauth.alipay.com/oauth2/publicAppAuthorize.htm';
|
||||
export const alipayEndpoint = 'https://openapi.alipay.com/gateway.do';
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
ConnectorErrorCodes,
|
||||
GetConnectorConfig,
|
||||
ValidateConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import nock from 'nock';
|
||||
|
||||
import AlipayConnector from '.';
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
* https://opendocs.alipay.com/open/263/105808
|
||||
* https://opendocs.alipay.com/open/01emu5
|
||||
*/
|
||||
import { SocialConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
SocialConnector,
|
||||
AuthResponseParser,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
GetAuthorizationUri,
|
||||
GetUserInfo,
|
||||
GetConnectorConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
import dayjs from 'dayjs';
|
||||
import got from 'got';
|
||||
|
@ -42,6 +42,7 @@ import {
|
|||
import { signingParameters } from './utils';
|
||||
|
||||
export type { AlipayConfig } from './types';
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class AlipayConnector extends SocialConnector<AlipayConfig> {
|
||||
private readonly signingParameters = signingParameters;
|
||||
|
@ -49,8 +50,6 @@ export default class AlipayConnector extends SocialConnector<AlipayConfig> {
|
|||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is AlipayConfig {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.0",
|
||||
"@silverhand/jest-config": "1.0.0-rc.3",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorType, ConnectorMetadata } from '@logto/connector-types';
|
||||
import { ConnectorType, ConnectorMetadata } from '@logto/connector-schemas';
|
||||
|
||||
export const endpoint = 'https://dm.aliyuncs.com/';
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { GetConnectorConfig, ValidateConfig } from '@logto/connector-types';
|
||||
import { GetConnectorConfig, ValidateConfig } from '@logto/connector-schemas';
|
||||
|
||||
import AliyunDmConnector from '.';
|
||||
import { mockedConfig } from './mock';
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { EmailConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
EmailConnector,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
EmailSendMessageByFunction,
|
||||
GetConnectorConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
import { HTTPError } from 'got';
|
||||
|
||||
|
@ -17,12 +17,12 @@ import {
|
|||
sendMailErrorResponseGuard,
|
||||
} from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class AliyunDmConnector extends EmailConnector<AliyunDmConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is AliyunDmConfig {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.0",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorMetadata, ConnectorType } from '@logto/connector-types';
|
||||
import { ConnectorMetadata, ConnectorType } from '@logto/connector-schemas';
|
||||
|
||||
export const endpoint = 'https://dysmsapi.aliyuncs.com/';
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { GetConnectorConfig, ValidateConfig } from '@logto/connector-types';
|
||||
import { GetConnectorConfig, ValidateConfig } from '@logto/connector-schemas';
|
||||
|
||||
import AliyunSmsConnector from '.';
|
||||
import { mockedConnectorConfig, mockedValidConnectorConfig, phoneTest, codeTest } from './mock';
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { SmsConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
SmsConnector,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
SmsSendMessageByFunction,
|
||||
GetConnectorConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
import { HTTPError } from 'got';
|
||||
|
||||
|
@ -12,12 +12,12 @@ import { defaultMetadata } from './constant';
|
|||
import { sendSms } from './single-send-text';
|
||||
import { aliyunSmsConfigGuard, AliyunSmsConfig, sendSmsResponseGuard } from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class AliyunSmsConnector extends SmsConnector<AliyunSmsConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is AliyunSmsConfig {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.0",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-types';
|
||||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-schemas';
|
||||
|
||||
// https://appleid.apple.com/.well-known/openid-configuration
|
||||
export const issuer = 'https://appleid.apple.com';
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
ConnectorErrorCodes,
|
||||
GetConnectorConfig,
|
||||
ValidateConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { jwtVerify } from 'jose';
|
||||
|
||||
import AppleConnector from '.';
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
import { SocialConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
SocialConnector,
|
||||
AuthResponseParser,
|
||||
GetAuthorizationUri,
|
||||
GetUserInfo,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
GetConnectorConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { createRemoteJWKSet, jwtVerify } from 'jose';
|
||||
|
||||
import { scope, defaultMetadata, jwksUri, issuer, authorizationEndpoint } from './constant';
|
||||
import { appleConfigGuard, authResponseGuard, AppleConfig, AuthResponse } from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
// TO-DO: support nonce validation
|
||||
export default class AppleConnector extends SocialConnector<AppleConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is AppleConfig {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@azure/msal-node": "^1.12.0",
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.0",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-types';
|
||||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-schemas';
|
||||
|
||||
export const graphAPIEndpoint = 'https://graph.microsoft.com/v1.0/me';
|
||||
export const scopes = ['User.Read'];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { GetConnectorConfig } from '@logto/connector-types';
|
||||
import { GetConnectorConfig } from '@logto/connector-schemas';
|
||||
|
||||
import AzureADConnector from '.';
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ import {
|
|||
AuthorizationUrlRequest,
|
||||
CryptoProvider,
|
||||
} from '@azure/msal-node';
|
||||
import { SocialConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
SocialConnector,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
GetAuthorizationUri,
|
||||
|
@ -15,7 +15,7 @@ import {
|
|||
codeWithRedirectDataGuard,
|
||||
CodeWithRedirectData,
|
||||
GetConnectorConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert, conditional } from '@silverhand/essentials';
|
||||
import got, { HTTPError } from 'got';
|
||||
|
||||
|
@ -27,6 +27,8 @@ import {
|
|||
userInfoResponseGuard,
|
||||
} from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class AzureADConnector extends SocialConnector<AzureADConfig> {
|
||||
public clientApplication!: ConfidentialClientApplication;
|
||||
public authCodeUrlParams!: AuthorizationUrlRequest;
|
||||
|
@ -37,8 +39,6 @@ export default class AzureADConnector extends SocialConnector<AzureADConfig> {
|
|||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is AzureADConfig {
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
{
|
||||
"name": "@logto/connector-base-classes",
|
||||
"version": "1.0.0-beta.3",
|
||||
"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/connector-types": "^1.0.0-beta.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@silverhand/eslint-config": "1.0.0-rc.2",
|
||||
"@silverhand/essentials": "^1.1.6",
|
||||
"@silverhand/ts-config": "1.0.0-rc.2",
|
||||
"@types/node": "^16.3.1",
|
||||
"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"
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
import { existsSync, readFileSync } from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import {
|
||||
ConnectorMetadata,
|
||||
GetConnectorConfig,
|
||||
EmailSendMessageFunction,
|
||||
EmailSendTestMessageFunction,
|
||||
EmailSendMessageByFunction,
|
||||
SmsSendMessageFunction,
|
||||
SmsSendTestMessageFunction,
|
||||
SmsSendMessageByFunction,
|
||||
GetAuthorizationUri,
|
||||
GetUserInfo,
|
||||
AuthResponseParser,
|
||||
} from '@logto/connector-types';
|
||||
|
||||
export class BaseConnector<T> {
|
||||
public metadata!: ConnectorMetadata;
|
||||
public getConfig: GetConnectorConfig;
|
||||
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
this.getConfig = getConnectorConfig;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
public validateConfig(config: unknown): asserts config is T {}
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
protected metadataParser = (currentPath: string) => {
|
||||
if (
|
||||
!this.metadata.logo.startsWith('http') &&
|
||||
existsSync(path.join(currentPath, '..', this.metadata.logo))
|
||||
) {
|
||||
const data = readFileSync(path.join(currentPath, '..', this.metadata.logo));
|
||||
this.metadata.logo = `data:image/svg+xml;base64,${data.toString('base64')}`;
|
||||
}
|
||||
|
||||
if (
|
||||
this.metadata.logoDark &&
|
||||
!this.metadata.logoDark.startsWith('http') &&
|
||||
existsSync(path.join(currentPath, '..', this.metadata.logoDark))
|
||||
) {
|
||||
const data = readFileSync(path.join(currentPath, '..', this.metadata.logoDark));
|
||||
this.metadata.logoDark = `data:image/svg+xml;base64,${data.toString('base64')}`;
|
||||
}
|
||||
|
||||
if (this.metadata.readme && existsSync(path.join(currentPath, '..', this.metadata.readme))) {
|
||||
this.metadata.readme = readFileSync(
|
||||
path.join(currentPath, '..', this.metadata.readme),
|
||||
'utf8'
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
this.metadata.configTemplate &&
|
||||
existsSync(path.join(currentPath, '..', this.metadata.configTemplate))
|
||||
) {
|
||||
this.metadata.configTemplate = readFileSync(
|
||||
path.join(currentPath, '..', this.metadata.configTemplate),
|
||||
'utf8'
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export class SmsConnector<T> extends BaseConnector<T> {
|
||||
protected 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 class EmailConnector<T> extends BaseConnector<T> {
|
||||
protected 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 class SocialConnector<T> extends BaseConnector<T> {
|
||||
public getAuthorizationUri!: GetAuthorizationUri;
|
||||
|
||||
public getUserInfo!: GetUserInfo;
|
||||
|
||||
protected authResponseParser!: AuthResponseParser;
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.0",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-types';
|
||||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-schemas';
|
||||
|
||||
/**
|
||||
* Note: If you do not include a version number we will default to the oldest available version, so it's recommended to include the version number in your requests.
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
ConnectorErrorCodes,
|
||||
GetConnectorConfig,
|
||||
ValidateConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import nock from 'nock';
|
||||
|
||||
import FacebookConnector from '.';
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow
|
||||
*/
|
||||
|
||||
import { SocialConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
SocialConnector,
|
||||
AuthResponseParser,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
|
@ -13,7 +13,7 @@ import {
|
|||
GetConnectorConfig,
|
||||
codeWithRedirectDataGuard,
|
||||
CodeWithRedirectData,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
import got, { HTTPError } from 'got';
|
||||
|
||||
|
@ -33,12 +33,12 @@ import {
|
|||
userInfoResponseGuard,
|
||||
} from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class FacebookConnector extends SocialConnector<FacebookConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is FacebookConfig {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.0",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-types';
|
||||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-schemas';
|
||||
|
||||
export const authorizationEndpoint = 'https://github.com/login/oauth/authorize';
|
||||
export const scope = 'read:user';
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
ConnectorErrorCodes,
|
||||
GetConnectorConfig,
|
||||
ValidateConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import nock from 'nock';
|
||||
import * as qs from 'query-string';
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { SocialConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
SocialConnector,
|
||||
AuthResponseParser,
|
||||
GetAuthorizationUri,
|
||||
GetUserInfo,
|
||||
|
@ -8,7 +8,7 @@ import {
|
|||
GetConnectorConfig,
|
||||
codeDataGuard,
|
||||
CodeData,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert, conditional } from '@silverhand/essentials';
|
||||
import got, { HTTPError } from 'got';
|
||||
import * as qs from 'query-string';
|
||||
|
@ -29,12 +29,12 @@ import {
|
|||
userInfoResponseGuard,
|
||||
} from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class GithubConnector extends SocialConnector<GithubConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is GithubConfig {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.0",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-types';
|
||||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-schemas';
|
||||
|
||||
export const authorizationEndpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
|
||||
export const accessTokenEndpoint = 'https://oauth2.googleapis.com/token';
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
ConnectorErrorCodes,
|
||||
GetConnectorConfig,
|
||||
ValidateConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import nock from 'nock';
|
||||
|
||||
import GoogleConnector from '.';
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* The Implementation of OpenID Connect of Google Identity Platform.
|
||||
* https://developers.google.com/identity/protocols/oauth2/openid-connect
|
||||
*/
|
||||
import { SocialConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
SocialConnector,
|
||||
AuthResponseParser,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
|
@ -12,7 +12,7 @@ import {
|
|||
GetConnectorConfig,
|
||||
codeWithRedirectDataGuard,
|
||||
CodeWithRedirectData,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { conditional, assert } from '@silverhand/essentials';
|
||||
import got, { HTTPError } from 'got';
|
||||
|
||||
|
@ -31,12 +31,12 @@ import {
|
|||
userInfoResponseGuard,
|
||||
} from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class GoogleConnector extends SocialConnector<GoogleConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is GoogleConfig {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.6",
|
||||
"zod": "^3.14.3"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorType, ConnectorMetadata } from '@logto/connector-types';
|
||||
import { ConnectorType, ConnectorMetadata } from '@logto/connector-schemas';
|
||||
|
||||
export const defaultMetadata: ConnectorMetadata = {
|
||||
id: 'mock-email-service',
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
import { EmailConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
EmailConnector,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
EmailSendMessageByFunction,
|
||||
GetConnectorConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
|
||||
import { defaultMetadata } from './constant';
|
||||
import { mockMailConfigGuard, MockMailConfig } from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class MockMailConnector extends EmailConnector<MockMailConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is MockMailConfig {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.6",
|
||||
"zod": "^3.14.3"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorType, ConnectorMetadata } from '@logto/connector-types';
|
||||
import { ConnectorType, ConnectorMetadata } from '@logto/connector-schemas';
|
||||
|
||||
export const defaultMetadata: ConnectorMetadata = {
|
||||
id: 'mock-short-message-service',
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
import { SmsConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
SmsConnector,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
SmsSendMessageByFunction,
|
||||
GetConnectorConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
|
||||
import { defaultMetadata } from './constant';
|
||||
import { mockSmsConfigGuard, MockSmsConfig } from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class MockSmsConnector extends SmsConnector<MockSmsConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is MockSmsConfig {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.0",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-types';
|
||||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-schemas';
|
||||
|
||||
export const defaultMetadata: ConnectorMetadata = {
|
||||
id: 'mock-social-connector',
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
import { randomUUID } from 'crypto';
|
||||
|
||||
import { SocialConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
SocialConnector,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
GetAuthorizationUri,
|
||||
GetUserInfo,
|
||||
GetConnectorConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { defaultMetadata } from './constant';
|
||||
import { mockSocialConfigGuard, MockSocialConfig } from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class MockSocialConnector extends SocialConnector<MockSocialConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is MockSocialConfig {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@logto/connector-types",
|
||||
"name": "@logto/connector-schemas",
|
||||
"version": "1.0.0-beta.4",
|
||||
"main": "lib/index.js",
|
||||
"author": "Silverhand Inc. <contact@silverhand.io>",
|
||||
|
@ -29,6 +29,7 @@
|
|||
"@silverhand/essentials": "^1.1.6",
|
||||
"@silverhand/ts-config": "1.0.0-rc.2",
|
||||
"@types/jest": "^28.1.6",
|
||||
"@types/node": "^16.3.1",
|
||||
"eslint": "^8.21.0",
|
||||
"jest": "^28.1.3",
|
||||
"lint-staged": "^13.0.0",
|
|
@ -1,63 +1,4 @@
|
|||
// FIXME: @Darcy
|
||||
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
||||
|
||||
import type { Language } from '@logto/phrases';
|
||||
import { Nullable } from '@silverhand/essentials';
|
||||
import { z } from 'zod';
|
||||
|
||||
export enum ConnectorType {
|
||||
Email = 'Email',
|
||||
SMS = 'SMS',
|
||||
Social = 'Social',
|
||||
}
|
||||
|
||||
export enum ConnectorPlatform {
|
||||
Native = 'Native',
|
||||
Universal = 'Universal',
|
||||
Web = 'Web',
|
||||
}
|
||||
|
||||
type i18nPhrases = { [Language.English]: string } & {
|
||||
[key in Exclude<Language, Language.English>]?: string;
|
||||
};
|
||||
|
||||
export interface ConnectorMetadata {
|
||||
id: string;
|
||||
target: string;
|
||||
type: ConnectorType;
|
||||
platform: Nullable<ConnectorPlatform>;
|
||||
name: i18nPhrases;
|
||||
logo: string;
|
||||
logoDark: Nullable<string>;
|
||||
description: i18nPhrases;
|
||||
readme: string;
|
||||
configTemplate: string;
|
||||
}
|
||||
|
||||
export enum ConnectorErrorCodes {
|
||||
General,
|
||||
InsufficientRequestParameters,
|
||||
InvalidConfig,
|
||||
InvalidResponse,
|
||||
TemplateNotFound,
|
||||
NotImplemented,
|
||||
SocialAuthCodeInvalid,
|
||||
SocialAccessTokenInvalid,
|
||||
SocialIdTokenInvalid,
|
||||
AuthorizationFailed,
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
import { ConnectorMetadata } from './types';
|
||||
|
||||
export type EmailMessageTypes = {
|
||||
SignIn: {
|
||||
|
@ -129,16 +70,55 @@ export type GetConnectorConfig = (id: string) => Promise<unknown>;
|
|||
|
||||
export type AuthResponseParser<T = Record<string, unknown>> = (response: unknown) => Promise<T>;
|
||||
|
||||
export const codeDataGuard = z.object({
|
||||
code: z.string(),
|
||||
});
|
||||
abstract class BaseConnector<T> {
|
||||
public getConfig: GetConnectorConfig;
|
||||
public metadata!: ConnectorMetadata;
|
||||
|
||||
export type CodeData = z.infer<typeof codeDataGuard>;
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
this.getConfig = getConnectorConfig;
|
||||
}
|
||||
|
||||
export const codeWithRedirectDataGuard = z.object({
|
||||
code: z.string(),
|
||||
redirectUri: z.string(),
|
||||
});
|
||||
public abstract validateConfig(config: unknown): asserts config is T;
|
||||
}
|
||||
|
||||
export type CodeWithRedirectData = z.infer<typeof codeWithRedirectDataGuard>;
|
||||
/* eslint-enable @typescript-eslint/consistent-type-definitions */
|
||||
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';
|
62
packages/connector-schemas/src/types.ts
Normal file
62
packages/connector-schemas/src/types.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
// FIXME: @Darcy
|
||||
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
||||
|
||||
import type { Language } from '@logto/phrases';
|
||||
import { Nullable } from '@silverhand/essentials';
|
||||
import { z } from 'zod';
|
||||
|
||||
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 interface ConnectorMetadata {
|
||||
id: string;
|
||||
target: string;
|
||||
type: ConnectorType;
|
||||
platform: Nullable<ConnectorPlatform>;
|
||||
name: i18nPhrases;
|
||||
logo: string;
|
||||
logoDark: Nullable<string>;
|
||||
description: i18nPhrases;
|
||||
readme: string;
|
||||
configTemplate: string;
|
||||
}
|
||||
|
||||
export const codeDataGuard = z.object({
|
||||
code: z.string(),
|
||||
});
|
||||
|
||||
export type CodeData = z.infer<typeof codeDataGuard>;
|
||||
|
||||
export const codeWithRedirectDataGuard = z.object({
|
||||
code: z.string(),
|
||||
redirectUri: z.string(),
|
||||
});
|
||||
|
||||
export type CodeWithRedirectData = z.infer<typeof codeWithRedirectDataGuard>;
|
||||
/* eslint-enable @typescript-eslint/consistent-type-definitions */
|
|
@ -24,7 +24,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.6",
|
||||
"@silverhand/jest-config": "1.0.0-rc.3",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorType, ConnectorMetadata } from '@logto/connector-types';
|
||||
import { ConnectorType, ConnectorMetadata } from '@logto/connector-schemas';
|
||||
|
||||
export const endpoint = 'https://api.sendgrid.com/v3/mail/send';
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { GetConnectorConfig, ValidateConfig } from '@logto/connector-types';
|
||||
import { GetConnectorConfig, ValidateConfig } from '@logto/connector-schemas';
|
||||
|
||||
import SendGridMailConnector from '.';
|
||||
import { mockedConfig } from './mock';
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { EmailConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
EmailConnector,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
EmailSendMessageByFunction,
|
||||
GetConnectorConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
import got, { HTTPError } from 'got';
|
||||
|
||||
|
@ -18,12 +18,12 @@ import {
|
|||
PublicParameters,
|
||||
} from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class SendGridMailConnector extends EmailConnector<SendGridMailConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is SendGridMailConfig {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.6",
|
||||
"@silverhand/jest-config": "1.0.0-rc.3",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorType, ConnectorMetadata } from '@logto/connector-types';
|
||||
import { ConnectorType, ConnectorMetadata } from '@logto/connector-schemas';
|
||||
|
||||
export const defaultMetadata: ConnectorMetadata = {
|
||||
id: 'simple-mail-transfer-protocol',
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { GetConnectorConfig, ValidateConfig } from '@logto/connector-types';
|
||||
import { GetConnectorConfig, ValidateConfig } from '@logto/connector-schemas';
|
||||
|
||||
import SmtpConnector from '.';
|
||||
import { SmtpConfig } from './types';
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { EmailConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
EmailConnector,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
EmailSendMessageByFunction,
|
||||
GetConnectorConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
import nodemailer from 'nodemailer';
|
||||
import SMTPTransport from 'nodemailer/lib/smtp-transport';
|
||||
|
@ -12,12 +12,12 @@ import SMTPTransport from 'nodemailer/lib/smtp-transport';
|
|||
import { defaultMetadata } from './constant';
|
||||
import { ContextType, smtpConfigGuard, SmtpConfig } from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class SmtpConnector extends EmailConnector<SmtpConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is SmtpConfig {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.6",
|
||||
"@silverhand/jest-config": "1.0.0-rc.3",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorType, ConnectorMetadata } from '@logto/connector-types';
|
||||
import { ConnectorType, ConnectorMetadata } from '@logto/connector-schemas';
|
||||
|
||||
export const endpoint = 'https://api.twilio.com/2010-04-01/Accounts/{{accountSID}}/Messages.json';
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { GetConnectorConfig, ValidateConfig } from '@logto/connector-types';
|
||||
import { GetConnectorConfig, ValidateConfig } from '@logto/connector-schemas';
|
||||
|
||||
import TwilioSmsConnector from '.';
|
||||
import { mockedConfig } from './mock';
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
import { SmsConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
SmsConnector,
|
||||
ConnectorError,
|
||||
ConnectorErrorCodes,
|
||||
SmsSendMessageByFunction,
|
||||
GetConnectorConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
import got, { HTTPError } from 'got';
|
||||
|
||||
import { defaultMetadata, endpoint } from './constant';
|
||||
import { twilioSmsConfigGuard, TwilioSmsConfig, PublicParameters } from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class TwilioSmsConnector extends SmsConnector<TwilioSmsConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is TwilioSmsConfig {
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig",
|
||||
"include": ["src"],
|
||||
"exclude": ["src/**/*.test.ts"]
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"extends": "@silverhand/ts-config/tsconfig.base",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.0",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-types';
|
||||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-schemas';
|
||||
|
||||
export const authorizationEndpoint = 'wechat://'; // This is used to arouse the native WeChat App
|
||||
export const accessTokenEndpoint = 'https://api.weixin.qq.com/sns/oauth2/access_token';
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
ConnectorErrorCodes,
|
||||
GetConnectorConfig,
|
||||
ValidateConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import nock from 'nock';
|
||||
|
||||
import WechatNativeConnector from '.';
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
|
||||
*/
|
||||
|
||||
import { SocialConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
SocialConnector,
|
||||
GetAuthorizationUri,
|
||||
GetUserInfo,
|
||||
ConnectorError,
|
||||
|
@ -13,7 +13,7 @@ import {
|
|||
AuthResponseParser,
|
||||
codeDataGuard,
|
||||
CodeData,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
import got, { HTTPError } from 'got';
|
||||
|
||||
|
@ -35,12 +35,12 @@ import {
|
|||
WechatNativeConfig,
|
||||
} from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class WechatNativeConnector extends SocialConnector<WechatNativeConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is WechatNativeConfig {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"prepack": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/schemas": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
"@silverhand/essentials": "^1.1.0",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-types';
|
||||
import { ConnectorMetadata, ConnectorType, ConnectorPlatform } from '@logto/connector-schemas';
|
||||
|
||||
export const authorizationEndpoint = 'https://open.weixin.qq.com/connect/qrconnect';
|
||||
export const accessTokenEndpoint = 'https://api.weixin.qq.com/sns/oauth2/access_token';
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
ConnectorErrorCodes,
|
||||
GetConnectorConfig,
|
||||
ValidateConfig,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import nock from 'nock';
|
||||
|
||||
import WechatConnector from '.';
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
|
||||
*/
|
||||
|
||||
import { SocialConnector } from '@logto/connector-base-classes';
|
||||
import {
|
||||
SocialConnector,
|
||||
AuthResponseParser,
|
||||
GetAuthorizationUri,
|
||||
GetUserInfo,
|
||||
|
@ -13,7 +13,7 @@ import {
|
|||
GetConnectorConfig,
|
||||
codeDataGuard,
|
||||
CodeData,
|
||||
} from '@logto/connector-types';
|
||||
} from '@logto/connector-schemas';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
import got, { HTTPError } from 'got';
|
||||
|
||||
|
@ -36,12 +36,12 @@ import {
|
|||
WechatConfig,
|
||||
} from './types';
|
||||
|
||||
export { defaultMetadata } from './constant';
|
||||
|
||||
export default class WechatConnector extends SocialConnector<WechatConfig> {
|
||||
constructor(getConnectorConfig: GetConnectorConfig) {
|
||||
super(getConnectorConfig);
|
||||
this.metadata = defaultMetadata;
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
this.metadataParser(__dirname);
|
||||
}
|
||||
|
||||
public validateConfig(config: unknown): asserts config is WechatConfig {
|
||||
|
|
|
@ -28,10 +28,10 @@
|
|||
"@logto/connector-facebook": "^1.0.0-beta.4",
|
||||
"@logto/connector-github": "^1.0.0-beta.4",
|
||||
"@logto/connector-google": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/connector-sendgrid-email": "^1.0.0-beta.4",
|
||||
"@logto/connector-smtp": "^1.0.0-beta.4",
|
||||
"@logto/connector-twilio-sms": "^1.0.0-beta.4",
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-wechat-native": "^1.0.0-beta.4",
|
||||
"@logto/connector-wechat-web": "^1.0.0-beta.4",
|
||||
"@logto/phrases": "^1.0.0-beta.4",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorPlatform } from '@logto/connector-types';
|
||||
import { ConnectorPlatform } from '@logto/connector-schemas';
|
||||
import { Connector, ConnectorMetadata, ConnectorType } from '@logto/schemas';
|
||||
|
||||
export const mockMetadata: ConnectorMetadata = {
|
||||
|
@ -148,35 +148,35 @@ export const mockConnectorList: Connector[] = [
|
|||
|
||||
export const mockConnectorInstanceList: Array<{
|
||||
connector: Connector;
|
||||
instance: { metadata: ConnectorMetadata };
|
||||
metadata: ConnectorMetadata;
|
||||
}> = [
|
||||
{
|
||||
connector: mockConnector0,
|
||||
instance: { metadata: { ...mockMetadata0, type: ConnectorType.Social } },
|
||||
metadata: { ...mockMetadata0, type: ConnectorType.Social },
|
||||
},
|
||||
{
|
||||
connector: mockConnector1,
|
||||
instance: { metadata: mockMetadata1 },
|
||||
metadata: mockMetadata1,
|
||||
},
|
||||
{
|
||||
connector: mockConnector2,
|
||||
instance: { metadata: mockMetadata2 },
|
||||
metadata: mockMetadata2,
|
||||
},
|
||||
{
|
||||
connector: mockConnector3,
|
||||
instance: { metadata: mockMetadata3 },
|
||||
metadata: mockMetadata3,
|
||||
},
|
||||
{
|
||||
connector: mockConnector4,
|
||||
instance: { metadata: { ...mockMetadata4, type: ConnectorType.Email, platform: null } },
|
||||
metadata: { ...mockMetadata4, type: ConnectorType.Email, platform: null },
|
||||
},
|
||||
{
|
||||
connector: mockConnector5,
|
||||
instance: { metadata: { ...mockMetadata5, type: ConnectorType.SMS, platform: null } },
|
||||
metadata: { ...mockMetadata5, type: ConnectorType.SMS, platform: null },
|
||||
},
|
||||
{
|
||||
connector: mockConnector6,
|
||||
instance: { metadata: { ...mockMetadata6, type: ConnectorType.Email, platform: null } },
|
||||
metadata: { ...mockMetadata6, type: ConnectorType.Email, platform: null },
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -185,14 +185,12 @@ export const mockAliyunDmConnectorInstance = {
|
|||
...mockConnector,
|
||||
id: 'aliyun-dm',
|
||||
},
|
||||
instance: {
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'aliyun-dm',
|
||||
target: 'aliyun-dm',
|
||||
type: ConnectorType.Email,
|
||||
platform: null,
|
||||
},
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'aliyun-dm',
|
||||
target: 'aliyun-dm',
|
||||
type: ConnectorType.Email,
|
||||
platform: null,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -201,14 +199,12 @@ export const mockAliyunSmsConnectorInstance = {
|
|||
...mockConnector,
|
||||
id: 'aliyun-sms',
|
||||
},
|
||||
instance: {
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'aliyun-sms',
|
||||
target: 'aliyun-sms',
|
||||
type: ConnectorType.SMS,
|
||||
platform: null,
|
||||
},
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'aliyun-sms',
|
||||
target: 'aliyun-sms',
|
||||
type: ConnectorType.SMS,
|
||||
platform: null,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -217,14 +213,12 @@ export const mockFacebookConnectorInstance = {
|
|||
...mockConnector,
|
||||
id: 'facebook',
|
||||
},
|
||||
instance: {
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'facebook',
|
||||
target: 'facebook',
|
||||
type: ConnectorType.Social,
|
||||
platform: ConnectorPlatform.Web,
|
||||
},
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'facebook',
|
||||
target: 'facebook',
|
||||
type: ConnectorType.Social,
|
||||
platform: ConnectorPlatform.Web,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -233,14 +227,12 @@ export const mockGithubConnectorInstance = {
|
|||
...mockConnector,
|
||||
id: 'github',
|
||||
},
|
||||
instance: {
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'github',
|
||||
target: 'github',
|
||||
type: ConnectorType.Social,
|
||||
platform: ConnectorPlatform.Web,
|
||||
},
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'github',
|
||||
target: 'github',
|
||||
type: ConnectorType.Social,
|
||||
platform: ConnectorPlatform.Web,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -249,14 +241,12 @@ export const mockWechatConnectorInstance = {
|
|||
...mockConnector,
|
||||
id: 'wechat-web',
|
||||
},
|
||||
instance: {
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'wechat-web',
|
||||
target: 'wechat',
|
||||
type: ConnectorType.Social,
|
||||
platform: ConnectorPlatform.Web,
|
||||
},
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'wechat-web',
|
||||
target: 'wechat',
|
||||
type: ConnectorType.Social,
|
||||
platform: ConnectorPlatform.Web,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -265,14 +255,12 @@ export const mockWechatNativeConnectorInstance = {
|
|||
...mockConnector,
|
||||
id: 'wechat-native',
|
||||
},
|
||||
instance: {
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'wechat-native',
|
||||
target: 'wechat',
|
||||
type: ConnectorType.Social,
|
||||
platform: ConnectorPlatform.Native,
|
||||
},
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'wechat-native',
|
||||
target: 'wechat',
|
||||
type: ConnectorType.Social,
|
||||
platform: ConnectorPlatform.Native,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -282,14 +270,12 @@ export const mockGoogleConnectorInstance = {
|
|||
id: 'google',
|
||||
enabled: false,
|
||||
},
|
||||
instance: {
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'google',
|
||||
target: 'google',
|
||||
type: ConnectorType.Social,
|
||||
platform: ConnectorPlatform.Web,
|
||||
},
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: 'google',
|
||||
target: 'google',
|
||||
type: ConnectorType.Social,
|
||||
platform: ConnectorPlatform.Web,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorPlatform } from '@logto/connector-types';
|
||||
import { ConnectorPlatform } from '@logto/connector-schemas';
|
||||
import { Connector } from '@logto/schemas';
|
||||
|
||||
import {
|
||||
|
|
|
@ -1,16 +1,37 @@
|
|||
import { existsSync, readFileSync } from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import { ConnectorType, GetConnectorConfig } from '@logto/connector-schemas';
|
||||
import { Connector } from '@logto/schemas';
|
||||
import resolvePackagePath from 'resolve-package-path';
|
||||
|
||||
import { ConnectorInstance, SocialConnectorInstance } from '@/connectors/types';
|
||||
import RequestError from '@/errors/RequestError';
|
||||
import { findAllConnectors, insertConnector } from '@/queries/connector';
|
||||
|
||||
import { defaultConnectorPackages } from './consts';
|
||||
import { ConnectorType, ConnectorInstance, Instance, SocialConnectorInstance } from './types';
|
||||
import { connectorPackages } from './consts';
|
||||
import { getConnectorConfig } from './utilities';
|
||||
|
||||
// eslint-disable-next-line @silverhand/fp/no-let
|
||||
let cachedConnectors: Instance[] | undefined;
|
||||
let cachedConnectorInstances: ConnectorInstance[] | undefined;
|
||||
|
||||
const loadConnectors = async () => {
|
||||
if (cachedConnectors) {
|
||||
return cachedConnectors;
|
||||
export const getConnectorInstances = async (): Promise<ConnectorInstance[]> => {
|
||||
const connectors = await findAllConnectors();
|
||||
const connectorMap = new Map(connectors.map((connector) => [connector.id, connector]));
|
||||
|
||||
if (cachedConnectorInstances) {
|
||||
return cachedConnectorInstances.map((connectorInstance) => {
|
||||
const { id } = connectorInstance.metadata;
|
||||
const connector = connectorMap.get(id);
|
||||
|
||||
if (!connector) {
|
||||
throw new RequestError({ code: 'entity.not_found', id, status: 404 });
|
||||
}
|
||||
// eslint-disable-next-line @silverhand/fp/no-mutation
|
||||
connectorInstance.connector = connector;
|
||||
|
||||
return connectorInstance;
|
||||
});
|
||||
}
|
||||
|
||||
const {
|
||||
|
@ -20,36 +41,95 @@ const loadConnectors = async () => {
|
|||
const connectorPackages = [...defaultConnectorPackages, ...additionalConnectorPackages];
|
||||
|
||||
// eslint-disable-next-line @silverhand/fp/no-mutation
|
||||
cachedConnectors = await Promise.all(
|
||||
cachedConnectorInstances = await Promise.all(
|
||||
connectorPackages.map(async (packageName) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const { default: Builder } = await import(packageName);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
|
||||
const instance: Instance = new Builder(getConnectorConfig);
|
||||
const { default: Builder, defaultMetadata: metadata } = await import(packageName);
|
||||
|
||||
class InstanceBuilder extends Builder {
|
||||
private _connector: Connector;
|
||||
|
||||
public get connector() {
|
||||
return this._connector;
|
||||
}
|
||||
|
||||
public set connector(input: Connector) {
|
||||
this._connector = input;
|
||||
}
|
||||
|
||||
constructor(getConnectorConfig: GetConnectorConfig, connectorFromDatabase: Connector) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
super(getConnectorConfig);
|
||||
this._connector = connectorFromDatabase;
|
||||
}
|
||||
}
|
||||
|
||||
const connector = connectorMap.get(metadata.id);
|
||||
|
||||
if (!connector) {
|
||||
throw new RequestError({ code: 'entity.not_found', id: metadata.id, status: 404 });
|
||||
}
|
||||
|
||||
// TODO: can address type of Builder when dynamic import, temporarily use `as` to unblock
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const instance = new InstanceBuilder(
|
||||
getConnectorConfig,
|
||||
connector
|
||||
) as unknown as ConnectorInstance;
|
||||
// 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'
|
||||
);
|
||||
}
|
||||
|
||||
return instance;
|
||||
})
|
||||
);
|
||||
|
||||
return cachedConnectors;
|
||||
};
|
||||
|
||||
export const getConnectorInstances = async (): Promise<ConnectorInstance[]> => {
|
||||
const connectors = await findAllConnectors();
|
||||
const connectorMap = new Map(connectors.map((connector) => [connector.id, connector]));
|
||||
|
||||
const allInstances = await loadConnectors();
|
||||
|
||||
return allInstances.map((instance) => {
|
||||
const { id } = instance.metadata;
|
||||
const connector = connectorMap.get(id);
|
||||
|
||||
if (!connector) {
|
||||
throw new RequestError({ code: 'entity.not_found', id, status: 404 });
|
||||
}
|
||||
|
||||
return { instance, connector };
|
||||
});
|
||||
return cachedConnectorInstances;
|
||||
};
|
||||
|
||||
export const getConnectorInstanceById = async (id: string): Promise<ConnectorInstance> => {
|
||||
|
@ -70,7 +150,7 @@ export const getConnectorInstanceById = async (id: string): Promise<ConnectorIns
|
|||
const isSocialConnectorInstance = (
|
||||
connector: ConnectorInstance
|
||||
): connector is SocialConnectorInstance => {
|
||||
return connector.instance.metadata.type === ConnectorType.Social;
|
||||
return connector.metadata.type === ConnectorType.Social;
|
||||
};
|
||||
|
||||
export const getSocialConnectorInstanceById = async (
|
||||
|
@ -92,8 +172,8 @@ export const getSocialConnectorInstanceById = async (
|
|||
export const initConnectors = async () => {
|
||||
const connectors = await findAllConnectors();
|
||||
const existingConnectors = new Map(connectors.map((connector) => [connector.id, connector]));
|
||||
const allConnectors = await loadConnectors();
|
||||
const newConnectors = allConnectors.filter(({ metadata: { id } }) => {
|
||||
const allConnectorInstances = await getConnectorInstances();
|
||||
const newConnectors = allConnectorInstances.filter(({ metadata: { id } }) => {
|
||||
const connector = existingConnectors.get(id);
|
||||
|
||||
if (!connector) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { SmsConnector, EmailConnector, SocialConnector } from '@logto/connector-base-classes';
|
||||
import { SmsConnector, EmailConnector, SocialConnector } from '@logto/connector-schemas';
|
||||
import { PasscodeType, Connector } from '@logto/schemas';
|
||||
import { z } from 'zod';
|
||||
|
||||
|
@ -17,28 +17,17 @@ export const socialUserInfoGuard = z.object({
|
|||
|
||||
export type SocialUserInfo = z.infer<typeof socialUserInfoGuard>;
|
||||
|
||||
export type Instance =
|
||||
export type SmsConnectorInstance = InstanceType<typeof SmsConnector> & { connector: Connector };
|
||||
|
||||
export type EmailConnectorInstance = InstanceType<typeof EmailConnector> & { connector: Connector };
|
||||
|
||||
export type SocialConnectorInstance = InstanceType<typeof SocialConnector> & {
|
||||
connector: Connector;
|
||||
};
|
||||
|
||||
type ArbitraryConnector =
|
||||
| InstanceType<typeof SmsConnector>
|
||||
| InstanceType<typeof EmailConnector>
|
||||
| InstanceType<typeof SocialConnector>;
|
||||
|
||||
export type SmsConnectorInstance = {
|
||||
instance: InstanceType<typeof SmsConnector>;
|
||||
connector: Connector;
|
||||
};
|
||||
|
||||
export type EmailConnectorInstance = {
|
||||
instance: InstanceType<typeof EmailConnector>;
|
||||
connector: Connector;
|
||||
};
|
||||
|
||||
export type SocialConnectorInstance = {
|
||||
instance: InstanceType<typeof SocialConnector>;
|
||||
connector: Connector;
|
||||
};
|
||||
|
||||
export type ConnectorInstance =
|
||||
| SmsConnectorInstance
|
||||
| EmailConnectorInstance
|
||||
| SocialConnectorInstance
|
||||
| { instance: Instance; connector: Connector };
|
||||
export type ConnectorInstance = ArbitraryConnector & { connector: Connector };
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorType, ValidateConfig, GetConnectorConfig } from '@logto/connector-types';
|
||||
import { ConnectorType, ValidateConfig, GetConnectorConfig } from '@logto/connector-schemas';
|
||||
import { Passcode, PasscodeType, Connector } from '@logto/schemas';
|
||||
|
||||
import { mockConnector, mockMetadata } from '@/__mocks__';
|
||||
|
@ -27,13 +27,11 @@ jest.mock('@/connectors');
|
|||
|
||||
type ConnectorInstance = {
|
||||
connector: Connector;
|
||||
instance: {
|
||||
metadata: ConnectorMetadata;
|
||||
validateConfig?: ValidateConfig<unknown>;
|
||||
getConfig?: GetConnectorConfig;
|
||||
sendMessage?: unknown;
|
||||
sendTestMessage?: unknown;
|
||||
};
|
||||
metadata: ConnectorMetadata;
|
||||
validateConfig?: ValidateConfig<unknown>;
|
||||
getConfig?: GetConnectorConfig;
|
||||
sendMessage?: unknown;
|
||||
sendTestMessage?: unknown;
|
||||
};
|
||||
|
||||
const mockedFindUnconsumedPasscodesByJtiAndType =
|
||||
|
@ -149,16 +147,14 @@ describe('sendPasscode', () => {
|
|||
...mockConnector,
|
||||
id: 'id1',
|
||||
},
|
||||
instance: {
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
type: ConnectorType.Email,
|
||||
platform: null,
|
||||
},
|
||||
sendMessage,
|
||||
validateConfig,
|
||||
getConfig,
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
type: ConnectorType.Email,
|
||||
platform: null,
|
||||
},
|
||||
sendMessage,
|
||||
validateConfig,
|
||||
getConfig,
|
||||
},
|
||||
];
|
||||
getConnectorInstancesPlaceHolder.mockResolvedValueOnce(mockConnectorInstances);
|
||||
|
@ -191,31 +187,27 @@ describe('sendPasscode', () => {
|
|||
...mockConnector,
|
||||
id: 'id0',
|
||||
},
|
||||
instance: {
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
type: ConnectorType.SMS,
|
||||
platform: null,
|
||||
},
|
||||
sendMessage,
|
||||
validateConfig,
|
||||
getConfig,
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
type: ConnectorType.SMS,
|
||||
platform: null,
|
||||
},
|
||||
sendMessage,
|
||||
validateConfig,
|
||||
getConfig,
|
||||
},
|
||||
{
|
||||
connector: {
|
||||
...mockConnector,
|
||||
id: 'id1',
|
||||
},
|
||||
instance: {
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
type: ConnectorType.Email,
|
||||
platform: null,
|
||||
},
|
||||
validateConfig,
|
||||
getConfig,
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
type: ConnectorType.Email,
|
||||
platform: null,
|
||||
},
|
||||
validateConfig,
|
||||
getConfig,
|
||||
},
|
||||
];
|
||||
getConnectorInstancesPlaceHolder.mockResolvedValueOnce(mockConnectorInstances);
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Passcode, PasscodeType } from '@logto/schemas';
|
|||
import { customAlphabet, nanoid } from 'nanoid';
|
||||
|
||||
import { getConnectorInstances } from '@/connectors';
|
||||
import { ConnectorType, EmailConnectorInstance, SmsConnectorInstance } from '@/connectors/types';
|
||||
import { EmailConnectorInstance, SmsConnectorInstance, ConnectorType } from '@/connectors/types';
|
||||
import RequestError from '@/errors/RequestError';
|
||||
import {
|
||||
consumePasscode,
|
||||
|
@ -49,11 +49,11 @@ export const sendPasscode = async (passcode: Passcode) => {
|
|||
|
||||
const emailConnectorInstance = connectorInstances.find(
|
||||
(connector): connector is EmailConnectorInstance =>
|
||||
connector.connector.enabled && connector.instance.metadata.type === ConnectorType.Email
|
||||
connector.connector.enabled && connector.metadata.type === ConnectorType.Email
|
||||
);
|
||||
const smsConnectorInstance = connectorInstances.find(
|
||||
(connector): connector is SmsConnectorInstance =>
|
||||
connector.connector.enabled && connector.instance.metadata.type === ConnectorType.SMS
|
||||
connector.connector.enabled && connector.metadata.type === ConnectorType.SMS
|
||||
);
|
||||
|
||||
const connectorInstance = passcode.email ? emailConnectorInstance : smsConnectorInstance;
|
||||
|
@ -66,10 +66,7 @@ export const sendPasscode = async (passcode: Passcode) => {
|
|||
})
|
||||
);
|
||||
|
||||
const {
|
||||
connector,
|
||||
instance: { metadata, sendMessage },
|
||||
} = connectorInstance;
|
||||
const { connector, metadata, sendMessage } = connectorInstance;
|
||||
|
||||
const response = await sendMessage(emailOrPhone, passcode.type, {
|
||||
code: passcode.code,
|
||||
|
|
|
@ -41,7 +41,7 @@ export const validateSignInMethods = (
|
|||
|
||||
if (isEnabled(signInMethods.email)) {
|
||||
assertThat(
|
||||
enabledConnectorInstances.some((item) => item.instance.metadata.type === ConnectorType.Email),
|
||||
enabledConnectorInstances.some((item) => item.metadata.type === ConnectorType.Email),
|
||||
new RequestError({
|
||||
code: 'sign_in_experiences.enabled_connector_not_found',
|
||||
type: ConnectorType.Email,
|
||||
|
@ -51,7 +51,7 @@ export const validateSignInMethods = (
|
|||
|
||||
if (isEnabled(signInMethods.sms)) {
|
||||
assertThat(
|
||||
enabledConnectorInstances.some((item) => item.instance.metadata.type === ConnectorType.SMS),
|
||||
enabledConnectorInstances.some((item) => item.metadata.type === ConnectorType.SMS),
|
||||
new RequestError({
|
||||
code: 'sign_in_experiences.enabled_connector_not_found',
|
||||
type: ConnectorType.SMS,
|
||||
|
@ -61,9 +61,7 @@ export const validateSignInMethods = (
|
|||
|
||||
if (isEnabled(signInMethods.social)) {
|
||||
assertThat(
|
||||
enabledConnectorInstances.some(
|
||||
(item) => item.instance.metadata.type === ConnectorType.Social
|
||||
),
|
||||
enabledConnectorInstances.some((item) => item.metadata.type === ConnectorType.Social),
|
||||
new RequestError({
|
||||
code: 'sign_in_experiences.enabled_connector_not_found',
|
||||
type: ConnectorType.Social,
|
||||
|
|
|
@ -41,7 +41,7 @@ export const getUserInfoByAuthCode = async (
|
|||
): Promise<SocialUserInfo> => {
|
||||
const connector = await getConnector(connectorId);
|
||||
|
||||
return connector.instance.getUserInfo(data);
|
||||
return connector.getUserInfo(data);
|
||||
};
|
||||
|
||||
export const getUserInfoFromInteractionResult = async (
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorError, ConnectorErrorCodes } from '@logto/connector-types';
|
||||
import { ConnectorError, ConnectorErrorCodes } from '@logto/connector-schemas';
|
||||
|
||||
import RequestError from '@/errors/RequestError';
|
||||
import { createContextWithRouteParameters } from '@/utils/test-utils';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorError, ConnectorErrorCodes } from '@logto/connector-types';
|
||||
import { ConnectorError, ConnectorErrorCodes } from '@logto/connector-schemas';
|
||||
import { conditional } from '@silverhand/essentials';
|
||||
import { Middleware } from 'koa';
|
||||
import { z } from 'zod';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { GetConnectorConfig, ValidateConfig } from '@logto/connector-types';
|
||||
import { GetConnectorConfig, ValidateConfig } from '@logto/connector-schemas';
|
||||
import { Connector, ConnectorType } from '@logto/schemas';
|
||||
|
||||
import { mockConnectorInstanceList, mockMetadata, mockConnector } from '@/__mocks__';
|
||||
|
@ -11,13 +11,11 @@ import connectorRoutes from './connector';
|
|||
|
||||
type ConnectorInstance = {
|
||||
connector: Connector;
|
||||
instance: {
|
||||
metadata: ConnectorMetadata;
|
||||
validateConfig?: ValidateConfig<unknown>;
|
||||
getConfig?: GetConnectorConfig;
|
||||
sendMessage?: unknown;
|
||||
sendTestMessage?: unknown;
|
||||
};
|
||||
metadata: ConnectorMetadata;
|
||||
validateConfig?: ValidateConfig<unknown>;
|
||||
getConfig?: GetConnectorConfig;
|
||||
sendMessage?: unknown;
|
||||
sendTestMessage?: unknown;
|
||||
};
|
||||
|
||||
const getConnectorInstancesPlaceHolder = jest.fn() as jest.MockedFunction<
|
||||
|
@ -59,7 +57,7 @@ describe('connector route', () => {
|
|||
it('throws if more than one SMS connector is enabled', async () => {
|
||||
getConnectorInstancesPlaceHolder.mockResolvedValueOnce(
|
||||
mockConnectorInstanceList.filter(
|
||||
(connectorInstance) => connectorInstance.instance.metadata.type !== ConnectorType.Email
|
||||
(connectorInstance) => connectorInstance.metadata.type !== ConnectorType.Email
|
||||
)
|
||||
);
|
||||
const response = await connectorRequest.get('/connectors').send({});
|
||||
|
@ -69,7 +67,7 @@ describe('connector route', () => {
|
|||
it('shows all connectors', async () => {
|
||||
getConnectorInstancesPlaceHolder.mockResolvedValueOnce(
|
||||
mockConnectorInstanceList.filter(
|
||||
(connectorInstance) => connectorInstance.instance.metadata.type === ConnectorType.Social
|
||||
(connectorInstance) => connectorInstance.metadata.type === ConnectorType.Social
|
||||
)
|
||||
);
|
||||
const response = await connectorRequest.get('/connectors').send({});
|
||||
|
@ -114,13 +112,11 @@ describe('connector route', () => {
|
|||
};
|
||||
const mockedSmsConnectorInstance: ConnectorInstance = {
|
||||
connector: mockConnector,
|
||||
instance: {
|
||||
metadata: mockedMetadata,
|
||||
validateConfig: jest.fn(),
|
||||
getConfig: jest.fn(),
|
||||
sendMessage: jest.fn(),
|
||||
sendTestMessage: mockSendTestMessage,
|
||||
},
|
||||
metadata: mockedMetadata,
|
||||
validateConfig: jest.fn(),
|
||||
getConfig: jest.fn(),
|
||||
sendMessage: jest.fn(),
|
||||
sendTestMessage: mockSendTestMessage,
|
||||
};
|
||||
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([mockedSmsConnectorInstance]);
|
||||
const response = await connectorRequest
|
||||
|
@ -137,13 +133,11 @@ describe('connector route', () => {
|
|||
const sendTestMessage = jest.fn();
|
||||
const mockedEmailConnector: ConnectorInstance = {
|
||||
connector: mockConnector,
|
||||
instance: {
|
||||
metadata: mockMetadata,
|
||||
validateConfig: jest.fn(),
|
||||
getConfig: jest.fn(),
|
||||
sendMessage: jest.fn(),
|
||||
sendTestMessage,
|
||||
},
|
||||
metadata: mockMetadata,
|
||||
validateConfig: jest.fn(),
|
||||
getConfig: jest.fn(),
|
||||
sendMessage: jest.fn(),
|
||||
sendTestMessage,
|
||||
};
|
||||
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([mockedEmailConnector]);
|
||||
const response = await connectorRequest
|
||||
|
|
|
@ -15,10 +15,7 @@ import assertThat from '@/utils/assert-that';
|
|||
|
||||
import { AuthedRouter } from './types';
|
||||
|
||||
const transpileConnectorInstance = ({
|
||||
connector,
|
||||
instance: { metadata },
|
||||
}: ConnectorInstance): ConnectorDto => ({
|
||||
const transpileConnectorInstance = ({ connector, metadata }: ConnectorInstance): ConnectorDto => ({
|
||||
...connector,
|
||||
...metadata,
|
||||
});
|
||||
|
@ -38,26 +35,20 @@ export default function connectorRoutes<T extends AuthedRouter>(router: T) {
|
|||
assertThat(
|
||||
connectorInstances.filter(
|
||||
(connector) =>
|
||||
connector.connector.enabled && connector.instance.metadata.type === ConnectorType.Email
|
||||
connector.connector.enabled && connector.metadata.type === ConnectorType.Email
|
||||
).length <= 1,
|
||||
'connector.more_than_one_email'
|
||||
);
|
||||
assertThat(
|
||||
connectorInstances.filter(
|
||||
(connector) =>
|
||||
connector.connector.enabled && connector.instance.metadata.type === ConnectorType.SMS
|
||||
connector.connector.enabled && connector.metadata.type === ConnectorType.SMS
|
||||
).length <= 1,
|
||||
'connector.more_than_one_sms'
|
||||
);
|
||||
|
||||
const filteredInstances = filterTarget
|
||||
? connectorInstances.filter(
|
||||
({
|
||||
instance: {
|
||||
metadata: { target },
|
||||
},
|
||||
}) => target === filterTarget
|
||||
)
|
||||
? connectorInstances.filter(({ metadata: { target } }) => target === filterTarget)
|
||||
: connectorInstances;
|
||||
|
||||
ctx.body = filteredInstances.map((connectorInstance) =>
|
||||
|
@ -97,7 +88,8 @@ export default function connectorRoutes<T extends AuthedRouter>(router: T) {
|
|||
const connectorInstance = await getConnectorInstanceById(id);
|
||||
const {
|
||||
connector: { config },
|
||||
instance: { validateConfig, metadata },
|
||||
validateConfig,
|
||||
metadata,
|
||||
} = connectorInstance;
|
||||
|
||||
/**
|
||||
|
@ -121,7 +113,7 @@ export default function connectorRoutes<T extends AuthedRouter>(router: T) {
|
|||
connectors
|
||||
.filter(
|
||||
(connector) =>
|
||||
connector.instance.metadata.type === metadata.type && connector.connector.enabled
|
||||
connector.metadata.type === metadata.type && connector.connector.enabled
|
||||
)
|
||||
.map(async ({ connector: { id } }) =>
|
||||
updateConnector({ set: { enabled: false }, where: { id }, jsonbMode: 'merge' })
|
||||
|
@ -152,9 +144,7 @@ export default function connectorRoutes<T extends AuthedRouter>(router: T) {
|
|||
body,
|
||||
} = ctx.guard;
|
||||
|
||||
const {
|
||||
instance: { metadata, validateConfig },
|
||||
} = await getConnectorInstanceById(id);
|
||||
const { metadata, validateConfig } = await getConnectorInstanceById(id);
|
||||
|
||||
/**
|
||||
* Assertion functions always need explicit annotations.
|
||||
|
@ -197,13 +187,11 @@ export default function connectorRoutes<T extends AuthedRouter>(router: T) {
|
|||
const connector: SmsConnectorInstance | EmailConnectorInstance | undefined = phone
|
||||
? connectorInstances.find(
|
||||
(connector): connector is SmsConnectorInstance =>
|
||||
connector.instance.metadata.id === id &&
|
||||
connector.instance.metadata.type === ConnectorType.SMS
|
||||
connector.metadata.id === id && connector.metadata.type === ConnectorType.SMS
|
||||
)
|
||||
: connectorInstances.find(
|
||||
(connector): connector is EmailConnectorInstance =>
|
||||
connector.instance.metadata.id === id &&
|
||||
connector.instance.metadata.type === ConnectorType.Email
|
||||
connector.metadata.id === id && connector.metadata.type === ConnectorType.Email
|
||||
);
|
||||
|
||||
assertThat(
|
||||
|
@ -214,9 +202,7 @@ export default function connectorRoutes<T extends AuthedRouter>(router: T) {
|
|||
})
|
||||
);
|
||||
|
||||
const {
|
||||
instance: { sendTestMessage },
|
||||
} = connector;
|
||||
const { sendTestMessage } = connector;
|
||||
assertThat(
|
||||
sendTestMessage,
|
||||
new RequestError({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorError, ConnectorErrorCodes, ValidateConfig } from '@logto/connector-types';
|
||||
import { ConnectorError, ConnectorErrorCodes, ValidateConfig } from '@logto/connector-schemas';
|
||||
import { Connector, ConnectorType } from '@logto/schemas';
|
||||
|
||||
import { mockConnectorInstanceList, mockMetadata, mockConnector } from '@/__mocks__';
|
||||
|
@ -12,11 +12,9 @@ import connectorRoutes from './connector';
|
|||
|
||||
type ConnectorInstance = {
|
||||
connector: Connector;
|
||||
instance: {
|
||||
metadata: ConnectorMetadata;
|
||||
validateConfig?: ValidateConfig<unknown>;
|
||||
sendMessage?: unknown;
|
||||
};
|
||||
metadata: ConnectorMetadata;
|
||||
validateConfig?: ValidateConfig<unknown>;
|
||||
sendMessage?: unknown;
|
||||
};
|
||||
|
||||
const getConnectorInstancesPlaceHolder = jest.fn() as jest.MockedFunction<
|
||||
|
@ -36,15 +34,13 @@ const getConnectorInstanceByIdPlaceHolder = jest.fn(async (connectorId: string)
|
|||
})
|
||||
);
|
||||
|
||||
const { instance, connector } = connectorInstance;
|
||||
const { metadata, connector } = connectorInstance;
|
||||
|
||||
return {
|
||||
connector,
|
||||
instance: {
|
||||
...instance,
|
||||
validateConfig: validateConfigPlaceHolder,
|
||||
sendMessage: sendMessagePlaceHolder,
|
||||
},
|
||||
metadata,
|
||||
validateConfig: validateConfigPlaceHolder,
|
||||
sendMessage: sendMessagePlaceHolder,
|
||||
};
|
||||
});
|
||||
const validateConfigPlaceHolder = jest.fn() as jest.MockedFunction<ValidateConfig<unknown>>;
|
||||
|
@ -87,7 +83,7 @@ describe('connector PATCH routes', () => {
|
|||
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([
|
||||
{
|
||||
connector: mockConnector,
|
||||
instance: { metadata: { ...mockMetadata, type: ConnectorType.Social } },
|
||||
metadata: { ...mockMetadata, type: ConnectorType.Social },
|
||||
},
|
||||
]);
|
||||
const response = await connectorRequest
|
||||
|
@ -113,7 +109,7 @@ describe('connector PATCH routes', () => {
|
|||
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([
|
||||
{
|
||||
connector: mockConnector,
|
||||
instance: { metadata: mockMetadata },
|
||||
metadata: mockMetadata,
|
||||
},
|
||||
]);
|
||||
const response = await connectorRequest
|
||||
|
@ -126,7 +122,7 @@ describe('connector PATCH routes', () => {
|
|||
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([
|
||||
{
|
||||
connector: mockConnector,
|
||||
instance: { metadata: mockMetadata },
|
||||
metadata: mockMetadata,
|
||||
},
|
||||
]);
|
||||
const response = await connectorRequest
|
||||
|
@ -158,7 +154,9 @@ describe('connector PATCH routes', () => {
|
|||
};
|
||||
getConnectorInstanceByIdPlaceHolder.mockResolvedValueOnce({
|
||||
connector: mockedConnector,
|
||||
instance: { metadata: mockedMetadata, validateConfig: jest.fn(), sendMessage: jest.fn() },
|
||||
metadata: mockedMetadata,
|
||||
validateConfig: jest.fn(),
|
||||
sendMessage: jest.fn(),
|
||||
});
|
||||
const response = await connectorRequest
|
||||
.patch('/connectors/id1/enabled')
|
||||
|
@ -200,11 +198,9 @@ describe('connector PATCH routes', () => {
|
|||
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([
|
||||
{
|
||||
connector: mockConnector,
|
||||
instance: {
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
type: ConnectorType.SMS,
|
||||
},
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
type: ConnectorType.SMS,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
@ -218,7 +214,7 @@ describe('connector PATCH routes', () => {
|
|||
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([
|
||||
{
|
||||
connector: mockConnector,
|
||||
instance: { metadata: mockMetadata },
|
||||
metadata: mockMetadata,
|
||||
},
|
||||
]);
|
||||
const response = await connectorRequest
|
||||
|
@ -262,7 +258,7 @@ describe('connector PATCH routes', () => {
|
|||
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([
|
||||
{
|
||||
connector: mockConnector,
|
||||
instance: { metadata: mockMetadata },
|
||||
metadata: mockMetadata,
|
||||
},
|
||||
]);
|
||||
const response = await connectorRequest
|
||||
|
@ -275,7 +271,7 @@ describe('connector PATCH routes', () => {
|
|||
getConnectorInstancesPlaceHolder.mockResolvedValueOnce([
|
||||
{
|
||||
connector: mockConnector,
|
||||
instance: { metadata: mockMetadata },
|
||||
metadata: mockMetadata,
|
||||
},
|
||||
]);
|
||||
const response = await connectorRequest
|
||||
|
|
|
@ -61,13 +61,13 @@ const getConnectorInstanceByIdHelper = jest.fn(async (connectorId: string) => {
|
|||
type: connectorId.startsWith('social') ? ConnectorType.Social : ConnectorType.SMS,
|
||||
};
|
||||
|
||||
return { connector, instance: { metadata, getAuthorizationUri: jest.fn(async () => '') } };
|
||||
return { connector, metadata, getAuthorizationUri: jest.fn(async () => '') };
|
||||
});
|
||||
jest.mock('@/connectors', () => ({
|
||||
getSocialConnectorInstanceById: async (connectorId: string) => {
|
||||
const connectorInstance = await getConnectorInstanceByIdHelper(connectorId);
|
||||
|
||||
if (connectorInstance.instance.metadata.type !== ConnectorType.Social) {
|
||||
if (connectorInstance.metadata.type !== ConnectorType.Social) {
|
||||
throw new RequestError({
|
||||
code: 'entity.not_found',
|
||||
status: 404,
|
||||
|
@ -170,7 +170,7 @@ describe('sessionSocialRoutes', () => {
|
|||
|
||||
it('throw error when auth code is wrong', async () => {
|
||||
(getConnectorInstanceById as jest.Mock).mockResolvedValueOnce({
|
||||
instance: { metadata: { target: connectorTarget } },
|
||||
metadata: { target: connectorTarget },
|
||||
});
|
||||
const response = await sessionRequest.post('/session/sign-in/social/auth').send({
|
||||
connectorId: 'connectorId',
|
||||
|
@ -183,7 +183,7 @@ describe('sessionSocialRoutes', () => {
|
|||
|
||||
it('throw error when code is provided but connector can not be found', async () => {
|
||||
(getConnectorInstanceById as jest.Mock).mockResolvedValueOnce({
|
||||
instance: { metadata: { target: connectorTarget } },
|
||||
metadata: { target: connectorTarget },
|
||||
});
|
||||
const response = await sessionRequest.post('/session/sign-in/social/auth').send({
|
||||
connectorId: '_connectorId',
|
||||
|
@ -196,7 +196,7 @@ describe('sessionSocialRoutes', () => {
|
|||
|
||||
it('get and add user info with auth code, as well as assign result and redirect', async () => {
|
||||
(getConnectorInstanceById as jest.Mock).mockResolvedValueOnce({
|
||||
instance: { metadata: { target: connectorTarget } },
|
||||
metadata: { target: connectorTarget },
|
||||
});
|
||||
const response = await sessionRequest.post('/session/sign-in/social/auth').send({
|
||||
connectorId: 'connectorId',
|
||||
|
@ -224,7 +224,7 @@ describe('sessionSocialRoutes', () => {
|
|||
it('throw error when identity exists', async () => {
|
||||
const wrongConnectorTarget = 'wrongConnectorTarget';
|
||||
(getConnectorInstanceById as jest.Mock).mockResolvedValueOnce({
|
||||
instance: { metadata: { target: wrongConnectorTarget } },
|
||||
metadata: { target: wrongConnectorTarget },
|
||||
});
|
||||
const response = await sessionRequest.post('/session/sign-in/social/auth').send({
|
||||
connectorId: '_connectorId_',
|
||||
|
@ -250,7 +250,7 @@ describe('sessionSocialRoutes', () => {
|
|||
beforeEach(() => {
|
||||
const mockGetConnectorInstanceById = getConnectorInstanceById as jest.Mock;
|
||||
mockGetConnectorInstanceById.mockResolvedValueOnce({
|
||||
instance: { metadata: { target: 'connectorTarget' } },
|
||||
metadata: { target: 'connectorTarget' },
|
||||
});
|
||||
});
|
||||
afterEach(() => {
|
||||
|
@ -312,7 +312,7 @@ describe('sessionSocialRoutes', () => {
|
|||
beforeEach(() => {
|
||||
const mockGetConnectorInstanceById = getConnectorInstanceById as jest.Mock;
|
||||
mockGetConnectorInstanceById.mockResolvedValueOnce({
|
||||
instance: { metadata: { target: 'connectorTarget' } },
|
||||
metadata: { target: 'connectorTarget' },
|
||||
});
|
||||
});
|
||||
afterEach(() => {
|
||||
|
@ -378,7 +378,7 @@ describe('sessionSocialRoutes', () => {
|
|||
beforeEach(() => {
|
||||
const mockGetConnectorInstanceById = getConnectorInstanceById as jest.Mock;
|
||||
mockGetConnectorInstanceById.mockResolvedValueOnce({
|
||||
instance: { metadata: { target: 'connectorTarget' } },
|
||||
metadata: { target: 'connectorTarget' },
|
||||
});
|
||||
});
|
||||
afterEach(() => {
|
||||
|
|
|
@ -45,7 +45,7 @@ export default function sessionSocialRoutes<T extends AnonymousRouter>(
|
|||
assertThat(state && redirectUri, 'session.insufficient_info');
|
||||
const connector = await getSocialConnectorInstanceById(connectorId);
|
||||
assertThat(connector.connector.enabled, 'connector.not_enabled');
|
||||
const redirectTo = await connector.instance.getAuthorizationUri({ state, redirectUri });
|
||||
const redirectTo = await connector.getAuthorizationUri({ state, redirectUri });
|
||||
ctx.body = { redirectTo };
|
||||
|
||||
return next();
|
||||
|
@ -67,9 +67,7 @@ export default function sessionSocialRoutes<T extends AnonymousRouter>(
|
|||
const type = 'SignInSocial';
|
||||
ctx.log(type, { connectorId, data });
|
||||
const {
|
||||
instance: {
|
||||
metadata: { target },
|
||||
},
|
||||
metadata: { target },
|
||||
} = await getConnectorInstanceById(connectorId);
|
||||
|
||||
const userInfo = await getUserInfoByAuthCode(connectorId, data);
|
||||
|
@ -120,9 +118,7 @@ export default function sessionSocialRoutes<T extends AnonymousRouter>(
|
|||
const type = 'SignInSocialBind';
|
||||
ctx.log(type, { connectorId });
|
||||
const {
|
||||
instance: {
|
||||
metadata: { target },
|
||||
},
|
||||
metadata: { target },
|
||||
} = await getConnectorInstanceById(connectorId);
|
||||
|
||||
const userInfo = await getUserInfoFromInteractionResult(connectorId, result);
|
||||
|
@ -162,9 +158,7 @@ export default function sessionSocialRoutes<T extends AnonymousRouter>(
|
|||
const type = 'RegisterSocial';
|
||||
ctx.log(type, { connectorId });
|
||||
const {
|
||||
instance: {
|
||||
metadata: { target },
|
||||
},
|
||||
metadata: { target },
|
||||
} = await getConnectorInstanceById(connectorId);
|
||||
|
||||
const userInfo = await getUserInfoFromInteractionResult(connectorId, result);
|
||||
|
@ -209,9 +203,7 @@ export default function sessionSocialRoutes<T extends AnonymousRouter>(
|
|||
const type = 'RegisterSocialBind';
|
||||
ctx.log(type, { connectorId, userId });
|
||||
const {
|
||||
instance: {
|
||||
metadata: { target },
|
||||
},
|
||||
metadata: { target },
|
||||
} = await getConnectorInstanceById(connectorId);
|
||||
|
||||
const userInfo = await getUserInfoFromInteractionResult(connectorId, result);
|
||||
|
|
|
@ -52,8 +52,7 @@ export default function signInExperiencesRoutes<T extends AuthedRouter>(router:
|
|||
const filteredSocialSignInConnectorTargets = socialSignInConnectorTargets?.filter((target) =>
|
||||
enabledConnectorInstances.some(
|
||||
(connector) =>
|
||||
connector.instance.metadata.target === target &&
|
||||
connector.instance.metadata.type === ConnectorType.Social
|
||||
connector.metadata.target === target && connector.metadata.type === ConnectorType.Social
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ jest.mock('@/connectors', () => ({
|
|||
getSocialConnectorInstanceById: async (connectorId: string) => {
|
||||
const connectorInstance = await getConnectorInstanceById(connectorId);
|
||||
|
||||
if (connectorInstance.instance.metadata.type !== ConnectorType.Social) {
|
||||
if (connectorInstance.metadata.type !== ConnectorType.Social) {
|
||||
throw new RequestError({
|
||||
code: 'entity.not_found',
|
||||
status: 404,
|
||||
|
@ -92,19 +92,19 @@ describe('GET /.well-known/sign-in-exp', () => {
|
|||
...mockSignInExperience,
|
||||
socialConnectors: [
|
||||
{
|
||||
...mockGithubConnectorInstance.instance.metadata,
|
||||
...mockGithubConnectorInstance.metadata,
|
||||
id: mockGithubConnectorInstance.connector.id,
|
||||
},
|
||||
{
|
||||
...mockFacebookConnectorInstance.instance.metadata,
|
||||
...mockFacebookConnectorInstance.metadata,
|
||||
id: mockFacebookConnectorInstance.connector.id,
|
||||
},
|
||||
{
|
||||
...mockWechatConnectorInstance.instance.metadata,
|
||||
...mockWechatConnectorInstance.metadata,
|
||||
id: mockWechatConnectorInstance.connector.id,
|
||||
},
|
||||
{
|
||||
...mockWechatNativeConnectorInstance.instance.metadata,
|
||||
...mockWechatNativeConnectorInstance.metadata,
|
||||
id: mockWechatNativeConnectorInstance.connector.id,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ConnectorMetadata } from '@logto/connector-types';
|
||||
import { ConnectorMetadata } from '@logto/connector-schemas';
|
||||
import { SignInMode } from '@logto/schemas';
|
||||
import {
|
||||
adminConsoleApplicationId,
|
||||
|
@ -55,17 +55,13 @@ export default function wellKnownRoutes<T extends AnonymousRouter>(router: T, pr
|
|||
Array<ConnectorMetadata & { id: string }>
|
||||
>((previous, connectorTarget) => {
|
||||
const connectors = connectorInstances.filter(
|
||||
({
|
||||
instance: {
|
||||
metadata: { target },
|
||||
},
|
||||
connector: { enabled },
|
||||
}) => target === connectorTarget && enabled
|
||||
({ metadata: { target }, connector: { enabled } }) =>
|
||||
target === connectorTarget && enabled
|
||||
);
|
||||
|
||||
return [
|
||||
...previous,
|
||||
...connectors.map(({ instance: { metadata }, connector: { id } }) => ({
|
||||
...connectors.map(({ metadata, connector: { id } }) => ({
|
||||
...metadata,
|
||||
id,
|
||||
})),
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
},
|
||||
"prettier": "@silverhand/eslint-config/.prettierrc",
|
||||
"dependencies": {
|
||||
"@logto/connector-types": "^1.0.0-beta.4",
|
||||
"@logto/connector-schemas": "^1.0.0-beta.4",
|
||||
"@logto/phrases": "^1.0.0-beta.4",
|
||||
"@logto/phrases-ui": "^1.0.0-beta.4",
|
||||
"@logto/shared": "^1.0.0-beta.4",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { ConnectorMetadata } from '@logto/connector-types';
|
||||
import { ConnectorMetadata } from '@logto/connector-schemas';
|
||||
|
||||
import { Connector } from '../db-entries';
|
||||
|
||||
export type { ConnectorMetadata } from '@logto/connector-types';
|
||||
export { ConnectorType, ConnectorPlatform } from '@logto/connector-types';
|
||||
export type { ConnectorMetadata } from '@logto/connector-schemas';
|
||||
export { ConnectorType, ConnectorPlatform } from '@logto/connector-schemas';
|
||||
|
||||
export type ConnectorDto = Connector & ConnectorMetadata;
|
||||
|
|
163
pnpm-lock.yaml
generated
163
pnpm-lock.yaml
generated
|
@ -21,7 +21,7 @@ importers:
|
|||
packages/connector-alipay-native:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@shopify/jest-koa-mocks': ^5.0.0
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
|
@ -47,7 +47,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
'@silverhand/jest-config': 1.0.0-rc.3_bi2kohzqnxavgozw3csgny5hju
|
||||
|
@ -78,7 +78,7 @@ importers:
|
|||
packages/connector-alipay-web:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@shopify/jest-koa-mocks': ^5.0.0
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
|
@ -104,7 +104,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
'@silverhand/jest-config': 1.0.0-rc.3_bi2kohzqnxavgozw3csgny5hju
|
||||
|
@ -135,7 +135,7 @@ importers:
|
|||
packages/connector-aliyun-dm:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
'@silverhand/essentials': ^1.1.0
|
||||
|
@ -152,7 +152,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
'@silverhand/jest-config': 1.0.0-rc.3_bi2kohzqnxavgozw3csgny5hju
|
||||
|
@ -174,7 +174,7 @@ importers:
|
|||
packages/connector-aliyun-sms:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
|
@ -192,7 +192,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/schemas': link:../schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
|
@ -215,7 +215,7 @@ importers:
|
|||
packages/connector-apple:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
|
@ -236,7 +236,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/schemas': link:../schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
|
@ -263,7 +263,7 @@ importers:
|
|||
specifiers:
|
||||
'@azure/msal-node': ^1.12.0
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
|
@ -285,7 +285,7 @@ importers:
|
|||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@azure/msal-node': 1.12.0
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/schemas': link:../schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
|
@ -308,33 +308,10 @@ importers:
|
|||
tsc-watch: 5.0.3_typescript@4.7.4
|
||||
typescript: 4.7.4
|
||||
|
||||
packages/connector-base-classes:
|
||||
specifiers:
|
||||
'@logto/connector-types': ^1.0.0-beta.3
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
'@silverhand/essentials': ^1.1.6
|
||||
'@silverhand/ts-config': 1.0.0-rc.2
|
||||
'@types/node': ^16.3.1
|
||||
eslint: ^8.21.0
|
||||
lint-staged: ^13.0.0
|
||||
prettier: ^2.7.1
|
||||
typescript: ^4.7.4
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
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
|
||||
'@types/node': 16.11.12
|
||||
eslint: 8.21.0
|
||||
lint-staged: 13.0.0
|
||||
prettier: 2.7.1
|
||||
typescript: 4.7.4
|
||||
|
||||
packages/connector-facebook:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
|
@ -354,7 +331,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/schemas': link:../schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
|
@ -379,7 +356,7 @@ importers:
|
|||
packages/connector-github:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
|
@ -400,7 +377,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/schemas': link:../schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
|
@ -426,7 +403,7 @@ importers:
|
|||
packages/connector-google:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
|
@ -446,7 +423,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/schemas': link:../schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
|
@ -470,7 +447,7 @@ importers:
|
|||
|
||||
packages/connector-mock-email:
|
||||
specifiers:
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
'@silverhand/essentials': ^1.1.6
|
||||
|
@ -483,7 +460,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
zod: 3.14.3
|
||||
|
@ -499,7 +476,7 @@ importers:
|
|||
|
||||
packages/connector-mock-sms:
|
||||
specifiers:
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
'@silverhand/essentials': ^1.1.6
|
||||
|
@ -512,7 +489,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
zod: 3.14.3
|
||||
|
@ -528,7 +505,7 @@ importers:
|
|||
|
||||
packages/connector-mock-social:
|
||||
specifiers:
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
|
@ -542,7 +519,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/schemas': link:../schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
|
@ -557,10 +534,43 @@ importers:
|
|||
tsc-watch: 5.0.3_typescript@4.7.4
|
||||
typescript: 4.7.4
|
||||
|
||||
packages/connector-schemas:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/phrases': ^1.0.0-beta.4
|
||||
'@shopify/jest-koa-mocks': ^5.0.0
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
'@silverhand/essentials': ^1.1.6
|
||||
'@silverhand/ts-config': 1.0.0-rc.2
|
||||
'@types/jest': ^28.1.6
|
||||
'@types/node': ^16.3.1
|
||||
eslint: ^8.21.0
|
||||
jest: ^28.1.3
|
||||
lint-staged: ^13.0.0
|
||||
prettier: ^2.7.1
|
||||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/phrases': link:../phrases
|
||||
zod: 3.14.3
|
||||
devDependencies:
|
||||
'@jest/types': 28.1.3
|
||||
'@shopify/jest-koa-mocks': 5.0.0
|
||||
'@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
|
||||
'@types/jest': 28.1.6
|
||||
'@types/node': 16.11.12
|
||||
eslint: 8.21.0
|
||||
jest: 28.1.3_@types+node@16.11.12
|
||||
lint-staged: 13.0.0
|
||||
prettier: 2.7.1
|
||||
typescript: 4.7.4
|
||||
|
||||
packages/connector-sendgrid-mail:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
'@silverhand/essentials': ^1.1.6
|
||||
|
@ -577,7 +587,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
'@silverhand/jest-config': 1.0.0-rc.3_bi2kohzqnxavgozw3csgny5hju
|
||||
|
@ -599,7 +609,7 @@ importers:
|
|||
packages/connector-smtp:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
'@silverhand/essentials': ^1.1.6
|
||||
|
@ -617,7 +627,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
'@silverhand/jest-config': 1.0.0-rc.3_bi2kohzqnxavgozw3csgny5hju
|
||||
|
@ -640,7 +650,7 @@ importers:
|
|||
packages/connector-twilio-sms:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
'@silverhand/essentials': ^1.1.6
|
||||
|
@ -657,7 +667,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
'@silverhand/jest-config': 1.0.0-rc.3_bi2kohzqnxavgozw3csgny5hju
|
||||
|
@ -676,41 +686,10 @@ importers:
|
|||
tsc-watch: 5.0.3_typescript@4.7.4
|
||||
typescript: 4.7.4
|
||||
|
||||
packages/connector-types:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/phrases': ^1.0.0-beta.4
|
||||
'@shopify/jest-koa-mocks': ^5.0.0
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
'@silverhand/essentials': ^1.1.6
|
||||
'@silverhand/ts-config': 1.0.0-rc.2
|
||||
'@types/jest': ^28.1.6
|
||||
eslint: ^8.21.0
|
||||
jest: ^28.1.3
|
||||
lint-staged: ^13.0.0
|
||||
prettier: ^2.7.1
|
||||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/phrases': link:../phrases
|
||||
zod: 3.14.3
|
||||
devDependencies:
|
||||
'@jest/types': 28.1.3
|
||||
'@shopify/jest-koa-mocks': 5.0.0
|
||||
'@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
|
||||
'@types/jest': 28.1.6
|
||||
eslint: 8.21.0
|
||||
jest: 28.1.3
|
||||
lint-staged: 13.0.0
|
||||
prettier: 2.7.1
|
||||
typescript: 4.7.4
|
||||
|
||||
packages/connector-wechat-native:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
|
@ -730,7 +709,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/schemas': link:../schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
|
@ -755,7 +734,7 @@ importers:
|
|||
packages/connector-wechat-web:
|
||||
specifiers:
|
||||
'@jest/types': ^28.1.3
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/schemas': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
'@silverhand/eslint-config': 1.0.0-rc.2
|
||||
|
@ -775,7 +754,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/schemas': link:../schemas
|
||||
'@logto/shared': link:../shared
|
||||
'@silverhand/essentials': 1.1.7
|
||||
|
@ -938,10 +917,10 @@ importers:
|
|||
'@logto/connector-facebook': ^1.0.0-beta.4
|
||||
'@logto/connector-github': ^1.0.0-beta.4
|
||||
'@logto/connector-google': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/connector-sendgrid-email': ^1.0.0-beta.4
|
||||
'@logto/connector-smtp': ^1.0.0-beta.4
|
||||
'@logto/connector-twilio-sms': ^1.0.0-beta.4
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-wechat-native': ^1.0.0-beta.4
|
||||
'@logto/connector-wechat-web': ^1.0.0-beta.4
|
||||
'@logto/phrases': ^1.0.0-beta.4
|
||||
|
@ -1023,10 +1002,10 @@ importers:
|
|||
'@logto/connector-facebook': link:../connector-facebook
|
||||
'@logto/connector-github': link:../connector-github
|
||||
'@logto/connector-google': link:../connector-google
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/connector-sendgrid-email': link:../connector-sendgrid-mail
|
||||
'@logto/connector-smtp': link:../connector-smtp
|
||||
'@logto/connector-twilio-sms': link:../connector-twilio-sms
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-wechat-native': link:../connector-wechat-native
|
||||
'@logto/connector-wechat-web': link:../connector-wechat-web
|
||||
'@logto/phrases': link:../phrases
|
||||
|
@ -1242,7 +1221,7 @@ importers:
|
|||
|
||||
packages/schemas:
|
||||
specifiers:
|
||||
'@logto/connector-types': ^1.0.0-beta.4
|
||||
'@logto/connector-schemas': ^1.0.0-beta.4
|
||||
'@logto/phrases': ^1.0.0-beta.4
|
||||
'@logto/phrases-ui': ^1.0.0-beta.4
|
||||
'@logto/shared': ^1.0.0-beta.4
|
||||
|
@ -1265,7 +1244,7 @@ importers:
|
|||
typescript: ^4.7.4
|
||||
zod: ^3.14.3
|
||||
dependencies:
|
||||
'@logto/connector-types': link:../connector-types
|
||||
'@logto/connector-schemas': link:../connector-schemas
|
||||
'@logto/phrases': link:../phrases
|
||||
'@logto/phrases-ui': link:../phrases-ui
|
||||
'@logto/shared': link:../shared
|
||||
|
|
Loading…
Add table
Reference in a new issue