@intlayer/backend 3.5.4 → 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 +238 -0
- package/dist/cjs/controllers/ai.controller.cjs.map +1 -0
- 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 +4 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/middlewares/request.middleware.cjs +4 -0
- package/dist/cjs/middlewares/request.middleware.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 +69 -0
- package/dist/cjs/routes/ai.routes.cjs.map +1 -0
- 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/project.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/auditDictionary/CJS_FORMAT.md +23 -0
- package/dist/cjs/utils/auditDictionary/JSON_FORMAT.md +26 -0
- package/dist/cjs/utils/auditDictionary/JSX_FORMAT.md +28 -0
- package/dist/cjs/utils/auditDictionary/MJS_FORMAT.md +23 -0
- package/dist/cjs/utils/auditDictionary/PROMPT.md +151 -0
- package/dist/cjs/utils/auditDictionary/TSX_FORMAT.md +28 -0
- package/dist/cjs/utils/auditDictionary/TS_FORMAT.md +22 -0
- package/dist/cjs/utils/auditDictionary/index.cjs +98 -0
- 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/ErrorHandler.cjs +1 -1
- package/dist/cjs/utils/errors/ErrorHandler.cjs.map +1 -1
- package/dist/cjs/utils/errors/errorCodes.cjs +104 -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 +201 -0
- package/dist/esm/controllers/ai.controller.mjs.map +1 -0
- 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 +4 -0
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/middlewares/request.middleware.mjs +4 -0
- package/dist/esm/middlewares/request.middleware.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 +49 -0
- package/dist/esm/routes/ai.routes.mjs.map +1 -0
- 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/auditDictionary/CJS_FORMAT.md +23 -0
- package/dist/esm/utils/auditDictionary/JSON_FORMAT.md +26 -0
- package/dist/esm/utils/auditDictionary/JSX_FORMAT.md +28 -0
- package/dist/esm/utils/auditDictionary/MJS_FORMAT.md +23 -0
- package/dist/esm/utils/auditDictionary/PROMPT.md +151 -0
- package/dist/esm/utils/auditDictionary/TSX_FORMAT.md +28 -0
- package/dist/esm/utils/auditDictionary/TS_FORMAT.md +22 -0
- package/dist/esm/utils/auditDictionary/index.mjs +73 -0
- 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/ErrorHandler.mjs +1 -1
- package/dist/esm/utils/errors/ErrorHandler.mjs.map +1 -1
- package/dist/esm/utils/errors/errorCodes.mjs +104 -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 +61 -0
- package/dist/types/controllers/ai.controller.d.ts.map +1 -0
- 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 +3 -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 +25 -0
- package/dist/types/routes/ai.routes.d.ts.map +1 -0
- 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/project.types.d.ts +3 -0
- package/dist/types/types/project.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/audit/index.d.ts +28 -0
- package/dist/types/utils/audit/index.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/ErrorHandler.d.ts.map +1 -1
- package/dist/types/utils/errors/errorCodes.d.ts +104 -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 +6 -5
|
@@ -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":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
```javascript
|
|
2
|
+
const { t, enu } = require("intlayer");
|
|
3
|
+
|
|
4
|
+
/** @type {import('intlayer').IntlayerConfig} */
|
|
5
|
+
module.exports = {
|
|
6
|
+
key: "my-key",
|
|
7
|
+
content: {
|
|
8
|
+
exampleText: t({
|
|
9
|
+
en: "Example of content in English",
|
|
10
|
+
fr: "Example de contenu en français",
|
|
11
|
+
es: "Ejemplo de contenido en español",
|
|
12
|
+
}),
|
|
13
|
+
numberOfCar: enu({
|
|
14
|
+
"<-1": "Less than minus one car",
|
|
15
|
+
"-1": "Minus one car",
|
|
16
|
+
0: "No cars",
|
|
17
|
+
1: "One car",
|
|
18
|
+
">5": "Some cars",
|
|
19
|
+
">19": "Many cars",
|
|
20
|
+
}),
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
```json
|
|
2
|
+
{
|
|
3
|
+
"key": "my-key",
|
|
4
|
+
"content": {
|
|
5
|
+
"profileText": {
|
|
6
|
+
"NodeType": "translation",
|
|
7
|
+
"translation": {
|
|
8
|
+
"en": "Manage profile",
|
|
9
|
+
"fr": "Gérer le profil",
|
|
10
|
+
"es": "Administrar perfil"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"numberOfCar": {
|
|
14
|
+
"NodeType": "enumeration",
|
|
15
|
+
"enumeration": {
|
|
16
|
+
"<-1": "Less than minus one car",
|
|
17
|
+
"-1": "Minus one car",
|
|
18
|
+
"0": "No cars",
|
|
19
|
+
"1": "One car",
|
|
20
|
+
">5": "Some cars",
|
|
21
|
+
">19": "Many cars"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
```tsx
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { t, enu, type DeclarationContent } from "intlayer";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
key: "my-key",
|
|
7
|
+
content: {
|
|
8
|
+
exampleText: t({
|
|
9
|
+
en: "Example of content in English",
|
|
10
|
+
fr: "Example de contenu en français",
|
|
11
|
+
es: "Ejemplo de contenido en español",
|
|
12
|
+
}),
|
|
13
|
+
exampleOfReactNode: t({
|
|
14
|
+
en: <h1>Example of ReactNode in English</h1>,
|
|
15
|
+
fr: <h1>Example de ReactNode en français</h1>,
|
|
16
|
+
es: <h1>Ejemplo de ReactNode en español</h1>,
|
|
17
|
+
}),
|
|
18
|
+
numberOfCar: enu({
|
|
19
|
+
"<-1": "Less than minus one car",
|
|
20
|
+
"-1": "Minus one car",
|
|
21
|
+
"0": "No cars",
|
|
22
|
+
"1": "One car",
|
|
23
|
+
">5": "Some cars",
|
|
24
|
+
">19": "Many cars",
|
|
25
|
+
}),
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
```javascript
|
|
2
|
+
import { t, enu } from "intlayer";
|
|
3
|
+
|
|
4
|
+
/** @type {import('intlayer').IntlayerConfig} */
|
|
5
|
+
export default {
|
|
6
|
+
key: "my-key",
|
|
7
|
+
content: {
|
|
8
|
+
exampleText: t({
|
|
9
|
+
en: "Example of content in English",
|
|
10
|
+
fr: "Example de contenu en français",
|
|
11
|
+
es: "Ejemplo de contenido en español",
|
|
12
|
+
}),
|
|
13
|
+
numberOfCar: enu({
|
|
14
|
+
"<-1": "Less than minus one car",
|
|
15
|
+
"-1": "Minus one car",
|
|
16
|
+
0: "No cars",
|
|
17
|
+
1: "One car",
|
|
18
|
+
">5": "Some cars",
|
|
19
|
+
">19": "Many cars",
|
|
20
|
+
}),
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
```
|
|
@@ -0,0 +1,151 @@
|
|
|
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
|
+
|
|
3
|
+
**Instructions:**
|
|
4
|
+
|
|
5
|
+
1. **File Location:**
|
|
6
|
+
|
|
7
|
+
- The content declaration files are located in the `{{filePath}}` directory relative to the project root.
|
|
8
|
+
|
|
9
|
+
2. **Locales:**
|
|
10
|
+
|
|
11
|
+
- Default locale: {{defaultLocale}}
|
|
12
|
+
- Required Locales: {{otherLocales}} (add the missing locales in `t({ ... })` function)
|
|
13
|
+
|
|
14
|
+
3. **Content Declaration Format:**
|
|
15
|
+
|
|
16
|
+
- Example format:
|
|
17
|
+
|
|
18
|
+
{{declarationsContentTemplate}}
|
|
19
|
+
|
|
20
|
+
4. **Audit Requirements:**
|
|
21
|
+
|
|
22
|
+
- **Consistency:** Ensure that all keys have translations for all specified locales.
|
|
23
|
+
- **Missing Content:** Identify any missing translations and specify the expected content.
|
|
24
|
+
- **Misplaced Content:** Detect if any translations are placed under incorrect keys.
|
|
25
|
+
- **Type Compliance:** Verify that the content types match the declarations (e.g., strings, string arrays).
|
|
26
|
+
|
|
27
|
+
5. **Modification Guidelines:**
|
|
28
|
+
|
|
29
|
+
- **Do Not Alter Structure:** If the file structure is correct, do not modify it. Only add, update, or remove content declarations as necessary.
|
|
30
|
+
- **Do Not Change a value type** If a key value is like `exampleKey: "exampleValue"`, avoid a maximum to not change the value type to `exampleKey: t({ en: "exampleValue" })`.
|
|
31
|
+
- **Return Only Final File Content:** Provide the updated file content without any additional comments or explanations.
|
|
32
|
+
- **Ensure No Translations are Missing:** If an element is a multilingual content and a translation is missing, add it. Including localized content as `es-MX` or `en-UK`.
|
|
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
|
+
- **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
|
+
- **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.
|
|
37
|
+
|
|
38
|
+
6. **Example Scenario:**
|
|
39
|
+
|
|
40
|
+
- **Example 1:**
|
|
41
|
+
|
|
42
|
+
- **Input File:**
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { t, type DeclarationContent } from "intlayer";
|
|
46
|
+
|
|
47
|
+
export default {
|
|
48
|
+
key: "creative-work-structured-data",
|
|
49
|
+
content: {
|
|
50
|
+
audienceType: t({
|
|
51
|
+
en: "Developers, Content Managers",
|
|
52
|
+
fr: "Développeurs, Responsables de contenu",
|
|
53
|
+
es: "Desarrolladores, Gestores de Contenido",
|
|
54
|
+
}),
|
|
55
|
+
},
|
|
56
|
+
} satisfies DeclarationContent;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- **Expected Output (No Changes Needed):**
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { t, type DeclarationContent } from "intlayer";
|
|
63
|
+
|
|
64
|
+
export default {
|
|
65
|
+
key: "creative-work-structured-data",
|
|
66
|
+
content: {
|
|
67
|
+
audienceType: t({
|
|
68
|
+
en: "Developers, Content Managers",
|
|
69
|
+
fr: "Développeurs, Responsables de contenu",
|
|
70
|
+
es: "Desarrolladores, Gestores de Contenido",
|
|
71
|
+
}),
|
|
72
|
+
},
|
|
73
|
+
} satisfies DeclarationContent;
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- **Incorrect Output (Unwanted Structural Change):**
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { t, type DeclarationContent } from "intlayer";
|
|
80
|
+
|
|
81
|
+
export default {
|
|
82
|
+
key: "creative-work-structured-data",
|
|
83
|
+
content: {
|
|
84
|
+
audienceType: t({
|
|
85
|
+
en: "Developers, Content Managers",
|
|
86
|
+
fr: "Développeurs, Responsables de contenu",
|
|
87
|
+
es: "Desarrolladores, Gestores de Contenido",
|
|
88
|
+
}),
|
|
89
|
+
// Missing multilingual content for 'projectDescription'
|
|
90
|
+
projectDescription: t({
|
|
91
|
+
en: "This project involves structured data for creative work.",
|
|
92
|
+
fr: "Ce projet implique des données structurées pour le travail créatif.",
|
|
93
|
+
es: "Este proyecto involucra datos estructurados para trabajo creativo.",
|
|
94
|
+
}),
|
|
95
|
+
},
|
|
96
|
+
} satisfies DeclarationContent;
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- **Clarification:** In this scenario, since the input file is already valid and complete, the expected output should be identical to the input without any additional fields or comments.
|
|
100
|
+
|
|
101
|
+
- **Example 2:**
|
|
102
|
+
|
|
103
|
+
- **Input File:**
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
import { t } from "react-intlayer";
|
|
107
|
+
|
|
108
|
+
const content = {
|
|
109
|
+
key: "creative-work-structured-data",
|
|
110
|
+
content: {
|
|
111
|
+
audienceType: t({
|
|
112
|
+
en: "Developers, Content Managers",
|
|
113
|
+
es: "Desarrolladores, Gestores de Contenido",
|
|
114
|
+
}),
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
- **Expected Output (No Changes Needed):**
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { t, type DeclarationContent } from "intlayer";
|
|
123
|
+
|
|
124
|
+
const content = {
|
|
125
|
+
key: "creative-work-structured-data",
|
|
126
|
+
content: {
|
|
127
|
+
audienceType: t({
|
|
128
|
+
en: "Developers, Content Managers",
|
|
129
|
+
fr: "Développeurs, Responsables de contenu",
|
|
130
|
+
es: "Desarrolladores, Gestores de Contenido",
|
|
131
|
+
}),
|
|
132
|
+
},
|
|
133
|
+
} satisfies DeclarationContent;
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- **Clarification:** In this scenario:
|
|
137
|
+
- A missing translation for the `audienceType` key was added.
|
|
138
|
+
- The import of the `t` function was imported from `react-intlayer` instead of `intlayer`.
|
|
139
|
+
- A type `DeclarationContent` was added to the file to strengthen the content declaration.
|
|
140
|
+
|
|
141
|
+
**Tags Instructions:**
|
|
142
|
+
|
|
143
|
+
{{tagsInstructions}}
|
|
144
|
+
|
|
145
|
+
**File to Audit:**
|
|
146
|
+
|
|
147
|
+
{{fileContent}}
|
|
148
|
+
|
|
149
|
+
**Expected Response:**
|
|
150
|
+
|
|
151
|
+
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,28 @@
|
|
|
1
|
+
```tsx
|
|
2
|
+
import React, { type ReactNode } from "react";
|
|
3
|
+
import { t, enu, type DeclarationContent } from "intlayer";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
key: "my-key",
|
|
7
|
+
content: {
|
|
8
|
+
exampleText: t({
|
|
9
|
+
en: "Example of content in English",
|
|
10
|
+
fr: "Example de contenu en français",
|
|
11
|
+
es: "Ejemplo de contenido en español",
|
|
12
|
+
}),
|
|
13
|
+
exampleOfReactNode: t<ReactNode>({
|
|
14
|
+
en: <h1>Example of ReactNode in English</h1>,
|
|
15
|
+
fr: <h1>Example de ReactNode en français</h1>,
|
|
16
|
+
es: <h1>Ejemplo de ReactNode en español</h1>,
|
|
17
|
+
}),
|
|
18
|
+
numberOfCar: enu({
|
|
19
|
+
"<-1": "Less than minus one car",
|
|
20
|
+
"-1": "Minus one car",
|
|
21
|
+
"0": "No cars",
|
|
22
|
+
"1": "One car",
|
|
23
|
+
">5": "Some cars",
|
|
24
|
+
">19": "Many cars",
|
|
25
|
+
}),
|
|
26
|
+
},
|
|
27
|
+
} satisfies DeclarationContent;
|
|
28
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
```typescript
|
|
2
|
+
import { t, enu, type DeclarationContent } from "intlayer";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
key: "my-key",
|
|
6
|
+
content: {
|
|
7
|
+
exampleText: t({
|
|
8
|
+
en: "Example of content in English",
|
|
9
|
+
fr: "Example de contenu en français",
|
|
10
|
+
es: "Ejemplo de contenido en español",
|
|
11
|
+
}),
|
|
12
|
+
numberOfCar: enu({
|
|
13
|
+
"<-1": "Less than minus one car",
|
|
14
|
+
"-1": "Minus one car",
|
|
15
|
+
"0": "No cars",
|
|
16
|
+
"1": "One car",
|
|
17
|
+
">5": "Some cars",
|
|
18
|
+
">19": "Many cars",
|
|
19
|
+
}),
|
|
20
|
+
},
|
|
21
|
+
} satisfies DeclarationContent;
|
|
22
|
+
```
|
|
@@ -0,0 +1,73 @@
|
|
|
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 FILE_TEMPLATE = {
|
|
14
|
+
ts: getFileContent("./TS_FORMAT.md"),
|
|
15
|
+
tsx: getFileContent("./TSX_FORMAT.md"),
|
|
16
|
+
js: getFileContent("./MJS_FORMAT.md"),
|
|
17
|
+
mjs: getFileContent("./MJS_FORMAT.md"),
|
|
18
|
+
cjs: getFileContent("./CJS_FORMAT.md"),
|
|
19
|
+
jsx: getFileContent("./JSX_FORMAT.md"),
|
|
20
|
+
json: getFileContent("./JSON_FORMAT.md")
|
|
21
|
+
};
|
|
22
|
+
const CHAT_GPT_PROMPT = getFileContent("./PROMPT.md");
|
|
23
|
+
const formatLocaleWithName = (locale) => {
|
|
24
|
+
const localeName = getLocaleName(locale);
|
|
25
|
+
return `${locale}: ${localeName}`;
|
|
26
|
+
};
|
|
27
|
+
const formatTagInstructions = (tags = []) => tags.map((tag) => `- ${tag.key}: ${tag.instructions}`).join("\n\n");
|
|
28
|
+
const auditDictionary = async ({
|
|
29
|
+
fileContent,
|
|
30
|
+
filePath,
|
|
31
|
+
model,
|
|
32
|
+
openAiApiKey,
|
|
33
|
+
customPrompt,
|
|
34
|
+
locales,
|
|
35
|
+
defaultLocale,
|
|
36
|
+
tags
|
|
37
|
+
}) => {
|
|
38
|
+
try {
|
|
39
|
+
const openai = new OpenAI({
|
|
40
|
+
apiKey: openAiApiKey
|
|
41
|
+
});
|
|
42
|
+
const splitted = (filePath ?? ".json").split(".");
|
|
43
|
+
const fileExtension = splitted[splitted.length - 1];
|
|
44
|
+
const prompt = customPrompt ?? CHAT_GPT_PROMPT.replace("{{filePath}}", filePath ?? "Not provided").replace(
|
|
45
|
+
"{{defaultLocale}}",
|
|
46
|
+
`{${formatLocaleWithName(defaultLocale)}}`
|
|
47
|
+
).replace(
|
|
48
|
+
"{{otherLocales}}",
|
|
49
|
+
`{${locales.map(formatLocaleWithName).join(", ")}}`
|
|
50
|
+
).replace(
|
|
51
|
+
"{{declarationsContentTemplate}}",
|
|
52
|
+
FILE_TEMPLATE[fileExtension]
|
|
53
|
+
).replace("{{fileContent}}", fileContent).replace("{{tagsInstructions}}", formatTagInstructions(tags));
|
|
54
|
+
const chatCompletion = await openai.chat.completions.create({
|
|
55
|
+
model: model ?? "gpt-4o-mini",
|
|
56
|
+
messages: [{ role: "system", content: prompt }]
|
|
57
|
+
});
|
|
58
|
+
const newContent = chatCompletion.choices[0].message?.content;
|
|
59
|
+
logger.info(
|
|
60
|
+
`${chatCompletion.usage?.total_tokens} tokens used in the request`
|
|
61
|
+
);
|
|
62
|
+
return {
|
|
63
|
+
fileContent: newContent ?? "",
|
|
64
|
+
tokenUsed: chatCompletion.usage?.total_tokens ?? 0
|
|
65
|
+
};
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error(error);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
export {
|
|
71
|
+
auditDictionary
|
|
72
|
+
};
|
|
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
|
|
@@ -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":[]}
|