mirror of
https://github.com/strapi/strapi.git
synced 2025-12-28 07:33:17 +00:00
feat(content-releases): add findOne endpoint (#18821)
This commit is contained in:
parent
f9fb2e7c49
commit
30e8a6321d
@ -56,6 +56,11 @@ packages/core/content-releases/server/src/routes/release.ts
|
||||
}
|
||||
```
|
||||
|
||||
**Get a single release**
|
||||
|
||||
- method: `GET`
|
||||
- endpoint: `/content-releases/:id`
|
||||
|
||||
**Create a release**:
|
||||
|
||||
- method: `POST`
|
||||
@ -72,11 +77,10 @@ packages/core/content-releases/server/src/routes/release.ts
|
||||
**Create a release action**
|
||||
|
||||
- method: `POST`
|
||||
- endpoint: `/content-releases/release-actions/`
|
||||
- endpoint: `/content-releases/:releaseId/actions`
|
||||
- body:
|
||||
```ts
|
||||
{
|
||||
releaseId: number,
|
||||
entry: {
|
||||
id: number,
|
||||
contentType: string
|
||||
|
||||
@ -46,6 +46,7 @@ export const AddReleaseDialog = ({ handleClose }: AddReleaseDialogProps) => {
|
||||
});
|
||||
|
||||
if ('data' in response) {
|
||||
// When the response returns an object with 'data', handle success
|
||||
toggleNotification({
|
||||
type: 'success',
|
||||
message: formatMessage({
|
||||
@ -53,13 +54,16 @@ export const AddReleaseDialog = ({ handleClose }: AddReleaseDialogProps) => {
|
||||
defaultMessage: 'Release created.',
|
||||
}),
|
||||
});
|
||||
|
||||
push(`/plugins/content-releases/${response.data.data.id}`);
|
||||
} else if (isErrorAxiosError(response.error)) {
|
||||
// When the response returns an object with 'error', handle axios error
|
||||
toggleNotification({
|
||||
type: 'warning',
|
||||
message: formatAPIError(response.error),
|
||||
});
|
||||
} else {
|
||||
// Otherwise, the response returns an object with 'error', handle a generic error
|
||||
toggleNotification({
|
||||
type: 'warning',
|
||||
message: formatMessage({ id: 'notification.error', defaultMessage: 'An error occurred' }),
|
||||
|
||||
@ -3,7 +3,11 @@ import { createApi } from '@reduxjs/toolkit/query/react';
|
||||
import { pluginId } from '../pluginId';
|
||||
import { axiosBaseQuery } from '../utils/data';
|
||||
|
||||
import type { CreateRelease, GetAllReleases } from '../../../shared/contracts/releases';
|
||||
import type {
|
||||
CreateRelease,
|
||||
GetReleases,
|
||||
ReleaseDataResponse,
|
||||
} from '../../../shared/contracts/releases';
|
||||
|
||||
const releaseApi = createApi({
|
||||
reducerPath: pluginId,
|
||||
@ -11,7 +15,7 @@ const releaseApi = createApi({
|
||||
tagTypes: ['Releases'],
|
||||
endpoints: (build) => {
|
||||
return {
|
||||
getRelease: build.query<GetAllReleases.Response, undefined>({
|
||||
getRelease: build.query<GetReleases.Response, undefined>({
|
||||
query() {
|
||||
return {
|
||||
url: '/content-releases',
|
||||
@ -20,7 +24,7 @@ const releaseApi = createApi({
|
||||
},
|
||||
providesTags: ['Releases'],
|
||||
}),
|
||||
createRelease: build.mutation<CreateRelease.Response, CreateRelease.Request['body']>({
|
||||
createRelease: build.mutation<{ data: ReleaseDataResponse }, CreateRelease.Request['body']>({
|
||||
query(data) {
|
||||
return {
|
||||
url: '/content-releases',
|
||||
|
||||
@ -20,22 +20,22 @@ const axiosBaseQuery = async <TData = any, TSend = any>({
|
||||
|
||||
if (method === 'POST') {
|
||||
const res = await post<TData, AxiosResponse<TData>, TSend>(url, data, config);
|
||||
return res;
|
||||
return { data: res.data };
|
||||
}
|
||||
if (method === 'DELETE') {
|
||||
const res = await del<TData, AxiosResponse<TData>, TSend>(url, config);
|
||||
return res;
|
||||
return { data: res.data };
|
||||
}
|
||||
if (method === 'PUT') {
|
||||
const res = await put<TData, AxiosResponse<TData>, TSend>(url, data, config);
|
||||
return res;
|
||||
return { data: res.data };
|
||||
}
|
||||
|
||||
/**
|
||||
* Default is GET.
|
||||
*/
|
||||
const res = await get<TData, AxiosResponse<TData>, TSend>(url, config);
|
||||
return res;
|
||||
return { data: res.data };
|
||||
} catch (error) {
|
||||
const err = error as AxiosError;
|
||||
|
||||
|
||||
@ -1,9 +1,16 @@
|
||||
{
|
||||
"extends": "./admin/tsconfig.json",
|
||||
"include": ["./admin/src", "./admin/custom.d.ts", "./shared"],
|
||||
"exclude": ["tests", "**/*.test.*"],
|
||||
"include": [
|
||||
"./admin/src",
|
||||
"./admin/custom.d.ts",
|
||||
"./shared"
|
||||
],
|
||||
"exclude": [
|
||||
"tests",
|
||||
"**/*.test.*"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"outDir": "./dist"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,6 @@
|
||||
"@tests/*": ["./tests/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src", "../shared", "tests", "custom.d.ts"],
|
||||
"include": ["./src", "../shared", "tests", "custom.d.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import releaseActionController from '../release-action';
|
||||
|
||||
describe('release-action controller', () => {
|
||||
describe('Release Action controller', () => {
|
||||
describe('create', () => {
|
||||
beforeEach(() => {
|
||||
global.strapi = {
|
||||
@ -48,10 +48,12 @@ describe('release-action controller', () => {
|
||||
state: {
|
||||
user: {},
|
||||
},
|
||||
params: {
|
||||
id: 1,
|
||||
},
|
||||
request: {
|
||||
// Mock missing type property
|
||||
body: {
|
||||
releaseId: 1,
|
||||
entry: {
|
||||
id: 1,
|
||||
contentType: 'api::category.category',
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import type Koa from 'koa';
|
||||
import { validateReleaseActionCreateSchema } from './validation/release-action';
|
||||
import { ReleaseActionCreateArgs } from '../../../shared/types';
|
||||
import type { CreateReleaseAction } from '../../../shared/contracts/release-actions';
|
||||
import { getService } from '../utils';
|
||||
|
||||
const releaseActionController = {
|
||||
async create(ctx: Koa.Context) {
|
||||
const releaseActionArgs: ReleaseActionCreateArgs = ctx.request.body;
|
||||
const releaseId: CreateReleaseAction.Request['params']['releaseId'] = ctx.params.releaseId;
|
||||
const releaseActionArgs: CreateReleaseAction.Request['body'] = ctx.request.body;
|
||||
|
||||
await validateReleaseActionCreateSchema(releaseActionArgs);
|
||||
|
||||
const releaseService = getService('release', { strapi });
|
||||
const { releaseId, ...action } = releaseActionArgs;
|
||||
const releaseAction = await releaseService.createAction(releaseId, action);
|
||||
const releaseAction = await releaseService.createAction(releaseId, releaseActionArgs);
|
||||
|
||||
ctx.body = {
|
||||
data: releaseAction,
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
import type Koa from 'koa';
|
||||
import { errors } from '@strapi/utils';
|
||||
import { RELEASE_MODEL_UID } from '../constants';
|
||||
import { validateCreateRelease } from './validation/release';
|
||||
import { ReleaseCreateArgs, UserInfo } from '../../../shared/types';
|
||||
import type { CreateRelease, GetRelease, Release } from '../../../shared/contracts/releases';
|
||||
import type { UserInfo } from '../../../shared/types';
|
||||
import { getService } from '../utils';
|
||||
|
||||
type ReleaseWithPopulatedActions = Release & { actions: { count: number } };
|
||||
|
||||
const releaseController = {
|
||||
async findMany(ctx: Koa.Context) {
|
||||
const permissionsManager = strapi.admin.services.permission.createPermissionsManager({
|
||||
@ -14,12 +18,54 @@ const releaseController = {
|
||||
await permissionsManager.validateQuery(ctx.query);
|
||||
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
||||
|
||||
ctx.body = await getService('release', { strapi }).findMany(query);
|
||||
const { results, pagination } = await getService('release', { strapi }).findMany(query);
|
||||
|
||||
// Format the data object
|
||||
const data = results.map((release: ReleaseWithPopulatedActions) => {
|
||||
const { actions, ...releaseData } = release;
|
||||
|
||||
return {
|
||||
...releaseData,
|
||||
actions: {
|
||||
meta: {
|
||||
count: actions.count,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
ctx.body = { data, pagination };
|
||||
},
|
||||
|
||||
async findOne(ctx: Koa.Context) {
|
||||
const id: GetRelease.Request['params']['id'] = ctx.params.id;
|
||||
|
||||
const result = (await getService('release', { strapi }).findOne(
|
||||
Number(id)
|
||||
)) as ReleaseWithPopulatedActions | null;
|
||||
|
||||
if (!result) {
|
||||
throw new errors.NotFoundError(`Release not found for id: ${id}`);
|
||||
}
|
||||
|
||||
const { actions, ...release } = result;
|
||||
|
||||
// Format the data object
|
||||
const data = {
|
||||
...release,
|
||||
actions: {
|
||||
meta: {
|
||||
count: actions.count,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
ctx.body = { data };
|
||||
},
|
||||
|
||||
async create(ctx: Koa.Context) {
|
||||
const user: UserInfo = ctx.state.user;
|
||||
const releaseArgs: ReleaseCreateArgs = ctx.request.body;
|
||||
const releaseArgs: CreateRelease.Request['body'] = ctx.request.body;
|
||||
|
||||
await validateCreateRelease(releaseArgs);
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { yup, validateYupSchema } from '@strapi/utils';
|
||||
|
||||
const releaseActionCreateSchema = yup.object().shape({
|
||||
releaseId: yup.number().required(),
|
||||
entry: yup
|
||||
.object()
|
||||
.shape({
|
||||
|
||||
@ -3,7 +3,7 @@ export default {
|
||||
routes: [
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/release-actions',
|
||||
path: '/:releaseId/actions',
|
||||
handler: 'release-action.create',
|
||||
config: {
|
||||
policies: [
|
||||
|
||||
@ -33,5 +33,21 @@ export default {
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
path: '/:id',
|
||||
handler: 'release.findOne',
|
||||
config: {
|
||||
policies: [
|
||||
'admin::isAuthenticatedAdmin',
|
||||
{
|
||||
name: 'admin::hasPermissions',
|
||||
config: {
|
||||
actions: ['plugin::content-releases.read'],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ReleaseActionCreateArgs } from '../../../../shared/types';
|
||||
import type { CreateReleaseAction } from '../../../../shared/contracts/release-actions';
|
||||
import createReleaseValidationService from '../validation';
|
||||
|
||||
const baseStrapiMock = {
|
||||
@ -10,22 +10,13 @@ const baseStrapiMock = {
|
||||
contentType: jest.fn(),
|
||||
};
|
||||
|
||||
describe('releaseValidation service', () => {
|
||||
describe('Release Validation service', () => {
|
||||
describe('validateEntryContentType', () => {
|
||||
it('throws an error if the content type does not exist', () => {
|
||||
// @ts-expect-error Ignore missing properties
|
||||
const releaseValidationService = createReleaseValidationService({ strapi: baseStrapiMock });
|
||||
|
||||
const mockReleaseAction: ReleaseActionCreateArgs = {
|
||||
releaseId: 1,
|
||||
entry: {
|
||||
id: 1,
|
||||
contentType: 'api::plop.plop',
|
||||
},
|
||||
type: 'publish',
|
||||
};
|
||||
|
||||
expect(() => releaseValidationService.validateEntryContentType(mockReleaseAction)).toThrow(
|
||||
expect(() => releaseValidationService.validateEntryContentType('api::plop.plop')).toThrow(
|
||||
'No content type found for uid api::plop.plop'
|
||||
);
|
||||
});
|
||||
@ -40,16 +31,9 @@ describe('releaseValidation service', () => {
|
||||
// @ts-expect-error Ignore missing properties
|
||||
const releaseValidationService = createReleaseValidationService({ strapi: strapiMock });
|
||||
|
||||
const mockReleaseAction: ReleaseActionCreateArgs = {
|
||||
releaseId: 1,
|
||||
entry: {
|
||||
id: 1,
|
||||
contentType: 'api::category.category',
|
||||
},
|
||||
type: 'publish',
|
||||
};
|
||||
|
||||
expect(() => releaseValidationService.validateEntryContentType(mockReleaseAction)).toThrow(
|
||||
expect(() =>
|
||||
releaseValidationService.validateEntryContentType('api::category.category')
|
||||
).toThrow(
|
||||
'Content type with uid api::category.category does not have draftAndPublish enabled'
|
||||
);
|
||||
});
|
||||
@ -71,8 +55,7 @@ describe('releaseValidation service', () => {
|
||||
// @ts-expect-error Ignore missing properties
|
||||
const releaseValidationService = createReleaseValidationService({ strapi: strapiMock });
|
||||
|
||||
const mockReleaseAction: ReleaseActionCreateArgs = {
|
||||
releaseId: 1,
|
||||
const mockReleaseAction: CreateReleaseAction.Request['body'] = {
|
||||
entry: {
|
||||
id: 1,
|
||||
contentType: 'api::category.category',
|
||||
@ -80,9 +63,9 @@ describe('releaseValidation service', () => {
|
||||
type: 'publish',
|
||||
};
|
||||
|
||||
expect(() => releaseValidationService.validateUniqueEntry(mockReleaseAction)).rejects.toThrow(
|
||||
'No release found for id 1'
|
||||
);
|
||||
expect(() =>
|
||||
releaseValidationService.validateUniqueEntry(1, mockReleaseAction)
|
||||
).rejects.toThrow('No release found for id 1');
|
||||
});
|
||||
|
||||
it('throws an error if a contentType entry already exists in the release', () => {
|
||||
@ -109,8 +92,7 @@ describe('releaseValidation service', () => {
|
||||
// @ts-expect-error Ignore missing properties
|
||||
const releaseValidationService = createReleaseValidationService({ strapi: strapiMock });
|
||||
|
||||
const mockReleaseAction: ReleaseActionCreateArgs = {
|
||||
releaseId: 1,
|
||||
const mockReleaseAction: CreateReleaseAction.Request['body'] = {
|
||||
entry: {
|
||||
id: 1,
|
||||
contentType: 'api::category.category',
|
||||
@ -118,7 +100,9 @@ describe('releaseValidation service', () => {
|
||||
type: 'publish',
|
||||
};
|
||||
|
||||
expect(() => releaseValidationService.validateUniqueEntry(mockReleaseAction)).rejects.toThrow(
|
||||
expect(() =>
|
||||
releaseValidationService.validateUniqueEntry(1, mockReleaseAction)
|
||||
).rejects.toThrow(
|
||||
'Entry with id 1 and contentType api::category.category already exists in release with id 1'
|
||||
);
|
||||
});
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
import { setCreatorFields } from '@strapi/utils';
|
||||
import type { LoadedStrapi } from '@strapi/types';
|
||||
import { RELEASE_ACTION_MODEL_UID, RELEASE_MODEL_UID } from '../constants';
|
||||
import type { ReleaseCreateArgs, UserInfo, ReleaseActionCreateArgs } from '../../../shared/types';
|
||||
import type { GetReleases, CreateRelease, GetRelease } from '../../../shared/contracts/releases';
|
||||
import type { CreateReleaseAction } from '../../../shared/contracts/release-actions';
|
||||
import type { UserInfo } from '../../../shared/types';
|
||||
import { getService } from '../utils';
|
||||
|
||||
const createReleaseService = ({ strapi }: { strapi: LoadedStrapi }) => ({
|
||||
async create(releaseData: ReleaseCreateArgs, { user }: { user: UserInfo }) {
|
||||
async create(releaseData: CreateRelease.Request['body'], { user }: { user: UserInfo }) {
|
||||
const releaseWithCreatorFields = await setCreatorFields({ user })(releaseData);
|
||||
|
||||
const release = await strapi.entityService.create(RELEASE_MODEL_UID, {
|
||||
return strapi.entityService.create(RELEASE_MODEL_UID, {
|
||||
data: releaseWithCreatorFields,
|
||||
});
|
||||
|
||||
return release;
|
||||
},
|
||||
async findMany(query: Record<string, unknown>) {
|
||||
const { results, pagination } = await strapi.entityService.findPage(RELEASE_MODEL_UID, {
|
||||
findMany(query?: GetReleases.Request['query']) {
|
||||
return strapi.entityService.findPage(RELEASE_MODEL_UID, {
|
||||
...query,
|
||||
populate: {
|
||||
actions: {
|
||||
@ -24,23 +24,28 @@ const createReleaseService = ({ strapi }: { strapi: LoadedStrapi }) => ({
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
data: results,
|
||||
pagination,
|
||||
};
|
||||
},
|
||||
findOne(id: GetRelease.Request['params']['id']) {
|
||||
return strapi.entityService.findOne(RELEASE_MODEL_UID, id, {
|
||||
populate: {
|
||||
actions: {
|
||||
// @ts-expect-error TS error on populate, is not considering count
|
||||
count: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
async createAction(
|
||||
releaseId: ReleaseActionCreateArgs['releaseId'],
|
||||
action: Pick<ReleaseActionCreateArgs, 'type' | 'entry'>
|
||||
releaseId: CreateReleaseAction.Request['params']['releaseId'],
|
||||
action: Pick<CreateReleaseAction.Request['body'], 'type' | 'entry'>
|
||||
) {
|
||||
const { validateEntryContentType, validateUniqueEntry } = getService('release-validation', {
|
||||
strapi,
|
||||
});
|
||||
|
||||
await Promise.all([
|
||||
validateEntryContentType({ releaseId, ...action }),
|
||||
validateUniqueEntry({ releaseId, ...action }),
|
||||
validateEntryContentType(action.entry.contentType),
|
||||
validateUniqueEntry(releaseId, action),
|
||||
]);
|
||||
|
||||
const { entry, type } = action;
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
import { errors } from '@strapi/utils';
|
||||
import { LoadedStrapi } from '@strapi/types';
|
||||
import { Release, ReleaseActionCreateArgs } from '../../../shared/types';
|
||||
import type { Release } from '../../../shared/contracts/releases';
|
||||
import type { CreateReleaseAction } from '../../../shared/contracts/release-actions';
|
||||
import { RELEASE_MODEL_UID } from '../constants';
|
||||
|
||||
const createReleaseValidationService = ({ strapi }: { strapi: LoadedStrapi }) => ({
|
||||
async validateUniqueEntry(releaseActionArgs: ReleaseActionCreateArgs) {
|
||||
async validateUniqueEntry(
|
||||
releaseId: CreateReleaseAction.Request['params']['releaseId'],
|
||||
releaseActionArgs: CreateReleaseAction.Request['body']
|
||||
) {
|
||||
/**
|
||||
* Asserting the type, otherwise TS complains: 'release.actions' is of type 'unknown', even though the types come through for non-populated fields...
|
||||
* Possibly related to the comment on GetValues: https://github.com/strapi/strapi/blob/main/packages/core/types/src/modules/entity-service/result.ts
|
||||
*/
|
||||
const release = (await strapi.entityService.findOne(
|
||||
RELEASE_MODEL_UID,
|
||||
releaseActionArgs.releaseId,
|
||||
{
|
||||
populate: { actions: { populate: { entry: { fields: ['id'] } } } },
|
||||
}
|
||||
)) as Release | null;
|
||||
const release = (await strapi.entityService.findOne(RELEASE_MODEL_UID, releaseId, {
|
||||
populate: { actions: { populate: { entry: { fields: ['id'] } } } },
|
||||
})) as Release | null;
|
||||
|
||||
if (!release) {
|
||||
throw new errors.ValidationError(`No release found for id ${releaseActionArgs.releaseId}`);
|
||||
throw new errors.NotFoundError(`No release found for id ${releaseId}`);
|
||||
}
|
||||
|
||||
const isEntryInRelease = release.actions.some(
|
||||
@ -29,23 +29,23 @@ const createReleaseValidationService = ({ strapi }: { strapi: LoadedStrapi }) =>
|
||||
|
||||
if (isEntryInRelease) {
|
||||
throw new errors.ValidationError(
|
||||
`Entry with id ${releaseActionArgs.entry.id} and contentType ${releaseActionArgs.entry.contentType} already exists in release with id ${releaseActionArgs.releaseId}`
|
||||
`Entry with id ${releaseActionArgs.entry.id} and contentType ${releaseActionArgs.entry.contentType} already exists in release with id ${releaseId}`
|
||||
);
|
||||
}
|
||||
},
|
||||
validateEntryContentType(releaseActionArgs: ReleaseActionCreateArgs) {
|
||||
const contentType = strapi.contentType(releaseActionArgs.entry.contentType);
|
||||
validateEntryContentType(
|
||||
contentTypeUid: CreateReleaseAction.Request['body']['entry']['contentType']
|
||||
) {
|
||||
const contentType = strapi.contentType(contentTypeUid);
|
||||
|
||||
if (!contentType) {
|
||||
throw new errors.ValidationError(
|
||||
`No content type found for uid ${releaseActionArgs.entry.contentType}`
|
||||
);
|
||||
throw new errors.NotFoundError(`No content type found for uid ${contentTypeUid}`);
|
||||
}
|
||||
|
||||
// TODO: V5 migration - All contentType will have draftAndPublish enabled
|
||||
if (!contentType.options?.draftAndPublish) {
|
||||
throw new errors.ValidationError(
|
||||
`Content type with uid ${releaseActionArgs.entry.contentType} does not have draftAndPublish enabled`
|
||||
`Content type with uid ${contentTypeUid} does not have draftAndPublish enabled`
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["./src"],
|
||||
"exclude": ["./src/**/*.test.ts"],
|
||||
"extends": "./server/tsconfig.json",
|
||||
"include": ["./server/src", "./shared"],
|
||||
"exclude": ["./server/src/**/*.test.ts"],
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist/server"
|
||||
"rootDir": ".",
|
||||
"outDir": "./dist"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"include": ["src", "../shared/types.ts"],
|
||||
"exclude": ["node_modules"],
|
||||
"include": [
|
||||
"src"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
import { Attribute, Common } from '@strapi/types';
|
||||
import type { Release } from './releases';
|
||||
import type { Entity } from '../types';
|
||||
|
||||
import type { errors } from '@strapi/utils';
|
||||
|
||||
type ReleaseActionEntry = Entity & {
|
||||
// Entity attributes
|
||||
[key: string]: Attribute.Any;
|
||||
};
|
||||
|
||||
export interface ReleaseAction {
|
||||
type: 'publish' | 'unpublish';
|
||||
entry: ReleaseActionEntry;
|
||||
contentType: Common.UID.ContentType;
|
||||
release: Release;
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /content-releases/:id/actions - Create a release action
|
||||
*/
|
||||
export declare namespace CreateReleaseAction {
|
||||
export interface Request {
|
||||
params: {
|
||||
releaseId: Release['id'];
|
||||
};
|
||||
body: {
|
||||
type: ReleaseAction['type'];
|
||||
entry: {
|
||||
id: ReleaseActionEntry['id'];
|
||||
contentType: Common.UID.ContentType;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
data:
|
||||
| ReleaseAction
|
||||
| {
|
||||
data: null;
|
||||
error: errors.ApplicationError | errors.ValidationError | errors.NotFoundError;
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,48 +1,84 @@
|
||||
import { Entity as StrapiEntity } from '@strapi/types';
|
||||
import type { Entity } from '../types';
|
||||
import type { ReleaseAction } from './release-actions';
|
||||
import type { UserInfo } from '../types';
|
||||
import { errors } from '@strapi/utils';
|
||||
|
||||
export interface Entity {
|
||||
id: StrapiEntity.ID;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface Release extends Entity {
|
||||
name: string;
|
||||
releasedAt: string;
|
||||
actions: ReleaseAction[];
|
||||
}
|
||||
|
||||
type Pagination = {
|
||||
page: number;
|
||||
pageSize: number;
|
||||
pageCount: number;
|
||||
total: number;
|
||||
};
|
||||
|
||||
export interface ReleaseDataResponse extends Omit<Release, 'actions'> {
|
||||
actions: { meta: { count: number } };
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /content-releases - Create a single release
|
||||
* GET /content-releases/ - Get all releases
|
||||
*/
|
||||
export declare namespace GetReleases {
|
||||
export interface Request {
|
||||
state: {
|
||||
userAbility: {};
|
||||
};
|
||||
query?: Partial<Pick<Pagination, 'page' | 'pageSize'>>;
|
||||
}
|
||||
|
||||
export type Response =
|
||||
| {
|
||||
data: ReleaseDataResponse[];
|
||||
pagination: Pagination;
|
||||
}
|
||||
| {
|
||||
data: null;
|
||||
error: errors.ApplicationError;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /content-releases/:id - Get a single release
|
||||
*/
|
||||
export declare namespace GetRelease {
|
||||
export interface Request {
|
||||
state: {
|
||||
userAbility: {};
|
||||
};
|
||||
params: {
|
||||
id: Release['id'];
|
||||
};
|
||||
}
|
||||
|
||||
export type Response =
|
||||
| {
|
||||
data: ReleaseDataResponse;
|
||||
}
|
||||
| {
|
||||
data: null;
|
||||
error: errors.ApplicationError | errors.NotFoundError;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /content-releases/ - Create a release
|
||||
*/
|
||||
export declare namespace CreateRelease {
|
||||
export interface Request {
|
||||
query: {};
|
||||
body: Omit<Release, keyof Entity>;
|
||||
state: {
|
||||
user: UserInfo;
|
||||
};
|
||||
body: {
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
data: Release;
|
||||
/**
|
||||
* TODO: check if we also could recieve errors.YupValidationError
|
||||
*/
|
||||
error?: errors.ApplicationError | errors.YupValidationError | errors.UnauthorizedError;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /content-releases - Get all the release
|
||||
*/
|
||||
export declare namespace GetAllReleases {
|
||||
export interface Request {
|
||||
query: {};
|
||||
body: {};
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Validate this with BE
|
||||
*/
|
||||
export interface Response {
|
||||
data: Release[];
|
||||
error?: errors.ApplicationError;
|
||||
}
|
||||
export type Response =
|
||||
| { data: ReleaseDataResponse }
|
||||
| { data: null; error: errors.ApplicationError | errors.ValidationError };
|
||||
}
|
||||
|
||||
@ -1,16 +1,14 @@
|
||||
import type { Entity, Common } from '@strapi/types';
|
||||
import type { Entity as StrapiEntity } from '@strapi/types';
|
||||
|
||||
// @TODO: Probably user & role types should be imported from a common package
|
||||
interface RoleInfo {
|
||||
id: Entity.ID;
|
||||
interface RoleInfo extends Omit<Entity, 'createdAt' | 'updatedAt'> {
|
||||
name: string;
|
||||
code: string;
|
||||
description?: string;
|
||||
usersCount?: number;
|
||||
}
|
||||
|
||||
export interface UserInfo {
|
||||
id: Entity.ID;
|
||||
export interface UserInfo extends Entity {
|
||||
firstname: string;
|
||||
lastname?: string;
|
||||
username?: null | string;
|
||||
@ -19,35 +17,10 @@ export interface UserInfo {
|
||||
blocked: boolean;
|
||||
preferedLanguage: null | string;
|
||||
roles: RoleInfo[];
|
||||
}
|
||||
|
||||
export interface Entity {
|
||||
id: StrapiEntity.ID;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
interface ReleaseActionEntry {
|
||||
id: Entity.ID;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface ReleaseAction {
|
||||
type: 'publish' | 'unpublish';
|
||||
entry: ReleaseActionEntry;
|
||||
contentType: Common.UID.ContentType;
|
||||
release: Release;
|
||||
}
|
||||
|
||||
export interface Release {
|
||||
id: Entity.ID;
|
||||
name: string;
|
||||
releasedAt: Date;
|
||||
actions: ReleaseAction[];
|
||||
}
|
||||
|
||||
export type ReleaseCreateArgs = Pick<Release, 'name'>;
|
||||
|
||||
export interface ReleaseActionCreateArgs extends Pick<ReleaseAction, 'type'> {
|
||||
releaseId: Entity.ID;
|
||||
entry: {
|
||||
id: Entity.ID;
|
||||
contentType: Common.UID.ContentType;
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user