manifest
Version:
The backend for AI code editors
376 lines (375 loc) • 16.9 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenApiCrudService = void 0;
const common_1 = require("@nestjs/common");
const common_2 = require("../../../../common/src");
const constants_1 = require("../../constants");
const open_api_utils_service_1 = require("./open-api-utils.service");
let OpenApiCrudService = class OpenApiCrudService {
constructor(openApiUtilsService) {
this.openApiUtilsService = openApiUtilsService;
}
generateEntityPaths(entityManifests) {
const paths = {};
entityManifests
.filter((entityManifest) => !entityManifest.single)
.forEach((entityManifest) => {
paths[`/${constants_1.API_PATH}/${constants_1.COLLECTIONS_PATH}/${entityManifest.slug}`] = {};
paths[`/${constants_1.API_PATH}/${constants_1.COLLECTIONS_PATH}/${entityManifest.slug}/{id}`] =
{};
paths[`/${constants_1.API_PATH}/${constants_1.COLLECTIONS_PATH}/${entityManifest.slug}/select-options`] = {};
if (this.isNotForbidden(entityManifest.policies.create)) {
Object.assign(paths[`/${constants_1.API_PATH}/${constants_1.COLLECTIONS_PATH}/${entityManifest.slug}`], this.generateCreatePath(entityManifest));
}
if (this.isNotForbidden(entityManifest.policies.read)) {
Object.assign(paths[`/${constants_1.API_PATH}/${constants_1.COLLECTIONS_PATH}/${entityManifest.slug}`], this.generateListPath(entityManifest));
Object.assign(paths[`/${constants_1.API_PATH}/${constants_1.COLLECTIONS_PATH}/${entityManifest.slug}/{id}`], this.generateDetailPath(entityManifest));
Object.assign(paths[`/${constants_1.API_PATH}/${constants_1.COLLECTIONS_PATH}/${entityManifest.slug}/select-options`], this.generateListSelectOptionsPath(entityManifest));
}
if (this.isNotForbidden(entityManifest.policies.update)) {
Object.assign(paths[`/${constants_1.API_PATH}/${constants_1.COLLECTIONS_PATH}/${entityManifest.slug}/{id}`], this.generateUpdatePath(entityManifest), this.generatePatchPath(entityManifest));
}
if (this.isNotForbidden(entityManifest.policies.delete)) {
Object.assign(paths[`/${constants_1.API_PATH}/${constants_1.COLLECTIONS_PATH}/${entityManifest.slug}/{id}`], this.generateDeletePath(entityManifest));
}
});
entityManifests
.filter((entityManifest) => entityManifest.single)
.forEach((entityManifest) => {
if (this.isNotForbidden(entityManifest.policies.read)) {
paths[`/${constants_1.API_PATH}/${constants_1.SINGLES_PATH}/${entityManifest.slug}`] = {
...this.generateDetailPath(entityManifest, true)
};
}
if (this.isNotForbidden(entityManifest.policies.update)) {
paths[`/${constants_1.API_PATH}/${constants_1.SINGLES_PATH}/${entityManifest.slug}`] = {
...this.generateDetailPath(entityManifest, true),
...this.generatePatchPath(entityManifest, true)
};
}
});
return paths;
}
generateListPath(entityManifest) {
return {
get: {
summary: `List ${entityManifest.namePlural}`,
description: `Retrieves a paginated list of ${entityManifest.namePlural}. In addition to the general parameters below, each property of the ${entityManifest.nameSingular} can be used as a filter: https://manifest.build/docs/rest-api#filters`,
tags: [(0, common_2.upperCaseFirstLetter)(entityManifest.namePlural)],
security: this.openApiUtilsService.getSecurityRequirements(entityManifest.policies.read),
parameters: [
{
name: 'page',
in: 'query',
description: 'The page number',
required: false,
schema: {
type: 'integer',
default: 1
}
},
{
name: 'perPage',
in: 'query',
description: 'The number of items per page',
required: false,
schema: {
type: 'integer',
default: 10
}
},
{
name: 'orderBy',
in: 'query',
description: 'The field to order by',
required: false,
schema: {
type: 'string'
}
},
{
name: 'order',
in: 'query',
description: 'The order direction',
required: false,
schema: {
type: 'string',
enum: ['ASC', 'DESC']
}
},
{
name: 'relations',
in: 'query',
description: 'The relations to include. For several relations, use a comma-separated list',
required: false,
schema: {
type: 'string'
}
}
],
responses: {
'200': {
description: 'OK',
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/Paginator'
}
}
}
}
}
}
};
}
generateListSelectOptionsPath(entityManifest) {
return {
get: {
summary: `List ${entityManifest.namePlural} for select options`,
description: `Retrieves a list of ${entityManifest.namePlural} for select options. The response is an array of objects with the properties 'id' and 'label'. Used in the admin panel to fill select dropdowns.`,
tags: [(0, common_2.upperCaseFirstLetter)(entityManifest.namePlural)],
security: [
{
Admin: []
}
],
responses: {
'200': {
description: `List of ${entityManifest.namePlural} for select options`,
content: {
'application/json': {
schema: {
type: 'array',
items: {
$ref: `#/components/schemas/SelectOption`
}
}
}
}
}
}
}
};
}
generateCreatePath(entityManifest) {
return {
post: {
summary: `Create a new ${entityManifest.nameSingular}`,
description: `Creates a new ${entityManifest.nameSingular} passing the properties in the request body as JSON.`,
tags: [(0, common_2.upperCaseFirstLetter)(entityManifest.namePlural)],
requestBody: {
content: {
'application/json': {
schema: {
type: 'object'
}
}
}
},
security: this.openApiUtilsService.getSecurityRequirements(entityManifest.policies.create),
responses: {
'201': {
description: `OK`
},
'400': {
description: `Bad request`
}
}
}
};
}
generateDetailPath(entityManifest, single) {
return {
get: {
summary: `Get a single ${entityManifest.nameSingular}`,
description: `Retrieves the details of a single ${entityManifest.nameSingular} by its ID.`,
tags: [
(0, common_2.upperCaseFirstLetter)(entityManifest.namePlural || entityManifest.nameSingular)
],
parameters: single
? []
: [
{
name: 'id',
in: 'path',
description: `The ID of the ${entityManifest.nameSingular}`,
required: true,
schema: {
type: 'string',
format: 'uuid',
example: '123e4567-e89b-12d3-a456-426614174000'
}
}
],
security: this.openApiUtilsService.getSecurityRequirements(entityManifest.policies.read),
responses: {
'200': {
description: `OK`,
content: {
'application/json': {
schema: {
type: 'object'
}
}
}
},
'404': {
description: `The ${entityManifest.nameSingular} was not found`
}
}
}
};
}
generateUpdatePath(entityManifest, single) {
return {
put: {
summary: `Update an existing ${entityManifest.nameSingular} (full replace)`,
description: `Updates a single ${entityManifest.nameSingular} by its ID. The properties to update are passed in the request body as JSON. This operation fully replaces the entity and its relations. Leaving a property out will remove it.`,
tags: [
(0, common_2.upperCaseFirstLetter)(entityManifest.namePlural || entityManifest.nameSingular)
],
requestBody: {
content: {
'application/json': {
schema: {
type: 'object'
}
}
}
},
parameters: single
? []
: [
{
name: 'id',
in: 'path',
description: `The ID of the ${entityManifest.nameSingular}`,
required: true,
schema: {
type: 'string',
format: 'uuid',
example: '123e4567-e89b-12d3-a456-426614174000'
}
}
],
security: this.openApiUtilsService.getSecurityRequirements(entityManifest.policies.update),
responses: {
'200': {
description: `OK`,
content: {
'application/json': {
schema: {
type: 'object'
}
}
}
},
'404': {
description: `Not found`
}
}
}
};
}
generatePatchPath(entityManifest, single) {
return {
patch: {
summary: `Update an existing ${entityManifest.nameSingular} (partial update)`,
description: `Updates a single ${entityManifest.nameSingular} by its ID. The properties to update are passed in the request body as JSON. This operation partially updates the entity and its relations. Leaving a property out will not remove it.`,
tags: [
(0, common_2.upperCaseFirstLetter)(entityManifest.namePlural || entityManifest.nameSingular)
],
requestBody: {
content: {
'application/json': {
schema: {
type: 'object'
}
}
}
},
parameters: single
? []
: [
{
name: 'id',
in: 'path',
description: `The ID of the ${entityManifest.nameSingular}`,
required: true,
schema: {
type: 'string',
format: 'uuid',
example: '123e4567-e89b-12d3-a456-426614174000'
}
}
],
security: this.openApiUtilsService.getSecurityRequirements(entityManifest.policies.update),
responses: {
'200': {
description: `OK`,
content: {
'application/json': {
schema: {
type: 'object'
}
}
}
},
'404': {
description: `Not found`
}
}
}
};
}
generateDeletePath(entityManifest) {
return {
delete: {
summary: `Delete an existing ${entityManifest.nameSingular}`,
description: `Deletes a single ${entityManifest.nameSingular} by its ID.`,
tags: [(0, common_2.upperCaseFirstLetter)(entityManifest.namePlural)],
parameters: [
{
name: 'id',
in: 'path',
description: `The ID of the ${entityManifest.nameSingular}`,
required: true,
schema: {
type: 'string',
format: 'uuid',
example: '123e4567-e89b-12d3-a456-426614174000'
}
}
],
security: this.openApiUtilsService.getSecurityRequirements(entityManifest.policies.delete),
responses: {
'200': {
description: `OK`
},
'404': {
description: `The ${entityManifest.nameSingular} was not found`
}
}
}
};
}
isNotForbidden(policies) {
return policies.every((policy) => {
return policy.access !== 'forbidden';
});
}
};
exports.OpenApiCrudService = OpenApiCrudService;
exports.OpenApiCrudService = OpenApiCrudService = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [open_api_utils_service_1.OpenApiUtilsService])
], OpenApiCrudService);