cabloy 5.1.248 → 5.1.250

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 (121) hide show
  1. package/.cabloy-version +1 -1
  2. package/.github/workflows/create-cabloy.yml +50 -3
  3. package/.vscode/settings.json +1 -2
  4. package/CHANGELOG.md +31 -0
  5. package/package.json +1 -7
  6. package/repo-agent-governance/managed-assets.json +12 -12
  7. package/repo-agent-governance/skills/cabloy-spec-execution/references/status-and-evidence.md +1 -1
  8. package/repo-agent-governance/skills/cabloy-spec-generation/references/canonical-spec-input.md +1 -1
  9. package/repo-agent-governance/skills/cabloy-spec-generation/references/repo-specs-document-set.md +2 -2
  10. package/repo-agent-governance/skills/cabloy-spec-generation/references/traceability-and-status-rules.md +1 -1
  11. package/repo-agent-governance/tools/spec-charts/generate-implementation-charts.mjs +73 -22
  12. package/repo-agent-governance/tools/spec-charts/generate-implementation-charts.test.mjs +98 -7
  13. package/repo-docs/ai/playbook-spec-execution.md +1 -1
  14. package/repo-docs/backend/crud-workflow.md +92 -1
  15. package/repo-docs/backend/dto-guide.md +16 -1
  16. package/repo-docs/backend/dto-infer-generation.md +23 -5
  17. package/repo-docs/backend/orm-aggregate-group-guide.md +32 -0
  18. package/repo-docs/backend/validation-guide.md +38 -2
  19. package/repo-e2e/specs/cabloy-basic.spec.ts +9 -2
  20. package/vona/package.original.json +1 -7
  21. package/vona/packages-cli/cli/package.json +1 -1
  22. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudAnalysis/aggregate/src/dto/{{resourceName}}AggregateRes.tsx_ +11 -0
  23. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudAnalysis/common/src/lib/{{resourceName}}Analysis.ts_ +14 -0
  24. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudAnalysis/common/test/{{resourceName}}Analysis.test.ts_ +81 -0
  25. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudAnalysis/group/src/dto/{{resourceName}}GroupResItem.tsx_ +11 -0
  26. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/controller/{{resourceName}}.ts_ +18 -1
  27. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/dto/{{resourceName}}SelectReq.tsx_ +2 -0
  28. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/service/{{resourceName}}.ts_ +14 -1
  29. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/test/{{resourceName}}.test.ts_ +4 -0
  30. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/snippets/3-en-us.ts +2 -0
  31. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/snippets/4-zh-cn.ts +2 -0
  32. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/controller/{{resourceName}}.ts_ +18 -1
  33. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/dto/{{resourceName}}SelectReq.tsx_ +2 -0
  34. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/service/{{resourceName}}.ts_ +14 -1
  35. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/test/{{resourceName}}.test.ts_ +1 -1
  36. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/snippets/3-en-us.ts +2 -0
  37. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/snippets/4-zh-cn.ts +2 -0
  38. package/vona/packages-cli/cli-set-api/package.json +1 -1
  39. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.crudBasic.ts +2 -0
  40. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.crudStart.ts +2 -0
  41. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.masterDetail.ts +9 -1
  42. package/vona/packages-cli/cli-set-api/src/lib/crudAnalysis.ts +11 -0
  43. package/vona/packages-cli/cli-set-api/test/crudAnalysis.test.ts +385 -0
  44. package/vona/packages-utils/babel-plugin-vona-bean-module/package.json +1 -1
  45. package/vona/packages-vona/vona/package.json +1 -1
  46. package/vona/packages-vona/vona-core/package.json +1 -1
  47. package/vona/packages-vona/vona-mock/package.json +1 -1
  48. package/vona/pnpm-lock.yaml +76 -1008
  49. package/vona/src/suite/a-training/modules/training-student/src/.metadata/index.ts +18 -0
  50. package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +2 -0
  51. package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +2 -0
  52. package/vona/src/suite/a-training/modules/training-student/src/controller/student.ts +28 -1
  53. package/vona/src/suite/a-training/modules/training-student/src/dto/studentAggregateRes.tsx +11 -0
  54. package/vona/src/suite/a-training/modules/training-student/src/dto/studentGroupResItem.tsx +11 -0
  55. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectReq.tsx +2 -0
  56. package/vona/src/suite/a-training/modules/training-student/src/lib/studentAnalysis.ts +12 -0
  57. package/vona/src/suite/a-training/modules/training-student/src/service/student.ts +22 -1
  58. package/vona/src/suite/a-training/modules/training-student/test/student.test.ts +4 -0
  59. package/vona/src/suite/a-training/modules/training-student/test/studentAnalysis.test.ts +422 -0
  60. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/package.json +1 -1
  61. package/vona/src/suite-vendor/a-cabloy/package.json +2 -2
  62. package/vona/src/suite-vendor/a-captcha/modules/a-captcha/package.json +1 -1
  63. package/vona/src/suite-vendor/a-captcha/package.json +1 -1
  64. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  65. package/vona/src/suite-vendor/a-vona/modules/a-hmr/package.json +1 -1
  66. package/vona/src/suite-vendor/a-vona/modules/a-locale/package.json +1 -1
  67. package/vona/src/suite-vendor/a-vona/modules/a-openapi/package.json +1 -1
  68. package/vona/src/suite-vendor/a-vona/modules/a-openapiutils/package.json +1 -1
  69. package/vona/src/suite-vendor/a-vona/modules/a-openapiutils/src/lib/utils.ts +1 -1
  70. package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
  71. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/.metadata/index.ts +26 -26
  72. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/aggregateResult.ts +53 -0
  73. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/analysis/controls.ts +163 -0
  74. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/analysis/execute.ts +49 -0
  75. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/analysis/index.ts +3 -0
  76. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/analysis/policy.ts +140 -0
  77. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/bean.model/bean.model_cache.ts +4 -2
  78. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/bean.model/bean.model_crud_inner.ts +8 -3
  79. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dto.ts +3 -0
  80. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoAggregate.ts +4 -1
  81. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoAnalysis.ts +34 -0
  82. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/index.ts +1 -0
  83. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/analysis.ts +137 -0
  84. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/index.ts +1 -0
  85. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsAggr.ts +1 -1
  86. package/vona/src/suite-vendor/a-vona/modules/a-orm/test/aggregateResult.test.ts +81 -0
  87. package/vona/src/suite-vendor/a-vona/modules/a-orm/test/analysis.test.ts +208 -0
  88. package/vona/src/suite-vendor/a-vona/modules/a-orm/test/analysis.types.test.ts +112 -0
  89. package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
  90. package/vona/src/suite-vendor/a-vona/modules/a-queue/package.json +1 -1
  91. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/package.json +1 -1
  92. package/vona/src/suite-vendor/a-vona/modules/a-user/package.json +1 -1
  93. package/vona/src/suite-vendor/a-vona/modules/a-web/package.json +1 -1
  94. package/vona/src/suite-vendor/a-vona/modules/a-web/src/.metadata/index.ts +40 -40
  95. package/vona/src/suite-vendor/a-vona/modules/a-web/src/bean/pipe.filter.ts +44 -3
  96. package/vona/src/suite-vendor/a-vona/modules/a-web/src/lib/analysisFilter.ts +69 -0
  97. package/vona/src/suite-vendor/a-vona/modules/a-web/src/lib/decorator/arguments.ts +6 -4
  98. package/vona/src/suite-vendor/a-vona/modules/a-web/src/lib/index.ts +1 -0
  99. package/vona/src/suite-vendor/a-vona/modules/a-web/src/types/dto.ts +2 -1
  100. package/vona/src/suite-vendor/a-vona/modules/a-web/src/types/filter.ts +7 -2
  101. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  102. package/zova/package.original.json +0 -6
  103. package/zova/packages-cli/cli/package.json +2 -2
  104. package/zova/packages-cli/cli-set-front/package.json +2 -2
  105. package/zova/packages-utils/zova-jsx/package.json +2 -2
  106. package/zova/packages-utils/zova-vite/package.json +1 -1
  107. package/zova/packages-zova/zova/package.json +3 -3
  108. package/zova/packages-zova/zova-core/package.json +1 -1
  109. package/zova/pnpm-lock.yaml +11 -963
  110. package/zova/src/suite/a-home/modules/home-layoutadmin/src/component/layoutAdmin/render.header.tsx +4 -1
  111. package/zova/src/suite/a-home/modules/home-layoutadmin/src/component/layoutAdmin/render.tabs.tsx +2 -2
  112. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/schemas.ts +16 -2
  113. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/types.ts +201 -7
  114. package/zova/src/suite/a-training/modules/training-student/src/api/trainingStudent.ts +42 -0
  115. package/zova/src/suite/a-training/modules/training-student/src/apiSchema/trainingStudent.ts +10 -0
  116. package/zova/src/suite-vendor/a-zova/modules/a-ssr/package.json +1 -1
  117. package/zova/src/suite-vendor/a-zova/modules/a-ssrserver/package.json +1 -1
  118. package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
  119. package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
  120. package/zova/src/suite-vendor/a-zova/package.json +5 -5
  121. package/vona/.textlintrc.json +0 -19
@@ -0,0 +1,69 @@
1
+ import type { Constructable } from 'vona';
2
+ import type { ISchemaObjectExtensionField } from 'vona-module-a-openapi';
3
+ import type { IAnalysisPolicy, TypeAnalysisMode } from 'vona-module-a-orm';
4
+ import type z from 'zod';
5
+
6
+ import { ZodMetadata } from '@cabloy/zod-openapi';
7
+ import { appResource } from 'vona';
8
+ import { $schema } from 'vona-module-a-openapiutils';
9
+ import { analysisCapabilities, analysisControlSchemas } from 'vona-module-a-orm';
10
+
11
+ import type { IDecoratorDtoOptions } from '../types/dto.ts';
12
+
13
+ export interface IArgFilterOptions {
14
+ mode?: TypeAnalysisMode;
15
+ }
16
+
17
+ export function prepareAnalysisFilter(
18
+ schemaLike: z.ZodType | Constructable,
19
+ options?: IArgFilterOptions,
20
+ ) {
21
+ const schema = $schema(schemaLike as Constructable);
22
+ if (!options?.mode) return { schema };
23
+ const policy = (
24
+ appResource.getBean(schemaLike as Constructable)?.options as IDecoratorDtoOptions | undefined
25
+ )?.analysis;
26
+ if (!policy) throw new Error('Analysis filter requires a DTO analysis policy');
27
+ return {
28
+ schema: createAnalysisFilterSchema(schema, policy, options.mode),
29
+ analysis: policy,
30
+ analysisMode: options.mode,
31
+ };
32
+ }
33
+
34
+ function createAnalysisFilterSchema(
35
+ schema: z.ZodType,
36
+ policy: IAnalysisPolicy,
37
+ mode: TypeAnalysisMode,
38
+ ) {
39
+ const inner = ZodMetadata.unwrapChained(schema);
40
+ if (inner.type !== 'object') throw new Error('Analysis filter requires an object DTO schema');
41
+ const object = schema as z.ZodObject;
42
+ if (typeof object.safeExtend !== 'function') {
43
+ throw new TypeError('Analysis filter requires an extensible object DTO schema');
44
+ }
45
+ for (const key of ['groups', 'aggrs', 'having', 'joins', 'distinct']) {
46
+ if (key in object.shape) throw new Error(`Analysis control conflicts with DTO field: ${key}`);
47
+ }
48
+ const controls = analysisControlSchemas(policy, mode);
49
+ const capabilities = analysisCapabilities(policy, mode);
50
+ const metadata: ISchemaObjectExtensionField = {
51
+ filter: { capabilities: { analysis: capabilities } },
52
+ };
53
+ const shape: Record<string, z.ZodType> = {
54
+ aggrs: controls.aggrs.openapi(metadata),
55
+ };
56
+ if (controls.groups) shape.groups = controls.groups.openapi(metadata);
57
+ const derived = object.safeExtend(shape);
58
+ const original = ZodMetadata.getOpenapiMetadata(schema) as
59
+ | ISchemaObjectExtensionField
60
+ | undefined;
61
+ const ref = ZodMetadata.getRefId(schema);
62
+ return derived.openapi(`${ref ?? 'filter'}_${mode}`, {
63
+ ...original,
64
+ filter: {
65
+ ...original?.filter,
66
+ capabilities: { ...original?.filter?.capabilities, analysis: capabilities },
67
+ },
68
+ });
69
+ }
@@ -3,8 +3,10 @@ import type { SchemaLike } from 'vona-module-a-openapiutils';
3
3
  import type z from 'zod';
4
4
 
5
5
  import { setArgumentPipe } from 'vona-module-a-aspect';
6
- import { $schema } from 'vona-module-a-openapiutils';
7
6
 
7
+ import type { IArgFilterOptions } from '../analysisFilter.ts';
8
+
9
+ import { prepareAnalysisFilter } from '../analysisFilter.ts';
8
10
  import { createPipesArgumentDecorator } from './pipesArgument.ts';
9
11
 
10
12
  function Param(): ParameterDecorator;
@@ -71,10 +73,10 @@ function RbacScopeCurrent(): ParameterDecorator {
71
73
  return createPipesArgumentDecorator('rbacScopeCurrent')();
72
74
  }
73
75
 
74
- function ArgFilter(schemaLike: z.ZodType | Constructable): any {
76
+ function ArgFilter(schemaLike: z.ZodType | Constructable, options?: IArgFilterOptions): any {
75
77
  return function (target: object, prop: MetadataKey | undefined, index: number) {
76
- const schema = $schema(schemaLike as any);
77
- setArgumentPipe('a-web:filter', { type: 'query', schema }, target, prop, index);
78
+ const prepared = prepareAnalysisFilter(schemaLike, options);
79
+ setArgumentPipe('a-web:filter', { type: 'query', ...prepared }, target, prop, index);
78
80
  };
79
81
  }
80
82
 
@@ -1,3 +1,4 @@
1
+ export * from './analysisFilter.ts';
1
2
  export * from './const.ts';
2
3
  export * from './decorator/index.ts';
3
4
  export * from './middleware/index.ts';
@@ -2,7 +2,7 @@ import type { OmitNever } from 'vona';
2
2
  import type { ServiceOnion } from 'vona-module-a-onion';
3
3
  import type { ISchemaObjectExtensionField, TypeSchemaScene } from 'vona-module-a-openapi';
4
4
  import type { SchemaLike } from 'vona-module-a-openapiutils';
5
- import type { SymbolKeyFieldsMore } from 'vona-module-a-orm';
5
+ import type { IAnalysisPolicy, SymbolKeyFieldsMore } from 'vona-module-a-orm';
6
6
 
7
7
  export interface IDtoRecord {}
8
8
 
@@ -10,6 +10,7 @@ export interface IDecoratorDtoOptions<FieldsMore = never> {
10
10
  [SymbolKeyFieldsMore]?: FieldsMore;
11
11
  independent?: boolean;
12
12
  schemaScene?: TypeSchemaScene;
13
+ analysis?: IAnalysisPolicy;
13
14
  openapi?: ISchemaObjectExtensionField;
14
15
  pipes?: SchemaLike | SchemaLike[];
15
16
  blocks?: any[];
@@ -1,4 +1,9 @@
1
- import type { IModelSelectParamsJoinType, ITableRecord, TypeOpsNormal } from 'vona-module-a-orm';
1
+ import type {
2
+ IAnalysisCapabilities,
3
+ IModelSelectParamsJoinType,
4
+ ITableRecord,
5
+ TypeOpsNormal,
6
+ } from 'vona-module-a-orm';
2
7
 
3
8
  import type {
4
9
  IDecoratorFilterTransformOptions,
@@ -15,7 +20,7 @@ export interface ISchemaObjectExtensionFieldFilterCapabilities {
15
20
  where?: boolean;
16
21
  // filter?: boolean;
17
22
  order?: boolean;
18
- // group?: boolean;
23
+ analysis?: IAnalysisCapabilities;
19
24
  }
20
25
 
21
26
  export type TypeSchemaObjectExtensionFieldFilterTransform = [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-suite-a-vona",
3
- "version": "5.1.115",
3
+ "version": "5.1.116",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "",
6
6
  "author": "",
@@ -31,7 +31,6 @@
31
31
  "format:fix": "oxfmt --write",
32
32
  "lint": "oxlint",
33
33
  "lint:fix": "oxlint --fix",
34
- "docs:fix": "textlint --fix ./packages-docs/**/*.md",
35
34
  "dev:ssr:admin": "npm run prerun && quasar dev --mode ssr --flavor admin",
36
35
  "build:ssr:admin": "npm run prerun && quasar build --mode ssr --flavor admin",
37
36
  "preview:ssr:admin": "concurrently \"node ./dist-mock/index.js\" \"node ./dist/ssr-admin/index.js\"",
@@ -89,11 +88,6 @@
89
88
  "vite": "^8.3.4",
90
89
  "vite-plugin-fake-server-turbo": "^3.0.18",
91
90
  "zova-vite": "workspace:^",
92
- "textlint": "^15.7.0",
93
- "textlint-rule-en-no-mixed-period": "^3.0.2",
94
- "textlint-rule-ja-no-mixed-period": "^3.0.2",
95
- "textlint-rule-ja-space-between-half-and-full-width": "^2.4.2",
96
- "textlint-rule-period-in-list-item": "^1.0.1",
97
91
  "oxfmt": "^0.74.0",
98
92
  "oxlint": "^1.89.0"
99
93
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova-cli",
3
- "version": "1.2.123",
3
+ "version": "1.2.124",
4
4
  "gitHead": "6f675a8cc46d596142c591c28a40cc4d82fcc6cc",
5
5
  "description": "zova cli",
6
6
  "keywords": [
@@ -44,7 +44,7 @@
44
44
  "@cabloy/process-helper": "^3.1.9",
45
45
  "fs-extra": "^11.3.5",
46
46
  "semver": "^7.6.2",
47
- "zova-cli-set-front": "^1.2.121"
47
+ "zova-cli-set-front": "^1.2.122"
48
48
  },
49
49
  "devDependencies": {
50
50
  "clean-package": "^2.2.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova-cli-set-front",
3
- "version": "1.2.121",
3
+ "version": "1.2.122",
4
4
  "gitHead": "6f675a8cc46d596142c591c28a40cc4d82fcc6cc",
5
5
  "description": "zova cli-set-front",
6
6
  "keywords": [
@@ -70,7 +70,7 @@
70
70
  "vite": "^8.3.4",
71
71
  "yaml": "^2.8.3",
72
72
  "zova-openapi": "^1.1.17",
73
- "zova-vite": "^1.1.52"
73
+ "zova-vite": "^1.1.53"
74
74
  },
75
75
  "devDependencies": {
76
76
  "clean-package": "^2.2.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova-jsx",
3
- "version": "1.1.95",
3
+ "version": "1.1.96",
4
4
  "gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
5
5
  "description": "Zova JSX",
6
6
  "keywords": [
@@ -50,7 +50,7 @@
50
50
  "@cabloy/word-utils": "^2.1.14",
51
51
  "typestyle": "^2.4.0",
52
52
  "vue": "^3.5.38",
53
- "zova-core": "^5.1.95"
53
+ "zova-core": "^5.1.96"
54
54
  },
55
55
  "devDependencies": {
56
56
  "clean-package": "^2.2.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova-vite",
3
- "version": "1.1.52",
3
+ "version": "1.1.53",
4
4
  "gitHead": "09d901d17140a80ee0764211b441cda72fd94663",
5
5
  "description": "zova vite",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova",
3
- "version": "5.1.179",
3
+ "version": "5.1.180",
4
4
  "gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
5
5
  "description": "A vue3 framework with ioc",
6
6
  "keywords": [
@@ -45,8 +45,8 @@
45
45
  "postpack": "clean-package restore"
46
46
  },
47
47
  "dependencies": {
48
- "zova-core": "^5.1.95",
49
- "zova-suite-a-zova": "^5.1.178"
48
+ "zova-core": "^5.1.96",
49
+ "zova-suite-a-zova": "^5.1.179"
50
50
  },
51
51
  "devDependencies": {
52
52
  "clean-package": "^2.2.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova-core",
3
- "version": "5.1.95",
3
+ "version": "5.1.96",
4
4
  "gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
5
5
  "description": "A vue3 framework with ioc",
6
6
  "keywords": [