mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
feat(core): add connector usage to GET APIs response (#4097)
* feat: add GET /connectors/:id/usage to get passwordless connector usage * refactor(core): get usage when possible when transpiling connector
This commit is contained in:
parent
876b0687f6
commit
e0ee44d5d0
4 changed files with 44 additions and 20 deletions
|
@ -32,12 +32,14 @@ export default function socialRoutes<T extends AuthedMeRouter>(
|
|||
const connectors = await getLogtoConnectors();
|
||||
const { socialSignInConnectorTargets } = await findDefaultSignInExperience();
|
||||
|
||||
ctx.body = connectors
|
||||
.filter(
|
||||
({ type, metadata: { target } }) =>
|
||||
type === ConnectorType.Social && socialSignInConnectorTargets.includes(target)
|
||||
)
|
||||
.map((connector) => transpileLogtoConnector(connector));
|
||||
ctx.body = await Promise.all(
|
||||
connectors
|
||||
.filter(
|
||||
({ type, metadata: { target } }) =>
|
||||
type === ConnectorType.Social && socialSignInConnectorTargets.includes(target)
|
||||
)
|
||||
.map(async (connector) => transpileLogtoConnector(connector))
|
||||
);
|
||||
|
||||
return next();
|
||||
});
|
||||
|
|
|
@ -152,7 +152,7 @@ export default function connectorRoutes<T extends AuthedRouter>(
|
|||
}
|
||||
|
||||
const connector = await getLogtoConnectorById(insertConnectorId);
|
||||
ctx.body = transpileLogtoConnector(connector);
|
||||
ctx.body = await transpileLogtoConnector(connector);
|
||||
|
||||
return next();
|
||||
}
|
||||
|
@ -186,7 +186,9 @@ export default function connectorRoutes<T extends AuthedRouter>(
|
|||
? connectors.filter(({ metadata: { target } }) => target === filterTarget)
|
||||
: connectors;
|
||||
|
||||
ctx.body = filteredConnectors.map((connector) => transpileLogtoConnector(connector));
|
||||
ctx.body = await Promise.all(
|
||||
filteredConnectors.map(async (connector) => transpileLogtoConnector(connector))
|
||||
);
|
||||
|
||||
return next();
|
||||
}
|
||||
|
@ -208,7 +210,7 @@ export default function connectorRoutes<T extends AuthedRouter>(
|
|||
// Hide demo connector
|
||||
assertThat(!demoConnectorIds.includes(connector.metadata.id), 'connector.not_found');
|
||||
|
||||
ctx.body = transpileLogtoConnector(connector);
|
||||
ctx.body = await transpileLogtoConnector(connector);
|
||||
|
||||
return next();
|
||||
}
|
||||
|
@ -308,7 +310,7 @@ export default function connectorRoutes<T extends AuthedRouter>(
|
|||
jsonbMode: 'replace',
|
||||
});
|
||||
const connector = await getLogtoConnectorById(id);
|
||||
ctx.body = transpileLogtoConnector(connector);
|
||||
ctx.body = await transpileLogtoConnector(connector);
|
||||
|
||||
return next();
|
||||
}
|
||||
|
|
|
@ -6,31 +6,50 @@ import type { ConnectorFactory } from '@logto/cli/lib/connector/index.js';
|
|||
import { loadConnectorFactories as _loadConnectorFactories } from '@logto/cli/lib/connector/index.js';
|
||||
import { connectorDirectory } from '@logto/cli/lib/constants.js';
|
||||
import { getConnectorPackagesFromDirectory } from '@logto/cli/lib/utils.js';
|
||||
import { demoConnectorIds } from '@logto/connector-kit';
|
||||
import {
|
||||
demoConnectorIds,
|
||||
ConnectorType,
|
||||
type EmailConnector,
|
||||
type SmsConnector,
|
||||
} from '@logto/connector-kit';
|
||||
import type { ConnectorFactoryResponse, ConnectorResponse } from '@logto/schemas';
|
||||
import { findPackage } from '@logto/shared';
|
||||
import { deduplicate, pick } from '@silverhand/essentials';
|
||||
import { conditional, deduplicate, pick, trySafe } from '@silverhand/essentials';
|
||||
|
||||
import { EnvSet } from '#src/env-set/index.js';
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
|
||||
import type { LogtoConnector } from './types.js';
|
||||
import { type LogtoConnector } from './types.js';
|
||||
|
||||
export const transpileLogtoConnector = ({
|
||||
dbEntry,
|
||||
metadata,
|
||||
type,
|
||||
}: LogtoConnector): ConnectorResponse => {
|
||||
const isDemo = demoConnectorIds.includes(dbEntry.connectorId);
|
||||
const { config } = dbEntry;
|
||||
export const isPasswordlessLogtoConnector = (
|
||||
connector: LogtoConnector
|
||||
): connector is LogtoConnector<EmailConnector | SmsConnector> =>
|
||||
connector.type !== ConnectorType.Social;
|
||||
|
||||
export const transpileLogtoConnector = async (
|
||||
connector: LogtoConnector,
|
||||
extraInfo?: Record<string, unknown>
|
||||
): Promise<ConnectorResponse> => {
|
||||
const usagePayload = conditional(
|
||||
/** Should do the check in advance since only passwordless connectors could have `getUsage` method. */
|
||||
isPasswordlessLogtoConnector(connector) &&
|
||||
connector.getUsage && {
|
||||
usage: await trySafe(connector.getUsage(new Date(connector.dbEntry.createdAt))),
|
||||
}
|
||||
);
|
||||
const { dbEntry, metadata, type } = connector;
|
||||
const { config, connectorId: id } = dbEntry;
|
||||
const isDemo = demoConnectorIds.includes(id);
|
||||
|
||||
return {
|
||||
type,
|
||||
...metadata,
|
||||
...pick(dbEntry, 'id', 'connectorId', 'syncProfile', 'metadata'),
|
||||
isDemo,
|
||||
extraInfo,
|
||||
// Hide demo connector config
|
||||
config: isDemo ? {} : config,
|
||||
...usagePayload,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ export const connectorResponseGuard = Connectors.guard
|
|||
type: z.nativeEnum(ConnectorType),
|
||||
isDemo: z.boolean().optional(),
|
||||
extraInfo: z.record(z.unknown()).optional(),
|
||||
usage: z.number().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue