@intlayer/backend 8.12.2 → 8.12.4-canary.0
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/assets/utils/AI/askDocQuestion/embeddings/docs/en/bundle_optimization.json +9954 -6953
- package/dist/assets/utils/AI/askDocQuestion/embeddings/docs/en/configuration.json +1 -1
- package/dist/esm/controllers/ai.controller.mjs.map +1 -1
- package/dist/esm/controllers/audit.controller.mjs.map +1 -1
- package/dist/esm/controllers/bitbucket.controller.mjs.map +1 -1
- package/dist/esm/controllers/cliSessionToken.controller.mjs.map +1 -1
- package/dist/esm/controllers/demo.controller.mjs +32 -25
- package/dist/esm/controllers/demo.controller.mjs.map +1 -1
- package/dist/esm/controllers/dictionary.controller.mjs +1 -0
- package/dist/esm/controllers/dictionary.controller.mjs.map +1 -1
- package/dist/esm/controllers/environment.controller.mjs.map +1 -1
- package/dist/esm/controllers/eventListener.controller.mjs.map +1 -1
- package/dist/esm/controllers/github.controller.mjs.map +1 -1
- package/dist/esm/controllers/gitlab.controller.mjs.map +1 -1
- package/dist/esm/controllers/newsletter.controller.mjs.map +1 -1
- package/dist/esm/controllers/oAuth2.controller.mjs.map +1 -1
- package/dist/esm/controllers/organization.controller.mjs.map +1 -1
- package/dist/esm/controllers/project.controller.mjs.map +1 -1
- package/dist/esm/controllers/projectAccessKey.controller.mjs.map +1 -1
- package/dist/esm/controllers/projectMemberAccess.controller.mjs.map +1 -1
- package/dist/esm/controllers/recursiveAudit.controller.mjs.map +1 -1
- package/dist/esm/controllers/reviewer.controller.mjs.map +1 -1
- package/dist/esm/controllers/searchDoc.controller.mjs.map +1 -1
- package/dist/esm/controllers/showcaseProject.controller.mjs.map +1 -1
- package/dist/esm/controllers/stripe.controller.mjs.map +1 -1
- package/dist/esm/controllers/tag.controller.mjs.map +1 -1
- package/dist/esm/controllers/translation.controller.mjs.map +1 -1
- package/dist/esm/controllers/user.controller.mjs.map +1 -1
- package/dist/esm/emails/AffiliateActivatedEmail.mjs.map +1 -1
- package/dist/esm/emails/AffiliateConversionEmail.mjs.map +1 -1
- package/dist/esm/emails/AffiliateInvitationEmail.mjs.map +1 -1
- package/dist/esm/emails/AffiliateWelcomeEmail.mjs.map +1 -1
- package/dist/esm/emails/InviteUserEmail.mjs.map +1 -1
- package/dist/esm/emails/MagicLinkEmail.mjs.map +1 -1
- package/dist/esm/emails/MissionRequestedClientEmail.mjs.map +1 -1
- package/dist/esm/emails/MissionRequestedReviewerEmail.mjs.map +1 -1
- package/dist/esm/emails/OAuthTokenCreatedEmail.mjs.map +1 -1
- package/dist/esm/emails/PasswordChangeConfirmation.mjs.map +1 -1
- package/dist/esm/emails/ResetUserPassword.mjs.map +1 -1
- package/dist/esm/emails/ReviewerApplicationEmail.mjs.map +1 -1
- package/dist/esm/emails/ReviewerApprovedEmail.mjs.map +1 -1
- package/dist/esm/emails/ReviewerContactEmail.mjs.map +1 -1
- package/dist/esm/emails/SubscriptionPaymentCancellation.mjs.map +1 -1
- package/dist/esm/emails/SubscriptionPaymentError.mjs.map +1 -1
- package/dist/esm/emails/SubscriptionPaymentSuccess.mjs.map +1 -1
- package/dist/esm/emails/ValidateUserEmail.mjs.map +1 -1
- package/dist/esm/emails/Welcome.mjs.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/logger/index.mjs.map +1 -1
- package/dist/esm/middlewares/oAuth2.middleware.mjs.map +1 -1
- package/dist/esm/middlewares/sessionAuth.middleware.mjs.map +1 -1
- package/dist/esm/routes/ai.routes.mjs.map +1 -1
- package/dist/esm/routes/audit.routes.mjs.map +1 -1
- package/dist/esm/routes/bitbucket.routes.mjs.map +1 -1
- package/dist/esm/routes/demo.routes.mjs.map +1 -1
- package/dist/esm/routes/dictionary.routes.mjs.map +1 -1
- package/dist/esm/routes/environment.routes.mjs.map +1 -1
- package/dist/esm/routes/eventListener.routes.mjs.map +1 -1
- package/dist/esm/routes/github.routes.mjs.map +1 -1
- package/dist/esm/routes/gitlab.routes.mjs.map +1 -1
- package/dist/esm/routes/newsletter.routes.mjs.map +1 -1
- package/dist/esm/routes/organization.routes.mjs.map +1 -1
- package/dist/esm/routes/paramsSchemas.mjs.map +1 -1
- package/dist/esm/routes/project.routes.mjs.map +1 -1
- package/dist/esm/routes/reviewer.routes.mjs.map +1 -1
- package/dist/esm/routes/search.routes.mjs.map +1 -1
- package/dist/esm/routes/showcaseProject.routes.mjs.map +1 -1
- package/dist/esm/routes/stripe.routes.mjs.map +1 -1
- package/dist/esm/routes/tags.routes.mjs.map +1 -1
- package/dist/esm/routes/translate.routes.mjs.map +1 -1
- package/dist/esm/routes/user.routes.mjs.map +1 -1
- package/dist/esm/schemas/account.schema.mjs.map +1 -1
- package/dist/esm/schemas/affiliate.schema.mjs.map +1 -1
- package/dist/esm/schemas/affiliateInvitation.schema.mjs.map +1 -1
- package/dist/esm/schemas/audit.schema.mjs.map +1 -1
- package/dist/esm/schemas/auditJob.schema.mjs.map +1 -1
- package/dist/esm/schemas/auditPage.schema.mjs.map +1 -1
- package/dist/esm/schemas/cliSessionToken.schema.mjs.map +1 -1
- package/dist/esm/schemas/dictionary.schema.mjs.map +1 -1
- package/dist/esm/schemas/discussion.schema.mjs.map +1 -1
- package/dist/esm/schemas/oAuth2.schema.mjs.map +1 -1
- package/dist/esm/schemas/organization.schema.mjs.map +1 -1
- package/dist/esm/schemas/plans.schema.mjs.map +1 -1
- package/dist/esm/schemas/project.schema.mjs.map +1 -1
- package/dist/esm/schemas/promoCode.schema.mjs.map +1 -1
- package/dist/esm/schemas/reviewer.schema.mjs.map +1 -1
- package/dist/esm/schemas/session.schema.mjs.map +1 -1
- package/dist/esm/schemas/showcaseProject.schema.mjs.map +1 -1
- package/dist/esm/schemas/tag.schema.mjs.map +1 -1
- package/dist/esm/schemas/user.schema.mjs.map +1 -1
- package/dist/esm/services/affiliate.service.mjs.map +1 -1
- package/dist/esm/services/audit/analysis/analyzeBundleContent.mjs.map +1 -1
- package/dist/esm/services/audit/analysis/analyzeLinguisticStructure.mjs.map +1 -1
- package/dist/esm/services/audit/analysis/analyzeMetadata.mjs.map +1 -1
- package/dist/esm/services/audit/analysis/analyzeRobots.mjs.map +1 -1
- package/dist/esm/services/audit/analysis/analyzeSitemap.mjs.map +1 -1
- package/dist/esm/services/audit/analysis/analyzeUrlStructure.mjs.map +1 -1
- package/dist/esm/services/audit/analysis/calculateScore.mjs.map +1 -1
- package/dist/esm/services/audit/checkers/bundleChecker.mjs.map +1 -1
- package/dist/esm/services/audit/checkers/linguisticChecker.mjs.map +1 -1
- package/dist/esm/services/audit/checkers/metadataChecker.mjs.map +1 -1
- package/dist/esm/services/audit/checkers/pageChecker.mjs.map +1 -1
- package/dist/esm/services/audit/checkers/robotsChecker.mjs.map +1 -1
- package/dist/esm/services/audit/checkers/sitemapChecker.mjs.map +1 -1
- package/dist/esm/services/audit/checkers/urlChecker.mjs.map +1 -1
- package/dist/esm/services/audit/recursiveAudit.service.mjs.map +1 -1
- package/dist/esm/services/audit/seoAudit.service.mjs.map +1 -1
- package/dist/esm/services/bitbucket.service.mjs.map +1 -1
- package/dist/esm/services/ci.service.mjs.map +1 -1
- package/dist/esm/services/cliSessionToken.service.mjs.map +1 -1
- package/dist/esm/services/dictionary.service.mjs.map +1 -1
- package/dist/esm/services/email.service.mjs.map +1 -1
- package/dist/esm/services/environment.service.mjs.map +1 -1
- package/dist/esm/services/github.service.mjs.map +1 -1
- package/dist/esm/services/gitlab.service.mjs.map +1 -1
- package/dist/esm/services/oAuth2.service.mjs.map +1 -1
- package/dist/esm/services/organization.service.mjs.map +1 -1
- package/dist/esm/services/project/projectScreenshot.service.mjs.map +1 -1
- package/dist/esm/services/project.service.mjs.map +1 -1
- package/dist/esm/services/projectAccessKey.service.mjs.map +1 -1
- package/dist/esm/services/promoCode.service.mjs.map +1 -1
- package/dist/esm/services/reviewer/pictureUpload.service.mjs.map +1 -1
- package/dist/esm/services/reviewer.service.mjs.map +1 -1
- package/dist/esm/services/reviewerMessage.service.mjs.map +1 -1
- package/dist/esm/services/reviewerMission.service.mjs.map +1 -1
- package/dist/esm/services/session.service.mjs.map +1 -1
- package/dist/esm/services/showcase/showcaseProject.service.mjs.map +1 -1
- package/dist/esm/services/showcase/showcaseScan.service.mjs.map +1 -1
- package/dist/esm/services/showcase/showcaseUploadScreenshot.service.mjs.map +1 -1
- package/dist/esm/services/showcase/showcaseVerifyBundle.service.mjs.map +1 -1
- package/dist/esm/services/showcase/showcaseVerifyGithub.service.mjs.map +1 -1
- package/dist/esm/services/subscription.service.mjs.map +1 -1
- package/dist/esm/services/tag.service.mjs.map +1 -1
- package/dist/esm/services/translationQueue.service.mjs.map +1 -1
- package/dist/esm/services/translationWorker.service.mjs.map +1 -1
- package/dist/esm/services/user/avatarUpload.service.mjs.map +1 -1
- package/dist/esm/services/user.service.mjs.map +1 -1
- package/dist/esm/services/webhook.service.mjs.map +1 -1
- package/dist/esm/types/user.types.mjs.map +1 -1
- package/dist/esm/utils/AI/askDocQuestion/askDocQuestion.mjs.map +1 -1
- package/dist/esm/utils/AI/askDocQuestion/embeddings/docs/en/bundle_optimization.json +9954 -6953
- package/dist/esm/utils/AI/askDocQuestion/embeddings/docs/en/configuration.json +1 -1
- package/dist/esm/utils/AI/askDocQuestion/indexMarkdownFiles.mjs.map +1 -1
- package/dist/esm/utils/AI/auditDictionary/index.mjs.map +1 -1
- package/dist/esm/utils/AI/auditDictionaryField/index.mjs.map +1 -1
- package/dist/esm/utils/AI/auditDictionaryMetadata/index.mjs.map +1 -1
- package/dist/esm/utils/AI/auditTag/index.mjs.map +1 -1
- package/dist/esm/utils/AI/autocomplete/index.mjs.map +1 -1
- package/dist/esm/utils/AI/chat/index.mjs.map +1 -1
- package/dist/esm/utils/AI/chat/mcpInProcessTools.mjs.map +1 -1
- package/dist/esm/utils/AI/chat/sessionTools.mjs.map +1 -1
- package/dist/esm/utils/AI/customQuery/index.mjs.map +1 -1
- package/dist/esm/utils/AI/getProjectAIOptions.mjs.map +1 -1
- package/dist/esm/utils/AI/translateDictionaryDB.mjs.map +1 -1
- package/dist/esm/utils/AI/translateJSON/index.mjs.map +1 -1
- package/dist/esm/utils/accessControl.mjs.map +1 -1
- package/dist/esm/utils/auth/getAuth.mjs.map +1 -1
- package/dist/esm/utils/cors.mjs +2 -13
- package/dist/esm/utils/cors.mjs.map +1 -1
- package/dist/esm/utils/demoDictionaries.mjs.map +1 -1
- package/dist/esm/utils/ensureArrayQueryFilter.mjs.map +1 -1
- package/dist/esm/utils/ensureMongoDocumentToObject.mjs.map +1 -1
- package/dist/esm/utils/errors/ErrorHandler.mjs.map +1 -1
- package/dist/esm/utils/errors/ErrorsClass.mjs.map +1 -1
- package/dist/esm/utils/errors/errorCodes.mjs.map +1 -1
- package/dist/esm/utils/errors/index.mjs +1 -0
- package/dist/esm/utils/filtersAndPagination/getDictionaryFiltersAndPagination.mjs.map +1 -1
- package/dist/esm/utils/filtersAndPagination/getDiscussionFiltersAndPagination.mjs.map +1 -1
- package/dist/esm/utils/filtersAndPagination/getFiltersAndPaginationFromBody.mjs.map +1 -1
- package/dist/esm/utils/filtersAndPagination/getOrganizationFiltersAndPagination.mjs.map +1 -1
- package/dist/esm/utils/filtersAndPagination/getProjectFiltersAndPagination.mjs.map +1 -1
- package/dist/esm/utils/filtersAndPagination/getTagFiltersAndPagination.mjs.map +1 -1
- package/dist/esm/utils/filtersAndPagination/getUserFiltersAndPagination.mjs.map +1 -1
- package/dist/esm/utils/getFaviconUrl.mjs.map +1 -1
- package/dist/esm/utils/github/connectGithub.mjs.map +1 -1
- package/dist/esm/utils/httpStatusCodes.mjs.map +1 -1
- package/dist/esm/utils/image/resizeImage.mjs.map +1 -1
- package/dist/esm/utils/mapper/dictionary.mjs.map +1 -1
- package/dist/esm/utils/mapper/organization.mjs.map +1 -1
- package/dist/esm/utils/mapper/project.mjs.map +1 -1
- package/dist/esm/utils/mapper/session.mjs.map +1 -1
- package/dist/esm/utils/mapper/showcaseProject.mjs.map +1 -1
- package/dist/esm/utils/mapper/tag.mjs.map +1 -1
- package/dist/esm/utils/mapper/user.mjs.map +1 -1
- package/dist/esm/utils/mongoDB/connectDB.mjs.map +1 -1
- package/dist/esm/utils/oAuth2.mjs.map +1 -1
- package/dist/esm/utils/permissions.mjs.map +1 -1
- package/dist/esm/utils/plan.mjs.map +1 -1
- package/dist/esm/utils/puppeteer/launchBrowser.mjs.map +1 -1
- package/dist/esm/utils/rateLimiter.mjs.map +1 -1
- package/dist/esm/utils/redis/connectRedis.mjs.map +1 -1
- package/dist/esm/utils/removeObjectKeys.mjs.map +1 -1
- package/dist/esm/utils/responseData.mjs.map +1 -1
- package/dist/esm/utils/s3/s3Client.mjs.map +1 -1
- package/dist/esm/utils/validation/validateDictionary.mjs.map +1 -1
- package/dist/esm/utils/validation/validateOrganization.mjs.map +1 -1
- package/dist/esm/utils/validation/validateProject.mjs.map +1 -1
- package/dist/esm/utils/validation/validateTag.mjs.map +1 -1
- package/dist/esm/utils/validation/validateUser.mjs.map +1 -1
- package/dist/esm/webhooks/stripe.webhook.mjs.map +1 -1
- package/dist/types/controllers/ai.controller.d.ts.map +1 -1
- package/dist/types/controllers/bitbucket.controller.d.ts.map +1 -1
- package/dist/types/controllers/cliSessionToken.controller.d.ts.map +1 -1
- package/dist/types/controllers/demo.controller.d.ts.map +1 -1
- package/dist/types/controllers/dictionary.controller.d.ts.map +1 -1
- package/dist/types/controllers/environment.controller.d.ts.map +1 -1
- package/dist/types/controllers/eventListener.controller.d.ts.map +1 -1
- package/dist/types/controllers/github.controller.d.ts.map +1 -1
- package/dist/types/controllers/gitlab.controller.d.ts.map +1 -1
- package/dist/types/controllers/newsletter.controller.d.ts.map +1 -1
- package/dist/types/controllers/oAuth2.controller.d.ts.map +1 -1
- package/dist/types/controllers/organization.controller.d.ts.map +1 -1
- package/dist/types/controllers/project.controller.d.ts.map +1 -1
- package/dist/types/controllers/projectAccessKey.controller.d.ts.map +1 -1
- package/dist/types/controllers/projectMemberAccess.controller.d.ts.map +1 -1
- package/dist/types/controllers/recursiveAudit.controller.d.ts.map +1 -1
- package/dist/types/controllers/reviewer.controller.d.ts.map +1 -1
- package/dist/types/controllers/searchDoc.controller.d.ts.map +1 -1
- package/dist/types/controllers/showcaseProject.controller.d.ts.map +1 -1
- package/dist/types/controllers/stripe.controller.d.ts.map +1 -1
- package/dist/types/controllers/tag.controller.d.ts.map +1 -1
- package/dist/types/controllers/translation.controller.d.ts.map +1 -1
- package/dist/types/controllers/user.controller.d.ts.map +1 -1
- package/dist/types/emails/AffiliateActivatedEmail.d.ts +20 -18
- package/dist/types/emails/AffiliateActivatedEmail.d.ts.map +1 -1
- package/dist/types/emails/AffiliateConversionEmail.d.ts +21 -19
- package/dist/types/emails/AffiliateConversionEmail.d.ts.map +1 -1
- package/dist/types/emails/AffiliateInvitationEmail.d.ts +20 -18
- package/dist/types/emails/AffiliateInvitationEmail.d.ts.map +1 -1
- package/dist/types/emails/AffiliateWelcomeEmail.d.ts +20 -18
- package/dist/types/emails/AffiliateWelcomeEmail.d.ts.map +1 -1
- package/dist/types/emails/InviteUserEmail.d.ts +20 -18
- package/dist/types/emails/InviteUserEmail.d.ts.map +1 -1
- package/dist/types/emails/MagicLinkEmail.d.ts +20 -18
- package/dist/types/emails/MagicLinkEmail.d.ts.map +1 -1
- package/dist/types/emails/MissionRequestedClientEmail.d.ts +20 -18
- package/dist/types/emails/MissionRequestedClientEmail.d.ts.map +1 -1
- package/dist/types/emails/MissionRequestedReviewerEmail.d.ts +20 -18
- package/dist/types/emails/MissionRequestedReviewerEmail.d.ts.map +1 -1
- package/dist/types/emails/OAuthTokenCreatedEmail.d.ts +20 -18
- package/dist/types/emails/OAuthTokenCreatedEmail.d.ts.map +1 -1
- package/dist/types/emails/PasswordChangeConfirmation.d.ts +20 -18
- package/dist/types/emails/PasswordChangeConfirmation.d.ts.map +1 -1
- package/dist/types/emails/ResetUserPassword.d.ts +20 -18
- package/dist/types/emails/ResetUserPassword.d.ts.map +1 -1
- package/dist/types/emails/ReviewerApplicationEmail.d.ts +20 -18
- package/dist/types/emails/ReviewerApplicationEmail.d.ts.map +1 -1
- package/dist/types/emails/ReviewerApprovedEmail.d.ts +20 -18
- package/dist/types/emails/ReviewerApprovedEmail.d.ts.map +1 -1
- package/dist/types/emails/ReviewerContactEmail.d.ts +3 -1
- package/dist/types/emails/ReviewerContactEmail.d.ts.map +1 -1
- package/dist/types/emails/SubscriptionPaymentCancellation.d.ts +20 -18
- package/dist/types/emails/SubscriptionPaymentCancellation.d.ts.map +1 -1
- package/dist/types/emails/SubscriptionPaymentError.d.ts +20 -18
- package/dist/types/emails/SubscriptionPaymentError.d.ts.map +1 -1
- package/dist/types/emails/SubscriptionPaymentSuccess.d.ts +20 -18
- package/dist/types/emails/SubscriptionPaymentSuccess.d.ts.map +1 -1
- package/dist/types/emails/ValidateUserEmail.d.ts +20 -18
- package/dist/types/emails/ValidateUserEmail.d.ts.map +1 -1
- package/dist/types/emails/Welcome.d.ts +20 -18
- package/dist/types/emails/Welcome.d.ts.map +1 -1
- package/dist/types/export.d.ts +1 -1
- package/dist/types/logger/index.d.ts +3 -1
- package/dist/types/logger/index.d.ts.map +1 -1
- package/dist/types/middlewares/oAuth2.middleware.d.ts.map +1 -1
- package/dist/types/middlewares/sessionAuth.middleware.d.ts.map +1 -1
- package/dist/types/routes/demo.routes.d.ts.map +1 -1
- package/dist/types/schemas/account.schema.d.ts +35 -34
- package/dist/types/schemas/account.schema.d.ts.map +1 -1
- package/dist/types/schemas/affiliate.schema.d.ts +109 -108
- package/dist/types/schemas/affiliate.schema.d.ts.map +1 -1
- package/dist/types/schemas/affiliateInvitation.schema.d.ts +49 -48
- package/dist/types/schemas/affiliateInvitation.schema.d.ts.map +1 -1
- package/dist/types/schemas/audit.schema.d.ts.map +1 -1
- package/dist/types/schemas/auditJob.schema.d.ts +6 -6
- package/dist/types/schemas/auditPage.schema.d.ts +6 -6
- package/dist/types/schemas/cliSessionToken.schema.d.ts +14 -13
- package/dist/types/schemas/cliSessionToken.schema.d.ts.map +1 -1
- package/dist/types/schemas/dictionary.schema.d.ts +60 -59
- package/dist/types/schemas/dictionary.schema.d.ts.map +1 -1
- package/dist/types/schemas/discussion.schema.d.ts +51 -50
- package/dist/types/schemas/discussion.schema.d.ts.map +1 -1
- package/dist/types/schemas/oAuth2.schema.d.ts +18 -17
- package/dist/types/schemas/oAuth2.schema.d.ts.map +1 -1
- package/dist/types/schemas/organization.schema.d.ts +45 -44
- package/dist/types/schemas/organization.schema.d.ts.map +1 -1
- package/dist/types/schemas/plans.schema.d.ts +45 -44
- package/dist/types/schemas/plans.schema.d.ts.map +1 -1
- package/dist/types/schemas/project.schema.d.ts +73 -72
- package/dist/types/schemas/project.schema.d.ts.map +1 -1
- package/dist/types/schemas/promoCode.schema.d.ts +61 -60
- package/dist/types/schemas/promoCode.schema.d.ts.map +1 -1
- package/dist/types/schemas/reviewer.schema.d.ts +221 -220
- package/dist/types/schemas/reviewer.schema.d.ts.map +1 -1
- package/dist/types/schemas/session.schema.d.ts +54 -52
- package/dist/types/schemas/session.schema.d.ts.map +1 -1
- package/dist/types/schemas/showcaseProject.schema.d.ts +61 -60
- package/dist/types/schemas/showcaseProject.schema.d.ts.map +1 -1
- package/dist/types/schemas/tag.schema.d.ts +45 -44
- package/dist/types/schemas/tag.schema.d.ts.map +1 -1
- package/dist/types/schemas/user.schema.d.ts +71 -70
- package/dist/types/schemas/user.schema.d.ts.map +1 -1
- package/dist/types/services/affiliate.service.d.ts.map +1 -1
- package/dist/types/services/audit/analysis/analyzeBundleContent.d.ts.map +1 -1
- package/dist/types/services/audit/analysis/analyzeLinguisticStructure.d.ts.map +1 -1
- package/dist/types/services/audit/analysis/analyzeRobots.d.ts.map +1 -1
- package/dist/types/services/audit/analysis/analyzeSitemap.d.ts.map +1 -1
- package/dist/types/services/audit/analysis/calculateScore.d.ts.map +1 -1
- package/dist/types/services/audit/checkers/bundleChecker.d.ts.map +1 -1
- package/dist/types/services/audit/recursiveAudit.service.d.ts +5 -4
- package/dist/types/services/audit/recursiveAudit.service.d.ts.map +1 -1
- package/dist/types/services/audit/types.d.ts.map +1 -1
- package/dist/types/services/bitbucket.service.d.ts.map +1 -1
- package/dist/types/services/cliSessionToken.service.d.ts.map +1 -1
- package/dist/types/services/dictionary.service.d.ts.map +1 -1
- package/dist/types/services/email.service.d.ts.map +1 -1
- package/dist/types/services/github.service.d.ts.map +1 -1
- package/dist/types/services/gitlab.service.d.ts.map +1 -1
- package/dist/types/services/oAuth2.service.d.ts.map +1 -1
- package/dist/types/services/organization.service.d.ts.map +1 -1
- package/dist/types/services/project/projectScreenshot.service.d.ts.map +1 -1
- package/dist/types/services/project.service.d.ts.map +1 -1
- package/dist/types/services/promoCode.service.d.ts.map +1 -1
- package/dist/types/services/reviewer/pictureUpload.service.d.ts.map +1 -1
- package/dist/types/services/reviewer.service.d.ts.map +1 -1
- package/dist/types/services/reviewerMessage.service.d.ts.map +1 -1
- package/dist/types/services/reviewerMission.service.d.ts.map +1 -1
- package/dist/types/services/session.service.d.ts.map +1 -1
- package/dist/types/services/showcase/showcaseProject.service.d.ts.map +1 -1
- package/dist/types/services/showcase/showcaseScan.service.d.ts.map +1 -1
- package/dist/types/services/showcase/showcaseUploadScreenshot.service.d.ts.map +1 -1
- package/dist/types/services/showcase/showcaseVerifyBundle.service.d.ts.map +1 -1
- package/dist/types/services/showcase/showcaseVerifyGithub.service.d.ts.map +1 -1
- package/dist/types/services/subscription.service.d.ts.map +1 -1
- package/dist/types/services/tag.service.d.ts.map +1 -1
- package/dist/types/services/translationQueue.service.d.ts +2 -1
- package/dist/types/services/translationQueue.service.d.ts.map +1 -1
- package/dist/types/services/translationWorker.service.d.ts.map +1 -1
- package/dist/types/services/user/avatarUpload.service.d.ts.map +1 -1
- package/dist/types/services/user.service.d.ts.map +1 -1
- package/dist/types/services/webhook.service.d.ts.map +1 -1
- package/dist/types/types/Routes.d.ts.map +1 -1
- package/dist/types/types/account.types.d.ts.map +1 -1
- package/dist/types/types/affiliate.types.d.ts.map +1 -1
- package/dist/types/types/affiliateInvitation.types.d.ts.map +1 -1
- package/dist/types/types/dictionary.types.d.ts.map +1 -1
- package/dist/types/types/discussion.types.d.ts.map +1 -1
- package/dist/types/types/oAuth2.types.d.ts.map +1 -1
- package/dist/types/types/organization.types.d.ts.map +1 -1
- package/dist/types/types/plan.types.d.ts.map +1 -1
- package/dist/types/types/project.types.d.ts.map +1 -1
- package/dist/types/types/promoCode.types.d.ts.map +1 -1
- package/dist/types/types/reviewer.types.d.ts.map +1 -1
- package/dist/types/types/session.types.d.ts.map +1 -1
- package/dist/types/types/showcaseProject.types.d.ts.map +1 -1
- package/dist/types/types/tag.types.d.ts.map +1 -1
- package/dist/types/types/user.types.d.ts.map +1 -1
- package/dist/types/utils/AI/askDocQuestion/askDocQuestion.d.ts.map +1 -1
- package/dist/types/utils/AI/askDocQuestion/indexMarkdownFiles.d.ts.map +1 -1
- package/dist/types/utils/AI/auditDictionary/index.d.ts.map +1 -1
- package/dist/types/utils/AI/auditDictionaryField/index.d.ts.map +1 -1
- package/dist/types/utils/AI/auditDictionaryMetadata/index.d.ts.map +1 -1
- package/dist/types/utils/AI/auditTag/index.d.ts.map +1 -1
- package/dist/types/utils/AI/autocomplete/index.d.ts.map +1 -1
- package/dist/types/utils/AI/chat/index.d.ts.map +1 -1
- package/dist/types/utils/AI/chat/mcpInProcessTools.d.ts.map +1 -1
- package/dist/types/utils/AI/chat/sessionTools.d.ts +25 -24
- package/dist/types/utils/AI/chat/sessionTools.d.ts.map +1 -1
- package/dist/types/utils/AI/customQuery/index.d.ts.map +1 -1
- package/dist/types/utils/AI/translateDictionaryDB.d.ts.map +1 -1
- package/dist/types/utils/AI/translateJSON/index.d.ts.map +1 -1
- package/dist/types/utils/auth/getAuth.d.ts.map +1 -1
- package/dist/types/utils/cors.d.ts +1 -7
- package/dist/types/utils/cors.d.ts.map +1 -1
- package/dist/types/utils/demoDictionaries.d.ts.map +1 -1
- package/dist/types/utils/ensureArrayQueryFilter.d.ts.map +1 -1
- package/dist/types/utils/errors/ErrorHandler.d.ts +8 -6
- package/dist/types/utils/errors/ErrorHandler.d.ts.map +1 -1
- package/dist/types/utils/errors/ErrorsClass.d.ts.map +1 -1
- package/dist/types/utils/errors/errorCodes.d.ts.map +1 -1
- package/dist/types/utils/filtersAndPagination/getDictionaryFiltersAndPagination.d.ts.map +1 -1
- package/dist/types/utils/filtersAndPagination/getDiscussionFiltersAndPagination.d.ts.map +1 -1
- package/dist/types/utils/filtersAndPagination/getFiltersAndPaginationFromBody.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 +7 -6
- package/dist/types/utils/filtersAndPagination/getTagFiltersAndPagination.d.ts.map +1 -1
- package/dist/types/utils/filtersAndPagination/getUserFiltersAndPagination.d.ts.map +1 -1
- package/dist/types/utils/getFaviconUrl.d.ts.map +1 -1
- package/dist/types/utils/github/connectGithub.d.ts.map +1 -1
- package/dist/types/utils/httpStatusCodes.d.ts.map +1 -1
- package/dist/types/utils/image/resizeImage.d.ts.map +1 -1
- package/dist/types/utils/mapper/dictionary.d.ts.map +1 -1
- package/dist/types/utils/mapper/project.d.ts.map +1 -1
- package/dist/types/utils/mapper/session.d.ts.map +1 -1
- package/dist/types/utils/mapper/showcaseProject.d.ts.map +1 -1
- package/dist/types/utils/mapper/tag.d.ts.map +1 -1
- package/dist/types/utils/mergeFunctionTypes.d.ts.map +1 -1
- package/dist/types/utils/mongoDB/connectDB.d.ts.map +1 -1
- package/dist/types/utils/mongoDB/types.d.ts.map +1 -1
- package/dist/types/utils/oAuth2.d.ts.map +1 -1
- package/dist/types/utils/permissions.d.ts +2 -1
- package/dist/types/utils/permissions.d.ts.map +1 -1
- package/dist/types/utils/plan.d.ts.map +1 -1
- package/dist/types/utils/rateLimiter.d.ts.map +1 -1
- package/dist/types/utils/redis/connectRedis.d.ts.map +1 -1
- package/dist/types/utils/responseData.d.ts.map +1 -1
- package/dist/types/utils/s3/s3Client.d.ts.map +1 -1
- package/dist/types/utils/validation/validateDictionary.d.ts.map +1 -1
- package/dist/types/utils/validation/validateOrganization.d.ts.map +1 -1
- package/dist/types/utils/validation/validateProject.d.ts.map +1 -1
- package/dist/types/utils/validation/validateTag.d.ts.map +1 -1
- package/dist/types/utils/validation/validateUser.d.ts.map +1 -1
- package/package.json +17 -17
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discussion.schema.mjs","names":[],"sources":["../../../src/schemas/discussion.schema.ts"],"sourcesContent":["import type { RenameId } from '@utils/mongoDB/types';\nimport { type Model, model, Schema } from 'mongoose';\nimport type { Discussion, DiscussionSchema } from '@/types/discussion.types';\n\nexport const discussionSchema = new Schema<DiscussionSchema>(\n {\n discussionId: {\n type: String,\n required: true,\n unique: true,\n },\n messages: [\n {\n role: {\n type: String,\n required: true,\n enum: ['user', 'assistant', 'system'],\n },\n content: {\n type: String,\n required: true,\n },\n timestamp: {\n type: Date,\n default: Date.now,\n },\n relatedFiles: {\n type: [String],\n },\n },\n ],\n userId: {\n type: Schema.Types.ObjectId,\n ref: 'user',\n required: false,\n },\n projectId: {\n type: Schema.Types.ObjectId,\n ref: 'project',\n required: false,\n },\n organizationId: {\n type: Schema.Types.ObjectId,\n ref: 'organization',\n required: false,\n },\n title: {\n type: String,\n required: false,\n },\n type: {\n type: String,\n enum: ['doc', 'dashboard'],\n required: false,\n },\n isArchived: {\n type: Boolean,\n default: false,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\nexport const DiscussionModel = model<RenameId<Discussion>, Model<Discussion>>(\n 'discussion',\n discussionSchema\n);\n"],"mappings":";;;AAIA,MAAa,mBAAmB,IAAI,OAClC;CACE,cAAc;EACZ,MAAM;EACN,UAAU;EACV,QAAQ;
|
|
1
|
+
{"version":3,"file":"discussion.schema.mjs","names":[],"sources":["../../../src/schemas/discussion.schema.ts"],"sourcesContent":["import type { RenameId } from '@utils/mongoDB/types';\nimport { type Model, model, Schema } from 'mongoose';\nimport type { Discussion, DiscussionSchema } from '@/types/discussion.types';\n\nexport const discussionSchema = new Schema<DiscussionSchema>(\n {\n discussionId: {\n type: String,\n required: true,\n unique: true,\n },\n messages: [\n {\n role: {\n type: String,\n required: true,\n enum: ['user', 'assistant', 'system'],\n },\n content: {\n type: String,\n required: true,\n },\n timestamp: {\n type: Date,\n default: Date.now,\n },\n relatedFiles: {\n type: [String],\n },\n },\n ],\n userId: {\n type: Schema.Types.ObjectId,\n ref: 'user',\n required: false,\n },\n projectId: {\n type: Schema.Types.ObjectId,\n ref: 'project',\n required: false,\n },\n organizationId: {\n type: Schema.Types.ObjectId,\n ref: 'organization',\n required: false,\n },\n title: {\n type: String,\n required: false,\n },\n type: {\n type: String,\n enum: ['doc', 'dashboard'],\n required: false,\n },\n isArchived: {\n type: Boolean,\n default: false,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\nexport const DiscussionModel = model<RenameId<Discussion>, Model<Discussion>>(\n 'discussion',\n discussionSchema\n);\n"],"mappings":";;;AAIA,MAAa,mBAAmB,IAAI,OAClC;CACE,cAAc;EACZ,MAAM;EACN,UAAU;EACV,QAAQ;EACT;CACD,UAAU,CACR;EACE,MAAM;GACJ,MAAM;GACN,UAAU;GACV,MAAM;IAAC;IAAQ;IAAa;IAAS;GACtC;EACD,SAAS;GACP,MAAM;GACN,UAAU;GACX;EACD,WAAW;GACT,MAAM;GACN,SAAS,KAAK;GACf;EACD,cAAc,EACZ,MAAM,CAAC,OAAO,EACf;EACF,CACF;CACD,QAAQ;EACN,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;EACX;CACD,WAAW;EACT,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;EACX;CACD,gBAAgB;EACd,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;EACX;CACD,OAAO;EACL,MAAM;EACN,UAAU;EACX;CACD,MAAM;EACJ,MAAM;EACN,MAAM,CAAC,OAAO,YAAY;EAC1B,UAAU;EACX;CACD,YAAY;EACV,MAAM;EACN,SAAS;EACV;CACF,EACD;CACE,YAAY;CAEZ,QAAQ;EACN,UAAU;EACV,YAAY;EACZ,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI,IAAI,UAAU;IACnB;;EAEJ;CACD,UAAU;EACR,UAAU;EACV,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI;IACL;;EAEJ;CACF,CACF;AAED,MAAa,kBAAkB,MAC7B,cACA,iBACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oAuth2.schema.mjs","names":[],"sources":["../../../src/schemas/oAuth2.schema.ts"],"sourcesContent":["import type { Client, Token as TokenType } from '@node-oauth/oauth2-server';\nimport { type Model, model, Schema } from 'mongoose';\nimport type { User } from '@/types/user.types';\n\nexport type Token = Omit<TokenType, 'client' | 'user'> & {\n clientId: Client['id'];\n userId: User['id'];\n};\n\nexport const accessTokenSchema = new Schema<Token>(\n {\n accessToken: {\n type: String,\n required: true,\n },\n accessTokenExpiresAt: {\n type: Date,\n },\n clientId: {\n type: String,\n ref: 'Project',\n required: true,\n },\n userId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\n// MongoDB TTL fallback: tokens are normally garbage collected by their\n// accessTokenExpiresAt, but if the sliding-refresh keeps a token alive for a\n// long time we still want a hard upper bound from creation.\naccessTokenSchema.index(\n { createdAt: 1 },\n {\n expireAfterSeconds: 60 * 60 * 24 * 90, // 90 Days\n }\n);\n\nexport const OAuth2AccessTokenModel = model<Token, Model<Token>>(\n 'oAuth2',\n accessTokenSchema\n);\n"],"mappings":";;;AASA,MAAa,oBAAoB,IAAI,OACnC;CACE,aAAa;EACX,MAAM;EACN,UAAU;
|
|
1
|
+
{"version":3,"file":"oAuth2.schema.mjs","names":[],"sources":["../../../src/schemas/oAuth2.schema.ts"],"sourcesContent":["import type { Client, Token as TokenType } from '@node-oauth/oauth2-server';\nimport { type Model, model, Schema } from 'mongoose';\nimport type { User } from '@/types/user.types';\n\nexport type Token = Omit<TokenType, 'client' | 'user'> & {\n clientId: Client['id'];\n userId: User['id'];\n};\n\nexport const accessTokenSchema = new Schema<Token>(\n {\n accessToken: {\n type: String,\n required: true,\n },\n accessTokenExpiresAt: {\n type: Date,\n },\n clientId: {\n type: String,\n ref: 'Project',\n required: true,\n },\n userId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\n// MongoDB TTL fallback: tokens are normally garbage collected by their\n// accessTokenExpiresAt, but if the sliding-refresh keeps a token alive for a\n// long time we still want a hard upper bound from creation.\naccessTokenSchema.index(\n { createdAt: 1 },\n {\n expireAfterSeconds: 60 * 60 * 24 * 90, // 90 Days\n }\n);\n\nexport const OAuth2AccessTokenModel = model<Token, Model<Token>>(\n 'oAuth2',\n accessTokenSchema\n);\n"],"mappings":";;;AASA,MAAa,oBAAoB,IAAI,OACnC;CACE,aAAa;EACX,MAAM;EACN,UAAU;EACX;CACD,sBAAsB,EACpB,MAAM,MACP;CACD,UAAU;EACR,MAAM;EACN,KAAK;EACL,UAAU;EACX;CACD,QAAQ;EACN,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;EACX;CACF,EACD;CACE,YAAY;CAEZ,QAAQ;EACN,UAAU;EACV,YAAY;EACZ,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI,IAAI,UAAU;IACnB;;EAEJ;CACD,UAAU;EACR,UAAU;EACV,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI;IACL;;EAEJ;CACF,CACF;AAKD,kBAAkB,MAChB,EAAE,WAAW,GAAG,EAChB,EACE,oBAAoB,OAAU,KAAK,IACpC,CACF;AAED,MAAa,yBAAyB,MACpC,UACA,kBACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organization.schema.mjs","names":[],"sources":["../../../src/schemas/organization.schema.ts"],"sourcesContent":["import {\n MEMBERS_MIN_LENGTH,\n NAME_MAX_LENGTH,\n NAME_MIN_LENGTH,\n} from '@utils/validation/validateOrganization';\nimport { model, Schema } from 'mongoose';\nimport type {\n OrganizationModelType,\n OrganizationSchema,\n} from '@/types/organization.types';\nimport { planSchema } from './plans.schema';\n\nexport const organizationSchema = new Schema<OrganizationSchema>(\n {\n name: {\n type: String,\n required: true,\n minlength: NAME_MIN_LENGTH,\n maxlength: NAME_MAX_LENGTH,\n },\n membersIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n adminsIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n creatorId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n plan: {\n type: planSchema,\n },\n ssoEnabled: {\n type: Boolean,\n default: false,\n },\n domain: {\n type: String,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\n// Add virtual field for id\norganizationSchema.virtual('id').get(function () {\n return this._id.toString();\n});\n\nexport const OrganizationModel = model<\n OrganizationSchema,\n OrganizationModelType\n>('organization', organizationSchema);\n"],"mappings":";;;;;AAYA,MAAa,qBAAqB,IAAI,OACpC;CACE,MAAM;EACJ,MAAM;EACN,UAAU;EACV;EACA;
|
|
1
|
+
{"version":3,"file":"organization.schema.mjs","names":[],"sources":["../../../src/schemas/organization.schema.ts"],"sourcesContent":["import {\n MEMBERS_MIN_LENGTH,\n NAME_MAX_LENGTH,\n NAME_MIN_LENGTH,\n} from '@utils/validation/validateOrganization';\nimport { model, Schema } from 'mongoose';\nimport type {\n OrganizationModelType,\n OrganizationSchema,\n} from '@/types/organization.types';\nimport { planSchema } from './plans.schema';\n\nexport const organizationSchema = new Schema<OrganizationSchema>(\n {\n name: {\n type: String,\n required: true,\n minlength: NAME_MIN_LENGTH,\n maxlength: NAME_MAX_LENGTH,\n },\n membersIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n adminsIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n creatorId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n plan: {\n type: planSchema,\n },\n ssoEnabled: {\n type: Boolean,\n default: false,\n },\n domain: {\n type: String,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\n// Add virtual field for id\norganizationSchema.virtual('id').get(function () {\n return this._id.toString();\n});\n\nexport const OrganizationModel = model<\n OrganizationSchema,\n OrganizationModelType\n>('organization', organizationSchema);\n"],"mappings":";;;;;AAYA,MAAa,qBAAqB,IAAI,OACpC;CACE,MAAM;EACJ,MAAM;EACN,UAAU;EACV;EACA;EACD;CACD,YAAY;EACV,MAAM,CAAC,OAAO,MAAM,SAAS;EAC7B,KAAK;EACL,UAAU;EACV;EACD;CACD,WAAW;EACT,MAAM,CAAC,OAAO,MAAM,SAAS;EAC7B,KAAK;EACL,UAAU;EACV;EACD;CACD,WAAW;EACT,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;EACX;CACD,MAAM,EACJ,MAAM,YACP;CACD,YAAY;EACV,MAAM;EACN,SAAS;EACV;CACD,QAAQ,EACN,MAAM,QACP;CACF,EACD;CACE,YAAY;CAEZ,QAAQ;EACN,UAAU;EACV,YAAY;EACZ,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI,IAAI,UAAU;IACnB;;EAEJ;CACD,UAAU;EACR,UAAU;EACV,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI;IACL;;EAEJ;CACF,CACF;AAGD,mBAAmB,QAAQ,KAAK,CAAC,IAAI,WAAY;AAC/C,QAAO,KAAK,IAAI,UAAU;EAC1B;AAEF,MAAa,oBAAoB,MAG/B,gBAAgB,mBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plans.schema.mjs","names":[],"sources":["../../../src/schemas/plans.schema.ts"],"sourcesContent":["import { Schema } from 'mongoose';\nimport type { PlanSchema } from '@/types/plan.types';\n\nexport const planSchema = new Schema<PlanSchema>(\n {\n type: {\n type: String,\n required: true,\n enum: ['PREMIUM', 'ENTERPRISE'],\n },\n period: {\n type: String,\n required: true,\n enum: ['MONTHLY', 'YEARLY'],\n default: 'MONTHLY',\n },\n creatorId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n subscriptionId: {\n type: String,\n required: true,\n },\n customerId: {\n type: String,\n required: true,\n },\n priceId: {\n type: String,\n required: true,\n },\n status: {\n type: String,\n required: true,\n enum: [\n 'active',\n 'canceled',\n 'past_due',\n 'unpaid',\n 'incomplete',\n 'incomplete_expired',\n 'paused',\n 'trialing',\n ],\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n"],"mappings":";;;AAGA,MAAa,aAAa,IAAI,OAC5B;CACE,MAAM;EACJ,MAAM;EACN,UAAU;EACV,MAAM,CAAC,WAAW,
|
|
1
|
+
{"version":3,"file":"plans.schema.mjs","names":[],"sources":["../../../src/schemas/plans.schema.ts"],"sourcesContent":["import { Schema } from 'mongoose';\nimport type { PlanSchema } from '@/types/plan.types';\n\nexport const planSchema = new Schema<PlanSchema>(\n {\n type: {\n type: String,\n required: true,\n enum: ['PREMIUM', 'ENTERPRISE'],\n },\n period: {\n type: String,\n required: true,\n enum: ['MONTHLY', 'YEARLY'],\n default: 'MONTHLY',\n },\n creatorId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n subscriptionId: {\n type: String,\n required: true,\n },\n customerId: {\n type: String,\n required: true,\n },\n priceId: {\n type: String,\n required: true,\n },\n status: {\n type: String,\n required: true,\n enum: [\n 'active',\n 'canceled',\n 'past_due',\n 'unpaid',\n 'incomplete',\n 'incomplete_expired',\n 'paused',\n 'trialing',\n ],\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n"],"mappings":";;;AAGA,MAAa,aAAa,IAAI,OAC5B;CACE,MAAM;EACJ,MAAM;EACN,UAAU;EACV,MAAM,CAAC,WAAW,aAAa;EAChC;CACD,QAAQ;EACN,MAAM;EACN,UAAU;EACV,MAAM,CAAC,WAAW,SAAS;EAC3B,SAAS;EACV;CACD,WAAW;EACT,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;EACX;CACD,gBAAgB;EACd,MAAM;EACN,UAAU;EACX;CACD,YAAY;EACV,MAAM;EACN,UAAU;EACX;CACD,SAAS;EACP,MAAM;EACN,UAAU;EACX;CACD,QAAQ;EACN,MAAM;EACN,UAAU;EACV,MAAM;GACJ;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD;EACF;CACF,EACD;CACE,YAAY;CAEZ,QAAQ;EACN,UAAU;EACV,YAAY;EACZ,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI,IAAI,UAAU;IACnB;;EAEJ;CACD,UAAU;EACR,UAAU;EACV,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI;IACL;;EAEJ;CACF,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.schema.mjs","names":[],"sources":["../../../src/schemas/project.schema.ts"],"sourcesContent":["import { ALL_LOCALES } from '@intlayer/types/allLocales';\nimport { AiProviders } from '@intlayer/types/config';\nimport type { RenameId } from '@utils/mongoDB/types';\nimport {\n MEMBERS_MIN_LENGTH,\n NAME_MAX_LENGTH,\n NAME_MIN_LENGTH,\n} from '@utils/validation/validateProject';\nimport { model, Schema } from 'mongoose';\nimport type {\n Environment,\n OAuth2Access,\n Project,\n ProjectModelType,\n ProjectSchema,\n} from '@/types/project.types';\n\n// Define the oAuth2Access subdocument schema with timestamps\nconst oAuth2AccessSchema = new Schema<RenameId<OAuth2Access>>(\n {\n clientId: { type: String, required: true },\n clientSecret: { type: String, required: true },\n userId: { type: Schema.Types.ObjectId, ref: 'User', required: true },\n name: { type: String, required: true },\n expiresAt: { type: Date },\n accessToken: { type: [String], required: true, default: [] },\n grants: { type: [String], required: true, default: [] },\n allowedEnvironmentIds: { type: Schema.Types.Mixed, default: null },\n allowedLocales: { type: [String], default: null },\n },\n {\n timestamps: true,\n }\n);\n\nconst memberAccessSchema = new Schema(\n {\n userId: { type: Schema.Types.ObjectId, ref: 'User', required: true },\n allowedEnvironmentIds: { type: Schema.Types.Mixed, default: null },\n allowedLocales: { type: [String], default: null },\n },\n { _id: false }\n);\n\n// Schema for generic webhooks (Vercel, Netlify, Custom, etc.)\nconst webhookSchema = new Schema(\n {\n name: { type: String, required: true },\n url: { type: String, required: true },\n enabled: { type: Boolean, default: true },\n secret: { type: String }, // Optional signature secret\n },\n { _id: true }\n);\n\nconst projectConfigSchema = new Schema<Project['configuration']>(\n {\n internationalization: {\n locales: {\n type: [String],\n enum: Object.values(ALL_LOCALES),\n required: true,\n },\n defaultLocale: {\n type: String,\n enum: Object.values(ALL_LOCALES),\n },\n },\n editor: {\n applicationURL: {\n type: String,\n },\n cmsURL: {\n type: String,\n },\n },\n ai: {\n provider: {\n type: String,\n enum: Object.values(AiProviders),\n },\n model: {\n type: String,\n },\n apiKey: {\n type: String,\n },\n applicationContext: {\n type: String,\n },\n baseURL: {\n type: String,\n },\n },\n },\n {\n _id: false, // Prevents the generation of an _id field for this subdocument\n }\n);\n\n// Schema for webhooks/CI configuration (top-level project property, not part of configuration)\nconst webhooksConfigSchema = new Schema<Project['webhooks']>(\n {\n autoTriggerBuilds: { type: Boolean, default: false }, // Master toggle\n webhooks: [webhookSchema], // Generic hooks (Vercel, Netlify, Custom)\n },\n {\n _id: false,\n }\n);\n\nconst repositorySchema = new Schema<Project['repository']>(\n {\n provider: {\n type: String,\n enum: ['github', 'gitlab', 'bitbucket'],\n required: true,\n },\n owner: { type: String, required: true },\n repository: { type: String, required: true },\n branch: { type: String, default: 'main' },\n url: { type: String, required: true },\n configFilePath: { type: String, required: true },\n token: { type: String }, // Repo-scoped OAuth token for CI operations\n // GitHub specific\n installationId: { type: Number },\n // GitLab specific\n projectId: { type: Number },\n instanceUrl: { type: String },\n // Bitbucket specific\n workspace: { type: String },\n },\n {\n _id: false,\n }\n);\n\nconst environmentSchema = new Schema<Environment>(\n {\n name: {\n type: String,\n required: true,\n validate: {\n validator: (value: string) => !/\\s/.test(value),\n message: 'Environment name must not contain spaces.',\n },\n },\n isDefault: { type: Boolean, default: false },\n configuration: projectConfigSchema,\n },\n { timestamps: true }\n);\n\nexport const projectSchema = new Schema<ProjectSchema>(\n {\n organizationId: {\n type: Schema.Types.ObjectId,\n ref: 'Organization',\n required: true,\n },\n name: {\n type: String,\n required: true,\n minlength: NAME_MIN_LENGTH,\n maxlength: NAME_MAX_LENGTH,\n },\n configuration: projectConfigSchema,\n oAuth2Access: [oAuth2AccessSchema],\n repository: repositorySchema,\n webhooks: webhooksConfigSchema,\n autoFill: {\n type: Boolean,\n default: false,\n },\n imageUrl: {\n type: String,\n },\n environments: {\n type: [environmentSchema],\n default: [],\n },\n membersIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n adminsIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n viewersIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n default: [],\n },\n memberAccess: {\n type: [memberAccessSchema],\n default: [],\n },\n creatorId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\nexport const ProjectModel = model<ProjectSchema, ProjectModelType>(\n 'project',\n projectSchema\n);\n"],"mappings":";;;;;;AAkBA,MAAM,qBAAqB,IAAI,OAC7B;CACE,UAAU;EAAE,MAAM;EAAQ,UAAU;
|
|
1
|
+
{"version":3,"file":"project.schema.mjs","names":[],"sources":["../../../src/schemas/project.schema.ts"],"sourcesContent":["import { ALL_LOCALES } from '@intlayer/types/allLocales';\nimport { AiProviders } from '@intlayer/types/config';\nimport type { RenameId } from '@utils/mongoDB/types';\nimport {\n MEMBERS_MIN_LENGTH,\n NAME_MAX_LENGTH,\n NAME_MIN_LENGTH,\n} from '@utils/validation/validateProject';\nimport { model, Schema } from 'mongoose';\nimport type {\n Environment,\n OAuth2Access,\n Project,\n ProjectModelType,\n ProjectSchema,\n} from '@/types/project.types';\n\n// Define the oAuth2Access subdocument schema with timestamps\nconst oAuth2AccessSchema = new Schema<RenameId<OAuth2Access>>(\n {\n clientId: { type: String, required: true },\n clientSecret: { type: String, required: true },\n userId: { type: Schema.Types.ObjectId, ref: 'User', required: true },\n name: { type: String, required: true },\n expiresAt: { type: Date },\n accessToken: { type: [String], required: true, default: [] },\n grants: { type: [String], required: true, default: [] },\n allowedEnvironmentIds: { type: Schema.Types.Mixed, default: null },\n allowedLocales: { type: [String], default: null },\n },\n {\n timestamps: true,\n }\n);\n\nconst memberAccessSchema = new Schema(\n {\n userId: { type: Schema.Types.ObjectId, ref: 'User', required: true },\n allowedEnvironmentIds: { type: Schema.Types.Mixed, default: null },\n allowedLocales: { type: [String], default: null },\n },\n { _id: false }\n);\n\n// Schema for generic webhooks (Vercel, Netlify, Custom, etc.)\nconst webhookSchema = new Schema(\n {\n name: { type: String, required: true },\n url: { type: String, required: true },\n enabled: { type: Boolean, default: true },\n secret: { type: String }, // Optional signature secret\n },\n { _id: true }\n);\n\nconst projectConfigSchema = new Schema<Project['configuration']>(\n {\n internationalization: {\n locales: {\n type: [String],\n enum: Object.values(ALL_LOCALES),\n required: true,\n },\n defaultLocale: {\n type: String,\n enum: Object.values(ALL_LOCALES),\n },\n },\n editor: {\n applicationURL: {\n type: String,\n },\n cmsURL: {\n type: String,\n },\n },\n ai: {\n provider: {\n type: String,\n enum: Object.values(AiProviders),\n },\n model: {\n type: String,\n },\n apiKey: {\n type: String,\n },\n applicationContext: {\n type: String,\n },\n baseURL: {\n type: String,\n },\n },\n },\n {\n _id: false, // Prevents the generation of an _id field for this subdocument\n }\n);\n\n// Schema for webhooks/CI configuration (top-level project property, not part of configuration)\nconst webhooksConfigSchema = new Schema<Project['webhooks']>(\n {\n autoTriggerBuilds: { type: Boolean, default: false }, // Master toggle\n webhooks: [webhookSchema], // Generic hooks (Vercel, Netlify, Custom)\n },\n {\n _id: false,\n }\n);\n\nconst repositorySchema = new Schema<Project['repository']>(\n {\n provider: {\n type: String,\n enum: ['github', 'gitlab', 'bitbucket'],\n required: true,\n },\n owner: { type: String, required: true },\n repository: { type: String, required: true },\n branch: { type: String, default: 'main' },\n url: { type: String, required: true },\n configFilePath: { type: String, required: true },\n token: { type: String }, // Repo-scoped OAuth token for CI operations\n // GitHub specific\n installationId: { type: Number },\n // GitLab specific\n projectId: { type: Number },\n instanceUrl: { type: String },\n // Bitbucket specific\n workspace: { type: String },\n },\n {\n _id: false,\n }\n);\n\nconst environmentSchema = new Schema<Environment>(\n {\n name: {\n type: String,\n required: true,\n validate: {\n validator: (value: string) => !/\\s/.test(value),\n message: 'Environment name must not contain spaces.',\n },\n },\n isDefault: { type: Boolean, default: false },\n configuration: projectConfigSchema,\n },\n { timestamps: true }\n);\n\nexport const projectSchema = new Schema<ProjectSchema>(\n {\n organizationId: {\n type: Schema.Types.ObjectId,\n ref: 'Organization',\n required: true,\n },\n name: {\n type: String,\n required: true,\n minlength: NAME_MIN_LENGTH,\n maxlength: NAME_MAX_LENGTH,\n },\n configuration: projectConfigSchema,\n oAuth2Access: [oAuth2AccessSchema],\n repository: repositorySchema,\n webhooks: webhooksConfigSchema,\n autoFill: {\n type: Boolean,\n default: false,\n },\n imageUrl: {\n type: String,\n },\n environments: {\n type: [environmentSchema],\n default: [],\n },\n membersIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n adminsIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n required: true,\n minlength: MEMBERS_MIN_LENGTH,\n },\n viewersIds: {\n type: [Schema.Types.ObjectId],\n ref: 'User',\n default: [],\n },\n memberAccess: {\n type: [memberAccessSchema],\n default: [],\n },\n creatorId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\nexport const ProjectModel = model<ProjectSchema, ProjectModelType>(\n 'project',\n projectSchema\n);\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promoCode.schema.mjs","names":[],"sources":["../../../src/schemas/promoCode.schema.ts"],"sourcesContent":["import { model, Schema } from 'mongoose';\nimport type {\n PromoCodeModelType,\n PromoCodeSchema,\n} from '@/types/promoCode.types';\n\nconst toJSONTransform = (_doc: any, ret: any) => {\n const { _id, ...rest } = ret;\n return { ...rest, id: _id.toString() };\n};\n\nconst toObjectTransform = (_doc: any, ret: any) => {\n const { _id, ...rest } = ret;\n return { ...rest, id: _id };\n};\n\nexport const promoCodeSchema = new Schema<PromoCodeSchema>(\n {\n code: {\n type: String,\n required: true,\n unique: true,\n uppercase: true,\n trim: true,\n },\n stripeCouponId: { type: String, required: true },\n stripePromotionCodeId: { type: String, required: false },\n affiliateId: {\n type: Schema.Types.ObjectId,\n ref: 'affiliate',\n required: false,\n },\n discountType: {\n type: String,\n enum: ['percentage', 'amount'],\n required: true,\n },\n discountValue: { type: Number, required: true },\n currency: { type: String, required: false },\n maxRedemptions: { type: Number, required: false },\n timesRedeemed: { type: Number, default: 0 },\n active: { type: Boolean, default: true },\n expiresAt: { type: Date, required: false },\n },\n {\n timestamps: true,\n toJSON: {\n virtuals: true,\n versionKey: false,\n transform: toJSONTransform,\n },\n toObject: {\n virtuals: true,\n transform: toObjectTransform,\n },\n }\n);\n\nexport const PromoCodeModel = model<PromoCodeSchema, PromoCodeModelType>(\n 'promoCode',\n promoCodeSchema\n);\nexport default PromoCodeModel;\n"],"mappings":";;;AAMA,MAAM,mBAAmB,MAAW,QAAa;CAC/C,MAAM,EAAE,KAAK,GAAG,SAAS;
|
|
1
|
+
{"version":3,"file":"promoCode.schema.mjs","names":[],"sources":["../../../src/schemas/promoCode.schema.ts"],"sourcesContent":["import { model, Schema } from 'mongoose';\nimport type {\n PromoCodeModelType,\n PromoCodeSchema,\n} from '@/types/promoCode.types';\n\nconst toJSONTransform = (_doc: any, ret: any) => {\n const { _id, ...rest } = ret;\n return { ...rest, id: _id.toString() };\n};\n\nconst toObjectTransform = (_doc: any, ret: any) => {\n const { _id, ...rest } = ret;\n return { ...rest, id: _id };\n};\n\nexport const promoCodeSchema = new Schema<PromoCodeSchema>(\n {\n code: {\n type: String,\n required: true,\n unique: true,\n uppercase: true,\n trim: true,\n },\n stripeCouponId: { type: String, required: true },\n stripePromotionCodeId: { type: String, required: false },\n affiliateId: {\n type: Schema.Types.ObjectId,\n ref: 'affiliate',\n required: false,\n },\n discountType: {\n type: String,\n enum: ['percentage', 'amount'],\n required: true,\n },\n discountValue: { type: Number, required: true },\n currency: { type: String, required: false },\n maxRedemptions: { type: Number, required: false },\n timesRedeemed: { type: Number, default: 0 },\n active: { type: Boolean, default: true },\n expiresAt: { type: Date, required: false },\n },\n {\n timestamps: true,\n toJSON: {\n virtuals: true,\n versionKey: false,\n transform: toJSONTransform,\n },\n toObject: {\n virtuals: true,\n transform: toObjectTransform,\n },\n }\n);\n\nexport const PromoCodeModel = model<PromoCodeSchema, PromoCodeModelType>(\n 'promoCode',\n promoCodeSchema\n);\nexport default PromoCodeModel;\n"],"mappings":";;;AAMA,MAAM,mBAAmB,MAAW,QAAa;CAC/C,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,QAAO;EAAE,GAAG;EAAM,IAAI,IAAI,UAAU;EAAE;;AAGxC,MAAM,qBAAqB,MAAW,QAAa;CACjD,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,QAAO;EAAE,GAAG;EAAM,IAAI;EAAK;;AAG7B,MAAa,kBAAkB,IAAI,OACjC;CACE,MAAM;EACJ,MAAM;EACN,UAAU;EACV,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD,gBAAgB;EAAE,MAAM;EAAQ,UAAU;EAAM;CAChD,uBAAuB;EAAE,MAAM;EAAQ,UAAU;EAAO;CACxD,aAAa;EACX,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;EACX;CACD,cAAc;EACZ,MAAM;EACN,MAAM,CAAC,cAAc,SAAS;EAC9B,UAAU;EACX;CACD,eAAe;EAAE,MAAM;EAAQ,UAAU;EAAM;CAC/C,UAAU;EAAE,MAAM;EAAQ,UAAU;EAAO;CAC3C,gBAAgB;EAAE,MAAM;EAAQ,UAAU;EAAO;CACjD,eAAe;EAAE,MAAM;EAAQ,SAAS;EAAG;CAC3C,QAAQ;EAAE,MAAM;EAAS,SAAS;EAAM;CACxC,WAAW;EAAE,MAAM;EAAM,UAAU;EAAO;CAC3C,EACD;CACE,YAAY;CACZ,QAAQ;EACN,UAAU;EACV,YAAY;EACZ,WAAW;EACZ;CACD,UAAU;EACR,UAAU;EACV,WAAW;EACZ;CACF,CACF;AAED,MAAa,iBAAiB,MAC5B,aACA,gBACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewer.schema.mjs","names":[],"sources":["../../../src/schemas/reviewer.schema.ts"],"sourcesContent":["import { model, Schema } from 'mongoose';\nimport type {\n ReviewerMessageModelType,\n ReviewerMessageSchema,\n ReviewerProfileModelType,\n ReviewerProfileSchema,\n ReviewerReviewModelType,\n ReviewerReviewSchema,\n TranslationMissionModelType,\n TranslationMissionSchema,\n} from '@/types/reviewer.types';\n\nconst toJSONTransform = (_doc: any, ret: any) => {\n const { _id, ...rest } = ret;\n return { ...rest, id: _id.toString() };\n};\n\nconst toObjectTransform = (_doc: any, ret: any) => {\n const { _id, ...rest } = ret;\n return { ...rest, id: _id };\n};\n\nconst schemaOptions = {\n timestamps: true,\n toJSON: { virtuals: true, versionKey: false, transform: toJSONTransform },\n toObject: { virtuals: true, transform: toObjectTransform },\n};\n\n// ── Reviewer Profile ──────────────────────────────────────────────────────\n\nconst languagePairSchema = new Schema(\n {\n from: { type: String, required: true },\n to: { type: String, required: true },\n },\n { _id: false }\n);\n\nexport const reviewerProfileSchema = new Schema<ReviewerProfileSchema>(\n {\n userId: {\n type: Schema.Types.ObjectId,\n ref: 'user',\n required: true,\n unique: true,\n },\n bio: { type: String },\n mainPicture: { type: String },\n coverPicture: { type: String },\n languagePairs: { type: [languagePairSchema], default: [] },\n categories: {\n type: [String],\n enum: [\n 'copywriter',\n 'translator',\n 'proofreader',\n 'technical_writer',\n 'marketing',\n ],\n default: [],\n },\n pricePerHour: { type: Number, required: true, default: 0 },\n status: {\n type: String,\n enum: ['pending', 'active', 'suspended'],\n default: 'pending',\n },\n totalMissions: { type: Number, default: 0 },\n averageRating: { type: Number, default: 0, min: 0, max: 5 },\n reviewCount: { type: Number, default: 0 },\n stripeAccountId: { type: String },\n socialLinks: {\n type: new Schema(\n {\n github: { type: String },\n linkedin: { type: String },\n portfolio: { type: String },\n },\n { _id: false }\n ),\n default: undefined,\n },\n isHidden: { type: Boolean, default: false },\n },\n schemaOptions\n);\n\nexport const ReviewerProfileModel = model<\n ReviewerProfileSchema,\n ReviewerProfileModelType\n>('reviewerProfile', reviewerProfileSchema);\n\n// ── Translation Mission ─────────────────────────────────────────────────────\n\nexport const translationMissionSchema = new Schema<TranslationMissionSchema>(\n {\n reviewerId: {\n type: Schema.Types.ObjectId,\n ref: 'reviewerProfile',\n required: true,\n },\n clientUserId: {\n type: Schema.Types.ObjectId,\n ref: 'user',\n required: true,\n },\n projectId: { type: Schema.Types.ObjectId, ref: 'project' },\n dictionaryIds: {\n type: [Schema.Types.ObjectId],\n ref: 'dictionary',\n default: [],\n },\n sourceLocale: { type: String, required: true },\n targetLocales: { type: [String], required: true },\n wordCount: { type: Number, default: 0 },\n estimatedHours: { type: Number, default: 0 },\n pricePerHour: { type: Number, required: true },\n totalPrice: { type: Number, default: 0 },\n currency: { type: String, default: 'usd' },\n status: {\n type: String,\n enum: [\n 'pending',\n 'accepted',\n 'in_progress',\n 'reviewer_review',\n 'client_review',\n 'completed',\n 'canceled',\n ],\n default: 'pending',\n },\n notes: { type: String },\n aiPreGeneratedAt: { type: Date },\n completedAt: { type: Date },\n canceledAt: { type: Date },\n },\n schemaOptions\n);\n\nexport const TranslationMissionModel = model<\n TranslationMissionSchema,\n TranslationMissionModelType\n>('translationMission', translationMissionSchema);\n\n// ── Reviewer Review ───────────────────────────────────────────────────────\n\nexport const reviewerReviewSchema = new Schema<ReviewerReviewSchema>(\n {\n missionId: {\n type: Schema.Types.ObjectId,\n ref: 'translationMission',\n required: true,\n unique: true,\n },\n reviewerId: {\n type: Schema.Types.ObjectId,\n ref: 'reviewerProfile',\n required: true,\n },\n rating: { type: Number, required: true, min: 1, max: 5 },\n comment: { type: String },\n },\n schemaOptions\n);\n\nexport const ReviewerReviewModel = model<\n ReviewerReviewSchema,\n ReviewerReviewModelType\n>('reviewerReview', reviewerReviewSchema);\n\n// ── Reviewer Message ──────────────────────────────────────────────────────\n\nexport const reviewerMessageSchema = new Schema<ReviewerMessageSchema>(\n {\n missionId: {\n type: Schema.Types.ObjectId,\n ref: 'translationMission',\n required: true,\n },\n senderId: {\n type: Schema.Types.ObjectId,\n ref: 'user',\n required: true,\n },\n content: { type: String, required: true },\n readAt: { type: Date },\n },\n schemaOptions\n);\n\nexport const ReviewerMessageModel = model<\n ReviewerMessageSchema,\n ReviewerMessageModelType\n>('reviewerMessage', reviewerMessageSchema);\n"],"mappings":";;;AAYA,MAAM,mBAAmB,MAAW,QAAa;CAC/C,MAAM,EAAE,KAAK,GAAG,SAAS;
|
|
1
|
+
{"version":3,"file":"reviewer.schema.mjs","names":[],"sources":["../../../src/schemas/reviewer.schema.ts"],"sourcesContent":["import { model, Schema } from 'mongoose';\nimport type {\n ReviewerMessageModelType,\n ReviewerMessageSchema,\n ReviewerProfileModelType,\n ReviewerProfileSchema,\n ReviewerReviewModelType,\n ReviewerReviewSchema,\n TranslationMissionModelType,\n TranslationMissionSchema,\n} from '@/types/reviewer.types';\n\nconst toJSONTransform = (_doc: any, ret: any) => {\n const { _id, ...rest } = ret;\n return { ...rest, id: _id.toString() };\n};\n\nconst toObjectTransform = (_doc: any, ret: any) => {\n const { _id, ...rest } = ret;\n return { ...rest, id: _id };\n};\n\nconst schemaOptions = {\n timestamps: true,\n toJSON: { virtuals: true, versionKey: false, transform: toJSONTransform },\n toObject: { virtuals: true, transform: toObjectTransform },\n};\n\n// ── Reviewer Profile ──────────────────────────────────────────────────────\n\nconst languagePairSchema = new Schema(\n {\n from: { type: String, required: true },\n to: { type: String, required: true },\n },\n { _id: false }\n);\n\nexport const reviewerProfileSchema = new Schema<ReviewerProfileSchema>(\n {\n userId: {\n type: Schema.Types.ObjectId,\n ref: 'user',\n required: true,\n unique: true,\n },\n bio: { type: String },\n mainPicture: { type: String },\n coverPicture: { type: String },\n languagePairs: { type: [languagePairSchema], default: [] },\n categories: {\n type: [String],\n enum: [\n 'copywriter',\n 'translator',\n 'proofreader',\n 'technical_writer',\n 'marketing',\n ],\n default: [],\n },\n pricePerHour: { type: Number, required: true, default: 0 },\n status: {\n type: String,\n enum: ['pending', 'active', 'suspended'],\n default: 'pending',\n },\n totalMissions: { type: Number, default: 0 },\n averageRating: { type: Number, default: 0, min: 0, max: 5 },\n reviewCount: { type: Number, default: 0 },\n stripeAccountId: { type: String },\n socialLinks: {\n type: new Schema(\n {\n github: { type: String },\n linkedin: { type: String },\n portfolio: { type: String },\n },\n { _id: false }\n ),\n default: undefined,\n },\n isHidden: { type: Boolean, default: false },\n },\n schemaOptions\n);\n\nexport const ReviewerProfileModel = model<\n ReviewerProfileSchema,\n ReviewerProfileModelType\n>('reviewerProfile', reviewerProfileSchema);\n\n// ── Translation Mission ─────────────────────────────────────────────────────\n\nexport const translationMissionSchema = new Schema<TranslationMissionSchema>(\n {\n reviewerId: {\n type: Schema.Types.ObjectId,\n ref: 'reviewerProfile',\n required: true,\n },\n clientUserId: {\n type: Schema.Types.ObjectId,\n ref: 'user',\n required: true,\n },\n projectId: { type: Schema.Types.ObjectId, ref: 'project' },\n dictionaryIds: {\n type: [Schema.Types.ObjectId],\n ref: 'dictionary',\n default: [],\n },\n sourceLocale: { type: String, required: true },\n targetLocales: { type: [String], required: true },\n wordCount: { type: Number, default: 0 },\n estimatedHours: { type: Number, default: 0 },\n pricePerHour: { type: Number, required: true },\n totalPrice: { type: Number, default: 0 },\n currency: { type: String, default: 'usd' },\n status: {\n type: String,\n enum: [\n 'pending',\n 'accepted',\n 'in_progress',\n 'reviewer_review',\n 'client_review',\n 'completed',\n 'canceled',\n ],\n default: 'pending',\n },\n notes: { type: String },\n aiPreGeneratedAt: { type: Date },\n completedAt: { type: Date },\n canceledAt: { type: Date },\n },\n schemaOptions\n);\n\nexport const TranslationMissionModel = model<\n TranslationMissionSchema,\n TranslationMissionModelType\n>('translationMission', translationMissionSchema);\n\n// ── Reviewer Review ───────────────────────────────────────────────────────\n\nexport const reviewerReviewSchema = new Schema<ReviewerReviewSchema>(\n {\n missionId: {\n type: Schema.Types.ObjectId,\n ref: 'translationMission',\n required: true,\n unique: true,\n },\n reviewerId: {\n type: Schema.Types.ObjectId,\n ref: 'reviewerProfile',\n required: true,\n },\n rating: { type: Number, required: true, min: 1, max: 5 },\n comment: { type: String },\n },\n schemaOptions\n);\n\nexport const ReviewerReviewModel = model<\n ReviewerReviewSchema,\n ReviewerReviewModelType\n>('reviewerReview', reviewerReviewSchema);\n\n// ── Reviewer Message ──────────────────────────────────────────────────────\n\nexport const reviewerMessageSchema = new Schema<ReviewerMessageSchema>(\n {\n missionId: {\n type: Schema.Types.ObjectId,\n ref: 'translationMission',\n required: true,\n },\n senderId: {\n type: Schema.Types.ObjectId,\n ref: 'user',\n required: true,\n },\n content: { type: String, required: true },\n readAt: { type: Date },\n },\n schemaOptions\n);\n\nexport const ReviewerMessageModel = model<\n ReviewerMessageSchema,\n ReviewerMessageModelType\n>('reviewerMessage', reviewerMessageSchema);\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.schema.mjs","names":[],"sources":["../../../src/schemas/session.schema.ts"],"sourcesContent":["import { model, Schema } from 'mongoose';\nimport type { SessionModelType, SessionSchema } from '@/types/session.types';\n\nexport const sessionSchema = new Schema<SessionSchema>(\n {\n activeOrganizationId: {\n type: Schema.Types.ObjectId,\n ref: 'Organization',\n required: false,\n },\n activeProjectId: {\n type: Schema.Types.ObjectId,\n ref: 'Project',\n required: false,\n },\n activeEnvironmentId: {\n type: Schema.Types.ObjectId,\n required: false,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\nexport const SessionModel = model<SessionSchema, SessionModelType>(\n 'session',\n sessionSchema\n);\n"],"mappings":";;;AAGA,MAAa,gBAAgB,IAAI,OAC/B;CACE,sBAAsB;EACpB,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;
|
|
1
|
+
{"version":3,"file":"session.schema.mjs","names":[],"sources":["../../../src/schemas/session.schema.ts"],"sourcesContent":["import { model, Schema } from 'mongoose';\nimport type { SessionModelType, SessionSchema } from '@/types/session.types';\n\nexport const sessionSchema = new Schema<SessionSchema>(\n {\n activeOrganizationId: {\n type: Schema.Types.ObjectId,\n ref: 'Organization',\n required: false,\n },\n activeProjectId: {\n type: Schema.Types.ObjectId,\n ref: 'Project',\n required: false,\n },\n activeEnvironmentId: {\n type: Schema.Types.ObjectId,\n required: false,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\nexport const SessionModel = model<SessionSchema, SessionModelType>(\n 'session',\n sessionSchema\n);\n"],"mappings":";;;AAGA,MAAa,gBAAgB,IAAI,OAC/B;CACE,sBAAsB;EACpB,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;EACX;CACD,iBAAiB;EACf,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;EACX;CACD,qBAAqB;EACnB,MAAM,OAAO,MAAM;EACnB,UAAU;EACX;CACF,EACD;CACE,YAAY;CAEZ,QAAQ;EACN,UAAU;EACV,YAAY;EACZ,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI,IAAI,UAAU;IACnB;;EAEJ;CACD,UAAU;EACR,UAAU;EACV,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI;IACL;;EAEJ;CACF,CACF;AAED,MAAa,eAAe,MAC1B,WACA,cACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"showcaseProject.schema.mjs","names":[],"sources":["../../../src/schemas/showcaseProject.schema.ts"],"sourcesContent":["import { model, Schema } from 'mongoose';\nimport type {\n ShowcaseProjectDocument,\n ShowcaseProjectModelType,\n} from '@/types/showcaseProject.types';\n\nconst scanDetailsSchema = new Schema(\n {\n score: { type: Number },\n langTag: { type: String },\n htmlDir: { type: String },\n hreflangs: { type: [String] },\n hasXDefault: { type: Boolean },\n hasCanonical: { type: Boolean },\n hasLocalizedLinks: { type: Boolean },\n allAnchorsLocalized: { type: Boolean },\n robotsTxt: {\n accessible: { type: Boolean },\n disallowWithoutLocaleAlternates: { type: Boolean },\n },\n sitemapXml: {\n urlsDiscoveredCount: { type: Number },\n alternatesPresent: { type: Boolean },\n xDefaultPresent: { type: Boolean },\n },\n },\n { _id: false }\n);\n\nexport const showcaseProjectSchema = new Schema<ShowcaseProjectDocument>(\n {\n title: { type: String, required: true },\n description: { type: String, default: '' },\n imageUrl: { type: String, default: '' },\n logoUrl: { type: String },\n websiteUrl: { type: String, required: true, unique: true },\n githubUrl: { type: String },\n tags: { type: [String], default: [] },\n upvoters: { type: [String], default: [] },\n downvoters: { type: [String], default: [] },\n isOpenSource: { type: Boolean, default: false },\n createdAt: { type: Date, default: Date.now },\n intlayerVersion: { type: String },\n libsUsed: { type: [String], default: [] },\n packageDetails: { type: Map, of: String, default: {} },\n lastScanDate: { type: Date },\n scanDetails: { type: scanDetailsSchema },\n owner: { type: String },\n status: {\n type: String,\n enum: ['pending_scan', 'active', 'scan_failed'],\n default: 'pending_scan',\n },\n },\n {\n timestamps: false,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\nexport const ShowcaseProjectModel = model<\n ShowcaseProjectDocument,\n ShowcaseProjectModelType\n>('ShowcaseProject', showcaseProjectSchema);\n"],"mappings":";;;AAMA,MAAM,oBAAoB,IAAI,OAC5B;CACE,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"showcaseProject.schema.mjs","names":[],"sources":["../../../src/schemas/showcaseProject.schema.ts"],"sourcesContent":["import { model, Schema } from 'mongoose';\nimport type {\n ShowcaseProjectDocument,\n ShowcaseProjectModelType,\n} from '@/types/showcaseProject.types';\n\nconst scanDetailsSchema = new Schema(\n {\n score: { type: Number },\n langTag: { type: String },\n htmlDir: { type: String },\n hreflangs: { type: [String] },\n hasXDefault: { type: Boolean },\n hasCanonical: { type: Boolean },\n hasLocalizedLinks: { type: Boolean },\n allAnchorsLocalized: { type: Boolean },\n robotsTxt: {\n accessible: { type: Boolean },\n disallowWithoutLocaleAlternates: { type: Boolean },\n },\n sitemapXml: {\n urlsDiscoveredCount: { type: Number },\n alternatesPresent: { type: Boolean },\n xDefaultPresent: { type: Boolean },\n },\n },\n { _id: false }\n);\n\nexport const showcaseProjectSchema = new Schema<ShowcaseProjectDocument>(\n {\n title: { type: String, required: true },\n description: { type: String, default: '' },\n imageUrl: { type: String, default: '' },\n logoUrl: { type: String },\n websiteUrl: { type: String, required: true, unique: true },\n githubUrl: { type: String },\n tags: { type: [String], default: [] },\n upvoters: { type: [String], default: [] },\n downvoters: { type: [String], default: [] },\n isOpenSource: { type: Boolean, default: false },\n createdAt: { type: Date, default: Date.now },\n intlayerVersion: { type: String },\n libsUsed: { type: [String], default: [] },\n packageDetails: { type: Map, of: String, default: {} },\n lastScanDate: { type: Date },\n scanDetails: { type: scanDetailsSchema },\n owner: { type: String },\n status: {\n type: String,\n enum: ['pending_scan', 'active', 'scan_failed'],\n default: 'pending_scan',\n },\n },\n {\n timestamps: false,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\nexport const ShowcaseProjectModel = model<\n ShowcaseProjectDocument,\n ShowcaseProjectModelType\n>('ShowcaseProject', showcaseProjectSchema);\n"],"mappings":";;;AAMA,MAAM,oBAAoB,IAAI,OAC5B;CACE,OAAO,EAAE,MAAM,QAAQ;CACvB,SAAS,EAAE,MAAM,QAAQ;CACzB,SAAS,EAAE,MAAM,QAAQ;CACzB,WAAW,EAAE,MAAM,CAAC,OAAO,EAAE;CAC7B,aAAa,EAAE,MAAM,SAAS;CAC9B,cAAc,EAAE,MAAM,SAAS;CAC/B,mBAAmB,EAAE,MAAM,SAAS;CACpC,qBAAqB,EAAE,MAAM,SAAS;CACtC,WAAW;EACT,YAAY,EAAE,MAAM,SAAS;EAC7B,iCAAiC,EAAE,MAAM,SAAS;EACnD;CACD,YAAY;EACV,qBAAqB,EAAE,MAAM,QAAQ;EACrC,mBAAmB,EAAE,MAAM,SAAS;EACpC,iBAAiB,EAAE,MAAM,SAAS;EACnC;CACF,EACD,EAAE,KAAK,OAAO,CACf;AAED,MAAa,wBAAwB,IAAI,OACvC;CACE,OAAO;EAAE,MAAM;EAAQ,UAAU;EAAM;CACvC,aAAa;EAAE,MAAM;EAAQ,SAAS;EAAI;CAC1C,UAAU;EAAE,MAAM;EAAQ,SAAS;EAAI;CACvC,SAAS,EAAE,MAAM,QAAQ;CACzB,YAAY;EAAE,MAAM;EAAQ,UAAU;EAAM,QAAQ;EAAM;CAC1D,WAAW,EAAE,MAAM,QAAQ;CAC3B,MAAM;EAAE,MAAM,CAAC,OAAO;EAAE,SAAS,EAAE;EAAE;CACrC,UAAU;EAAE,MAAM,CAAC,OAAO;EAAE,SAAS,EAAE;EAAE;CACzC,YAAY;EAAE,MAAM,CAAC,OAAO;EAAE,SAAS,EAAE;EAAE;CAC3C,cAAc;EAAE,MAAM;EAAS,SAAS;EAAO;CAC/C,WAAW;EAAE,MAAM;EAAM,SAAS,KAAK;EAAK;CAC5C,iBAAiB,EAAE,MAAM,QAAQ;CACjC,UAAU;EAAE,MAAM,CAAC,OAAO;EAAE,SAAS,EAAE;EAAE;CACzC,gBAAgB;EAAE,MAAM;EAAK,IAAI;EAAQ,SAAS,EAAE;EAAE;CACtD,cAAc,EAAE,MAAM,MAAM;CAC5B,aAAa,EAAE,MAAM,mBAAmB;CACxC,OAAO,EAAE,MAAM,QAAQ;CACvB,QAAQ;EACN,MAAM;EACN,MAAM;GAAC;GAAgB;GAAU;GAAc;EAC/C,SAAS;EACV;CACF,EACD;CACE,YAAY;CAEZ,QAAQ;EACN,UAAU;EACV,YAAY;EACZ,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI,IAAI,UAAU;IACnB;;EAEJ;CACD,UAAU;EACR,UAAU;EACV,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI;IACL;;EAEJ;CACF,CACF;AAED,MAAa,uBAAuB,MAGlC,mBAAmB,sBAAsB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tag.schema.mjs","names":[],"sources":["../../../src/schemas/tag.schema.ts"],"sourcesContent":["import {\n KEY_MAX_LENGTH,\n KEY_MIN_LENGTH,\n NAME_MAX_LENGTH,\n NAME_MIN_LENGTH,\n} from '@utils/validation/validateTag';\nimport { model, Schema } from 'mongoose';\nimport type { TagModelType, TagSchema } from '@/types/tag.types';\n\nexport const tagSchema = new Schema<TagSchema>(\n {\n organizationId: {\n type: Schema.Types.ObjectId,\n ref: 'Organization',\n required: true,\n },\n projectId: {\n type: Schema.Types.ObjectId,\n ref: 'Project',\n required: true,\n },\n key: {\n type: String,\n required: true,\n minlength: KEY_MIN_LENGTH,\n maxlength: KEY_MAX_LENGTH,\n },\n name: {\n type: String,\n minlength: NAME_MIN_LENGTH,\n maxlength: NAME_MAX_LENGTH,\n },\n description: {\n type: String,\n },\n instructions: {\n type: String,\n },\n creatorId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\nexport const TagModel = model<TagSchema, TagModelType>('tag', tagSchema);\n"],"mappings":";;;;AASA,MAAa,YAAY,IAAI,OAC3B;CACE,gBAAgB;EACd,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;
|
|
1
|
+
{"version":3,"file":"tag.schema.mjs","names":[],"sources":["../../../src/schemas/tag.schema.ts"],"sourcesContent":["import {\n KEY_MAX_LENGTH,\n KEY_MIN_LENGTH,\n NAME_MAX_LENGTH,\n NAME_MIN_LENGTH,\n} from '@utils/validation/validateTag';\nimport { model, Schema } from 'mongoose';\nimport type { TagModelType, TagSchema } from '@/types/tag.types';\n\nexport const tagSchema = new Schema<TagSchema>(\n {\n organizationId: {\n type: Schema.Types.ObjectId,\n ref: 'Organization',\n required: true,\n },\n projectId: {\n type: Schema.Types.ObjectId,\n ref: 'Project',\n required: true,\n },\n key: {\n type: String,\n required: true,\n minlength: KEY_MIN_LENGTH,\n maxlength: KEY_MAX_LENGTH,\n },\n name: {\n type: String,\n minlength: NAME_MIN_LENGTH,\n maxlength: NAME_MAX_LENGTH,\n },\n description: {\n type: String,\n },\n instructions: {\n type: String,\n },\n creatorId: {\n type: Schema.Types.ObjectId,\n ref: 'User',\n required: true,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\nexport const TagModel = model<TagSchema, TagModelType>('tag', tagSchema);\n"],"mappings":";;;;AASA,MAAa,YAAY,IAAI,OAC3B;CACE,gBAAgB;EACd,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;EACX;CACD,WAAW;EACT,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;EACX;CACD,KAAK;EACH,MAAM;EACN,UAAU;EACV;EACA;EACD;CACD,MAAM;EACJ,MAAM;EACN;EACA;EACD;CACD,aAAa,EACX,MAAM,QACP;CACD,cAAc,EACZ,MAAM,QACP;CACD,WAAW;EACT,MAAM,OAAO,MAAM;EACnB,KAAK;EACL,UAAU;EACX;CACF,EACD;CACE,YAAY;CAEZ,QAAQ;EACN,UAAU;EACV,YAAY;EACZ,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI,IAAI,UAAU;IACnB;;EAEJ;CACD,UAAU;EACR,UAAU;EACV,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI;IACL;;EAEJ;CACF,CACF;AAED,MAAa,WAAW,MAA+B,OAAO,UAAU"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.schema.mjs","names":[],"sources":["../../../src/schemas/user.schema.ts"],"sourcesContent":["import {\n NAMES_MAX_LENGTH,\n NAMES_MIN_LENGTH,\n} from '@utils/validation/validateUser';\nimport { model, Schema } from 'mongoose';\nimport validator from 'validator';\nimport type { UserModelType, UserSchema } from '@/types/user.types';\n\nexport const userSchema = new Schema<UserSchema>(\n {\n email: {\n type: String,\n required: true,\n unique: true,\n validate: [validator.isEmail, 'Please fill a valid email address'],\n lowercase: true,\n trim: true,\n },\n name: {\n type: String,\n maxlength: NAMES_MAX_LENGTH,\n minlength: NAMES_MIN_LENGTH,\n },\n image: {\n type: String,\n required: false,\n },\n phone: {\n type: String,\n maxlength: 20,\n },\n\n customerId: {\n type: String,\n required: false,\n },\n\n emailsList: {\n type: {\n newsLetter: {\n type: Boolean,\n default: false,\n },\n },\n required: false,\n },\n emailVerified: {\n type: Boolean,\n default: false,\n required: false,\n },\n role: {\n type: String,\n enum: ['admin', 'user'],\n default: 'user',\n required: false,\n },\n lastLoginMethod: {\n type: String,\n enum: ['email', 'google', 'github', 'passkey'],\n required: false,\n },\n lang: {\n type: String,\n required: false,\n },\n dateOfBirth: {\n type: Date,\n required: false,\n },\n lastActiveOrganizationId: {\n type: String,\n required: false,\n },\n lastActiveProjectId: {\n type: String,\n required: false,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\nexport const UserModel = model<UserSchema, UserModelType>('user', userSchema);\n"],"mappings":";;;;;AAQA,MAAa,aAAa,IAAI,OAC5B;CACE,OAAO;EACL,MAAM;EACN,UAAU;EACV,QAAQ;EACR,UAAU,CAAC,UAAU,SAAS,
|
|
1
|
+
{"version":3,"file":"user.schema.mjs","names":[],"sources":["../../../src/schemas/user.schema.ts"],"sourcesContent":["import {\n NAMES_MAX_LENGTH,\n NAMES_MIN_LENGTH,\n} from '@utils/validation/validateUser';\nimport { model, Schema } from 'mongoose';\nimport validator from 'validator';\nimport type { UserModelType, UserSchema } from '@/types/user.types';\n\nexport const userSchema = new Schema<UserSchema>(\n {\n email: {\n type: String,\n required: true,\n unique: true,\n validate: [validator.isEmail, 'Please fill a valid email address'],\n lowercase: true,\n trim: true,\n },\n name: {\n type: String,\n maxlength: NAMES_MAX_LENGTH,\n minlength: NAMES_MIN_LENGTH,\n },\n image: {\n type: String,\n required: false,\n },\n phone: {\n type: String,\n maxlength: 20,\n },\n\n customerId: {\n type: String,\n required: false,\n },\n\n emailsList: {\n type: {\n newsLetter: {\n type: Boolean,\n default: false,\n },\n },\n required: false,\n },\n emailVerified: {\n type: Boolean,\n default: false,\n required: false,\n },\n role: {\n type: String,\n enum: ['admin', 'user'],\n default: 'user',\n required: false,\n },\n lastLoginMethod: {\n type: String,\n enum: ['email', 'google', 'github', 'passkey'],\n required: false,\n },\n lang: {\n type: String,\n required: false,\n },\n dateOfBirth: {\n type: Date,\n required: false,\n },\n lastActiveOrganizationId: {\n type: String,\n required: false,\n },\n lastActiveProjectId: {\n type: String,\n required: false,\n },\n },\n {\n timestamps: true,\n\n toJSON: {\n virtuals: true, // keep the automatic `id` getter\n versionKey: false, // drop __v\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id.toString(),\n };\n },\n },\n toObject: {\n virtuals: true,\n transform(_doc, ret: any) {\n const { _id, ...rest } = ret;\n return {\n ...rest,\n id: _id,\n };\n },\n },\n }\n);\n\nexport const UserModel = model<UserSchema, UserModelType>('user', userSchema);\n"],"mappings":";;;;;AAQA,MAAa,aAAa,IAAI,OAC5B;CACE,OAAO;EACL,MAAM;EACN,UAAU;EACV,QAAQ;EACR,UAAU,CAAC,UAAU,SAAS,oCAAoC;EAClE,WAAW;EACX,MAAM;EACP;CACD,MAAM;EACJ,MAAM;EACN;EACA;EACD;CACD,OAAO;EACL,MAAM;EACN,UAAU;EACX;CACD,OAAO;EACL,MAAM;EACN,WAAW;EACZ;CAED,YAAY;EACV,MAAM;EACN,UAAU;EACX;CAED,YAAY;EACV,MAAM,EACJ,YAAY;GACV,MAAM;GACN,SAAS;GACV,EACF;EACD,UAAU;EACX;CACD,eAAe;EACb,MAAM;EACN,SAAS;EACT,UAAU;EACX;CACD,MAAM;EACJ,MAAM;EACN,MAAM,CAAC,SAAS,OAAO;EACvB,SAAS;EACT,UAAU;EACX;CACD,iBAAiB;EACf,MAAM;EACN,MAAM;GAAC;GAAS;GAAU;GAAU;GAAU;EAC9C,UAAU;EACX;CACD,MAAM;EACJ,MAAM;EACN,UAAU;EACX;CACD,aAAa;EACX,MAAM;EACN,UAAU;EACX;CACD,0BAA0B;EACxB,MAAM;EACN,UAAU;EACX;CACD,qBAAqB;EACnB,MAAM;EACN,UAAU;EACX;CACF,EACD;CACE,YAAY;CAEZ,QAAQ;EACN,UAAU;EACV,YAAY;EACZ,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI,IAAI,UAAU;IACnB;;EAEJ;CACD,UAAU;EACR,UAAU;EACV,UAAU,MAAM,KAAU;GACxB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,UAAO;IACL,GAAG;IACH,IAAI;IACL;;EAEJ;CACF,CACF;AAED,MAAa,YAAY,MAAiC,QAAQ,WAAW"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"affiliate.service.mjs","names":[],"sources":["../../../src/services/affiliate.service.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport {\n AffiliateModel,\n AffiliateReferralModel,\n} from '@schemas/affiliate.schema';\nimport { AffiliateInvitationModel } from '@schemas/affiliateInvitation.schema';\nimport { GenericError } from '@utils/errors';\nimport Stripe from 'stripe';\nimport type {\n Affiliate,\n AffiliateDocument,\n AffiliateReferralDocument,\n AffiliateStats,\n CommissionType,\n} from '@/types/affiliate.types';\nimport type { AffiliateInvitationDocument } from '@/types/affiliateInvitation.types';\nimport type { Organization } from '@/types/organization.types';\nimport type { User } from '@/types/user.types';\n\nconst generateReferralCode = (): string =>\n Math.random().toString(36).substring(2, 8).toUpperCase();\n\nconst ensureUniqueCode = async (): Promise<string> => {\n let code = generateReferralCode();\n let attempts = 0;\n while (await AffiliateModel.exists({ referralCode: code })) {\n code = generateReferralCode();\n if (++attempts > 10)\n throw new GenericError('AFFILIATE_CODE_GENERATION_FAILED');\n }\n return code;\n};\n\nexport const createAffiliate = async (\n userId: User['id'],\n options: {\n commissionRate?: number;\n commissionType?: CommissionType;\n country?: string;\n stripeAccountType?: 'express' | 'standard';\n email?: string;\n } = {}\n): Promise<AffiliateDocument> => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n const accountType = options.stripeAccountType ?? 'express';\n\n const account =\n accountType === 'standard'\n ? await stripe.accounts.create({\n type: 'standard',\n ...(options.email ? { email: options.email } : {}),\n })\n : await stripe.accounts.create({\n controller: {\n stripe_dashboard: { type: 'none' },\n fees: { payer: 'application' },\n losses: { payments: 'stripe' },\n requirement_collection: 'stripe',\n },\n country: options.country ?? 'US',\n business_type: 'individual',\n business_profile: {\n product_description: 'Intlayer Affiliate Program',\n },\n capabilities: {\n card_payments: { requested: true },\n transfers: { requested: true },\n },\n settings: {\n payouts: { schedule: { interval: 'monthly', monthly_anchor: 1 } },\n },\n });\n\n const referralCode = await ensureUniqueCode();\n\n const affiliate = await AffiliateModel.create({\n userId,\n stripeAccountId: account.id,\n stripeAccountType: accountType,\n referralCode,\n status: 'onboarding',\n commissionRate: options.commissionRate ?? 20,\n commissionType: options.commissionType ?? 'one_time',\n });\n\n return affiliate;\n};\n\nexport const getAffiliateByUserId = async (\n userId: User['id'] | string\n): Promise<AffiliateDocument | null> =>\n AffiliateModel.findOne({ userId: String(userId) });\n\nexport const getAffiliateById = async (\n affiliateId: Affiliate['id'] | string\n): Promise<AffiliateDocument | null> =>\n AffiliateModel.findById(String(affiliateId));\n\nexport const getAffiliateByCode = async (\n referralCode: string\n): Promise<AffiliateDocument | null> =>\n AffiliateModel.findOne({ referralCode: referralCode.toUpperCase() });\n\nexport const findAffiliates = async (\n query: Record<string, unknown> = {},\n skip = 0,\n limit = 20\n): Promise<AffiliateDocument[]> =>\n AffiliateModel.find(query).sort({ createdAt: -1 }).skip(skip).limit(limit);\n\nexport const countAffiliates = async (\n query: Record<string, unknown> = {}\n): Promise<number> => AffiliateModel.countDocuments(query);\n\nexport const createAccountSession = async (\n stripeAccountId: string\n): Promise<string> => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n\n const accountSession = await stripe.accountSessions.create({\n account: stripeAccountId,\n components: {\n account_onboarding: { enabled: true },\n },\n });\n\n return accountSession.client_secret;\n};\n\nexport const createOnboardingLink = async (\n stripeAccountId: string,\n returnUrl: string,\n refreshUrl: string\n): Promise<string> => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n\n const accountLink = await stripe.accountLinks.create({\n account: stripeAccountId,\n return_url: returnUrl,\n refresh_url: refreshUrl,\n type: 'account_onboarding',\n });\n\n await AffiliateModel.findOneAndUpdate(\n { stripeAccountId },\n { stripeOnboardingInitiated: true }\n );\n\n return accountLink.url;\n};\n\nexport const markAffiliateActive = async (\n stripeAccountId: string,\n capabilities: { chargesEnabled: boolean; payoutsEnabled: boolean }\n): Promise<AffiliateDocument | null> =>\n AffiliateModel.findOneAndUpdate(\n { stripeAccountId, status: { $ne: 'active' } },\n {\n status: 'active',\n chargesEnabled: capabilities.chargesEnabled,\n payoutsEnabled: capabilities.payoutsEnabled,\n activatedAt: new Date(),\n },\n { new: true }\n );\n\nexport const payAffiliateCommission = async (\n referral: AffiliateReferralDocument\n): Promise<void> => {\n const affiliate = await getAffiliateById(String(referral.affiliateId));\n if (!affiliate?.stripeAccountId) return;\n\n const fullAmount = referral.commissionAmount ?? 0;\n if (fullAmount <= 0) return;\n\n const commissionAmount = Math.round(\n fullAmount * (affiliate.commissionRate / 100)\n );\n if (commissionAmount <= 0) return;\n\n const currency = (referral.commissionCurrency ?? 'usd').toLowerCase();\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n\n try {\n const transfer = await stripe.transfers.create({\n amount: commissionAmount,\n currency,\n destination: affiliate.stripeAccountId,\n metadata: {\n affiliateId: String(affiliate.id),\n referralId: String((referral as any)._id ?? referral.id),\n },\n });\n\n await AffiliateReferralModel.findByIdAndUpdate(\n (referral as any)._id ?? referral.id,\n { payoutStatus: 'paid', payoutId: transfer.id }\n );\n } catch (err) {\n // Mark payout as failed so it can be retried manually; do not throw\n // so the webhook returns 200 and Stripe does not keep retrying.\n await AffiliateReferralModel.findByIdAndUpdate(\n (referral as any)._id ?? referral.id,\n { payoutStatus: 'failed' }\n );\n }\n};\n\nexport const setAffiliateStatus = async (\n affiliateId: string,\n update: { status?: 'active' | 'suspended' }\n): Promise<AffiliateDocument | null> =>\n AffiliateModel.findByIdAndUpdate(affiliateId, update, { new: true });\n\nexport const trackReferral = async (\n referralCode: string,\n organizationId: Organization['id'] | string,\n subscriptionId?: string,\n commissionAmount?: number,\n commissionCurrency?: string\n): Promise<AffiliateReferralDocument | null> => {\n const affiliate = await getAffiliateByCode(referralCode);\n if (!affiliate) return null;\n\n const existing = await AffiliateReferralModel.findOne({\n affiliateId: affiliate.id,\n referredOrganizationId: String(organizationId),\n });\n\n if (existing) {\n // Keep the subscriptionId in sync with the latest attempt so the webhook\n // can match the referral when invoice.payment_succeeded fires.\n if (\n subscriptionId &&\n existing.subscriptionId !== subscriptionId &&\n existing.conversionStatus === 'pending'\n ) {\n existing.subscriptionId = subscriptionId;\n await existing.save();\n }\n return existing;\n }\n\n return AffiliateReferralModel.create({\n affiliateId: affiliate.id,\n referredOrganizationId: String(organizationId),\n subscriptionId,\n commissionAmount,\n commissionCurrency,\n conversionStatus: 'pending',\n payoutStatus: 'pending',\n });\n};\n\nexport const convertReferral = async (\n subscriptionId: string,\n commissionAmount?: number,\n commissionCurrency?: string,\n organizationId?: string\n): Promise<AffiliateReferralDocument | null> => {\n // Primary lookup: match by the exact subscription ID stored at tracking time.\n const bySubscription = await AffiliateReferralModel.findOneAndUpdate(\n { subscriptionId, conversionStatus: 'pending' },\n { conversionStatus: 'converted', commissionAmount, commissionCurrency },\n { returnDocument: 'after' }\n );\n if (bySubscription) return bySubscription;\n\n // Fallback: the referral was created during a previous payment attempt and still\n // holds an old subscriptionId. Match by organization and update to the current one.\n if (!organizationId) return null;\n return AffiliateReferralModel.findOneAndUpdate(\n { referredOrganizationId: organizationId, conversionStatus: 'pending' },\n {\n conversionStatus: 'converted',\n subscriptionId,\n commissionAmount,\n commissionCurrency,\n },\n { returnDocument: 'after' }\n );\n};\n\nexport const getAffiliateStats = async (\n userId: User['id'] | string\n): Promise<AffiliateStats | null> => {\n const affiliate = await getAffiliateByUserId(userId);\n if (!affiliate) return null;\n\n const referrals = await AffiliateReferralModel.find({\n affiliateId: affiliate.id,\n });\n\n const converted = referrals.filter(\n (referral) => referral.conversionStatus === 'converted'\n );\n const pending = referrals.filter(\n (referral) => referral.conversionStatus === 'pending'\n );\n const totalEarned = converted.reduce(\n (sum, referral) => sum + (referral.commissionAmount ?? 0),\n 0\n );\n const pendingAmount = pending.reduce(\n (sum, referral) => sum + (referral.commissionAmount ?? 0),\n 0\n );\n\n const appUrl = process.env.APP_URL;\n const referralLink = `${appUrl}/pricing?ref=${affiliate.referralCode}`;\n\n return {\n affiliate: affiliate.toJSON() as any,\n totalReferrals: referrals.length,\n convertedReferrals: converted.length,\n pendingReferrals: pending.length,\n totalCommissionEarned: totalEarned,\n pendingCommission: pendingAmount,\n referralLink,\n };\n};\n\n// ─── Invitation flow ──────────────────────────────────────────────────────────\n\nconst INVITATION_TTL_DAYS = 7;\n\nexport const createAffiliateInvitation = async (\n email: string,\n invitedBy: User['id'],\n options: {\n commissionRate?: number;\n commissionType?: CommissionType;\n country?: string;\n } = {}\n): Promise<AffiliateInvitationDocument> => {\n const token = randomUUID();\n const expiresAt = new Date();\n expiresAt.setDate(expiresAt.getDate() + INVITATION_TTL_DAYS);\n\n // Replace any existing pending invitation for this email\n await AffiliateInvitationModel.deleteMany({ email, status: 'pending' });\n\n return AffiliateInvitationModel.create({\n email,\n token,\n status: 'pending',\n invitedBy,\n commissionRate: options.commissionRate ?? 20,\n commissionType: options.commissionType ?? 'one_time',\n country: options.country,\n expiresAt,\n });\n};\n\nexport const findAffiliateInvitations = async (\n query: Record<string, unknown> = {},\n skip = 0,\n limit = 20\n): Promise<AffiliateInvitationDocument[]> =>\n AffiliateInvitationModel.find(query)\n .sort({ createdAt: -1 })\n .skip(skip)\n .limit(limit);\n\nexport const countAffiliateInvitations = async (\n query: Record<string, unknown> = {}\n): Promise<number> => AffiliateInvitationModel.countDocuments(query);\n\nexport const getAffiliateInvitationByToken = async (\n token: string\n): Promise<AffiliateInvitationDocument | null> => {\n const invitation = await AffiliateInvitationModel.findOne({ token });\n if (!invitation) return null;\n\n if (invitation.status === 'pending' && invitation.expiresAt < new Date()) {\n invitation.status = 'expired';\n await invitation.save();\n }\n\n return invitation;\n};\n\nexport const acceptAffiliateInvitation = async (\n token: string,\n userId: User['id'],\n options: {\n country?: string;\n stripeAccountType?: 'express' | 'standard';\n email?: string;\n } = {}\n): Promise<AffiliateDocument> => {\n const invitation = await getAffiliateInvitationByToken(token);\n\n if (!invitation) throw new GenericError('AFFILIATE_INVITATION_NOT_FOUND');\n if (invitation.status !== 'pending')\n throw new GenericError('AFFILIATE_INVITATION_ALREADY_USED');\n\n const affiliate = await createAffiliate(userId, {\n commissionRate: invitation.commissionRate,\n commissionType: invitation.commissionType,\n country: options.country ?? invitation.country,\n stripeAccountType: options.stripeAccountType ?? 'express',\n email: options.email,\n });\n\n invitation.status = 'accepted';\n await invitation.save();\n\n return affiliate;\n};\n"],"mappings":";;;;;;;AAmBA,MAAM,6BACJ,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,YAAY;AAEzD,MAAM,mBAAmB,YAA6B;CACpD,IAAI,OAAO,qBAAqB;CAChC,IAAI,WAAW;CACf,OAAO,MAAM,eAAe,OAAO,EAAE,cAAc,KAAK,CAAC,GAAG;EAC1D,OAAO,qBAAqB;EAC5B,IAAI,EAAE,WAAW,IACf,MAAM,IAAI,aAAa,kCAAkC;CAC7D;CACA,OAAO;AACT;AAEA,MAAa,kBAAkB,OAC7B,QACA,UAMI,CAAC,MAC0B;CAC/B,MAAM,SAAS,IAAI,OAAO,QAAQ,IAAI,iBAAkB;CACxD,MAAM,cAAc,QAAQ,qBAAqB;CAEjD,MAAM,UACJ,gBAAgB,aACZ,MAAM,OAAO,SAAS,OAAO;EAC3B,MAAM;EACN,GAAI,QAAQ,QAAQ,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;CAClD,CAAC,IACD,MAAM,OAAO,SAAS,OAAO;EAC3B,YAAY;GACV,kBAAkB,EAAE,MAAM,OAAO;GACjC,MAAM,EAAE,OAAO,cAAc;GAC7B,QAAQ,EAAE,UAAU,SAAS;GAC7B,wBAAwB;EAC1B;EACA,SAAS,QAAQ,WAAW;EAC5B,eAAe;EACf,kBAAkB,EAChB,qBAAqB,6BACvB;EACA,cAAc;GACZ,eAAe,EAAE,WAAW,KAAK;GACjC,WAAW,EAAE,WAAW,KAAK;EAC/B;EACA,UAAU,EACR,SAAS,EAAE,UAAU;GAAE,UAAU;GAAW,gBAAgB;EAAE,EAAE,EAClE;CACF,CAAC;CAEP,MAAM,eAAe,MAAM,iBAAiB;CAY5C,OAAO,MAViB,eAAe,OAAO;EAC5C;EACA,iBAAiB,QAAQ;EACzB,mBAAmB;EACnB;EACA,QAAQ;EACR,gBAAgB,QAAQ,kBAAkB;EAC1C,gBAAgB,QAAQ,kBAAkB;CAC5C,CAAC;AAGH;AAEA,MAAa,uBAAuB,OAClC,WAEA,eAAe,QAAQ,EAAE,QAAQ,OAAO,MAAM,EAAE,CAAC;AAEnD,MAAa,mBAAmB,OAC9B,gBAEA,eAAe,SAAS,OAAO,WAAW,CAAC;AAE7C,MAAa,qBAAqB,OAChC,iBAEA,eAAe,QAAQ,EAAE,cAAc,aAAa,YAAY,EAAE,CAAC;AAErE,MAAa,iBAAiB,OAC5B,QAAiC,CAAC,GAClC,OAAO,GACP,QAAQ,OAER,eAAe,KAAK,KAAK,CAAC,CAAC,KAAK,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,KAAK;AAE3E,MAAa,kBAAkB,OAC7B,QAAiC,CAAC,MACd,eAAe,eAAe,KAAK;AAEzD,MAAa,uBAAuB,OAClC,oBACoB;CAUpB,QAAO,MAPsB,IAFV,OAAO,QAAQ,IAAI,iBAEJ,CAAC,CAAC,gBAAgB,OAAO;EACzD,SAAS;EACT,YAAY,EACV,oBAAoB,EAAE,SAAS,KAAK,EACtC;CACF,CAAC,EAEoB,CAAC;AACxB;AAEA,MAAa,uBAAuB,OAClC,iBACA,WACA,eACoB;CAGpB,MAAM,cAAc,MAAM,IAFP,OAAO,QAAQ,IAAI,iBAEP,CAAC,CAAC,aAAa,OAAO;EACnD,SAAS;EACT,YAAY;EACZ,aAAa;EACb,MAAM;CACR,CAAC;CAED,MAAM,eAAe,iBACnB,EAAE,gBAAgB,GAClB,EAAE,2BAA2B,KAAK,CACpC;CAEA,OAAO,YAAY;AACrB;AAEA,MAAa,sBAAsB,OACjC,iBACA,iBAEA,eAAe,iBACb;CAAE;CAAiB,QAAQ,EAAE,KAAK,SAAS;AAAE,GAC7C;CACE,QAAQ;CACR,gBAAgB,aAAa;CAC7B,gBAAgB,aAAa;CAC7B,6BAAa,IAAI,KAAK;AACxB,GACA,EAAE,KAAK,KAAK,CACd;AAEF,MAAa,yBAAyB,OACpC,aACkB;CAClB,MAAM,YAAY,MAAM,iBAAiB,OAAO,SAAS,WAAW,CAAC;CACrE,IAAI,CAAC,WAAW,iBAAiB;CAEjC,MAAM,aAAa,SAAS,oBAAoB;CAChD,IAAI,cAAc,GAAG;CAErB,MAAM,mBAAmB,KAAK,MAC5B,cAAc,UAAU,iBAAiB,IAC3C;CACA,IAAI,oBAAoB,GAAG;CAE3B,MAAM,YAAY,SAAS,sBAAsB,MAAK,CAAE,YAAY;CACpE,MAAM,SAAS,IAAI,OAAO,QAAQ,IAAI,iBAAkB;CAExD,IAAI;EACF,MAAM,WAAW,MAAM,OAAO,UAAU,OAAO;GAC7C,QAAQ;GACR;GACA,aAAa,UAAU;GACvB,UAAU;IACR,aAAa,OAAO,UAAU,EAAE;IAChC,YAAY,OAAQ,SAAiB,OAAO,SAAS,EAAE;GACzD;EACF,CAAC;EAED,MAAM,uBAAuB,kBAC1B,SAAiB,OAAO,SAAS,IAClC;GAAE,cAAc;GAAQ,UAAU,SAAS;EAAG,CAChD;CACF,SAAS,KAAK;EAGZ,MAAM,uBAAuB,kBAC1B,SAAiB,OAAO,SAAS,IAClC,EAAE,cAAc,SAAS,CAC3B;CACF;AACF;AAEA,MAAa,qBAAqB,OAChC,aACA,WAEA,eAAe,kBAAkB,aAAa,QAAQ,EAAE,KAAK,KAAK,CAAC;AAErE,MAAa,gBAAgB,OAC3B,cACA,gBACA,gBACA,kBACA,uBAC8C;CAC9C,MAAM,YAAY,MAAM,mBAAmB,YAAY;CACvD,IAAI,CAAC,WAAW,OAAO;CAEvB,MAAM,WAAW,MAAM,uBAAuB,QAAQ;EACpD,aAAa,UAAU;EACvB,wBAAwB,OAAO,cAAc;CAC/C,CAAC;CAED,IAAI,UAAU;EAGZ,IACE,kBACA,SAAS,mBAAmB,kBAC5B,SAAS,qBAAqB,WAC9B;GACA,SAAS,iBAAiB;GAC1B,MAAM,SAAS,KAAK;EACtB;EACA,OAAO;CACT;CAEA,OAAO,uBAAuB,OAAO;EACnC,aAAa,UAAU;EACvB,wBAAwB,OAAO,cAAc;EAC7C;EACA;EACA;EACA,kBAAkB;EAClB,cAAc;CAChB,CAAC;AACH;AAEA,MAAa,kBAAkB,OAC7B,gBACA,kBACA,oBACA,mBAC8C;CAE9C,MAAM,iBAAiB,MAAM,uBAAuB,iBAClD;EAAE;EAAgB,kBAAkB;CAAU,GAC9C;EAAE,kBAAkB;EAAa;EAAkB;CAAmB,GACtE,EAAE,gBAAgB,QAAQ,CAC5B;CACA,IAAI,gBAAgB,OAAO;CAI3B,IAAI,CAAC,gBAAgB,OAAO;CAC5B,OAAO,uBAAuB,iBAC5B;EAAE,wBAAwB;EAAgB,kBAAkB;CAAU,GACtE;EACE,kBAAkB;EAClB;EACA;EACA;CACF,GACA,EAAE,gBAAgB,QAAQ,CAC5B;AACF;AAEA,MAAa,oBAAoB,OAC/B,WACmC;CACnC,MAAM,YAAY,MAAM,qBAAqB,MAAM;CACnD,IAAI,CAAC,WAAW,OAAO;CAEvB,MAAM,YAAY,MAAM,uBAAuB,KAAK,EAClD,aAAa,UAAU,GACzB,CAAC;CAED,MAAM,YAAY,UAAU,QACzB,aAAa,SAAS,qBAAqB,WAC9C;CACA,MAAM,UAAU,UAAU,QACvB,aAAa,SAAS,qBAAqB,SAC9C;CACA,MAAM,cAAc,UAAU,QAC3B,KAAK,aAAa,OAAO,SAAS,oBAAoB,IACvD,CACF;CACA,MAAM,gBAAgB,QAAQ,QAC3B,KAAK,aAAa,OAAO,SAAS,oBAAoB,IACvD,CACF;CAGA,MAAM,eAAe,GADN,QAAQ,IAAI,QACI,eAAe,UAAU;CAExD,OAAO;EACL,WAAW,UAAU,OAAO;EAC5B,gBAAgB,UAAU;EAC1B,oBAAoB,UAAU;EAC9B,kBAAkB,QAAQ;EAC1B,uBAAuB;EACvB,mBAAmB;EACnB;CACF;AACF;AAIA,MAAM,sBAAsB;AAE5B,MAAa,4BAA4B,OACvC,OACA,WACA,UAII,CAAC,MACoC;CACzC,MAAM,QAAQ,WAAW;CACzB,MAAM,4BAAY,IAAI,KAAK;CAC3B,UAAU,QAAQ,UAAU,QAAQ,IAAI,mBAAmB;CAG3D,MAAM,yBAAyB,WAAW;EAAE;EAAO,QAAQ;CAAU,CAAC;CAEtE,OAAO,yBAAyB,OAAO;EACrC;EACA;EACA,QAAQ;EACR;EACA,gBAAgB,QAAQ,kBAAkB;EAC1C,gBAAgB,QAAQ,kBAAkB;EAC1C,SAAS,QAAQ;EACjB;CACF,CAAC;AACH;AAEA,MAAa,2BAA2B,OACtC,QAAiC,CAAC,GAClC,OAAO,GACP,QAAQ,OAER,yBAAyB,KAAK,KAAK,CAAC,CACjC,KAAK,EAAE,WAAW,GAAG,CAAC,CAAC,CACvB,KAAK,IAAI,CAAC,CACV,MAAM,KAAK;AAEhB,MAAa,4BAA4B,OACvC,QAAiC,CAAC,MACd,yBAAyB,eAAe,KAAK;AAEnE,MAAa,gCAAgC,OAC3C,UACgD;CAChD,MAAM,aAAa,MAAM,yBAAyB,QAAQ,EAAE,MAAM,CAAC;CACnE,IAAI,CAAC,YAAY,OAAO;CAExB,IAAI,WAAW,WAAW,aAAa,WAAW,4BAAY,IAAI,KAAK,GAAG;EACxE,WAAW,SAAS;EACpB,MAAM,WAAW,KAAK;CACxB;CAEA,OAAO;AACT;AAEA,MAAa,4BAA4B,OACvC,OACA,QACA,UAII,CAAC,MAC0B;CAC/B,MAAM,aAAa,MAAM,8BAA8B,KAAK;CAE5D,IAAI,CAAC,YAAY,MAAM,IAAI,aAAa,gCAAgC;CACxE,IAAI,WAAW,WAAW,WACxB,MAAM,IAAI,aAAa,mCAAmC;CAE5D,MAAM,YAAY,MAAM,gBAAgB,QAAQ;EAC9C,gBAAgB,WAAW;EAC3B,gBAAgB,WAAW;EAC3B,SAAS,QAAQ,WAAW,WAAW;EACvC,mBAAmB,QAAQ,qBAAqB;EAChD,OAAO,QAAQ;CACjB,CAAC;CAED,WAAW,SAAS;CACpB,MAAM,WAAW,KAAK;CAEtB,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"affiliate.service.mjs","names":[],"sources":["../../../src/services/affiliate.service.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport {\n AffiliateModel,\n AffiliateReferralModel,\n} from '@schemas/affiliate.schema';\nimport { AffiliateInvitationModel } from '@schemas/affiliateInvitation.schema';\nimport { GenericError } from '@utils/errors';\nimport Stripe from 'stripe';\nimport type {\n Affiliate,\n AffiliateDocument,\n AffiliateReferralDocument,\n AffiliateStats,\n CommissionType,\n} from '@/types/affiliate.types';\nimport type { AffiliateInvitationDocument } from '@/types/affiliateInvitation.types';\nimport type { Organization } from '@/types/organization.types';\nimport type { User } from '@/types/user.types';\n\nconst generateReferralCode = (): string =>\n Math.random().toString(36).substring(2, 8).toUpperCase();\n\nconst ensureUniqueCode = async (): Promise<string> => {\n let code = generateReferralCode();\n let attempts = 0;\n while (await AffiliateModel.exists({ referralCode: code })) {\n code = generateReferralCode();\n if (++attempts > 10)\n throw new GenericError('AFFILIATE_CODE_GENERATION_FAILED');\n }\n return code;\n};\n\nexport const createAffiliate = async (\n userId: User['id'],\n options: {\n commissionRate?: number;\n commissionType?: CommissionType;\n country?: string;\n stripeAccountType?: 'express' | 'standard';\n email?: string;\n } = {}\n): Promise<AffiliateDocument> => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n const accountType = options.stripeAccountType ?? 'express';\n\n const account =\n accountType === 'standard'\n ? await stripe.accounts.create({\n type: 'standard',\n ...(options.email ? { email: options.email } : {}),\n })\n : await stripe.accounts.create({\n controller: {\n stripe_dashboard: { type: 'none' },\n fees: { payer: 'application' },\n losses: { payments: 'stripe' },\n requirement_collection: 'stripe',\n },\n country: options.country ?? 'US',\n business_type: 'individual',\n business_profile: {\n product_description: 'Intlayer Affiliate Program',\n },\n capabilities: {\n card_payments: { requested: true },\n transfers: { requested: true },\n },\n settings: {\n payouts: { schedule: { interval: 'monthly', monthly_anchor: 1 } },\n },\n });\n\n const referralCode = await ensureUniqueCode();\n\n const affiliate = await AffiliateModel.create({\n userId,\n stripeAccountId: account.id,\n stripeAccountType: accountType,\n referralCode,\n status: 'onboarding',\n commissionRate: options.commissionRate ?? 20,\n commissionType: options.commissionType ?? 'one_time',\n });\n\n return affiliate;\n};\n\nexport const getAffiliateByUserId = async (\n userId: User['id'] | string\n): Promise<AffiliateDocument | null> =>\n AffiliateModel.findOne({ userId: String(userId) });\n\nexport const getAffiliateById = async (\n affiliateId: Affiliate['id'] | string\n): Promise<AffiliateDocument | null> =>\n AffiliateModel.findById(String(affiliateId));\n\nexport const getAffiliateByCode = async (\n referralCode: string\n): Promise<AffiliateDocument | null> =>\n AffiliateModel.findOne({ referralCode: referralCode.toUpperCase() });\n\nexport const findAffiliates = async (\n query: Record<string, unknown> = {},\n skip = 0,\n limit = 20\n): Promise<AffiliateDocument[]> =>\n AffiliateModel.find(query).sort({ createdAt: -1 }).skip(skip).limit(limit);\n\nexport const countAffiliates = async (\n query: Record<string, unknown> = {}\n): Promise<number> => AffiliateModel.countDocuments(query);\n\nexport const createAccountSession = async (\n stripeAccountId: string\n): Promise<string> => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n\n const accountSession = await stripe.accountSessions.create({\n account: stripeAccountId,\n components: {\n account_onboarding: { enabled: true },\n },\n });\n\n return accountSession.client_secret;\n};\n\nexport const createOnboardingLink = async (\n stripeAccountId: string,\n returnUrl: string,\n refreshUrl: string\n): Promise<string> => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n\n const accountLink = await stripe.accountLinks.create({\n account: stripeAccountId,\n return_url: returnUrl,\n refresh_url: refreshUrl,\n type: 'account_onboarding',\n });\n\n await AffiliateModel.findOneAndUpdate(\n { stripeAccountId },\n { stripeOnboardingInitiated: true }\n );\n\n return accountLink.url;\n};\n\nexport const markAffiliateActive = async (\n stripeAccountId: string,\n capabilities: { chargesEnabled: boolean; payoutsEnabled: boolean }\n): Promise<AffiliateDocument | null> =>\n AffiliateModel.findOneAndUpdate(\n { stripeAccountId, status: { $ne: 'active' } },\n {\n status: 'active',\n chargesEnabled: capabilities.chargesEnabled,\n payoutsEnabled: capabilities.payoutsEnabled,\n activatedAt: new Date(),\n },\n { new: true }\n );\n\nexport const payAffiliateCommission = async (\n referral: AffiliateReferralDocument\n): Promise<void> => {\n const affiliate = await getAffiliateById(String(referral.affiliateId));\n if (!affiliate?.stripeAccountId) return;\n\n const fullAmount = referral.commissionAmount ?? 0;\n if (fullAmount <= 0) return;\n\n const commissionAmount = Math.round(\n fullAmount * (affiliate.commissionRate / 100)\n );\n if (commissionAmount <= 0) return;\n\n const currency = (referral.commissionCurrency ?? 'usd').toLowerCase();\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n\n try {\n const transfer = await stripe.transfers.create({\n amount: commissionAmount,\n currency,\n destination: affiliate.stripeAccountId,\n metadata: {\n affiliateId: String(affiliate.id),\n referralId: String((referral as any)._id ?? referral.id),\n },\n });\n\n await AffiliateReferralModel.findByIdAndUpdate(\n (referral as any)._id ?? referral.id,\n { payoutStatus: 'paid', payoutId: transfer.id }\n );\n } catch (err) {\n // Mark payout as failed so it can be retried manually; do not throw\n // so the webhook returns 200 and Stripe does not keep retrying.\n await AffiliateReferralModel.findByIdAndUpdate(\n (referral as any)._id ?? referral.id,\n { payoutStatus: 'failed' }\n );\n }\n};\n\nexport const setAffiliateStatus = async (\n affiliateId: string,\n update: { status?: 'active' | 'suspended' }\n): Promise<AffiliateDocument | null> =>\n AffiliateModel.findByIdAndUpdate(affiliateId, update, { new: true });\n\nexport const trackReferral = async (\n referralCode: string,\n organizationId: Organization['id'] | string,\n subscriptionId?: string,\n commissionAmount?: number,\n commissionCurrency?: string\n): Promise<AffiliateReferralDocument | null> => {\n const affiliate = await getAffiliateByCode(referralCode);\n if (!affiliate) return null;\n\n const existing = await AffiliateReferralModel.findOne({\n affiliateId: affiliate.id,\n referredOrganizationId: String(organizationId),\n });\n\n if (existing) {\n // Keep the subscriptionId in sync with the latest attempt so the webhook\n // can match the referral when invoice.payment_succeeded fires.\n if (\n subscriptionId &&\n existing.subscriptionId !== subscriptionId &&\n existing.conversionStatus === 'pending'\n ) {\n existing.subscriptionId = subscriptionId;\n await existing.save();\n }\n return existing;\n }\n\n return AffiliateReferralModel.create({\n affiliateId: affiliate.id,\n referredOrganizationId: String(organizationId),\n subscriptionId,\n commissionAmount,\n commissionCurrency,\n conversionStatus: 'pending',\n payoutStatus: 'pending',\n });\n};\n\nexport const convertReferral = async (\n subscriptionId: string,\n commissionAmount?: number,\n commissionCurrency?: string,\n organizationId?: string\n): Promise<AffiliateReferralDocument | null> => {\n // Primary lookup: match by the exact subscription ID stored at tracking time.\n const bySubscription = await AffiliateReferralModel.findOneAndUpdate(\n { subscriptionId, conversionStatus: 'pending' },\n { conversionStatus: 'converted', commissionAmount, commissionCurrency },\n { returnDocument: 'after' }\n );\n if (bySubscription) return bySubscription;\n\n // Fallback: the referral was created during a previous payment attempt and still\n // holds an old subscriptionId. Match by organization and update to the current one.\n if (!organizationId) return null;\n return AffiliateReferralModel.findOneAndUpdate(\n { referredOrganizationId: organizationId, conversionStatus: 'pending' },\n {\n conversionStatus: 'converted',\n subscriptionId,\n commissionAmount,\n commissionCurrency,\n },\n { returnDocument: 'after' }\n );\n};\n\nexport const getAffiliateStats = async (\n userId: User['id'] | string\n): Promise<AffiliateStats | null> => {\n const affiliate = await getAffiliateByUserId(userId);\n if (!affiliate) return null;\n\n const referrals = await AffiliateReferralModel.find({\n affiliateId: affiliate.id,\n });\n\n const converted = referrals.filter(\n (referral) => referral.conversionStatus === 'converted'\n );\n const pending = referrals.filter(\n (referral) => referral.conversionStatus === 'pending'\n );\n const totalEarned = converted.reduce(\n (sum, referral) => sum + (referral.commissionAmount ?? 0),\n 0\n );\n const pendingAmount = pending.reduce(\n (sum, referral) => sum + (referral.commissionAmount ?? 0),\n 0\n );\n\n const appUrl = process.env.APP_URL;\n const referralLink = `${appUrl}/pricing?ref=${affiliate.referralCode}`;\n\n return {\n affiliate: affiliate.toJSON() as any,\n totalReferrals: referrals.length,\n convertedReferrals: converted.length,\n pendingReferrals: pending.length,\n totalCommissionEarned: totalEarned,\n pendingCommission: pendingAmount,\n referralLink,\n };\n};\n\n// ─── Invitation flow ──────────────────────────────────────────────────────────\n\nconst INVITATION_TTL_DAYS = 7;\n\nexport const createAffiliateInvitation = async (\n email: string,\n invitedBy: User['id'],\n options: {\n commissionRate?: number;\n commissionType?: CommissionType;\n country?: string;\n } = {}\n): Promise<AffiliateInvitationDocument> => {\n const token = randomUUID();\n const expiresAt = new Date();\n expiresAt.setDate(expiresAt.getDate() + INVITATION_TTL_DAYS);\n\n // Replace any existing pending invitation for this email\n await AffiliateInvitationModel.deleteMany({ email, status: 'pending' });\n\n return AffiliateInvitationModel.create({\n email,\n token,\n status: 'pending',\n invitedBy,\n commissionRate: options.commissionRate ?? 20,\n commissionType: options.commissionType ?? 'one_time',\n country: options.country,\n expiresAt,\n });\n};\n\nexport const findAffiliateInvitations = async (\n query: Record<string, unknown> = {},\n skip = 0,\n limit = 20\n): Promise<AffiliateInvitationDocument[]> =>\n AffiliateInvitationModel.find(query)\n .sort({ createdAt: -1 })\n .skip(skip)\n .limit(limit);\n\nexport const countAffiliateInvitations = async (\n query: Record<string, unknown> = {}\n): Promise<number> => AffiliateInvitationModel.countDocuments(query);\n\nexport const getAffiliateInvitationByToken = async (\n token: string\n): Promise<AffiliateInvitationDocument | null> => {\n const invitation = await AffiliateInvitationModel.findOne({ token });\n if (!invitation) return null;\n\n if (invitation.status === 'pending' && invitation.expiresAt < new Date()) {\n invitation.status = 'expired';\n await invitation.save();\n }\n\n return invitation;\n};\n\nexport const acceptAffiliateInvitation = async (\n token: string,\n userId: User['id'],\n options: {\n country?: string;\n stripeAccountType?: 'express' | 'standard';\n email?: string;\n } = {}\n): Promise<AffiliateDocument> => {\n const invitation = await getAffiliateInvitationByToken(token);\n\n if (!invitation) throw new GenericError('AFFILIATE_INVITATION_NOT_FOUND');\n if (invitation.status !== 'pending')\n throw new GenericError('AFFILIATE_INVITATION_ALREADY_USED');\n\n const affiliate = await createAffiliate(userId, {\n commissionRate: invitation.commissionRate,\n commissionType: invitation.commissionType,\n country: options.country ?? invitation.country,\n stripeAccountType: options.stripeAccountType ?? 'express',\n email: options.email,\n });\n\n invitation.status = 'accepted';\n await invitation.save();\n\n return affiliate;\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzeBundleContent.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/analyzeBundleContent.ts"],"sourcesContent":["import { ALL_LOCALES } from '@intlayer/types/allLocales';\nimport { load } from 'cheerio';\n\nexport type BundleChunkInput = {\n url: string;\n isMainBundle: boolean;\n content: string;\n};\n\nexport type ChunkAnalysis = {\n url: string;\n fileSize: number;\n totalLocaleSize: number;\n unusedLocaleSize: number;\n usedLocaleSize: number;\n dictionariesFound: number;\n unusedPercent: number; // unusedLocaleSize / totalLocaleSize\n};\n\nexport type BundleContentAnalysis = {\n currentLocale: string;\n totalPageSize: number;\n renderedContentSize: number;\n contentSize: number; // renderedContentSize + all locale content\n totalLocaleSize: number; // all locale strings (used + unused, main + lazy)\n totalUnusedLocaleSize: number; // all unused locale strings (main + lazy)\n unusedPercentOfLocale: number; // totalUnusedLocale / totalLocale\n mainBundleChunks: ChunkAnalysis[];\n lazyBundleChunks: ChunkAnalysis[];\n};\n\nconst allLocaleValues = new Set(Object.values(ALL_LOCALES) as string[]);\nconst isLocaleCode = (key: string): boolean =>\n allLocaleValues.has(key) || /^[a-z]{2}(-[A-Z]{2,4})?$/.test(key);\n\nconst extractValueEnd = (text: string, valueStart: number): number => {\n let cursor = valueStart;\n while (cursor < text.length && ' \\t\\n\\r'.includes(text[cursor])) cursor++;\n if (cursor >= text.length) return valueStart;\n\n const char = text[cursor];\n if (char === '{' || char === '[') {\n const endChar = char === '{' ? '}' : ']';\n let depth = 1;\n cursor++;\n while (cursor < text.length && depth > 0) {\n if (text[cursor] === char) depth++;\n else if (text[cursor] === endChar) depth--;\n else if (text[cursor] === '\"' || text[cursor] === '`') {\n const quote = text[cursor];\n cursor++;\n while (cursor < text.length) {\n if (text[cursor] === '\\\\') {\n cursor += 2;\n continue;\n }\n if (text[cursor] === quote) break;\n cursor++;\n }\n }\n cursor++;\n }\n return cursor;\n }\n if (char === '\"' || char === '`') {\n const quote = char;\n cursor++;\n while (cursor < text.length) {\n if (text[cursor] === '\\\\') {\n cursor += 2;\n continue;\n }\n if (text[cursor] === quote) {\n cursor++;\n break;\n }\n cursor++;\n }\n return cursor;\n }\n const endMatch = text.slice(cursor).search(/[,}\\]\\s]/);\n return endMatch === -1 ? text.length : cursor + endMatch;\n};\n\n// Matches both quoted (\"en\":) and unquoted (en:) locale keys followed by {\n// Works for any i18n solution — intlayer, i18next, vue-i18n, FormatJS, etc.\nconst LOCALE_KEY_PATTERN =\n /(?:\"([a-z]{2}(?:-[A-Z]{2,4})?)\"|\\b([a-z]{2}(?:-[A-Z]{2,4})?)\\b)\\s*:\\s*(?=\\{)/g;\n\n// Maximum character gap between two locale key positions to consider them\n// part of the same i18n object. Large enough for big translation objects.\nconst LOCALE_CLUSTER_WINDOW = 10_000;\n\n// Returns false when a candidate value is clearly not i18n text:\n// - contains hex/control escape sequences (ANSI codes, binary data)\nconst looksLikeI18nContent = (valueText: string): boolean => {\n if (/\\\\x[0-9a-fA-F]{2}/.test(valueText)) return false;\n if (/\\\\u00[01][0-9a-fA-F]/.test(valueText)) return false;\n return true;\n};\n\ntype LocaleMatch = {\n locale: string;\n position: number;\n valueStart: number;\n valueEnd: number;\n valueSize: number;\n};\n\nconst analyzeChunkLocaleContent = (\n text: string,\n baseCurrent: string\n): {\n unusedLocaleSize: number;\n usedLocaleSize: number;\n dictionariesFound: number;\n} => {\n // Step 1: collect all candidate locale key matches\n const candidates: LocaleMatch[] = [];\n const regex = new RegExp(LOCALE_KEY_PATTERN.source, 'g');\n let match = regex.exec(text);\n\n while (match !== null) {\n const locale = match[1] ?? match[2];\n if (isLocaleCode(locale)) {\n const valueStart = match.index + match[0].length;\n const valueEnd = extractValueEnd(text, valueStart);\n const valueSize = valueEnd - valueStart;\n const valueText = text.slice(valueStart, valueEnd);\n if (valueSize >= 5 && looksLikeI18nContent(valueText)) {\n candidates.push({\n locale,\n position: match.index,\n valueStart,\n valueEnd,\n valueSize,\n });\n }\n }\n match = regex.exec(text);\n }\n\n // Step 2: a locale key is i18n content only if another locale key with a\n // DIFFERENT locale code exists within LOCALE_CLUSTER_WINDOW chars.\n const isI18nMatch = (idx: number): boolean => {\n const base = candidates[idx].locale.split('-')[0].toLowerCase();\n for (let j = 0; j < candidates.length; j++) {\n if (j === idx) continue;\n const dist = Math.abs(candidates[j].position - candidates[idx].position);\n if (dist > LOCALE_CLUSTER_WINDOW) continue;\n if (candidates[j].locale.split('-')[0].toLowerCase() !== base)\n return true;\n }\n return false;\n };\n\n let unusedLocaleSize = 0;\n let usedLocaleSize = 0;\n let dictionariesFound = 0;\n\n for (let i = 0; i < candidates.length; i++) {\n if (!isI18nMatch(i)) continue;\n\n const { locale, valueSize } = candidates[i];\n dictionariesFound++;\n\n if (locale.split('-')[0].toLowerCase() === baseCurrent) {\n usedLocaleSize += valueSize;\n } else {\n unusedLocaleSize += valueSize;\n }\n }\n\n return { unusedLocaleSize, usedLocaleSize, dictionariesFound };\n};\n\nexport const analyzeBundleContent = (\n chunks: BundleChunkInput[],\n htmlContent: string,\n currentLocale: string,\n totalPageSize: number\n): BundleContentAnalysis => {\n const empty: BundleContentAnalysis = {\n currentLocale,\n totalPageSize,\n renderedContentSize: 0,\n contentSize: 0,\n totalLocaleSize: 0,\n totalUnusedLocaleSize: 0,\n unusedPercentOfLocale: 0,\n mainBundleChunks: [],\n lazyBundleChunks: [],\n };\n\n if (!chunks.length && !htmlContent) return empty;\n\n // Rendered content size from HTML visible text\n const $ = load(htmlContent);\n $('script, style, noscript, iframe').remove();\n\n const pageStrings = new Set<string>();\n $('body *')\n .contents()\n .filter((_, el) => el.type === 'text')\n .each((_, el) => {\n const text = $(el).text().replace(/\\s+/g, ' ').trim();\n if (text.length > 1) pageStrings.add(text);\n });\n\n let renderedContentSize = 0;\n pageStrings.forEach((s) => {\n renderedContentSize += Buffer.byteLength(s, 'utf-8');\n });\n\n const baseCurrent = currentLocale.split('-')[0].toLowerCase();\n\n const mainBundleChunks: ChunkAnalysis[] = [];\n const lazyBundleChunks: ChunkAnalysis[] = [];\n\n for (const chunk of chunks) {\n const { unusedLocaleSize, usedLocaleSize, dictionariesFound } =\n analyzeChunkLocaleContent(chunk.content, baseCurrent);\n\n const totalLocaleSize = unusedLocaleSize + usedLocaleSize;\n const analysis: ChunkAnalysis = {\n url: chunk.url,\n fileSize: Buffer.byteLength(chunk.content, 'utf-8'),\n totalLocaleSize,\n unusedLocaleSize,\n usedLocaleSize,\n dictionariesFound,\n unusedPercent:\n totalLocaleSize > 0\n ? Math.round((unusedLocaleSize / totalLocaleSize) * 100)\n : 0,\n };\n\n if (chunk.isMainBundle) {\n mainBundleChunks.push(analysis);\n } else if (dictionariesFound > 0) {\n lazyBundleChunks.push(analysis);\n }\n }\n\n const totalUnusedLocaleSize =\n mainBundleChunks.reduce((s, c) => s + c.unusedLocaleSize, 0) +\n lazyBundleChunks.reduce((s, c) => s + c.unusedLocaleSize, 0);\n const totalLocaleSize =\n mainBundleChunks.reduce((s, c) => s + c.totalLocaleSize, 0) +\n lazyBundleChunks.reduce((s, c) => s + c.totalLocaleSize, 0);\n const contentSize = renderedContentSize + totalLocaleSize;\n\n const unusedPercentOfLocale =\n totalLocaleSize > 0\n ? Math.round((totalUnusedLocaleSize / totalLocaleSize) * 100)\n : 0;\n\n return {\n currentLocale,\n totalPageSize,\n renderedContentSize,\n contentSize,\n totalLocaleSize,\n totalUnusedLocaleSize,\n unusedPercentOfLocale,\n mainBundleChunks,\n lazyBundleChunks,\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"analyzeBundleContent.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/analyzeBundleContent.ts"],"sourcesContent":["import { ALL_LOCALES } from '@intlayer/types/allLocales';\nimport { load } from 'cheerio';\n\nexport type BundleChunkInput = {\n url: string;\n isMainBundle: boolean;\n content: string;\n};\n\nexport type ChunkAnalysis = {\n url: string;\n fileSize: number;\n totalLocaleSize: number;\n unusedLocaleSize: number;\n usedLocaleSize: number;\n dictionariesFound: number;\n unusedPercent: number; // unusedLocaleSize / totalLocaleSize\n};\n\nexport type BundleContentAnalysis = {\n currentLocale: string;\n totalPageSize: number;\n renderedContentSize: number;\n contentSize: number; // renderedContentSize + all locale content\n totalLocaleSize: number; // all locale strings (used + unused, main + lazy)\n totalUnusedLocaleSize: number; // all unused locale strings (main + lazy)\n unusedPercentOfLocale: number; // totalUnusedLocale / totalLocale\n mainBundleChunks: ChunkAnalysis[];\n lazyBundleChunks: ChunkAnalysis[];\n};\n\nconst allLocaleValues = new Set(Object.values(ALL_LOCALES) as string[]);\nconst isLocaleCode = (key: string): boolean =>\n allLocaleValues.has(key) || /^[a-z]{2}(-[A-Z]{2,4})?$/.test(key);\n\nconst extractValueEnd = (text: string, valueStart: number): number => {\n let cursor = valueStart;\n while (cursor < text.length && ' \\t\\n\\r'.includes(text[cursor])) cursor++;\n if (cursor >= text.length) return valueStart;\n\n const char = text[cursor];\n if (char === '{' || char === '[') {\n const endChar = char === '{' ? '}' : ']';\n let depth = 1;\n cursor++;\n while (cursor < text.length && depth > 0) {\n if (text[cursor] === char) depth++;\n else if (text[cursor] === endChar) depth--;\n else if (text[cursor] === '\"' || text[cursor] === '`') {\n const quote = text[cursor];\n cursor++;\n while (cursor < text.length) {\n if (text[cursor] === '\\\\') {\n cursor += 2;\n continue;\n }\n if (text[cursor] === quote) break;\n cursor++;\n }\n }\n cursor++;\n }\n return cursor;\n }\n if (char === '\"' || char === '`') {\n const quote = char;\n cursor++;\n while (cursor < text.length) {\n if (text[cursor] === '\\\\') {\n cursor += 2;\n continue;\n }\n if (text[cursor] === quote) {\n cursor++;\n break;\n }\n cursor++;\n }\n return cursor;\n }\n const endMatch = text.slice(cursor).search(/[,}\\]\\s]/);\n return endMatch === -1 ? text.length : cursor + endMatch;\n};\n\n// Matches both quoted (\"en\":) and unquoted (en:) locale keys followed by {\n// Works for any i18n solution — intlayer, i18next, vue-i18n, FormatJS, etc.\nconst LOCALE_KEY_PATTERN =\n /(?:\"([a-z]{2}(?:-[A-Z]{2,4})?)\"|\\b([a-z]{2}(?:-[A-Z]{2,4})?)\\b)\\s*:\\s*(?=\\{)/g;\n\n// Maximum character gap between two locale key positions to consider them\n// part of the same i18n object. Large enough for big translation objects.\nconst LOCALE_CLUSTER_WINDOW = 10_000;\n\n// Returns false when a candidate value is clearly not i18n text:\n// - contains hex/control escape sequences (ANSI codes, binary data)\nconst looksLikeI18nContent = (valueText: string): boolean => {\n if (/\\\\x[0-9a-fA-F]{2}/.test(valueText)) return false;\n if (/\\\\u00[01][0-9a-fA-F]/.test(valueText)) return false;\n return true;\n};\n\ntype LocaleMatch = {\n locale: string;\n position: number;\n valueStart: number;\n valueEnd: number;\n valueSize: number;\n};\n\nconst analyzeChunkLocaleContent = (\n text: string,\n baseCurrent: string\n): {\n unusedLocaleSize: number;\n usedLocaleSize: number;\n dictionariesFound: number;\n} => {\n // Step 1: collect all candidate locale key matches\n const candidates: LocaleMatch[] = [];\n const regex = new RegExp(LOCALE_KEY_PATTERN.source, 'g');\n let match = regex.exec(text);\n\n while (match !== null) {\n const locale = match[1] ?? match[2];\n if (isLocaleCode(locale)) {\n const valueStart = match.index + match[0].length;\n const valueEnd = extractValueEnd(text, valueStart);\n const valueSize = valueEnd - valueStart;\n const valueText = text.slice(valueStart, valueEnd);\n if (valueSize >= 5 && looksLikeI18nContent(valueText)) {\n candidates.push({\n locale,\n position: match.index,\n valueStart,\n valueEnd,\n valueSize,\n });\n }\n }\n match = regex.exec(text);\n }\n\n // Step 2: a locale key is i18n content only if another locale key with a\n // DIFFERENT locale code exists within LOCALE_CLUSTER_WINDOW chars.\n const isI18nMatch = (idx: number): boolean => {\n const base = candidates[idx].locale.split('-')[0].toLowerCase();\n for (let j = 0; j < candidates.length; j++) {\n if (j === idx) continue;\n const dist = Math.abs(candidates[j].position - candidates[idx].position);\n if (dist > LOCALE_CLUSTER_WINDOW) continue;\n if (candidates[j].locale.split('-')[0].toLowerCase() !== base)\n return true;\n }\n return false;\n };\n\n let unusedLocaleSize = 0;\n let usedLocaleSize = 0;\n let dictionariesFound = 0;\n\n for (let i = 0; i < candidates.length; i++) {\n if (!isI18nMatch(i)) continue;\n\n const { locale, valueSize } = candidates[i];\n dictionariesFound++;\n\n if (locale.split('-')[0].toLowerCase() === baseCurrent) {\n usedLocaleSize += valueSize;\n } else {\n unusedLocaleSize += valueSize;\n }\n }\n\n return { unusedLocaleSize, usedLocaleSize, dictionariesFound };\n};\n\nexport const analyzeBundleContent = (\n chunks: BundleChunkInput[],\n htmlContent: string,\n currentLocale: string,\n totalPageSize: number\n): BundleContentAnalysis => {\n const empty: BundleContentAnalysis = {\n currentLocale,\n totalPageSize,\n renderedContentSize: 0,\n contentSize: 0,\n totalLocaleSize: 0,\n totalUnusedLocaleSize: 0,\n unusedPercentOfLocale: 0,\n mainBundleChunks: [],\n lazyBundleChunks: [],\n };\n\n if (!chunks.length && !htmlContent) return empty;\n\n // Rendered content size from HTML visible text\n const $ = load(htmlContent);\n $('script, style, noscript, iframe').remove();\n\n const pageStrings = new Set<string>();\n $('body *')\n .contents()\n .filter((_, el) => el.type === 'text')\n .each((_, el) => {\n const text = $(el).text().replace(/\\s+/g, ' ').trim();\n if (text.length > 1) pageStrings.add(text);\n });\n\n let renderedContentSize = 0;\n pageStrings.forEach((s) => {\n renderedContentSize += Buffer.byteLength(s, 'utf-8');\n });\n\n const baseCurrent = currentLocale.split('-')[0].toLowerCase();\n\n const mainBundleChunks: ChunkAnalysis[] = [];\n const lazyBundleChunks: ChunkAnalysis[] = [];\n\n for (const chunk of chunks) {\n const { unusedLocaleSize, usedLocaleSize, dictionariesFound } =\n analyzeChunkLocaleContent(chunk.content, baseCurrent);\n\n const totalLocaleSize = unusedLocaleSize + usedLocaleSize;\n const analysis: ChunkAnalysis = {\n url: chunk.url,\n fileSize: Buffer.byteLength(chunk.content, 'utf-8'),\n totalLocaleSize,\n unusedLocaleSize,\n usedLocaleSize,\n dictionariesFound,\n unusedPercent:\n totalLocaleSize > 0\n ? Math.round((unusedLocaleSize / totalLocaleSize) * 100)\n : 0,\n };\n\n if (chunk.isMainBundle) {\n mainBundleChunks.push(analysis);\n } else if (dictionariesFound > 0) {\n lazyBundleChunks.push(analysis);\n }\n }\n\n const totalUnusedLocaleSize =\n mainBundleChunks.reduce((s, c) => s + c.unusedLocaleSize, 0) +\n lazyBundleChunks.reduce((s, c) => s + c.unusedLocaleSize, 0);\n const totalLocaleSize =\n mainBundleChunks.reduce((s, c) => s + c.totalLocaleSize, 0) +\n lazyBundleChunks.reduce((s, c) => s + c.totalLocaleSize, 0);\n const contentSize = renderedContentSize + totalLocaleSize;\n\n const unusedPercentOfLocale =\n totalLocaleSize > 0\n ? Math.round((totalUnusedLocaleSize / totalLocaleSize) * 100)\n : 0;\n\n return {\n currentLocale,\n totalPageSize,\n renderedContentSize,\n contentSize,\n totalLocaleSize,\n totalUnusedLocaleSize,\n unusedPercentOfLocale,\n mainBundleChunks,\n lazyBundleChunks,\n };\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzeLinguisticStructure.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/analyzeLinguisticStructure.ts"],"sourcesContent":["export const analyzeLinguisticStructure = (\n $: any,\n baseUrl: string,\n localesSet: Set<string>\n) => {\n const langTag = $('html').attr('lang') ?? 'not found';\n const htmlLangPresent = langTag !== 'not found';\n const dirTag = $('html').attr('dir') ?? null;\n const htmlDirPresent = Boolean(dirTag);\n\n const currentLocale = langTag;\n if (currentLocale && currentLocale !== 'not found') {\n localesSet.add(currentLocale);\n }\n\n const hreflangs: { hreflang: string; href: string }[] = [];\n $(\"link[rel='alternate']\").each((_: any, elem: any) => {\n const hreflang = $(elem).attr('hreflang');\n const href = $(elem).attr('href');\n if (hreflang && href) {\n hreflangs.push({ hreflang, href });\n }\n });\n\n const hreflangDiversity = new Set(hreflangs.map((h) => h.hreflang)).size;\n const hasXDefault = hreflangs.some((h) => h.hreflang === 'x-default');\n\n const alternates: string[] = [];\n for (const item of hreflangs) {\n try {\n const absUrl = new URL(item.href, baseUrl).href;\n alternates.push(absUrl);\n const locale = item.hreflang;\n if (locale && locale !== 'x-default') {\n localesSet.add(locale);\n }\n } catch {\n // ignore\n }\n }\n\n return {\n langTag,\n htmlLangPresent,\n dirTag,\n htmlDirPresent,\n currentLocale,\n hreflangs,\n hreflangDiversity,\n hasXDefault,\n alternates,\n };\n};\n"],"mappings":";AAAA,MAAa,8BACX,GACA,SACA,eACG;CACH,MAAM,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"analyzeLinguisticStructure.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/analyzeLinguisticStructure.ts"],"sourcesContent":["export const analyzeLinguisticStructure = (\n $: any,\n baseUrl: string,\n localesSet: Set<string>\n) => {\n const langTag = $('html').attr('lang') ?? 'not found';\n const htmlLangPresent = langTag !== 'not found';\n const dirTag = $('html').attr('dir') ?? null;\n const htmlDirPresent = Boolean(dirTag);\n\n const currentLocale = langTag;\n if (currentLocale && currentLocale !== 'not found') {\n localesSet.add(currentLocale);\n }\n\n const hreflangs: { hreflang: string; href: string }[] = [];\n $(\"link[rel='alternate']\").each((_: any, elem: any) => {\n const hreflang = $(elem).attr('hreflang');\n const href = $(elem).attr('href');\n if (hreflang && href) {\n hreflangs.push({ hreflang, href });\n }\n });\n\n const hreflangDiversity = new Set(hreflangs.map((h) => h.hreflang)).size;\n const hasXDefault = hreflangs.some((h) => h.hreflang === 'x-default');\n\n const alternates: string[] = [];\n for (const item of hreflangs) {\n try {\n const absUrl = new URL(item.href, baseUrl).href;\n alternates.push(absUrl);\n const locale = item.hreflang;\n if (locale && locale !== 'x-default') {\n localesSet.add(locale);\n }\n } catch {\n // ignore\n }\n }\n\n return {\n langTag,\n htmlLangPresent,\n dirTag,\n htmlDirPresent,\n currentLocale,\n hreflangs,\n hreflangDiversity,\n hasXDefault,\n alternates,\n };\n};\n"],"mappings":";AAAA,MAAa,8BACX,GACA,SACA,eACG;CACH,MAAM,UAAU,EAAE,OAAO,CAAC,KAAK,OAAO,IAAI;CAC1C,MAAM,kBAAkB,YAAY;CACpC,MAAM,SAAS,EAAE,OAAO,CAAC,KAAK,MAAM,IAAI;CACxC,MAAM,iBAAiB,QAAQ,OAAO;CAEtC,MAAM,gBAAgB;AACtB,KAAI,iBAAiB,kBAAkB,YACrC,YAAW,IAAI,cAAc;CAG/B,MAAM,YAAkD,EAAE;AAC1D,GAAE,wBAAwB,CAAC,MAAM,GAAQ,SAAc;EACrD,MAAM,WAAW,EAAE,KAAK,CAAC,KAAK,WAAW;EACzC,MAAM,OAAO,EAAE,KAAK,CAAC,KAAK,OAAO;AACjC,MAAI,YAAY,KACd,WAAU,KAAK;GAAE;GAAU;GAAM,CAAC;GAEpC;CAEF,MAAM,oBAAoB,IAAI,IAAI,UAAU,KAAK,MAAM,EAAE,SAAS,CAAC,CAAC;CACpE,MAAM,cAAc,UAAU,MAAM,MAAM,EAAE,aAAa,YAAY;CAErE,MAAM,aAAuB,EAAE;AAC/B,MAAK,MAAM,QAAQ,UACjB,KAAI;EACF,MAAM,SAAS,IAAI,IAAI,KAAK,MAAM,QAAQ,CAAC;AAC3C,aAAW,KAAK,OAAO;EACvB,MAAM,SAAS,KAAK;AACpB,MAAI,UAAU,WAAW,YACvB,YAAW,IAAI,OAAO;SAElB;AAKV,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzeMetadata.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/analyzeMetadata.ts"],"sourcesContent":["export const analyzeMetadata = ($: any) => {\n const canonical = $(\"link[rel='canonical']\").attr('href');\n const hasCanonicalTag = Boolean(canonical);\n\n return {\n hasCanonicalTag,\n };\n};\n"],"mappings":";AAAA,MAAa,mBAAmB,MAAW;CACzC,MAAM,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"analyzeMetadata.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/analyzeMetadata.ts"],"sourcesContent":["export const analyzeMetadata = ($: any) => {\n const canonical = $(\"link[rel='canonical']\").attr('href');\n const hasCanonicalTag = Boolean(canonical);\n\n return {\n hasCanonicalTag,\n };\n};\n"],"mappings":";AAAA,MAAa,mBAAmB,MAAW;CACzC,MAAM,YAAY,EAAE,wBAAwB,CAAC,KAAK,OAAO;AAGzD,QAAO,EACL,iBAHsB,QAAQ,UAGf,EAChB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzeRobots.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/analyzeRobots.ts"],"sourcesContent":["export const analyzeRobots = async (\n origin: string,\n discoveredLocales: Set<string>\n): Promise<{\n robotsPresent: boolean;\n robotsContent: string | null;\n noLocalizedUrlsForgotten: boolean;\n errors: string[];\n}> => {\n const errors: string[] = [];\n let robotsPresent = false;\n let robotsContent: string | null = null;\n let noLocalizedUrlsForgotten = true;\n\n try {\n const robotsUrl = `${origin}/robots.txt`;\n const response = await fetch(robotsUrl, {\n method: 'GET',\n headers: { 'User-Agent': 'Mozilla/5.0 (compatible; SEO-Audit-Bot/1.0)' },\n });\n\n if (response.ok) {\n robotsPresent = true;\n robotsContent = await response.text();\n\n if (robotsContent && discoveredLocales.size > 0) {\n const disallowedPaths: string[] = [];\n const lines = robotsContent.split('\\n');\n\n for (const line of lines) {\n const trimmed = line.trim().toLowerCase();\n if (trimmed.startsWith('disallow:')) {\n const path = trimmed.substring('disallow:'.length).trim();\n disallowedPaths.push(path);\n }\n }\n\n for (const locale of discoveredLocales) {\n for (const disallowedPath of disallowedPaths) {\n if (\n disallowedPath === `/${locale}` ||\n disallowedPath === `/${locale}/`\n ) {\n noLocalizedUrlsForgotten = false;\n errors.push(\n `Locale path \"${locale}\" appears to be blocked in robots.txt: ${disallowedPath}`\n );\n }\n }\n }\n }\n } else {\n errors.push(`robots.txt not found (HTTP ${response.status})`);\n }\n } catch (error) {\n errors.push(\n `Failed to fetch robots.txt: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n\n return {\n robotsPresent,\n robotsContent,\n noLocalizedUrlsForgotten,\n errors,\n };\n};\n"],"mappings":";AAAA,MAAa,gBAAgB,OAC3B,QACA,sBAMI;CACJ,MAAM,SAAmB,
|
|
1
|
+
{"version":3,"file":"analyzeRobots.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/analyzeRobots.ts"],"sourcesContent":["export const analyzeRobots = async (\n origin: string,\n discoveredLocales: Set<string>\n): Promise<{\n robotsPresent: boolean;\n robotsContent: string | null;\n noLocalizedUrlsForgotten: boolean;\n errors: string[];\n}> => {\n const errors: string[] = [];\n let robotsPresent = false;\n let robotsContent: string | null = null;\n let noLocalizedUrlsForgotten = true;\n\n try {\n const robotsUrl = `${origin}/robots.txt`;\n const response = await fetch(robotsUrl, {\n method: 'GET',\n headers: { 'User-Agent': 'Mozilla/5.0 (compatible; SEO-Audit-Bot/1.0)' },\n });\n\n if (response.ok) {\n robotsPresent = true;\n robotsContent = await response.text();\n\n if (robotsContent && discoveredLocales.size > 0) {\n const disallowedPaths: string[] = [];\n const lines = robotsContent.split('\\n');\n\n for (const line of lines) {\n const trimmed = line.trim().toLowerCase();\n if (trimmed.startsWith('disallow:')) {\n const path = trimmed.substring('disallow:'.length).trim();\n disallowedPaths.push(path);\n }\n }\n\n for (const locale of discoveredLocales) {\n for (const disallowedPath of disallowedPaths) {\n if (\n disallowedPath === `/${locale}` ||\n disallowedPath === `/${locale}/`\n ) {\n noLocalizedUrlsForgotten = false;\n errors.push(\n `Locale path \"${locale}\" appears to be blocked in robots.txt: ${disallowedPath}`\n );\n }\n }\n }\n }\n } else {\n errors.push(`robots.txt not found (HTTP ${response.status})`);\n }\n } catch (error) {\n errors.push(\n `Failed to fetch robots.txt: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n\n return {\n robotsPresent,\n robotsContent,\n noLocalizedUrlsForgotten,\n errors,\n };\n};\n"],"mappings":";AAAA,MAAa,gBAAgB,OAC3B,QACA,sBAMI;CACJ,MAAM,SAAmB,EAAE;CAC3B,IAAI,gBAAgB;CACpB,IAAI,gBAA+B;CACnC,IAAI,2BAA2B;AAE/B,KAAI;EACF,MAAM,YAAY,GAAG,OAAO;EAC5B,MAAM,WAAW,MAAM,MAAM,WAAW;GACtC,QAAQ;GACR,SAAS,EAAE,cAAc,+CAA+C;GACzE,CAAC;AAEF,MAAI,SAAS,IAAI;AACf,mBAAgB;AAChB,mBAAgB,MAAM,SAAS,MAAM;AAErC,OAAI,iBAAiB,kBAAkB,OAAO,GAAG;IAC/C,MAAM,kBAA4B,EAAE;IACpC,MAAM,QAAQ,cAAc,MAAM,KAAK;AAEvC,SAAK,MAAM,QAAQ,OAAO;KACxB,MAAM,UAAU,KAAK,MAAM,CAAC,aAAa;AACzC,SAAI,QAAQ,WAAW,YAAY,EAAE;MACnC,MAAM,OAAO,QAAQ,UAAU,EAAmB,CAAC,MAAM;AACzD,sBAAgB,KAAK,KAAK;;;AAI9B,SAAK,MAAM,UAAU,kBACnB,MAAK,MAAM,kBAAkB,gBAC3B,KACE,mBAAmB,IAAI,YACvB,mBAAmB,IAAI,OAAO,IAC9B;AACA,gCAA2B;AAC3B,YAAO,KACL,gBAAgB,OAAO,yCAAyC,iBACjE;;;QAMT,QAAO,KAAK,8BAA8B,SAAS,OAAO,GAAG;UAExD,OAAO;AACd,SAAO,KACL,+BAA+B,iBAAiB,QAAQ,MAAM,UAAU,kBACzE;;AAGH,QAAO;EACL;EACA;EACA;EACA;EACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzeSitemap.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/analyzeSitemap.ts"],"sourcesContent":["import { load } from 'cheerio';\n\nexport const analyzeSitemap = async (\n origin: string,\n discoveredLocales: Set<string>\n): Promise<{\n sitemapPresent: boolean;\n hasXDefault: boolean;\n hasAlternates: boolean;\n noLocalizedUrlsForgotten: boolean;\n localizedUrlsFound: string[];\n errors: string[];\n}> => {\n const errors: string[] = [];\n let sitemapPresent = false;\n let hasXDefault = false;\n let hasAlternates = false;\n let noLocalizedUrlsForgotten = true;\n const localizedUrlsFound: string[] = [];\n\n try {\n const sitemapUrl = `${origin}/sitemap.xml`;\n const response = await fetch(sitemapUrl, {\n method: 'GET',\n headers: { 'User-Agent': 'Mozilla/5.0 (compatible; SEO-Audit-Bot/1.0)' },\n });\n\n if (response.ok) {\n sitemapPresent = true;\n const sitemapContent = await response.text();\n const $ = load(sitemapContent, { xmlMode: true });\n\n const xDefaultLinks = $(\n 'link[rel=\"alternate\"][hreflang=\"x-default\"], xhtml\\\\:link[rel=\"alternate\"][hreflang=\"x-default\"]'\n );\n if (xDefaultLinks.length > 0) {\n hasXDefault = true;\n }\n\n const alternateLinks = $(\n 'link[rel=\"alternate\"][hreflang], xhtml\\\\:link[rel=\"alternate\"][hreflang]'\n );\n if (alternateLinks.length > 0) {\n hasAlternates = true;\n }\n\n if (discoveredLocales.size > 0) {\n const urlElements = $('url');\n const urlsWithMissingLocales: Array<{\n url: string;\n missingLocales: string[];\n }> = [];\n const allFoundLocales = new Set<string>();\n\n urlElements.each((_, urlElement) => {\n const locElement = $(urlElement).find('loc').first();\n const url = locElement.text().trim();\n if (!url) return;\n\n const hreflangLinks = $(urlElement).find(\n 'link[rel=\"alternate\"][hreflang], xhtml\\\\:link[rel=\"alternate\"][hreflang]'\n );\n const localesInThisUrl = new Set<string>();\n\n hreflangLinks.each((_, linkEl) => {\n const hreflang = $(linkEl).attr('hreflang');\n if (hreflang && hreflang !== 'x-default') {\n localesInThisUrl.add(hreflang);\n allFoundLocales.add(hreflang);\n }\n });\n\n try {\n const urlObj = new URL(url);\n const pathParts = urlObj.pathname.split('/').filter(Boolean);\n if (pathParts.length > 0 && discoveredLocales.has(pathParts[0])) {\n localesInThisUrl.add(pathParts[0]);\n allFoundLocales.add(pathParts[0]);\n localizedUrlsFound.push(url);\n }\n } catch {\n // Invalid URL, skip\n }\n\n const missingInThisUrl: string[] = [];\n for (const locale of discoveredLocales) {\n if (!localesInThisUrl.has(locale)) {\n missingInThisUrl.push(locale);\n }\n }\n\n if (\n missingInThisUrl.length > 0 &&\n missingInThisUrl.length < discoveredLocales.size\n ) {\n urlsWithMissingLocales.push({\n url,\n missingLocales: missingInThisUrl,\n });\n }\n });\n\n if (urlsWithMissingLocales.length > 0) {\n noLocalizedUrlsForgotten = false;\n for (const { url, missingLocales } of urlsWithMissingLocales) {\n errors.push(\n `URL \"${url}\" is missing alternate links for locales: ${missingLocales.join(', ')}`\n );\n }\n }\n\n const completelyMissingLocales: string[] = [];\n for (const locale of discoveredLocales) {\n if (!allFoundLocales.has(locale)) {\n completelyMissingLocales.push(locale);\n }\n }\n\n if (completelyMissingLocales.length > 0) {\n noLocalizedUrlsForgotten = false;\n errors.push(\n `The following locales are completely missing from the sitemap: ${completelyMissingLocales.join(', ')}`\n );\n }\n }\n } else {\n errors.push(`sitemap.xml not found (HTTP ${response.status})`);\n }\n } catch (error) {\n errors.push(\n `Failed to fetch sitemap.xml: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n\n return {\n sitemapPresent,\n hasXDefault,\n hasAlternates,\n noLocalizedUrlsForgotten,\n localizedUrlsFound,\n errors,\n };\n};\n"],"mappings":";;;AAEA,MAAa,iBAAiB,OAC5B,QACA,sBAQI;CACJ,MAAM,SAAmB,
|
|
1
|
+
{"version":3,"file":"analyzeSitemap.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/analyzeSitemap.ts"],"sourcesContent":["import { load } from 'cheerio';\n\nexport const analyzeSitemap = async (\n origin: string,\n discoveredLocales: Set<string>\n): Promise<{\n sitemapPresent: boolean;\n hasXDefault: boolean;\n hasAlternates: boolean;\n noLocalizedUrlsForgotten: boolean;\n localizedUrlsFound: string[];\n errors: string[];\n}> => {\n const errors: string[] = [];\n let sitemapPresent = false;\n let hasXDefault = false;\n let hasAlternates = false;\n let noLocalizedUrlsForgotten = true;\n const localizedUrlsFound: string[] = [];\n\n try {\n const sitemapUrl = `${origin}/sitemap.xml`;\n const response = await fetch(sitemapUrl, {\n method: 'GET',\n headers: { 'User-Agent': 'Mozilla/5.0 (compatible; SEO-Audit-Bot/1.0)' },\n });\n\n if (response.ok) {\n sitemapPresent = true;\n const sitemapContent = await response.text();\n const $ = load(sitemapContent, { xmlMode: true });\n\n const xDefaultLinks = $(\n 'link[rel=\"alternate\"][hreflang=\"x-default\"], xhtml\\\\:link[rel=\"alternate\"][hreflang=\"x-default\"]'\n );\n if (xDefaultLinks.length > 0) {\n hasXDefault = true;\n }\n\n const alternateLinks = $(\n 'link[rel=\"alternate\"][hreflang], xhtml\\\\:link[rel=\"alternate\"][hreflang]'\n );\n if (alternateLinks.length > 0) {\n hasAlternates = true;\n }\n\n if (discoveredLocales.size > 0) {\n const urlElements = $('url');\n const urlsWithMissingLocales: Array<{\n url: string;\n missingLocales: string[];\n }> = [];\n const allFoundLocales = new Set<string>();\n\n urlElements.each((_, urlElement) => {\n const locElement = $(urlElement).find('loc').first();\n const url = locElement.text().trim();\n if (!url) return;\n\n const hreflangLinks = $(urlElement).find(\n 'link[rel=\"alternate\"][hreflang], xhtml\\\\:link[rel=\"alternate\"][hreflang]'\n );\n const localesInThisUrl = new Set<string>();\n\n hreflangLinks.each((_, linkEl) => {\n const hreflang = $(linkEl).attr('hreflang');\n if (hreflang && hreflang !== 'x-default') {\n localesInThisUrl.add(hreflang);\n allFoundLocales.add(hreflang);\n }\n });\n\n try {\n const urlObj = new URL(url);\n const pathParts = urlObj.pathname.split('/').filter(Boolean);\n if (pathParts.length > 0 && discoveredLocales.has(pathParts[0])) {\n localesInThisUrl.add(pathParts[0]);\n allFoundLocales.add(pathParts[0]);\n localizedUrlsFound.push(url);\n }\n } catch {\n // Invalid URL, skip\n }\n\n const missingInThisUrl: string[] = [];\n for (const locale of discoveredLocales) {\n if (!localesInThisUrl.has(locale)) {\n missingInThisUrl.push(locale);\n }\n }\n\n if (\n missingInThisUrl.length > 0 &&\n missingInThisUrl.length < discoveredLocales.size\n ) {\n urlsWithMissingLocales.push({\n url,\n missingLocales: missingInThisUrl,\n });\n }\n });\n\n if (urlsWithMissingLocales.length > 0) {\n noLocalizedUrlsForgotten = false;\n for (const { url, missingLocales } of urlsWithMissingLocales) {\n errors.push(\n `URL \"${url}\" is missing alternate links for locales: ${missingLocales.join(', ')}`\n );\n }\n }\n\n const completelyMissingLocales: string[] = [];\n for (const locale of discoveredLocales) {\n if (!allFoundLocales.has(locale)) {\n completelyMissingLocales.push(locale);\n }\n }\n\n if (completelyMissingLocales.length > 0) {\n noLocalizedUrlsForgotten = false;\n errors.push(\n `The following locales are completely missing from the sitemap: ${completelyMissingLocales.join(', ')}`\n );\n }\n }\n } else {\n errors.push(`sitemap.xml not found (HTTP ${response.status})`);\n }\n } catch (error) {\n errors.push(\n `Failed to fetch sitemap.xml: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n\n return {\n sitemapPresent,\n hasXDefault,\n hasAlternates,\n noLocalizedUrlsForgotten,\n localizedUrlsFound,\n errors,\n };\n};\n"],"mappings":";;;AAEA,MAAa,iBAAiB,OAC5B,QACA,sBAQI;CACJ,MAAM,SAAmB,EAAE;CAC3B,IAAI,iBAAiB;CACrB,IAAI,cAAc;CAClB,IAAI,gBAAgB;CACpB,IAAI,2BAA2B;CAC/B,MAAM,qBAA+B,EAAE;AAEvC,KAAI;EACF,MAAM,aAAa,GAAG,OAAO;EAC7B,MAAM,WAAW,MAAM,MAAM,YAAY;GACvC,QAAQ;GACR,SAAS,EAAE,cAAc,+CAA+C;GACzE,CAAC;AAEF,MAAI,SAAS,IAAI;AACf,oBAAiB;GAEjB,MAAM,IAAI,KAAK,MADc,SAAS,MAAM,EACb,EAAE,SAAS,MAAM,CAAC;AAKjD,OAHsB,EACpB,2GAEe,CAAC,SAAS,EACzB,eAAc;AAMhB,OAHuB,EACrB,+EAEgB,CAAC,SAAS,EAC1B,iBAAgB;AAGlB,OAAI,kBAAkB,OAAO,GAAG;IAC9B,MAAM,cAAc,EAAE,MAAM;IAC5B,MAAM,yBAGD,EAAE;IACP,MAAM,kCAAkB,IAAI,KAAa;AAEzC,gBAAY,MAAM,GAAG,eAAe;KAElC,MAAM,MADa,EAAE,WAAW,CAAC,KAAK,MAAM,CAAC,OACvB,CAAC,MAAM,CAAC,MAAM;AACpC,SAAI,CAAC,IAAK;KAEV,MAAM,gBAAgB,EAAE,WAAW,CAAC,KAClC,+EACD;KACD,MAAM,mCAAmB,IAAI,KAAa;AAE1C,mBAAc,MAAM,GAAG,WAAW;MAChC,MAAM,WAAW,EAAE,OAAO,CAAC,KAAK,WAAW;AAC3C,UAAI,YAAY,aAAa,aAAa;AACxC,wBAAiB,IAAI,SAAS;AAC9B,uBAAgB,IAAI,SAAS;;OAE/B;AAEF,SAAI;MAEF,MAAM,YAAY,IADC,IAAI,IACC,CAAC,SAAS,MAAM,IAAI,CAAC,OAAO,QAAQ;AAC5D,UAAI,UAAU,SAAS,KAAK,kBAAkB,IAAI,UAAU,GAAG,EAAE;AAC/D,wBAAiB,IAAI,UAAU,GAAG;AAClC,uBAAgB,IAAI,UAAU,GAAG;AACjC,0BAAmB,KAAK,IAAI;;aAExB;KAIR,MAAM,mBAA6B,EAAE;AACrC,UAAK,MAAM,UAAU,kBACnB,KAAI,CAAC,iBAAiB,IAAI,OAAO,CAC/B,kBAAiB,KAAK,OAAO;AAIjC,SACE,iBAAiB,SAAS,KAC1B,iBAAiB,SAAS,kBAAkB,KAE5C,wBAAuB,KAAK;MAC1B;MACA,gBAAgB;MACjB,CAAC;MAEJ;AAEF,QAAI,uBAAuB,SAAS,GAAG;AACrC,gCAA2B;AAC3B,UAAK,MAAM,EAAE,KAAK,oBAAoB,uBACpC,QAAO,KACL,QAAQ,IAAI,4CAA4C,eAAe,KAAK,KAAK,GAClF;;IAIL,MAAM,2BAAqC,EAAE;AAC7C,SAAK,MAAM,UAAU,kBACnB,KAAI,CAAC,gBAAgB,IAAI,OAAO,CAC9B,0BAAyB,KAAK,OAAO;AAIzC,QAAI,yBAAyB,SAAS,GAAG;AACvC,gCAA2B;AAC3B,YAAO,KACL,kEAAkE,yBAAyB,KAAK,KAAK,GACtG;;;QAIL,QAAO,KAAK,+BAA+B,SAAS,OAAO,GAAG;UAEzD,OAAO;AACd,SAAO,KACL,gCAAgC,iBAAiB,QAAQ,MAAM,UAAU,kBAC1E;;AAGH,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzeUrlStructure.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/analyzeUrlStructure.ts"],"sourcesContent":["import { ALL_LOCALES } from '@intlayer/types/allLocales';\n\nexport const analyzeUrlStructure = async (page: any, origin: string) => {\n const targetHostname = new URL(origin).hostname;\n\n const anchors: { href: string; text: string }[] = await page.$$eval(\n 'a[href]',\n (nodes: any[]) =>\n nodes.map((a) => ({\n href: a.getAttribute('href'),\n text: a.innerText?.trim() || '',\n }))\n );\n\n let localizedCount = 0;\n let totalInternalCount = 0;\n const localizedLinks: string[] = [];\n const nonLocalizedLinks: string[] = [];\n const internalUrls: string[] = [];\n\n for (const { href, text } of anchors) {\n if (!href || href.startsWith('#') || href.startsWith('javascript:'))\n continue;\n\n try {\n const url = new URL(href, origin);\n const urlHostname = url.hostname;\n\n const normalizeHost = (host: string) =>\n host.startsWith('www.') ? host.slice(4) : host;\n\n const isInternal =\n normalizeHost(urlHostname) === normalizeHost(targetHostname);\n\n if (isInternal) {\n totalInternalCount++;\n let normalizedPath = url.pathname;\n if (normalizedPath.length > 1 && normalizedPath.endsWith('/')) {\n normalizedPath = normalizedPath.slice(0, -1);\n }\n const normalizedUrl = url.origin + normalizedPath + url.search;\n internalUrls.push(normalizedUrl);\n const path = url.pathname.toLowerCase();\n const hostname = url.hostname.toLowerCase();\n\n const hasLocaleInPath = Object.values(ALL_LOCALES).some((locale) => {\n const localeLower = (locale as string).toLowerCase();\n return (\n path.startsWith(`/${localeLower}/`) ||\n path === `/${localeLower}` ||\n path.includes(`/${localeLower}/`)\n );\n });\n\n const hasLocaleInSubdomain = Object.values(ALL_LOCALES).some(\n (locale) => {\n const localeLower = (locale as string).toLowerCase();\n return (\n hostname.startsWith(`${localeLower}.`) ||\n hostname.includes(`.${localeLower}.`)\n );\n }\n );\n\n const linkHtml = `\\`\\`\\`\\`html\\n<a href='${href}'>${text || 'Link'}</a>\\n\\`\\`\\``;\n\n if (hasLocaleInPath || hasLocaleInSubdomain) {\n localizedCount++;\n localizedLinks.push(linkHtml);\n } else {\n nonLocalizedLinks.push(linkHtml);\n }\n }\n } catch {\n // ignore invalid URLs\n }\n }\n\n const hasLocalizedLinks = localizedCount > 0;\n const allAnchorsLocalized =\n totalInternalCount === 0 || localizedCount === totalInternalCount;\n\n let urlStructureLocalized: 'none' | 'path-based' | 'subdomain-based' = 'none';\n if (hasLocalizedLinks) {\n urlStructureLocalized = 'path-based';\n }\n\n return {\n urlStructureLocalized,\n hasLocalizedLinks,\n allAnchorsLocalized,\n totalInternalCount,\n localizedCount,\n localizedLinks,\n nonLocalizedLinks,\n internalUrls: Array.from(new Set(internalUrls)),\n };\n};\n"],"mappings":";;;AAEA,MAAa,sBAAsB,OAAO,MAAW,WAAmB;CACtE,MAAM,iBAAiB,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"analyzeUrlStructure.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/analyzeUrlStructure.ts"],"sourcesContent":["import { ALL_LOCALES } from '@intlayer/types/allLocales';\n\nexport const analyzeUrlStructure = async (page: any, origin: string) => {\n const targetHostname = new URL(origin).hostname;\n\n const anchors: { href: string; text: string }[] = await page.$$eval(\n 'a[href]',\n (nodes: any[]) =>\n nodes.map((a) => ({\n href: a.getAttribute('href'),\n text: a.innerText?.trim() || '',\n }))\n );\n\n let localizedCount = 0;\n let totalInternalCount = 0;\n const localizedLinks: string[] = [];\n const nonLocalizedLinks: string[] = [];\n const internalUrls: string[] = [];\n\n for (const { href, text } of anchors) {\n if (!href || href.startsWith('#') || href.startsWith('javascript:'))\n continue;\n\n try {\n const url = new URL(href, origin);\n const urlHostname = url.hostname;\n\n const normalizeHost = (host: string) =>\n host.startsWith('www.') ? host.slice(4) : host;\n\n const isInternal =\n normalizeHost(urlHostname) === normalizeHost(targetHostname);\n\n if (isInternal) {\n totalInternalCount++;\n let normalizedPath = url.pathname;\n if (normalizedPath.length > 1 && normalizedPath.endsWith('/')) {\n normalizedPath = normalizedPath.slice(0, -1);\n }\n const normalizedUrl = url.origin + normalizedPath + url.search;\n internalUrls.push(normalizedUrl);\n const path = url.pathname.toLowerCase();\n const hostname = url.hostname.toLowerCase();\n\n const hasLocaleInPath = Object.values(ALL_LOCALES).some((locale) => {\n const localeLower = (locale as string).toLowerCase();\n return (\n path.startsWith(`/${localeLower}/`) ||\n path === `/${localeLower}` ||\n path.includes(`/${localeLower}/`)\n );\n });\n\n const hasLocaleInSubdomain = Object.values(ALL_LOCALES).some(\n (locale) => {\n const localeLower = (locale as string).toLowerCase();\n return (\n hostname.startsWith(`${localeLower}.`) ||\n hostname.includes(`.${localeLower}.`)\n );\n }\n );\n\n const linkHtml = `\\`\\`\\`\\`html\\n<a href='${href}'>${text || 'Link'}</a>\\n\\`\\`\\``;\n\n if (hasLocaleInPath || hasLocaleInSubdomain) {\n localizedCount++;\n localizedLinks.push(linkHtml);\n } else {\n nonLocalizedLinks.push(linkHtml);\n }\n }\n } catch {\n // ignore invalid URLs\n }\n }\n\n const hasLocalizedLinks = localizedCount > 0;\n const allAnchorsLocalized =\n totalInternalCount === 0 || localizedCount === totalInternalCount;\n\n let urlStructureLocalized: 'none' | 'path-based' | 'subdomain-based' = 'none';\n if (hasLocalizedLinks) {\n urlStructureLocalized = 'path-based';\n }\n\n return {\n urlStructureLocalized,\n hasLocalizedLinks,\n allAnchorsLocalized,\n totalInternalCount,\n localizedCount,\n localizedLinks,\n nonLocalizedLinks,\n internalUrls: Array.from(new Set(internalUrls)),\n };\n};\n"],"mappings":";;;AAEA,MAAa,sBAAsB,OAAO,MAAW,WAAmB;CACtE,MAAM,iBAAiB,IAAI,IAAI,OAAO,CAAC;CAEvC,MAAM,UAA4C,MAAM,KAAK,OAC3D,YACC,UACC,MAAM,KAAK,OAAO;EAChB,MAAM,EAAE,aAAa,OAAO;EAC5B,MAAM,EAAE,WAAW,MAAM,IAAI;EAC9B,EAAE,CACN;CAED,IAAI,iBAAiB;CACrB,IAAI,qBAAqB;CACzB,MAAM,iBAA2B,EAAE;CACnC,MAAM,oBAA8B,EAAE;CACtC,MAAM,eAAyB,EAAE;AAEjC,MAAK,MAAM,EAAE,MAAM,UAAU,SAAS;AACpC,MAAI,CAAC,QAAQ,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,cAAc,CACjE;AAEF,MAAI;GACF,MAAM,MAAM,IAAI,IAAI,MAAM,OAAO;GACjC,MAAM,cAAc,IAAI;GAExB,MAAM,iBAAiB,SACrB,KAAK,WAAW,OAAO,GAAG,KAAK,MAAM,EAAE,GAAG;AAK5C,OAFE,cAAc,YAAY,KAAK,cAAc,eAAe,EAE9C;AACd;IACA,IAAI,iBAAiB,IAAI;AACzB,QAAI,eAAe,SAAS,KAAK,eAAe,SAAS,IAAI,CAC3D,kBAAiB,eAAe,MAAM,GAAG,GAAG;IAE9C,MAAM,gBAAgB,IAAI,SAAS,iBAAiB,IAAI;AACxD,iBAAa,KAAK,cAAc;IAChC,MAAM,OAAO,IAAI,SAAS,aAAa;IACvC,MAAM,WAAW,IAAI,SAAS,aAAa;IAE3C,MAAM,kBAAkB,OAAO,OAAO,YAAY,CAAC,MAAM,WAAW;KAClE,MAAM,cAAe,OAAkB,aAAa;AACpD,YACE,KAAK,WAAW,IAAI,YAAY,GAAG,IACnC,SAAS,IAAI,iBACb,KAAK,SAAS,IAAI,YAAY,GAAG;MAEnC;IAEF,MAAM,uBAAuB,OAAO,OAAO,YAAY,CAAC,MACrD,WAAW;KACV,MAAM,cAAe,OAAkB,aAAa;AACpD,YACE,SAAS,WAAW,GAAG,YAAY,GAAG,IACtC,SAAS,SAAS,IAAI,YAAY,GAAG;MAG1C;IAED,MAAM,WAAW,0BAA0B,KAAK,IAAI,QAAQ,OAAO;AAEnE,QAAI,mBAAmB,sBAAsB;AAC3C;AACA,oBAAe,KAAK,SAAS;UAE7B,mBAAkB,KAAK,SAAS;;UAG9B;;CAKV,MAAM,oBAAoB,iBAAiB;CAC3C,MAAM,sBACJ,uBAAuB,KAAK,mBAAmB;CAEjD,IAAI,wBAAmE;AACvE,KAAI,kBACF,yBAAwB;AAG1B,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA,cAAc,MAAM,KAAK,IAAI,IAAI,aAAa,CAAC;EAChD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calculateScore.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/calculateScore.ts"],"sourcesContent":["import { logger } from '@logger';\nimport type { AuditEvent } from '../types';\n\nexport type Score = {\n score: number;\n totalScore: number;\n};\n\nconst scoreCheck = (score: number, event: AuditEvent): number => {\n if (event.status === 'success') return score;\n if (event.status === 'warning') return score / 2;\n if (event.status === 'error') return 0;\n return score;\n};\n\nconst scoreRecord = {\n robots_robotsPresent: 10,\n robots_noLocalizedUrlsForgotten: 8,\n sitemap_sitemapPresent: 10,\n sitemap_noLocalizedUrlsForgotten: 9,\n sitemap_hasAlternates: 8,\n sitemap_hasXDefault: 7,\n url_htmlLang: 9,\n url_htmlDir: 3,\n url_hasCanonical: 10,\n url_hreflang: 9,\n url_hasLocalizedLinks: 8,\n url_hasXDefault: 7,\n url_allAnchorsLocalized: 6,\n url_currentLocale: 3,\n url_unusedBundleContent: 8,\n};\n\nexport const mutateScore = (score: Score, event: AuditEvent): Score => {\n const newScore: Score = { ...score };\n\n const typeWithoutUrl = event.type?.split('\\\\')[0];\n\n if (!typeWithoutUrl) {\n return newScore;\n }\n\n const scoreValue = scoreRecord[typeWithoutUrl as keyof typeof scoreRecord];\n\n if (typeof scoreValue === 'number') {\n newScore.score += scoreCheck(scoreValue, event);\n newScore.totalScore += scoreValue;\n }\n\n logger.info('Score mutation', {\n type: event.type,\n typeWithoutUrl,\n scoreValue,\n newScore,\n });\n\n return newScore;\n};\n"],"mappings":";;;AAQA,MAAM,cAAc,OAAe,UAA8B;
|
|
1
|
+
{"version":3,"file":"calculateScore.mjs","names":[],"sources":["../../../../../src/services/audit/analysis/calculateScore.ts"],"sourcesContent":["import { logger } from '@logger';\nimport type { AuditEvent } from '../types';\n\nexport type Score = {\n score: number;\n totalScore: number;\n};\n\nconst scoreCheck = (score: number, event: AuditEvent): number => {\n if (event.status === 'success') return score;\n if (event.status === 'warning') return score / 2;\n if (event.status === 'error') return 0;\n return score;\n};\n\nconst scoreRecord = {\n robots_robotsPresent: 10,\n robots_noLocalizedUrlsForgotten: 8,\n sitemap_sitemapPresent: 10,\n sitemap_noLocalizedUrlsForgotten: 9,\n sitemap_hasAlternates: 8,\n sitemap_hasXDefault: 7,\n url_htmlLang: 9,\n url_htmlDir: 3,\n url_hasCanonical: 10,\n url_hreflang: 9,\n url_hasLocalizedLinks: 8,\n url_hasXDefault: 7,\n url_allAnchorsLocalized: 6,\n url_currentLocale: 3,\n url_unusedBundleContent: 8,\n};\n\nexport const mutateScore = (score: Score, event: AuditEvent): Score => {\n const newScore: Score = { ...score };\n\n const typeWithoutUrl = event.type?.split('\\\\')[0];\n\n if (!typeWithoutUrl) {\n return newScore;\n }\n\n const scoreValue = scoreRecord[typeWithoutUrl as keyof typeof scoreRecord];\n\n if (typeof scoreValue === 'number') {\n newScore.score += scoreCheck(scoreValue, event);\n newScore.totalScore += scoreValue;\n }\n\n logger.info('Score mutation', {\n type: event.type,\n typeWithoutUrl,\n scoreValue,\n newScore,\n });\n\n return newScore;\n};\n"],"mappings":";;;AAQA,MAAM,cAAc,OAAe,UAA8B;AAC/D,KAAI,MAAM,WAAW,UAAW,QAAO;AACvC,KAAI,MAAM,WAAW,UAAW,QAAO,QAAQ;AAC/C,KAAI,MAAM,WAAW,QAAS,QAAO;AACrC,QAAO;;AAGT,MAAM,cAAc;CAClB,sBAAsB;CACtB,iCAAiC;CACjC,wBAAwB;CACxB,kCAAkC;CAClC,uBAAuB;CACvB,qBAAqB;CACrB,cAAc;CACd,aAAa;CACb,kBAAkB;CAClB,cAAc;CACd,uBAAuB;CACvB,iBAAiB;CACjB,yBAAyB;CACzB,mBAAmB;CACnB,yBAAyB;CAC1B;AAED,MAAa,eAAe,OAAc,UAA6B;CACrE,MAAM,WAAkB,EAAE,GAAG,OAAO;CAEpC,MAAM,iBAAiB,MAAM,MAAM,MAAM,KAAK,CAAC;AAE/C,KAAI,CAAC,eACH,QAAO;CAGT,MAAM,aAAa,YAAY;AAE/B,KAAI,OAAO,eAAe,UAAU;AAClC,WAAS,SAAS,WAAW,YAAY,MAAM;AAC/C,WAAS,cAAc;;AAGzB,QAAO,KAAK,kBAAkB;EAC5B,MAAM,MAAM;EACZ;EACA;EACA;EACD,CAAC;AAEF,QAAO"}
|