diff --git a/.eslintrc.json b/.eslintrc.json index 8948a31958e..162dc7b5913 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,6 +1,7 @@ { "extends": "eslint:recommended", "rules": { + // "quotes": ["warn", "single", { "avoidEscape": true }], "require-atomic-updates": "off", "block-spacing": [ "error", @@ -118,6 +119,240 @@ "unicode-bom": [ "error", "never" + ], + "no-restricted-properties": [ + "warn", + { + "object": "Promise", + "property": "map", + "message": "Bluebird-specific method 'Promise.map' detected. Suggestion: use native arrays with Promise.all or a library like 'p-map'." + }, + { + "object": "Promise", + "property": "reduce", + "message": "Bluebird-specific method 'Promise.reduce' detected. Suggestion: use Array.reduce plus async/await or a concurrency library." + }, + { + "object": "Promise", + "property": "filter", + "message": "Bluebird-specific method 'Promise.filter' detected. Suggestion: use Array.filter plus async/await or a concurrency library." + }, + { + "object": "Promise", + "property": "each", + "message": "Bluebird-specific method 'Promise.each' detected. Suggestion: use a for-loop/forEach with async/await." + }, + { + "object": "Promise", + "property": "props", + "message": "Bluebird-specific method 'Promise.props' detected. Suggestion: use Promise.all with Object.entries or a custom approach." + }, + { + "object": "Promise", + "property": "join", + "message": "Bluebird-specific method 'Promise.join' detected. Suggestion: use Promise.all([...]) and destructuring in .then." + }, + { + "object": "Promise", + "property": "try", + "message": "Bluebird-specific method 'Promise.try' detected. Suggestion: use a try/catch block or an async function." + }, + { + "object": "Promise", + "property": "attempt", + "message": "Bluebird-specific method 'Promise.attempt' detected. Suggestion: same as 'Promise.try'—use try/catch or async." + }, + { + "object": "Promise", + "property": "method", + "message": "Bluebird-specific method 'Promise.method' detected. Suggestion: define an async function or return a native Promise." + }, + { + "object": "Promise", + "property": "promisify", + "message": "Bluebird-specific method 'Promise.promisify' detected. Suggestion: use native 'util.promisify' or wrap in a new Promise." + }, + { + "object": "Promise", + "property": "promisifyAll", + "message": "Bluebird-specific method 'Promise.promisifyAll' detected. Suggestion: consider 'util.promisify' for each function or a similar library." + }, + { + "object": "Promise", + "property": "fromCallback", + "message": "Bluebird-specific method 'Promise.fromCallback' detected. Suggestion: use new Promise(...) or 'util.promisify'." + }, + { + "object": "Promise", + "property": "coroutine", + "message": "Bluebird-specific method 'Promise.coroutine' detected. Suggestion: use native async/await." + }, + { + "object": "Promise", + "property": "spawn", + "message": "Bluebird-specific method 'Promise.spawn' detected. Suggestion: use native async/await." + }, + { + "object": "Promise", + "property": "using", + "message": "Bluebird-specific method 'Promise.using' detected. Suggestion: use try/finally or a resource-management library." + }, + { + "object": "Promise", + "property": "disposer", + "message": "Bluebird-specific method 'Promise.disposer' detected. Suggestion: use try/finally or a resource-management library." + }, + { + "object": "Promise", + "property": "settle", + "message": "Bluebird-specific method 'Promise.settle' detected. Suggestion: use native 'Promise.allSettled'." + }, + + /* ---------- Same methods on the Bluebird object itself ---------- */ + { + "object": "Bluebird", + "property": "map", + "message": "Bluebird-specific method 'Bluebird.map' detected. Suggestion: use array mapping + Promise.all or 'p-map'." + }, + { + "object": "Bluebird", + "property": "reduce", + "message": "Bluebird-specific method 'Bluebird.reduce' detected. Suggestion: use array reduce + async/await or concurrency library." + }, + { + "object": "Bluebird", + "property": "filter", + "message": "Bluebird-specific method 'Bluebird.filter' detected. Suggestion: use array filter + async/await or concurrency library." + }, + { + "object": "Bluebird", + "property": "each", + "message": "Bluebird-specific method 'Bluebird.each' detected. Suggestion: use a for-loop or forEach + async/await." + }, + { + "object": "Bluebird", + "property": "props", + "message": "Bluebird-specific method 'Bluebird.props' detected. Suggestion: use Promise.all with object entries or a custom approach." + }, + { + "object": "Bluebird", + "property": "join", + "message": "Bluebird-specific method 'Bluebird.join' detected. Suggestion: use Promise.all([...]) and destructuring." + }, + { + "object": "Bluebird", + "property": "try", + "message": "Bluebird-specific method 'Bluebird.try' detected. Suggestion: use a try/catch block or async function." + }, + { + "object": "Bluebird", + "property": "attempt", + "message": "Bluebird-specific method 'Bluebird.attempt' detected. Suggestion: use a try/catch block or async function." + }, + { + "object": "Bluebird", + "property": "method", + "message": "Bluebird-specific method 'Bluebird.method' detected. Suggestion: define an async function or return a native Promise." + }, + { + "object": "Bluebird", + "property": "promisify", + "message": "Bluebird-specific method 'Bluebird.promisify' detected. Suggestion: use native 'util.promisify' or wrap in a new Promise." + }, + { + "object": "Bluebird", + "property": "promisifyAll", + "message": "Bluebird-specific method 'Bluebird.promisifyAll' detected. Suggestion: consider 'util.promisify' or a similar library." + }, + { + "object": "Bluebird", + "property": "fromCallback", + "message": "Bluebird-specific method 'Bluebird.fromCallback' detected. Suggestion: use new Promise(...) or 'util.promisify'." + }, + { + "object": "Bluebird", + "property": "coroutine", + "message": "Bluebird-specific method 'Bluebird.coroutine' detected. Suggestion: use native async/await." + }, + { + "object": "Bluebird", + "property": "spawn", + "message": "Bluebird-specific method 'Bluebird.spawn' detected. Suggestion: use native async/await." + }, + { + "object": "Bluebird", + "property": "using", + "message": "Bluebird-specific method 'Bluebird.using' detected. Suggestion: use try/finally or a resource-management library." + }, + { + "object": "Bluebird", + "property": "disposer", + "message": "Bluebird-specific method 'Bluebird.disposer' detected. Suggestion: use try/finally or a resource-management library." + }, + { + "object": "Bluebird", + "property": "settle", + "message": "Bluebird-specific method 'Bluebird.settle' detected. Suggestion: use native 'Promise.allSettled'." + } + ], + "no-restricted-syntax": [ + "warn", + { + "selector": "CallExpression[callee.property.name='tap']", + "message": "Bluebird-specific instance method '.tap()' detected. Suggestion: use '.then(value => { ...; return value; })'." + }, + { + "selector": "CallExpression[callee.property.name='tapCatch']", + "message": "Bluebird-specific instance method '.tapCatch()' detected. Suggestion: use '.catch(error => { ...; throw error; })'." + }, + { + "selector": "CallExpression[callee.property.name='spread']", + "message": "Bluebird-specific instance method '.spread()' detected. Suggestion: use '.then(([a, b]) => ... )' with array destructuring." + }, + { + "selector": "CallExpression[callee.type='MemberExpression'][callee.property.name='bind'][callee.object.name=/^(Promise|Bluebird|BPromise)$/]", + "message": "Bluebird-specific '.bind()' detected on a Bluebird promise. Suggestion: manually bind 'this' or use arrow functions." + }, + { + "selector": "CallExpression[callee.property.name='delay']", + "message": "Bluebird-specific instance method '.delay()' detected. Suggestion: use setTimeout() or a library (e.g., p-delay)." + }, + { + "selector": "CallExpression[callee.property.name='timeout']", + "message": "Bluebird-specific instance method '.timeout()' detected. Suggestion: use p-timeout or similar library." + }, + { + "selector": "CallExpression[callee.property.name='return']", + "message": "Bluebird-specific instance method '.return()' detected. Suggestion: use '.then(() => someValue)' or rewrite chain." + }, + { + "selector": "CallExpression[callee.property.name='throw']", + "message": "Bluebird-specific instance method '.throw()' detected. Suggestion: use '.then(() => { throw error; })'." + }, + { + "selector": "CallExpression[callee.property.name='asCallback']", + "message": "Bluebird-specific instance method '.asCallback()' detected. Suggestion: use 'util.callbackify' or rewrite manually." + }, + { + "selector": "CallExpression[callee.property.name='nodeify']", + "message": "Bluebird-specific instance method '.nodeify()' detected. Suggestion: use 'util.callbackify' or rewrite manually." + }, + { + "selector": "CallExpression[callee.property.name='reflect']", + "message": "Bluebird-specific instance method '.reflect()' detected. Suggestion: use 'Promise.allSettled' or custom handling." + }, + { + "selector": "CallExpression[callee.property.name='caught']", + "message": "Bluebird-specific instance method '.caught()' detected. Suggestion: use '.catch()' with condition or separate logic." + }, + { + "selector": "CallExpression[callee.property.name='catchReturn']", + "message": "Bluebird-specific instance method '.catchReturn()' detected. Suggestion: use '.catch(err => fallbackValue)' or similar." + }, + { + "selector": "CallExpression[callee.property.name='catchThrow']", + "message": "Bluebird-specific instance method '.catchThrow()' detected. Suggestion: use '.catch(err => { throw newError; })'." + } ] }, "overrides": [ @@ -142,28 +377,16 @@ { "files": [ "plugins/content/frontend/content-blocks/**/*.js", - "plugins/journey_engine/frontend/builder/**/*.js", - "plugins/content/frontend/content-blocks/**/*.vue", - "plugins/journey_engine/frontend/builder/**/*.vue" - ], - "plugins": [ - "vue", - "@stylistic" + "plugins/journey_engine/frontend/builder/**/*.js" ], "extends": [ - "eslint:recommended", - "plugin:vue/vue3-essential", - "plugin:vue/vue3-strongly-recommended", - "plugin:vue/vue3-recommended" + "eslint:recommended" ], "rules": { - // override these post initial content release, to make them fit with countly convention "no-console": ["error"], - "@stylistic/quotes": ["error", "single"], - "@stylistic/quote-props": ["error", "as-needed"], - "no-unused-vars": "off", - "vue/no-unused-vars": ["error", { - "ignorePattern": "^_" + "no-unused-vars": ["error", { + "argsIgnorePattern": "^_", // unused function args + "varsIgnorePattern": "^_" // unused variables }] }, "parserOptions": { diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6e9af8aa073..7101e68dc5a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,318 +1,443 @@ version: 2 updates: -- package-ecosystem: npm - directory: "/" - schedule: - interval: daily - open-pull-requests-limit: 10 - reviewers: - - ar2rsawseen - assignees: - - ar2rsawseen - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/alerts" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/assistant" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/browser" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/compare" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/compliance-hub" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/consolidate" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/crashes" - schedule: - interval: daily - open-pull-requests-limit: 10 - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/dashboards" - schedule: - interval: daily - open-pull-requests-limit: 10 - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/data_migration" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/data-manager" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/dbviewer" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/density" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/desktop" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/enterpriseinfo" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/errorlogs" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/hooks" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/locale" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/logger" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/mobile" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/onboarding" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/plugin-upload" - schedule: - interval: daily - open-pull-requests-limit: 10 - reviewers: - - Cookiezaurs - assignees: - - Cookiezaurs - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/plugins" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/populator" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/push" - schedule: - interval: daily - open-pull-requests-limit: 10 - reviewers: - - cihadtekin - assignees: - - cihadtekin - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/recaptcha" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/remote-config" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/reports" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/server-stats" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/slipping-away-users" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/sources" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/star-rating" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/system-utility" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/systemlogs" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/times-of-day" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/two-factor-auth" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/views" - schedule: - interval: daily - open-pull-requests-limit: 10 - reviewers: - - Cookiezaurs - assignees: - - Cookiezaurs - labels: - - dependencies - versioning-strategy: increase-if-necessary -- package-ecosystem: npm - directory: "/plugins/web" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - versioning-strategy: increase-if-necessary + # NPM dependencies + - package-ecosystem: npm + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 + reviewers: + - ar2rsawseen + assignees: + - ar2rsawseen + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/ui-tests" + schedule: + interval: daily + open-pull-requests-limit: 10 + reviewers: + - can-angun + assignees: + - can-angun + labels: + - dependencies + versioning-strategy: increase-if-necessary + + # API utilities + - package-ecosystem: npm + directory: "/api/utils/countly-request" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/api/utils/countly-root" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + # Scripts + - package-ecosystem: npm + directory: "/bin/scripts/device_list" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/bin/scripts/timezones" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + # Plugins + - package-ecosystem: npm + directory: "/plugins/alerts" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/browser" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/compare" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/compliance-hub" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/consolidate" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/crashes" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/dashboards" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/data_migration" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/data-manager" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/dbviewer" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/density" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/desktop" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/enterpriseinfo" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/errorlogs" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/guides" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/hooks" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/ip_store" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/locale" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/logger" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/mobile" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/onboarding" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/plugins" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/populator" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/push" + schedule: + interval: daily + open-pull-requests-limit: 10 + reviewers: + - cihadtekin + assignees: + - cihadtekin + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/recaptcha" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/remote-config" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/reports" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/sdk" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/server-stats" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/slipping-away-users" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/sources" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/star-rating" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/system-utility" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/systemlogs" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/times-of-day" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/two-factor-auth" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/views" + schedule: + interval: daily + open-pull-requests-limit: 10 + reviewers: + - Cookiezaurs + assignees: + - Cookiezaurs + labels: + - dependencies + versioning-strategy: increase-if-necessary + + - package-ecosystem: npm + directory: "/plugins/web" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + versioning-strategy: increase-if-necessary + + # Keep GitHub Actions up to date + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + labels: + - "dependencies" + - "github-actions" + reviewers: + - "ar2rsawseen" + groups: + actions: + patterns: + - "*" + + # Keep Docker dependencies up to date + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "weekly" + labels: + - "dependencies" + - "docker" + reviewers: + - "ar2rsawseen" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7b673659d1a..e650cdacc1d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -37,11 +37,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -52,7 +52,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -66,4 +66,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 73a66a78ecc..6deaa4f28db 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -19,7 +19,7 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Enable command line shell: bash @@ -45,16 +45,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Log in to Docker Hub - uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push Docker image - uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 with: push: true file: ./Dockerfile-core diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 48f66a2d308..d953ad414ac 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set output id: vars @@ -26,13 +26,13 @@ jobs: echo ${{ steps.vars.outputs.tag }} - name: Log in to Docker Hub - uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push Docker image - uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 with: context: . push: true @@ -43,7 +43,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set output id: vars @@ -57,13 +57,13 @@ jobs: echo ${{ steps.vars.outputs.tag }} - name: Log in to Docker Hub - uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push Docker image - uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 with: push: true file: ./Dockerfile-api @@ -74,7 +74,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set output id: vars @@ -88,13 +88,13 @@ jobs: echo ${{ steps.vars.outputs.tag }} - name: Log in to Docker Hub - uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push Docker image - uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 with: push: true file: ./Dockerfile-frontend @@ -105,7 +105,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set output id: vars @@ -119,13 +119,13 @@ jobs: echo ${{ steps.vars.outputs.tag }} - name: Log in to Docker Hub - uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push Docker image - uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 with: push: true file: ./Dockerfile-core diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1c5a2fcecd0..71f1c39272d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,7 +26,7 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Copy code shell: bash @@ -96,7 +96,7 @@ jobs: COUNTLY_CONFIG_API_PREVENT_JOBS: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Copy code shell: bash @@ -153,7 +153,7 @@ jobs: COUNTLY_CONFIG_API_PREVENT_JOBS: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Prepare tests shell: bash @@ -205,7 +205,7 @@ jobs: COUNTLY_CONFIG_API_PREVENT_JOBS: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Copy code shell: bash @@ -263,7 +263,7 @@ jobs: COUNTLY_CONFIG_API_PREVENT_JOBS: true steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install Chrome shell: bash @@ -346,7 +346,7 @@ jobs: COUNTLY_CONFIG_API_PREVENT_JOBS: true steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install Chrome shell: bash diff --git a/.github/workflows/release_notice.yml b/.github/workflows/release_notice.yml index 0f959e9b5a9..590e85d5f18 100644 --- a/.github/workflows/release_notice.yml +++ b/.github/workflows/release_notice.yml @@ -14,7 +14,7 @@ jobs: run: echo "$GITHUB_CONTEXT" - name: Send custom JSON data to Slack workflow id: slack - uses: slackapi/slack-github-action@v1.23.0 + uses: slackapi/slack-github-action@v2.0.0 with: # This data can be any valid JSON from a previous step in the GitHub Action payload: | @@ -28,7 +28,7 @@ jobs: env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_RELEASE }} - name: Send custom JSON data to Discord - uses: sarisia/actions-status-discord@v1.13.0 + uses: sarisia/actions-status-discord@v1.15.3 with: webhook: ${{ secrets.DISCORD_WEBHOOK_URL }} nodetail: true diff --git a/.github/workflows/stable-je-deploy.yml b/.github/workflows/stable-je-deploy.yml index 6393bd70357..e7fbe5ab92e 100644 --- a/.github/workflows/stable-je-deploy.yml +++ b/.github/workflows/stable-je-deploy.yml @@ -19,7 +19,7 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Deploy server shell: bash diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 00000000000..4af22ddd479 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged --verbose \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f5f8a15156..1936c288197 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ Fixes: - [star-rating] Added missing columns to Rating Widgets table edit - [star-rating] Fix rating score and responses table sorting - [ui] Fix alignment of drawers title and close icon +- [heatmaps] Get heatmap data from new drill events collection + +Fixes: +- [localization] Fixed grammatical errors Dependencies: - Bump countly-sdk-web from 25.1.0 to 25.4.0 diff --git a/api/utils/countly-request/package-lock.json b/api/utils/countly-request/package-lock.json index 57af8f88f04..ddfc8e4f7d7 100644 --- a/api/utils/countly-request/package-lock.json +++ b/api/utils/countly-request/package-lock.json @@ -13,10 +13,39 @@ "hpagent": "^1.2.0" }, "devDependencies": { - "mocha": "^10.8.2", + "mocha": "^11.1.0", "should": "^13.2.3" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -87,12 +116,16 @@ } }, "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { @@ -266,14 +299,81 @@ } }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/clone-response": { @@ -305,6 +405,21 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -378,11 +493,19 @@ "node": ">=0.3.1" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" }, "node_modules/end-of-stream": { "version": "1.4.4", @@ -393,10 +516,11 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -450,12 +574,22 @@ "flat": "cli.js" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, - "license": "ISC" + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/fsevents": { "version": "2.3.2", @@ -476,6 +610,7 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -495,21 +630,21 @@ } }, "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">=12" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -527,6 +662,22 @@ "node": ">= 6" } }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/got": { "version": "11.8.5", "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", @@ -594,25 +745,6 @@ "node": ">=10.19.0" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -639,6 +771,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -685,6 +818,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -749,6 +905,13 @@ "node": ">=8" } }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -770,10 +933,20 @@ "node": ">=10" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mocha": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", - "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz", + "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==", "dev": true, "license": "MIT", "dependencies": { @@ -784,7 +957,7 @@ "diff": "^5.2.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", - "glob": "^8.1.0", + "glob": "^10.4.5", "he": "^1.2.0", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", @@ -794,8 +967,8 @@ "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" }, "bin": { @@ -803,7 +976,7 @@ "mocha": "bin/mocha.js" }, "engines": { - "node": ">= 14.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/ms": { @@ -878,6 +1051,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -887,6 +1067,33 @@ "node": ">=8" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -946,6 +1153,7 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -997,6 +1205,29 @@ "randombytes": "^2.1.0" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/should": { "version": "13.2.3", "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", @@ -1051,11 +1282,44 @@ "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", "dev": true }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -1065,11 +1329,59 @@ "node": ">=8" } }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -1077,6 +1389,16 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -1116,6 +1438,22 @@ "node": ">=8.0" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/workerpool": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", @@ -1124,10 +1462,30 @@ "license": "Apache-2.0" }, "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -1140,6 +1498,64 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -1150,36 +1566,38 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-unparser": { @@ -1197,6 +1615,51 @@ "node": ">=10" } }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/api/utils/countly-request/package.json b/api/utils/countly-request/package.json index 3c5080bdb45..df7ab76f5a2 100644 --- a/api/utils/countly-request/package.json +++ b/api/utils/countly-request/package.json @@ -18,7 +18,7 @@ "hpagent": "^1.2.0" }, "devDependencies": { - "mocha": "^10.8.2", + "mocha": "^11.1.0", "should": "^13.2.3" } } diff --git a/bin/scripts/localization/clean-all-plugins.sh b/bin/scripts/localization/clean-all-plugins.sh new file mode 100755 index 00000000000..128e4066412 --- /dev/null +++ b/bin/scripts/localization/clean-all-plugins.sh @@ -0,0 +1,236 @@ +#!/bin/bash + +# Script to clean unused localization keys from all Countly plugins +# This script iterates through each plugin in the plugins directory +# and runs the clean-localization.sh script on each one + +# Don't exit on error, we want to process all plugins even if some fail +set +e + +# Correct path detection +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +COUNTLY_ROOT="$(cd "$SCRIPT_DIR/../../.." &> /dev/null && pwd )" # Go up three levels from bin/scripts/localization to countly root +PLUGINS_DIR="$COUNTLY_ROOT/plugins" +CLEAN_SCRIPT="$SCRIPT_DIR/clean-localization.sh" + +# Print paths for debugging +echo "COUNTLY_ROOT: $COUNTLY_ROOT" +echo "PLUGINS_DIR: $PLUGINS_DIR" + +# Default values +APPLY_CHANGES=false +SKIP_CONFIRMATION=false +VERBOSE=false +INCLUDE_PATTERN="" +EXCLUDE_PATTERN="" +DEBUG=false + +# Print usage +function print_usage { + echo "Usage: $0 [options]" + echo + echo "Options:" + echo " --apply Automatically apply changes to the original properties files" + echo " --force Skip confirmation when applying changes" + echo " --verbose Show more detailed output" + echo " --debug Show debug information about the script execution" + echo " --include=PATTERN Only process plugins matching the pattern (grep -E format)" + echo " --exclude=PATTERN Skip plugins matching the pattern (grep -E format)" + echo " --help, -h Show this help message" + echo + echo "Examples:" + echo " $0 # Check all plugins" + echo " $0 --apply # Check and apply changes to all plugins" + echo " $0 --apply --force # Check and apply changes without confirmation" + echo " $0 --include='^(alerts|surveys)$' # Only process alerts and surveys plugins" + echo " $0 --exclude='^empty$' # Process all plugins except 'empty'" + echo " $0 --debug # Show debug information" +} + +# Parse arguments +for arg in "$@"; do + case $arg in + --apply) + APPLY_CHANGES=true + ;; + --force) + SKIP_CONFIRMATION=true + ;; + --verbose) + VERBOSE=true + ;; + --debug) + DEBUG=true + ;; + --include=*) + INCLUDE_PATTERN="${arg#*=}" + ;; + --exclude=*) + EXCLUDE_PATTERN="${arg#*=}" + ;; + --help|-h) + print_usage + exit 0 + ;; + -*) + echo "Unknown option: $arg" + print_usage + exit 1 + ;; + esac +done + +# Debug check +if [ "$DEBUG" = true ]; then + echo "DEBUG: Script location: $SCRIPT_DIR" + echo "DEBUG: Clean script path: $CLEAN_SCRIPT" + echo "DEBUG: Script options:" + echo " APPLY_CHANGES: $APPLY_CHANGES" + echo " SKIP_CONFIRMATION: $SKIP_CONFIRMATION" + echo " VERBOSE: $VERBOSE" + echo " DEBUG: $DEBUG" + echo " INCLUDE_PATTERN: $INCLUDE_PATTERN" + echo " EXCLUDE_PATTERN: $EXCLUDE_PATTERN" + # Check if the Node.js script exists + if [ -f "$CLEAN_SCRIPT" ]; then + echo "DEBUG: Clean localization script found at $CLEAN_SCRIPT" + else + echo "ERROR: Clean localization script NOT found at $CLEAN_SCRIPT" + exit 1 + fi + # Check Node.js version + echo "DEBUG: Node.js version: $(node --version)" + echo +fi + +# Prepare arguments for the clean-localization.sh script +CLEAN_ARGS=() +if [ "$APPLY_CHANGES" = true ]; then + CLEAN_ARGS+=("--apply") +fi +if [ "$SKIP_CONFIRMATION" = true ]; then + CLEAN_ARGS+=("--force") +fi + +# Check if plugins directory exists +if [ ! -d "$PLUGINS_DIR" ]; then + echo "Error: Plugins directory not found at $PLUGINS_DIR" + exit 1 +fi + +# Collect all plugin directories +echo "Scanning for plugins in $PLUGINS_DIR..." +PLUGINS=() +for plugin_dir in "$PLUGINS_DIR"/*; do + if [ -d "$plugin_dir" ]; then + plugin_name=$(basename "$plugin_dir") + + # Apply include pattern if specified + if [ -n "$INCLUDE_PATTERN" ]; then + if ! echo "$plugin_name" | grep -Eq "$INCLUDE_PATTERN"; then + [ "$VERBOSE" = true ] && echo "Skipping plugin '$plugin_name' (not matching include pattern)" + continue + fi + fi + + # Apply exclude pattern if specified + if [ -n "$EXCLUDE_PATTERN" ]; then + if echo "$plugin_name" | grep -Eq "$EXCLUDE_PATTERN"; then + [ "$VERBOSE" = true ] && echo "Skipping plugin '$plugin_name' (matching exclude pattern)" + continue + fi + fi + + PLUGINS+=("$plugin_name") + fi +done + +echo "Found ${#PLUGINS[@]} plugins to process" +echo + +# Process each plugin +PROCESSED=0 +SUCCESS=0 +FAILED=0 +WITH_UNUSED_KEYS=0 +FAILED_PLUGINS=() + +for plugin in "${PLUGINS[@]}"; do + echo "================================================================================" + echo "Processing plugin: $plugin ($(( PROCESSED + 1 ))/${#PLUGINS[@]})" + echo "================================================================================" + + # Check if the plugin has a localization directory + LOCALIZATION_DIR="$PLUGINS_DIR/$plugin/frontend/public/localization" + if [ ! -d "$LOCALIZATION_DIR" ]; then + echo "Plugin '$plugin' does not have a localization directory. Skipping." + echo + ((PROCESSED++)) + continue + fi + + # Check if the plugin has a properties file + PROPERTIES_FILE="$LOCALIZATION_DIR/$plugin.properties" + if [ ! -f "$PROPERTIES_FILE" ]; then + echo "Plugin '$plugin' does not have a main properties file ($plugin.properties). Skipping." + echo + ((PROCESSED++)) + continue + fi + + # Run the cleanup script on this plugin + if [ "$DEBUG" = true ]; then + # shellcheck disable=SC2145 + echo "DEBUG: Running command: $CLEAN_SCRIPT $plugin ${CLEAN_ARGS[@]}" + fi + + if [ "$VERBOSE" = true ]; then + # In verbose mode, run directly to show real-time output + "$CLEAN_SCRIPT" "$plugin" "${CLEAN_ARGS[@]}" + RESULT=$? + else + # In non-verbose mode, capture output to check for unused keys + OUTPUT_FILE=$(mktemp) + "$CLEAN_SCRIPT" "$plugin" "${CLEAN_ARGS[@]}" > "$OUTPUT_FILE" 2>&1 + RESULT=$? + cat "$OUTPUT_FILE" + + # Check if unused keys were found + if grep -q "Found [1-9][0-9]* unused keys" "$OUTPUT_FILE"; then + ((WITH_UNUSED_KEYS++)) + fi + rm "$OUTPUT_FILE" + fi + + # Check result + if [ $RESULT -eq 0 ]; then + ((SUCCESS++)) + else + echo "ERROR: Failed to process plugin $plugin (exit code $RESULT)" + FAILED_PLUGINS+=("$plugin ($RESULT)") + ((FAILED++)) + fi + + ((PROCESSED++)) + echo +done + +echo "================================================================================" +echo "Summary:" +echo "================================================================================" +echo "Total plugins processed: $PROCESSED" +echo "Successful: $SUCCESS" +echo "Failed: $FAILED" +echo "Plugins with unused keys: $WITH_UNUSED_KEYS" +echo + +if [ $FAILED -gt 0 ]; then + echo "Failed plugins:" + for plugin in "${FAILED_PLUGINS[@]}"; do + echo " - $plugin" + done + echo +fi + +echo "All done!" +exit 0 \ No newline at end of file diff --git a/bin/scripts/localization/clean-localization-keys.js b/bin/scripts/localization/clean-localization-keys.js new file mode 100644 index 00000000000..58c1880d9a5 --- /dev/null +++ b/bin/scripts/localization/clean-localization-keys.js @@ -0,0 +1,249 @@ +/** + * Script to clean unused localization keys from Countly plugin properties files + * + * This script: + * 1. Reads all keys from a plugin's localization properties file + * 2. Scans the entire project to find localization key usage + * 3. Identifies unused keys and creates a new properties file without them + * + * Usage: node clean-localization-keys.js [] + * Example: node clean-localization-keys.js alerts + * node clean-localization-keys.js surveys surveys + */ + +const fs = require('fs'); +const path = require('path'); +const util = require('util'); + +const readFile = util.promisify(fs.readFile); +const writeFile = util.promisify(fs.writeFile); +const readdir = util.promisify(fs.readdir); +const access = util.promisify(fs.access); + +// Get plugin name from command line arguments +const pluginName = process.argv[2]; +// Get properties file name (defaults to plugin name if not provided) +const propertiesFileName = process.argv[3] || pluginName; + +// Check if plugin name was provided +if (!pluginName) { + console.error('Error: No plugin name provided'); + console.error('Usage: node clean-localization-keys.js []'); + console.error('Example: node clean-localization-keys.js alerts'); + console.error(' node clean-localization-keys.js surveys surveys'); + process.exit(1); +} + +// Define paths - fixed to correctly reference the root directory +const scriptDir = __dirname; +const countlyRoot = path.resolve(scriptDir, '../../..'); // Go up three levels from bin/scripts/localization +const pluginPath = path.join(countlyRoot, 'plugins', pluginName); +const localizationPath = path.join(pluginPath, 'frontend', 'public', 'localization', `${propertiesFileName}.properties`); + +// Check if plugin directory exists +(async function() { + try { + await access(pluginPath, fs.constants.F_OK); + } + catch (err) { + console.error(`Error: Plugin '${pluginName}' not found at ${pluginPath}`); + process.exit(1); + } + + // Check if properties file exists + try { + await access(localizationPath, fs.constants.F_OK); + } + catch (err) { + console.error(`Error: Properties file not found at ${localizationPath}`); + console.error(`Make sure the plugin has a localization file at: frontend/public/localization/${propertiesFileName}.properties`); + process.exit(1); + } + + await cleanUnusedKeys(); +})(); + +/** + * Recursively get all JavaScript and HTML files in a directory and its subdirectories + * @param {string} dir - Directory path + * @param {Array} extensions - Array of file extensions to include (e.g., ['.js', '.html']) + * @param {Array} excludeDirs - Array of directory names to exclude + * @returns {Promise} - Array of file paths + */ +async function getFilesWithExtensions(dir, extensions, excludeDirs = ['node_modules', '.git']) { + try { + const entries = await readdir(dir, { withFileTypes: true }); + const files = await Promise.all(entries.map(async(entry) => { + const fullPath = path.resolve(dir, entry.name); + + try { + if (entry.isDirectory()) { + if (excludeDirs.includes(entry.name)) { + return []; + } + return getFilesWithExtensions(fullPath, extensions, excludeDirs); + } + + if (extensions.some(ext => entry.name.endsWith(ext))) { + return [fullPath]; + } + return []; + } + catch (err) { + console.warn(`Warning: Could not process ${fullPath}: ${err.message}`); + return []; + } + })); + return files.flat(); + } + catch (err) { + console.warn(`Warning: Could not read directory ${dir}: ${err.message}`); + return []; + } +} + +/** + * Extract keys from properties file + * @param {string} filePath - Path to properties file + * @returns {Promise} - Map of key to value and line number + */ +async function extractKeysFromProperties(filePath) { + const content = await readFile(filePath, 'utf8'); + const lines = content.split('\n'); + + const keys = {}; + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + if (line.trim() === '' || line.trim().startsWith('#')) { + continue; // Skip empty lines and comments + } + + const equalPos = line.indexOf('='); + if (equalPos > 0) { + const key = line.substring(0, equalPos).trim(); + const value = line.substring(equalPos + 1).trim(); + keys[key] = { value, lineNumber: i }; + } + } + + return keys; +} + +/** + * Check if a key is used anywhere in the project + * @param {string} key - The localization key + * @param {string[]} files - List of files to check + * @returns {Promise} - Whether the key is used + */ +async function isKeyUsed(key, files) { + // Different patterns for how keys might be used in the code + const patterns = [ + `["${key}"]`, // jQuery.i18n.map["key"] + `['${key}']`, // jQuery.i18n.map['key'] + `"${key}"`, // In various contexts + `'${key}'`, // In various contexts + `\`${key}\``, // Template literals + `data-localize="${key}"`, // HTML data-localize attribute + `data-localize='${key}'` // HTML data-localize attribute with single quotes + ]; + + for (const file of files) { + try { + const content = await readFile(file, 'utf8'); + + for (const pattern of patterns) { + if (content.includes(pattern)) { + // Found usage, return true immediately + return true; + } + } + } + catch (err) { + console.warn(`Warning: Could not read file ${file}: ${err.message}`); + } + } + + return false; +} + +/** + * Create a new properties file without unused keys + * @param {Object} keys - Map of all keys + * @param {string[]} unusedKeys - List of unused keys + * @param {string} filePath - Path to original properties file + */ +async function createCleanedProperties(keys, unusedKeys, filePath) { + const content = await readFile(filePath, 'utf8'); + const lines = content.split('\n'); + + // Mark lines that contain unused keys for removal + const linesToRemove = new Set(); + for (const key of unusedKeys) { + if (keys[key]) { + linesToRemove.add(keys[key].lineNumber); + } + } + + // Create new content without the unused keys + const newLines = lines.filter((_, i) => !linesToRemove.has(i)); + + // Write the new content back to the file + const newPath = path.join(path.dirname(filePath), `${path.basename(filePath)}.clean`); + await writeFile(newPath, newLines.join('\n')); + return newPath; +} + +/** + * Main function that runs the cleanup + */ +async function cleanUnusedKeys() { + try { + console.log(`Scanning files for unused localization keys in plugin: ${pluginName}...`); + + // Get relevant files across the entire project (JS, HTML files) + const projectFiles = await getFilesWithExtensions(countlyRoot, ['.js', '.html', '.hbs', '.ejs', '.vue'], ['node_modules', '.git', 'dump', 'log']); + console.log(`Found ${projectFiles.length} relevant files to scan across the project.`); + + // Extract keys from properties file + const keys = await extractKeysFromProperties(localizationPath); + console.log(`Found ${Object.keys(keys).length} localization keys in ${propertiesFileName}.properties.`); + + // Find unused keys + const unusedKeys = []; + let checkedCount = 0; + + for (const key of Object.keys(keys)) { + const isUsed = await isKeyUsed(key, projectFiles); + if (!isUsed) { + unusedKeys.push(key); + } + + // Show progress + checkedCount++; + if (checkedCount % 10 === 0 || checkedCount === Object.keys(keys).length) { + process.stdout.write(`\rChecked ${checkedCount}/${Object.keys(keys).length} keys...`); + } + } + console.log(); // New line after progress + + console.log(`Found ${unusedKeys.length} unused keys.`); + + if (unusedKeys.length > 0) { + console.log('Unused keys:'); + unusedKeys.forEach(key => { + console.log(`- ${key}`); + }); + + // Create a new properties file without the unused keys + const newPath = await createCleanedProperties(keys, unusedKeys, localizationPath); + console.log(`\nCleaned properties file created at: ${newPath}`); + } + else { + console.log('No unused keys found. Great job!'); + } + + } + catch (err) { + console.error('Error:', err); + } +} \ No newline at end of file diff --git a/bin/scripts/localization/clean-localization.sh b/bin/scripts/localization/clean-localization.sh new file mode 100755 index 00000000000..f7fd58af742 --- /dev/null +++ b/bin/scripts/localization/clean-localization.sh @@ -0,0 +1,163 @@ +#!/bin/bash + +# Script to clean unused localization keys from a Countly plugin's properties file +# and automatically apply the changes + +set -e # Exit on error + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +COUNTLY_ROOT="$(cd "$SCRIPT_DIR/../../.." &> /dev/null && pwd )" # Fix: Go up three levels from bin/scripts/localization +PLUGINS_DIR="$COUNTLY_ROOT/plugins" # Fix: Use the plugins directory at the root level + +# Default values +APPLY_CHANGES=false +SKIP_CONFIRMATION=false + +# Print usage +function print_usage { + echo "Usage: $0 [] [--apply] [--force]" + echo + echo "Arguments:" + echo " plugin-name Name of the plugin to scan (required)" + echo " properties-file Name of the properties file without .properties extension" + echo " (defaults to plugin name if not provided)" + echo + echo "Options:" + echo " --apply Automatically apply changes to the original properties file" + echo " --force Skip confirmation when applying changes" + echo + echo "Examples:" + echo " $0 alerts # Check alerts plugin with alerts.properties" + echo " $0 surveys surveys # Check surveys plugin with surveys.properties" + echo " $0 alerts --apply # Check and apply changes to alerts.properties" + echo " $0 alerts --apply --force # Check and apply changes without confirmation" +} + +# Parse arguments +PLUGIN_NAME="" +PROPERTIES_FILE="" +REMAINING_ARGS=() + +for arg in "$@"; do + case $arg in + --apply) + APPLY_CHANGES=true + ;; + --force) + SKIP_CONFIRMATION=true + ;; + --help|-h) + print_usage + exit 0 + ;; + -*) + echo "Unknown option: $arg" + print_usage + exit 1 + ;; + *) + if [ -z "$PLUGIN_NAME" ]; then + PLUGIN_NAME="$arg" + elif [ -z "$PROPERTIES_FILE" ]; then + PROPERTIES_FILE="$arg" + else + REMAINING_ARGS+=("$arg") + fi + ;; + esac +done + +# Check if plugin name was provided +if [ -z "$PLUGIN_NAME" ]; then + echo "Error: No plugin name provided" + print_usage + exit 1 +fi + +# Use plugin name as properties file name if not provided +if [ -z "$PROPERTIES_FILE" ]; then + PROPERTIES_FILE="$PLUGIN_NAME" +fi + +# Define paths +PLUGIN_DIR="$PLUGINS_DIR/$PLUGIN_NAME" +PROPERTIES_PATH="$PLUGIN_DIR/frontend/public/localization/$PROPERTIES_FILE.properties" +BACKUP_PATH="$PROPERTIES_PATH.backup" +CLEAN_PATH="$PROPERTIES_PATH.clean" +NODE_SCRIPT="$SCRIPT_DIR/clean-localization-keys.js" + +# Check if the plugin directory exists +if [ ! -d "$PLUGIN_DIR" ]; then + echo "Error: Plugin directory not found at $PLUGIN_DIR" + exit 1 +fi + +# Check if the properties file exists +if [ ! -f "$PROPERTIES_PATH" ]; then + echo "Error: Properties file not found at $PROPERTIES_PATH" + echo "Make sure the plugin has a localization file at: frontend/public/localization/$PROPERTIES_FILE.properties" + exit 1 +fi + +# Main execution +echo "===== Cleaning unused localization keys from $PROPERTIES_FILE.properties =====" +echo + +# Create a backup of the original file, unless running with --apply --force +if [ "$APPLY_CHANGES" = true ] && [ "$SKIP_CONFIRMATION" = true ]; then + # Skip backup when running with both --apply and --force + echo "Skipping backup creation (running with --apply --force)" +else + echo "Creating backup of original file at $BACKUP_PATH" + cp "$PROPERTIES_PATH" "$BACKUP_PATH" + echo "Backup created successfully." +fi +echo + +# Run the Node.js cleanup script +echo "Running cleanup script..." +node "$NODE_SCRIPT" "$PLUGIN_NAME" "$PROPERTIES_FILE" +echo + +# Check if the cleaned file exists +if [ ! -f "$CLEAN_PATH" ]; then + echo "No changes were applied. The script did not produce a cleaned file." + exit 0 +fi + +# Check if there are any differences +if cmp -s "$PROPERTIES_PATH" "$CLEAN_PATH"; then + echo "No changes detected. The original and cleaned files are identical." + # Remove the clean file since it's the same as the original + rm "$CLEAN_PATH" + exit 0 +fi + +# Apply changes if requested +if [ "$APPLY_CHANGES" = true ]; then + if [ "$SKIP_CONFIRMATION" = false ]; then + echo "Do you want to apply these changes to the original properties file? [y/N]" + read -r response + if [[ ! "$response" =~ ^[Yy]$ ]]; then + echo "Changes not applied. You can find the cleaned file at: $CLEAN_PATH" + exit 0 + fi + fi + + echo "Applying changes to original properties file..." + cp "$CLEAN_PATH" "$PROPERTIES_PATH" + rm "$CLEAN_PATH" + echo "Changes applied successfully." + + # Only mention the backup if we created one + if [ "$SKIP_CONFIRMATION" = false ] || [ "$APPLY_CHANGES" = false ]; then + echo "Original file backed up at: $BACKUP_PATH" + echo "If you need to restore the original file, run: cp $BACKUP_PATH $PROPERTIES_PATH" + fi +else + echo "To apply the changes, use the --apply option or manually copy the cleaned file:" + echo "cp $CLEAN_PATH $PROPERTIES_PATH" +fi + +echo +echo "===== Cleanup process complete! =====" \ No newline at end of file diff --git a/bin/scripts/timezones/package-lock.json b/bin/scripts/timezones/package-lock.json index 8e919c0ad20..2c69b28afbd 100644 --- a/bin/scripts/timezones/package-lock.json +++ b/bin/scripts/timezones/package-lock.json @@ -1,47 +1,126 @@ { "name": "timezones", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 3, "requires": true, - "dependencies": { - "moment": { + "packages": { + "": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "moment-timezone": "0.5.48", + "node-fetch": "3.3.2" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/moment": { "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" - }, - "moment-timezone": { - "version": "0.5.35", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.35.tgz", - "integrity": "sha512-cY/pBOEXepQvlgli06ttCTKcIf8cD1nmNwOKQQAdHBqYApQSpAqotBMX0RJZNgMp6i0PlZuf1mFtnlyEkwyvFw==", - "requires": { - "moment": ">= 2.9.0" - } - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.48", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", + "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", + "license": "MIT", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" } } } diff --git a/bin/scripts/timezones/package.json b/bin/scripts/timezones/package.json index cfdcb1bc2ce..0ba29f8a4cf 100644 --- a/bin/scripts/timezones/package.json +++ b/bin/scripts/timezones/package.json @@ -22,7 +22,7 @@ }, "homepage": "https://count.ly/", "dependencies": { - "moment-timezone": "0.5.35", - "node-fetch": "2.6.7" + "moment-timezone": "0.5.48", + "node-fetch": "3.3.2" } } diff --git a/frontend/express/public/localization/dashboard/dashboard.properties b/frontend/express/public/localization/dashboard/dashboard.properties index d40c7050c0b..aa178f92fea 100644 --- a/frontend/express/public/localization/dashboard/dashboard.properties +++ b/frontend/express/public/localization/dashboard/dashboard.properties @@ -1,10 +1,10 @@ #common common.total-sessions = Total Sessions -common.total-sessions-description = Number of times your application is opened, by new or returning users, in the selected time period. +common.total-sessions-description = The number of times your application is opened by new or returning users within the selected time period. common.new-sessions = New Sessions -common.new-sessions-description = Number of times your application is opened by a new user, in the selected time period. It is equal to the number of New Users and it only counts the first session the user had. +common.new-sessions-description = The number of times your application is opened by a new user within the selected time period. This is equal to the number of New Users and only counts the user's first session. common.unique-sessions = Unique Sessions -common.unique-sessions-description = Number of times your application is opened by a new or returning user from a unique device, in the selected time period. It is equal to the number of Total Users. +common.unique-sessions-description = The number of times your application is opened by a new or returning user from a unique device within the selected time period. This is equal to the number of Total Users. common.total-users = TOTAL USERS common.new-users = NEW USERS common.returning-users = RETURNING USERS @@ -18,15 +18,15 @@ common.table.no-data = No data common.search.no-match-found = No match found common.table.total-users = Total Users common.selected-users = Some specific users -common.table.total-users-desc = The number of users (unique devices/IDs) who have opened your application in the selected time period. +common.table.total-users-desc = The number of users (unique devices/IDs) who have opened your application within the selected time period. web.common.table.total-users = Total Visitors -web.common.table.total-users-desc = The number of visitors (unique devices/IDs) who have visited your website in the selected time period. +web.common.table.total-users-desc = The number of visitors (unique devices/IDs) who have visited your website within the selected time period. common.table.new-users = New Users -common.table.new-users-desc = The number of first-time users (unique devices/IDs) in the selected time period. +common.table.new-users-desc = The number of first-time users (unique devices/IDs) within the selected time period. common.table.returning-users = Returning Users -common.table.returning-users-desc = Number of users using your application for the second or later time, in the selected time period, calculated as Total Users (less) New Users. +common.table.returning-users-desc = The number of users using your application for the second or later time within the selected time period, calculated as Total Users minus New Users. web.common.table.returning-users = Returning Visitors -web.common.table.returning-users-desc = Number of visitors using your website for the second or later time, in the selected time period, calculated as Total Visitors (less) New Visitors. +web.common.table.returning-users-desc = The number of visitors using your website for the second or later time within the selected time period, calculated as Total Visitors minus New Visitors. common.table.total-sessions = Total Sessions common.table.new-sessions = New Sessions common.table.unique-sessions = Unique Sessions @@ -47,27 +47,27 @@ common.yesterday = Yesterday common.previous-period = Previous period common.previous-year = Same period in previous year common.bar.top-resolution = Top Resolutions -common.bar.top-resolution.description = Top 5 resolution settings of the devices used your users' sessions, in the selected time period. -web.common.bar.top-resolution.description = Top 5 resolution settings of the devices used your visitors' sessions, in the selected time period. +common.bar.top-resolution.description = The top 5 resolution settings of the devices used in your users' sessions within the selected time period. +web.common.bar.top-resolution.description = The top 5 resolution settings of the devices used in your visitors' sessions within the selected time period. common.bar.top-carrier = Top Carriers common.bar.top-users = TOP USERS common.bar.top-platform = Top Platforms -common.bar.top-platform.description = Top 5 versions of the platforms of your users’ sessions, in the selected time period. -web.common.bar.top-platform.description = Top 5 versions of the platforms of your visitors’ sessions, in the selected time period. +common.bar.top-platform.description = The top 5 platform versions of your users’ sessions within the selected time period. +web.common.bar.top-platform.description = The top 5 platform versions of your visitors’ sessions within the selected time period. common.bar.top-platform-version = Top Platform Versions -common.bar.top-platform-version.description = Top 3 versions of the platforms of your users' sessions, in the selected time period. -web.common.bar.top-platform-version.description = Top 3 versions of the platforms of your visitors' sessions, in the selected time period. +common.bar.top-platform-version.description = The top 3 platform versions of your users' sessions within the selected time period. +web.common.bar.top-platform-version.description = The top 3 platform versions of your visitors' sessions within the selected time period. common.bar.top-devices = Top Devices -common.bar.top-devices.description = Top 5 devices of your users’ based on their sessions, in the selected time period. -web.common.bar.top-devices.description = Top 5 devices of your visitors’ based on their sessions, in the selected time period. +common.bar.top-devices.description = The top 5 devices of your users based on their sessions within the selected time period. +web.common.bar.top-devices.description = The top 5 devices of your visitors based on their sessions within the selected time period. common.bar.top-device-types = Top Device types -common.bar.top-device-types.description = Top 5 device types of your users’ based on their sessions, in the selected time period. -web.common.bar.top-device-types.description = Top 5 device types of your visitors’ based on their sessions, in the selected time period. +common.bar.top-device-types.description = The top 5 device types of your users based on their sessions within the selected time period. +web.common.bar.top-device-types.description = The top 5 device types of your visitors based on their sessions within the selected time period. common.bar.top-browsers = Top Browsers -common.bar.top-browsers.description = Top 5 browsers of your users’ based on their sessions, in the selected time period +common.bar.top-browsers.description = The top 5 browsers of your users based on their sessions within the selected time period. common.bar.top-app-versions = Top App Versions -common.bar.top-app-versions.description = Top 5 App versions of your users’ based on their sessions, in the selected time period. -web.common.bar.top-app-versions.description = Top 5 App versions of your visitors’ based on their sessions, in the selected time period. +common.bar.top-app-versions.description = The top 5 app versions of your users based on their sessions within the selected time period. +web.common.bar.top-app-versions.description = The top 5 app versions of your visitors based on their sessions within the selected time period. common.bar.no-data = No Data common.apply = Apply common.apply-changes = Apply changes @@ -106,7 +106,7 @@ common.started = Started common.info = Information common.save-changes = Save changes common.graph-max = Maximum {0} {1} reached on {2} -common.graph-min = Minumum {0} {1} on {2} +common.graph-min = Minimum {0} {1} on {2} common.graph.time-spent = Time Spent (min) common.graph.average-time = Avg. Time Spent (min) common.graph.reqs-received = Requests Received @@ -161,7 +161,7 @@ common.search = Search common.unknown = Unknown common.eu = European Union common.integrate-sdks = Need some help with SDK integration? -common.integrate-sdks-text = helps you generate personalized code snippets and SDK integration tutorials based on your platforms and Countly features you want to use. +common.integrate-sdks-text = Helps you generate personalized code snippets and SDK integration tutorials based on your platforms and Countly features you want to use. common.integrate-sdks-platforms = Select a platform to get started common.go-to-countries = Go to Countries common.show = Show @@ -251,7 +251,7 @@ common.copy-error-message = Something went wrong, please copy it again. common.created-at-by = Created {0} by {1} common.updated = Updated common.manage = Manage -common.selected-with-count ={0} Selected +common.selected-with-count = {0} Selected common.selected = Selected common.select-all-with-count = Select all {0} common.deselect = Deselect @@ -348,7 +348,7 @@ taskmanager.recalculating = Recalculating #task manager assistent notification strings assistant.taskmanager.longTaskTooLong.title = This request is running for too long. -assistant.taskmanager.longTaskTooLong.message = We have switched it to report manager and will notify you when it is finished. +assistant.taskmanager.longTaskTooLong.message = We have switched it to the report manager and will notify you when it is finished. assistant.taskmanager.longTaskTooLong.info = Check its status in Utilities -> Report Manager assistant.taskmanager.longTaskAlreadyRunning.title = A similar report is already running. assistant.taskmanager.longTaskAlreadyRunning.message = Looks like report with same parameters already running in report manager @@ -409,7 +409,7 @@ sidebar.analytics.carriers = Carriers sidebar.analytics.platforms = Platforms sidebar.analytics.resolutions = Resolutions sidebar.analytics.technology = Technology -sidebar.analytics.technology-description = Overview details of your app or website traffic by your users’ technology, such as platform, device, resolution, browsers and app version. +sidebar.analytics.technology-description = Overview details of your app or website traffic based on your users’ technology, such as platform, device, resolution, browsers, and app version. sidebar.analytics.geo = Geo sidebar.engagement = Engagement sidebar.events = Events @@ -448,7 +448,7 @@ sidebar.banner.upgrade-button = Manage your plan dashboard.apply = Apply dashboard.home-desc = Overview of collected data dashboard.empty-title = Nothing to show -dashboard.empty-text = There are no data to show. Enable features or Customize this page to see data about choosen features. +dashboard.empty-text = There is no data to show. Enable features or customize this page to see data about chosen features. dashboard.audience = Audience dashboard.customize-home = Customize Home dashboard.avg-time-spent = Avg. Session Duration @@ -457,7 +457,7 @@ dashboard.time-spent = Time Spent dashboard.time-spent-desc = Total time spent for this period dashboard.reqs-received = REQUESTS RECEIVED dashboard.avg-reqs-received = Avg. Requests Received -dashboard.avg-reqs-received-desc = Number of write API requests Countly Server receives for each session (includes sessions, session extensions, events, etc) +dashboard.avg-reqs-received-desc = The number of write API requests the Countly Server receives for each session (includes sessions, session extensions, events, etc.). dashboard.bounce-rate = BOUNCE RATE dashboard.pages-per-visit = PAGES PER VISIT dashboard.note-title-remaining = Remaining @@ -469,8 +469,8 @@ users.title = USERS #user-activity user-activity.title = User Activity web.user-activity.title = Visitor Activity -user-activity.description = Overview of the total number of users who started a session on your application, distributed in pre-set categories of numbers of sessions. -web.user-activity.description = Overview of the total number of visitors who started a session on your website, distributed in pre-set categories of numbers of sessions. +user-activity.description = An overview of the total number of users who started a session on your application, distributed in pre-set categories based on the number of sessions. +web.user-activity.description = An overview of the total number of visitors who started a session on your website, distributed in pre-set categories based on the number of sessions. user-activity.barchart-all-users = All Users web.user-activity.barchart-all-users = All Visitors user-activity.barchart-thirty-days = Active Users (30 days) @@ -501,7 +501,7 @@ session-durations.description = Time period(s) for which users have opened your #session-frequency session-frequency.title = Session Frequency -session-frequency.description = Number of times users open your application, in the selected time period, distributed into frequency ranges. +session-frequency.description = The number of times users open your application within the selected time period, distributed into frequency ranges. session-frequency.table.frequency = Time since last session #notes @@ -533,8 +533,8 @@ session-duration.table.duration = Session duration #countries countries.title = Countries -countries.description = An overview of the geographical distribution of your users and their sessions in the selected time period. -web.countries.description = An overview of the geographical distribution of your visitors and their sessions in the selected time period. +countries.description = An overview of the geographical distribution of your users and their sessions within the selected time period. +web.countries.description = An overview of the geographical distribution of your visitors and their sessions within the selected time period. countries.table.country = Country countries.table.city = City countries.back-to-list = Back to Country List @@ -556,8 +556,8 @@ web.user-analytics.overview-title = Visitors Overview #resolutions resolutions.title = Resolutions -resolutions.description = Detailed information on the resolution settings of the devices through which your users access your application, in the selected time period. -web.resolutions.description = Detailed information on the resolution settings of the devices through which your visitors access your website, in the selected time period. +resolutions.description = Detailed information on the resolution settings of the devices through which your users access your application within the selected time period. +web.resolutions.description = Detailed information on the resolution settings of the devices through which your visitors access your website within the selected time period. resolutions.table.resolution = Resolution resolutions.table.width = Width @@ -566,22 +566,22 @@ resolutions.table.height = Height #device_type device_type.title = Devices and Types -device_type.description = Details of the device models and types from which your users access your application, in the selected time period. -web.device_type.description = Details of the device models and types from which your visitors access your website, in the selected time period. +device_type.description = Details of the device models and types from which your users access your application within the selected time period. +web.device_type.description = Details of the device models and types from which your visitors access your website within the selected time period. device_type.table.device_type = Device Type device_type.types = Types device_type.devices = Devices #app-versions app-versions.title = App Versions -app-versions.description = Detailed information on the application versions of your application accessed by your users, in the selected time period. -web.app-versions.description = Detailed information on the website versions of your website accessed by your visitors, in the selected time period. +app-versions.description = Detailed information on the application versions of your application accessed by your users within the selected time period. +web.app-versions.description = Detailed information on the website versions of your website accessed by your visitors within the selected time period. app-versions.table.app-version = App Version #carriers carriers.title = Carriers carriers.table.carrier = Carrier -carriers.description = Detailed information on the network carriers of the devices through which your users access your application, in the selected time period. +carriers.description = Detailed information on the network carriers of the devices through which your users access your application within the selected time period. #platforms platforms.title = Platforms @@ -589,8 +589,8 @@ platforms.pie-right = PLATFORM VERSIONS platforms.table.platform = Platform platforms.table.platform-version = Platform Version platforms.table.platform-version-for = Platform Versions for -platforms.description = Details of the platforms on which yours users access your application, in the selected time period. -web.platforms.description = Details of the platforms on which yours visitors access your website, in the selected time period. +platforms.description = Details of the platforms on which your users access your application within the selected time period. +web.platforms.description = Details of the platforms on which your visitors access your website within the selected time period. platforms.platforms-for = Platforms for platforms.version-distribution = Platforms version distribution platforms.versions = Versions @@ -611,7 +611,7 @@ events.blueprint-events-show.visible = Visible Events events.go-to-events = Go to Events events.blueprint-events-properties-tooltip = Edited properties of this event will be updated on All Events and other plugins. -events.blueprint-event-groups-include-events-tooltip = Select at least 2 events to create an Event Group. New Event Groups will automatically sum all the selected event properties and report them. +events.blueprint-event-groups-include-events-tooltip = Select at least 2 events to create an Event Group. New Event Groups will automatically sum all the selected event properties and report them. events.blueprint-event-groups-properties-tooltip = Edited properties in this Event Group will be updated across All Events and other plugins. events.blueprint-event-group-included-events = INCLUDED EVENTS @@ -646,7 +646,7 @@ events.general.yes-delete-event = Yes, delete event events.general.yes-delete-events = Yes, delete events events.general.want-to-discard = You have made changes to this event. Do you want to leave and discard those changes? events.general.want-to-discard-title = Discard changes? -events.general.events-deleted = Selected events deleted sucessfully +events.general.events-deleted = Selected events deleted successfully events.general.no-hidden-events = There are no hidden events events.general.no-visible-events = There are no visible events events.back-to-events = Back to all events @@ -678,7 +678,7 @@ events.edit.display-sum-description = A display name for the optional sum proper events.edit.display-duration = Display name for duration events.edit.display-duration-description = A display name for the optional duration property of this event. events.edit.event-properties = Event properties -events.no-event = There are no events tracked for this application\! +events.no-event = There are no events tracked for this application! events.delete-confirm = You are about to delete all data associated with event "{0}". Do you want to continue? events.delete-confirm-many = You are about to delete all data associated with these events. Do you want to continue? events.delete.multiple-events = {0} events @@ -687,7 +687,7 @@ events.edit.omit-event-segments-description = Choose which segments of this cust events.edit.omit-event-segments-description-drill = Data for these segments will still be stored in Drill. events.edit.omit-event-segments-to-omit = Segments to omit events.edit.omit-event-select-segments = Select segments -event.edit.omitt-warning = You are about to omit data for some segments of this event. Omitted segments will not be saved in the future and past data for these segments will be purged immediately after you save these settings. Do you want to continue? +event.edit.omitt-warning = You are about to omit data for some segments of this event. Omitted segments will not be saved in the future, and past data for these segments will be purged immediately after you save these settings. Do you want to continue? events.overview.title = Overview events.overview.drawer-title = Configure overview events.overview.empty = You don't have any items in overview @@ -698,15 +698,15 @@ events.overview.choose-event = Choose event events.overview.choose-property = Choose property events.overview.table.title-event = Event events.overview.table.title-property = Property -events.overview.max-c = You can add maximum 12 previews in overview. Please delete some of previously added to add new. -events.overview.have-already-one = You have already one item with the same event and propery in overview. +events.overview.max-c = You can add a maximum of 12 previews in the overview. Please delete some of the previously added items to add new ones. +events.overview.have-already-one = You already have one item with the same event and property in the overview. events.overview.empty-title = Events overview is empty -events.overview.empty-text-admin = Configure events overview to visualise your most important custom events at a glance. -events.overview.empty-text-user = Request an admin of this application to configure events overview to visualise most important custom events at a glance. +events.overview.empty-text-admin = Configure the events overview to visualise your most important custom events at a glance. +events.overview.empty-text-user = Request an admin of this application to configure the events overview to visualise the most important custom events at a glance. events.overview.save-changes = Save changes events.overview.unknown = NA -events.all.empty-title = This application doesn't have any custom events -events.all.empty-text = Log some custom events inside your application's code using the SDKs and visit this section later +events.all.empty-title = This application does not have any custom events. +events.all.empty-text = Log some custom events inside your application's code using the SDKs and visit this section later. events.top-events.title = Top Events By Count events.top-events.24hours = 24-Hours events.top-events.30days = 30-Days @@ -717,7 +717,7 @@ events.max-segmentation-limit = Maximum limit of segmentations ({0}) in current events.max-unique-value-limit = Maximum limit of unique values ({0}) in current event segmentation "{1}" has been reached. Limit can be adjusted. events.event-group-drawer-create = Create new Event Group -events.event-group-name = Event Group name +events.event-group-name = Event Group name events.group-use-description = Use description events.group-include-events = Include events events.group-select-events = Select events to include @@ -729,9 +729,9 @@ events.group-invisibility-checkbox = Event Group is invisible events.group-properties = Event Group Properties events.event-group-count = Display name for count events.event-group-count-description = A display name for the count property of this event -events.event-group-sum= Display name for sum +events.event-group-sum = Display name for sum events.event-group-sum-description = A display name for the sum property of this event -events.event-group-duration = Display name for duration +events.event-group-duration = Display name for duration events.event-group-duration-description = A display name for the duration property of this event events.create-group = Create Event Group events.save-group = Save Event Group @@ -748,8 +748,8 @@ export.documents = documents export.export-columns-selected-count = {0}/{1} selected export.format-if-possible = Format timestamps to readable date export.format-if-possible-explain = Fields which are saved in data base as timestamps will be converted to show as date string like in table. For example: "Mon, 29 Jun 2020 17:14:15" -export.export-started = Export file is being generated. When ready you will see notification or can download it in report manager. -export.export-failed = Error upon attempting to export table data. +export.export-started = The export file is being generated. When ready, you will see a notification or can download it in the report manager. +export.export-failed = An error occurred while attempting to export table data. export.export-finished = Export completed. export.export-finished-click = Click to download exported file. export.file-name = File name @@ -759,9 +759,9 @@ management-applications.title = Application Management management-applications.my-new-app = My new app management-applications.clear-data = Clear data management-applications.clear-reset-data = Reset application -management-applications.clear-reset-explanation = Resets app to initial clean state like right after creation +management-applications.clear-reset-explanation = Resets the app to its initial clean state, as it was right after creation. management-applications.clear-all-data = Clear all data -management-applications.clear-all-explanation = Removes collected data but keeps configurations +management-applications.clear-all-explanation = Removes collected data but keeps the configurations. management-applications.clear-1month-data = Clear data older than 1 month management-applications.clear-3month-data = Clear data older than 3 months management-applications.clear-6month-data = Clear data older than 6 months @@ -784,7 +784,7 @@ management-applications.category.tip = Select a category management-applications.app-id = App ID management-applications.app-id.hint = This ID is used for the read API management-applications.app-key = App Key -management-applications.app-key.hint = You'll need this key for SDK integration +management-applications.app-key.hint = You will need this key for SDK integration. management-applications.app-key.generate = Will generate automatically management-applications.app-key-unique = This App Key is already in use management-applications.time-zone = Time Zone @@ -795,23 +795,23 @@ management-applications.icon = App Icon management-applications.add-application = Add application management-applications.clear-confirm-all = You are about to clear all the collected data stored for your application. Do you want to continue? management-applications.clear-confirm-period = You are about to clear all the collected data stored for your application within a selected period of time. Do you want to continue? -management-applications.clear-confirm-reset = You are about to reset your app to initial clean state. Do you want to continue? +management-applications.clear-confirm-reset = You are about to reset your app to its initial clean state. Do you want to continue? management-applications.clear-admin = Only administrators of an application can clear it's data. management-applications.clear-success = Application data is successfully cleared. management-applications.reset-success = Application is successfully reset. management-applications.delete-confirm = You are about to delete all the data associated with your application. Do you want to continue? management-applications.delete-admin = Only administrators of an application can delete it. management-applications.app-locked = Application is locked. -management-applications.icon-error = Only jpg, png and gif image formats are allowed +management-applications.icon-error = Only JPG, PNG, and GIF image formats are allowed. management-applications.no-app-warning = In order to start collecting data you need to add an application to your account. management-applications.app-key-change-warning-title = Changing the App key management-applications.app-key-change-warning = Changing the app key will cause all users from this point on to be recorded as new users even if they used your application before. This action is only recommended if you are migrating an application from another server or changing the app key of a new application. management-applications.app-key-change-warning-confirm = Continue, change the app key management-applications.app-key-change-warning-EE = Changing the app key will cause all users from this point on to be recorded as new users even if they used your application before. This action is only recommended if you are migrating an application from another server or changing the app key of a new application. If your intention was to change the app key to stop collecting data for this application, recommended way of doing so is using Filtering Rules plugin. -management-applications.first-app-message2 = Great\! You can now embed Countly SDK into your application and start viewing your stats instantly. Don't forget to get your App Key from above. +management-applications.first-app-message2 = Great! You can now embed the Countly SDK into your application and start viewing your stats instantly. Don't forget to get your App Key from above. management-applications.types.mobile = Mobile management-applications.checksum-salt = Salt for checksum -management-applications.checksum-salt.hint = Will only accept requests where checksum is signed with the same salt in SDK +management-applications.checksum-salt.hint = Will only accept requests where the checksum is signed with the same salt in the SDK. management-applications.app-domain = Website Domain management-applications.app-creator = App created by management-applications.app-created-at = Date of creation @@ -831,9 +831,9 @@ management-applications.plugins.saved.title = Plugin configuration management-applications.plugins.saved = Changes saved successfully! management-applications.plugins.error.server = Unknown server error management-applications.create-first-app-title = Let's add your first application. -management-applications.create-first-app-description = After adding your first application you'll be ready to start collecting data. +management-applications.create-first-app-description = After adding your first application, you will be ready to start collecting data. management-applications.contact-an-admin = Please contact an administrator -management-applications.dont-access = You don't access rights to any application. +management-applications.dont-access = You don't have access rights to any application. management-applications.plugins-description = Settings in this section will override global settings for the application management-applications.application-lock-tooltip = Application lock prevents accidental data purge and data population management-applications.application-tooltip-locked-text = App is locked. Unlock it to allow changes. @@ -857,7 +857,7 @@ management-users.apps = Apps management-users.sidebar-title = User Management management-users.users = Users management-users.view-title = Manage Users -management-users.editing-your-account = You\'re about to edit your own account. So you may be logged out automatically if changed something related with your permission. Do you want to contiue? +management-users.editing-your-account = You are about to edit your own account. So you may be logged out automatically if you change something related to your permission. Do you want to continue? management-users.feature = Feature management-users.create = Create management-users.read = Read @@ -869,7 +869,7 @@ management-users.create-new-user = Create new user management-users.remove-permission-set = Remove permission set management-users.create-user = Create user management-users.discard-changes = Discard Changes -management-users.discard-confirm = You will lose all changes that you made. Are you sure to continue? +management-users.discard-confirm = You will lose all the changes that you have made. Are you sure you want to continue? management-users.permission-settings = Permission settings management-users.user-has-access-to = User has access to management-users.role = Role @@ -888,7 +888,7 @@ management-users.drag-and-drop-or = Drag and drop file here or management-users.click-to-upload = click to upload a file management-users.browser = browser management-users.files-to-add-picture = files to add picture -management-users.pp-size-warning = JPG, PNG and GIF files allowed. Maximum size is 5 MB. +management-users.pp-size-warning = JPG, PNG, and GIF files are allowed. The maximum size is 5 MB. management-users.remove-image = Remove image management-users.email = E-mail management-users.enter-email = Enter E-mail address @@ -912,8 +912,8 @@ management-users.disable-2fa-user = Disable 2FA management-users.all-roles = All roles management-users.not-logged-in-yet = Not logged in yet management-users.close = Click to close -management-users.password-change-confirm = You have changed {0}\''s password. Do you want a notification email to be sent? -management-users.delete-confirm = You are about to delete {0}\''s account. Do you want to continue? +management-users.password-change-confirm = You have changed {0}'s password. Do you want a notification email to be sent? +management-users.delete-confirm = You are about to delete {0}'s account. Do you want to continue? management-users.delete-confirm-title = Delete user? management-users.yes-delete-user = Yes, delete user management-users.email.invalid = invalid email @@ -930,12 +930,12 @@ management-users.revoke-confirm = You are about to remove this user's access to management-users.email-tip = User will be notified even if there is not an account for this email... management-users.last_login = Last Login management-users.created = Created -management-users.created-message = User created successfully\! +management-users.created-message = User created successfully! management-users.removed = Removed -management-users.removed-message = User removed successfully\! +management-users.removed-message = User removed successfully! management-users.remove-canceled = User remove canceled management-users.updated = Updated -management-users.updated-message = User informations updated successfully\! +management-users.updated-message = User information updated successfully! management-users.confirm-loss-checkboxes = You will lose all marked permissions below. Are you sure you want to continue? management-users.select-app-first-title = Select app first management-users.select-app-first-message = You need to select app or apps before you mark permission boxes @@ -954,7 +954,7 @@ management-users.group-blank = - management-users.reset-filters = Reset Filters management-users.search-placeholder = Search in Features management-users.reset-failed-logins = Reset failed logins -management-users.reset-failed-logins-success = Failed logins reset successfully\! +management-users.reset-failed-logins-success = Failed logins reset successfully! management-users.reset-failed-logins-failed = Failed to reset logins\! management-users.cannot-delete-own-account = You can not delete your own account management-users.cannot-revoke-own-admin = You can not revoke your own global admin privileges @@ -984,9 +984,9 @@ management.preset.duplicate-preset = Duplicate date preset management.preset.date-range = Date range management.preset.exclude-current-day = Exclude current day management.preset.exclude-current-day.description = By excluding the current day, results may change as the day has not yet ended. -management.preset.created = Preset created successfully\! -management.preset.updated = Preset updated successfully\! -management.preset.deleted = Preset deleted successfully\! +management.preset.created = Preset created successfully! +management.preset.updated = Preset updated successfully! +management.preset.deleted = Preset deleted successfully! management.preset.created.error = Something went wrong while creating preset. management.preset.updated.error = Something went wrong while updating preset. management.preset.deleted.error = Something went wrong while deleting preset. @@ -1008,23 +1008,23 @@ user-settings.old-password = Old password... user-settings.new-password = New password... user-settings.password-again = Again... user-settings.alert = Something is wrong... -user-settings.success = Settings saved successfully\! +user-settings.success = Settings saved successfully! user-settings.api-key = API Key user-settings.password-match = Passwords don't match user-settings.old-password-match = Provide old password to change it user-settings.old-password-not-match = Old password does not match -user-settings.password-not-old = New password must not be the same as old the one +user-settings.password-not-old = New password must not be the same as the old one user-settings.force-password-reset = It is time to change your password. user-settings.please-correct-input = Please fix errors before submitting the form user-settings.api-key-length = API key should be exactly 32 characters long user-settings.api-key-restrict = API key should contain digits and alphabetical characters user-settings.regenerate-api-key = Regenerate API key user-settigs.delete-account = Delete account -user-settings.delete-account-title = Delete account? +user-settings.delete-account-title = Delete account? user-settings.delete-account-confirm = Do you really want to delete your account? You won't be able to recover it. -user-settings.password-mandatory = Password is mandatory! -user-settings.global admin limit = This account is last global admin account. Can't delete last global admin account. -user-settings.password not valid = Given password is not valid +user-settings.password-mandatory = Password is mandatory. +user-settings.global admin limit = This account is the last global admin account. Can't delete the last global admin account. +user-settings.password not valid = The given password is not valid user-settings.profile-picture = Profile Picture user-settings.upload = Upload @@ -1063,12 +1063,12 @@ app-users.download-export = Download user's exported data app-users.delete-export = Purge user's exported data app-users.delete-userdata = Purge selected user's data completely app-users.delete-userdata-confirm = Do you really want to purge all data associated with this user? -app-users.export-started = Exporting has started sucessfully. +app-users.export-started = Exporting has started successfully. app-users.export-finished = User data is exported. You can download it now. app-users.export-finished-click = Click here to download. -app-users.export-failed = There was error during export process. There might be more information in logs. +app-users.export-failed = There was an error during the export process. There might be more information in logs. app-users.export-deleted = Export data was purged -app-users.userdata-deleted = User's data has been purged +app-users.userdata-deleted = User's data has been purged app-users.yes-purge-data = Yes, purge data app-users.no-dont-purge = No, don't purge app-users.purge-confirm-title = Purge user's data completely? @@ -1085,28 +1085,28 @@ token_manager.page-title = Token Manager token_manager.create-token = Create Token token_manager.create-new-token = Create New Token token_manager.table.id = Token ID -token_manager.table.ends =Valid until -token_manager.table.multi = Multiple times +token_manager.table.ends = Valid Until +token_manager.table.multi = Multiple times token_manager.table.owner = Token owner token_manager.table.app = App -token_manager.table.status = Status +token_manager.table.status = Status token_manager.table.endpoint = Endpoint token_manager.table.endpoints = Endpoints token_manager.table.endpoint-name = Endpoint Name token_manager.table.endpoint-detail = ENDPOINT DETAILS -token_manager.table.endpoints-description = Given endpoints are interpreted as regularexpressions +token_manager.table.endpoints-description = Given endpoints are interpreted as regular expressions. token_manager.table.expiration-description = Set expiration time for token token_manager.table.purpose = Description token_manager.table.token-description = Token Description -token_manager.table.purpose-desc = Some information to help user identify created token. -token_manager.table.endpoint-desc = You can limit token to a single or multiple endpoints. Given endpoints are interpreted as regular expressions. -token_manager.table.multi-desc = Token can be used multiple times +token_manager.table.purpose-desc = Some information to help the user identify created token. +token_manager.table.endpoint-desc = You can limit the token to a single or multiple endpoints. Given endpoints are interpreted as regular expressions. +token_manager.table.multi-desc = Token can be used multiple times. token_manager.table.apps-title = Token Usage token_manager.table.apps-limit = Allow token to be used only in some apps token_manager.table.apps-allow = Allow token to be used in all apps -token_manager.table.limit-limit.label = Limited Time +token_manager.table.limit-limit.label = Limited Time token_manager.table.limit-limit.text = Token will expire after the time you set -token_manager.table.limit-allow.label = Unlimited Time +token_manager.table.limit-allow.label = Unlimited Time token_manager.table.limit-allow.text = Token can be used until it is deleted token_manager.table.limit-title = Token Expiration token_manager.table.enter-number = Enter number @@ -1119,24 +1119,24 @@ token_manager.delete-token-confirm = Do you really want to delete this token? token_manager.delete-token-confirm-title = Delete token? token_manager.yes-delete-token = Yes, delete token token_manager.delete-error = Deleting token failed -token_manager.select-apps-error = You have to chose apps or set option to "Allow token to be used in all apps" -token_manager.select-expire-error = You have to choose after how long time token expires or set option to "Token can be used till it is deleted" +token_manager.select-apps-error = You have to choose apps or set option to "Allow token to be used in all apps" +token_manager.select-expire-error = You have to choose after how long time token expires or set option to "Token can be used until it is deleted" token_manager.table.delete-token = Delete token token_manager.table.status-expired = Expired token_manager.table.status-active = Active token_manager.copy-token = Click to copy -token_manager.token-coppied = Token coppied +token_manager.token-coppied = Token Copied token_manager.query-param = Query Parameters token_manager.query-param-value = Value -token_manager.query-param-desc = Limit by some parameter values(for example method=get_events) Value is used as regex when validating. +token_manager.query-param-desc = Limit by some parameter values (for example, method=get_events). The value is used as a regex when validating. token_manager.add-new-endpoint = Add new endpoint token_manager.add-param = Add parameter -token_manager.parameter = Parameter -token_manager.select-apps = Select Apps +token_manager.parameter = Parameter +token_manager.select-apps = Select Apps token_manager.select-time-unit = Select time unit token_manager.token-expiration-time = Expiration Time -token_manager.LoginAuthToken-description = This token is created when creating dashboard screenshots. If you are not currently rendering dashboard images, you can delete this token. -token_manager.LoggedInAuth-description = This token is used for keeping users session. Deleting it will log out user currently using it to keep session. +token_manager.LoginAuthToken-description = This token is created when creating dashboard screenshots. If you are not currently rendering dashboard images, you can delete this token. +token_manager.LoggedInAuth-description = This token is used for keeping the user's session. Deleting it will log out the user currently using it to keep the session. version_history.page-title = Countly version history @@ -1145,7 +1145,7 @@ version_history.package-version = Package version version_history.version = Version version_history.upgraded = Upgraded / installed version_history.alert-title = Version mismatch -version_history.alert-message = There is a version mismatch between version in files and in database. It may indicate that upgrade scripts didn't complete properly. +version_history.alert-message = There is a version mismatch between the version in the files and the version in the database. It may indicate that upgrade scripts did not complete properly. internal-events.[CLY]_session = Session #jobs @@ -1168,11 +1168,11 @@ systemlogs.action.task_manager_task_created = Report created #events-overview events.overview.title.new = Events Overview -events.overview.title.new.tooltip = Complete summary of all Events being tracked. -events.overview.total.event.count = Total number of Events triggered in the last 30 days. -events.overview.event.per.user = Average number of Events triggered per user, in the last 30 days. -events.overview.event.per.session = Average number of Events triggered per session, in the last 30 days. -events.overview.event.metrics = Overview of the metrics calculated by the identified Events, in the last 30 days. +events.overview.title.new.tooltip = A complete summary of all Events being tracked. +events.overview.total.event.count = The total number of Events triggered in the last 30 days. +events.overview.event.per.user = The average number of Events triggered per user in the last 30 days. +events.overview.event.per.session = The average number of Events triggered per session in the last 30 days. +events.overview.event.metrics = An overview of the metrics calculated by the identified Events in the last 30 days. events.overview.event.monitor.events = A quick summary of selected Events that you wish to monitor. To select Events that you want to highlight here, please click on 'Configure Events'. events.overview.metrics = Event Metrics events.overview.monitor = Monitor Events @@ -1196,12 +1196,12 @@ events.overview.manage.items = Manage Items events.overview.last-30days = Last 30 Days #all-events -events.all.title.tooltip = Details of the stats of each Event, in the selected time period, and their comparison where applicable. +events.all.title.tooltip = Details of the stats of each Event within the selected time period, and their comparison where applicable. events.all.title.new = All Events events.all.period = PERIOD events.all.event = EVENT events.all.segmentation = SEGMENTATION BY -events.segment.values = SEGMENT VALUES(S) +events.segment.values = SEGMENT VALUE(S) events.all.search.placeholder = Search in {0} Events events.all.group = GROUP events.all.error = Could not fetch data @@ -1217,24 +1217,24 @@ events.drill-drawer.title = Event Drill events.drill-drawer.save-button = Go to Drill #auto-refresh -auto-refresh.help= Automatically refresh can be adjusted through this switch -auto-refresh.enable= Enable Auto-refresh -auto-refresh.stop= Stop Auto-refresh -auto-refresh.is= Auto-refresh is +auto-refresh.help = Automatic refresh can be adjusted through this switch. +auto-refresh.enable = Enable Auto-refresh +auto-refresh.stop = Stop Auto-refresh +auto-refresh.is = Auto-refresh is auto-refresh.enabled = Enabled initial-setup.application = Application initial-setup.add-first-application-title = Let's add your first application -initial-setup.add-first-application-byline = After adding your first application, you'll be ready to start collecting data +initial-setup.add-first-application-byline = After adding your first application, you will be ready to start collecting data. initial-setup.add-demo-application-title = Let's create a demo app for you! initial-setup.application-type-label = Select your application type initial-setup.time-zone-label = Select your time zone -initial-setup.application-sample-label = We'll populate some demo data for your app, which example sounds the best? +initial-setup.application-sample-label = We will populate some demo data for your app. Which example sounds the best? initial-setup.create-application = Create Application initial-setup.continue-data-population = Continue with data population initial-setup.consent-title = Before we start... -initial-setup.analytics-blurb-1 = We utilize Countly to understand user interactions and collect feedback, helping us enhance our product continuously. However, your privacy remains our priority. -initial-setup.analytics-blurb-2 = This analysis is done on the server level, so we won't see or collect any individual details or any data you record. The data is reported back only to our dedicated Countly server based in Europe. Please note, you can change your mind at any time in the settings. +initial-setup.analytics-blurb-1 = We utilize Countly to understand user interactions and collect feedback, helping us enhance our product continuously. However, your privacy remains our priority. +initial-setup.analytics-blurb-2 = This analysis is done at the server level, so we will not see or collect any individual details or any data you record. The data is reported back only to our dedicated Countly server based in Europe. Please note, you can change your mind at any time in the settings. initial-setup.analytics-question = Considering our commitment to maintaining your privacy and the potential benefits for product enhancement, would you be comfortable enabling Countly on this server? initial-setup.analytics-no = No, maybe later initial-setup.analytics-yes = Yes, enable Countly on this server diff --git a/frontend/express/public/localization/help/help.properties b/frontend/express/public/localization/help/help.properties index 1ac0fd77d2f..ed31daa5f9d 100644 --- a/frontend/express/public/localization/help/help.properties +++ b/frontend/express/public/localization/help/help.properties @@ -1,48 +1,48 @@ -help.help-mode-welcome = Hover on each item to view a brief explanation.

While in this mode auto-refreshing of your data is disabled and will be enabled as soon as you turn off the help mode. -help.help-mode-welcome-title = Welcome to the help mode\! +help.help-mode-welcome = Hover over each item to view a brief explanation.

While in this mode, auto-refreshing of your data is disabled and will be enabled as soon as you turn off help mode. +help.help-mode-welcome-title = Welcome to Help Mode! #dashboard -help.dashboard.total-sessions = Number of times your application is opened. Click this item to see a time series representation of total sessions. -help.dashboard.total-users = Number of unique devices your application is used from. Click this item to see a time series representation of total users. -help.dashboard.new-users = Number of first time users. Click this item to see a time series representation of new users. -help.dashboard.total-time-spent = Total time users spent using your application. -help.dashboard.avg-time-spent2 = Total time spent using your application divided by total session count. Click this item to see a time series representation of average time spent per session. -help.dashboard.reqs-received = Number of write API requests Countly Server received for this application. Click this item to see a time series representation of requests received. -help.dashboard.avg-reqs-received = Number of write API requests Countly Server received for this application divided by total user count. Click this item to see a time series representation of average requests per user. -help.dashboard.top-platforms = Shows at most top three platforms represented by different colors according to the number of sessions from each platform. Hover on each color to see the platform name. -help.dashboard.top-resolutions = Shows at most top three resolutions represented by different colors according to the number of sessions from each resolution. Hover on each color to see the resolution. -help.dashboard.top-carriers = Shows at most top three carriers represented by different colors according to the number of sessions from each carrier. Hover on each color to see the carrier name. -help.dashboard.top-users = Shows at most top three days in which your application reached maximum number of total users. Hover on each color to see the date. -help.dashboard.map = World map shows session counts from each country represented by a tone of green according to the count. Next to the map you can see a table of top ten countries together with the sessions counts (table is shown only if there is any available data). +help.dashboard.total-sessions = The number of times your application is opened. Click this item to see a time series representation of total sessions. +help.dashboard.total-users = The number of unique devices your application is used from. Click this item to see a time series representation of total users. +help.dashboard.new-users = The number of first-time users. Click this item to see a time series representation of new users. +help.dashboard.total-time-spent = The total time users spent using your application. +help.dashboard.avg-time-spent2 = The total time spent using your application divided by the total session count. Click this item to see a time series representation of the average time spent per session. +help.dashboard.reqs-received = The number of write API requests the Countly Server received for this application. Click this item to see a time series representation of requests received. +help.dashboard.avg-reqs-received = The number of write API requests the Countly Server received for this application, divided by the total user count. Click this item to see a time series representation of the average requests per user. +help.dashboard.top-platforms = Shows at most the top three platforms represented by different colors according to the number of sessions from each platform. Hover over each color to see the platform name. +help.dashboard.top-resolutions = Shows at most the top three resolutions represented by different colors according to the number of sessions from each resolution. Hover over each color to see the resolution. +help.dashboard.top-carriers = Shows at most the top three carriers represented by different colors according to the number of sessions from each carrier. Hover over each color to see the carrier name. +help.dashboard.top-users = Shows at most the top three days in which your application reached the maximum number of total users. Hover over each color to see the date. +help.dashboard.map = The world map shows session counts from each country, represented by a tone of green according to the count. Next to the map, you can see a table of the top ten countries together with their session counts (the table is shown only if there is any available data). #sessions view -help.sessions.total-sessions = Number of times your application is opened. Time series representation of this item is identified by the top border color of this block. -help.sessions.new-sessions = Number of times your application is opened by a first time user. Time series representation of this item is identified by the top border color of this block. -help.sessions.unique-sessions = Number of times your application is opened from a unique device. Time series representation of this item is identified by the top border color of this block. +help.sessions.total-sessions = The number of times your application is opened. The time series representation of this item is identified by the top border color of this block. +help.sessions.new-sessions = The number of times your application is opened by a first-time user. The time series representation of this item is identified by the top border color of this block. +help.sessions.unique-sessions = The number of times your application is opened from a unique device. The time series representation of this item is identified by the top border color of this block. #users view -help.users.total-users = Number of unique devices. Time series representation of this item is identified by the top border color of this block. -help.users.new-users = Number of first time users. Time series representation of this item is identified by the top border color of this block. -help.users.returning-users = Number of users that have used your application at least one time before. Time series representation of this item is identified by the top border color of this block. +help.users.total-users = The number of unique devices. The time series representation of this item is identified by the top border color of this block. +help.users.new-users = The number of first-time users. The time series representation of this item is identified by the top border color of this block. +help.users.returning-users = The number of users that have used your application at least one time before. The time series representation of this item is identified by the top border color of this block. #countries view -help.countries.chart = World map shows session counts from each country represented by a tone of green according to the count. -help.countries.table = Country\: Name of the country.
Total Sessions\: Number of times your application is opened by a user from this country.
Total Users\: Number of unique devices your application is used from within this country.
New Users\: Number of first time users from this country.
-help.countries.total-sessions = Number of times your application is opened. -help.countries.total-users = Number of unique devices. -help.countries.new-users = Number of first time users. +help.countries.chart = The world map shows session counts from each country represented by a tone of green according to the count. +help.countries.table = Country: Name of the country.
Total Sessions: The number of times your application is opened by a user from this country.
Total Users: The number of unique devices from which your application is used within this country.
New Users: The number of first-time users from this country.
+help.countries.total-sessions = The number of times your application is opened. +help.countries.total-users = The number of unique devices. +help.countries.new-users = The number of first-time users. #devices view -help.devices.chart = Pie chart on the left shows percentage of total users from each device (unique device percentages). Pie chart on the right shows percentage of first time users from each device. -help.devices.platform-versions2 = Shows at most top three platform versions represented by different colors according to the number of sessions from each platform version. Hover on each color to see the platform version. +help.devices.chart = The pie chart on the left shows the percentage of total users from each device (unique device percentages). The pie chart on the right shows the percentage of first-time users from each device. +help.devices.platform-versions2 = Shows at most the top three platform versions represented by different colors according to the number of sessions from each platform version. Hover over each color to see the platform version. #loyalty view -help.loyalty.chart = Total number of users from each session count segment (1, 2, 3-5, 6-9, 10-19, 20-49, 50-99, 100-499, > 500) is visualized using a bar chart. -help.loyalty.table = Session Count\: Session count segment. User is categorized into one of 1, 2, 3-5, 6-9, 10-19, 20-49, 50-99, 100-499, > 500 according to his total session count.
Number of Users\: Number of users (unique devices) that are in a particular session count segment.
Percent\: Percentage of users that are in a particular session count segment.
+help.loyalty.chart = The total number of users from each session count segment (1, 2, 3-5, 6-9, 10-19, 20-49, 50-99, 100-499, > 500) is visualized using a bar chart. +help.loyalty.table = Session Count: Session count segment. A user is categorized into one of 1, 2, 3-5, 6-9, 10-19, 20-49, 50-99, 100-499, > 500 according to their total session count.
Number of Users: The number of users (unique devices) that are in a particular session count segment.
Percent: The percentage of users that are in a particular session count segment.
#frequency view -help.frequency.chart = Total number of users from each session frequency segment (First session, 1-24 hours, 1 day, 2 days, 3 days, 4 days, 5 days, 6 days, 7 days, 8-14 days, 15-30 days, 30+ days) is visualized using a bar chart. -help.frequency.table = Time after previous session\: Time between users' consequent sessions. User is categorized into one of First session, 1-24 hours, 1 day, 2 days, 3 days, 4 days, 5 days, 6 days, 7 days, 8-14 days, 15-30 days or 30+ days according to his session frequency.
Number of Users\: Number of users (unique devices) in this session frequency segment.
Percent\: Percentage of users in this session frequency segment.
+help.frequency.chart = The total number of users from each session frequency segment (First session, 1-24 hours, 1 day, 2 days, 3 days, 4 days, 5 days, 6 days, 7 days, 8-14 days, 15-30 days, 30+ days) is visualized using a bar chart. +help.frequency.table = Time after previous session: Time between users' consequent sessions. A user is categorized into one of First session, 1-24 hours, 1 day, 2 days, 3 days, 4 days, 5 days, 6 days, 7 days, 8-14 days, 15-30 days or 30+ days according to their session frequency.
Number of Users: Number of users (unique devices) in this session frequency segment.
Percent: Percentage of users in this session frequency segment.
#platforms view help.platform-versions.chart = Pie chart on the left shows percentage of total users from each platform. Pie chart on the right shows percentage of total users from each platform version. You can toggle between iOS and Android to see distribution of platform versions (Toggle button will appear only if there is more than one platform) @@ -84,10 +84,10 @@ help.device_type.chart = Pie chart on the left shows percentage of total users f #session durations view help.durations.chart = Total number of users from each session duration segment (0-10 seconds, 11-30 seconds, 31-60 seconds, 1-3 minutes, 3-10 minutes, 10-30 minutes, 30-60 minutes or > 1 hour) is visualized using a bar chart. -help.durations.table = Session duration\: User is categorized into one of 0-10 seconds, 11-30 seconds, 31-60 seconds, 1-3 minutes, 3-10 minutes, 10-30 minutes, 30-60 minutes or > 1 hour according to his session duration.
Number of Users\: Number of users (unique devices) in this session duration segment.
Percent\: Percentage of users in this session duration segment.
+help.durations.table = Session duration: A user is categorized into one of 0-10 seconds, 11-30 seconds, 31-60 seconds, 1-3 minutes, 3-10 minutes, 10-30 minutes, 30-60 minutes or > 1 hour according to their session duration.
Number of Users: Number of users (unique devices) in this session duration segment.
Percent: Percentage of users in this session duration segment.
#push help.manage-apps.push-apn-certificate = Certificate file for Apple Push Notification (APN) service. In order to send Push Notifications, you need to supply at least one .PK12 file for this app. -help.manage-apps.push-gcm-key = Server API Key for Google Cloud Messaging (GCM) service. It's required if you're going to send messages to your Android app users from Countly. You can get one from Google API Console. +help.manage-apps.push-gcm-key = Server API Key for Google Cloud Messaging (GCM) service. It is required if you're going to send messages to your Android app users from Countly. You can get one from the Google API Console. help.datatables-export = Only visible data will be downloaded diff --git a/frontend/express/public/localization/mail/mail.properties b/frontend/express/public/localization/mail/mail.properties index 4057182d877..edcff97a9d0 100644 --- a/frontend/express/public/localization/mail/mail.properties +++ b/frontend/express/public/localization/mail/mail.properties @@ -1,10 +1,10 @@ #mail templates mail.new-member-subject = Your Countly Account -mail.new-member = Hi {0},

Your Countly account on {1} is created with the following details;

Username: {2}
Password: {3}

Enjoy,
A fellow Countly Admin -mail.new-member-prid = Hi {0},

Your Countly account on {1} is created with the following details;

Username: {2}
You can set up your password following this link.
Enjoy,
A fellow Countly Admin +mail.new-member = Hi {0},

Your Countly account on {1} has been created with the following details:

Username: {2}
Password: {3}

Enjoy,
A fellow Countly Admin +mail.new-member-prid = Hi {0},

Your Countly account on {1} has been created with the following details:

Username: {2}
You can set up your password by following this link.
Enjoy,
A fellow Countly Admin mail.password-change-subject = Countly Account - Password Change -mail.password-change = Hi {0},

Your password for your Countly account on {1} has been changed. Below you can find your updated account details;

Username: {2}
Password: {3}

Best,
A fellow Countly Admin +mail.password-change = Hi {0},

Your password for your Countly account on {1} has been changed. Below you can find your updated account details:

Username: {2}
Password: {3}

Best,
A fellow Countly Admin mail.password-reset-subject = Countly Account - Password Reset -mail.password-reset = Hi {0},

You can reset your Countly account password by following this link.

If you did not request to reset your password ignore this email.

Best,
A fellow Countly Admin +mail.password-reset = Hi {0},

You can reset your Countly account password by following this link.

If you did not request to reset your password, please ignore this email.

Best,
A fellow Countly Admin mail.time-ban-subject = {0}: Your account is locked -mail.time-ban = Hi {0},

Due to excess number of failed login attempts, your account has been blocked. You can use this link to unlock your user and login to your dashboard for once.

Best
A fellow admin \ No newline at end of file +mail.time-ban = Hi {0},

Due to an excessive number of failed login attempts, your account has been blocked. You can use this link to unlock your user and log in to your dashboard once.

Best,
A fellow admin \ No newline at end of file diff --git a/frontend/express/public/localization/pre-login/pre-login.properties b/frontend/express/public/localization/pre-login/pre-login.properties index f5b1430dcde..8605a441361 100644 --- a/frontend/express/public/localization/pre-login/pre-login.properties +++ b/frontend/express/public/localization/pre-login/pre-login.properties @@ -13,10 +13,10 @@ placeholder.enter-password = Enter your password login.title = Login login.forgot = Forgot password? login.result = Login Failed -login.blocked = Your account was locked due to too many incorrect login attempts. Please wait for a while or contact with your system admin. -login.locked = Your account was locked by admin +login.blocked = Your account has been locked due to too many incorrect login attempts. Please wait for a while or contact your system admin. +login.locked = Your account has been locked by an admin. login.button = Sign In -login.token-expired = Your session was expired. Please login again +login.token-expired = Your session has expired. Please log in again. login.email-adress = Email Address login.email-adress-or-username = Username or E-mail address login.sign-in = or Sign In With Your Email @@ -35,15 +35,15 @@ forgot.explanation = Please enter your account email below in order to receive i forgot.result = You will receive an email shortly if the email you entered exists in the system forgot.button = Send Email forgot.invalid-email = Invalid email address format. -forgot.error = Somethings went wrong. Please try again later. +forgot.error = Something went wrong. Please try again later. forgot.sent-email-title = Password Reset Email Sent forgot.sent-email = An email has been sent to your email address, {0}. Follow the directions in the email to reset your password. #reset reset.explanation = Create your new account password below. -reset.result = You can login with your new password\! +reset.result = You can log in with your new password! reset.invalid = Invalid password reset request -reset.dont-match = Passwords don't match\! +reset.dont-match = Passwords do not match! reset.confirm-password = Confirm Password reset.new-password = New Password reset.button = Reset my password @@ -61,17 +61,17 @@ management-users.full_name.invalid = Must provide full name setup.title = Registration setup.full-name = Full Name setup.username = Username -setup.explanation = You have succesfully setup Countly on your server. You just need to create your administrator account in order to complete the installation. +setup.explanation = You have successfully set up Countly on your server. You just need to create your administrator account to complete the installation. setup.button = Create Account -setup.hint-password-good=Your password is good to go\! +setup.hint-password-good=Your password is good to go! setup.error-username = Please enter a valid username. setup.error-full-name = Please enter a valid full name. -setup.error-email = Please enter a valid email adress. -setup.error-confirm-password = Confirmation password has to be the same as password. +setup.error-email = Please enter a valid email address. +setup.error-confirm-password = The confirmation password has to be the same as the password. setup.ready = Your Countly server is ready! setup.byline = Let's first create your dashboard user account setup.continue-demo-app = Continue with a demo app setup.continue-own-app = I want to create my own app #logout -logout.inactivity = You have been logged out due to inactivity +logout.inactivity = You have been logged out due to inactivity. diff --git a/package-lock.json b/package-lock.json index a50617071d1..6efb549769a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -76,7 +76,9 @@ "grunt-eslint": "24.3.0", "grunt-mocha-nyc": "1.0.3", "grunt-mocha-test": "0.13.3", + "husky": "^9.1.7", "jsdoc": "^4.0.0", + "lint-staged": "^15.4.3", "mocha": "10.8.2", "nyc": "17.1.0", "should": "13.2.3", @@ -92,10 +94,251 @@ "hpagent": "^1.2.0" }, "devDependencies": { - "mocha": "^10.8.2", + "mocha": "^11.1.0", "should": "^13.2.3" } }, + "api/utils/countly-request/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "api/utils/countly-request/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "api/utils/countly-request/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "api/utils/countly-request/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "api/utils/countly-request/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "api/utils/countly-request/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "api/utils/countly-request/node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "api/utils/countly-request/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "api/utils/countly-request/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "api/utils/countly-request/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "api/utils/countly-request/node_modules/mocha": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.2.2.tgz", + "integrity": "sha512-VlSBxrPYHK4YNOEbFdkCxHQbZMoNzBkoPprqtZRW6311EUF/DlSxoycE2e/2NtRk4WKkIXzyrXDTrlikJMWgbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "api/utils/countly-request/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "api/utils/countly-request/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "api/utils/countly-request/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "api/utils/countly-request/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "api/utils/countly-request/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "api/utils/countly-root": { "version": "0.1.0" }, @@ -114,14 +357,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -304,9 +547,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", "engines": { @@ -314,9 +557,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -333,27 +576,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", - "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", + "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.0" + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", - "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.1.tgz", + "integrity": "sha512-I0dZ3ZpCrJ1c04OqlNsQcKiZlsrXf/kkE4FXzID9rIOYICsAbA8mMDzhW/luRNAHdCNt7os/u8wenklZDlUVUQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.26.3" + "@babel/types": "^7.27.1" }, "bin": { "parser": "bin/babel-parser.js" @@ -363,15 +606,15 @@ } }, "node_modules/@babel/template": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", - "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.1.tgz", + "integrity": "sha512-Fyo3ghWMqkHHpHQCoBs2VnYjR4iWFFjguTDEqA5WgZDOrFesVjMhMM2FSqTKSoUSDO1VQtavj8NFpdRBEvJTtg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -432,14 +675,14 @@ "license": "MIT" }, "node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", + "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -636,6 +879,109 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1216,6 +1562,19 @@ "sparse-bitfield": "^3.0.3" } }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1310,6 +1669,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz", + "integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, "node_modules/@parcel/watcher": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", @@ -1382,10 +1751,21 @@ "node": ">=10" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@puppeteer/browsers": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.2.tgz", - "integrity": "sha512-i4Ez+s9oRWQbNjtI/3+jxr7OH508mjAKvza0ekPJem0ZtmsYHP3B5dq62+IaBHKaGCOuqJxXzvFLUhJvQ6jtsQ==", + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.3.tgz", + "integrity": "sha512-iPpnFpX25gKIVsHsqVjHV+/GzW36xPgsscWkCnrrETndcdxNsXLdCrTwhkCJNR/FGWr122dJUBeyV4niz/j3TA==", "license": "Apache-2.0", "dependencies": { "debug": "^4.4.0", @@ -1955,6 +2335,22 @@ "node": ">=6" } }, + "node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -2233,9 +2629,9 @@ "optional": true }, "node_modules/bare-fs": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.1.2.tgz", - "integrity": "sha512-8wSeOia5B7LwD4+h465y73KOdj5QHsbbuoUfPBi+pXgFJIPuG7SsiOdJuijWMyfid49eD+WivpfY7KT8gbAzBA==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.1.4.tgz", + "integrity": "sha512-r8+26Voz8dGX3AYpJdFb1ZPaUSM8XOLCZvy+YGpRTmwPHIxA7Z3Jov/oMPtV7hfRQbOnH8qGlLTzQAbgtdNN0Q==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -2946,9 +3342,9 @@ } }, "node_modules/chromium-bidi": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-4.0.1.tgz", - "integrity": "sha512-oRgKuzRQYXEUBlrlXWeBbot0KLyFOAwTe0pt3EJYZ1I0yvvr1dl6zhnUxlkKvSAk0pin+c1SxeuxBILISEgIEw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-4.1.1.tgz", + "integrity": "sha512-biR7t4vF3YluE6RlMSk9IWk+b9U+WWyzHp+N2pL9vRTk+UXHYRTVp7jTK58ZNzMLBgoLMHY4QyJMbeuw3eKxqg==", "license": "Apache-2.0", "dependencies": { "mitt": "^3.0.1", @@ -2989,6 +3385,93 @@ "node": ">=6" } }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -3050,6 +3533,13 @@ "color-support": "bin.js" } }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -3635,9 +4125,9 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.1425554", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1425554.tgz", - "integrity": "sha512-uRfxR6Nlzdzt0ihVIkV+sLztKgs7rgquY/Mhcv1YNCWDh5IZgl5mnn2aeEnW5stYTE0wwiF4RYVz8eMEpV1SEw==", + "version": "0.0.1439962", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1439962.tgz", + "integrity": "sha512-jJF48UdryzKiWhJ1bLKr7BFWUQCEIT5uCNbDLqkQJBtkFxYzILJH44WN0PDKMIlGDN7Utb8vyUY85C3w4R/t2g==", "license": "BSD-3-Clause" }, "node_modules/dezalgo": { @@ -3722,6 +4212,13 @@ "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", "license": "MIT" }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -3815,6 +4312,19 @@ "node": ">=6" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/err-code": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", @@ -4280,12 +4790,146 @@ "node": ">= 0.6" } }, - "node_modules/eventemitter2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", - "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==", - "license": "MIT" - }, + "node_modules/eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==", + "license": "MIT" + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true, + "license": "MIT" + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/execa/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/exif-parser": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", @@ -5211,6 +5855,19 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", @@ -6248,6 +6905,16 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -6258,6 +6925,22 @@ "ms": "^2.0.0" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/icanhazip": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/icanhazip/-/icanhazip-1.0.3.tgz", @@ -6871,6 +7554,22 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jake": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", @@ -7302,6 +8001,19 @@ "node": ">= 8" } }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -7318,6 +8030,185 @@ "uc.micro": "^2.0.0" } }, + "node_modules/lint-staged": { + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.2.tgz", + "integrity": "sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.4.1", + "commander": "^13.1.0", + "debug": "^4.4.0", + "execa": "^8.0.1", + "lilconfig": "^3.1.3", + "listr2": "^8.2.5", + "micromatch": "^4.0.8", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.7.0" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/lint-staged/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/lint-staged/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", + "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/livereload-js": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", @@ -7433,21 +8324,159 @@ "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", "license": "MIT" }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/lowercase-keys": { @@ -7751,6 +8780,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -7840,6 +8876,32 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", @@ -8500,6 +9562,35 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/npmlog": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", @@ -8842,6 +9933,22 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -9024,6 +10131,13 @@ "node": ">=8" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -9169,6 +10283,40 @@ "node": ">=0.10.0" } }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", @@ -9225,6 +10373,19 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -9389,9 +10550,9 @@ } }, "node_modules/prebuild-install/node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", + "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", "license": "MIT", "dependencies": { "chownr": "^1.1.1", @@ -9602,17 +10763,17 @@ } }, "node_modules/puppeteer": { - "version": "24.7.1", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.7.1.tgz", - "integrity": "sha512-fFNINKC/pOI83WQsxOxWC+w1lt4KNWAOuq6S8XSQoMJm9imjmnhhfv/UsDNyJe+1bVZ7bbUMXYpvsp9Mkv5MWw==", + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.8.0.tgz", + "integrity": "sha512-8GPlUKXvZK8ANxab75UerMar14ZnJTJpPok3XN9Nx6f7SKyabyFK39pQruMni6zfrwVBrPXp3Mo6ztwKEmXaDQ==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.10.2", - "chromium-bidi": "4.0.1", + "@puppeteer/browsers": "2.10.3", + "chromium-bidi": "4.1.1", "cosmiconfig": "^9.0.0", - "devtools-protocol": "0.0.1425554", - "puppeteer-core": "24.7.1", + "devtools-protocol": "0.0.1439962", + "puppeteer-core": "24.8.0", "typed-query-selector": "^2.12.0" }, "bin": { @@ -9623,15 +10784,15 @@ } }, "node_modules/puppeteer-core": { - "version": "24.7.1", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.7.1.tgz", - "integrity": "sha512-ORJJEk5nZiIRlYm4PgbtwTvnTGLlHiB8E9V6jZqqu8kaWjpbj/6HT1Yfj81rE66P3ZZqMPXqjEBxRkK1QSsu+w==", + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.8.0.tgz", + "integrity": "sha512-tDf2YKIo5kM5r0vOzT52+PTgN0bBZOA4OFgQaqYyfarrcXLLJ92wi/lSMe44hd+F+gk0gw9QsAzyRW8v6ra93w==", "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.10.2", - "chromium-bidi": "4.0.1", + "@puppeteer/browsers": "2.10.3", + "chromium-bidi": "4.1.1", "debug": "^4.4.0", - "devtools-protocol": "0.0.1425554", + "devtools-protocol": "0.0.1439962", "typed-query-selector": "^2.12.0", "ws": "^8.18.1" }, @@ -9967,6 +11128,52 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -9988,6 +11195,13 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, "node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -10425,6 +11639,49 @@ "node": ">=20.12.2" } }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -10745,6 +12002,16 @@ ], "license": "MIT" }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-template": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", @@ -10765,6 +12032,22 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -10777,6 +12060,20 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", @@ -10789,6 +12086,19 @@ "node": ">=0.10.0" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -10859,30 +12169,23 @@ } }, "node_modules/superagent/node_modules/formidable": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.2.tgz", - "integrity": "sha512-Jqc1btCy3QzRbJaICGwKcBfGWuLADRerLzDqi2NwSt/UkXLsHJw2TVResiaoBufHVHy9aSgClOHCeJsSsFLTbg==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", "dev": true, "license": "MIT", "dependencies": { + "@paralleldrive/cuid2": "^2.2.2", "dezalgo": "^1.0.4", - "hexoid": "^2.0.0", "once": "^1.4.0" }, + "engines": { + "node": ">=14.0.0" + }, "funding": { "url": "https://ko-fi.com/tunnckoCore/commissions" } }, - "node_modules/superagent/node_modules/hexoid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-2.0.0.tgz", - "integrity": "sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/superagent/node_modules/mime": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", @@ -11591,6 +12894,25 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -11611,9 +12933,9 @@ } }, "node_modules/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", + "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -11701,6 +13023,19 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" }, + "node_modules/yaml": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", + "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", diff --git a/package.json b/package.json index 24e1cd1f582..1ff9755f2ea 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,15 @@ "type": "git", "url": "git://github.com/countly/countly-server.git" }, + "scripts": { + "test": "grunt --verbose", + "prepare": "husky" + }, + "lint-staged": { + "*.{js,vue}": [ + "eslint --fix --no-quiet" + ] + }, "devDependencies": { "@stylistic/eslint-plugin": "^2.11.0", "docdash": "^2.0.1", @@ -26,10 +35,9 @@ "nyc": "17.1.0", "should": "13.2.3", "supertest": "7.1.0", - "typescript": "^5.8.2" - }, - "scripts": { - "test": "grunt --verbose" + "typescript": "^5.8.2", + "husky": "^9.1.7", + "lint-staged": "^15.4.3" }, "dependencies": { "all-the-cities": "3.1.0", diff --git a/plugins/alerts/frontend/public/localization/alerts.properties b/plugins/alerts/frontend/public/localization/alerts.properties index 1e9e476007a..427a0bd335c 100644 --- a/plugins/alerts/frontend/public/localization/alerts.properties +++ b/plugins/alerts/frontend/public/localization/alerts.properties @@ -19,24 +19,24 @@ alert.Online-users=Online Users alert.Cohorts=Cohorts alert.Profile-groups = Profile Groups alert.Revenue=Revenue -alert.Data_type= Data Type +alert.Data_type=Data Type alert.For_Application=For Application alert.all-applications=All Applications alert.Select_app=Select Application alert.Select_apps=Select Applications alert.Select_event=Select Event -alert.Alert_type=Alert type +alert.Alert_type=Alert Type alert.Select_a_type=Select a Type alert.Alert_Me_When=Alert Me When alert.Action=Action -alert.e-mail=e-mail -alert.HTTP_request=HTTP request -alert.E-mail_address=E-mail address(One email per line) -alert.Http_Request_URL=Http Request URL -alert.Create_New_Alert=Create new alert +alert.e-mail=Email +alert.HTTP_request=HTTP Request +alert.E-mail_address=Email Address (One email per line) +alert.Http_Request_URL=HTTP Request URL +alert.Create_New_Alert=Create New Alert alert.RUNNING_ALERTS=Active Alerts alert.TOTAL_ALERTS_SENT=TOTAL ALERTS SENT -alert.Today_ALERT_SENT=Today ALERT SENT +alert.Today_ALERT_SENT=Today Alerts Sent alert.Edit=Edit alert.Delete=Delete alert.Save_Changes=Save Changes @@ -57,11 +57,11 @@ alert.You_will_be_notified_via_email=You will be notified via email alert.delete-confirm-title = Delete Alert alert.delete-confirm = Confirm to delete this alert? alert.yes-delete-alert = Yes, delete alert -alert.email-place-holder=Enter emails -alert.enter-alert-name = Enter alert name +alert.email-place-holder=Enter Emails +alert.enter-alert-name = Enter Alert Name alert.Application = Application alert.Condition = Condition -alert.CreateBy = Created by +alert.CreateBy = Created By alert.compare-remind = Metrics are compared on a daily basis. alert.add-number = Add Number alert.make-changes-remind = You made {0} changes. @@ -72,7 +72,7 @@ alert.starView-disabled-suggest = Please enable Ratings plugin to receive alerts alert.crashesView-disabled-title = Crashes plugin is disabled! alert.crashesView-disabled-desc = You will not receive data alerts from Crashes. alert.crashesView-disabled-suggest = Please enable Crashes plugin to receive alerts. -alert.email-to-receive = E-mail to receive alerts +alert.email-to-receive = Email to receive alerts alert.data-point = Data point alert.select-metric=Select Metric alert.define-variable=Define Variation @@ -90,14 +90,14 @@ alerts.empty-subtitle= Create new alerts to receive emails when specific conditi alerts.alert-is-enabled= Alert is Enabled alerts.alert-is-disabled= Alert is Disabled alerts.select-data-type= Select a data type -alerts.select-an-application= Select an application +alerts.select-an-application= Select an Application alerts.filter= Filter alerts.add-filter=+ Add Filter alerts.segment-value= String alerts.widget-name= Widget Name alert.email-to-specific-address = To specific address alert.email-to-group = To users in a group -alerts.select-group = Enter user group name +alerts.select-group = Enter User Group Name alerts.email-icon1 = This alert can only be used within alerts.email-icon2 = to trigger actions. alerts.period-select-reminder-hourly = Value will be checked every hour diff --git a/plugins/compare/frontend/public/localization/compare.properties b/plugins/compare/frontend/public/localization/compare.properties index 38167ad646b..608107999d2 100644 --- a/plugins/compare/frontend/public/localization/compare.properties +++ b/plugins/compare/frontend/public/localization/compare.properties @@ -1,7 +1,7 @@ # e.g. select maximum 10 events to compare compare.plugin-title = Compare -compare.plugin-description = Extensible plugin to compare multiple apps and custom events -compare.limit = Select maximum {0} {1} to compare +compare.plugin-description = Extensible plugin to compare multiple apps and custom events. +compare.limit = Select a maximum of {0} {1} to compare compare.button = Compare compare.back = Back compare.results.by = Results by @@ -19,7 +19,7 @@ compare.apps.app-name = App Name compare.apps.total-unique = Total Visitors/Users compare.apps.new-unique = New Visitors/Users compare.apps.all-apps = All apps -compare.apps.maximum.placeholder = Select maximum 20 applications to compare +compare.apps.maximum.placeholder = Select a maximum of 20 applications to compare compare.apps.results.by.total.sessions = Total Sessions compare.apps.results.by.total.visitors = Total Visitors / Users compare.apps.results.by.new.visitors = New Visitors / Users diff --git a/plugins/compliance-hub/frontend/public/localization/compliance-hub.properties b/plugins/compliance-hub/frontend/public/localization/compliance-hub.properties index 9f1935112b6..9f8df6a0766 100644 --- a/plugins/compliance-hub/frontend/public/localization/compliance-hub.properties +++ b/plugins/compliance-hub/frontend/public/localization/compliance-hub.properties @@ -1,10 +1,10 @@ #consent compliance_hub.title = Compliance Hub compliance-hub.plugin-title = Data Compliance Hub -compliance-hub.description = Providing and aggregating features in compliance with GDPR -compliance_hub.Export-finished = App User export finished -compliance_hub.App-user-deleted = App User deleted -compliance_hub.Export-file-deleted = App User export file deleted +compliance-hub.description = Provides and aggregates features in compliance with GDPR. +compliance_hub.Export-finished = App User Export Finished. +compliance_hub.App-user-deleted = App User Deleted. +compliance_hub.Export-file-deleted = App User Export File Deleted. compliance_hub.Sessions = Sessions compliance_hub.Events = Events compliance_hub.Views = Views @@ -21,7 +21,7 @@ consent.changes = Changes consent.opt-i = Opt in consent.opt-o = Opt out consent.opt-in = Opted in for {0} feature(s) -consent.opt-out = Opted out from {0} feature(s) +consent.opt-out = Opted out of {0} feature(s) consent.metrics = Metrics consent.data-compliance = Data compliance metrics consent.history = Consent history @@ -29,11 +29,11 @@ consent.history-for = Consent history for {0} consent.go-history = Go to consent history consent.export-history = Export/Purge history consent.search-device-id = Search for Device ID -consent.userdata-exports = User data exports -consent.userdata-purges = User data purges +consent.userdata-exports = User data exports. +consent.userdata-purges = User data purges. consent.type = Consent type consent.feature = Feature type -consent.metrics-desc = View consent requests (opt-ins or opt-outs) in a time series graph +consent.metrics-desc = View consent requests (opt-ins or opt-outs) in a time-series graph. consent.users-desc = View list of users and their consent states consent.history-desc = View a history of consent changes consent.exports-desc = View all export and purge actions previously executed diff --git a/plugins/crashes/frontend/public/localization/crashes.properties b/plugins/crashes/frontend/public/localization/crashes.properties index 3144bead43b..f8d01454d31 100644 --- a/plugins/crashes/frontend/public/localization/crashes.properties +++ b/plugins/crashes/frontend/public/localization/crashes.properties @@ -1,9 +1,9 @@ #crashes crashes.title = Crashes crashes.plugin-title = Crash analytics -crashes.plugin-description = See actionable information about crashes and exceptions including which users are impacted +crashes.plugin-description = See actionable information about crashes and exceptions, including which users are impacted. crashes.not-found = This crash report cannot be viewed. Possible reasons: You are trying to view a crash report that you do not have access to or the link to this crash is invalid. -crashes.search = Search for Error +crashes.search = Search for Error crashes.all = All crashes.show = Show crashes.hide = Hide @@ -109,7 +109,7 @@ crashes.posted_comment = Posted crashes.edit = Edit crashes.cancel = Cancel crashes.edited_comment = Edited -crashes.alert-fails = Some operations were not succesful +crashes.alert-fails = Some operations were not successful crashes.confirm-delete = Are you sure you want to delete this crash? crashes.confirm-comment-delete = Are you sure you want to delete this comment? crashes.resolved-users = Resolved upgrades @@ -161,22 +161,22 @@ crashes.help-latest-version = Latest app version that you released to market tha crashes.help-unresolved = Amount of unresolved crashes crashes.help-resolved = Percentage of the crashes that have been resolved over the total number of crashes that have occurred. crashes.help-frequency-short = How often in amount of sessions the app crashes for each user -crashes.help-affected-levels = Breakdown of affected users, who had at least one fatal crash, then at least one only non-fatal crash/catched exception and unaffected users, that did not have any crashes or their crashes were resolved. Amount of affected users gets reduced when users upgrade to version higher than for which crash was resolved +crashes.help-affected-levels = Breakdown of affected users, who had at least one fatal crash, then at least one non-fatal crash/caught exception, and unaffected users, that did not have any crashes or their crashes were resolved. The amount of affected users gets reduced when users upgrade to a version higher than the one for which the crash was resolved. crashes.help-platforms = Details of the platforms on which crashes have occurred. Top 4 platforms are listed here. crashes.help-fatals = Comparison of fatal crashes and non-fatal/catched exceptions crashes.help-new = Number of crashes that have not yet been viewed. crashes.help-reoccurred = Number of crashes that have occurred multiple times. -crashes.help-total = Timeline of all occurrences of all crashes. Same crash may occurred multiple times for same or different users. +crashes.help-total = Timeline of all occurrences of all crashes. The same crash may have occurred multiple times for the same or different users. crashes.help-nonfatal = Timeline of non-fatal crashes or catched exceptions that were reported to server crashes.help-session = Timeline for crashes/session in % -crashes.help-unique = Timeline of crash types. Only the first ocurrence of each crash time recorded here. +crashes.help-unique = Timeline of crash types. Only the first occurrence of each crash time is recorded here. crashes.help-fatal = Timeline of fatal crashes, which made users exit your app crashes.help-ram = Shows how much RAM was in use at the time of the crash, displaying the average, minimum, and maximum amounts of RAM used when the crash occurred. -crashes.help-disk = Shows how full was disk space in the moment of crash, displaying the average, minimum, and maximum values of all crashes -crashes.help-battery = Shows how full was the battery at the moment of crash, displaying the average, minimum, and maximum values of all crashes -crashes.help-run = Showing how long app was running before it crashed, displaying the average, minimum, and maximum values of all crashes -crashes.help-frequency = Showing how often in amount of sessions does the app crash for each user, displaying minimum amount of sessions between crashes, maximum amount and average value of sessions between each repeated crash -crashes.help-free-users= Number of users who have not experienced a crash for the applied filter in the selected time period, expressed as a percentage of the total number of users within that time period. +crashes.help-disk = Shows how full the disk space was at the moment of the crash, displaying the average, minimum, and maximum values of all crashes. +crashes.help-battery = Shows how full the battery was at the moment of the crash, displaying the average, minimum, and maximum values of all crashes. +crashes.help-run = Shows how long the app was running before it crashed, displaying the average, minimum, and maximum values of all crashes. +crashes.help-frequency = Shows how often, in the amount of sessions, the app crashes for each user, displaying the minimum amount of sessions between crashes, the maximum amount, and the average value of sessions between each repeated crash. +crashes.help-free-users= The number of users who have not experienced a crash for the applied filter in the selected time period, expressed as a percentage of the total number of users within that time period. crashes.help-free-sessions = Number of sessions during which the selected crash did not occur in the selected time period, expressed as a percentage of the total number of sessions within that time period. crashes.help-crash-fatality = Number of fatal crashes, expressed as a percentage of the total number of crashes that have occurred. diff --git a/plugins/dashboards/frontend/public/localization/dashboards.properties b/plugins/dashboards/frontend/public/localization/dashboards.properties index fd7b8a91824..b5b456cc996 100644 --- a/plugins/dashboards/frontend/public/localization/dashboards.properties +++ b/plugins/dashboards/frontend/public/localization/dashboards.properties @@ -1,13 +1,13 @@ #No dashboards dashboards.home-title = Welcome to Dashboards -dashboards.home-description = Dashboards lets you visualise data for multiple applications and metrics with ease. Using full screen mode on a TV you will always be on top of your KPIs. +dashboards.home-description = Dashboards let you visualize data for multiple applications and metrics with ease. By using full-screen mode on a TV, you'll always stay on top of your KPIs. dashboards.save-dashboard = Save Changes dashboards.activate-full-screen = Activate full screen mode #No widgets dashboards.empty-dashboard = Your dashboard is empty -dashboards.empty-dashboard-description = Create your own composition of widgets to focus on metrics most important for your business -dashboards.select-cohorts-multi = Select maximum 5 cohorts +dashboards.empty-dashboard-description = Create your own composition of widgets to focus on the metrics most important to your business +dashboards.select-cohorts-multi = Select up to 5 cohorts dashboards.cohorts-label = Cohorts dashboards.cohorts-visualization = Visualization dashboards.bar-chart-multi-cohort = Bar Chart @@ -22,7 +22,7 @@ dashboards.create-and-add = Create and add widget dashboards.save-changes = Save Changes dashboards.dashboard-theme = Dashboard theme -dashboards.create-email-reports = Create E-mail Report +dashboards.create-email-reports = Create Email Report dashboards.select_dashboards = Select custom dashboard to receive reports from dashboards.select-report-date-range = Select dashboard data date range dashboards.select = Select dashboard @@ -44,7 +44,7 @@ dashbaords.dashboard-theme-7 = Deep Blue dashboards.compared-to-prev-period = compared to prev.period dashboards.sharing_status = Allow Dashboard Sharing -configs.help.dashboards-sharing_status = Enable dashboard sharing for users to share a dashboard with other users. If set to off, a dashboard cannot be shared with others. +configs.help.dashboards-sharing_status = Enable dashboard sharing for users to share a dashboard with other users. If set to off, dashboards cannot be shared with others. dashboards.access-denied = This dashboard is no longer shared with you or an error has occurred. Please ask your global administrator if you think this is due to an issue. dashbaords.access-denied-title = Access Denied dashboards.edit-access-denied = You don't have the edit permission for this dashboard. Please ask your global administrator if you think this is due to an issue. @@ -80,7 +80,6 @@ dashboards.custom-period.select-date-range = Select period - #Final localization dashboards.plugin-title = Dashboards @@ -94,7 +93,7 @@ dashboards.duplicate-dashboard-heading = Duplicate dashboard dashboards.create-dashboard = Create dashboard dashboards.save-dashboard = Save dashboard dashboards.share.all-users = All users -dashboards.share.all-users.description = Share view access to dashbaord with all users +dashboards.share.all-users.description = Share view access to dashboard with all users dashboards.share.selected-users = Some specific users dashboards.share.selected-users.description = Share the dashboard with some specific users dashboards.share.none = Private @@ -210,7 +209,7 @@ dashboards.crauf = Fatal Crash-Free Users dashboards.craunf = Non-Fatal Crash-Free Users dashboards.crfses = Fatal Crash-Free Sessions dashboards.crnfses = Non-Fatal Crash-Free Sessions -dashboards.send-email = Notify all users via emails +dashboards.send-email = Notify all users via email dashboards.additional-settings = Additional Settings dashboards.dashboard-invite-subtitle = A new dashboard on Countly was shared with you. dashboards.dashboard-invite-content = was shared with you with View permission. Click to access the dashboard. diff --git a/plugins/data_migration/frontend/public/localization/data_migration.properties b/plugins/data_migration/frontend/public/localization/data_migration.properties index 58c50a52b11..e8d4beb8ded 100644 --- a/plugins/data_migration/frontend/public/localization/data_migration.properties +++ b/plugins/data_migration/frontend/public/localization/data_migration.properties @@ -1,7 +1,7 @@ #titles data-migration.plugin-title = Data Migration data-migration.page-title = Data Migration -data-migration.plugin-description = Migrate your data from one Countly server to another +data-migration.plugin-description = Migrate data from one Countly server to another. data-migration.import-export-button-title = Export or import data data-migration.export-data = Export data data-migration.import-data = Import data @@ -17,7 +17,7 @@ data-migration.export-type-download-description = data-migration.server-token = Server token data-migration.server-address=Server address data-migration.server-token-description = Token generated in target server "Import form" -data-migration.server-address-description= As seen in browser +data-migration.server-address-description= As displayed in your browser. data-migration.export-data-button = Export data data-migration.send-export-button = Send export data-migration.test-connection = Test connection @@ -44,9 +44,9 @@ data-migration.create-another-token = Create another token data-migration.generated-token = Token has been generated data-migration.copy-url = Copy URL data-migration.copy-token = Copy Token -data-migration.tokken-coppied-in-clipboard = Server token copied into the clipboard -data-migration.address-coppied-in-clipboard = Server address copied into the clipboard -data-migration.close-without-copy = If you close this tab you won't be able to copy this token anymore. Do you want to close it? +data-migration.tokken-coppied-in-clipboard = Server token copied to the clipboard +data-migration.address-coppied-in-clipboard = Server address copied to the clipboard +data-migration.close-without-copy = If you close this tab, you won't be able to copy this token anymore. Do you want to close it? data-migration.close-confirm-title = Close tab? data-migration.cancel = Cancel data-migration.continue-and-close = Continue and close @@ -91,7 +91,7 @@ data-migration.resend-export = Send export #confirms,notifications data-migration.delete-log-confirm = Do you really want to delete the log file? data-migration.delete-export-confirm = Do you really want to delete export files? -data-migration.delete-import-confirm = Do you really want to delete export files and the log file? +data-migration.delete-import-confirm = Do you really want to delete the export files and the log file? data-migration.app-redirected = App({app_name}) is redirected. data-migration.app-redirected-explanation = All incoming SDK calls for this app are redirected to remote server: data-migration.app-redirected-remove = Click to go to app settings @@ -127,7 +127,7 @@ data-migration.failed-generate-scripts = Failed to generate export scripts data-migration.failed-sending = Your previous export has failed in sending phase. You can try to resend data or delete previously exported data and start a new export process. data-migration.export-stopped = Export process is stopped. You can delete data and start new process. data-migration.export-started = Export process has successfully started. -data-migration.target-server-not-valid= Target server address is not valid +data-migration.target-server-not-valid= Target server address is invalid data-migration.enter-your-server-address = Enter your server address data-migration.enter-your-server-token = Enter your server token data-migration.enter-your-export-folder = Enter your export folder @@ -149,7 +149,7 @@ data-migration.import-started = Import process started successfully data-migration.import-file-missing = Import file is missing. data-migration.import-process-exist = There is an ongoing import process on target server with same apps. Clear out the data on target server to start a new import process. data-migration.file-to-big-warning = Chosen file exceeds server limitation for maximum file size. Please modify your server settings to allow uploading bigger files. -data-migration.file-to-big-error = File is to large to upload to server. Please modify your server settings to allow uploading bigger files. +data-migration.file-to-big-error = File is too large to upload to the server. Please modify your server settings to allow uploading bigger files. data-migration.badformat = Uploaded file should be .tar.gz data-migration.could-not-find-file = Could not find file on server data-migration.unable-to-delete-log-file = Unable to delete log file diff --git a/plugins/guides/frontend/public/localization/guides.properties b/plugins/guides/frontend/public/localization/guides.properties index 6c2d76d58dd..bb9a4eb387f 100755 --- a/plugins/guides/frontend/public/localization/guides.properties +++ b/plugins/guides/frontend/public/localization/guides.properties @@ -1,7 +1,7 @@ #guides guides.plugin-title = Countly Guides -guides.plugin-description = Guides about Countly features, including articles and walkthroughs. +guides.plugin-description = Provides guides about Countly's features, including articles and walkthroughs. guides.overview = Overview guides.all = All guides.walkthrough = Walkthrough @@ -25,7 +25,7 @@ guides.search.in-guides = Search in Guides guides.search.in-countly-guides = Search in Countly Guides guides.search.results-count = {0} results for "{1}" guides.search.start = Start searching -guides.search.start-description= Type something and press enter to see the results +guides.search.start-description= Type something and press Enter to see the results guides.search.no-result = ...hmm, there are no results guides.search.no-result-description = Try adjusting your search to find what you’re looking for diff --git a/plugins/hooks/frontend/public/localization/hooks.properties b/plugins/hooks/frontend/public/localization/hooks.properties index 81d517625c9..36b41cf4e76 100644 --- a/plugins/hooks/frontend/public/localization/hooks.properties +++ b/plugins/hooks/frontend/public/localization/hooks.properties @@ -1,10 +1,10 @@ hooks.plugin-title = Hooks -hooks.plugin-description = Trigger external HTTP endpoints & receive emails based on incoming data and internal actions +hooks.plugin-description = Trigger external HTTP endpoints and receive emails based on incoming data and internal actions hooks.new-hook = New hook hooks.drawer-create-title = Create new hook hooks.hook-name = Hook name hooks.hook-description = Hook description -hooks.hook-description-note = An optional description that'll be visible to all users while viewing this hook. +hooks.hook-description-note = An optional description that will be visible to all users while viewing this hook. hooks.for_applications = For application hooks.trigger = Trigger hooks.effects = Actions @@ -13,9 +13,9 @@ hooks.save-hook = Save hook hooks.set-hook-trigger= Trigger Type hooks.select-effect = Select Action hooks.select-trigger = Select trigger -hooks.set-hook-effect = Select action +hooks.set-hook-effect = Select Action hooks.applications = Applications -hooks.create-by = Create by +hooks.create-by = Created by hooks.edit = Edit hooks.delete = Delete hooks.trigger-and-effects = Trigger & Actions @@ -29,11 +29,11 @@ hooks.delete-confirm = Confirm that you want to delete this hook. hooks.edit-your-hook = Edit your hook hooks.delete-confirm-title = Delete Hook hooks.batch-size = Action batch procesing size -hooks.pipelineInterval = Action pipeline interval -hooks.batchActionSize = Action batch procesing size -hooks.refreshRulesPeriod = Refresh rules period -hooks.requestLimit = Request limit -hooks.timeWindowForRequestLimit = Time window for request limit +hooks.pipelineInterval = Action Pipeline Interval +hooks.batchActionSize = Action Batch Processing Size +hooks.refreshRulesPeriod = Refresh Rules Period +hooks.requestLimit = Request Limit +hooks.timeWindowForRequestLimit = Time Window for Request Limit configs.help.hooks-pipelineInterval=The interval between each batch of actions. configs.help.hooks-batchActionSize=The number of actions to be processed in each batch. @@ -46,7 +46,7 @@ configs.help.hooks-timeWindowForRequestLimit=The time window for the request lim hooks.InternalEventTrigger = Internal Actions hooks.trigger-api-endpoint-uri= API Endpoint hooks.trigger-introduction = Introduction -hooks.trigger-api-endpoint-intro-content = Send a GET request with query string parameter "payload" as a JSON string to the below URL:
{0} +hooks.trigger-api-endpoint-intro-content = Send a GET request with the query string parameter "payload" as a JSON string to the URL below:
{0} hooks.APIEndPointTrigger = API Endpoint hooks.internal-event-selector-title = Internal Actions hooks.internal-event-selector-placeholder = Please select an internal action @@ -78,38 +78,38 @@ hooks.select-http-effect-method = HTTP Method hooks.query-string-or-json-body = Query string (for GET) or request body (for POST) hooks.http-method-get = GET hooks.http-method-post = POST -hooks.http-effect-description= Use {{payload_json}} to include the entire trigger data as a JSON object in your request body, or {{payload_string}} to include a stringified JSON in your query string. You can also use individual properties within the trigger data such as {{user}}. +hooks.http-effect-description= Use {{payload_json}} to include the entire trigger data as a JSON object in your request body, or {{payload_string}} to include a stringified JSON in your query string. You can also use individual properties within the trigger data, such as {{user}}. hooks.intro-hooks-trigger = /hooks/trigger will capture triggered data from the selected hook trigger. Output: Trigger output data from selected hook. -hooks.intro-i-app_users-delete= /i/app_users/delete will capture deleted user profiles.Output: Individual user profile data -hooks.intro-i-app_users-update = /i/app_users/update will capture updated user profiles.Output: Individual user profile data -hooks.intro-i-app_users-create = /i/app_users/create will capture created user profiles.Output: Individual user profile data -hooks.intro-cohort-exit = /cohort/exit will capture users who exit from the selected cohort. Output: Individual user profile data -hooks.intro-cohort-enter = /cohort/enter will capture users who enter into the selected cohort. Output: Individual user profile data -hooks.intro-incoming-data = Will capture event data when match filter rules. Output: Event data & user profile data. -hooks.copy-notify-message = API Endpoint URL is copied. +hooks.intro-i-app_users-delete= /i/app_users/delete will capture deleted user profiles. Output: Individual user profile data. +hooks.intro-i-app_users-update = /i/app_users/update will capture updated user profiles. Output: Individual user profile data. +hooks.intro-i-app_users-create = /i/app_users/create will capture created user profiles. Output: Individual user profile data. +hooks.intro-cohort-exit = /cohort/exit will capture users who exit from the selected cohort. Output: Individual user profile data. +hooks.intro-cohort-enter = /cohort/enter will capture users who enter into the selected cohort. Output: Individual user profile data. +hooks.intro-incoming-data = Will capture event data when filter rules match. Output: Event data & user profile data. +hooks.copy-notify-message = API Endpoint URL copied. hooks.copy-notify-title = Copy URL hooks.Select_country = Select Country hooks.Select_timezone = Select Timezone hooks.messages.name.placeholder = Name of your Hook -hooks.plugin-title-desc = An overview of all hooks set up. You can enable or disable any hook by using their respective toggle switch. +hooks.plugin-title-desc = An overview of all set up hooks. You can enable or disable any hook by using its respective toggle switch. hooks.status-all = All Hooks hooks.status-enabled = Enabled hooks.status-disabled = Disabled hooks.all-applications = All Applications -hooks.action = ACTION +hooks.action = Action hooks.select-application = Select an Application hooks.description-placeholder = Enter hook description hooks.name = Name hooks.description = Description hooks.optional = Optional hooks.source-application = Source Application -hooks.step1 = Basic-info +hooks.step1 = Basic Info hooks.step2 = Trigger hooks.step3 = Actions -hooks.trigger-intro = Set up the details of what will be the trigger for the hook. -hooks.effects-intro = Select the actions the hook will do upon being triggered. You can add more than one action. +hooks.trigger-intro = Set up the details of what will trigger the hook. +hooks.effects-intro = Select the actions the hook will perform upon being triggered. You can add more than one action. hooks.test-hook = HOOK TESTING hooks.test-hook-intro = Test your hooks to verify payloads or check if your hook setup is working properly before taking it live. @@ -121,28 +121,28 @@ hooks.trigger-via = Trigger Type hooks.api-trigger-intro = Send a GET request with query string parameter "payload" as a JSON string hooks.copy-url = Copy URL hooks.incoming-data = Data to trigger this hook -hooks.filter-rule = USE FILTERING RULE -hooks.scheduled-trigger-intro = Select the frequency and time to set the period to trigger hook automatically +hooks.filter-rule = Use Filtering Rule +hooks.scheduled-trigger-intro = Select the frequency and time to set the period to trigger the hook automatically hooks.back-to-hooks=Back to Hooks hooks.filtering-tips = Description for filtering rule hooks.edit = Edit hooks.delete = Delete hooks.app-desc=Select the app for which the hook will be created. -hooks.detail-title = HOOK DETAILS +hooks.detail-title = Hook Details hooks.trigger-count=Trigger Count hooks.trigger-and-effect = Trigger and Actions hooks.trigger-time = Last Trigger Time hooks.download-stacktrace = Download Stacktrace -hooks.stacktrace = ERROR LOGS +hooks.stacktrace = Error Logs hooks.time=Time hooks.action-step = Action Step -hooks.trigger-data = trigger data -hooks.action-data = Action data -hooks.trigger-tips = Set up the details of what will be the trigger for the hook. -hooks.actions-tips = Select the actions the hook will do upon being triggered. You can add more than one action. +hooks.trigger-data = Trigger Data +hooks.action-data = Action Data +hooks.trigger-tips = Set up the details of what will trigger the hook. +hooks.actions-tips = Select the actions the hook will perform upon being triggered. You can add more than one action. hooks.application-tips = The app(s) for which you want to create a hook. hooks.trigger-count-tips = Number of times the hook has been triggered. -hooks.trigger-action-tips = Identifies the trigger for the hook, and the actions that show the method through which data will be sent. +hooks.trigger-action-tips = Identifies the trigger for the hook and the actions that show the method through which data will be sent. hooks.trigger-save-failed = Hook could not be saved. systemlogs.action.hook_created = Hook Created diff --git a/plugins/locale/frontend/public/localization/locale.properties b/plugins/locale/frontend/public/localization/locale.properties index a11741e97b0..e64d8445a6c 100644 --- a/plugins/locale/frontend/public/localization/locale.properties +++ b/plugins/locale/frontend/public/localization/locale.properties @@ -2,7 +2,7 @@ languages.title = Languages languages.table.language = Language sidebar.analytics.languages = Languages -help.languages.chart = Details of the application languages your users are using, in the selected time period and as determined by their default device language settings. +help.languages.chart = Details of the application's languages your users use in the selected time period, based on their default device language settings. locale.plugin-title = Languages -locale.plugin-description = Display device locale/language metric \ No newline at end of file +locale.plugin-description = Displays device locale and language metrics. \ No newline at end of file diff --git a/plugins/logger/frontend/public/localization/logger.properties b/plugins/logger/frontend/public/localization/logger.properties index ccb5e5a2401..f6a379f88c4 100644 --- a/plugins/logger/frontend/public/localization/logger.properties +++ b/plugins/logger/frontend/public/localization/logger.properties @@ -1,6 +1,6 @@ #logger logger.title = Incoming Data Logs -logger.description = Log requests made to the write API to review and debug incoming data +logger.description = Logs requests made to the write API to review and debug incoming data. logger.all = All Requests logger.event = Events logger.session = Sessions @@ -23,9 +23,9 @@ logger.request-header = Headers logger.request-payload = Data logger.request-reponse = Response logger.request-canceled = Request Canceled -logger.problems = Problems occurred -logger.collection-description = Only up to last {0} incoming data logs are stored -logger.capped-remind = Your collection is not capped yet! Please notice that it may slow down the system performance. +logger.problems = Problems occurred. +logger.collection-description = Only up to the last {0} incoming data logs are stored +logger.capped-remind = Your collection is not capped yet. Please note that this may slow down system performance. logger.state = Set incoming data logging state logger.limit = Set incoming data logging limit per minute logger.state-on = On @@ -39,5 +39,5 @@ logger.request-query = Request query logger.request-header = Request header logger.version = Version -configs.help.logger-state = If incoming data logging state is set to "On", only the last 1000 requests will be saved. When the state is set to "Automatic", requests will continue to be logged until the limit per minute is reached. +configs.help.logger-state = If the incoming data logging state is set to "On", only the last 1000 requests will be saved. When the state is set to "Automatic", requests will continue to be logged until the limit per minute is reached. configs.help.logger-limit = Incoming data logging will turn off automatically when the number of requests logged per minute limit is reached. This will apply only when request logger state is set to "Automatic". \ No newline at end of file diff --git a/plugins/old-ui-compatibility/frontend/public/localization/old-ui-compatibility.properties b/plugins/old-ui-compatibility/frontend/public/localization/old-ui-compatibility.properties index 717d44f2f99..02752286c65 100644 --- a/plugins/old-ui-compatibility/frontend/public/localization/old-ui-compatibility.properties +++ b/plugins/old-ui-compatibility/frontend/public/localization/old-ui-compatibility.properties @@ -1,4 +1,4 @@ #old-ui-compatibility -old-ui-compatibility.plugin-title = Old UI compatability -old-ui-compatibility.plugin-description = Plugin to support old UI type plugins +old-ui-compatibility.plugin-title = Old UI compatibility +old-ui-compatibility.plugin-description = Provides compatibility for older UI-type plugins. diff --git a/plugins/push/frontend/public/localization/push.properties b/plugins/push/frontend/public/localization/push.properties index 5c292620973..3a2eb327a15 100755 --- a/plugins/push/frontend/public/localization/push.properties +++ b/plugins/push/frontend/public/localization/push.properties @@ -1,14 +1,14 @@ push-notification.title = Push Notifications -push-notification.description = An overview of all push notifications sent and actions performed in response. +push-notification.description = An overview of all push notifications sent, along with the user actions performed in response. push-notification.one-time = One-time Notifications push-notification.automated = Automated Notifications push-notification.transactional = API Notifications push-notification.total-app-users = Total App Users push-notification.enabled-users = Notification-enabled Users push-notification.enabled-users-percentage = Enabled Users Percentage -push-notification.enabled-users-percentage-description = Number of users who have agreed to receive notifications, expressed as a percentage over the total number of app users. +push-notification.enabled-users-percentage-description = The number of users who have agreed to receive notifications, expressed as a percentage of the total number of app users. push-notification.platform-filter-label-one-time = One-time notifications for -push-notification.platform-filter-label-automatic = Automatic notificatons for +push-notification.platform-filter-label-automatic = Automatic notifications for push-notification.platform-filter-label-transactional = Transactional notifications for push-notification.platform-filter-all = All Platforms push-notification.platform-filter-android = Android @@ -21,7 +21,7 @@ push-notification.unknown-error = Unknown error occurred. Please try again later push-notification.sent-serie-name = Notifications Sent push-notification.sent-serie-description = Total number of notifications sent in the selected time period. push-notification.actions-performed-serie-name = Actions Performed -push-notification.actions-performed-serie-description = Total number of actions performed by users in response to notifications sent, in the selected time period. +push-notification.actions-performed-serie-description = Total number of user actions performed in response to sent notifications within the selected time period. push-notification.table-notification-name = Notification name push-notification.table-status = Status push-notification.table-created = Created @@ -57,7 +57,7 @@ push-notification.right-before-sending-the-message = Right before sending the me push-notification.segmented-push-enabled-users = Segmented push-enabled users push-notification.delivery-type = Delivery Type push-notification.delivery-timeframe = Delivery Timeframe -push-notification.delivery-timeframe-description = Select the time you want the automated notifications to start being sent to users. +push-notification.delivery-timeframe-description = Select the time to start sending automated notifications to users. push-notification.trigger-type = Trigger Type push-notification.ios-badge-number-setting = IOS badge number push-notification.ios-json-data-setting = IOS JSON data @@ -88,19 +88,19 @@ push-notification.platforms = Platforms push-notification.android = Android push-notification.ios = iOS push-notification.targeting = Targeting -push-notification.targeting-tooltip = Select how to target the users who will recieve the notification. +push-notification.targeting-tooltip = Select how to target the users who will receive the notification. push-notification.all-push-enabled-users = All push-enabled users push-notification.all-push-enabled-users-description = Send to all users who have enabled receiving notifications. push-notification.use-segmentation = Use segmentation push-notification.use-segmentation-description = Send to users based on specific segmentation such as cohorts or locations. push-notification.push-enabled-users = Push-enabled users -push-notification.send-to-users-in-cohorts = Send to the users currently in selected cohorts(s) +push-notification.send-to-users-in-cohorts = Send to the users currently in selected cohort(s) push-notification.send-to-users-in-cohorts-description = Select cohort(s) of users who qualify to receive the notification. -push-notification.send-to-users-in-locations = Send to the users currently in selected Geolocations +push-notification.send-to-users-in-locations = Send to the users currently in selected Geolocation(s) push-notification.send-to-users-in-locations-description = Select geolocation(s) of users to whom you want to send the notification (e.g. users located in France). push-notification.select-event-to-set-trigger = Select one or more events to set the trigger push-notification.select-event-to-set-trigger-description = Select one or more events to set the trigger. -push-notification.select-cohort-to-set-trigger = Select one ore more cohorts to set the trigger +push-notification.select-cohort-to-set-trigger = Select one or more cohorts to set the trigger push-notification.select-cohort-to-set-trigger-description = Recalculation of cohorts above will trigger sending process automatically. push-notification.select-location = Please select a location push-notification.when-to-determine-users = When to determine the users? @@ -110,9 +110,9 @@ push-notification.determine-users-now = Determine users now push-notification.triggers = Triggers push-notification.triggers-description = Select the user behavior that will trigger the message sending process automatically. push-notification.cohorts-entry = Cohort(s) entry -push-notification.cohorts-entry-description = Triggered when user enters into any of the cohorts you select. +push-notification.cohorts-entry-description = Triggered when a user enters any of the cohorts you select. push-notification.cohorts-exit = Cohort(s) exit -push-notification.cohorts-exit-description = Triggered when user exits from any of the cohorts you select. +push-notification.cohorts-exit-description = Triggered when a user exits from any of the cohorts you select. push-notification.performed-events = Performed Event(s) push-notification.performed-events-description = Triggered when user performs a selected event. push-notification.select-event = Please select an event @@ -138,7 +138,7 @@ push-notification.relative-to-the-date-event-server = Relative to the date event push-notification.relative-to-the-date-event-device = Relative to the date event occurred on a device push-notification.send-anyway = Send anyway push-notification.cancel-when-user-exits-cohort = Cancel when user exits selected cohort(s) -push-notification.cancel-when-user-exits-cohort-description = Stops the message from being sent if the user is no longer in the selected cohort(s). +push-notification.cancel-when-user-exits-cohort-description = Stops sending the message if the user is no longer in the selected cohort(s). push-notification.send-now = Send now push-notification.send-now-description = Send the push notification immediately, once composition is complete. push-notification.scheduled = Scheduled @@ -156,7 +156,7 @@ push-notification.what-if-past-scheduled-tooltip = Select what happens if a user push-notification.do-not-send-message = Do not send the message push-notification.deliver-next-day = Deliver the message next day push-notification.immediately = Immediately -push-notification.immediately-description = Deliver this message as soon as triggering cohort is recalculated. +push-notification.immediately-description = Deliver this message as soon as the triggering cohort is recalculated. push-notification.delayed = Delayed push-notification.days = Days push-notification.hours = Hours @@ -216,7 +216,7 @@ push-notification.icon = Icon push-notification.icon-description = Set Android notification icon. push-notification.enter-icon = Enter icon push-notification.review-message = Review Mesage -push-notification.review-message-tooltip = Review all the details of you push notification. +push-notification.review-message-tooltip = Review all the details of your push notification. push-notification.message-name = Message name push-notification.review-title = Title push-notification.content = Content @@ -274,7 +274,7 @@ push-notification.remove = Remove push-notification.confirm = Confirm push-notification.internal-properties = Internal Properties push-notification.external-properties = External Properties -push-notification-fallback-value-description = User''s \"{0}\" property which falls back to \"{1}\" +push-notification-fallback-value-description = User's "{0}" property which falls back to "{1}" # Details diff --git a/plugins/star-rating/frontend/public/localization/star-rating.properties b/plugins/star-rating/frontend/public/localization/star-rating.properties index 3dfa2c60a72..7356b59e652 100644 --- a/plugins/star-rating/frontend/public/localization/star-rating.properties +++ b/plugins/star-rating/frontend/public/localization/star-rating.properties @@ -113,7 +113,7 @@ feedback.where-to-collect-feedback = Where to collect ratings? feedback.all-pages = On all pages feedback.selected-pages = On selected pages feedback.internalName = Internal Name -feedback.internalName.placeholder = Enter a internal Name +feedback.internalName.placeholder = Enter an Internal Name feedback.internalName.description = This name is internal and will not be shown to your end user. feedback.consent = Add user consent feedback.question = Question diff --git a/plugins/systemlogs/frontend/public/localization/systemlogs.properties b/plugins/systemlogs/frontend/public/localization/systemlogs.properties index 9a86cd6c9d7..b03d01bba77 100644 --- a/plugins/systemlogs/frontend/public/localization/systemlogs.properties +++ b/plugins/systemlogs/frontend/public/localization/systemlogs.properties @@ -1,7 +1,7 @@ #system logs systemlogs.title = Audit Logs -systemlogs.description = Logs dashboard user actions and data access +systemlogs.description = Logs user actions and data access on the dashboard. systemlogs.user = User systemlogs.action = Action systemlogs.timestamp = Time @@ -11,8 +11,8 @@ systemlogs.view-user-actions = View User Actions systemlogs.all-users = All Users systemlogs.all-actions = All Actions systemlogs.no-data = No additional data to display -systemlogs.has-data = With following data -systemlogs.changed-data = Following data was changed +systemlogs.has-data = With the following data +systemlogs.changed-data = The following data was changed systemlogs.field = Field systemlogs.value = Value systemlogs.before = Before @@ -25,7 +25,7 @@ systemlogs.for-crash = For Crash systemlogs.for-id = For ID systemlogs.data = Data configs.systemlogs-preventIPTracking = Disable IP Tracking -configs.help.systemlogs-preventIPTracking = Do not record IP address of actions taken by the users +configs.help.systemlogs-preventIPTracking = Do not record the IP address of actions taken by the users. systemlogs.action.logout = Logout systemlogs.action.password_reset = Password Reset @@ -50,17 +50,17 @@ systemlogs.action.user_updated = User Updated systemlogs.action.user_deleted = User Deleted systemlogs.action.graph_note_created = Graph Note Created systemlogs.action.graph_note_deleted = Graph Note Deleted -systemlogs.action.events_updated = Events updated -systemlogs.action.event_deleted = Event deleted +systemlogs.action.events_updated = Events Updated +systemlogs.action.event_deleted = Event Deleted systemlogs.action.export_app_user_deleted = App User export file deleted -systemlogs.action.export_app_user_started = App User export started -systemlogs.action.export_app_user = App User export finished +systemlogs.action.export_app_user_started = App User Export Started. +systemlogs.action.export_app_user = App User Export Finished. systemlogs.action.app_user_created = App User Created systemlogs.action.app_user_updated = App User Updated systemlogs.action.app_user_deleted = App User Deleted -systemlogs.action.token_login_failed = Login using token Failed -systemlogs.action.token_login_successfull = Login using token Successful -systemlogs.action.user_account_deleted = User has deleted his account +systemlogs.action.token_login_failed = Login Using Token Failed +systemlogs.action.token_login_successfull = Login Using Token Successful +systemlogs.action.user_account_deleted = User has deleted their account. systemlogs.action.feedback_widget_created = Feedback widget created systemlogs.action.feedback_widget_edited = Feedback widget edited systemlogs.action.feedback_widget_removed = Feedback widget removed @@ -68,9 +68,9 @@ systemlogs.action.feedback_widget_removed_with_data = Feedback widget removed wi systemlogs.action.populator_template_created = Populator template created systemlogs.action.populator_template_removed = Populator template removed systemlogs.action.populator_template_edited = Populator template edited -systemlogs.action.view_recalculation_finished = View recalculation finished -systemlogs.action.view_segments_ommit = View segments ommit -systemlogs.action.view_segments_ommit_complete = View segments ommit complete +systemlogs.action.view_recalculation_finished = View recalculation finished. +systemlogs.action.view_segments_ommit = View Segments Omitted +systemlogs.action.view_segments_ommit_complete = View Segments Omission Complete. systemlogs.action.cb-content_asset-updated = Content Builder Asset Updated systemlogs.action.cb-content_asset-uploaded = Content Builder Asset Uploaded systemlogs.action.cb-content_asset-deleted = Content Builder Asset Deleted diff --git a/plugins/times-of-day/frontend/public/localization/times-of-day.properties b/plugins/times-of-day/frontend/public/localization/times-of-day.properties index 1f7affa0c00..f7f36af7c48 100755 --- a/plugins/times-of-day/frontend/public/localization/times-of-day.properties +++ b/plugins/times-of-day/frontend/public/localization/times-of-day.properties @@ -1,5 +1,5 @@ times-of-day.title = Times of Day -times-of-day.description = Scatter plot chart with times and days of Session and Event occurrences in your application, based on users' local time. +times-of-day.description = Shows a scatter plot chart with the times and days of session and event occurrences in your application, based on users' local time. times-of-day.results-for = Results for times-of-day.total-users = Total users times-of-day.between = between diff --git a/plugins/views/api/api.js b/plugins/views/api/api.js index 8d5d9cdbca6..6668dac8a45 100644 --- a/plugins/views/api/api.js +++ b/plugins/views/api/api.js @@ -1349,178 +1349,216 @@ const escapedViewSegments = { "name": true, "segment": true, "height": true, "wi * @param {Object} params - Default parameters object * @returns {undefined} Returns nothing */ - function getHeatmap(params) { - var result = {types: [], data: []}; + async function getHeatmap(params) { + const result = {types: [], data: [], domains: []}; - var device = {}; + let device = {}; try { device = JSON.parse(params.qstring.device); } catch (SyntaxError) { - console.log('Parse device failed: ', params.qstring.device); + log.e('Parse device failed: ', params.qstring.device); } - var actionType = params.qstring.actionType; + const actionType = params.qstring.actionType; if (!(device.minWidth >= 0) || !(device.maxWidth >= 0)) { common.returnMessage(params, 400, 'Bad request parameter: device'); return false; } - var collectionName = "drill_events" + crypto.createHash('sha1').update("[CLY]_action" + params.qstring.app_id).digest('hex'); - common.drillDb.collection(collectionName).findOne({"_id": "meta_v2"}, {_id: 0, "sg.type": 1, "sg.domain": 1}, function(err1, meta) { - if (meta && meta.sg && meta.sg.type) { - result.types = Object.keys(meta.sg.type.values); + + if (params.qstring.period) { + //check if period comes from datapicker + if (params.qstring.period.indexOf(',') !== -1) { + try { + params.qstring.period = JSON.parse(params.qstring.period); + } + catch (SyntaxError) { + log.d('Parsing custom period failed!'); + common.returnMessage(params, 400, 'Bad request parameter: period'); + return false; + } } else { - result.types = []; + switch (params.qstring.period) { + case 'month': + case 'day': + case 'yesterday': + case 'hour': + break; + default: + if (!/([0-9]+)days/.test(params.qstring.period)) { + common.returnMessage(params, 400, 'Bad request parameter: period'); + return false; + } + break; + } } - if (meta && meta.sg && meta.sg.domain) { - result.domains = Object.keys(meta.sg.domain.values).map(function(item) { - return common.db.decode(item); - }); + } + else { + common.returnMessage(params, 400, 'Missing request parameter: period'); + return false; + } + + countlyCommon.setTimezone(params.appTimezone); + countlyCommon.setPeriod(params.qstring.period); + + const periodObj = countlyCommon.periodObj; + const matchQuery = {}; + const now = params.time.now.toDate(); + + //create current period array if it does not exist + if (!periodObj.currentPeriodArr) { + periodObj.currentPeriodArr = []; + + //create a period array that starts from the beginning of the current year until today + if (params.qstring.period === 'month') { + for (let i = 0; i < (now.getMonth() + 1); i++) { + const moment1 = moment(); + const daysInMonth = moment1.month(i).daysInMonth(); + + for (let j = 0; j < daysInMonth; j++) { + periodObj.currentPeriodArr.push(periodObj.activePeriod + '.' + (i + 1) + '.' + (j + 1)); + + // If current day of current month, just break + if ((i === now.getMonth()) && (j === (now.getDate() - 1))) { + break; + } + } + } } + //create a period array that starts from the beginning of the current month until today + else if (params.qstring.period === 'day') { + for (let i = 0; i < now.getDate(); i++) { + periodObj.currentPeriodArr.push(periodObj.activePeriod + '.' + (i + 1)); + } + } + //create one day period array else { - result.domains = []; + periodObj.currentPeriodArr.push(periodObj.activePeriod); } - common.drillDb.collection(collectionName).findOne({"_id": "meta"}, {_id: 0, "sg.type": 1, "sg.domain": 1}, function(err2, meta2) { - if (meta2 && meta2.sg && meta2.sg.type) { - common.arrayAddUniq(result.types, meta2.sg.type.values); - } - if (meta2 && meta2.sg && meta2.sg.domain) { - common.arrayAddUniq(result.domains, meta2.sg.domain.values); - } - var eventHash = crypto.createHash('sha1').update("[CLY]_action" + params.qstring.app_id).digest('hex'); - var collectionMeta = "drill_meta" + params.qstring.app_id; - common.drillDb.collection(collectionMeta).findOne({"_id": "meta_" + eventHash}, {_id: 0, "sg.domain": 1}, function(err3, meta_event) { - if (meta_event && meta_event.sg && meta_event.sg.type) { - common.arrayAddUniq(result.types, Object.keys(meta_event.sg.type.values)); - } - if (meta_event && meta_event.sg && meta_event.sg.domain) { - common.arrayAddUniq(result.domains, Object.keys(meta_event.sg.domain.values)); - } + } - if (params.qstring.period) { - //check if period comes from datapicker - if (params.qstring.period.indexOf(",") !== -1) { - try { - params.qstring.period = JSON.parse(params.qstring.period); - } - catch (SyntaxError) { - log.d('Parsing custom period failed!'); - common.returnMessage(params, 400, 'Bad request parameter: period'); - return false; - } - } - else { - switch (params.qstring.period) { - case "month": - case "day": - case "yesterday": - case "hour": - break; - default: - if (!/([0-9]+)days/.test(params.qstring.period)) { - common.returnMessage(params, 400, 'Bad request parameter: period'); - return false; - } - break; - } - } - } - else { - common.returnMessage(params, 400, 'Missing request parameter: period'); - return false; - } - countlyCommon.setTimezone(params.appTimezone); - countlyCommon.setPeriod(params.qstring.period); - var periodObj = countlyCommon.periodObj, - queryObject = {}, - now = params.time.now.toDate(); + //get timestamps of start of days (DD-MM-YYYY-00:00) with respect to apptimezone for both beginning and end of period arrays + let tmpArr; + const ts = {}; - //create current period array if it does not exist - if (!periodObj.currentPeriodArr) { - periodObj.currentPeriodArr = []; + tmpArr = periodObj.currentPeriodArr[0].split('.'); + ts.$gte = moment(new Date(Date.UTC(parseInt(tmpArr[0]), parseInt(tmpArr[1]) - 1, parseInt(tmpArr[2])))); + if (params.appTimezone) { + ts.$gte.tz(params.appTimezone); + } + ts.$gte = ts.$gte.valueOf() - ts.$gte.utcOffset() * 60000; - //create a period array that starts from the beginning of the current year until today - if (params.qstring.period === "month") { - for (let i = 0; i < (now.getMonth() + 1); i++) { - var moment1 = moment(); - var daysInMonth = moment1.month(i).daysInMonth(); + tmpArr = periodObj.currentPeriodArr[periodObj.currentPeriodArr.length - 1].split('.'); + ts.$lt = moment(new Date(Date.UTC(parseInt(tmpArr[0]), parseInt(tmpArr[1]) - 1, parseInt(tmpArr[2])))).add(1, 'days'); + if (params.appTimezone) { + ts.$lt.tz(params.appTimezone); + } + ts.$lt = ts.$lt.valueOf() - ts.$lt.utcOffset() * 60000; + + matchQuery.ts = ts; + matchQuery.a = params.qstring.app_id; + matchQuery.e = '[CLY]_action'; + matchQuery['sg.width'] = {}; + matchQuery['sg.width'].$gt = device.minWidth; + matchQuery['sg.width'].$lte = device.maxWidth; + matchQuery['sg.type'] = actionType; + + const projectionQuery = { + _id: 0, + c: 1, + 'sg.type': 1, + 'sg.width': 1, + 'sg.height': 1 + }; + + if (actionType === 'scroll') { + projectionQuery['sg.y'] = 1; + matchQuery['sg.view'] = params.qstring.view; + } + else { + projectionQuery['sg.x'] = 1; + projectionQuery['sg.y'] = 1; + matchQuery['up.lv'] = params.qstring.view; + } - for (var j = 0; j < daysInMonth; j++) { - periodObj.currentPeriodArr.push(periodObj.activePeriod + "." + (i + 1) + "." + (j + 1)); + if (params.qstring.segment) { + matchQuery['sg.segment'] = params.qstring.segment; + } - // If current day of current month, just break - if ((i === now.getMonth()) && (j === (now.getDate() - 1))) { - break; - } - } - } - } - //create a period array that starts from the beginning of the current month until today - else if (params.qstring.period === "day") { - for (let i = 0; i < now.getDate(); i++) { - periodObj.currentPeriodArr.push(periodObj.activePeriod + "." + (i + 1)); - } - } - //create one day period array - else { - periodObj.currentPeriodArr.push(periodObj.activePeriod); - } - } + const aggregateQuery = [ + { $match: matchQuery }, + ]; + + const use_union_with = plugins.getConfig('drill', params.app_id && params.app && params.app.plugins, true).use_union_with; + + if (use_union_with) { + const oldCollectionName = 'drill_events' + crypto.createHash('sha1').update('[CLY]_action' + params.qstring.app_id).digest('hex'); + const eventHash = crypto.createHash('sha1').update('[CLY]_action' + params.qstring.app_id).digest('hex'); + + const metaQuery = [ + { + $facet: { + meta: [ + { $match: { _id: 'meta' } }, + { $project: { _id: 0, 'sg.type': 1, 'sg.domain': 1 } }, + { $limit: 1 }, + ], + meta_v2: [ + { $match: { _id: 'meta_v2' } }, + { $project: { _id: 0, 'sg.type': 1, 'sg.domain': 1 } }, + { $limit: 1 }, + ], + }, + }, + ]; - //get timestamps of start of days (DD-MM-YYYY-00:00) with respect to apptimezone for both beginning and end of period arrays - var tmpArr; - var ts = {}; + const metaKeys = ['meta', 'meta_v2']; + const metas = await common.drillDb.collection(oldCollectionName).aggregate(metaQuery).toArray(); + metaKeys.forEach((key) => { + if (key in metas[0]) { + const meta = metas[0][key][0]; - tmpArr = periodObj.currentPeriodArr[0].split("."); - ts.$gte = moment(new Date(Date.UTC(parseInt(tmpArr[0]), parseInt(tmpArr[1]) - 1, parseInt(tmpArr[2])))); - if (params.appTimezone) { - ts.$gte.tz(params.appTimezone); + if (meta && meta.sg && meta.sg.type && meta.sg.type.values) { + common.arrayAddUniq(result.types, meta.sg.type.values); } - ts.$gte = ts.$gte.valueOf() - ts.$gte.utcOffset() * 60000; - tmpArr = periodObj.currentPeriodArr[periodObj.currentPeriodArr.length - 1].split("."); - ts.$lt = moment(new Date(Date.UTC(parseInt(tmpArr[0]), parseInt(tmpArr[1]) - 1, parseInt(tmpArr[2])))).add(1, 'days'); - if (params.appTimezone) { - ts.$lt.tz(params.appTimezone); + if (meta && meta.sg && meta.sg.domain && meta.sg.domain.values) { + common.arrayAddUniq(result.domains, meta.sg.domain.values); } - ts.$lt = ts.$lt.valueOf() - ts.$lt.utcOffset() * 60000; + } + }); - queryObject.ts = ts; - queryObject["sg.width"] = {}; - queryObject["sg.width"].$gt = device.minWidth; - queryObject["sg.width"].$lte = device.maxWidth; - queryObject["sg.type"] = actionType; + const moreMeta = await common.drillDb.collection(`drill_meta${params.qstring.app_id}`).findOne( + { _id: `meta_${eventHash}` }, + { _id: 0, 'sg.domain': 1 }, + ); - var projections = { - _id: 0, - c: 1, - "sg.type": 1, - "sg.width": 1, - "sg.height": 1 - }; + if (moreMeta && moreMeta.sg && moreMeta.sg.domain) { + common.arrayAddUniq(result.domains, Object.keys(moreMeta.sg.domain.values)); + } - if (actionType === "scroll") { - projections["sg.y"] = 1; - queryObject["sg.view"] = params.qstring.view; - } - else { - projections["sg.x"] = 1; - projections["sg.y"] = 1; - queryObject["up.lv"] = params.qstring.view; - } + const matchQueryOld = Object.assign({}, matchQuery); + delete matchQueryOld.a; + delete matchQueryOld.e; - if (params.qstring.segment) { - queryObject["sg.segment"] = params.qstring.segment; - } - common.drillDb.collection(collectionName).find(queryObject, projections).toArray(function(err, data) { - result.data = data; - common.returnOutput(params, result, true, params.token_headers); - }); - }); + aggregateQuery.push({ + $unionWith: { coll: oldCollectionName, pipeline: [{ $match: matchQueryOld }] }, }); - }); + } + + aggregateQuery.push({ $project: projectionQuery }); + + try { + const data = await common.drillDb.collection('drill_events').aggregate(aggregateQuery, { allowDiskUse: true }).toArray(); + result.data = data; + common.returnOutput(params, result, true, params.token_headers); + } + catch (err) { + log.e(err); + common.returnMessage(params, 500, 'Error fetching drill events'); + } } plugins.register("/o/actions", function(ob) { diff --git a/plugins/views/tests/heatmaps.js b/plugins/views/tests/heatmaps.js new file mode 100644 index 00000000000..77e92f6e0d1 --- /dev/null +++ b/plugins/views/tests/heatmaps.js @@ -0,0 +1,202 @@ +const crypto = require('crypto'); + +const moment = require('moment'); +const should = require('should'); +const spt = require('supertest'); + +const pluginManager = require('../../pluginManager.js'); +const testUtils = require('../../../test/testUtils'); + +const request = spt(testUtils.url); +const APP_ID = testUtils.get('APP_ID'); +const API_KEY_ADMIN = testUtils.get('API_KEY_ADMIN'); +const APP_KEY = testUtils.get('APP_KEY'); + +describe('Heatmap', async() => { + const clickData = { + type: 'click', + x: 1353, + y: 230, + width: 1440, + height: 3586, + }; + + before(async() => { + await request + .get('/i') + .query({ + api_key: API_KEY_ADMIN, + app_id: APP_ID, + app_key: APP_KEY, + device_id: 'heatmap_test', + events: JSON.stringify([ + { + key: '[CLY]_view', + count: 1, + timestamp: moment('2010-01-02').valueOf(), + hour: 21, + segmentation: { + name: 'Home', + visit: 1, + start: 1, + exit: 1, + bounce: 0, + }, + }, + ]), + }) + .expect(200); + + await request + .get('/i') + .query({ + api_key: API_KEY_ADMIN, + app_id: APP_ID, + app_key: APP_KEY, + device_id: 'heatmap_test', + events: JSON.stringify([ + { + key: '[CLY]_action', + count: 1, + timestamp: moment('2010-01-02').valueOf(), + hour: 21, + segmentation: { + ...clickData, + domain: 'https://doma.in', + view: 'Home', + }, + }, + ]), + }) + .expect(200); + }); + + it('gets heatmap data from drill_events collection', async() => { + const { body } = await request.post('/o/actions') + .send({ + api_key: API_KEY_ADMIN, + app_id: APP_ID, + app_key: APP_KEY, + view: 'Home', + period: JSON.stringify([moment('2010-01-01').valueOf(), moment('2010-01-31').valueOf()]), + device: JSON.stringify({ type: 'all', displayText: 'All', minWidth: 0, maxWidth: 10240 }), + actionType: 'click', + }); + + const { data } = body; + should(data.length).equal(1); + should(data[0].sg).eql(clickData); + }); + + it('gets heatmap data from old drill_events collection if union_with is true', async() => { + const db = await pluginManager.dbConnection('countly_drill'); + const oldCollectionName = 'drill_events' + crypto.createHash('sha1').update('[CLY]_action' + APP_ID).digest('hex'); + + const resp = await request.get('/o/apps/plugins?api_key=' + API_KEY_ADMIN + '&app_id=' + APP_ID); + const drillConfig = resp.body.plugins.drill; + + drillConfig.use_union_with = true; + + await request.post('/i/apps/update/plugins') + .send({ + app_id: APP_ID, + api_key: API_KEY_ADMIN, + args: { drill: drillConfig }, + }); + + await db.collection(oldCollectionName).insertOne({ + did: 'heatmap_test', + sg: { + ...clickData, + domain: 'https://doma.in', + view: 'Home', + }, + ts: moment('2010-01-02').valueOf(), + up: { lv: 'Home' }, + }); + + const { body } = await request.post('/o/actions') + .send({ + api_key: API_KEY_ADMIN, + app_id: APP_ID, + app_key: APP_KEY, + view: 'Home', + period: JSON.stringify([moment('2010-01-01').valueOf(), moment('2010-01-31').valueOf()]), + device: JSON.stringify({ type: 'all', displayText: 'All', minWidth: 0, maxWidth: 10240 }), + actionType: 'click', + }); + + const { data } = body; + should(data.length).equal(2); + should(data[0].sg).eql(clickData); + should(data[1].sg).eql(clickData); + + await db.collection(oldCollectionName).remove({ did: 'heatmap_test' }); + + db.close(); + }); + + it('does not get heatmap data from old drill_events collection if union_with is false', async() => { + const db = await pluginManager.dbConnection('countly_drill'); + const oldCollectionName = 'drill_events' + crypto.createHash('sha1').update('[CLY]_action' + APP_ID).digest('hex'); + + const resp = await request.get('/o/apps/plugins?api_key=' + API_KEY_ADMIN + '&app_id=' + APP_ID); + const drillConfig = resp.body.plugins.drill; + + drillConfig.use_union_with = false; + + await request.post('/i/apps/update/plugins') + .send({ + app_id: APP_ID, + api_key: API_KEY_ADMIN, + args: { drill: drillConfig }, + }); + + await db.collection(oldCollectionName).insertOne({ + did: 'heatmap_test', + sg: { + ...clickData, + domain: 'https://doma.in', + view: 'Home', + }, + ts: moment('2010-01-02').valueOf(), + up: { lv: 'Home' }, + }); + + const { body } = await request.post('/o/actions') + .send({ + api_key: API_KEY_ADMIN, + app_id: APP_ID, + app_key: APP_KEY, + view: 'Home', + period: JSON.stringify([moment('2010-01-01').valueOf(), moment('2010-01-31').valueOf()]), + device: JSON.stringify({ type: 'all', displayText: 'All', minWidth: 0, maxWidth: 10240 }), + actionType: 'click', + }); + + const { data } = body; + should(data.length).equal(1); + should(data[0].sg).eql(clickData); + + drillConfig.use_union_with = true; + + await request.post('/i/apps/update/plugins') + .send({ + app_id: APP_ID, + api_key: API_KEY_ADMIN, + args: { drill: drillConfig }, + }); + + await db.collection(oldCollectionName).remove({ did: 'heatmap_test' }); + + db.close(); + }); + + after(async() => { + const db = await pluginManager.dbConnection('countly_drill'); + + await db.collection('drill_events').remove({ did: 'heatmap_test' }); + + db.close(); + }); +}); diff --git a/plugins/views/tests/index.js b/plugins/views/tests/index.js new file mode 100644 index 00000000000..c859552a2b3 --- /dev/null +++ b/plugins/views/tests/index.js @@ -0,0 +1,2 @@ +require('./views.js'); +//require('./heatmaps.js'); diff --git a/plugins/views/tests.js b/plugins/views/tests/views.js similarity index 99% rename from plugins/views/tests.js rename to plugins/views/tests/views.js index 8ec2675af0f..b1ffe532ee7 100644 --- a/plugins/views/tests.js +++ b/plugins/views/tests/views.js @@ -1,6 +1,6 @@ var request = require('supertest'); var should = require('should'); -var testUtils = require("../../test/testUtils"); +var testUtils = require("../../../test/testUtils"); request = request.agent(testUtils.url); var APP_KEY = ""; var API_KEY_ADMIN = ""; @@ -1319,4 +1319,4 @@ describe('Testing views plugin', function() { }); }); }); -}); \ No newline at end of file +}); diff --git a/ui-tests/cypress/lib/dashboard/analytics/events/overview.js b/ui-tests/cypress/lib/dashboard/analytics/events/overview.js index 58b3c5418d7..b40987d3d07 100644 --- a/ui-tests/cypress/lib/dashboard/analytics/events/overview.js +++ b/ui-tests/cypress/lib/dashboard/analytics/events/overview.js @@ -18,7 +18,7 @@ const verifyStaticElementsOfPage = () => { labelElement: eventsOverviewPageElements.PAGE_SUB_TITLE, labelText: "Event Metrics", tooltipElement: eventsOverviewPageElements.PAGE_SUB_TITLE_TOOLTIP, - tooltipText: "Overview of the metrics calculated by the identified Events, in the last 30 days." + tooltipText: "An overview of the metrics calculated by the identified Events in the last 30 days." }); cy.verifyElement({ @@ -337,7 +337,7 @@ const verifyMonitorEventsMetricCard = ({ cy.verifyElement({ labelElement: eventsOverviewMonitorEventsMetricCardElements().EMPTY_MONITOR_EVENTS_TABLE_TITLE, - labelText: "This application doesn't have any custom events", + labelText: "This application does not have any custom events.", }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/analytics/geo/countries/countries.js b/ui-tests/cypress/lib/dashboard/analytics/geo/countries/countries.js index a59b6b37565..2f9a2835a4f 100644 --- a/ui-tests/cypress/lib/dashboard/analytics/geo/countries/countries.js +++ b/ui-tests/cypress/lib/dashboard/analytics/geo/countries/countries.js @@ -9,7 +9,7 @@ const verifyStaticElementsOfPage = () => { labelElement: countriesPageElements.PAGE_TITLE, labelText: "Countries", tooltipElement: countriesPageElements.PAGE_TITLE_TOOLTIP, - tooltipText: "An overview of the geographical distribution of your users and their sessions in the selected time period." + tooltipText: "An overview of the geographical distribution of your users and their sessions within the selected time period." }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/analytics/geo/languages/languages.js b/ui-tests/cypress/lib/dashboard/analytics/geo/languages/languages.js index ca137d68dd2..c01e5510ec3 100644 --- a/ui-tests/cypress/lib/dashboard/analytics/geo/languages/languages.js +++ b/ui-tests/cypress/lib/dashboard/analytics/geo/languages/languages.js @@ -9,7 +9,7 @@ const verifyStaticElementsOfPage = () => { labelElement: languagesPageElements.PAGE_TITLE, labelText: "Languages", tooltipElement: languagesPageElements.PAGE_TITLE_TOOLTIP, - tooltipText: "Details of the application languages your users are using, in the selected time period and as determined by their default device language settings." + tooltipText: "Details of the application's languages your users use in the selected time period, based on their default device language settings." }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/analytics/loyalty/timesOfDay.js b/ui-tests/cypress/lib/dashboard/analytics/loyalty/timesOfDay.js index b2c2ee90c48..e04afc038c7 100644 --- a/ui-tests/cypress/lib/dashboard/analytics/loyalty/timesOfDay.js +++ b/ui-tests/cypress/lib/dashboard/analytics/loyalty/timesOfDay.js @@ -9,7 +9,7 @@ const verifyStaticElementsOfPage = () => { labelElement: timesOfDayPageElements.PAGE_TITLE, labelText: "Times of Day", tooltipElement: timesOfDayPageElements.PAGE_TITLE_TOOLTIP, - tooltipText: "Scatter plot chart with times and days of Session and Event occurrences in your application, based on users' local time." + tooltipText: "Shows a scatter plot chart with the times and days of session and event occurrences in your application, based on users' local time." }); cy.scrollPageToTop(); diff --git a/ui-tests/cypress/lib/dashboard/analytics/loyalty/userActivity.js b/ui-tests/cypress/lib/dashboard/analytics/loyalty/userActivity.js index 6203117101a..e60ef767d11 100644 --- a/ui-tests/cypress/lib/dashboard/analytics/loyalty/userActivity.js +++ b/ui-tests/cypress/lib/dashboard/analytics/loyalty/userActivity.js @@ -9,7 +9,7 @@ const verifyStaticElementsOfPage = () => { labelElement: userActivityPageElements.PAGE_TITLE, labelText: "User Activity", tooltipElement: userActivityPageElements.PAGE_TITLE_TOOLTIP, - tooltipText: "Overview of the total number of users who started a session on your application, distributed in pre-set categories of numbers of sessions." + tooltipText: "An overview of the total number of users who started a session on your application, distributed in pre-set categories based on the number of sessions." }); cy.scrollPageToTop(); diff --git a/ui-tests/cypress/lib/dashboard/analytics/sessions/frequency.js b/ui-tests/cypress/lib/dashboard/analytics/sessions/frequency.js index 58eba70c7a8..a6e22a2d007 100644 --- a/ui-tests/cypress/lib/dashboard/analytics/sessions/frequency.js +++ b/ui-tests/cypress/lib/dashboard/analytics/sessions/frequency.js @@ -9,7 +9,7 @@ const verifyStaticElementsOfPage = () => { labelElement: sessionFrequencyPageElements.PAGE_TITLE, labelText: "Session Frequency", tooltipElement: sessionFrequencyPageElements.PAGE_TITLE_TOOLTIP, - tooltipText: "Number of times users open your application, in the selected time period, distributed into frequency ranges." + tooltipText: "The number of times users open your application within the selected time period, distributed into frequency ranges." }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/analytics/sessions/overview.js b/ui-tests/cypress/lib/dashboard/analytics/sessions/overview.js index 43f87832d9b..433bdeed853 100644 --- a/ui-tests/cypress/lib/dashboard/analytics/sessions/overview.js +++ b/ui-tests/cypress/lib/dashboard/analytics/sessions/overview.js @@ -163,7 +163,7 @@ const verifySessionsOverviewChart = ({ labelElement: analyticsSessionOverviewEChartElements.CHART_TOTAL_SESSIONS_LABEL, labelText: "Total Sessions", tooltipElement: analyticsSessionOverviewEChartElements.CHART_TOTAL_SESSIONS_TOOLTIP, - tooltipText: "Number of times your application is opened, by new or returning users, in the selected time period.", + tooltipText: "The number of times your application is opened by new or returning users within the selected time period.", }); cy.verifyElement({ @@ -187,7 +187,7 @@ const verifySessionsOverviewChart = ({ labelElement: analyticsSessionOverviewEChartElements.CHART_NEW_SESSIONS_LABEL, labelText: "New Sessions", tooltipElement: analyticsSessionOverviewEChartElements.CHART_NEW_SESSIONS_TOOLTIP, - tooltipText: "Number of times your application is opened by a new user, in the selected time period. It is equal to the number of New Users and it only counts the first session the user had.", + tooltipText: "The number of times your application is opened by a new user within the selected time period. This is equal to the number of New Users and only counts the user's first session.", }); cy.verifyElement({ @@ -211,7 +211,7 @@ const verifySessionsOverviewChart = ({ labelElement: analyticsSessionOverviewEChartElements.CHART_UNIQUE_SESSIONS_LABEL, labelText: "Unique Sessions", tooltipElement: analyticsSessionOverviewEChartElements.CHART_UNIQUE_SESSIONS_TOOLTIP, - tooltipText: "Number of times your application is opened by a new or returning user from a unique device, in the selected time period. It is equal to the number of Total Users.", + tooltipText: "The number of times your application is opened by a new or returning user from a unique device within the selected time period. This is equal to the number of Total Users.", }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/analytics/technology/carriers.js b/ui-tests/cypress/lib/dashboard/analytics/technology/carriers.js index b6aeaaabd11..c4fdec29251 100644 --- a/ui-tests/cypress/lib/dashboard/analytics/technology/carriers.js +++ b/ui-tests/cypress/lib/dashboard/analytics/technology/carriers.js @@ -9,7 +9,7 @@ const verifyStaticElementsOfPage = () => { labelElement: carriersPageElements.PAGE_TITLE, labelText: "Carriers", tooltipElement: carriersPageElements.PAGE_TITLE_TOOLTIP, - tooltipText: "Detailed information on the network carriers of the devices through which your users access your application, in the selected time period." + tooltipText: "Detailed information on the network carriers of the devices through which your users access your application within the selected time period." }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/analytics/technology/devicesAndTypes.js b/ui-tests/cypress/lib/dashboard/analytics/technology/devicesAndTypes.js index 1148ab595ac..e7ee269d590 100644 --- a/ui-tests/cypress/lib/dashboard/analytics/technology/devicesAndTypes.js +++ b/ui-tests/cypress/lib/dashboard/analytics/technology/devicesAndTypes.js @@ -11,7 +11,7 @@ const verifyStaticElementsOfPage = () => { labelElement: devicesAndTypesPageElements.PAGE_TITLE, labelText: "Devices and Types", tooltipElement: devicesAndTypesPageElements.PAGE_TITLE_TOOLTIP, - tooltipText: "Details of the device models and types from which your users access your application, in the selected time period." + tooltipText: "Details of the device models and types from which your users access your application within the selected time period." }); cy.verifyElement({ @@ -66,21 +66,21 @@ const verifyStaticElementsOfPage = () => { labelElement: devicesEGraphElements().TOP_PLATFORMS_LABEL, labelText: "Top Platforms", tooltipElement: devicesEGraphElements().TOP_PLATFORMS_TOOLTIP, - tooltipText: "Top 5 versions of the platforms of your users’ sessions, in the selected time period." + tooltipText: "The top 5 platform versions of your users’ sessions within the selected time period." }); cy.verifyElement({ labelElement: devicesEGraphElements().TOP_PLATFORMS_VERSIONS_LABEL, labelText: "Top Platform Versions", tooltipElement: devicesEGraphElements().TOP_PLATFORMS_VERSIONS_TOOLTIP, - tooltipText: "Top 3 versions of the platforms of your users' sessions, in the selected time period." + tooltipText: "The top 3 platform versions of your users' sessions within the selected time period." }); cy.verifyElement({ labelElement: devicesEGraphElements().TOP_RESOLUTIONS_LABEL, labelText: "Top Resolutions", tooltipElement: devicesEGraphElements().TOP_RESOLUTIONS_TOOLTIP, - tooltipText: "Top 5 resolution settings of the devices used your users' sessions, in the selected time period." + tooltipText: "The top 5 resolution settings of the devices used in your users' sessions within the selected time period." }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/analytics/technology/platforms.js b/ui-tests/cypress/lib/dashboard/analytics/technology/platforms.js index 770aae7fd2b..4524a392a0f 100644 --- a/ui-tests/cypress/lib/dashboard/analytics/technology/platforms.js +++ b/ui-tests/cypress/lib/dashboard/analytics/technology/platforms.js @@ -10,7 +10,7 @@ const verifyStaticElementsOfPage = () => { labelElement: platformsPageElements.PAGE_TITLE, labelText: "Platforms", tooltipElement: platformsPageElements.PAGE_TITLE_TOOLTIP, - tooltipText: "Details of the platforms on which yours users access your application, in the selected time period." + tooltipText: "Details of the platforms on which your users access your application within the selected time period." }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/analytics/technology/resolutions.js b/ui-tests/cypress/lib/dashboard/analytics/technology/resolutions.js index 242f8bc4cbe..e1d19a95e53 100644 --- a/ui-tests/cypress/lib/dashboard/analytics/technology/resolutions.js +++ b/ui-tests/cypress/lib/dashboard/analytics/technology/resolutions.js @@ -9,7 +9,7 @@ const verifyStaticElementsOfPage = () => { labelElement: resolutionsPageElements.PAGE_TITLE, labelText: "Resolutions", tooltipElement: resolutionsPageElements.PAGE_TITLE_TOOLTIP, - tooltipText: "Detailed information on the resolution settings of the devices through which your users access your application, in the selected time period." + tooltipText: "Detailed information on the resolution settings of the devices through which your users access your application within the selected time period." }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/analytics/technology/versions.js b/ui-tests/cypress/lib/dashboard/analytics/technology/versions.js index b6843b90f06..1fc391b471f 100644 --- a/ui-tests/cypress/lib/dashboard/analytics/technology/versions.js +++ b/ui-tests/cypress/lib/dashboard/analytics/technology/versions.js @@ -9,7 +9,7 @@ const verifyStaticElementsOfPage = () => { labelElement: versionsPageElements.PAGE_TITLE, labelText: "App Versions", tooltipElement: versionsPageElements.PAGE_TITLE_TOOLTIP, - tooltipText: "Detailed information on the application versions of your application accessed by your users, in the selected time period." + tooltipText: "Detailed information on the application versions of your application accessed by your users within the selected time period." }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/analytics/users/overview.js b/ui-tests/cypress/lib/dashboard/analytics/users/overview.js index dbb842fc861..c424979176a 100644 --- a/ui-tests/cypress/lib/dashboard/analytics/users/overview.js +++ b/ui-tests/cypress/lib/dashboard/analytics/users/overview.js @@ -143,7 +143,7 @@ const verifyUsersOverviewChart = ({ labelElement: usersOverviewEChartElements.CHART_TOTAL_USERS_LABEL, labelText: "Total Users", tooltipElement: usersOverviewEChartElements.CHART_TOTAL_USERS_TOOLTIP, - tooltipText: "The number of users (unique devices/IDs) who have opened your application in the selected time period.", + tooltipText: "The number of users (unique devices/IDs) who have opened your application within the selected time period.", }); cy.verifyElement({ @@ -167,7 +167,7 @@ const verifyUsersOverviewChart = ({ labelElement: usersOverviewEChartElements.CHART_NEW_USERS_LABEL, labelText: "New Users", tooltipElement: usersOverviewEChartElements.CHART_NEW_USERS_TOOLTIP, - tooltipText: "The number of first-time users (unique devices/IDs) in the selected time period.", + tooltipText: "The number of first-time users (unique devices/IDs) within the selected time period.", }); cy.verifyElement({ @@ -191,7 +191,7 @@ const verifyUsersOverviewChart = ({ labelElement: usersOverviewEChartElements.CHART_RETURNING_USERS_LABEL, labelText: "Returning Users", tooltipElement: usersOverviewEChartElements.CHART_RETURNING_USERS_TOOLTIP, - tooltipText: "Number of users using your application for the second or later time, in the selected time period, calculated as Total Users (less) New Users.", + tooltipText: "The number of users using your application for the second or later time within the selected time period, calculated as Total Users minus New Users.", }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/crashes/crashes.js b/ui-tests/cypress/lib/dashboard/crashes/crashes.js index 455c1d009e8..4c925411fe5 100644 --- a/ui-tests/cypress/lib/dashboard/crashes/crashes.js +++ b/ui-tests/cypress/lib/dashboard/crashes/crashes.js @@ -33,7 +33,7 @@ const verifyStaticElementsOfCrashGroupsPage = () => { labelElement: crashGroupsPageElements.ENABLED_LABEL, labelText: "Enabled", tooltipElement: crashGroupsPageElements.AUTO_REFRESH_IS_ENABLED_TOOLTIP, - tooltipText: "Automatically refresh can be adjusted through this switch" + tooltipText: "Automatic refresh can be adjusted through this switch." }); cy.verifyElement({ @@ -222,7 +222,7 @@ const verifyStaticElementsOfCrashStatisticsPage = () => { labelElement: crashStatisticsEChartElements.TOTAL_OCCURENCES_LABEL, labelText: "Total Occurences", tooltipElement: crashStatisticsEChartElements.TOTAL_OCCURENCES_TOOLTIP, - tooltipText: "Timeline of all occurrences of all crashes. Same crash may occurred multiple times for same or different users." + tooltipText: "Timeline of all occurrences of all crashes. The same crash may have occurred multiple times for the same or different users." }); cy.verifyElement({ @@ -233,7 +233,7 @@ const verifyStaticElementsOfCrashStatisticsPage = () => { labelElement: crashStatisticsEChartElements.UNIQUE_CRASHES_LABEL, labelText: "Unique Crashes", tooltipElement: crashStatisticsEChartElements.UNIQUE_CRASHES_TOOLTIP, - tooltipText: "Timeline of crash types. Only the first ocurrence of each crash time recorded here." + tooltipText: "Timeline of crash types. Only the first occurrence of each crash time is recorded here." }); cy.verifyElement({ @@ -255,7 +255,7 @@ const verifyStaticElementsOfCrashStatisticsPage = () => { labelElement: crashStatisticsEChartElements.CRASH_FREE_USERS_LABEL, labelText: "Crash-free Users", tooltipElement: crashStatisticsEChartElements.CRASH_FREE_USERS_TOOLTIP, - tooltipText: "Number of users who have not experienced a crash for the applied filter in the selected time period, expressed as a percentage of the total number of users within that time period." + tooltipText: "The number of users who have not experienced a crash for the applied filter in the selected time period, expressed as a percentage of the total number of users within that time period." }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/feedback/ratings/widgets.js b/ui-tests/cypress/lib/dashboard/feedback/ratings/widgets.js index 6a50c3c2abc..78ac728313f 100644 --- a/ui-tests/cypress/lib/dashboard/feedback/ratings/widgets.js +++ b/ui-tests/cypress/lib/dashboard/feedback/ratings/widgets.js @@ -80,11 +80,11 @@ const verifySettingsPageElements = ({ labelText: "Internal Name", element: feedbackRatingWidgetsPageElements.WIDGET_NAME_INPUT, value: widgetName, - elementPlaceHolder: "Widget Name" + elementPlaceHolder: "Enter an Internal Name" }); cy.verifyElement({ labelElement: feedbackRatingWidgetsPageElements.WIDGET_NAME_DESC, - labelText: "Name survey for internal purposes. It is not going to be shown on survey.", + labelText: "This name is internal and will not be shown to your end user.", }); cy.verifyElement({ labelElement: feedbackRatingWidgetsPageElements.QUESTION_LABEL, diff --git a/ui-tests/cypress/lib/dashboard/home/home.js b/ui-tests/cypress/lib/dashboard/home/home.js index 3f0f4275384..c77f4e8dff0 100644 --- a/ui-tests/cypress/lib/dashboard/home/home.js +++ b/ui-tests/cypress/lib/dashboard/home/home.js @@ -63,7 +63,7 @@ const verifyStaticElementsOfPage = () => { labelElement: homePageElements.AUDIENCE.NEW_SESSIONS_LABEL, labelText: "New Sessions", tooltipElement: homePageElements.AUDIENCE.NEW_SESSIONS_TOOLTIP, - tooltipText: "The number of first-time users (unique devices/IDs) in the selected time period." + tooltipText: "The number of first-time users (unique devices/IDs) within the selected time period." }); cy.verifyElement({ @@ -84,7 +84,7 @@ const verifyStaticElementsOfPage = () => { labelElement: homePageElements.AUDIENCE.AVG_REQUESTS_RECEIVED_LABEL, labelText: "Avg. Requests Received", tooltipElement: homePageElements.AUDIENCE.AVG_REQUESTS_RECEIVED_TOOLTIP, - tooltipText: "Number of write API requests Countly Server receives for each session (includes sessions, session extensions, events, etc)" + tooltipText: "The number of write API requests the Countly Server receives for each session (includes sessions, session extensions, events, etc.)." }); cy.verifyElement({ @@ -159,7 +159,7 @@ const verifyStaticElementsOfPage = () => { labelElement: homePageElements.TECHNOLOGY().LABEL, labelText: "Technology", tooltipElement: homePageElements.TECHNOLOGY().TOOLTIP, - tooltipText: "Overview details of your app or website traffic by your users’ technology, such as platform, device, resolution, browsers and app version." + tooltipText: "Overview details of your app or website traffic based on your users’ technology, such as platform, device, resolution, browsers, and app version." }); cy.verifyElement({ @@ -176,35 +176,35 @@ const verifyStaticElementsOfPage = () => { labelElement: homePageElements.TECHNOLOGY().TOP_PLATFORMS_LABEL, labelText: "Top Platforms", tooltipElement: homePageElements.TECHNOLOGY().TOP_PLATFORMS_TOOLTIP, - tooltipText: "Top 5 versions of the platforms of your users’ sessions, in the selected time period." + tooltipText: "The top 5 platform versions of your users’ sessions within the selected time period." }); cy.verifyElement({ labelElement: homePageElements.TECHNOLOGY().TOP_DEVICES_LABEL, labelText: "Top Devices", tooltipElement: homePageElements.TECHNOLOGY().TOP_DEVICES_TOOLTIP, - tooltipText: "Top 5 devices of your users’ based on their sessions, in the selected time period." + tooltipText: "The top 5 devices of your users based on their sessions within the selected time period." }); cy.verifyElement({ labelElement: homePageElements.TECHNOLOGY().TOP_APP_VERSIONS_LABEL, labelText: "Top App Versions", tooltipElement: homePageElements.TECHNOLOGY().TOP_APP_VERSIONS_TOOLTIP, - tooltipText: "Top 5 App versions of your users’ based on their sessions, in the selected time period." + tooltipText: "The top 5 app versions of your users based on their sessions within the selected time period." }); cy.verifyElement({ labelElement: homePageElements.TECHNOLOGY().TOP_DEVICE_TYPES_LABEL, labelText: "Top Device types", tooltipElement: homePageElements.TECHNOLOGY().TOP_DEVICE_TYPES_TOOLTIP, - tooltipText: "Top 5 device types of your users’ based on their sessions, in the selected time period." + tooltipText: "The top 5 device types of your users based on their sessions within the selected time period." }); cy.verifyElement({ labelElement: homePageElements.COUNTRIES.LABEL, labelText: "Countries", tooltipElement: homePageElements.COUNTRIES.TOOLTIP, - tooltipText: "An overview of the geographical distribution of your users and their sessions in the selected time period." + tooltipText: "An overview of the geographical distribution of your users and their sessions within the selected time period." }); cy.verifyElement({ @@ -270,7 +270,7 @@ const verifyStaticElementsOfPage = () => { labelElement: homePageElements.CRASH_STATISTICS.LABEL, labelText: "Crash Statistics", tooltipElement: homePageElements.CRASH_STATISTICS.TOOLTIP, - tooltipText: "See actionable information about crashes and exceptions including which users are impacted" + tooltipText: "See actionable information about crashes and exceptions, including which users are impacted." }); cy.verifyElement({ @@ -313,7 +313,7 @@ const verifyStaticElementsOfPage = () => { labelElement: homePageElements.CRASH_STATISTICS.CRASH_FREE_USERS_LABEL, labelText: "Crash-free Users", tooltipElement: homePageElements.CRASH_STATISTICS.CRASH_FREE_USERS_TOOLTIP, - tooltipText: "Number of users who have not experienced a crash for the applied filter in the selected time period, expressed as a percentage of the total number of users within that time period." + tooltipText: "The number of users who have not experienced a crash for the applied filter in the selected time period, expressed as a percentage of the total number of users within that time period." }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/manage/alerts/alerts.js b/ui-tests/cypress/lib/dashboard/manage/alerts/alerts.js index 60034e4f5c5..fbe1d7e6692 100644 --- a/ui-tests/cypress/lib/dashboard/manage/alerts/alerts.js +++ b/ui-tests/cypress/lib/dashboard/manage/alerts/alerts.js @@ -79,7 +79,7 @@ const verifyAlertDrawerPageElements = ({ if (!isEditPage) { cy.verifyElement({ labelElement: alertDrawerPageElements.DRAWER_PAGE_TITLE, - labelText: "Create new alert" + labelText: "Create New Alert" }); } else { @@ -99,7 +99,7 @@ const verifyAlertDrawerPageElements = ({ labelText: "Alert Name", element: alertDrawerPageElements.DRAWER_ALERT_NAME_INPUT, value: alertName, - elementPlaceHolder: "Enter alert name" + elementPlaceHolder: "Enter Alert Name" }); cy.verifyElement({ @@ -107,7 +107,7 @@ const verifyAlertDrawerPageElements = ({ labelText: "Application", element: alertDrawerPageElements.DRAWER_APPLICATION_SELECT, value: application, - elementPlaceHolder: "Select an application" + elementPlaceHolder: "Select an Application" }); cy.verifyElement({ @@ -537,7 +537,7 @@ const verifyAlertsDataFromTable = ({ cy.verifyElement({ labelElement: alertDataTableElements().COLUMN_NAME_CREATED_BY_LABEL, isElementVisible: false, - labelText: "Created by", + labelText: "Created By", }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/manage/apps/apps.js b/ui-tests/cypress/lib/dashboard/manage/apps/apps.js index 4012350993e..baa26b761d8 100644 --- a/ui-tests/cypress/lib/dashboard/manage/apps/apps.js +++ b/ui-tests/cypress/lib/dashboard/manage/apps/apps.js @@ -58,7 +58,7 @@ const verifyStaticElementsOfPage = () => { labelElement: applicationsPageElements.SALT_FOR_CHECKSUM_LABEL, labelText: "Salt for checksum", element: applicationsPageElements.SALT_FOR_CHECKSUM_DESCRIPTION_LABEL, - elementText: "Will only accept requests where checksum is signed with the same salt in SDK", + elementText: "Will only accept requests where the checksum is signed with the same salt in the SDK.", }); cy.verifyElement({ @@ -72,7 +72,7 @@ const verifyStaticElementsOfPage = () => { labelElement: applicationsPageElements.APP_KEY_LABEL, labelText: "App Key", element: applicationsPageElements.APP_KEY_DESCRIPTION_LABEL, - elementText: "You'll need this key for SDK integration", + elementText: "You will need this key for SDK integration.", }); cy.verifyElement({ @@ -84,7 +84,7 @@ const verifyStaticElementsOfPage = () => { cy.verifyElement({ labelElement: applicationsPageElements.ADD_UPLOAD_INSRUCTIONS_LABEL, - labelText: "Only jpg, png and gif image formats are allowed", + labelText: "Only JPG, PNG, and GIF image formats are allowed.", }); }; diff --git a/ui-tests/cypress/lib/dashboard/manage/configurations/configurations.js b/ui-tests/cypress/lib/dashboard/manage/configurations/configurations.js index a73db448a55..558de3b930d 100644 --- a/ui-tests/cypress/lib/dashboard/manage/configurations/configurations.js +++ b/ui-tests/cypress/lib/dashboard/manage/configurations/configurations.js @@ -1155,7 +1155,7 @@ const verifyPageElements = () => { cy.verifyElement({ labelElement: configurationsListBoxElements({ subFeature: SETTINGS.DASHBOARD.ALLOW_DASHBOARD_SHARING }).SELECTED_SUBFEATURE_DESCRIPTION, - labelText: "Enable dashboard sharing for users to share a dashboard with other users. If set to off, a dashboard cannot be shared with others.", + labelText: "Enable dashboard sharing for users to share a dashboard with other users. If set to off, dashboards cannot be shared with others.", }); cy.verifyElement({ @@ -1179,7 +1179,7 @@ const verifyPageElements = () => { cy.verifyElement({ labelElement: configurationsListBoxElements({ subFeature: SETTINGS.HOOKS.ACTION_BATCH_PROCESING_SIZE }).SELECTED_SUBFEATURE_TITLE, - labelText: "Action batch procesing size", + labelText: "Action Batch Processing Size", }); cy.verifyElement({ @@ -1195,7 +1195,7 @@ const verifyPageElements = () => { cy.verifyElement({ labelElement: configurationsListBoxElements({ subFeature: SETTINGS.HOOKS.ACTION_PIPELINE_INTERVAL }).SELECTED_SUBFEATURE_TITLE, - labelText: "Action pipeline interval", + labelText: "Action Pipeline Interval", }); cy.verifyElement({ @@ -1211,7 +1211,7 @@ const verifyPageElements = () => { cy.verifyElement({ labelElement: configurationsListBoxElements({ subFeature: SETTINGS.HOOKS.REFRESH_RULES_PERIOD }).SELECTED_SUBFEATURE_TITLE, - labelText: "Refresh rules period", + labelText: "Refresh Rules Period", }); cy.verifyElement({ @@ -1227,7 +1227,7 @@ const verifyPageElements = () => { cy.verifyElement({ labelElement: configurationsListBoxElements({ subFeature: SETTINGS.HOOKS.REQUEST_LIMIT }).SELECTED_SUBFEATURE_TITLE, - labelText: "Request limit", + labelText: "Request Limit", }); cy.verifyElement({ @@ -1243,7 +1243,7 @@ const verifyPageElements = () => { cy.verifyElement({ labelElement: configurationsListBoxElements({ subFeature: SETTINGS.HOOKS.TIME_WINDOW_FOR_REQUEST_LIMIT }).SELECTED_SUBFEATURE_TITLE, - labelText: "Time window for request limit", + labelText: "Time Window for Request Limit", }); cy.verifyElement({ @@ -1294,7 +1294,7 @@ const verifyPageElements = () => { cy.verifyElement({ labelElement: configurationsListBoxElements({ subFeature: SETTINGS.INCOMING_DATA_LOGS.DATA_LOGGING_STATE }).SELECTED_SUBFEATURE_DESCRIPTION, - labelText: "If incoming data logging state is set to \"On\", only the last 1000 requests will be saved. When the state is set to \"Automatic\", requests will continue to be logged until the limit per minute is reached.", + labelText: "If the incoming data logging state is set to \"On\", only the last 1000 requests will be saved. When the state is set to \"Automatic\", requests will continue to be logged until the limit per minute is reached.", }); cy.verifyElement({ @@ -1701,7 +1701,7 @@ const verifyPageElements = () => { cy.verifyElement({ labelElement: configurationsListBoxElements({ subFeature: SETTINGS.AUDIT_LOGS.DISABLE_IP_TRACKING }).SELECTED_SUBFEATURE_DESCRIPTION, - labelText: "Do not record IP address of actions taken by the users", + labelText: "Do not record the IP address of actions taken by the users.", }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/dashboard/manage/hooks/hooks.js b/ui-tests/cypress/lib/dashboard/manage/hooks/hooks.js index c57386319e9..8f6f64d968d 100644 --- a/ui-tests/cypress/lib/dashboard/manage/hooks/hooks.js +++ b/ui-tests/cypress/lib/dashboard/manage/hooks/hooks.js @@ -73,7 +73,7 @@ const verifyStaticElementsOfPage = () => { cy.verifyElement({ labelElement: hooksDataTableElements().COLUMN_NAME_CREATE_BY_LABEL, - labelText: "Create by", + labelText: "Created by", element: hooksDataTableElements().COLUMN_NAME_CREATE_BY_SORTABLE_ICON, }); }; diff --git a/ui-tests/cypress/lib/dashboard/manage/logger/logger.js b/ui-tests/cypress/lib/dashboard/manage/logger/logger.js index 110f93f93a1..7f667bbac68 100644 --- a/ui-tests/cypress/lib/dashboard/manage/logger/logger.js +++ b/ui-tests/cypress/lib/dashboard/manage/logger/logger.js @@ -8,12 +8,12 @@ const verifyStaticElementsOfPage = (isEnabled) => { labelElement: loggerPageElements.PAGE_TITLE, labelText: "Incoming Data Logs", tooltipElement: loggerPageElements.PAGE_TITLE_TOOLTIP, - tooltipText: "Log requests made to the write API to review and debug incoming data" + tooltipText: "Logs requests made to the write API to review and debug incoming data." }); cy.verifyElement({ labelElement: loggerPageElements.PAGE_SUB_TITLE, - labelText: "Only up to last 1000 incoming data logs are stored" + labelText: "Only up to the last 1000 incoming data logs are stored" }); if (isEnabled) { @@ -23,7 +23,7 @@ const verifyStaticElementsOfPage = (isEnabled) => { element: loggerPageElements.ENABLED_LABEL, elementText: "Enabled", tooltipElement: loggerPageElements.AUTO_REFRESH_IS_ENABLED_TOOLTIP, - tooltipText: "Automatically refresh can be adjusted through this switch", + tooltipText: "Automatic refresh can be adjusted through this switch.", }); cy.verifyElement({ @@ -37,7 +37,7 @@ const verifyStaticElementsOfPage = (isEnabled) => { labelElement: loggerPageElements.ENABLE_AUTO_REFRESH_LABEL, labelText: "Enable Auto-refresh", tooltipElement: loggerPageElements.ENABLE_AUTO_REFRESH_TOOLTIP, - tooltipText: "Automatically refresh can be adjusted through this switch" + tooltipText: "Automatic refresh can be adjusted through this switch." }); } diff --git a/ui-tests/cypress/lib/dashboard/manage/logs/systemlogs.js b/ui-tests/cypress/lib/dashboard/manage/logs/systemlogs.js index a6b4fae86d6..be9f39de4bf 100644 --- a/ui-tests/cypress/lib/dashboard/manage/logs/systemlogs.js +++ b/ui-tests/cypress/lib/dashboard/manage/logs/systemlogs.js @@ -109,7 +109,7 @@ const verifySystemLogsDataTable = ({ cy.verifyElement({ element: systemLogsDataTableElements(index).EXPAND_ROW, - elementText: "Following data was changed", + elementText: "The following data was changed", }); }; diff --git a/ui-tests/cypress/lib/dashboard/messaging/messaging.js b/ui-tests/cypress/lib/dashboard/messaging/messaging.js index cf07a486bad..ff63e2497b6 100644 --- a/ui-tests/cypress/lib/dashboard/messaging/messaging.js +++ b/ui-tests/cypress/lib/dashboard/messaging/messaging.js @@ -49,7 +49,7 @@ const verifyStaticElementsOfPage = () => { labelElement: messagingMetricCardElements.ENABLED_USERS_PERCENTAGE_LABEL, labelText: "Enabled Users Percentage", tooltipElement: messagingMetricCardElements.ENABLED_USERS_PERCENTAGE_PROGRESS_TOOLTIP, - tooltipText: "Number of users who have agreed to receive notifications, expressed as a percentage over the total number of app users." + tooltipText: "The number of users who have agreed to receive notifications, expressed as a percentage of the total number of app users." }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/onboarding/initialSetup.js b/ui-tests/cypress/lib/onboarding/initialSetup.js index 60108163002..9a45579b27f 100644 --- a/ui-tests/cypress/lib/onboarding/initialSetup.js +++ b/ui-tests/cypress/lib/onboarding/initialSetup.js @@ -113,7 +113,7 @@ const verifyDefaultPageElements = (isDemoApp) => { cy.verifyElement({ labelElement: initialSetupPageElements.PAGE_SUB_TITLE, - labelText: "After adding your first application, you'll be ready to start collecting data" + labelText: "After adding your first application, you will be ready to start collecting data." }); cy.verifyElement({ @@ -129,7 +129,7 @@ const verifyDefaultPageElements = (isDemoApp) => { element: initialSetupPageElements.APPLICATION_KEY_INPUT, elementPlaceHolder: "App Key", tooltipElement: initialSetupPageElements.APPLICATION_KEY_TOOLTIP, - tooltipText: "You'll need this key for SDK integration" + tooltipText: "You will need this key for SDK integration." }); cy.verifyElement({ diff --git a/ui-tests/cypress/lib/onboarding/setup.js b/ui-tests/cypress/lib/onboarding/setup.js index 0518ed8fd9e..c9d3e459278 100644 --- a/ui-tests/cypress/lib/onboarding/setup.js +++ b/ui-tests/cypress/lib/onboarding/setup.js @@ -74,7 +74,7 @@ const verifyConfirmPasswordHintSymbolMessage = () => { cy.verifyElement({ element: setupPageElements.CONFIRM_PASSWORD_ERROR_DOT, labelElement: setupPageElements.CONFIRM_PASSWORD_ERROR, - labelText: "Confirmation password has to be the same as password.", + labelText: "The confirmation password has to be the same as the password.", }); }; @@ -135,7 +135,7 @@ const verifyDefaultPageElements = () => { cy.verifyElement({ labelElement: setupPageElements.EMAIL_ADDRESS_ERROR, - labelText: "Please enter a valid email adress.", + labelText: "Please enter a valid email address.", }); cy.verifyElement({ @@ -168,7 +168,7 @@ const verifyDefaultPageElements = () => { cy.verifyElement({ element: setupPageElements.CONFIRM_PASSWORD_ERROR_DOT, labelElement: setupPageElements.CONFIRM_PASSWORD_ERROR, - labelText: "Confirmation password has to be the same as password.", + labelText: "The confirmation password has to be the same as the password.", }); }; diff --git a/ui-tests/cypress/support/elements/dashboard/manage/hooks/hooks.js b/ui-tests/cypress/support/elements/dashboard/manage/hooks/hooks.js index b743956e0f1..7f3ee3482b1 100644 --- a/ui-tests/cypress/support/elements/dashboard/manage/hooks/hooks.js +++ b/ui-tests/cypress/support/elements/dashboard/manage/hooks/hooks.js @@ -26,8 +26,8 @@ const hooksDataTableElements = (index = 0) => ({ COLUMN_NAME_TRIGGER_COUNT_SORTABLE_ICON: 'datatable-hooks-sortable-icon-trigger-count', COLUMN_NAME_LAST_TRIGGERED_LABEL: 'datatable-hooks-label-last-triggered', COLUMN_NAME_LAST_TRIGGERED_SORTABLE_ICON: 'datatable-hooks-sortable-icon-last-triggered', - COLUMN_NAME_CREATE_BY_LABEL: 'datatable-hooks-label-create-by', - COLUMN_NAME_CREATE_BY_SORTABLE_ICON: 'datatable-hooks-sortable-icon-create-by', + COLUMN_NAME_CREATE_BY_LABEL: 'datatable-hooks-label-created-by', + COLUMN_NAME_CREATE_BY_SORTABLE_ICON: 'datatable-hooks-sortable-icon-created-by', //Columns' Rows' Datas Elements STATUS: 'datatable-hooks-status-' + index + '-el-switch-wrapper', diff --git a/ui-tests/package-lock.json b/ui-tests/package-lock.json index db7923a9b97..e9e2bc5c0e3 100644 --- a/ui-tests/package-lock.json +++ b/ui-tests/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@faker-js/faker": "^8.2.0", + "@faker-js/faker": "^9.7.0", "base-64": "^1.0.0", "chai": "^5.1.1", "cypress-file-upload": "^5.0.8", @@ -75,18 +75,19 @@ } }, "node_modules/@faker-js/faker": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.2.0.tgz", - "integrity": "sha512-VacmzZqVxdWdf9y64lDOMZNDMM/FQdtM9IsaOPKOm2suYwEatb8VkdHqOzXcDnZbk7YDE2BmsJmy/2Hmkn563g==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.7.0.tgz", + "integrity": "sha512-aozo5vqjCmDoXLNUJarFZx2IN/GgGaogY4TMJ6so/WLZOWpSV7fvj2dmrV6sEAnUm1O7aCrhTibjpzeDFgNqbg==", "funding": [ { "type": "opencollective", "url": "https://opencollective.com/fakerjs" } ], + "license": "MIT", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0", - "npm": ">=6.14.13" + "node": ">=18.0.0", + "npm": ">=9.0.0" } }, "node_modules/@types/node": { @@ -368,9 +369,10 @@ "license": "Apache-2.0" }, "node_modules/chai": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", - "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", + "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", + "license": "MIT", "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", @@ -1389,9 +1391,10 @@ } }, "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", "engines": { "node": "*" } diff --git a/ui-tests/package.json b/ui-tests/package.json index 68e9f9764b7..5084cea17d6 100644 --- a/ui-tests/package.json +++ b/ui-tests/package.json @@ -9,7 +9,7 @@ }, "license": "ISC", "dependencies": { - "@faker-js/faker": "^8.2.0", + "@faker-js/faker": "^9.7.0", "base-64": "^1.0.0", "chai": "^5.1.1", "cypress-file-upload": "^5.0.8",