@intlayer/backend 3.5.5 → 3.5.6
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.
- package/dist/cjs/controllers/ai.controller.cjs +159 -7
- package/dist/cjs/controllers/ai.controller.cjs.map +1 -1
- package/dist/cjs/controllers/dictionary.controller.cjs +50 -17
- package/dist/cjs/controllers/dictionary.controller.cjs.map +1 -1
- package/dist/cjs/controllers/project.controller.cjs +2 -6
- package/dist/cjs/controllers/project.controller.cjs.map +1 -1
- package/dist/cjs/controllers/tag.controller.cjs +235 -0
- package/dist/cjs/controllers/tag.controller.cjs.map +1 -0
- package/dist/cjs/controllers/user.controller.cjs +1 -0
- package/dist/cjs/controllers/user.controller.cjs.map +1 -1
- package/dist/cjs/export.cjs.map +1 -1
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/models/tag.model.cjs +31 -0
- package/dist/cjs/models/tag.model.cjs.map +1 -0
- package/dist/cjs/routes/ai.routes.cjs +31 -4
- package/dist/cjs/routes/ai.routes.cjs.map +1 -1
- package/dist/cjs/routes/dictionary.routes.cjs +4 -4
- package/dist/cjs/routes/dictionary.routes.cjs.map +1 -1
- package/dist/cjs/routes/tags.routes.cjs +60 -0
- package/dist/cjs/routes/tags.routes.cjs.map +1 -0
- package/dist/cjs/schemas/dictionary.schema.cjs +31 -6
- package/dist/cjs/schemas/dictionary.schema.cjs.map +1 -1
- package/dist/cjs/schemas/project.schema.cjs +5 -0
- package/dist/cjs/schemas/project.schema.cjs.map +1 -1
- package/dist/cjs/schemas/tag.schema.cjs +64 -0
- package/dist/cjs/schemas/tag.schema.cjs.map +1 -0
- package/dist/cjs/services/dictionary.service.cjs +139 -27
- package/dist/cjs/services/dictionary.service.cjs.map +1 -1
- package/dist/cjs/services/project.service.cjs +14 -5
- package/dist/cjs/services/project.service.cjs.map +1 -1
- package/dist/cjs/services/tag.service.cjs +91 -0
- package/dist/cjs/services/tag.service.cjs.map +1 -0
- package/dist/cjs/types/dictionary.types.cjs.map +1 -1
- package/dist/cjs/types/tag.types.cjs +17 -0
- package/dist/cjs/types/tag.types.cjs.map +1 -0
- package/dist/cjs/utils/{audit → auditDictionary}/PROMPT.md +6 -1
- package/dist/cjs/utils/{audit → auditDictionary}/index.cjs +10 -8
- package/dist/cjs/utils/auditDictionary/index.cjs.map +1 -0
- package/dist/cjs/utils/auditDictionaryField/PROMPT.md +115 -0
- package/dist/cjs/utils/auditDictionaryField/index.cjs +81 -0
- package/dist/cjs/utils/auditDictionaryField/index.cjs.map +1 -0
- package/dist/cjs/utils/auditDictionaryMetadata/PROMPT.md +76 -0
- package/dist/cjs/utils/auditDictionaryMetadata/index.cjs +78 -0
- package/dist/cjs/utils/auditDictionaryMetadata/index.cjs.map +1 -0
- package/dist/cjs/utils/auditTag/PROMPT.md +34 -0
- package/dist/cjs/utils/auditTag/index.cjs +74 -0
- package/dist/cjs/utils/auditTag/index.cjs.map +1 -0
- package/dist/cjs/utils/ensureArrayQueryFilter.cjs +39 -0
- package/dist/cjs/utils/ensureArrayQueryFilter.cjs.map +1 -0
- package/dist/cjs/utils/ensureMongoDocumentToObject.cjs +35 -0
- package/dist/cjs/utils/ensureMongoDocumentToObject.cjs.map +1 -0
- package/dist/cjs/utils/errors/errorCodes.cjs +91 -0
- package/dist/cjs/utils/errors/errorCodes.cjs.map +1 -1
- package/dist/cjs/utils/filtersAndPagination/getDictionaryFiltersAndPagination.cjs +10 -11
- package/dist/cjs/utils/filtersAndPagination/getDictionaryFiltersAndPagination.cjs.map +1 -1
- package/dist/cjs/utils/filtersAndPagination/getOrganizationFiltersAndPagination.cjs +6 -10
- package/dist/cjs/utils/filtersAndPagination/getOrganizationFiltersAndPagination.cjs.map +1 -1
- package/dist/cjs/utils/filtersAndPagination/getProjectFiltersAndPagination.cjs +6 -10
- package/dist/cjs/utils/filtersAndPagination/getProjectFiltersAndPagination.cjs.map +1 -1
- package/dist/cjs/utils/filtersAndPagination/getTagFiltersAndPagination.cjs +51 -0
- package/dist/cjs/utils/filtersAndPagination/getTagFiltersAndPagination.cjs.map +1 -0
- package/dist/cjs/utils/filtersAndPagination/getUserFiltersAndPagination.cjs +2 -9
- package/dist/cjs/utils/filtersAndPagination/getUserFiltersAndPagination.cjs.map +1 -1
- package/dist/cjs/utils/mapper/dictionary.cjs +8 -4
- package/dist/cjs/utils/mapper/dictionary.cjs.map +1 -1
- package/dist/cjs/utils/mapper/organization.cjs +2 -4
- package/dist/cjs/utils/mapper/organization.cjs.map +1 -1
- package/dist/cjs/utils/mapper/project.cjs +2 -4
- package/dist/cjs/utils/mapper/project.cjs.map +1 -1
- package/dist/cjs/utils/mapper/tag.cjs +37 -0
- package/dist/cjs/utils/mapper/tag.cjs.map +1 -0
- package/dist/cjs/utils/mapper/user.cjs +2 -4
- package/dist/cjs/utils/mapper/user.cjs.map +1 -1
- package/dist/cjs/utils/removeObjectKeys.cjs +35 -0
- package/dist/cjs/utils/removeObjectKeys.cjs.map +1 -0
- package/dist/cjs/utils/validation/validateProject.cjs +17 -10
- package/dist/cjs/utils/validation/validateProject.cjs.map +1 -1
- package/dist/cjs/utils/validation/validateTag.cjs +93 -0
- package/dist/cjs/utils/validation/validateTag.cjs.map +1 -0
- package/dist/esm/controllers/ai.controller.mjs +155 -6
- package/dist/esm/controllers/ai.controller.mjs.map +1 -1
- package/dist/esm/controllers/dictionary.controller.mjs +50 -17
- package/dist/esm/controllers/dictionary.controller.mjs.map +1 -1
- package/dist/esm/controllers/project.controller.mjs +2 -6
- package/dist/esm/controllers/project.controller.mjs.map +1 -1
- package/dist/esm/controllers/tag.controller.mjs +203 -0
- package/dist/esm/controllers/tag.controller.mjs.map +1 -0
- package/dist/esm/controllers/user.controller.mjs +1 -0
- package/dist/esm/controllers/user.controller.mjs.map +1 -1
- package/dist/esm/export.mjs.map +1 -1
- package/dist/esm/index.mjs +2 -0
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/models/tag.model.mjs +7 -0
- package/dist/esm/models/tag.model.mjs.map +1 -0
- package/dist/esm/routes/ai.routes.mjs +37 -5
- package/dist/esm/routes/ai.routes.mjs.map +1 -1
- package/dist/esm/routes/dictionary.routes.mjs +4 -4
- package/dist/esm/routes/dictionary.routes.mjs.map +1 -1
- package/dist/esm/routes/tags.routes.mjs +40 -0
- package/dist/esm/routes/tags.routes.mjs.map +1 -0
- package/dist/esm/schemas/dictionary.schema.mjs +31 -6
- package/dist/esm/schemas/dictionary.schema.mjs.map +1 -1
- package/dist/esm/schemas/project.schema.mjs +5 -0
- package/dist/esm/schemas/project.schema.mjs.map +1 -1
- package/dist/esm/schemas/tag.schema.mjs +45 -0
- package/dist/esm/schemas/tag.schema.mjs.map +1 -0
- package/dist/esm/services/dictionary.service.mjs +137 -27
- package/dist/esm/services/dictionary.service.mjs.map +1 -1
- package/dist/esm/services/project.service.mjs +14 -5
- package/dist/esm/services/project.service.mjs.map +1 -1
- package/dist/esm/services/tag.service.mjs +61 -0
- package/dist/esm/services/tag.service.mjs.map +1 -0
- package/dist/esm/types/tag.types.mjs +1 -0
- package/dist/esm/types/tag.types.mjs.map +1 -0
- package/dist/esm/utils/{audit → auditDictionary}/PROMPT.md +6 -1
- package/dist/esm/utils/{audit → auditDictionary}/index.mjs +6 -4
- package/dist/esm/utils/auditDictionary/index.mjs.map +1 -0
- package/dist/esm/utils/auditDictionaryField/PROMPT.md +115 -0
- package/dist/esm/utils/auditDictionaryField/index.mjs +56 -0
- package/dist/esm/utils/auditDictionaryField/index.mjs.map +1 -0
- package/dist/esm/utils/auditDictionaryMetadata/PROMPT.md +76 -0
- package/dist/esm/utils/auditDictionaryMetadata/index.mjs +53 -0
- package/dist/esm/utils/auditDictionaryMetadata/index.mjs.map +1 -0
- package/dist/esm/utils/auditTag/PROMPT.md +34 -0
- package/dist/esm/utils/auditTag/index.mjs +49 -0
- package/dist/esm/utils/auditTag/index.mjs.map +1 -0
- package/dist/esm/utils/ensureArrayQueryFilter.mjs +15 -0
- package/dist/esm/utils/ensureArrayQueryFilter.mjs.map +1 -0
- package/dist/esm/utils/ensureMongoDocumentToObject.mjs +11 -0
- package/dist/esm/utils/ensureMongoDocumentToObject.mjs.map +1 -0
- package/dist/esm/utils/errors/errorCodes.mjs +91 -0
- package/dist/esm/utils/errors/errorCodes.mjs.map +1 -1
- package/dist/esm/utils/filtersAndPagination/getDictionaryFiltersAndPagination.mjs +10 -11
- package/dist/esm/utils/filtersAndPagination/getDictionaryFiltersAndPagination.mjs.map +1 -1
- package/dist/esm/utils/filtersAndPagination/getOrganizationFiltersAndPagination.mjs +6 -10
- package/dist/esm/utils/filtersAndPagination/getOrganizationFiltersAndPagination.mjs.map +1 -1
- package/dist/esm/utils/filtersAndPagination/getProjectFiltersAndPagination.mjs +6 -10
- package/dist/esm/utils/filtersAndPagination/getProjectFiltersAndPagination.mjs.map +1 -1
- package/dist/esm/utils/filtersAndPagination/getTagFiltersAndPagination.mjs +29 -0
- package/dist/esm/utils/filtersAndPagination/getTagFiltersAndPagination.mjs.map +1 -0
- package/dist/esm/utils/filtersAndPagination/getUserFiltersAndPagination.mjs +2 -9
- package/dist/esm/utils/filtersAndPagination/getUserFiltersAndPagination.mjs.map +1 -1
- package/dist/esm/utils/mapper/dictionary.mjs +8 -4
- package/dist/esm/utils/mapper/dictionary.mjs.map +1 -1
- package/dist/esm/utils/mapper/organization.mjs +2 -4
- package/dist/esm/utils/mapper/organization.mjs.map +1 -1
- package/dist/esm/utils/mapper/project.mjs +2 -4
- package/dist/esm/utils/mapper/project.mjs.map +1 -1
- package/dist/esm/utils/mapper/tag.mjs +12 -0
- package/dist/esm/utils/mapper/tag.mjs.map +1 -0
- package/dist/esm/utils/mapper/user.mjs +2 -4
- package/dist/esm/utils/mapper/user.mjs.map +1 -1
- package/dist/esm/utils/removeObjectKeys.mjs +11 -0
- package/dist/esm/utils/removeObjectKeys.mjs.map +1 -0
- package/dist/esm/utils/validation/validateProject.mjs +17 -10
- package/dist/esm/utils/validation/validateProject.mjs.map +1 -1
- package/dist/esm/utils/validation/validateTag.mjs +65 -0
- package/dist/esm/utils/validation/validateTag.mjs.map +1 -0
- package/dist/types/controllers/ai.controller.d.ts +45 -4
- package/dist/types/controllers/ai.controller.d.ts.map +1 -1
- package/dist/types/controllers/dictionary.controller.d.ts +6 -3
- package/dist/types/controllers/dictionary.controller.d.ts.map +1 -1
- package/dist/types/controllers/project.controller.d.ts +2 -4
- package/dist/types/controllers/project.controller.d.ts.map +1 -1
- package/dist/types/controllers/tag.controller.d.ts +39 -0
- package/dist/types/controllers/tag.controller.d.ts.map +1 -0
- package/dist/types/controllers/user.controller.d.ts.map +1 -1
- package/dist/types/export.d.ts +2 -0
- package/dist/types/export.d.ts.map +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/models/dictionary.model.d.ts +1 -0
- package/dist/types/models/dictionary.model.d.ts.map +1 -1
- package/dist/types/models/tag.model.d.ts +3 -0
- package/dist/types/models/tag.model.d.ts.map +1 -0
- package/dist/types/routes/ai.routes.d.ts +16 -1
- package/dist/types/routes/ai.routes.d.ts.map +1 -1
- package/dist/types/routes/dictionary.routes.d.ts +6 -2
- package/dist/types/routes/dictionary.routes.d.ts.map +1 -1
- package/dist/types/routes/tags.routes.d.ts +29 -0
- package/dist/types/routes/tags.routes.d.ts.map +1 -0
- package/dist/types/schemas/dictionary.schema.d.ts +1 -0
- package/dist/types/schemas/dictionary.schema.d.ts.map +1 -1
- package/dist/types/schemas/project.schema.d.ts.map +1 -1
- package/dist/types/schemas/tag.schema.d.ts +16 -0
- package/dist/types/schemas/tag.schema.d.ts.map +1 -0
- package/dist/types/services/dictionary.service.d.ts +10 -2
- package/dist/types/services/dictionary.service.d.ts.map +1 -1
- package/dist/types/services/project.service.d.ts.map +1 -1
- package/dist/types/services/tag.service.d.ts +45 -0
- package/dist/types/services/tag.service.d.ts.map +1 -0
- package/dist/types/types/dictionary.types.d.ts +14 -4
- package/dist/types/types/dictionary.types.d.ts.map +1 -1
- package/dist/types/types/tag.types.d.ts +26 -0
- package/dist/types/types/tag.types.d.ts.map +1 -0
- package/dist/types/utils/auditDictionary/index.d.ts +24 -0
- package/dist/types/utils/auditDictionary/index.d.ts.map +1 -0
- package/dist/types/utils/auditDictionaryField/index.d.ts +24 -0
- package/dist/types/utils/auditDictionaryField/index.d.ts.map +1 -0
- package/dist/types/utils/auditDictionaryMetadata/index.d.ts +21 -0
- package/dist/types/utils/auditDictionaryMetadata/index.d.ts.map +1 -0
- package/dist/types/utils/auditTag/index.d.ts +27 -0
- package/dist/types/utils/auditTag/index.d.ts.map +1 -0
- package/dist/types/utils/ensureArrayQueryFilter.d.ts +2 -0
- package/dist/types/utils/ensureArrayQueryFilter.d.ts.map +1 -0
- package/dist/types/utils/ensureMongoDocumentToObject.d.ts +8 -0
- package/dist/types/utils/ensureMongoDocumentToObject.d.ts.map +1 -0
- package/dist/types/utils/errors/errorCodes.d.ts +91 -0
- package/dist/types/utils/errors/errorCodes.d.ts.map +1 -1
- package/dist/types/utils/filtersAndPagination/getDictionaryFiltersAndPagination.d.ts +2 -0
- package/dist/types/utils/filtersAndPagination/getDictionaryFiltersAndPagination.d.ts.map +1 -1
- package/dist/types/utils/filtersAndPagination/getOrganizationFiltersAndPagination.d.ts.map +1 -1
- package/dist/types/utils/filtersAndPagination/getProjectFiltersAndPagination.d.ts.map +1 -1
- package/dist/types/utils/filtersAndPagination/getTagFiltersAndPagination.d.ts +24 -0
- package/dist/types/utils/filtersAndPagination/getTagFiltersAndPagination.d.ts.map +1 -0
- package/dist/types/utils/filtersAndPagination/getUserFiltersAndPagination.d.ts.map +1 -1
- package/dist/types/utils/mapper/dictionary.d.ts +1 -1
- package/dist/types/utils/mapper/dictionary.d.ts.map +1 -1
- package/dist/types/utils/mapper/organization.d.ts.map +1 -1
- package/dist/types/utils/mapper/project.d.ts.map +1 -1
- package/dist/types/utils/mapper/tag.d.ts +16 -0
- package/dist/types/utils/mapper/tag.d.ts.map +1 -0
- package/dist/types/utils/mapper/user.d.ts +2 -2
- package/dist/types/utils/mapper/user.d.ts.map +1 -1
- package/dist/types/utils/removeObjectKeys.d.ts +2 -0
- package/dist/types/utils/removeObjectKeys.d.ts.map +1 -0
- package/dist/types/utils/validation/validateProject.d.ts.map +1 -1
- package/dist/types/utils/validation/validateTag.d.ts +16 -0
- package/dist/types/utils/validation/validateTag.d.ts.map +1 -0
- package/package.json +2 -3
- package/dist/cjs/utils/audit/index.cjs.map +0 -1
- package/dist/esm/utils/audit/index.mjs.map +0 -1
- /package/dist/cjs/utils/{audit → auditDictionary}/CJS_FORMAT.md +0 -0
- /package/dist/cjs/utils/{audit → auditDictionary}/JSON_FORMAT.md +0 -0
- /package/dist/cjs/utils/{audit → auditDictionary}/JSX_FORMAT.md +0 -0
- /package/dist/cjs/utils/{audit → auditDictionary}/MJS_FORMAT.md +0 -0
- /package/dist/cjs/utils/{audit → auditDictionary}/TSX_FORMAT.md +0 -0
- /package/dist/cjs/utils/{audit → auditDictionary}/TS_FORMAT.md +0 -0
- /package/dist/esm/utils/{audit → auditDictionary}/CJS_FORMAT.md +0 -0
- /package/dist/esm/utils/{audit → auditDictionary}/JSON_FORMAT.md +0 -0
- /package/dist/esm/utils/{audit → auditDictionary}/JSX_FORMAT.md +0 -0
- /package/dist/esm/utils/{audit → auditDictionary}/MJS_FORMAT.md +0 -0
- /package/dist/esm/utils/{audit → auditDictionary}/TSX_FORMAT.md +0 -0
- /package/dist/esm/utils/{audit → auditDictionary}/TS_FORMAT.md +0 -0
|
@@ -1,34 +1,95 @@
|
|
|
1
1
|
import { DictionaryModel } from './../models/dictionary.model.mjs';
|
|
2
|
+
import { ensureMongoDocumentToObject } from './../utils/ensureMongoDocumentToObject.mjs';
|
|
2
3
|
import { GenericError } from './../utils/errors/index.mjs';
|
|
4
|
+
import { removeObjectKeys } from './../utils/removeObjectKeys.mjs';
|
|
3
5
|
import {
|
|
4
6
|
validateDictionary
|
|
5
7
|
} from './../utils/validation/validateDictionary.mjs';
|
|
6
|
-
const findDictionaries = async (filters, skip = 0, limit = 100) =>
|
|
8
|
+
const findDictionaries = async (filters, skip = 0, limit = 100) => {
|
|
9
|
+
try {
|
|
10
|
+
const dictionaries = await DictionaryModel.aggregate([
|
|
11
|
+
// Stage 1: Match the filters
|
|
12
|
+
{ $match: filters },
|
|
13
|
+
// Stage 2: Skip for pagination
|
|
14
|
+
{ $skip: skip },
|
|
15
|
+
// Stage 3: Limit the number of documents
|
|
16
|
+
{ $limit: limit },
|
|
17
|
+
// Stage 4: Add the 'availableVersions' field
|
|
18
|
+
{
|
|
19
|
+
$addFields: {
|
|
20
|
+
availableVersions: {
|
|
21
|
+
$map: {
|
|
22
|
+
input: { $objectToArray: "$content" },
|
|
23
|
+
as: "version",
|
|
24
|
+
in: "$$version.k"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// (Optional) Stage 5: Project the fields you want to include/exclude
|
|
30
|
+
// For example, to exclude the entire 'content' field and keep only 'availableVersions'
|
|
31
|
+
// {
|
|
32
|
+
// $project: {
|
|
33
|
+
// content: 0 // Exclude the 'content' field
|
|
34
|
+
// }
|
|
35
|
+
// }
|
|
36
|
+
]);
|
|
37
|
+
return dictionaries;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error("Error fetching dictionaries:", error);
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
7
43
|
const getDictionaryById = async (dictionaryId) => {
|
|
8
|
-
const dictionary = await DictionaryModel.
|
|
9
|
-
|
|
44
|
+
const dictionary = await DictionaryModel.aggregate([
|
|
45
|
+
// Stage 1: Match the document by ID
|
|
46
|
+
{ $match: { _id: dictionaryId } },
|
|
47
|
+
// Stage 2: Add the 'availableVersions' field
|
|
48
|
+
{
|
|
49
|
+
$addFields: {
|
|
50
|
+
availableVersions: {
|
|
51
|
+
$map: {
|
|
52
|
+
input: { $objectToArray: "$content" },
|
|
53
|
+
as: "version",
|
|
54
|
+
in: "$$version.k"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
]);
|
|
60
|
+
if (!dictionary.length) {
|
|
10
61
|
throw new GenericError("DICTIONARY_NOT_FOUND", { dictionaryId });
|
|
11
62
|
}
|
|
12
|
-
return dictionary;
|
|
63
|
+
return dictionary[0];
|
|
13
64
|
};
|
|
14
65
|
const getDictionaryByKey = async (dictionaryKey, projectId) => {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
66
|
+
const dictionaries = await getDictionariesByKeys([dictionaryKey], projectId);
|
|
67
|
+
console.log("dictionaries", dictionaries);
|
|
68
|
+
return dictionaries[0];
|
|
69
|
+
};
|
|
70
|
+
const getDictionariesByKeys = async (dictionaryKeys, projectId) => {
|
|
71
|
+
const dictionaries = await DictionaryModel.aggregate([
|
|
72
|
+
// Stage 1: Match the document by key
|
|
73
|
+
{ $match: { key: { $in: dictionaryKeys }, projectIds: projectId } },
|
|
74
|
+
// Stage 2: Add the 'availableVersions' field
|
|
75
|
+
{
|
|
76
|
+
$addFields: {
|
|
77
|
+
availableVersions: {
|
|
78
|
+
$map: {
|
|
79
|
+
input: { $objectToArray: "$content" },
|
|
80
|
+
as: "version",
|
|
81
|
+
in: "$$version.k"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
]);
|
|
87
|
+
if (!dictionaries) {
|
|
20
88
|
throw new GenericError("DICTIONARY_NOT_FOUND", {
|
|
21
|
-
|
|
89
|
+
dictionaryKeys,
|
|
22
90
|
projectId
|
|
23
91
|
});
|
|
24
92
|
}
|
|
25
|
-
return dictionary;
|
|
26
|
-
};
|
|
27
|
-
const getDictionariesByKeys = async (dictionaryKey, projectId) => {
|
|
28
|
-
const dictionaries = await DictionaryModel.find({
|
|
29
|
-
key: dictionaryKey,
|
|
30
|
-
projectIds: projectId
|
|
31
|
-
});
|
|
32
93
|
return dictionaries;
|
|
33
94
|
};
|
|
34
95
|
const getDictionariesKeys = async (projectId) => {
|
|
@@ -37,6 +98,30 @@ const getDictionariesKeys = async (projectId) => {
|
|
|
37
98
|
}).select("key");
|
|
38
99
|
return dictionaries.map((dictionary) => dictionary.key);
|
|
39
100
|
};
|
|
101
|
+
const getDictionariesByTags = async (tags, projectId) => {
|
|
102
|
+
const dictionaries = await DictionaryModel.aggregate([
|
|
103
|
+
// Stage 1: Match the document by tags
|
|
104
|
+
{
|
|
105
|
+
$match: {
|
|
106
|
+
tags: { $in: tags },
|
|
107
|
+
projectIds: projectId
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
// Stage 2: Add the 'availableVersions' field
|
|
111
|
+
{
|
|
112
|
+
$addFields: {
|
|
113
|
+
availableVersions: {
|
|
114
|
+
$map: {
|
|
115
|
+
input: { $objectToArray: "$content" },
|
|
116
|
+
as: "version",
|
|
117
|
+
in: "$$version.k"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
]);
|
|
123
|
+
return dictionaries;
|
|
124
|
+
};
|
|
40
125
|
const countDictionaries = async (filters) => {
|
|
41
126
|
const result = await DictionaryModel.countDocuments(filters);
|
|
42
127
|
if (typeof result === "undefined") {
|
|
@@ -73,27 +158,31 @@ const getExistingDictionaryKey = async (dictionariesKeys, projectId) => {
|
|
|
73
158
|
return { existingDictionariesKey, newDictionariesKey };
|
|
74
159
|
};
|
|
75
160
|
const updateDictionaryById = async (dictionaryId, dictionary) => {
|
|
76
|
-
const
|
|
77
|
-
const
|
|
161
|
+
const dictionaryObject = ensureMongoDocumentToObject(dictionary);
|
|
162
|
+
const dictionaryToUpdate = removeObjectKeys(dictionaryObject, ["_id"]);
|
|
163
|
+
const updatedKeys = Object.keys(dictionaryToUpdate);
|
|
164
|
+
const errors = await validateDictionary(dictionaryToUpdate, updatedKeys);
|
|
78
165
|
if (Object.keys(errors).length > 0) {
|
|
79
166
|
throw new GenericError("DICTIONARY_INVALID_FIELDS", {
|
|
80
167
|
dictionaryId,
|
|
81
168
|
errors
|
|
82
169
|
});
|
|
83
170
|
}
|
|
84
|
-
const existingDictionary = await getDictionaryById(dictionaryId);
|
|
85
171
|
const result = await DictionaryModel.updateOne(
|
|
86
172
|
{ _id: dictionaryId },
|
|
87
|
-
|
|
173
|
+
dictionaryToUpdate
|
|
88
174
|
);
|
|
89
175
|
if (result.matchedCount === 0) {
|
|
90
176
|
throw new GenericError("DICTIONARY_UPDATE_FAILED", { dictionaryId });
|
|
91
177
|
}
|
|
92
|
-
|
|
178
|
+
const updatedDictionary = await getDictionaryById(dictionaryId);
|
|
179
|
+
return updatedDictionary;
|
|
93
180
|
};
|
|
94
181
|
const updateDictionaryByKey = async (dictionaryKey, dictionary, projectId) => {
|
|
95
|
-
const
|
|
96
|
-
const
|
|
182
|
+
const dictionaryObject = ensureMongoDocumentToObject(dictionary);
|
|
183
|
+
const dictionaryToUpdate = removeObjectKeys(dictionaryObject, ["_id"]);
|
|
184
|
+
const updatedKeys = Object.keys(dictionaryToUpdate);
|
|
185
|
+
const errors = await validateDictionary(dictionaryToUpdate, updatedKeys);
|
|
97
186
|
if (Object.keys(errors).length > 0) {
|
|
98
187
|
throw new GenericError("DICTIONARY_INVALID_FIELDS", {
|
|
99
188
|
dictionaryKey,
|
|
@@ -101,15 +190,15 @@ const updateDictionaryByKey = async (dictionaryKey, dictionary, projectId) => {
|
|
|
101
190
|
errors
|
|
102
191
|
});
|
|
103
192
|
}
|
|
104
|
-
const existingDictionary = await getDictionaryByKey(dictionaryKey, projectId);
|
|
105
193
|
const result = await DictionaryModel.updateOne(
|
|
106
194
|
{ key: dictionaryKey, projectIds: projectId },
|
|
107
|
-
|
|
195
|
+
dictionaryToUpdate
|
|
108
196
|
);
|
|
109
197
|
if (result.matchedCount === 0) {
|
|
110
198
|
throw new GenericError("DICTIONARY_UPDATE_FAILED", { dictionaryKey });
|
|
111
199
|
}
|
|
112
|
-
|
|
200
|
+
const updatedDictionary = await getDictionaryByKey(dictionaryKey, projectId);
|
|
201
|
+
return updatedDictionary;
|
|
113
202
|
};
|
|
114
203
|
const deleteDictionaryById = async (dictionaryId) => {
|
|
115
204
|
const dictionary = await DictionaryModel.findByIdAndDelete(dictionaryId);
|
|
@@ -118,16 +207,37 @@ const deleteDictionaryById = async (dictionaryId) => {
|
|
|
118
207
|
}
|
|
119
208
|
return dictionary;
|
|
120
209
|
};
|
|
210
|
+
const incrementVersion = (dictionary) => {
|
|
211
|
+
const VERSION_PREFIX = "v";
|
|
212
|
+
const availableVersions = dictionary.availableVersions ?? [];
|
|
213
|
+
const currentVersion = availableVersions.length > 0 ? availableVersions[availableVersions.length - 1] : "v1";
|
|
214
|
+
const getVersionNumber = (version) => {
|
|
215
|
+
const match = version.match(/^v(\d+)$/);
|
|
216
|
+
if (!match) {
|
|
217
|
+
throw new Error(`Invalid version format: ${version}`);
|
|
218
|
+
}
|
|
219
|
+
return parseInt(match[1], 10);
|
|
220
|
+
};
|
|
221
|
+
let newNumber = getVersionNumber(currentVersion) + 1;
|
|
222
|
+
let newVersion = `${VERSION_PREFIX}${newNumber}`;
|
|
223
|
+
while (availableVersions.includes(newVersion)) {
|
|
224
|
+
newNumber += 1;
|
|
225
|
+
newVersion = `${VERSION_PREFIX}${newNumber}`;
|
|
226
|
+
}
|
|
227
|
+
return newVersion;
|
|
228
|
+
};
|
|
121
229
|
export {
|
|
122
230
|
countDictionaries,
|
|
123
231
|
createDictionary,
|
|
124
232
|
deleteDictionaryById,
|
|
125
233
|
findDictionaries,
|
|
126
234
|
getDictionariesByKeys,
|
|
235
|
+
getDictionariesByTags,
|
|
127
236
|
getDictionariesKeys,
|
|
128
237
|
getDictionaryById,
|
|
129
238
|
getDictionaryByKey,
|
|
130
239
|
getExistingDictionaryKey,
|
|
240
|
+
incrementVersion,
|
|
131
241
|
updateDictionaryById,
|
|
132
242
|
updateDictionaryByKey
|
|
133
243
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/services/dictionary.service.ts"],"sourcesContent":["import { DictionaryModel } from '@models/dictionary.model';\nimport { GenericError } from '@utils/errors';\nimport type { DictionaryFilters } from '@utils/filtersAndPagination/getDictionaryFiltersAndPagination';\nimport {\n type DictionaryFields,\n validateDictionary,\n} from '@utils/validation/validateDictionary';\nimport type { ObjectId } from 'mongoose';\nimport type {\n Dictionary,\n DictionaryData,\n DictionaryDocument,\n} from '@/types/dictionary.types';\n\n/**\n * Finds dictionaries based on filters and pagination options.\n * @param filters - MongoDB filter query.\n * @param skip - Number of documents to skip.\n * @param limit - Number of documents to limit.\n * @returns List of dictionaries matching the filters.\n */\nexport const findDictionaries = async (\n filters: DictionaryFilters,\n skip = 0,\n limit = 100\n): Promise<DictionaryDocument[]> =>\n await DictionaryModel.find(filters).skip(skip).limit(limit);\n\n/**\n * Finds a dictionary by its ID.\n * @param dictionaryId - The ID of the dictionary to find.\n * @returns The dictionary matching the ID.\n */\nexport const getDictionaryById = async (\n dictionaryId: string | ObjectId\n): Promise<DictionaryDocument> => {\n const dictionary = await DictionaryModel.findById(dictionaryId);\n\n if (!dictionary) {\n throw new GenericError('DICTIONARY_NOT_FOUND', { dictionaryId });\n }\n\n return dictionary;\n};\n\n/**\n * Finds a dictionary by its ID.\n * @param dictionaryKey - The ID of the dictionary to find.\n * @returns The dictionary matching the ID.\n */\nexport const getDictionaryByKey = async (\n dictionaryKey: string,\n projectId: string | ObjectId\n): Promise<DictionaryDocument> => {\n const dictionary = await DictionaryModel.findOne({\n key: dictionaryKey,\n projectIds: projectId,\n });\n\n if (!dictionary) {\n throw new GenericError('DICTIONARY_NOT_FOUND', {\n dictionaryKey,\n projectId,\n });\n }\n\n return dictionary;\n};\n\nexport const getDictionariesByKeys = async (\n dictionaryKey: string[],\n projectId: string | ObjectId\n): Promise<DictionaryDocument[]> => {\n const dictionaries = await DictionaryModel.find({\n key: dictionaryKey,\n projectIds: projectId,\n });\n\n return dictionaries;\n};\n\nexport const getDictionariesKeys = async (\n projectId: string | ObjectId\n): Promise<string[]> => {\n const dictionaries = await DictionaryModel.find({\n projectIds: projectId,\n }).select('key');\n\n return dictionaries.map((dictionary) => dictionary.key);\n};\n\n/**\n * Counts the total number of dictionaries that match the filters.\n * @param filters - MongoDB filter query.\n * @returns Total number of dictionaries.\n */\nexport const countDictionaries = async (\n filters: DictionaryFilters\n): Promise<number> => {\n const result = await DictionaryModel.countDocuments(filters);\n\n if (typeof result === 'undefined') {\n throw new GenericError('DICTIONARY_COUNT_FAILED', { filters });\n }\n\n return result;\n};\n\n/**\n * Creates a new dictionary in the database.\n * @param dictionary - The dictionary data to create.\n * @returns The created dictionary.\n */\nexport const createDictionary = async (\n dictionary: DictionaryData\n): Promise<DictionaryDocument> => {\n const errors = await validateDictionary(dictionary);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('DICTIONARY_INVALID_FIELDS', {\n errors,\n });\n }\n\n return await DictionaryModel.create(dictionary);\n};\n\ntype GetExistingDictionaryResult = {\n existingDictionariesKey: string[];\n newDictionariesKey: string[];\n};\n\n/**\n * Gets the existing dictionaries from the provided list of keys.\n * @param dictionariesKeys - List of dictionary keys to check.\n * @param projectId - The ID of the project to check the dictionaries against.\n * @returns The existing dictionaries and the new dictionaries.\n */\nexport const getExistingDictionaryKey = async (\n dictionariesKeys: string[],\n projectId: string | ObjectId\n): Promise<GetExistingDictionaryResult> => {\n // Fetch dictionaries from the database where the key is in the provided list\n const existingDictionaries = await DictionaryModel.find({\n key: { $in: dictionariesKeys },\n projectIds: projectId,\n });\n\n // Map existing dictionaries to a LocalDictionary object\n const existingDictionariesKey: string[] = [];\n const newDictionariesKey: string[] = [];\n\n for (const key of dictionariesKeys) {\n const isDictionaryExist = existingDictionaries.some(\n (dictionary) => dictionary.key === key\n );\n\n if (isDictionaryExist) {\n existingDictionariesKey.push(key);\n } else {\n newDictionariesKey.push(key);\n }\n }\n\n return { existingDictionariesKey, newDictionariesKey };\n};\n\n/**\n * Updates an existing dictionary in the database by its ID.\n * @param dictionaryId - The ID of the dictionary to update.\n * @param dictionary - The updated dictionary data.\n * @returns The updated dictionary.\n */\nexport const updateDictionaryById = async (\n dictionaryId: string | ObjectId,\n dictionary: Partial<Dictionary>\n): Promise<DictionaryDocument> => {\n const updatedKeys = Object.keys(dictionary) as DictionaryFields;\n const errors = validateDictionary(dictionary, updatedKeys);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('DICTIONARY_INVALID_FIELDS', {\n dictionaryId,\n errors,\n });\n }\n\n const existingDictionary = await getDictionaryById(dictionaryId);\n\n const result = await DictionaryModel.updateOne(\n { _id: dictionaryId },\n { ...dictionary, content: [existingDictionary.content, dictionary.content] }\n );\n\n if (result.matchedCount === 0) {\n throw new GenericError('DICTIONARY_UPDATE_FAILED', { dictionaryId });\n }\n\n return await getDictionaryById(dictionaryId);\n};\n\n/**\n * Updates an existing dictionary in the database by its key.\n * @param dictionaryKey - The ID of the dictionary to update.\n * @param dictionary - The updated dictionary data.\n * @returns The updated dictionary.\n */\nexport const updateDictionaryByKey = async (\n dictionaryKey: string,\n dictionary: Partial<Dictionary>,\n projectId: string | ObjectId\n): Promise<DictionaryDocument> => {\n const updatedKeys = Object.keys(dictionary) as DictionaryFields;\n const errors = validateDictionary(dictionary, updatedKeys);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('DICTIONARY_INVALID_FIELDS', {\n dictionaryKey,\n projectId,\n errors,\n });\n }\n\n const existingDictionary = await getDictionaryByKey(dictionaryKey, projectId);\n\n const result = await DictionaryModel.updateOne(\n { key: dictionaryKey, projectIds: projectId },\n { ...dictionary, content: [existingDictionary.content, dictionary.content] }\n );\n\n if (result.matchedCount === 0) {\n throw new GenericError('DICTIONARY_UPDATE_FAILED', { dictionaryKey });\n }\n\n return await getDictionaryByKey(dictionaryKey, projectId);\n};\n\n/**\n * Deletes a dictionary from the database by its ID.\n * @param dictionaryId - The ID of the dictionary to delete.\n * @returns The result of the deletion operation.\n */\nexport const deleteDictionaryById = async (\n dictionaryId: string\n): Promise<DictionaryDocument> => {\n const dictionary = await DictionaryModel.findByIdAndDelete(dictionaryId);\n\n if (!dictionary) {\n throw new GenericError('DICTIONARY_NOT_FOUND', { dictionaryId });\n }\n\n return dictionary;\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/services/dictionary.service.ts"],"sourcesContent":["import { DictionaryModel } from '@models/dictionary.model';\nimport { ensureMongoDocumentToObject } from '@utils/ensureMongoDocumentToObject';\nimport { GenericError } from '@utils/errors';\nimport type { DictionaryFilters } from '@utils/filtersAndPagination/getDictionaryFiltersAndPagination';\nimport { removeObjectKeys } from '@utils/removeObjectKeys';\nimport {\n type DictionaryFields,\n validateDictionary,\n} from '@utils/validation/validateDictionary';\nimport { ObjectId } from 'mongoose';\nimport type {\n Dictionary,\n DictionaryData,\n DictionaryDocument,\n} from '@/types/dictionary.types';\nimport type { Project } from '@/types/project.types';\n\n/**\n * Finds dictionaries based on filters and pagination options.\n * @param filters - MongoDB filter query.\n * @param skip - Number of documents to skip.\n * @param limit - Number of documents to limit.\n * @returns List of dictionaries matching the filters.\n */\nexport const findDictionaries = async (\n filters: DictionaryFilters,\n skip = 0,\n limit = 100\n): Promise<DictionaryDocument[]> => {\n try {\n const dictionaries = await DictionaryModel.aggregate<DictionaryDocument>([\n // Stage 1: Match the filters\n { $match: filters },\n\n // Stage 2: Skip for pagination\n { $skip: skip },\n\n // Stage 3: Limit the number of documents\n { $limit: limit },\n\n // Stage 4: Add the 'availableVersions' field\n {\n $addFields: {\n availableVersions: {\n $map: {\n input: { $objectToArray: '$content' },\n as: 'version',\n in: '$$version.k',\n },\n },\n },\n },\n\n // (Optional) Stage 5: Project the fields you want to include/exclude\n // For example, to exclude the entire 'content' field and keep only 'availableVersions'\n // {\n // $project: {\n // content: 0 // Exclude the 'content' field\n // }\n // }\n ]);\n\n return dictionaries;\n } catch (error) {\n console.error('Error fetching dictionaries:', error);\n throw error;\n }\n};\n\n/**\n * Finds a dictionary by its ID.\n * @param dictionaryId - The ID of the dictionary to find.\n * @returns The dictionary matching the ID.\n */\n/**\n * Finds a dictionary by its ID and includes the 'availableVersions' field.\n * @param dictionaryId - The ID of the dictionary to find.\n * @returns The dictionary matching the ID with available versions.\n */\nexport const getDictionaryById = async (\n dictionaryId: string | ObjectId\n): Promise<DictionaryDocument> => {\n const dictionary = await DictionaryModel.aggregate<DictionaryDocument>([\n // Stage 1: Match the document by ID\n { $match: { _id: dictionaryId } },\n\n // Stage 2: Add the 'availableVersions' field\n {\n $addFields: {\n availableVersions: {\n $map: {\n input: { $objectToArray: '$content' },\n as: 'version',\n in: '$$version.k',\n },\n },\n },\n },\n ]);\n\n if (!dictionary.length) {\n throw new GenericError('DICTIONARY_NOT_FOUND', { dictionaryId });\n }\n\n return dictionary[0];\n};\n\n/**\n * Finds a dictionary by its ID.\n * @param dictionaryKey - The ID of the dictionary to find.\n * @returns The dictionary matching the ID.\n */\nexport const getDictionaryByKey = async (\n dictionaryKey: string,\n projectId: string | ObjectId\n): Promise<DictionaryDocument> => {\n const dictionaries = await getDictionariesByKeys([dictionaryKey], projectId);\n\n console.log('dictionaries', dictionaries);\n\n return dictionaries[0];\n};\n\nexport const getDictionariesByKeys = async (\n dictionaryKeys: string[],\n projectId: string | ObjectId\n): Promise<DictionaryDocument[]> => {\n const dictionaries = await DictionaryModel.aggregate<DictionaryDocument>([\n // Stage 1: Match the document by key\n { $match: { key: { $in: dictionaryKeys }, projectIds: projectId } },\n\n // Stage 2: Add the 'availableVersions' field\n {\n $addFields: {\n availableVersions: {\n $map: {\n input: { $objectToArray: '$content' },\n as: 'version',\n in: '$$version.k',\n },\n },\n },\n },\n ]);\n\n if (!dictionaries) {\n throw new GenericError('DICTIONARY_NOT_FOUND', {\n dictionaryKeys,\n projectId,\n });\n }\n\n return dictionaries;\n};\n\nexport const getDictionariesKeys = async (\n projectId: string | ObjectId\n): Promise<string[]> => {\n const dictionaries = await DictionaryModel.find({\n projectIds: projectId,\n }).select('key');\n\n return dictionaries.map((dictionary) => dictionary.key);\n};\n\nexport const getDictionariesByTags = async (\n tags: string[],\n projectId: string | Project['_id']\n): Promise<DictionaryDocument[]> => {\n const dictionaries = await DictionaryModel.aggregate<DictionaryDocument>([\n // Stage 1: Match the document by tags\n {\n $match: {\n tags: { $in: tags },\n projectIds: projectId,\n },\n },\n\n // Stage 2: Add the 'availableVersions' field\n {\n $addFields: {\n availableVersions: {\n $map: {\n input: { $objectToArray: '$content' },\n as: 'version',\n in: '$$version.k',\n },\n },\n },\n },\n ]);\n\n return dictionaries;\n};\n\n/**\n * Counts the total number of dictionaries that match the filters.\n * @param filters - MongoDB filter query.\n * @returns Total number of dictionaries.\n */\nexport const countDictionaries = async (\n filters: DictionaryFilters\n): Promise<number> => {\n const result = await DictionaryModel.countDocuments(filters);\n\n if (typeof result === 'undefined') {\n throw new GenericError('DICTIONARY_COUNT_FAILED', { filters });\n }\n\n return result;\n};\n\n/**\n * Creates a new dictionary in the database.\n * @param dictionary - The dictionary data to create.\n * @returns The created dictionary.\n */\nexport const createDictionary = async (\n dictionary: DictionaryData\n): Promise<DictionaryDocument> => {\n const errors = await validateDictionary(dictionary);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('DICTIONARY_INVALID_FIELDS', {\n errors,\n });\n }\n\n return await DictionaryModel.create(dictionary);\n};\n\ntype GetExistingDictionaryResult = {\n existingDictionariesKey: string[];\n newDictionariesKey: string[];\n};\n\n/**\n * Gets the existing dictionaries from the provided list of keys.\n * @param dictionariesKeys - List of dictionary keys to check.\n * @param projectId - The ID of the project to check the dictionaries against.\n * @returns The existing dictionaries and the new dictionaries.\n */\nexport const getExistingDictionaryKey = async (\n dictionariesKeys: string[],\n projectId: string | ObjectId\n): Promise<GetExistingDictionaryResult> => {\n // Fetch dictionaries from the database where the key is in the provided list\n const existingDictionaries = await DictionaryModel.find({\n key: { $in: dictionariesKeys },\n projectIds: projectId,\n });\n\n // Map existing dictionaries to a LocalDictionary object\n const existingDictionariesKey: string[] = [];\n const newDictionariesKey: string[] = [];\n\n for (const key of dictionariesKeys) {\n const isDictionaryExist = existingDictionaries.some(\n (dictionary) => dictionary.key === key\n );\n\n if (isDictionaryExist) {\n existingDictionariesKey.push(key);\n } else {\n newDictionariesKey.push(key);\n }\n }\n\n return { existingDictionariesKey, newDictionariesKey };\n};\n\n/**\n * Updates an existing dictionary in the database by its ID.\n * @param dictionaryId - The ID of the dictionary to update.\n * @param dictionary - The updated dictionary data.\n * @returns The updated dictionary.\n */\nexport const updateDictionaryById = async (\n dictionaryId: string | ObjectId,\n dictionary: Partial<Dictionary>\n): Promise<DictionaryDocument> => {\n const dictionaryObject = ensureMongoDocumentToObject(dictionary);\n const dictionaryToUpdate = removeObjectKeys(dictionaryObject, ['_id']);\n\n const updatedKeys = Object.keys(dictionaryToUpdate) as DictionaryFields;\n const errors = await validateDictionary(dictionaryToUpdate, updatedKeys);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('DICTIONARY_INVALID_FIELDS', {\n dictionaryId,\n errors,\n });\n }\n\n const result = await DictionaryModel.updateOne(\n { _id: dictionaryId },\n dictionaryToUpdate\n );\n\n if (result.matchedCount === 0) {\n throw new GenericError('DICTIONARY_UPDATE_FAILED', { dictionaryId });\n }\n\n const updatedDictionary = await getDictionaryById(dictionaryId);\n\n return updatedDictionary;\n};\n\n/**\n * Updates an existing dictionary in the database by its key.\n * @param dictionaryKey - The ID of the dictionary to update.\n * @param dictionary - The updated dictionary data.\n * @returns The updated dictionary.\n */\nexport const updateDictionaryByKey = async (\n dictionaryKey: string,\n dictionary: Partial<Dictionary>,\n projectId: string | ObjectId\n): Promise<DictionaryDocument> => {\n const dictionaryObject = ensureMongoDocumentToObject(dictionary);\n\n const dictionaryToUpdate = removeObjectKeys(dictionaryObject, ['_id']);\n\n const updatedKeys = Object.keys(dictionaryToUpdate) as DictionaryFields;\n const errors = await validateDictionary(dictionaryToUpdate, updatedKeys);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('DICTIONARY_INVALID_FIELDS', {\n dictionaryKey,\n projectId,\n errors,\n });\n }\n\n const result = await DictionaryModel.updateOne(\n { key: dictionaryKey, projectIds: projectId },\n dictionaryToUpdate\n );\n\n if (result.matchedCount === 0) {\n throw new GenericError('DICTIONARY_UPDATE_FAILED', { dictionaryKey });\n }\n\n const updatedDictionary = await getDictionaryByKey(dictionaryKey, projectId);\n\n return updatedDictionary;\n};\n\n/**\n * Deletes a dictionary from the database by its ID.\n * @param dictionaryId - The ID of the dictionary to delete.\n * @returns The result of the deletion operation.\n */\nexport const deleteDictionaryById = async (\n dictionaryId: string\n): Promise<DictionaryDocument> => {\n const dictionary = await DictionaryModel.findByIdAndDelete(dictionaryId);\n\n if (!dictionary) {\n throw new GenericError('DICTIONARY_NOT_FOUND', { dictionaryId });\n }\n\n return dictionary;\n};\n\nexport const incrementVersion = (dictionary: Dictionary): string => {\n const VERSION_PREFIX = 'v';\n const availableVersions = dictionary.availableVersions ?? [];\n\n // Get the current version from the version list, default to 'v1' if not present\n const currentVersion =\n availableVersions.length > 0\n ? availableVersions[availableVersions.length - 1]\n : 'v1';\n\n // Function to extract the numeric part of the version\n const getVersionNumber = (version: string): number => {\n const match = version.match(/^v(\\d+)$/);\n if (!match) {\n throw new Error(`Invalid version format: ${version}`);\n }\n return parseInt(match[1], 10);\n };\n\n // Start with the next version number\n let newNumber = getVersionNumber(currentVersion) + 1;\n let newVersion = `${VERSION_PREFIX}${newNumber}`;\n\n // Loop until a unique version is found\n while (availableVersions.includes(newVersion)) {\n newNumber += 1;\n newVersion = `${VERSION_PREFIX}${newNumber}`;\n }\n\n return newVersion;\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ProjectModel } from './../models/project.model.mjs';
|
|
2
|
+
import { ensureMongoDocumentToObject } from './../utils/ensureMongoDocumentToObject.mjs';
|
|
2
3
|
import { GenericError } from './../utils/errors/index.mjs';
|
|
4
|
+
import { removeObjectKeys } from './../utils/removeObjectKeys.mjs';
|
|
3
5
|
import {
|
|
4
6
|
validateProject
|
|
5
7
|
} from './../utils/validation/validateProject.mjs';
|
|
@@ -29,10 +31,13 @@ const createProject = async (project) => {
|
|
|
29
31
|
return await ProjectModel.create(project);
|
|
30
32
|
};
|
|
31
33
|
const updateProjectById = async (projectId, project) => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
const projectObject = ensureMongoDocumentToObject(project);
|
|
35
|
+
const projectToUpdate = removeObjectKeys(projectObject, [
|
|
36
|
+
"_id",
|
|
37
|
+
"oAuth2Access",
|
|
38
|
+
"organizationId"
|
|
39
|
+
]);
|
|
40
|
+
const updatedKeys = Object.keys(projectToUpdate);
|
|
36
41
|
const errors = validateProject(project, updatedKeys);
|
|
37
42
|
if (Object.keys(errors).length > 0) {
|
|
38
43
|
throw new GenericError("PROJECT_INVALID_FIELDS", {
|
|
@@ -40,7 +45,11 @@ const updateProjectById = async (projectId, project) => {
|
|
|
40
45
|
errors
|
|
41
46
|
});
|
|
42
47
|
}
|
|
43
|
-
|
|
48
|
+
console.log("projectToUpdate", projectToUpdate);
|
|
49
|
+
const result = await ProjectModel.updateOne(
|
|
50
|
+
{ _id: projectId },
|
|
51
|
+
projectToUpdate
|
|
52
|
+
);
|
|
44
53
|
if (result.matchedCount === 0) {
|
|
45
54
|
throw new GenericError("PROJECT_UPDATE_FAILED", { projectId });
|
|
46
55
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/services/project.service.ts"],"sourcesContent":["import { ProjectModel } from '@models/project.model';\nimport { GenericError } from '@utils/errors';\nimport type { ProjectFilters } from '@utils/filtersAndPagination/getProjectFiltersAndPagination';\nimport {\n type ProjectFields,\n validateProject,\n} from '@utils/validation/validateProject';\nimport type { ObjectId } from 'mongoose';\nimport type {\n Project,\n ProjectData,\n ProjectDocument,\n} from '@/types/project.types';\n\n/**\n * Finds projects based on filters and pagination options.\n * @param filters - MongoDB filter query.\n * @param skip - Number of documents to skip.\n * @param limit - Number of documents to limit.\n * @returns List of projects matching the filters.\n */\nexport const findProjects = async (\n filters: ProjectFilters,\n skip = 0,\n limit = 100\n): Promise<ProjectDocument[]> =>\n await ProjectModel.find(filters).skip(skip).limit(limit);\n\n/**\n * Finds a project by its ID.\n * @param projectId - The ID of the project to find.\n * @returns The project matching the ID.\n */\nexport const getProjectById = async (\n projectId: string | ObjectId\n): Promise<ProjectDocument> => {\n const project = await ProjectModel.findById(projectId);\n\n if (!project) {\n throw new GenericError('PROJECT_NOT_DEFINED', { projectId });\n }\n\n return project;\n};\n\n/**\n * Counts the total number of projects that match the filters.\n * @param filters - MongoDB filter query.\n * @returns Total number of projects.\n */\nexport const countProjects = async (\n filters: ProjectFilters\n): Promise<number> => {\n const result = await ProjectModel.countDocuments(filters);\n\n if (typeof result === 'undefined') {\n throw new GenericError('PROJECT_COUNT_FAILED', { filters });\n }\n\n return result;\n};\n\n/**\n * Creates a new project in the database.\n * @param project - The project data to create.\n * @returns The created project.\n */\nexport const createProject = async (\n project: ProjectData\n): Promise<ProjectDocument> => {\n if ((project as Partial<Project>).oAuth2Access) {\n delete (project as Partial<Project>).oAuth2Access;\n }\n\n const errors = await validateProject(project, ['name']);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('PROJECT_INVALID_FIELDS', { errors });\n }\n\n return await ProjectModel.create(project);\n};\n\n/**\n * Updates an existing project in the database by its ID.\n * @param projectId - The ID of the project to update.\n * @param project - The updated project data.\n * @returns The updated project.\n */\nexport const updateProjectById = async (\n projectId: string | ObjectId,\n project: Partial<Project>\n): Promise<ProjectDocument> => {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/services/project.service.ts"],"sourcesContent":["import { ProjectModel } from '@models/project.model';\nimport { ensureMongoDocumentToObject } from '@utils/ensureMongoDocumentToObject';\nimport { GenericError } from '@utils/errors';\nimport type { ProjectFilters } from '@utils/filtersAndPagination/getProjectFiltersAndPagination';\nimport { removeObjectKeys } from '@utils/removeObjectKeys';\nimport {\n type ProjectFields,\n validateProject,\n} from '@utils/validation/validateProject';\nimport type { ObjectId } from 'mongoose';\nimport type {\n Project,\n ProjectData,\n ProjectDocument,\n} from '@/types/project.types';\n\n/**\n * Finds projects based on filters and pagination options.\n * @param filters - MongoDB filter query.\n * @param skip - Number of documents to skip.\n * @param limit - Number of documents to limit.\n * @returns List of projects matching the filters.\n */\nexport const findProjects = async (\n filters: ProjectFilters,\n skip = 0,\n limit = 100\n): Promise<ProjectDocument[]> =>\n await ProjectModel.find(filters).skip(skip).limit(limit);\n\n/**\n * Finds a project by its ID.\n * @param projectId - The ID of the project to find.\n * @returns The project matching the ID.\n */\nexport const getProjectById = async (\n projectId: string | ObjectId\n): Promise<ProjectDocument> => {\n const project = await ProjectModel.findById(projectId);\n\n if (!project) {\n throw new GenericError('PROJECT_NOT_DEFINED', { projectId });\n }\n\n return project;\n};\n\n/**\n * Counts the total number of projects that match the filters.\n * @param filters - MongoDB filter query.\n * @returns Total number of projects.\n */\nexport const countProjects = async (\n filters: ProjectFilters\n): Promise<number> => {\n const result = await ProjectModel.countDocuments(filters);\n\n if (typeof result === 'undefined') {\n throw new GenericError('PROJECT_COUNT_FAILED', { filters });\n }\n\n return result;\n};\n\n/**\n * Creates a new project in the database.\n * @param project - The project data to create.\n * @returns The created project.\n */\nexport const createProject = async (\n project: ProjectData\n): Promise<ProjectDocument> => {\n if ((project as Partial<Project>).oAuth2Access) {\n delete (project as Partial<Project>).oAuth2Access;\n }\n\n const errors = await validateProject(project, ['name']);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('PROJECT_INVALID_FIELDS', { errors });\n }\n\n return await ProjectModel.create(project);\n};\n\n/**\n * Updates an existing project in the database by its ID.\n * @param projectId - The ID of the project to update.\n * @param project - The updated project data.\n * @returns The updated project.\n */\nexport const updateProjectById = async (\n projectId: string | ObjectId,\n project: Partial<Project>\n): Promise<ProjectDocument> => {\n const projectObject = ensureMongoDocumentToObject(project);\n const projectToUpdate = removeObjectKeys(projectObject, [\n '_id',\n 'oAuth2Access',\n 'organizationId',\n ]);\n\n const updatedKeys = Object.keys(projectToUpdate) as ProjectFields;\n\n const errors = validateProject(project, updatedKeys);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('PROJECT_INVALID_FIELDS', {\n projectId,\n errors,\n });\n }\n\n console.log('projectToUpdate', projectToUpdate);\n\n const result = await ProjectModel.updateOne(\n { _id: projectId },\n projectToUpdate\n );\n\n if (result.matchedCount === 0) {\n throw new GenericError('PROJECT_UPDATE_FAILED', { projectId });\n }\n\n return await getProjectById(projectId);\n};\n\n/**\n * Deletes a project from the database by its ID.\n * @param projectId - The ID of the project to delete.\n * @returns The result of the deletion operation.\n */\nexport const deleteProjectById = async (\n projectId: string | ObjectId\n): Promise<ProjectDocument> => {\n const project = await ProjectModel.findByIdAndDelete(projectId);\n\n if (!project) {\n throw new GenericError('PROJECT_NOT_DEFINED', { projectId });\n }\n\n return project;\n};\n"],"mappings":"AAAA,SAAS,oBAAoB;AAC7B,SAAS,mCAAmC;AAC5C,SAAS,oBAAoB;AAE7B,SAAS,wBAAwB;AACjC;AAAA,EAEE;AAAA,OACK;AAeA,MAAM,eAAe,OAC1B,SACA,OAAO,GACP,QAAQ,QAER,MAAM,aAAa,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,KAAK;AAOlD,MAAM,iBAAiB,OAC5B,cAC6B;AAC7B,QAAM,UAAU,MAAM,aAAa,SAAS,SAAS;AAErD,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,aAAa,uBAAuB,EAAE,UAAU,CAAC;AAAA,EAC7D;AAEA,SAAO;AACT;AAOO,MAAM,gBAAgB,OAC3B,YACoB;AACpB,QAAM,SAAS,MAAM,aAAa,eAAe,OAAO;AAExD,MAAI,OAAO,WAAW,aAAa;AACjC,UAAM,IAAI,aAAa,wBAAwB,EAAE,QAAQ,CAAC;AAAA,EAC5D;AAEA,SAAO;AACT;AAOO,MAAM,gBAAgB,OAC3B,YAC6B;AAC7B,MAAK,QAA6B,cAAc;AAC9C,WAAQ,QAA6B;AAAA,EACvC;AAEA,QAAM,SAAS,MAAM,gBAAgB,SAAS,CAAC,MAAM,CAAC;AAEtD,MAAI,OAAO,KAAK,MAAM,EAAE,SAAS,GAAG;AAClC,UAAM,IAAI,aAAa,0BAA0B,EAAE,OAAO,CAAC;AAAA,EAC7D;AAEA,SAAO,MAAM,aAAa,OAAO,OAAO;AAC1C;AAQO,MAAM,oBAAoB,OAC/B,WACA,YAC6B;AAC7B,QAAM,gBAAgB,4BAA4B,OAAO;AACzD,QAAM,kBAAkB,iBAAiB,eAAe;AAAA,IACtD;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,cAAc,OAAO,KAAK,eAAe;AAE/C,QAAM,SAAS,gBAAgB,SAAS,WAAW;AAEnD,MAAI,OAAO,KAAK,MAAM,EAAE,SAAS,GAAG;AAClC,UAAM,IAAI,aAAa,0BAA0B;AAAA,MAC/C;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,UAAQ,IAAI,mBAAmB,eAAe;AAE9C,QAAM,SAAS,MAAM,aAAa;AAAA,IAChC,EAAE,KAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAEA,MAAI,OAAO,iBAAiB,GAAG;AAC7B,UAAM,IAAI,aAAa,yBAAyB,EAAE,UAAU,CAAC;AAAA,EAC/D;AAEA,SAAO,MAAM,eAAe,SAAS;AACvC;AAOO,MAAM,oBAAoB,OAC/B,cAC6B;AAC7B,QAAM,UAAU,MAAM,aAAa,kBAAkB,SAAS;AAE9D,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,aAAa,uBAAuB,EAAE,UAAU,CAAC;AAAA,EAC7D;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { TagModel } from './../models/tag.model.mjs';
|
|
2
|
+
import { GenericError } from './../utils/errors/index.mjs';
|
|
3
|
+
import { validateTag } from './../utils/validation/validateTag.mjs';
|
|
4
|
+
const findTags = async (filters, skip = 0, limit = 100) => await TagModel.find(filters).skip(skip).limit(limit);
|
|
5
|
+
const getTagById = async (tagId) => {
|
|
6
|
+
const tag = await TagModel.findById(tagId);
|
|
7
|
+
if (!tag) {
|
|
8
|
+
throw new GenericError("TAG_NOT_FOUND", { tagId });
|
|
9
|
+
}
|
|
10
|
+
return tag;
|
|
11
|
+
};
|
|
12
|
+
const getTagsByKeys = async (keys, organizationId) => {
|
|
13
|
+
const tags = await TagModel.find({ key: { $in: keys }, organizationId });
|
|
14
|
+
return tags;
|
|
15
|
+
};
|
|
16
|
+
const countTags = async (filters) => {
|
|
17
|
+
const result = await TagModel.countDocuments(filters);
|
|
18
|
+
if (typeof result === "undefined") {
|
|
19
|
+
throw new GenericError("TAG_COUNT_FAILED", { filters });
|
|
20
|
+
}
|
|
21
|
+
return result;
|
|
22
|
+
};
|
|
23
|
+
const createTag = async (tag) => {
|
|
24
|
+
const errors = await validateTag(tag, ["key"]);
|
|
25
|
+
if (Object.keys(errors).length > 0) {
|
|
26
|
+
throw new GenericError("TAG_INVALID_FIELDS", { errors });
|
|
27
|
+
}
|
|
28
|
+
return await TagModel.create(tag);
|
|
29
|
+
};
|
|
30
|
+
const updateTagById = async (tagId, tag) => {
|
|
31
|
+
const updatedKeys = Object.keys(tag);
|
|
32
|
+
const errors = validateTag(tag, updatedKeys);
|
|
33
|
+
if (Object.keys(errors).length > 0) {
|
|
34
|
+
throw new GenericError("TAG_INVALID_FIELDS", {
|
|
35
|
+
tagId,
|
|
36
|
+
errors
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const result = await TagModel.updateOne({ _id: tagId }, tag);
|
|
40
|
+
if (result.matchedCount === 0) {
|
|
41
|
+
throw new GenericError("TAG_UPDATE_FAILED", { tagId });
|
|
42
|
+
}
|
|
43
|
+
return await getTagById(tagId);
|
|
44
|
+
};
|
|
45
|
+
const deleteTagById = async (tagId) => {
|
|
46
|
+
const tag = await TagModel.findByIdAndDelete(tagId);
|
|
47
|
+
if (!tag) {
|
|
48
|
+
throw new GenericError("TAG_NOT_FOUND", { tagId });
|
|
49
|
+
}
|
|
50
|
+
return tag;
|
|
51
|
+
};
|
|
52
|
+
export {
|
|
53
|
+
countTags,
|
|
54
|
+
createTag,
|
|
55
|
+
deleteTagById,
|
|
56
|
+
findTags,
|
|
57
|
+
getTagById,
|
|
58
|
+
getTagsByKeys,
|
|
59
|
+
updateTagById
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=tag.service.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/services/tag.service.ts"],"sourcesContent":["import { TagModel } from '@models/tag.model';\nimport { GenericError } from '@utils/errors';\nimport type { TagFilters } from '@utils/filtersAndPagination/getTagFiltersAndPagination';\nimport { type TagFields, validateTag } from '@utils/validation/validateTag';\nimport type { ObjectId } from 'mongoose';\nimport { Organization } from '@/export';\nimport type { Tag, TagData, TagDocument } from '@/types/tag.types';\n\n/**\n * Finds tags based on filters and pagination options.\n * @param filters - MongoDB filter query.\n * @param skip - Number of documents to skip.\n * @param limit - Number of documents to limit.\n * @returns List of tags matching the filters.\n */\nexport const findTags = async (\n filters: TagFilters,\n skip = 0,\n limit = 100\n): Promise<TagDocument[]> =>\n await TagModel.find(filters).skip(skip).limit(limit);\n\n/**\n * Finds a tag by its ID.\n * @param tagId - The ID of the tag to find.\n * @returns The tag matching the ID.\n */\nexport const getTagById = async (\n tagId: string | ObjectId\n): Promise<TagDocument> => {\n const tag = await TagModel.findById(tagId);\n\n if (!tag) {\n throw new GenericError('TAG_NOT_FOUND', { tagId });\n }\n\n return tag;\n};\n\nexport const getTagsByKeys = async (\n keys: string[],\n organizationId: string | Organization['_id']\n): Promise<TagDocument[]> => {\n const tags = await TagModel.find({ key: { $in: keys }, organizationId });\n\n return tags;\n};\n\n/**\n * Counts the total number of tags that match the filters.\n * @param filters - MongoDB filter query.\n * @returns Total number of tags.\n */\nexport const countTags = async (filters: TagFilters): Promise<number> => {\n const result = await TagModel.countDocuments(filters);\n\n if (typeof result === 'undefined') {\n throw new GenericError('TAG_COUNT_FAILED', { filters });\n }\n\n return result;\n};\n\n/**\n * Creates a new tag in the database.\n * @param tag - The tag data to create.\n * @returns The created tag.\n */\nexport const createTag = async (tag: TagData): Promise<TagDocument> => {\n const errors = await validateTag(tag, ['key']);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('TAG_INVALID_FIELDS', { errors });\n }\n\n return await TagModel.create(tag);\n};\n\n/**\n * Updates an existing tag in the database by its ID.\n * @param tagId - The ID of the tag to update.\n * @param tag - The updated tag data.\n * @returns The updated tag.\n */\nexport const updateTagById = async (\n tagId: string | ObjectId,\n tag: Partial<Tag>\n): Promise<TagDocument> => {\n const updatedKeys = Object.keys(tag) as TagFields;\n\n const errors = validateTag(tag, updatedKeys);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('TAG_INVALID_FIELDS', {\n tagId,\n errors,\n });\n }\n\n const result = await TagModel.updateOne({ _id: tagId }, tag);\n\n if (result.matchedCount === 0) {\n throw new GenericError('TAG_UPDATE_FAILED', { tagId });\n }\n\n return await getTagById(tagId);\n};\n\n/**\n * Deletes a tag from the database by its ID.\n * @param tagId - The ID of the tag to delete.\n * @returns The result of the deletion operation.\n */\nexport const deleteTagById = async (\n tagId: string | ObjectId\n): Promise<TagDocument> => {\n const tag = await TagModel.findByIdAndDelete(tagId);\n\n if (!tag) {\n throw new GenericError('TAG_NOT_FOUND', { tagId });\n }\n\n return tag;\n};\n"],"mappings":"AAAA,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAE7B,SAAyB,mBAAmB;AAYrC,MAAM,WAAW,OACtB,SACA,OAAO,GACP,QAAQ,QAER,MAAM,SAAS,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,KAAK;AAO9C,MAAM,aAAa,OACxB,UACyB;AACzB,QAAM,MAAM,MAAM,SAAS,SAAS,KAAK;AAEzC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,aAAa,iBAAiB,EAAE,MAAM,CAAC;AAAA,EACnD;AAEA,SAAO;AACT;AAEO,MAAM,gBAAgB,OAC3B,MACA,mBAC2B;AAC3B,QAAM,OAAO,MAAM,SAAS,KAAK,EAAE,KAAK,EAAE,KAAK,KAAK,GAAG,eAAe,CAAC;AAEvE,SAAO;AACT;AAOO,MAAM,YAAY,OAAO,YAAyC;AACvE,QAAM,SAAS,MAAM,SAAS,eAAe,OAAO;AAEpD,MAAI,OAAO,WAAW,aAAa;AACjC,UAAM,IAAI,aAAa,oBAAoB,EAAE,QAAQ,CAAC;AAAA,EACxD;AAEA,SAAO;AACT;AAOO,MAAM,YAAY,OAAO,QAAuC;AACrE,QAAM,SAAS,MAAM,YAAY,KAAK,CAAC,KAAK,CAAC;AAE7C,MAAI,OAAO,KAAK,MAAM,EAAE,SAAS,GAAG;AAClC,UAAM,IAAI,aAAa,sBAAsB,EAAE,OAAO,CAAC;AAAA,EACzD;AAEA,SAAO,MAAM,SAAS,OAAO,GAAG;AAClC;AAQO,MAAM,gBAAgB,OAC3B,OACA,QACyB;AACzB,QAAM,cAAc,OAAO,KAAK,GAAG;AAEnC,QAAM,SAAS,YAAY,KAAK,WAAW;AAE3C,MAAI,OAAO,KAAK,MAAM,EAAE,SAAS,GAAG;AAClC,UAAM,IAAI,aAAa,sBAAsB;AAAA,MAC3C;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,MAAM,SAAS,UAAU,EAAE,KAAK,MAAM,GAAG,GAAG;AAE3D,MAAI,OAAO,iBAAiB,GAAG;AAC7B,UAAM,IAAI,aAAa,qBAAqB,EAAE,MAAM,CAAC;AAAA,EACvD;AAEA,SAAO,MAAM,WAAW,KAAK;AAC/B;AAOO,MAAM,gBAAgB,OAC3B,UACyB;AACzB,QAAM,MAAM,MAAM,SAAS,kBAAkB,KAAK;AAElD,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,aAAa,iBAAiB,EAAE,MAAM,CAAC;AAAA,EACnD;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=tag.types.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
You are an expert in internationalization and content management. Your task is to audit the content declaration files in the project and identify any potential issues or inconsistencies. Provide a detailed report of any issues found, including the file path, line number, and a brief explanation of the issue.
|
|
1
|
+
You are an expert in internationalization, copy writing and content management. Your task is to audit the content declaration files in the project and identify any potential issues or inconsistencies. Provide a detailed report of any issues found, including the file path, line number, and a brief explanation of the issue.
|
|
2
2
|
|
|
3
3
|
**Instructions:**
|
|
4
4
|
|
|
@@ -33,6 +33,7 @@ You are an expert in internationalization and content management. Your task is t
|
|
|
33
33
|
- **Manage Localizations:** If the required languages contains similar languages, as `en` and `en-GB`, consider `en` as English US and `en-GB` as English UK, and insert or review both translations to maintain clarity and correctness.
|
|
34
34
|
- **Order Translations:** If the translations are not in the same order as the required languages list, consider reordering the translations to maintain clarity and correctness.
|
|
35
35
|
- **Escape Special Characters:** If the translations contain special characters, escape them using the appropriate escape sequence.
|
|
36
|
+
- **Respect the tags instructions:** If the tags instructions are provided, ensure that the audited file adheres to them.
|
|
36
37
|
|
|
37
38
|
6. **Example Scenario:**
|
|
38
39
|
|
|
@@ -137,6 +138,10 @@ You are an expert in internationalization and content management. Your task is t
|
|
|
137
138
|
- The import of the `t` function was imported from `react-intlayer` instead of `intlayer`.
|
|
138
139
|
- A type `DeclarationContent` was added to the file to strengthen the content declaration.
|
|
139
140
|
|
|
141
|
+
**Tags Instructions:**
|
|
142
|
+
|
|
143
|
+
{{tagsInstructions}}
|
|
144
|
+
|
|
140
145
|
**File to Audit:**
|
|
141
146
|
|
|
142
147
|
{{fileContent}}
|
|
@@ -24,14 +24,16 @@ const formatLocaleWithName = (locale) => {
|
|
|
24
24
|
const localeName = getLocaleName(locale);
|
|
25
25
|
return `${locale}: ${localeName}`;
|
|
26
26
|
};
|
|
27
|
-
const
|
|
27
|
+
const formatTagInstructions = (tags = []) => tags.map((tag) => `- ${tag.key}: ${tag.instructions}`).join("\n\n");
|
|
28
|
+
const auditDictionary = async ({
|
|
28
29
|
fileContent,
|
|
29
30
|
filePath,
|
|
30
31
|
model,
|
|
31
32
|
openAiApiKey,
|
|
32
33
|
customPrompt,
|
|
33
34
|
locales,
|
|
34
|
-
defaultLocale
|
|
35
|
+
defaultLocale,
|
|
36
|
+
tags
|
|
35
37
|
}) => {
|
|
36
38
|
try {
|
|
37
39
|
const openai = new OpenAI({
|
|
@@ -48,7 +50,7 @@ const auditFile = async ({
|
|
|
48
50
|
).replace(
|
|
49
51
|
"{{declarationsContentTemplate}}",
|
|
50
52
|
FILE_TEMPLATE[fileExtension]
|
|
51
|
-
).replace("{{fileContent}}", fileContent);
|
|
53
|
+
).replace("{{fileContent}}", fileContent).replace("{{tagsInstructions}}", formatTagInstructions(tags));
|
|
52
54
|
const chatCompletion = await openai.chat.completions.create({
|
|
53
55
|
model: model ?? "gpt-4o-mini",
|
|
54
56
|
messages: [{ role: "system", content: prompt }]
|
|
@@ -66,6 +68,6 @@ const auditFile = async ({
|
|
|
66
68
|
}
|
|
67
69
|
};
|
|
68
70
|
export {
|
|
69
|
-
|
|
71
|
+
auditDictionary
|
|
70
72
|
};
|
|
71
73
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/utils/auditDictionary/index.ts"],"sourcesContent":["import { readFileSync } from 'fs';\nimport { dirname, join } from 'path';\nimport { fileURLToPath } from 'url';\nimport { getLocaleName } from '@intlayer/core';\nimport { logger } from '@logger';\nimport { Locales } from 'intlayer';\nimport { OpenAI } from 'openai';\nimport { Tag } from '@/types/tag.types';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport type AuditOptions = {\n locales: Locales[];\n defaultLocale: Locales;\n fileContent: string;\n filePath?: string;\n model?: string;\n openAiApiKey: string;\n customPrompt?: string;\n tags?: Tag[];\n};\nexport type AuditFileResultData = { fileContent: string; tokenUsed: number };\n\n/**\n * Reads the content of a file synchronously.\n *\n * @function\n * @param relativeFilePath - The relative or absolute path to the target file.\n * @returns The entire contents of the specified file as a UTF-8 encoded string.\n */\nconst getFileContent = (relativeFilePath: string): string => {\n const absolutePath = join(__dirname, relativeFilePath);\n const fileContent = readFileSync(absolutePath, 'utf-8');\n return fileContent;\n};\n\nconst FILE_TEMPLATE: Record<string, string> = {\n ts: getFileContent('./TS_FORMAT.md'),\n tsx: getFileContent('./TSX_FORMAT.md'),\n js: getFileContent('./MJS_FORMAT.md'),\n mjs: getFileContent('./MJS_FORMAT.md'),\n cjs: getFileContent('./CJS_FORMAT.md'),\n jsx: getFileContent('./JSX_FORMAT.md'),\n json: getFileContent('./JSON_FORMAT.md'),\n};\n\n// The prompt template to send to ChatGPT, requesting an audit of content declaration files.\nconst CHAT_GPT_PROMPT = getFileContent('./PROMPT.md');\n\n/**\n * Formats a locale with its full name and returns a string representation.\n *\n * @function\n * @param locale - A locale from the project's configuration (e.g., 'en-US', 'fr-FR').\n * @returns A formatted string combining the locale's name and code. Example: \"English (US): en-US\".\n */\nconst formatLocaleWithName = (locale: Locales): string => {\n // getLocaleName returns a human-readable name for the locale.\n const localeName = getLocaleName(locale);\n\n // Concatenate both the readable name and the locale code.\n return `${locale}: ${localeName}`;\n};\n\n/**\n * Formats an array of tags with their keys and instructions.\n *\n * @function\n * @param tags - An array of tags from the project's configuration.\n * @returns A string representation of the tags, with their keys and instructions.\n */\nconst formatTagInstructions = (tags: Tag[] = []) =>\n tags.map((tag) => `- ${tag.key}: ${tag.instructions}`).join('\\n\\n');\n\n/**\n * Audits a content declaration file by constructing a prompt for ChatGPT.\n * The prompt includes details about the project's locales, file paths of content declarations,\n * and requests for identifying issues or inconsistencies. It prints the prompt for each file,\n * and could be adapted to send requests to the ChatGPT model.\n */\nexport const auditDictionary = async ({\n fileContent,\n filePath,\n model,\n openAiApiKey,\n customPrompt,\n locales,\n defaultLocale,\n tags,\n}: AuditOptions): Promise<AuditFileResultData | undefined> => {\n try {\n // Optionally, you could initialize and configure the OpenAI client here, if you intend to make API calls.\n // Uncomment and configure the following lines if you have `openai` installed and want to call the API:\n\n const openai = new OpenAI({\n apiKey: openAiApiKey,\n });\n\n // Read the file's content.\n const splitted = (filePath ?? '.json').split('.');\n const fileExtension = splitted[splitted.length - 1];\n\n // Prepare the prompt for ChatGPT by replacing placeholders with actual values.\n const prompt =\n customPrompt ??\n CHAT_GPT_PROMPT.replace('{{filePath}}', filePath ?? 'Not provided')\n .replace(\n '{{defaultLocale}}',\n `{${formatLocaleWithName(defaultLocale)}}`\n )\n .replace(\n '{{otherLocales}}',\n `{${locales.map(formatLocaleWithName).join(', ')}}`\n )\n .replace(\n '{{declarationsContentTemplate}}',\n FILE_TEMPLATE[fileExtension]\n )\n .replace('{{fileContent}}', fileContent)\n .replace('{{tagsInstructions}}', formatTagInstructions(tags));\n\n // Example of how you might request a completion from ChatGPT:\n const chatCompletion = await openai.chat.completions.create({\n model: model ?? 'gpt-4o-mini',\n messages: [{ role: 'system', content: prompt }],\n });\n\n const newContent = chatCompletion.choices[0].message?.content;\n\n logger.info(\n `${chatCompletion.usage?.total_tokens} tokens used in the request`\n );\n\n return {\n fileContent: newContent ?? '',\n tokenUsed: chatCompletion.usage?.total_tokens ?? 0,\n };\n } catch (error) {\n console.error(error);\n }\n};\n"],"mappings":"AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,cAAc;AAEvB,SAAS,cAAc;AAGvB,MAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAqBxD,MAAM,iBAAiB,CAAC,qBAAqC;AAC3D,QAAM,eAAe,KAAK,WAAW,gBAAgB;AACrD,QAAM,cAAc,aAAa,cAAc,OAAO;AACtD,SAAO;AACT;AAEA,MAAM,gBAAwC;AAAA,EAC5C,IAAI,eAAe,gBAAgB;AAAA,EACnC,KAAK,eAAe,iBAAiB;AAAA,EACrC,IAAI,eAAe,iBAAiB;AAAA,EACpC,KAAK,eAAe,iBAAiB;AAAA,EACrC,KAAK,eAAe,iBAAiB;AAAA,EACrC,KAAK,eAAe,iBAAiB;AAAA,EACrC,MAAM,eAAe,kBAAkB;AACzC;AAGA,MAAM,kBAAkB,eAAe,aAAa;AASpD,MAAM,uBAAuB,CAAC,WAA4B;AAExD,QAAM,aAAa,cAAc,MAAM;AAGvC,SAAO,GAAG,MAAM,KAAK,UAAU;AACjC;AASA,MAAM,wBAAwB,CAAC,OAAc,CAAC,MAC5C,KAAK,IAAI,CAAC,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,YAAY,EAAE,EAAE,KAAK,MAAM;AAQ7D,MAAM,kBAAkB,OAAO;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAA8D;AAC5D,MAAI;AAIF,UAAM,SAAS,IAAI,OAAO;AAAA,MACxB,QAAQ;AAAA,IACV,CAAC;AAGD,UAAM,YAAY,YAAY,SAAS,MAAM,GAAG;AAChD,UAAM,gBAAgB,SAAS,SAAS,SAAS,CAAC;AAGlD,UAAM,SACJ,gBACA,gBAAgB,QAAQ,gBAAgB,YAAY,cAAc,EAC/D;AAAA,MACC;AAAA,MACA,IAAI,qBAAqB,aAAa,CAAC;AAAA,IACzC,EACC;AAAA,MACC;AAAA,MACA,IAAI,QAAQ,IAAI,oBAAoB,EAAE,KAAK,IAAI,CAAC;AAAA,IAClD,EACC;AAAA,MACC;AAAA,MACA,cAAc,aAAa;AAAA,IAC7B,EACC,QAAQ,mBAAmB,WAAW,EACtC,QAAQ,wBAAwB,sBAAsB,IAAI,CAAC;AAGhE,UAAM,iBAAiB,MAAM,OAAO,KAAK,YAAY,OAAO;AAAA,MAC1D,OAAO,SAAS;AAAA,MAChB,UAAU,CAAC,EAAE,MAAM,UAAU,SAAS,OAAO,CAAC;AAAA,IAChD,CAAC;AAED,UAAM,aAAa,eAAe,QAAQ,CAAC,EAAE,SAAS;AAEtD,WAAO;AAAA,MACL,GAAG,eAAe,OAAO,YAAY;AAAA,IACvC;AAEA,WAAO;AAAA,MACL,aAAa,cAAc;AAAA,MAC3B,WAAW,eAAe,OAAO,gBAAgB;AAAA,IACnD;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,KAAK;AAAA,EACrB;AACF;","names":[]}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
You are an expert in internationalization, copy writing and content management. Your task is to audit the given element into the content declaration file. If the element is not declared, review it. If this element is missing, write it by considering the given context of the content declaration, and by following instructions.
|
|
2
|
+
|
|
3
|
+
**Instructions:**
|
|
4
|
+
|
|
5
|
+
1. **Terminology:**
|
|
6
|
+
|
|
7
|
+
- **Content Declaration:** A content declaration is a is a file (.ts, .js or .json) that contains the multilingual declaration related to a specific content. A content declaration file is usually related to a specific component, or page or section of a website.
|
|
8
|
+
- **Tag:** A tag is attached to a content declaration and is used to group content declaration and harmonize them.
|
|
9
|
+
- **KeyPath** The KeyPath correspond to to the path to retrieve the targeted element from the `content` key of the content declaration file.
|
|
10
|
+
|
|
11
|
+
2. **Locales:**
|
|
12
|
+
|
|
13
|
+
- Required Locales: {{otherLocales}}
|
|
14
|
+
|
|
15
|
+
3. **Audit Requirements:**
|
|
16
|
+
|
|
17
|
+
- **Consistency:** Ensure that all keys have translations for all specified locales.
|
|
18
|
+
- **Missing Content:** Identify any missing translations and specify the expected content.
|
|
19
|
+
- **Misplaced Content:** Detect if any translations are placed under incorrect keys.
|
|
20
|
+
- **Type Compliance:** Verify that the content types match the declarations (e.g., strings, string arrays).
|
|
21
|
+
|
|
22
|
+
4. **Modification Guidelines:**
|
|
23
|
+
|
|
24
|
+
- **Return Only the Targeted Content:** Provide the updated targeted content as plain text without any markdown, additional comments or explanations.
|
|
25
|
+
- **Consider the locale context:** If the targeted field correspond to a specific language, contains similar languages, as `zh` or `en-GB`, consider return the content in this specified language.
|
|
26
|
+
- **Escape Special Characters:** If the translations contain special characters, escape them using the appropriate escape sequence.
|
|
27
|
+
- **Respect the tags instructions:** If the tags instructions are provided, ensure that the audited file adheres to them.
|
|
28
|
+
|
|
29
|
+
5. **Example Scenario:**
|
|
30
|
+
|
|
31
|
+
- **Example 1:**
|
|
32
|
+
|
|
33
|
+
- **Input File:**
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { t, type DeclarationContent } from "intlayer";
|
|
37
|
+
|
|
38
|
+
export default {
|
|
39
|
+
key: "creative-work-structured-data",
|
|
40
|
+
content: {
|
|
41
|
+
audienceType: t({
|
|
42
|
+
en: "Developers, Content Managers",
|
|
43
|
+
fr: "Développeurs, Responsables de contenu",
|
|
44
|
+
es: "",
|
|
45
|
+
}),
|
|
46
|
+
},
|
|
47
|
+
} satisfies DeclarationContent;
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- **Input keyPath:**
|
|
51
|
+
|
|
52
|
+
`[{type: "object", key: "audienceType"},{type: "translation", key: "es"}]`
|
|
53
|
+
|
|
54
|
+
- **Expected Output:**
|
|
55
|
+
|
|
56
|
+
Desarrolladores, Gestores de Contenido
|
|
57
|
+
|
|
58
|
+
- **Example 2:**
|
|
59
|
+
|
|
60
|
+
- **Input File:**
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { t, enu, type DeclarationContent } from "intlayer";
|
|
64
|
+
|
|
65
|
+
const content = {
|
|
66
|
+
key: "creative-work-structured-data",
|
|
67
|
+
content: {
|
|
68
|
+
en: {
|
|
69
|
+
audienceType: t({
|
|
70
|
+
en: "Developers, Content Managers",
|
|
71
|
+
fr: "Développeurs, Responsables de contenu",
|
|
72
|
+
es: "Desarrolladores, Gestores de Contenido",
|
|
73
|
+
}),
|
|
74
|
+
},
|
|
75
|
+
audienceType: {
|
|
76
|
+
object1: enu({
|
|
77
|
+
"1": t({
|
|
78
|
+
en: "Developers, Content Managers",
|
|
79
|
+
es: "Desarrolladores, Gestores de Contenido",
|
|
80
|
+
fr: "Développeurs, Responsables de contenu",
|
|
81
|
+
}),
|
|
82
|
+
">2": t({
|
|
83
|
+
en: "Developers, Content Managers",
|
|
84
|
+
es: "Desarrolladores, Gestores de Contenido",
|
|
85
|
+
fr: "Here content thst make no sense and should be replaced",
|
|
86
|
+
}),
|
|
87
|
+
}),
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
} satisfies DeclarationContent;
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- **Input target:**
|
|
94
|
+
|
|
95
|
+
`[{type: "object", key: "audienceType"},{type: "enumeration", key: ">2"},{type: "object", key: "audienceType"},{type: "translation", key: "es"}]`
|
|
96
|
+
|
|
97
|
+
- **Expected Output:**
|
|
98
|
+
|
|
99
|
+
Développeurs, Responsables de contenu
|
|
100
|
+
|
|
101
|
+
**Tags Instructions:**
|
|
102
|
+
|
|
103
|
+
{{tagsInstructions}}
|
|
104
|
+
|
|
105
|
+
**File to Audit:**
|
|
106
|
+
|
|
107
|
+
{{fileContent}}
|
|
108
|
+
|
|
109
|
+
**KeyPath:**
|
|
110
|
+
|
|
111
|
+
{{keyPath}}
|
|
112
|
+
|
|
113
|
+
**Expected Response:**
|
|
114
|
+
|
|
115
|
+
After auditing, provide only the targeted content as plain text without any Markdown or code block formatting. If no changes are needed, return the targeted content
|