@rytass/cms-base-nestjs-graphql-module 0.1.24 → 0.1.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/CHANGELOG.md +306 -0
  2. package/__tests__/enums.spec.ts +76 -0
  3. package/__tests__/language-decorator.spec.ts +17 -0
  4. package/__tests__/quadrats-element-scalar.spec.ts +123 -0
  5. package/llms.txt +361 -0
  6. package/package.json +10 -6
  7. package/project.json +23 -0
  8. package/src/cms-base-graphql.module.ts +101 -0
  9. package/src/constants/enum/base-action.enum.ts +17 -0
  10. package/src/constants/enum/base-resource.enum.ts +4 -0
  11. package/src/constants/option-providers.ts +35 -0
  12. package/src/data-loaders/article.dataloader.ts +84 -0
  13. package/src/data-loaders/members.dataloader.ts +36 -0
  14. package/src/decorators/language.decorator.ts +45 -0
  15. package/src/dto/article-collection.dto.ts +9 -0
  16. package/src/dto/article-multi-language-content.dto.ts +18 -0
  17. package/src/dto/article-signature-step.dto.ts +10 -0
  18. package/src/dto/article-signature.dto.ts +21 -0
  19. package/src/dto/article-stage-version.dto.ts +23 -0
  20. package/src/dto/article-version-content.input.ts +18 -0
  21. package/src/dto/article.dto.ts +16 -0
  22. package/src/dto/articles.args.ts +16 -0
  23. package/src/dto/backstage-article-collection.dto.ts +9 -0
  24. package/src/dto/backstage-article.args.ts +20 -0
  25. package/src/dto/backstage-article.dto.ts +14 -0
  26. package/src/dto/backstage-category.dto.ts +5 -0
  27. package/src/dto/base-article.dto.ts +19 -0
  28. package/src/dto/base-category.dto.ts +13 -0
  29. package/src/dto/categories.args.ts +27 -0
  30. package/src/dto/category-multi-language-name.dto.ts +10 -0
  31. package/src/dto/category-multi-language-name.input.ts +10 -0
  32. package/src/dto/category.dto.ts +8 -0
  33. package/src/dto/collection.dto.ts +13 -0
  34. package/src/dto/create-article.args.ts +27 -0
  35. package/src/dto/create-category.args.ts +15 -0
  36. package/src/dto/custom-field.input.ts +10 -0
  37. package/src/dto/update-article.args.ts +8 -0
  38. package/src/dto/update-category.args.ts +8 -0
  39. package/src/dto/user.dto.ts +10 -0
  40. package/{index.d.ts → src/index.ts} +2 -0
  41. package/src/mutations/article.mutations.ts +177 -0
  42. package/src/mutations/category.mutations.ts +78 -0
  43. package/src/queries/article.queries.ts +71 -0
  44. package/src/queries/category.queries.ts +53 -0
  45. package/src/resolvers/article-signature.resolver.ts +29 -0
  46. package/src/resolvers/article.resolver.ts +41 -0
  47. package/src/resolvers/backstage-article.resolver.ts +161 -0
  48. package/src/resolvers/backstage-category.resolver.ts +40 -0
  49. package/src/scalars/quadrats-element.scalar.ts +56 -0
  50. package/src/typings/cms-graphql-base-providers.ts +3 -0
  51. package/{typings/cms-graphql-base-root-module-async-options.dto.d.ts → src/typings/cms-graphql-base-root-module-async-options.dto.ts} +6 -4
  52. package/{typings/cms-graphql-base-root-module-option-factory.d.ts → src/typings/cms-graphql-base-root-module-option-factory.ts} +2 -1
  53. package/src/typings/cms-graphql-base-root-module-options.dto.ts +11 -0
  54. package/src/typings/dto/resolved-create-article-args.dto.ts +33 -0
  55. package/src/typings/dto/resolved-create-category-args.dto.ts +19 -0
  56. package/tsconfig.build.json +8 -0
  57. package/LICENSE +0 -21
  58. package/cms-base-graphql.module.d.ts +0 -9
  59. package/cms-base-graphql.module.js +0 -114
  60. package/constants/enum/base-action.enum.d.ts +0 -14
  61. package/constants/enum/base-action.enum.js +0 -17
  62. package/constants/enum/base-resource.enum.d.ts +0 -4
  63. package/constants/enum/base-resource.enum.js +0 -7
  64. package/constants/option-providers.d.ts +0 -2
  65. package/constants/option-providers.js +0 -20
  66. package/data-loaders/article.dataloader.d.ts +0 -17
  67. package/data-loaders/article.dataloader.js +0 -68
  68. package/data-loaders/members.dataloader.d.ts +0 -8
  69. package/data-loaders/members.dataloader.js +0 -56
  70. package/decorators/language.decorator.d.ts +0 -2
  71. package/decorators/language.decorator.js +0 -32
  72. package/dto/article-collection.dto.d.ts +0 -5
  73. package/dto/article-collection.dto.js +0 -27
  74. package/dto/article-multi-language-content.dto.d.ts +0 -7
  75. package/dto/article-multi-language-content.dto.js +0 -41
  76. package/dto/article-signature-step.dto.d.ts +0 -4
  77. package/dto/article-signature-step.dto.js +0 -28
  78. package/dto/article-signature.dto.d.ts +0 -7
  79. package/dto/article-signature.dto.js +0 -44
  80. package/dto/article-stage-version.dto.d.ts +0 -9
  81. package/dto/article-stage-version.dto.js +0 -59
  82. package/dto/article-version-content.input.d.ts +0 -7
  83. package/dto/article-version-content.input.js +0 -43
  84. package/dto/article.dto.d.ts +0 -7
  85. package/dto/article.dto.js +0 -37
  86. package/dto/articles.args.d.ts +0 -6
  87. package/dto/articles.args.js +0 -48
  88. package/dto/backstage-article-collection.dto.d.ts +0 -5
  89. package/dto/backstage-article-collection.dto.js +0 -27
  90. package/dto/backstage-article.args.d.ts +0 -6
  91. package/dto/backstage-article.args.js +0 -38
  92. package/dto/backstage-article.dto.d.ts +0 -6
  93. package/dto/backstage-article.dto.js +0 -38
  94. package/dto/backstage-category.dto.d.ts +0 -3
  95. package/dto/backstage-category.dto.js +0 -16
  96. package/dto/base-article.dto.d.ts +0 -7
  97. package/dto/base-article.dto.js +0 -47
  98. package/dto/base-category.dto.d.ts +0 -5
  99. package/dto/base-category.dto.js +0 -33
  100. package/dto/categories.args.d.ts +0 -8
  101. package/dto/categories.args.js +0 -62
  102. package/dto/category-multi-language-name.dto.d.ts +0 -4
  103. package/dto/category-multi-language-name.dto.js +0 -28
  104. package/dto/category-multi-language-name.input.d.ts +0 -4
  105. package/dto/category-multi-language-name.input.js +0 -30
  106. package/dto/category.dto.d.ts +0 -4
  107. package/dto/category.dto.js +0 -24
  108. package/dto/collection.dto.d.ts +0 -5
  109. package/dto/collection.dto.js +0 -33
  110. package/dto/create-article.args.d.ts +0 -11
  111. package/dto/create-article.args.js +0 -71
  112. package/dto/create-category.args.d.ts +0 -7
  113. package/dto/create-category.args.js +0 -45
  114. package/dto/custom-field.input.d.ts +0 -4
  115. package/dto/custom-field.input.js +0 -28
  116. package/dto/update-article.args.d.ts +0 -4
  117. package/dto/update-article.args.js +0 -24
  118. package/dto/update-category.args.d.ts +0 -4
  119. package/dto/update-category.args.js +0 -24
  120. package/dto/user.dto.d.ts +0 -4
  121. package/dto/user.dto.js +0 -28
  122. package/index.cjs.js +0 -2334
  123. package/index.js +0 -8
  124. package/mutations/article.mutations.d.ts +0 -22
  125. package/mutations/article.mutations.js +0 -338
  126. package/mutations/category.mutations.d.ts +0 -15
  127. package/mutations/category.mutations.js +0 -134
  128. package/queries/article.queries.d.ts +0 -16
  129. package/queries/article.queries.js +0 -132
  130. package/queries/category.queries.d.ts +0 -13
  131. package/queries/category.queries.js +0 -124
  132. package/resolvers/article-signature.resolver.d.ts +0 -10
  133. package/resolvers/article-signature.resolver.js +0 -68
  134. package/resolvers/article.resolver.d.ts +0 -14
  135. package/resolvers/article.resolver.js +0 -95
  136. package/resolvers/backstage-article.resolver.d.ts +0 -33
  137. package/resolvers/backstage-article.resolver.js +0 -296
  138. package/resolvers/backstage-category.resolver.d.ts +0 -8
  139. package/resolvers/backstage-category.resolver.js +0 -76
  140. package/scalars/quadrats-element.scalar.d.ts +0 -3
  141. package/scalars/quadrats-element.scalar.js +0 -47
  142. package/typings/cms-graphql-base-providers.d.ts +0 -3
  143. package/typings/cms-graphql-base-providers.js +0 -5
  144. package/typings/cms-graphql-base-root-module-options.dto.d.ts +0 -6
  145. package/typings/dto/resolved-create-article-args.dto.d.ts +0 -24
  146. package/typings/dto/resolved-create-category-args.dto.d.ts +0 -13
  147. /package/{typings/custom-field-value.type.d.ts → src/typings/custom-field-value.type.ts} +0 -0
@@ -0,0 +1,45 @@
1
+ import { createParamDecorator, ExecutionContext } from '@nestjs/common';
2
+ import { DEFAULT_LANGUAGE } from '@rytass/cms-base-nestjs-module';
3
+ import { Request } from 'express';
4
+
5
+ export const LANGUAGE_HEADER_KEY = 'x-language';
6
+
7
+ export const Language = createParamDecorator(async (_data: unknown, context: ExecutionContext): Promise<string> => {
8
+ const contextType = context.getType<'http' | 'graphql'>();
9
+
10
+ switch (contextType) {
11
+ case 'graphql': {
12
+ const { GqlExecutionContext } = await import('@nestjs/graphql');
13
+
14
+ const ctx = GqlExecutionContext.create(context).getContext<{
15
+ req: Request;
16
+ }>();
17
+
18
+ const headers = ctx.req.headers;
19
+ const requestLanguage = headers[LANGUAGE_HEADER_KEY];
20
+
21
+ if (typeof requestLanguage === 'string') return requestLanguage;
22
+
23
+ const acceptLanguage = headers['accept-language'] ?? '';
24
+
25
+ if (!acceptLanguage || typeof acceptLanguage !== 'string') return DEFAULT_LANGUAGE;
26
+
27
+ return acceptLanguage.split(',')[0].split(';')[0].trim();
28
+ }
29
+
30
+ case 'http':
31
+ default: {
32
+ const headers = (context.switchToHttp().getRequest() as Request).headers;
33
+
34
+ const requestLanguage = headers[LANGUAGE_HEADER_KEY];
35
+
36
+ if (typeof requestLanguage === 'string') return requestLanguage;
37
+
38
+ const acceptLanguage = headers['accept-language'] ?? '';
39
+
40
+ if (!acceptLanguage || typeof acceptLanguage !== 'string') return DEFAULT_LANGUAGE;
41
+
42
+ return acceptLanguage.split(',')[0].split(';')[0].trim();
43
+ }
44
+ }
45
+ });
@@ -0,0 +1,9 @@
1
+ import { Field, ObjectType } from '@nestjs/graphql';
2
+ import { Collection } from './collection.dto';
3
+ import { ArticleDto } from './article.dto';
4
+
5
+ @ObjectType('ArticleCollection')
6
+ export class ArticleCollectionDto extends Collection {
7
+ @Field(() => [ArticleDto])
8
+ articles: ArticleDto[];
9
+ }
@@ -0,0 +1,18 @@
1
+ import { Field, ObjectType } from '@nestjs/graphql';
2
+ import { QuadratsContentScalar } from '../scalars/quadrats-element.scalar';
3
+ import type { QuadratsElement } from '@quadrats/core';
4
+
5
+ @ObjectType('ArticleMultiLanguageContent')
6
+ export class ArticleMultiLanguageContentDto {
7
+ @Field(() => String)
8
+ language: string;
9
+
10
+ @Field(() => String)
11
+ title: string;
12
+
13
+ @Field(() => String, { nullable: true })
14
+ description: string | null;
15
+
16
+ @Field(() => QuadratsContentScalar)
17
+ content: QuadratsElement[];
18
+ }
@@ -0,0 +1,10 @@
1
+ import { Field, ID, ObjectType } from '@nestjs/graphql';
2
+
3
+ @ObjectType('ArticleSignatureStep')
4
+ export class ArticleSignatureStepDto {
5
+ @Field(() => ID)
6
+ id: string;
7
+
8
+ @Field(() => String)
9
+ name: string;
10
+ }
@@ -0,0 +1,21 @@
1
+ import { Field, ID, ObjectType, registerEnumType } from '@nestjs/graphql';
2
+ import { ArticleSignatureResult } from '@rytass/cms-base-nestjs-module';
3
+
4
+ @ObjectType('ArticleSignature')
5
+ export class ArticleSignatureDto {
6
+ @Field(() => ID)
7
+ id: string;
8
+
9
+ @Field(() => Date)
10
+ signedAt: Date;
11
+
12
+ @Field(() => ArticleSignatureResult)
13
+ result: ArticleSignatureResult;
14
+
15
+ @Field(() => String, { nullable: true })
16
+ rejectReason: string | null;
17
+ }
18
+
19
+ registerEnumType(ArticleSignatureResult, {
20
+ name: 'ArticleSignatureResult',
21
+ });
@@ -0,0 +1,23 @@
1
+ import { Field, ID, ObjectType } from '@nestjs/graphql';
2
+ import { BackstageArticleDto } from './backstage-article.dto';
3
+
4
+ @ObjectType('ArticleStageVersion')
5
+ export class ArticleStageVersionDto {
6
+ @Field(() => ID)
7
+ id: string;
8
+
9
+ @Field(() => BackstageArticleDto, { nullable: true })
10
+ draft: BackstageArticleDto | null;
11
+
12
+ @Field(() => BackstageArticleDto, { nullable: true })
13
+ reviewing: BackstageArticleDto | null;
14
+
15
+ @Field(() => BackstageArticleDto, { nullable: true })
16
+ verified: BackstageArticleDto | null;
17
+
18
+ @Field(() => BackstageArticleDto, { nullable: true })
19
+ scheduled: BackstageArticleDto | null;
20
+
21
+ @Field(() => BackstageArticleDto, { nullable: true })
22
+ released: BackstageArticleDto | null;
23
+ }
@@ -0,0 +1,18 @@
1
+ import { Field, InputType } from '@nestjs/graphql';
2
+ import { QuadratsContentScalar } from '../scalars/quadrats-element.scalar';
3
+ import { QuadratsElement } from '@quadrats/core';
4
+
5
+ @InputType('ArticleVersionContentInput')
6
+ export class ArticleVersionContentInput {
7
+ @Field(() => String, { nullable: true })
8
+ language?: string | null;
9
+
10
+ @Field(() => String)
11
+ title: string;
12
+
13
+ @Field(() => String, { nullable: true })
14
+ description?: string | null;
15
+
16
+ @Field(() => QuadratsContentScalar)
17
+ content: QuadratsElement[];
18
+ }
@@ -0,0 +1,16 @@
1
+ import { Field, ObjectType } from '@nestjs/graphql';
2
+ import { BaseArticleDto } from './base-article.dto';
3
+ import { QuadratsContentScalar } from '../scalars/quadrats-element.scalar';
4
+ import type { QuadratsElement } from '@quadrats/core';
5
+
6
+ @ObjectType('Article')
7
+ export class ArticleDto extends BaseArticleDto {
8
+ @Field(() => String)
9
+ title: string;
10
+
11
+ @Field(() => String, { nullable: true })
12
+ description: string | null;
13
+
14
+ @Field(() => QuadratsContentScalar)
15
+ content: QuadratsElement[];
16
+ }
@@ -0,0 +1,16 @@
1
+ import { ArgsType, Field, ID, Int } from '@nestjs/graphql';
2
+
3
+ @ArgsType()
4
+ export class ArticlesArgs {
5
+ @Field(() => [ID], { nullable: true })
6
+ categoryIds?: string[] | null;
7
+
8
+ @Field(() => Int, { nullable: true })
9
+ offset?: number | null;
10
+
11
+ @Field(() => Int, { nullable: true })
12
+ limit?: number | null;
13
+
14
+ @Field(() => String, { nullable: true })
15
+ searchTerm?: string | null;
16
+ }
@@ -0,0 +1,9 @@
1
+ import { Field, ObjectType } from '@nestjs/graphql';
2
+ import { Collection } from './collection.dto';
3
+ import { BackstageArticleDto } from './backstage-article.dto';
4
+
5
+ @ObjectType('BackstageArticleCollection')
6
+ export class BackstageArticleCollectionDto extends Collection {
7
+ @Field(() => [BackstageArticleDto])
8
+ articles: BackstageArticleDto[];
9
+ }
@@ -0,0 +1,20 @@
1
+ import { ArgsType, Field, registerEnumType } from '@nestjs/graphql';
2
+ import { ArticleSorter, ArticleStage } from '@rytass/cms-base-nestjs-module';
3
+ import { ArticlesArgs } from './articles.args';
4
+
5
+ @ArgsType()
6
+ export class BackstageArticleArgs extends ArticlesArgs {
7
+ @Field(() => ArticleStage)
8
+ stage: ArticleStage;
9
+
10
+ @Field(() => ArticleSorter, { nullable: true })
11
+ sorter?: ArticleSorter | null;
12
+ }
13
+
14
+ registerEnumType(ArticleStage, {
15
+ name: 'ArticleStage',
16
+ });
17
+
18
+ registerEnumType(ArticleSorter, {
19
+ name: 'ArticleSorter',
20
+ });
@@ -0,0 +1,14 @@
1
+ import { Field, Int, ObjectType } from '@nestjs/graphql';
2
+ import { BaseArticleDto } from './base-article.dto';
3
+
4
+ @ObjectType('BackstageArticle')
5
+ export class BackstageArticleDto extends BaseArticleDto {
6
+ @Field(() => Int)
7
+ version: number;
8
+
9
+ @Field(() => Date, { nullable: true })
10
+ deletedAt?: Date | null;
11
+
12
+ @Field(() => Date, { nullable: true })
13
+ submittedAt?: Date | null;
14
+ }
@@ -0,0 +1,5 @@
1
+ import { ObjectType } from '@nestjs/graphql';
2
+ import { BaseCategoryDto } from './base-category.dto';
3
+
4
+ @ObjectType('BackstageCategory')
5
+ export class BackstageCategoryDto extends BaseCategoryDto {}
@@ -0,0 +1,19 @@
1
+ import { Field, ID, ObjectType } from '@nestjs/graphql';
2
+
3
+ @ObjectType('BaseArticle')
4
+ export class BaseArticleDto {
5
+ @Field(() => ID)
6
+ id: string;
7
+
8
+ @Field(() => [String])
9
+ tags: string[];
10
+
11
+ @Field(() => Date)
12
+ createdAt: Date;
13
+
14
+ @Field(() => Date)
15
+ updatedAt: Date;
16
+
17
+ @Field(() => Date, { nullable: true })
18
+ releasedAt: Date | null;
19
+ }
@@ -0,0 +1,13 @@
1
+ import { Field, ID, ObjectType } from '@nestjs/graphql';
2
+
3
+ @ObjectType('BaseCategory')
4
+ export class BaseCategoryDto {
5
+ @Field(() => ID)
6
+ id: string;
7
+
8
+ @Field(() => Date)
9
+ createdAt: Date;
10
+
11
+ @Field(() => Date)
12
+ updatedAt: Date;
13
+ }
@@ -0,0 +1,27 @@
1
+ import { ArgsType, Field, ID, registerEnumType } from '@nestjs/graphql';
2
+ import { CategorySorter } from '@rytass/cms-base-nestjs-module';
3
+
4
+ @ArgsType()
5
+ export class CategoriesArgs {
6
+ @Field(() => [ID], { nullable: true })
7
+ parentIds?: string[] | null;
8
+
9
+ @Field(() => [ID], { nullable: true })
10
+ ids?: string[] | null;
11
+
12
+ @Field(() => String, { nullable: true })
13
+ searchTerm?: string | null;
14
+
15
+ @Field(() => Boolean, {
16
+ description: 'If true, return only top level categories',
17
+ nullable: true,
18
+ })
19
+ fromTop?: boolean | null;
20
+
21
+ @Field(() => CategorySorter, { nullable: true })
22
+ sorter?: CategorySorter | null;
23
+ }
24
+
25
+ registerEnumType(CategorySorter, {
26
+ name: 'CategorySorter',
27
+ });
@@ -0,0 +1,10 @@
1
+ import { Field, ObjectType } from '@nestjs/graphql';
2
+
3
+ @ObjectType('CategoryMultiLanguageName')
4
+ export class CategoryMultiLanguageNameDto {
5
+ @Field(() => String)
6
+ language: string;
7
+
8
+ @Field(() => String)
9
+ name: string;
10
+ }
@@ -0,0 +1,10 @@
1
+ import { Field, InputType } from '@nestjs/graphql';
2
+
3
+ @InputType('CategoryMultiLanguageNameInput')
4
+ export class CategoryMultiLanguageNameInput {
5
+ @Field(() => String, { nullable: true })
6
+ language?: string | null;
7
+
8
+ @Field(() => String)
9
+ name: string;
10
+ }
@@ -0,0 +1,8 @@
1
+ import { Field, ObjectType } from '@nestjs/graphql';
2
+ import { BaseCategoryDto } from './base-category.dto';
3
+
4
+ @ObjectType('Category')
5
+ export class CategoryDto extends BaseCategoryDto {
6
+ @Field(() => String)
7
+ name: string;
8
+ }
@@ -0,0 +1,13 @@
1
+ import { Field, Int, ObjectType } from '@nestjs/graphql';
2
+
3
+ @ObjectType('Collection')
4
+ export class Collection {
5
+ @Field(() => Int)
6
+ total: number;
7
+
8
+ @Field(() => Int)
9
+ offset: number;
10
+
11
+ @Field(() => Int)
12
+ limit: number;
13
+ }
@@ -0,0 +1,27 @@
1
+ import { ArgsType, Field, ID } from '@nestjs/graphql';
2
+ import { ArticleVersionContentInput } from './article-version-content.input';
3
+ import { CustomFieldInput } from './custom-field.input';
4
+
5
+ @ArgsType()
6
+ export class CreateArticleArgs {
7
+ @Field(() => [ID])
8
+ categoryIds: string[];
9
+
10
+ @Field(() => [String])
11
+ tags: string[];
12
+
13
+ @Field(() => [ArticleVersionContentInput])
14
+ multiLanguageContents: ArticleVersionContentInput[];
15
+
16
+ @Field(() => Date, { nullable: true })
17
+ releasedAt?: Date | null;
18
+
19
+ @Field(() => Boolean, { nullable: true })
20
+ submitted?: boolean | null;
21
+
22
+ @Field(() => String, { nullable: true })
23
+ signatureLevel?: string | null;
24
+
25
+ @Field(() => [CustomFieldInput], { nullable: true })
26
+ customFields?: CustomFieldInput[];
27
+ }
@@ -0,0 +1,15 @@
1
+ import { ArgsType, Field, ID } from '@nestjs/graphql';
2
+ import { CategoryMultiLanguageNameInput } from './category-multi-language-name.input';
3
+ import { CustomFieldInput } from './custom-field.input';
4
+
5
+ @ArgsType()
6
+ export class CreateCategoryArgs {
7
+ @Field(() => [ID], { nullable: true })
8
+ parentIds?: string[] | null;
9
+
10
+ @Field(() => [CategoryMultiLanguageNameInput])
11
+ multiLanguageNames: CategoryMultiLanguageNameInput[];
12
+
13
+ @Field(() => [CustomFieldInput], { nullable: true })
14
+ customFields?: CustomFieldInput[];
15
+ }
@@ -0,0 +1,10 @@
1
+ import { Field, ID, InputType } from '@nestjs/graphql';
2
+
3
+ @InputType('CustomFieldInput')
4
+ export class CustomFieldInput {
5
+ @Field(() => ID)
6
+ key: string;
7
+
8
+ @Field(() => String)
9
+ value: string;
10
+ }
@@ -0,0 +1,8 @@
1
+ import { ArgsType, Field, ID } from '@nestjs/graphql';
2
+ import { CreateArticleArgs } from './create-article.args';
3
+
4
+ @ArgsType()
5
+ export class UpdateArticleArgs extends CreateArticleArgs {
6
+ @Field(() => ID)
7
+ id: string;
8
+ }
@@ -0,0 +1,8 @@
1
+ import { ArgsType, Field, ID } from '@nestjs/graphql';
2
+ import { CreateCategoryArgs } from './create-category.args';
3
+
4
+ @ArgsType()
5
+ export class UpdateCategoryArgs extends CreateCategoryArgs {
6
+ @Field(() => ID)
7
+ id: string;
8
+ }
@@ -0,0 +1,10 @@
1
+ import { Field, ID, ObjectType } from '@nestjs/graphql';
2
+
3
+ @ObjectType('User')
4
+ export class UserDto {
5
+ @Field(() => ID)
6
+ id: string;
7
+
8
+ @Field(() => String)
9
+ account: string;
10
+ }
@@ -1,4 +1,6 @@
1
1
  export * from './cms-base-graphql.module';
2
+
3
+ // GraphQL Types
2
4
  export * from './dto/backstage-article.dto';
3
5
  export * from './dto/article.dto';
4
6
  export * from './dto/article-collection.dto';
@@ -0,0 +1,177 @@
1
+ import { ArticleBaseService, DEFAULT_LANGUAGE, MULTIPLE_LANGUAGE_MODE } from '@rytass/cms-base-nestjs-module';
2
+ import { Args, ID, Int, Mutation, Resolver } from '@nestjs/graphql';
3
+ import { BackstageArticleDto } from '../dto/backstage-article.dto';
4
+ import { CreateArticleArgs } from '../dto/create-article.args';
5
+ import { AllowActions, MemberId } from '@rytass/member-base-nestjs-module';
6
+ import { UpdateArticleArgs } from '../dto/update-article.args';
7
+ import { Inject } from '@nestjs/common';
8
+ import { BaseAction } from '../constants/enum/base-action.enum';
9
+ import { BaseResource } from '../constants/enum/base-resource.enum';
10
+ import { MAP_ARTICLE_CUSTOM_FIELDS_TO_ENTITY_COLUMNS } from '../typings/cms-graphql-base-providers';
11
+ import { CustomFieldInput } from '../dto/custom-field.input';
12
+ import { ResolvedCreateArticleArgsDto } from '../typings/dto/resolved-create-article-args.dto';
13
+
14
+ @Resolver()
15
+ export class ArticleMutations {
16
+ constructor(
17
+ @Inject(MULTIPLE_LANGUAGE_MODE)
18
+ private readonly multiLanguage: boolean,
19
+ @Inject(MAP_ARTICLE_CUSTOM_FIELDS_TO_ENTITY_COLUMNS)
20
+ private readonly mapArticleCustomFieldsToEntityColumns: (
21
+ customFields: CustomFieldInput[],
22
+ ) => Promise<Record<string, string>>,
23
+ private readonly articleService: ArticleBaseService,
24
+ ) {}
25
+
26
+ private async resolveCreateArticleArgs(args: CreateArticleArgs): Promise<ResolvedCreateArticleArgsDto> {
27
+ const extraArgsInput: Record<string, string | object> = {};
28
+
29
+ if (args.customFields?.length) {
30
+ Object.assign(extraArgsInput, await this.mapArticleCustomFieldsToEntityColumns(args.customFields));
31
+ }
32
+
33
+ const basePayload = {
34
+ categoryIds: args.categoryIds,
35
+ tags: args.tags,
36
+ submitted: args.submitted ?? undefined,
37
+ signatureLevel: args.signatureLevel ?? null,
38
+ releasedAt: args.releasedAt ?? null,
39
+ ...extraArgsInput,
40
+ };
41
+
42
+ if (!this.multiLanguage) {
43
+ const [content] = args.multiLanguageContents;
44
+
45
+ return {
46
+ ...basePayload,
47
+ title: content.title,
48
+ content: content.content,
49
+ description: content.description ?? undefined,
50
+ };
51
+ }
52
+
53
+ const multiLanguageContents = args.multiLanguageContents.reduce(
54
+ (vars, content) => ({
55
+ ...vars,
56
+ [content.language ?? DEFAULT_LANGUAGE]: {
57
+ title: content.title,
58
+ description: content.description,
59
+ content: content.content,
60
+ },
61
+ }),
62
+ {},
63
+ );
64
+
65
+ return {
66
+ ...basePayload,
67
+ multiLanguageContents,
68
+ };
69
+ }
70
+
71
+ @Mutation(() => BackstageArticleDto)
72
+ @AllowActions([[BaseResource.ARTICLE, BaseAction.CREATE]])
73
+ async createArticle(@MemberId() memberId: string, @Args() args: CreateArticleArgs): Promise<BackstageArticleDto> {
74
+ return this.articleService.create({
75
+ ...(await this.resolveCreateArticleArgs(args)),
76
+ userId: memberId,
77
+ });
78
+ }
79
+
80
+ @Mutation(() => BackstageArticleDto)
81
+ @AllowActions([[BaseResource.ARTICLE, BaseAction.UPDATE]])
82
+ async updateArticle(@MemberId() memberId: string, @Args() args: UpdateArticleArgs): Promise<BackstageArticleDto> {
83
+ return this.articleService.addVersion(args.id, {
84
+ ...(await this.resolveCreateArticleArgs(args)),
85
+ userId: memberId,
86
+ });
87
+ }
88
+
89
+ @Mutation(() => Boolean)
90
+ @AllowActions([[BaseResource.ARTICLE, BaseAction.DELETE]])
91
+ async deleteArticle(@Args('id', { type: () => ID }) id: string): Promise<boolean> {
92
+ await this.articleService.archive(id);
93
+
94
+ return true;
95
+ }
96
+
97
+ @Mutation(() => Boolean)
98
+ @AllowActions([[BaseResource.ARTICLE, BaseAction.DELETE_VERSION]])
99
+ async deleteArticleVersion(
100
+ @Args('id', { type: () => ID }) id: string,
101
+ @Args('version', { type: () => Int }) version: number,
102
+ ): Promise<boolean> {
103
+ await this.articleService.deleteVersion(id, version);
104
+
105
+ return true;
106
+ }
107
+
108
+ @Mutation(() => BackstageArticleDto)
109
+ @AllowActions([[BaseResource.ARTICLE, BaseAction.SUBMIT]])
110
+ async submitArticle(
111
+ @MemberId() memberId: string,
112
+ @Args('id', { type: () => ID }) id: string,
113
+ ): Promise<BackstageArticleDto> {
114
+ return this.articleService.submit(id, {
115
+ userId: memberId,
116
+ });
117
+ }
118
+
119
+ @Mutation(() => BackstageArticleDto)
120
+ @AllowActions([[BaseResource.ARTICLE, BaseAction.PUT_BACK]])
121
+ async putBackArticle(
122
+ @MemberId() _memberId: string,
123
+ @Args('id', { type: () => ID }) id: string,
124
+ ): Promise<BackstageArticleDto> {
125
+ return this.articleService.putBack(id);
126
+ }
127
+
128
+ @Mutation(() => BackstageArticleDto)
129
+ @AllowActions([[BaseResource.ARTICLE, BaseAction.APPROVE]])
130
+ async approveArticle(
131
+ @Args('id', { type: () => ID }) id: string,
132
+ @Args('version', { type: () => Int, nullable: true })
133
+ version?: number | null,
134
+ ): Promise<BackstageArticleDto> {
135
+ const article = await this.articleService.findById(id);
136
+
137
+ return this.articleService.approveVersion({
138
+ id,
139
+ version: version ?? article.version,
140
+ });
141
+ }
142
+
143
+ @Mutation(() => BackstageArticleDto)
144
+ @AllowActions([[BaseResource.ARTICLE, BaseAction.REJECT]])
145
+ async rejectArticle(
146
+ @Args('id', { type: () => ID }) id: string,
147
+ @Args('reason', { type: () => String, nullable: true })
148
+ reason?: string | null,
149
+ ): Promise<BackstageArticleDto> {
150
+ return this.articleService.rejectVersion({ id }, { reason });
151
+ }
152
+
153
+ @Mutation(() => BackstageArticleDto)
154
+ @AllowActions([[BaseResource.ARTICLE, BaseAction.RELEASE]])
155
+ releaseArticle(
156
+ @MemberId() userId: string,
157
+ @Args('id', { type: () => ID }) id: string,
158
+ @Args('releasedAt', { type: () => Date }) releasedAt: Date,
159
+ @Args('version', { type: () => Int, nullable: true })
160
+ version?: number | null,
161
+ ): Promise<BackstageArticleDto> {
162
+ return this.articleService.release(id, {
163
+ releasedAt,
164
+ userId,
165
+ version: version ?? undefined,
166
+ });
167
+ }
168
+
169
+ @Mutation(() => BackstageArticleDto)
170
+ @AllowActions([[BaseResource.ARTICLE, BaseAction.WITHDRAW]])
171
+ withdrawArticle(
172
+ @Args('id', { type: () => ID }) id: string,
173
+ @Args('version', { type: () => Int }) version: number,
174
+ ): Promise<BackstageArticleDto> {
175
+ return this.articleService.withdraw(id, version);
176
+ }
177
+ }