@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
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { dirname, join } from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
import { getLocaleName } from "@intlayer/core";
|
|
5
|
+
import { logger } from './../../logger/index.mjs';
|
|
6
|
+
import { OpenAI } from "openai";
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const getFileContent = (relativeFilePath) => {
|
|
9
|
+
const absolutePath = join(__dirname, relativeFilePath);
|
|
10
|
+
const fileContent = readFileSync(absolutePath, "utf-8");
|
|
11
|
+
return fileContent;
|
|
12
|
+
};
|
|
13
|
+
const CHAT_GPT_PROMPT = getFileContent("./PROMPT.md");
|
|
14
|
+
const formatLocaleWithName = (locale) => {
|
|
15
|
+
const localeName = getLocaleName(locale);
|
|
16
|
+
return `${locale}: ${localeName}`;
|
|
17
|
+
};
|
|
18
|
+
const formatTagInstructions = (tags = []) => tags.map((tag) => `- ${tag.key}: ${tag.instructions}`).join("\n\n");
|
|
19
|
+
const auditDictionaryField = async ({
|
|
20
|
+
fileContent,
|
|
21
|
+
model,
|
|
22
|
+
openAiApiKey,
|
|
23
|
+
customPrompt,
|
|
24
|
+
locales,
|
|
25
|
+
keyPath,
|
|
26
|
+
tags
|
|
27
|
+
}) => {
|
|
28
|
+
try {
|
|
29
|
+
const openai = new OpenAI({
|
|
30
|
+
apiKey: openAiApiKey
|
|
31
|
+
});
|
|
32
|
+
const prompt = customPrompt ?? CHAT_GPT_PROMPT.replace(
|
|
33
|
+
"{{otherLocales}}",
|
|
34
|
+
`{${locales.map(formatLocaleWithName).join(", ")}}`
|
|
35
|
+
).replace("{{keyPath}}", JSON.stringify(keyPath)).replace("{{fileContent}}", fileContent).replace("{{tagsInstructions}}", formatTagInstructions(tags));
|
|
36
|
+
const chatCompletion = await openai.chat.completions.create({
|
|
37
|
+
model: model ?? "gpt-4o-mini",
|
|
38
|
+
messages: [{ role: "system", content: prompt }]
|
|
39
|
+
});
|
|
40
|
+
const newContent = chatCompletion.choices[0].message?.content;
|
|
41
|
+
logger.info(
|
|
42
|
+
`${chatCompletion.usage?.total_tokens} tokens used in the request`
|
|
43
|
+
);
|
|
44
|
+
console.log("newContent", newContent);
|
|
45
|
+
return {
|
|
46
|
+
fileContent: newContent ?? "",
|
|
47
|
+
tokenUsed: chatCompletion.usage?.total_tokens ?? 0
|
|
48
|
+
};
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error(error);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
export {
|
|
54
|
+
auditDictionaryField
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/utils/auditDictionaryField/index.ts"],"sourcesContent":["import { readFileSync } from 'fs';\nimport { dirname, join } from 'path';\nimport { fileURLToPath } from 'url';\nimport { getLocaleName, type KeyPath } 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 AuditDictionaryFieldOptions = {\n locales: Locales[];\n fileContent: string;\n model?: string;\n openAiApiKey: string;\n customPrompt?: string;\n keyPath: KeyPath[];\n tags?: Tag[];\n};\nexport type AuditDictionaryFieldResultData = {\n fileContent: string;\n tokenUsed: number;\n};\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\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 auditDictionaryField = async ({\n fileContent,\n model,\n openAiApiKey,\n customPrompt,\n locales,\n keyPath,\n tags,\n}: AuditDictionaryFieldOptions): Promise<\n AuditDictionaryFieldResultData | undefined\n> => {\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 // Prepare the prompt for ChatGPT by replacing placeholders with actual values.\n const prompt =\n customPrompt ??\n CHAT_GPT_PROMPT.replace(\n '{{otherLocales}}',\n `{${locales.map(formatLocaleWithName).join(', ')}}`\n )\n .replace('{{keyPath}}', JSON.stringify(keyPath))\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 console.log('newContent', newContent);\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,qBAAmC;AAC5C,SAAS,cAAc;AAEvB,SAAS,cAAc;AAGvB,MAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAuBxD,MAAM,iBAAiB,CAAC,qBAAqC;AAC3D,QAAM,eAAe,KAAK,WAAW,gBAAgB;AACrD,QAAM,cAAc,aAAa,cAAc,OAAO;AACtD,SAAO;AACT;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,uBAAuB,OAAO;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAEK;AACH,MAAI;AAIF,UAAM,SAAS,IAAI,OAAO;AAAA,MACxB,QAAQ;AAAA,IACV,CAAC;AAGD,UAAM,SACJ,gBACA,gBAAgB;AAAA,MACd;AAAA,MACA,IAAI,QAAQ,IAAI,oBAAoB,EAAE,KAAK,IAAI,CAAC;AAAA,IAClD,EACG,QAAQ,eAAe,KAAK,UAAU,OAAO,CAAC,EAC9C,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,YAAQ,IAAI,cAAc,UAAU;AAEpC,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,76 @@
|
|
|
1
|
+
Your role is to review content declaration fields. Correct this fields if they are misspelled or do not match the expected content, and / or complete missing content.
|
|
2
|
+
|
|
3
|
+
1. **Terminology:**
|
|
4
|
+
|
|
5
|
+
- **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.
|
|
6
|
+
- **Tag:** A tag is attached to a content declaration and is used to group content declaration and harmonize them.
|
|
7
|
+
|
|
8
|
+
2. **Audit Requirements:**
|
|
9
|
+
|
|
10
|
+
- **Do Not Alter Structure:** If the file structure is correct, do not modify it. Only add, update, or remove content declarations as necessary.
|
|
11
|
+
- **Misspelled Content:** If declared, detect each `title`, `description` and `tags` are not misspelled. If some content is misspelled, correct it.
|
|
12
|
+
|
|
13
|
+
3. **Fields functions:**
|
|
14
|
+
|
|
15
|
+
- **Title:** The title of the content declaration allows to easily identify it. It should be considered as a readable way to represent the `key` (example: `page-metadata` -> `Page metadata`). It should be a short and descriptive title that accurately reflects the dictionary.
|
|
16
|
+
- **Description:** The description of the content declaration provides a brief summary of the content declaration. It should be a concise and informative description that explains the purpose and content of the dictionary.
|
|
17
|
+
- **Tags:** The tags is an array of strings that represent the key of the tags associated with the content declaration.
|
|
18
|
+
|
|
19
|
+
**Expected Response:**
|
|
20
|
+
|
|
21
|
+
After completion, provide only the final title, description and tags fields in a JSON without any Markdown, code block formatting or any additional comments or explanations.
|
|
22
|
+
|
|
23
|
+
**Example of expected response:**
|
|
24
|
+
|
|
25
|
+
- Entry:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { t, type DeclarationContent } from "intlayer";
|
|
29
|
+
import { Metadata } from "next";
|
|
30
|
+
|
|
31
|
+
const metadataContent = {
|
|
32
|
+
key: "pricing-metadata",
|
|
33
|
+
title: "",
|
|
34
|
+
description:
|
|
35
|
+
"here a description that doesn't make any sense and should be replaced",
|
|
36
|
+
content: {
|
|
37
|
+
title: t({
|
|
38
|
+
en: "Pricing | Intlayer",
|
|
39
|
+
fr: "Tarification | Intlayer",
|
|
40
|
+
es: "Precios | Intlayer",
|
|
41
|
+
}),
|
|
42
|
+
description: t({
|
|
43
|
+
en: "Discover our pricing plans and get access to premium features with Intlayer. Choose the plan that suits you best.",
|
|
44
|
+
fr: "Découvrez nos plans tarifaires et accédez aux fonctionnalités premium avec Intlayer. Choisissez le plan qui vous convient le mieux.",
|
|
45
|
+
es: "Descubre nuestros planes de precios y accede a funciones premium con Intlayer. Elige el plan que mejor te convenga.",
|
|
46
|
+
}),
|
|
47
|
+
keywords: t<string[]>({
|
|
48
|
+
en: ["Pricing", "Subscription"],
|
|
49
|
+
fr: ["Tarification", "Abonnement"],
|
|
50
|
+
es: ["Precios", "Suscripción"],
|
|
51
|
+
}),
|
|
52
|
+
},
|
|
53
|
+
} satisfies DeclarationContent<Metadata>;
|
|
54
|
+
|
|
55
|
+
export default metadataContent;
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- Response:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"title": "Pricing page metadata",
|
|
63
|
+
"description": "Metadata related to the pricing page, includes title, description, keywords, metadata for SEO purpose. It will help search engines understand the content of the page.",
|
|
64
|
+
"tags": ["page metadata", "pricing page"]
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**List of existing Tags:**
|
|
69
|
+
|
|
70
|
+
Here the list of existing tags as a context to help you to pick related ones.
|
|
71
|
+
|
|
72
|
+
{{tags}}
|
|
73
|
+
|
|
74
|
+
**Content Declaration to complete:**
|
|
75
|
+
|
|
76
|
+
{{contentDeclaration}}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { dirname, join } from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
import { logger } from './../../logger/index.mjs';
|
|
5
|
+
import { OpenAI } from "openai";
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const getFileContent = (relativeFilePath) => {
|
|
8
|
+
const absolutePath = join(__dirname, relativeFilePath);
|
|
9
|
+
const fileContent = readFileSync(absolutePath, "utf-8");
|
|
10
|
+
return fileContent;
|
|
11
|
+
};
|
|
12
|
+
const CHAT_GPT_PROMPT = getFileContent("./PROMPT.md");
|
|
13
|
+
const auditDictionaryMetadata = async ({
|
|
14
|
+
model,
|
|
15
|
+
openAiApiKey,
|
|
16
|
+
customPrompt,
|
|
17
|
+
tags,
|
|
18
|
+
fileContent
|
|
19
|
+
}) => {
|
|
20
|
+
try {
|
|
21
|
+
const openai = new OpenAI({
|
|
22
|
+
apiKey: openAiApiKey
|
|
23
|
+
});
|
|
24
|
+
const prompt = customPrompt ?? CHAT_GPT_PROMPT.replace(
|
|
25
|
+
"{{tags}}",
|
|
26
|
+
`${JSON.stringify(
|
|
27
|
+
tags.map(({ key, description }) => `- ${key}: ${description}`).join("\n\n"),
|
|
28
|
+
null,
|
|
29
|
+
2
|
|
30
|
+
)}`
|
|
31
|
+
).replace("{{contentDeclaration}}", fileContent);
|
|
32
|
+
console.log("prompt", prompt);
|
|
33
|
+
const chatCompletion = await openai.chat.completions.create({
|
|
34
|
+
model: model ?? "gpt-4o-mini",
|
|
35
|
+
messages: [{ role: "system", content: prompt }]
|
|
36
|
+
});
|
|
37
|
+
const newContent = chatCompletion.choices[0].message?.content;
|
|
38
|
+
console.log("newContent", newContent);
|
|
39
|
+
logger.info(
|
|
40
|
+
`${chatCompletion.usage?.total_tokens} tokens used in the request`
|
|
41
|
+
);
|
|
42
|
+
return {
|
|
43
|
+
fileContent: newContent ?? "",
|
|
44
|
+
tokenUsed: chatCompletion.usage?.total_tokens ?? 0
|
|
45
|
+
};
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error(error);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
export {
|
|
51
|
+
auditDictionaryMetadata
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/utils/auditDictionaryMetadata/index.ts"],"sourcesContent":["import { readFileSync } from 'fs';\nimport { dirname, join } from 'path';\nimport { fileURLToPath } from 'url';\nimport { logger } from '@logger';\nimport { OpenAI } from 'openai';\nimport { Tag } from '@/types/tag.types';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport type AuditOptions = {\n tags: Tag[];\n fileContent: string;\n model?: string;\n openAiApiKey: string;\n customPrompt?: string;\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\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 * 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 *\n */\nexport const auditDictionaryMetadata = async ({\n model,\n openAiApiKey,\n customPrompt,\n tags,\n fileContent,\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 // Prepare the prompt for ChatGPT by replacing placeholders with actual values.\n const prompt =\n customPrompt ??\n CHAT_GPT_PROMPT.replace(\n '{{tags}}',\n `${JSON.stringify(\n tags\n .map(({ key, description }) => `- ${key}: ${description}`)\n .join('\\n\\n'),\n null,\n 2\n )}`\n ).replace('{{contentDeclaration}}', fileContent);\n\n console.log('prompt', prompt);\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 console.log('newContent', newContent);\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,cAAc;AACvB,SAAS,cAAc;AAGvB,MAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAkBxD,MAAM,iBAAiB,CAAC,qBAAqC;AAC3D,QAAM,eAAe,KAAK,WAAW,gBAAgB;AACrD,QAAM,cAAc,aAAa,cAAc,OAAO;AACtD,SAAO;AACT;AAGA,MAAM,kBAAkB,eAAe,aAAa;AAS7C,MAAM,0BAA0B,OAAO;AAAA,EAC5C;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,SACJ,gBACA,gBAAgB;AAAA,MACd;AAAA,MACA,GAAG,KAAK;AAAA,QACN,KACG,IAAI,CAAC,EAAE,KAAK,YAAY,MAAM,KAAK,GAAG,KAAK,WAAW,EAAE,EACxD,KAAK,MAAM;AAAA,QACd;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,EAAE,QAAQ,0BAA0B,WAAW;AAEjD,YAAQ,IAAI,UAAU,MAAM;AAG5B,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,YAAQ,IAAI,cAAc,UAAU;AAEpC,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,34 @@
|
|
|
1
|
+
Your role is to review a tag. A tag is attached to a content declaration and is used to group content declarations and harmonize them.
|
|
2
|
+
|
|
3
|
+
- Here an example of a tag of a random project:
|
|
4
|
+
|
|
5
|
+
````json
|
|
6
|
+
{
|
|
7
|
+
"key": "page-metadata",
|
|
8
|
+
"name": "Page metadata",
|
|
9
|
+
"description": "Contain all metadata related to the page, such as title, description, keywords, etc for SEO purpose. It will help search engines understand the content of the page.",
|
|
10
|
+
"instructions": "## Metadata Tag//## Content Declaration structure//A content declaration containing this tag should a least includes the following fields://- title/- description/- keywords//### Example of structure//```json/{/ \"key\": \"...\",/ \"content\": {/ \"title\": \"...\",/ \"description\": \"...\",/ \"keywords\": [\"...\", \"...\", \"...\"]/ }/}/```//## Fields instructions//### 1. **Title Tag**//#### **Purpose**//The title tag defines the title of your webpage. It's displayed on search engine results pages (SERPs) as the clickable headline and is essential for both SEO and user experience.//#### **Best Practices**//- **Length:** Aim for **50-60 characters**. Search engines typically display the first 50-60 characters of a title tag. Titles longer than this may be truncated./- **Keywords:** Include primary keywords relevant to the page content, preferably toward the beginning./- **Clarity and Relevance:** Ensure the title accurately reflects the content of the page./- **Branding:** If appropriate, include your brand name at the end of the title (e.g., \"How to Bake a Cake | YourBrand\")./- **Uniqueness:** Each page on your website should have a unique title to avoid confusion and duplication issues.//### 2. **Meta Description**//#### **Purpose**//The meta description provides a brief summary of the webpage's content. While not a direct ranking factor, a compelling meta description can improve click-through rates (CTR) from SERPs.//#### **Best Practices**//- **Length:** Keep it between **150-160 characters**. Descriptions longer than this may be cut off in search results./- **Engaging and Inviting:** Write a clear, concise, and enticing summary that encourages users to click./- **Include Keywords:** Incorporate relevant keywords naturally, as they may be bolded in SERPs when they match the search query./- **Call to Action (CTA):** Use action-oriented language (e.g., \"Learn more,\" \"Discover,\" \"Get started\")./- **Unique Descriptions:** Ensure each page has a unique meta description to differentiate it from others.//### 3. **Meta Keywords**//#### **Purpose**//Historically used to list important keywords for a webpage. However, most modern search engines no longer use meta keywords for ranking.//#### **Best Practices**//- **Page Related Keywords:** The provided keywords should be relevant to the content of the page./- **Uniqueness:** Each page on your website should have a unique set of keywords to avoid confusion and duplication issues./- **Keyword number:** The number of keywords should be between 3-10."
|
|
11
|
+
}
|
|
12
|
+
````
|
|
13
|
+
|
|
14
|
+
1. **Audit Requirements:**
|
|
15
|
+
|
|
16
|
+
- **Misplaced Content:** Detect each `title`, `description` and `instructions` are defined correct. If not, provide the expected content.
|
|
17
|
+
- **Ensure Conherence with dictionary:** Ensure that the key instruction make sense with the content declaration to which the given tag is attached. If the instructions doesn't looks appropriate, suggest a new one.
|
|
18
|
+
|
|
19
|
+
2. **Modification Guidelines:**
|
|
20
|
+
|
|
21
|
+
- **Do Not Alter Structure:** If the file structure is correct, do not modify it. Only add, update, or remove content declarations as necessary.
|
|
22
|
+
- **Return Only Final File Content:** Provide the updated file content without any additional comments or explanations.
|
|
23
|
+
|
|
24
|
+
**Tags to Audit:**
|
|
25
|
+
|
|
26
|
+
{{tag}}
|
|
27
|
+
|
|
28
|
+
**Content Declaration that attach the tag into:**
|
|
29
|
+
|
|
30
|
+
{{contentDeclarations}}
|
|
31
|
+
|
|
32
|
+
**Expected Response:**
|
|
33
|
+
|
|
34
|
+
After auditing, provide only the final content of the file as plain text without any Markdown or code block formatting. If no changes are needed, return the file content exactly as it is.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { dirname, join } from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
import { logger } from './../../logger/index.mjs';
|
|
5
|
+
import { OpenAI } from "openai";
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const getFileContent = (relativeFilePath) => {
|
|
8
|
+
const absolutePath = join(__dirname, relativeFilePath);
|
|
9
|
+
const fileContent = readFileSync(absolutePath, "utf-8");
|
|
10
|
+
return fileContent;
|
|
11
|
+
};
|
|
12
|
+
const CHAT_GPT_PROMPT = getFileContent("./PROMPT.md");
|
|
13
|
+
const auditTag = async ({
|
|
14
|
+
model,
|
|
15
|
+
openAiApiKey,
|
|
16
|
+
customPrompt,
|
|
17
|
+
tag,
|
|
18
|
+
dictionaries
|
|
19
|
+
}) => {
|
|
20
|
+
try {
|
|
21
|
+
const openai = new OpenAI({
|
|
22
|
+
apiKey: openAiApiKey
|
|
23
|
+
});
|
|
24
|
+
const prompt = customPrompt ?? CHAT_GPT_PROMPT.replace("{{tag}}", `${JSON.stringify(tag)}`).replace(
|
|
25
|
+
"{{contentDeclarations}}",
|
|
26
|
+
dictionaries.map((dictionary) => `- ${JSON.stringify(dictionary)}`).join("\n\n")
|
|
27
|
+
);
|
|
28
|
+
console.log("prompt", prompt);
|
|
29
|
+
const chatCompletion = await openai.chat.completions.create({
|
|
30
|
+
model: model ?? "gpt-4o-mini",
|
|
31
|
+
messages: [{ role: "system", content: prompt }]
|
|
32
|
+
});
|
|
33
|
+
const newContent = chatCompletion.choices[0].message?.content;
|
|
34
|
+
console.log("newContent", newContent);
|
|
35
|
+
logger.info(
|
|
36
|
+
`${chatCompletion.usage?.total_tokens} tokens used in the request`
|
|
37
|
+
);
|
|
38
|
+
return {
|
|
39
|
+
fileContent: newContent ?? "",
|
|
40
|
+
tokenUsed: chatCompletion.usage?.total_tokens ?? 0
|
|
41
|
+
};
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error(error);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
export {
|
|
47
|
+
auditTag
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/utils/auditTag/index.ts"],"sourcesContent":["import { readFileSync } from 'fs';\nimport { dirname, join } from 'path';\nimport { fileURLToPath } from 'url';\nimport { logger } from '@logger';\nimport { OpenAI } from 'openai';\nimport { Dictionary } from '@/types/dictionary.types';\nimport { Tag } from '@/types/tag.types';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport type AuditOptions = {\n tag: Tag;\n dictionaries: Dictionary[];\n model?: string;\n openAiApiKey: string;\n customPrompt?: string;\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\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 * 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 *\n * @async\n * @function\n * @param filePath - The relative or absolute path to the target file.\n * @param options - Optional configuration for the audit process.\n * @returns This function returns a Promise that resolves once the audit is complete.\n */\nexport const auditTag = async ({\n model,\n openAiApiKey,\n customPrompt,\n tag,\n dictionaries,\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 // Prepare the prompt for ChatGPT by replacing placeholders with actual values.\n const prompt =\n customPrompt ??\n CHAT_GPT_PROMPT.replace('{{tag}}', `${JSON.stringify(tag)}`).replace(\n '{{contentDeclarations}}',\n dictionaries\n .map((dictionary) => `- ${JSON.stringify(dictionary)}`)\n .join('\\n\\n')\n );\n\n console.log('prompt', prompt);\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 console.log('newContent', newContent);\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,cAAc;AACvB,SAAS,cAAc;AAIvB,MAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAkBxD,MAAM,iBAAiB,CAAC,qBAAqC;AAC3D,QAAM,eAAe,KAAK,WAAW,gBAAgB;AACrD,QAAM,cAAc,aAAa,cAAc,OAAO;AACtD,SAAO;AACT;AAGA,MAAM,kBAAkB,eAAe,aAAa;AAc7C,MAAM,WAAW,OAAO;AAAA,EAC7B;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,SACJ,gBACA,gBAAgB,QAAQ,WAAW,GAAG,KAAK,UAAU,GAAG,CAAC,EAAE,EAAE;AAAA,MAC3D;AAAA,MACA,aACG,IAAI,CAAC,eAAe,KAAK,KAAK,UAAU,UAAU,CAAC,EAAE,EACrD,KAAK,MAAM;AAAA,IAChB;AAEF,YAAQ,IAAI,UAAU,MAAM;AAG5B,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,YAAQ,IAAI,cAAc,UAAU;AAEpC,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,15 @@
|
|
|
1
|
+
const ensureArrayQueryFilter = (filter) => {
|
|
2
|
+
let idsArray;
|
|
3
|
+
if (typeof filter === "string") {
|
|
4
|
+
idsArray = filter.split(",");
|
|
5
|
+
} else if (Array.isArray(filter)) {
|
|
6
|
+
idsArray = filter;
|
|
7
|
+
} else {
|
|
8
|
+
idsArray = [];
|
|
9
|
+
}
|
|
10
|
+
return idsArray;
|
|
11
|
+
};
|
|
12
|
+
export {
|
|
13
|
+
ensureArrayQueryFilter
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=ensureArrayQueryFilter.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/ensureArrayQueryFilter.ts"],"sourcesContent":["export const ensureArrayQueryFilter = (\n filter: string | string[] | undefined\n): string[] | undefined => {\n let idsArray: string[];\n\n if (typeof filter === 'string') {\n idsArray = filter.split(',');\n } else if (Array.isArray(filter)) {\n idsArray = filter;\n } else {\n idsArray = [];\n }\n\n return idsArray;\n};\n"],"mappings":"AAAO,MAAM,yBAAyB,CACpC,WACyB;AACzB,MAAI;AAEJ,MAAI,OAAO,WAAW,UAAU;AAC9B,eAAW,OAAO,MAAM,GAAG;AAAA,EAC7B,WAAW,MAAM,QAAQ,MAAM,GAAG;AAChC,eAAW;AAAA,EACb,OAAO;AACL,eAAW,CAAC;AAAA,EACd;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const ensureMongoDocumentToObject = (potentialDocument) => {
|
|
2
|
+
let potentialObject = potentialDocument;
|
|
3
|
+
if (typeof potentialDocument.toObject === "function") {
|
|
4
|
+
potentialObject = potentialDocument.toObject();
|
|
5
|
+
}
|
|
6
|
+
return potentialObject;
|
|
7
|
+
};
|
|
8
|
+
export {
|
|
9
|
+
ensureMongoDocumentToObject
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=ensureMongoDocumentToObject.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/ensureMongoDocumentToObject.ts"],"sourcesContent":["import type { Document } from 'mongoose';\n\n/**\n * If the dictionary is a mongoose document, convert it to an object\n * @param potentialDocument - The potential document to convert.\n * @returns The potential document converted to an object.\n */\nexport const ensureMongoDocumentToObject = <T extends object | Document>(\n potentialDocument: T\n): T => {\n let potentialObject: T = potentialDocument as T;\n\n // If the user is a mongoose document, convert it to an object\n if (typeof (potentialDocument as Document).toObject === 'function') {\n potentialObject = (potentialDocument as Document).toObject();\n }\n\n return potentialObject as T;\n};\n"],"mappings":"AAOO,MAAM,8BAA8B,CACzC,sBACM;AACN,MAAI,kBAAqB;AAGzB,MAAI,OAAQ,kBAA+B,aAAa,YAAY;AAClE,sBAAmB,kBAA+B,SAAS;AAAA,EAC7D;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -1234,6 +1234,97 @@ const errorData = {
|
|
|
1234
1234
|
es: "Error al auditar los archivos de declaraci\xF3n de contenido."
|
|
1235
1235
|
},
|
|
1236
1236
|
statusCode: HttpStatusCodes.INTERNAL_SERVER_ERROR_500
|
|
1237
|
+
},
|
|
1238
|
+
TAG_NOT_FOUND: {
|
|
1239
|
+
title: {
|
|
1240
|
+
en: "Tag Not Found",
|
|
1241
|
+
fr: "Tag non trouv\xE9",
|
|
1242
|
+
es: "Tag no encontrado"
|
|
1243
|
+
},
|
|
1244
|
+
message: {
|
|
1245
|
+
en: "The specified tag could not be found.",
|
|
1246
|
+
fr: "Le tag sp\xE9cifi\xE9 est introuvable.",
|
|
1247
|
+
es: "El tag especificado no se pudo encontrar."
|
|
1248
|
+
},
|
|
1249
|
+
statusCode: HttpStatusCodes.NOT_FOUND_404
|
|
1250
|
+
},
|
|
1251
|
+
TAG_ID_NOT_FOUND: {
|
|
1252
|
+
title: {
|
|
1253
|
+
en: "Tag ID Not Found",
|
|
1254
|
+
fr: "Identifiant de tag non trouv\xE9",
|
|
1255
|
+
es: "Identificador de tag no encontrado"
|
|
1256
|
+
},
|
|
1257
|
+
message: {
|
|
1258
|
+
en: "The tag ID was not found.",
|
|
1259
|
+
fr: "L'identifiant de tag n'a pas \xE9t\xE9 trouv\xE9.",
|
|
1260
|
+
es: "El identificador de tag no se ha encontrado."
|
|
1261
|
+
},
|
|
1262
|
+
statusCode: HttpStatusCodes.NOT_FOUND_404
|
|
1263
|
+
},
|
|
1264
|
+
TAG_ID_MISMATCH: {
|
|
1265
|
+
title: {
|
|
1266
|
+
en: "Tag ID Mismatch",
|
|
1267
|
+
fr: "Identifiant de tag non correspondant",
|
|
1268
|
+
es: "Identificador de tag no coincidente"
|
|
1269
|
+
},
|
|
1270
|
+
message: {
|
|
1271
|
+
en: "The provided tag ID does not match the expected value. Please verify and try again.",
|
|
1272
|
+
fr: "L'identifiant de tag fourni ne correspond pas \xE0 la valeur attendue. Veuillez v\xE9rifier et r\xE9essayer.",
|
|
1273
|
+
es: "El identificador de tag proporcionado no coincide con el valor esperado. Verifique e intente nuevamente."
|
|
1274
|
+
},
|
|
1275
|
+
statusCode: HttpStatusCodes.BAD_REQUEST_400
|
|
1276
|
+
},
|
|
1277
|
+
TAG_COUNT_FAILED: {
|
|
1278
|
+
title: {
|
|
1279
|
+
en: "Tag Count Failed",
|
|
1280
|
+
fr: "\xC9chec du comptage du tag",
|
|
1281
|
+
es: "Error al contar el tag"
|
|
1282
|
+
},
|
|
1283
|
+
message: {
|
|
1284
|
+
en: "Failed to count tags.",
|
|
1285
|
+
fr: "Le comptage des tags a \xE9chou\xE9.",
|
|
1286
|
+
es: "No se pudo contar los tags."
|
|
1287
|
+
},
|
|
1288
|
+
statusCode: HttpStatusCodes.INTERNAL_SERVER_ERROR_500
|
|
1289
|
+
},
|
|
1290
|
+
TAG_INVALID_FIELDS: {
|
|
1291
|
+
title: {
|
|
1292
|
+
en: "Tag Invalid Fields",
|
|
1293
|
+
fr: "Champs du tag invalides",
|
|
1294
|
+
es: "Campos del tag no v\xE1lidos"
|
|
1295
|
+
},
|
|
1296
|
+
message: {
|
|
1297
|
+
en: "The provided tag fields are invalid.",
|
|
1298
|
+
fr: "Les champs fournis pour le tag sont invalides.",
|
|
1299
|
+
es: "Los campos proporcionados para el tag no son v\xE1lidos."
|
|
1300
|
+
},
|
|
1301
|
+
statusCode: HttpStatusCodes.BAD_REQUEST_400
|
|
1302
|
+
},
|
|
1303
|
+
TAG_UPDATE_FAILED: {
|
|
1304
|
+
title: {
|
|
1305
|
+
en: "Tag Update Failed",
|
|
1306
|
+
fr: "\xC9chec de la mise \xE0 jour du tag",
|
|
1307
|
+
es: "Error al actualizar el tag"
|
|
1308
|
+
},
|
|
1309
|
+
message: {
|
|
1310
|
+
en: "Failed to update the specified tag.",
|
|
1311
|
+
fr: "La mise \xE0 jour du tag a \xE9chou\xE9.",
|
|
1312
|
+
es: "No se pudo actualizar el tag especificado."
|
|
1313
|
+
},
|
|
1314
|
+
statusCode: HttpStatusCodes.INTERNAL_SERVER_ERROR_500
|
|
1315
|
+
},
|
|
1316
|
+
TAG_NOT_IN_ORGANIZATION: {
|
|
1317
|
+
title: {
|
|
1318
|
+
en: "Tag Not In Organization",
|
|
1319
|
+
fr: "Tag non dans l'organisation",
|
|
1320
|
+
es: "Etiqueta no en la organizaci\xF3n"
|
|
1321
|
+
},
|
|
1322
|
+
message: {
|
|
1323
|
+
en: "The specified tag is not in the organization.",
|
|
1324
|
+
fr: "Le tag sp\xE9cifi\xE9 n'est pas dans l'organisation.",
|
|
1325
|
+
es: "La etiqueta especificada no est\xE1 en la organizaci\xF3n."
|
|
1326
|
+
},
|
|
1327
|
+
statusCode: HttpStatusCodes.FORBIDDEN_403
|
|
1237
1328
|
}
|
|
1238
1329
|
};
|
|
1239
1330
|
export {
|