mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor(core): migrate resource library to factory mode
This commit is contained in:
parent
f7c08332a1
commit
0442efeb60
5 changed files with 73 additions and 53 deletions
|
@ -1,19 +1,19 @@
|
|||
import { createMockUtils } from '@logto/shared/esm';
|
||||
|
||||
import { mockResource, mockResource2, mockResource3, mockScope } from '#src/__mocks__/index.js';
|
||||
import { MockQueries } from '#src/test-utils/tenant.js';
|
||||
|
||||
const { jest } = import.meta;
|
||||
const { mockEsmWithActual } = createMockUtils(jest);
|
||||
|
||||
const { findScopesByResourceIds } = await mockEsmWithActual('#src/queries/scope.js', () => ({
|
||||
findScopesByResourceIds: jest.fn(async () => [
|
||||
{ ...mockScope, id: '1', resourceId: mockResource.id },
|
||||
{ ...mockScope, id: '2', resourceId: mockResource.id },
|
||||
{ ...mockScope, id: '3', resourceId: mockResource2.id },
|
||||
]),
|
||||
}));
|
||||
const findScopesByResourceIds = jest.fn(async () => [
|
||||
{ ...mockScope, id: '1', resourceId: mockResource.id },
|
||||
{ ...mockScope, id: '2', resourceId: mockResource.id },
|
||||
{ ...mockScope, id: '3', resourceId: mockResource2.id },
|
||||
]);
|
||||
|
||||
const { attachScopesToResources } = await import('./resource.js');
|
||||
const { createResourceLibrary } = await import('./resource.js');
|
||||
|
||||
const { attachScopesToResources } = createResourceLibrary(
|
||||
new MockQueries({ scopes: { findScopesByResourceIds } })
|
||||
);
|
||||
|
||||
describe('attachScopesToResources', () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
import type { Resource, ResourceResponse } from '@logto/schemas';
|
||||
|
||||
import { findScopesByResourceIds } from '#src/queries/scope.js';
|
||||
import type Queries from '#src/tenants/Queries.js';
|
||||
|
||||
export const attachScopesToResources = async (
|
||||
resources: readonly Resource[]
|
||||
): Promise<ResourceResponse[]> => {
|
||||
const resourceIds = resources.map(({ id }) => id);
|
||||
const scopes = await findScopesByResourceIds(resourceIds);
|
||||
export const createResourceLibrary = (queries: Queries) => {
|
||||
const { findScopesByResourceIds } = queries.scopes;
|
||||
|
||||
return resources.map((resource) => ({
|
||||
...resource,
|
||||
scopes: scopes.filter(({ resourceId }) => resourceId === resource.id),
|
||||
}));
|
||||
const attachScopesToResources = async (
|
||||
resources: readonly Resource[]
|
||||
): Promise<ResourceResponse[]> => {
|
||||
const resourceIds = resources.map(({ id }) => id);
|
||||
const scopes = await findScopesByResourceIds(resourceIds);
|
||||
|
||||
return resources.map((resource) => ({
|
||||
...resource,
|
||||
scopes: scopes.filter(({ resourceId }) => resourceId === resource.id),
|
||||
}));
|
||||
};
|
||||
|
||||
return { attachScopesToResources };
|
||||
};
|
||||
|
|
|
@ -2,21 +2,14 @@ import type { Resource, CreateResource } from '@logto/schemas';
|
|||
import { pickDefault, createMockUtils } from '@logto/shared/esm';
|
||||
|
||||
import { mockResource, mockScope } from '#src/__mocks__/index.js';
|
||||
import { MockTenant } from '#src/test-utils/tenant.js';
|
||||
import { createRequester } from '#src/utils/test-utils.js';
|
||||
|
||||
const { jest } = import.meta;
|
||||
|
||||
const { mockEsm, mockEsmWithActual } = createMockUtils(jest);
|
||||
const { mockEsm } = createMockUtils(jest);
|
||||
|
||||
await mockEsmWithActual('#src/libraries/resource.js', () => ({
|
||||
attachScopesToResources: async (resources: Resource[]) =>
|
||||
resources.map((resource) => ({
|
||||
...resource,
|
||||
scopes: [],
|
||||
})),
|
||||
}));
|
||||
|
||||
const { findResourceById } = mockEsm('#src/queries/resource.js', () => ({
|
||||
const resources = {
|
||||
findTotalNumberOfResources: async () => ({ count: 10 }),
|
||||
findAllResources: async (): Promise<Resource[]> => [mockResource],
|
||||
findResourceById: jest.fn(async (): Promise<Resource> => mockResource),
|
||||
|
@ -30,26 +23,40 @@ const { findResourceById } = mockEsm('#src/queries/resource.js', () => ({
|
|||
}),
|
||||
deleteResourceById: jest.fn(),
|
||||
findScopesByResourceId: async () => [mockScope],
|
||||
}));
|
||||
};
|
||||
const { findResourceById } = resources;
|
||||
|
||||
const { insertScope, updateScopeById } = await mockEsmWithActual('#src/queries/scope.js', () => ({
|
||||
const scopes = {
|
||||
findScopesByResourceId: async () => [mockScope],
|
||||
findScopes: async () => [mockScope],
|
||||
insertScope: jest.fn(async () => mockScope),
|
||||
updateScopeById: jest.fn(async () => mockScope),
|
||||
deleteScopeById: jest.fn(),
|
||||
findScopeByNameAndResourceId: jest.fn(),
|
||||
}));
|
||||
};
|
||||
const { insertScope, updateScopeById } = scopes;
|
||||
|
||||
const libraries = {
|
||||
resources: {
|
||||
attachScopesToResources: async (resources: readonly Resource[]) =>
|
||||
resources.map((resource) => ({
|
||||
...resource,
|
||||
scopes: [],
|
||||
})),
|
||||
},
|
||||
};
|
||||
|
||||
mockEsm('@logto/core-kit', () => ({
|
||||
// eslint-disable-next-line unicorn/consistent-function-scoping
|
||||
buildIdGenerator: () => () => 'randomId',
|
||||
}));
|
||||
|
||||
const tenantContext = new MockTenant(undefined, { scopes, resources }, libraries);
|
||||
|
||||
const resourceRoutes = await pickDefault(import('./resource.js'));
|
||||
|
||||
describe('resource routes', () => {
|
||||
const resourceRequest = createRequester({ authedRoutes: resourceRoutes });
|
||||
const resourceRequest = createRequester({ authedRoutes: resourceRoutes, tenantContext });
|
||||
|
||||
it('GET /resources', async () => {
|
||||
const response = await resourceRequest.get('/resources');
|
||||
|
|
|
@ -5,25 +5,8 @@ import { object, string } from 'zod';
|
|||
|
||||
import { isTrue } from '#src/env-set/parameters.js';
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { attachScopesToResources } from '#src/libraries/resource.js';
|
||||
import koaGuard from '#src/middleware/koa-guard.js';
|
||||
import koaPagination from '#src/middleware/koa-pagination.js';
|
||||
import {
|
||||
findTotalNumberOfResources,
|
||||
findAllResources,
|
||||
findResourceById,
|
||||
insertResource,
|
||||
updateResourceById,
|
||||
deleteResourceById,
|
||||
} from '#src/queries/resource.js';
|
||||
import {
|
||||
countScopes,
|
||||
deleteScopeById,
|
||||
findScopeByNameAndResourceId,
|
||||
findScopes,
|
||||
insertScope,
|
||||
updateScopeById,
|
||||
} from '#src/queries/scope.js';
|
||||
import assertThat from '#src/utils/assert-that.js';
|
||||
import { parseSearchParamsForSearch } from '#src/utils/search.js';
|
||||
|
||||
|
@ -32,7 +15,29 @@ import type { AuthedRouter, RouterInitArgs } from './types.js';
|
|||
const resourceId = buildIdGenerator(21);
|
||||
const scopeId = resourceId;
|
||||
|
||||
export default function resourceRoutes<T extends AuthedRouter>(...[router]: RouterInitArgs<T>) {
|
||||
export default function resourceRoutes<T extends AuthedRouter>(
|
||||
...[router, { queries, libraries }]: RouterInitArgs<T>
|
||||
) {
|
||||
const {
|
||||
resources: {
|
||||
findTotalNumberOfResources,
|
||||
findAllResources,
|
||||
findResourceById,
|
||||
insertResource,
|
||||
updateResourceById,
|
||||
deleteResourceById,
|
||||
},
|
||||
scopes: {
|
||||
countScopes,
|
||||
deleteScopeById,
|
||||
findScopes,
|
||||
findScopeByNameAndResourceId,
|
||||
insertScope,
|
||||
updateScopeById,
|
||||
},
|
||||
} = queries;
|
||||
const { attachScopesToResources } = libraries.resources;
|
||||
|
||||
router.get(
|
||||
'/resources',
|
||||
koaPagination({ isOptional: true }),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { createConnectorLibrary } from '#src/libraries/connector.js';
|
||||
import { createPhraseLibrary } from '#src/libraries/phrase.js';
|
||||
import { createResourceLibrary } from '#src/libraries/resource.js';
|
||||
import { createSignInExperienceLibrary } from '#src/libraries/sign-in-experience/index.js';
|
||||
import { createUserLibrary } from '#src/libraries/user.js';
|
||||
|
||||
|
@ -10,6 +11,7 @@ export default class Libraries {
|
|||
users = createUserLibrary(this.queries);
|
||||
signInExperiences = createSignInExperienceLibrary(this.queries, this.connectors);
|
||||
phrases = createPhraseLibrary(this.queries);
|
||||
resources = createResourceLibrary(this.queries);
|
||||
|
||||
constructor(public readonly queries: Queries) {}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue