Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvement to the doc service API #20017

Merged
merged 6 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -660,8 +660,15 @@ export default {
return ctx.forbidden();
}

// @ts-expect-error - ids are not in .find
const entities = await documentManager.findMany({ ids, locale }, model);
const entities = await documentManager.findMany(
{
filters: {
id: ids,
},
locale,
},
model
);

if (!entities) {
return ctx.notFound();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,9 @@ describe('history-version service', () => {
contentType: {
uid: 'api::article.article',
},
args: [
{
locale: 'fr',
},
],
params: {
locale: 'fr',
},
};

const next = jest.fn((context) => ({ ...context, documentId: 'document-id' }));
Expand All @@ -154,7 +152,8 @@ describe('history-version service', () => {
expect(next).toHaveBeenCalled();

// Ensure we're only storing the data we need in the database
expect(mockFindOne).toHaveBeenLastCalledWith('document-id', {
expect(mockFindOne).toHaveBeenLastCalledWith({
documentId: 'document-id',
locale: 'fr',
populate: {
component: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,17 @@ const createHistoryService = ({ strapi }: { strapi: Core.Strapi }) => {
return next();
}

// Ignore actions that don't mutate documents
// NOTE: can do type narrowing with array includes
if (
!['create', 'update', 'publish', 'unpublish', 'discardDraft'].includes(context.action)
context.action !== 'create' &&
context.action !== 'update' &&
context.action !== 'publish' &&
context.action !== 'unpublish' &&
context.action !== 'discardDraft'
) {
return next();
}

// @ts-expect-error ContentType is not typed correctly on the context
const contentTypeUid = context.contentType.uid;
// Ignore content types not created by the user
if (!contentTypeUid.startsWith('api::')) {
Expand All @@ -155,19 +158,15 @@ const createHistoryService = ({ strapi }: { strapi: Core.Strapi }) => {

const documentContext =
context.action === 'create'
? // @ts-expect-error The context args are not typed correctly
{ documentId: result.documentId, locale: context.args[0]?.locale }
: // @ts-expect-error The context args are not typed correctly
{ documentId: context.args[0], locale: context.args[1]?.locale };
? { documentId: result.documentId, locale: context.params?.locale }
: { documentId: context.params.documentId, locale: context.params?.locale };

const locale = documentContext.locale ?? (await localesService.getDefaultLocale());
const document = await strapi
.documents(contentTypeUid)
.findOne(documentContext.documentId, {
locale,
populate: getDeepPopulate(contentTypeUid),
});

const document = await strapi.documents(contentTypeUid).findOne({
documentId: documentContext.documentId,
locale,
populate: getDeepPopulate(contentTypeUid),
});
const status = await getVersionStatus(contentTypeUid, document);

/**
Expand Down Expand Up @@ -309,7 +308,7 @@ const createHistoryService = ({ strapi }: { strapi: Core.Strapi }) => {
if ('documentId' in entry) {
relatedEntry = await strapi
.documents(attributeSchema.target)
.findOne(entry.documentId, { locale: entry.locale || undefined });
.findOne({ documentId: entry.documentId, locale: entry.locale || undefined });
}
// For media assets, only the id is available, double check that we have it
} else if ('id' in entry) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { sumDraftCounts } from './utils/draft';
import { ALLOWED_WEBHOOK_EVENTS } from '../constants';

type DocService = Modules.Documents.ServiceInstance;
type DocServiceParams<TAction extends keyof DocService> = Parameters<DocService[TAction]>;
type DocServiceParams<TAction extends keyof DocService> = Parameters<DocService[TAction]>[0];
Marc-Roig marked this conversation as resolved.
Show resolved Hide resolved
export type Document = Modules.Documents.Result<UID.ContentType>;

const { ApplicationError } = errors;
Expand Down Expand Up @@ -38,8 +38,12 @@ const emitEvent = async (uid: UID.ContentType, event: string, document: Document

const documentManager = ({ strapi }: { strapi: Core.Strapi }) => {
return {
async findOne(id: string, uid: UID.CollectionType, opts: DocServiceParams<'findOne'>[1] = {}) {
return strapi.documents(uid).findOne(id, opts);
async findOne(
id: string,
uid: UID.CollectionType,
opts: Omit<DocServiceParams<'findOne'>, 'documentId'> = {}
) {
return strapi.documents(uid).findOne({ ...opts, documentId: id });
},

/**
Expand Down Expand Up @@ -72,12 +76,12 @@ const documentManager = ({ strapi }: { strapi: Core.Strapi }) => {
return strapi.db.query(uid).findMany({ populate: opts.populate, where });
},

async findMany(opts: DocServiceParams<'findMany'>[0], uid: UID.CollectionType) {
async findMany(opts: DocServiceParams<'findMany'>, uid: UID.CollectionType) {
const params = { ...opts, populate: getDeepPopulate(uid) } as typeof opts;
return strapi.documents(uid).findMany(params);
},

async findPage(opts: DocServiceParams<'findMany'>[0], uid: UID.CollectionType) {
async findPage(opts: DocServiceParams<'findMany'>, uid: UID.CollectionType) {
// Pagination
const page = Number(opts?.page) || 1;
const pageSize = Number(opts?.pageSize) || 10;
Expand All @@ -98,7 +102,7 @@ const documentManager = ({ strapi }: { strapi: Core.Strapi }) => {
};
},

async create(uid: UID.CollectionType, opts: DocServiceParams<'create'>[0] = {} as any) {
async create(uid: UID.CollectionType, opts: DocServiceParams<'create'> = {} as any) {
const populate = opts.populate ?? (await buildDeepPopulate(uid));
const params = { ...opts, status: 'draft' as const, populate };

Expand All @@ -108,13 +112,13 @@ const documentManager = ({ strapi }: { strapi: Core.Strapi }) => {
async update(
id: Modules.Documents.ID,
uid: UID.CollectionType,
opts: DocServiceParams<'update'>[1] = {} as any
opts: Omit<DocServiceParams<'update'>, 'documentId'> = {} as any
) {
const publishData = pipe(omitPublishedAtField, omitIdField)(opts.data || {});
const populate = opts.populate ?? (await buildDeepPopulate(uid));
const params = { ...opts, data: publishData, populate, status: 'draft' };

return strapi.documents(uid).update(id, params);
return strapi.documents(uid).update({ ...params, documentId: id });
},

async clone(
Expand All @@ -133,7 +137,7 @@ const documentManager = ({ strapi }: { strapi: Core.Strapi }) => {

return strapi
.documents(uid)
.clone(id, params)
.clone({ ...params, documentId: id })
.then((result) => result?.versions.at(0));
},

Expand All @@ -155,20 +159,24 @@ const documentManager = ({ strapi }: { strapi: Core.Strapi }) => {
async delete(
id: Modules.Documents.ID,
uid: UID.CollectionType,
opts: DocServiceParams<'delete'>[1] = {} as any
opts: Omit<DocServiceParams<'delete'>, 'documentId'> = {} as any
) {
const populate = await buildDeepPopulate(uid);

await strapi.documents(uid).delete(id, { ...opts, populate });
await strapi.documents(uid).delete({
...opts,
documentId: id,
populate,
});
return {};
},

// FIXME: handle relations
async deleteMany(opts: DocServiceParams<'findMany'>[0], uid: UID.CollectionType) {
async deleteMany(opts: DocServiceParams<'findMany'>, uid: UID.CollectionType) {
const docs = await strapi.documents(uid).findMany(opts);

for (const doc of docs) {
await strapi.documents!(uid).delete(doc.documentId);
await strapi.documents!(uid).delete({ documentId: doc.documentId });
}

return { count: docs.length };
Expand All @@ -177,14 +185,14 @@ const documentManager = ({ strapi }: { strapi: Core.Strapi }) => {
async publish(
id: Modules.Documents.ID,
uid: UID.CollectionType,
opts: DocServiceParams<'publish'>[1] = {} as any
opts: Omit<DocServiceParams<'publish'>, 'documentId'> = {} as any
) {
const populate = await buildDeepPopulate(uid);
const params = { ...opts, populate };

return strapi
.documents(uid)
.publish(id, params)
.publish({ ...params, documentId: id })
.then((result) => result?.versions.at(0));
},

Expand Down Expand Up @@ -272,28 +280,28 @@ const documentManager = ({ strapi }: { strapi: Core.Strapi }) => {
async unpublish(
id: Modules.Documents.ID,
uid: UID.CollectionType,
opts: DocServiceParams<'unpublish'>[1] = {} as any
opts: Omit<DocServiceParams<'unpublish'>, 'documentId'> = {} as any
) {
const populate = await buildDeepPopulate(uid);
const params = { ...opts, populate };

return strapi
.documents(uid)
.unpublish(id, params)
.unpublish({ ...params, documentId: id })
.then((result) => result?.versions.at(0));
},

async discardDraft(
id: Modules.Documents.ID,
uid: UID.CollectionType,
opts: DocServiceParams<'discardDraft'>[1] = {} as any
opts: Omit<DocServiceParams<'discardDraft'>, 'documentId'> = {} as any
) {
const populate = await buildDeepPopulate(uid);
const params = { ...opts, populate };

return strapi
.documents(uid)
.discardDraft(id, params)
.discardDraft({ ...params, documentId: id })
.then((result) => result?.versions.at(0));
},

Expand All @@ -303,7 +311,7 @@ const documentManager = ({ strapi }: { strapi: Core.Strapi }) => {
if (!hasRelations) {
return 0;
}
const document = await strapi.documents(uid).findOne(id, { populate, locale });
const document = await strapi.documents(uid).findOne({ documentId: id, populate, locale });
if (!document) {
throw new ApplicationError(
`Unable to count draft relations, document with id ${id} and locale ${locale} not found`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ describe('Default Service', () => {

expect(dbInstance.findOne).toHaveBeenCalledWith();

expect(documentService.update).toHaveBeenCalledWith(1, {
expect(documentService.update).toHaveBeenCalledWith({
documentId: 1,
data: input,
status: 'published',
});
Expand Down Expand Up @@ -137,7 +138,7 @@ describe('Default Service', () => {

expect(dbInstance.findOne).toHaveBeenCalledWith();

expect(documentService.delete).toHaveBeenCalledWith(1, { status: 'published' });
expect(documentService.delete).toHaveBeenCalledWith({ documentId: 1, status: 'published' });
});
});
});
Expand Down
19 changes: 14 additions & 5 deletions packages/core/core/src/core-api/service/collection-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ export class CollectionTypeService
findOne(documentId: Modules.Documents.ID, params = {}) {
const { uid } = this.contentType;

return strapi.documents(uid).findOne(documentId, this.getFetchParams(params));
return strapi.documents(uid).findOne({
...this.getFetchParams(params),
documentId,
});
}

async create(params = { data: {} }) {
Expand All @@ -59,16 +62,22 @@ export class CollectionTypeService
return strapi.documents(uid).create(this.getFetchParams(params));
}

update(docId: Modules.Documents.ID, params = { data: {} }) {
update(documentId: Modules.Documents.ID, params = { data: {} }) {
const { uid } = this.contentType;

return strapi.documents(uid).update(docId, this.getFetchParams(params));
return strapi.documents(uid).update({
...this.getFetchParams(params),
documentId,
});
}

async delete(docId: Modules.Documents.ID, params = {}) {
async delete(documentId: Modules.Documents.ID, params = {}) {
const { uid } = this.contentType;

return strapi.documents(uid).delete(docId, this.getFetchParams(params));
return strapi.documents(uid).delete({
...this.getFetchParams(params),
documentId,
});
}
}

Expand Down
10 changes: 8 additions & 2 deletions packages/core/core/src/core-api/service/single-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ export class SingleTypeService extends CoreService implements Core.CoreAPI.Servi
const documentId = await this.getDocumentId();

if (documentId) {
return strapi.documents(uid).update(documentId, this.getFetchParams(params));
return strapi.documents(uid).update({
...this.getFetchParams(params),
documentId,
});
}

return strapi.documents(uid).create(this.getFetchParams(params));
Expand All @@ -43,7 +46,10 @@ export class SingleTypeService extends CoreService implements Core.CoreAPI.Servi
const documentId = await this.getDocumentId();
if (!documentId) return { deletedEntries: 0 };

return strapi.documents(uid).delete(documentId, this.getFetchParams(params));
return strapi.documents(uid).delete({
...this.getFetchParams(params),
documentId,
});
}
}

Expand Down
6 changes: 3 additions & 3 deletions packages/core/core/src/services/document-service/common.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { UID, Modules } from '@strapi/types';

export type RepositoryFactoryMethod = <TCollectionTypeUID extends UID.CollectionType>(
uid: TCollectionTypeUID
) => Modules.Documents.ServiceInstance<TCollectionTypeUID>;
export type RepositoryFactoryMethod = <TContentTypeUID extends UID.ContentType>(
uid: TContentTypeUID
) => Modules.Documents.ServiceInstance<TContentTypeUID>;

export const wrapInTransaction = (fn: (...args: any) => any) => {
return (...args: any[]) => strapi.db.transaction?.(() => fn(...args));
Expand Down