diff --git a/.commitlintrc.cjs b/.commitlintrc.cjs new file mode 100644 index 0000000..eb5c144 --- /dev/null +++ b/.commitlintrc.cjs @@ -0,0 +1,21 @@ +module.exports = { + extends: ["@commitlint/config-conventional"], + rules: { + "type-enum": [ + 2, + "always", + [ + "feat", + "fix", + "docs", + "style", + "refactor", + "perf", + "test", + "chore", + "ci", + "build", + ], + ], + }, +}; \ No newline at end of file diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..430bc40 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,53 @@ +# Node dependencies +node_modules +npm-debug.log +yarn-error.log + +# Logs and runtime data +*.log +logs +pids +*.pid +*.seed +*.pid.lock + +# Build artifacts (if any) +dist +build +coverage + +# Environment and secrets +.env +.env.* +!.env.example + +# Version control and CI/CD +.idea +.git +.gitignore +.gitattributes +.github +.gitlab-ci.yml + +# Editor & OS files +.DS_Store +*.swp +*.swo +.vscode +.idea +*.bak +Thumbs.db + +# Docker/OpenShift build files that shouldn’t go inside image +openshift/ +docker-compose.yml +Dockerfile.dev +README.md +test +tests +__tests__ +docs + +# Cache +.npm +.cache diff --git a/.env b/.env new file mode 100644 index 0000000..9ba3c35 --- /dev/null +++ b/.env @@ -0,0 +1,8 @@ +MISTRAL_API_KEY= +GEMINI_API_KEY= +DATABASE_URL= +ALLAS_ENDPOINT=https://a3s.fi +ALLAS_BUCKET= +ALLAS_ACCESS_KEY= +ALLAS_SECRET_KEY= +ALLAS_UPLOAD_ENDPOINT= \ No newline at end of file diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 0000000..5215ab6 --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,33 @@ +name: "CodeQL Config" +paths-ignore: + - "node_modules/" + - "openshift/" + - "dbinit/" + - "dist/" + - "build/" + - "coverage/" + - "**/.husky/**" + - "**/.idea/**" + - "scripts" + - "*.min.js" + - "*.test.ts" + - "*.test.js" + - "*.spec.ts" + - "*.spec.js" + - "__tests__/" + - "test/" + - "tests/" + - "*.d.ts" + - "public/" + - "static/" +queries: + - name: security-extended + uses: security-extended + - name: security-and-quality + uses: security-and-quality +# Query filters +query-filters: + - exclude: + id: js/unused-local-variable + - exclude: + id: js/debugger-statement \ No newline at end of file diff --git a/.github/prompts/pr_summary_prompt.yml b/.github/prompts/pr_summary_prompt.yml new file mode 100644 index 0000000..14726bd --- /dev/null +++ b/.github/prompts/pr_summary_prompt.yml @@ -0,0 +1,19 @@ +messages: + - role: user + content: | + Analyze this pull request and provide a clear, concise summary that anyone can understand. + + Title: "{{title}}" + Description: "{{description}}" + + Code Changes: + ``` + {{diff}} + ``` + + Please summarize: + - What this PR does (the main purpose) + - Key changes made in the code + - Any important details worth noting + + Keep it simple and focused. Use bullet points or short paragraphs as needed. \ No newline at end of file diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..8eed85d --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,32 @@ +name: "CodeQL Security Analysis" +on: + workflow_run: + workflows: ["YAML Lint"] + types: + - completed + pull_request: + branches: ["main"] +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: ['javascript', 'typescript'] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + config-file: ./.github/codeql/codeql-config.yml + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" \ No newline at end of file diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..69609e1 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,20 @@ +name: release-please + +on: + push: + branches: + - main + +permissions: + contents: write + pull-requests: write + +jobs: + release-please: + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: googleapis/release-please-action@v4 + with: + release-type: node + token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/yaml-scanner.yml b/.github/workflows/yaml-scanner.yml new file mode 100644 index 0000000..d547627 --- /dev/null +++ b/.github/workflows/yaml-scanner.yml @@ -0,0 +1,17 @@ +name: "YAML Lint" +on: + pull_request: + branches: [main] +jobs: + yaml-lint: + name: Lint YAML files + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install yamllint + run: sudo apt-get update && sudo apt-get install -y yamllint + - name: Run yamllint + run: |- + yamllint -d '{"extends": "default", "rules": {"line-length": false}}' . + continue-on-error: true diff --git a/.gitignore b/.gitignore index c1fb5fa..4a47133 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,30 @@ -.node_modules \ No newline at end of file +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + + +# production +/build + +# misc +.DS_Store +.idea +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..34eed8b --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1 @@ +npx --no -- commitlint --edit $1 \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..2312dc5 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0d56fd0 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +# Stage 1: Install dependencies +FROM node:20-alpine AS deps +WORKDIR /app +COPY package*.json ./ +RUN npm ci --only=production && \ + npm cache clean --force + +# Stage 2: Production runtime +FROM node:20-alpine AS runner +WORKDIR /app + +ENV NODE_ENV=production + +# Copy dependencies and application code +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +EXPOSE 3000 +ENV HOST=0.0.0.0 +ENV PORT=3000 + +# Stage 3: Start the application +CMD ["node", "server.js"] \ No newline at end of file diff --git a/docs/assets/db_structure.png b/docs/assets/db_structure.png new file mode 100644 index 0000000..07e8713 Binary files /dev/null and b/docs/assets/db_structure.png differ diff --git a/index.js b/index.js deleted file mode 100644 index 6341d93..0000000 --- a/index.js +++ /dev/null @@ -1,22 +0,0 @@ -// server.js -import Fastify from 'fastify' - -const fastify = Fastify({ - logger: true -}) - -fastify.get('/', async (request, reply) => { - return { hi: 'world' } -}) - -const start = async () => { - try { - await fastify.listen({ port: 3000 }) - console.log('Server running at http://localhost:3000') - } catch (err) { - fastify.log.error(err) - process.exit(1) - } -} - -start() diff --git a/mock_test.js b/mock_test.js deleted file mode 100644 index eb2fff9..0000000 --- a/mock_test.js +++ /dev/null @@ -1,43 +0,0 @@ -import 'dotenv/config'; -import { Mistral } from '@mistralai/mistralai'; -import pg from 'pg'; - -const { Pool } = pg; -const pool = new Pool({ - connectionString: process.env.DATABASE_URL, // e.g. postgres://user:password@localhost:5432/db -}); - -const client = new Mistral({ apiKey: process.env.MISTRAL_API_KEY }); - -async function embedAndInsert(ingredients) { - const texts = ingredients.map(i => i.text); - const response = await client.embeddings.create({ - model: "mistral-embed", - inputs: texts, - }); - - for (let i = 0; i < response.data.length; i++) { - const embedding = response.data[i].embedding; - const embedding_string = JSON.stringify(embedding); - const id = ingredients[i].id; - await pool.query( - `UPDATE ingredients SET embedding_name = $1 WHERE id = $2`, - [embedding_string, id] - ); - console.log(`Inserted embedding for id=${id} | length=${embedding.length}`); - } - -} -const ingredients = [ - { id: 1, text: "Sodium Fluoride" }, - { id: 2, text: "Hydrated Silica" }, - { id: 3, text: "Sodium Lauryl Sulfate (SLS)" }, - { id: 4, text: "Sorbitol" }, - { id: 5, text: "Titanium Dioxide" }, - { id: 6, text: "Potassium Nitrate" }, - { id: 7, text: "Xylitol" }, -]; -(async () => { - await embedAndInsert(ingredients); - await pool.end(); -})(); diff --git a/package.json b/package.json index 9218e5b..369d355 100644 --- a/package.json +++ b/package.json @@ -2,11 +2,17 @@ "name": "PastePick-server", "version": "1.0.0", "description": "", - "main": "index.js", + "main": "server.js", "scripts": { "dev": "nodemon server.js", "start": "node server.js", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "prepare": "husky" + }, + "lint-staged": { + "*.{js,jsx,ts,tsx}": [ + "biome format --write" + ] }, "keywords": [], "author": "", @@ -14,12 +20,25 @@ "packageManager": "pnpm@10.13.1", "type": "module", "dependencies": { + "@aws-sdk/client-s3": "^3.917.0", + "@fastify/cors": "^11.1.0", + "@fastify/multipart": "^9.3.0", + "@google/genai": "^1.25.0", "@mistralai/mistralai": "^1.10.0", + "@xenova/transformers": "^2.17.2", + "axios": "^1.13.2", "dotenv": "^17.2.2", "fastify": "^5.6.0", + "form-data": "^4.0.4", + "fuse.js": "^7.1.0", "pg": "^8.16.3" }, "devDependencies": { + "@biomejs/biome": "2.2.6", + "@commitlint/cli": "^20.1.0", + "@commitlint/config-conventional": "^20.0.0", + "husky": "^9.1.7", + "lint-staged": "^16.2.4", "nodemon": "^3.1.10" } -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e35f210..bf355b4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,28 +8,361 @@ importers: .: dependencies: + '@aws-sdk/client-s3': + specifier: ^3.917.0 + version: 3.917.0 + '@fastify/cors': + specifier: ^11.1.0 + version: 11.1.0 + '@fastify/multipart': + specifier: ^9.3.0 + version: 9.3.0 + '@google/genai': + specifier: ^1.25.0 + version: 1.25.0 '@mistralai/mistralai': specifier: ^1.10.0 version: 1.10.0 + '@xenova/transformers': + specifier: ^2.17.2 + version: 2.17.2 + axios: + specifier: ^1.13.2 + version: 1.13.2 dotenv: specifier: ^17.2.2 version: 17.2.2 fastify: specifier: ^5.6.0 version: 5.6.0 + form-data: + specifier: ^4.0.4 + version: 4.0.4 + fuse.js: + specifier: ^7.1.0 + version: 7.1.0 pg: specifier: ^8.16.3 version: 8.16.3 devDependencies: + '@biomejs/biome': + specifier: 2.2.6 + version: 2.2.6 + '@commitlint/cli': + specifier: ^20.1.0 + version: 20.1.0(@types/node@24.7.2)(typescript@5.9.3) + '@commitlint/config-conventional': + specifier: ^20.0.0 + version: 20.0.0 + husky: + specifier: ^9.1.7 + version: 9.1.7 + lint-staged: + specifier: ^16.2.4 + version: 16.2.4 nodemon: specifier: ^3.1.10 version: 3.1.10 packages: + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/crc32c@5.2.0': + resolution: {integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==} + + '@aws-crypto/sha1-browser@5.2.0': + resolution: {integrity: sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==} + + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/client-s3@3.917.0': + resolution: {integrity: sha512-3L73mDCpH7G0koFv3p3WkkEKqC5wn2EznKtNMrJ6hczPIr2Cu6DJz8VHeTZp9wFZLPrIBmh3ZW1KiLujT5Fd2w==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/client-sso@3.916.0': + resolution: {integrity: sha512-Eu4PtEUL1MyRvboQnoq5YKg0Z9vAni3ccebykJy615xokVZUdA3di2YxHM/hykDQX7lcUC62q9fVIvh0+UNk/w==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/core@3.916.0': + resolution: {integrity: sha512-1JHE5s6MD5PKGovmx/F1e01hUbds/1y3X8rD+Gvi/gWVfdg5noO7ZCerpRsWgfzgvCMZC9VicopBqNHCKLykZA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-env@3.916.0': + resolution: {integrity: sha512-3gDeqOXcBRXGHScc6xb7358Lyf64NRG2P08g6Bu5mv1Vbg9PKDyCAZvhKLkG7hkdfAM8Yc6UJNhbFxr1ud/tCQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-http@3.916.0': + resolution: {integrity: sha512-NmooA5Z4/kPFJdsyoJgDxuqXC1C6oPMmreJjbOPqcwo6E/h2jxaG8utlQFgXe5F9FeJsMx668dtxVxSYnAAqHQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-ini@3.917.0': + resolution: {integrity: sha512-rvQ0QamLySRq+Okc0ZqFHZ3Fbvj3tYuWNIlzyEKklNmw5X5PM1idYKlOJflY2dvUGkIqY3lUC9SC2WL+1s7KIw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-node@3.917.0': + resolution: {integrity: sha512-n7HUJ+TgU9wV/Z46yR1rqD9hUjfG50AKi+b5UXTlaDlVD8bckg40i77ROCllp53h32xQj/7H0yBIYyphwzLtmg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-process@3.916.0': + resolution: {integrity: sha512-SXDyDvpJ1+WbotZDLJW1lqP6gYGaXfZJrgFSXIuZjHb75fKeNRgPkQX/wZDdUvCwdrscvxmtyJorp2sVYkMcvA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-sso@3.916.0': + resolution: {integrity: sha512-gu9D+c+U/Dp1AKBcVxYHNNoZF9uD4wjAKYCjgSN37j4tDsazwMEylbbZLuRNuxfbXtizbo4/TiaxBXDbWM7AkQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.917.0': + resolution: {integrity: sha512-pZncQhFbwW04pB0jcD5OFv3x2gAddDYCVxyJVixgyhSw7bKCYxqu6ramfq1NxyVpmm+qsw+ijwi/3cCmhUHF/A==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-bucket-endpoint@3.914.0': + resolution: {integrity: sha512-mHLsVnPPp4iq3gL2oEBamfpeETFV0qzxRHmcnCfEP3hualV8YF8jbXGmwPCPopUPQDpbYDBHYtXaoClZikCWPQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-expect-continue@3.917.0': + resolution: {integrity: sha512-UPBq1ZP2CaxwbncWSbVqkhYXQrmfNiqAtHyBxi413hjRVZ4JhQ1UyH7pz5yqiG8zx2/+Po8cUD4SDUwJgda4nw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-flexible-checksums@3.916.0': + resolution: {integrity: sha512-CBRRg6slHHBYAm26AWY/pECHK0vVO/peDoNhZiAzUNt4jV6VftotjszEJ904pKGOr7/86CfZxtCnP3CCs3lQjA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-host-header@3.914.0': + resolution: {integrity: sha512-7r9ToySQ15+iIgXMF/h616PcQStByylVkCshmQqcdeynD/lCn2l667ynckxW4+ql0Q+Bo/URljuhJRxVJzydNA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-location-constraint@3.914.0': + resolution: {integrity: sha512-Mpd0Sm9+GN7TBqGnZg1+dO5QZ/EOYEcDTo7KfvoyrXScMlxvYm9fdrUVMmLdPn/lntweZGV3uNrs+huasGOOTA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-logger@3.914.0': + resolution: {integrity: sha512-/gaW2VENS5vKvJbcE1umV4Ag3NuiVzpsANxtrqISxT3ovyro29o1RezW/Avz/6oJqjnmgz8soe9J1t65jJdiNg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.914.0': + resolution: {integrity: sha512-yiAjQKs5S2JKYc+GrkvGMwkUvhepXDigEXpSJqUseR/IrqHhvGNuOxDxq+8LbDhM4ajEW81wkiBbU+Jl9G82yQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-sdk-s3@3.916.0': + resolution: {integrity: sha512-pjmzzjkEkpJObzmTthqJPq/P13KoNFuEi/x5PISlzJtHofCNcyXeVAQ90yvY2dQ6UXHf511Rh1/ytiKy2A8M0g==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-ssec@3.914.0': + resolution: {integrity: sha512-V1Oae/oLVbpNb9uWs+v80GKylZCdsbqs2c2Xb1FsAUPtYeSnxFuAWsF3/2AEMSSpFe0dTC5KyWr/eKl2aim9VQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-user-agent@3.916.0': + resolution: {integrity: sha512-mzF5AdrpQXc2SOmAoaQeHpDFsK2GE6EGcEACeNuoESluPI2uYMpuuNMYrUufdnIAIyqgKlis0NVxiahA5jG42w==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/nested-clients@3.916.0': + resolution: {integrity: sha512-tgg8e8AnVAer0rcgeWucFJ/uNN67TbTiDHfD+zIOPKep0Z61mrHEoeT/X8WxGIOkEn4W6nMpmS4ii8P42rNtnA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/region-config-resolver@3.914.0': + resolution: {integrity: sha512-KlmHhRbn1qdwXUdsdrJ7S/MAkkC1jLpQ11n+XvxUUUCGAJd1gjC7AjxPZUM7ieQ2zcb8bfEzIU7al+Q3ZT0u7Q==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.916.0': + resolution: {integrity: sha512-fuzUMo6xU7e0NBzBA6TQ4FUf1gqNbg4woBSvYfxRRsIfKmSMn9/elXXn4sAE5UKvlwVQmYnb6p7dpVRPyFvnQA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/token-providers@3.916.0': + resolution: {integrity: sha512-13GGOEgq5etbXulFCmYqhWtpcEQ6WI6U53dvXbheW0guut8fDFJZmEv7tKMTJgiybxh7JHd0rWcL9JQND8DwoQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/types@3.914.0': + resolution: {integrity: sha512-kQWPsRDmom4yvAfyG6L1lMmlwnTzm1XwMHOU+G5IFlsP4YEaMtXidDzW/wiivY0QFrhfCz/4TVmu0a2aPU57ug==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-arn-parser@3.893.0': + resolution: {integrity: sha512-u8H4f2Zsi19DGnwj5FSZzDMhytYF/bCh37vAtBsn3cNDL3YG578X5oc+wSX54pM3tOxS+NY7tvOAo52SW7koUA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-endpoints@3.916.0': + resolution: {integrity: sha512-bAgUQwvixdsiGNcuZSDAOWbyHlnPtg8G8TyHD6DTfTmKTHUW6tAn+af/ZYJPXEzXhhpwgJqi58vWnsiDhmr7NQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-locate-window@3.893.0': + resolution: {integrity: sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-user-agent-browser@3.914.0': + resolution: {integrity: sha512-rMQUrM1ECH4kmIwlGl9UB0BtbHy6ZuKdWFrIknu8yGTRI/saAucqNTh5EI1vWBxZ0ElhK5+g7zOnUuhSmVQYUA==} + + '@aws-sdk/util-user-agent-node@3.916.0': + resolution: {integrity: sha512-CwfWV2ch6UdjuSV75ZU99N03seEUb31FIUrXBnwa6oONqj/xqXwrxtlUMLx6WH3OJEE4zI3zt5PjlTdGcVwf4g==} + engines: {node: '>=18.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/xml-builder@3.914.0': + resolution: {integrity: sha512-k75evsBD5TcIjedycYS7QXQ98AmOtbnxRJOPtCo0IwYRmy7UvqgS/gBL5SmrIqeV6FDSYRQMgdBxSMp6MLmdew==} + engines: {node: '>=18.0.0'} + + '@aws/lambda-invoke-store@0.0.1': + resolution: {integrity: sha512-ORHRQ2tmvnBXc8t/X9Z8IcSbBA4xTLKuN873FopzklHMeqBst7YG0d+AX97inkvDX+NChYtSr+qGfcqGFaI8Zw==} + engines: {node: '>=18.0.0'} + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + + '@biomejs/biome@2.2.6': + resolution: {integrity: sha512-yKTCNGhek0rL5OEW1jbLeZX8LHaM8yk7+3JRGv08my+gkpmtb5dDE+54r2ZjZx0ediFEn1pYBOJSmOdDP9xtFw==} + engines: {node: '>=14.21.3'} + hasBin: true + + '@biomejs/cli-darwin-arm64@2.2.6': + resolution: {integrity: sha512-UZPmn3M45CjTYulgcrFJFZv7YmK3pTxTJDrFYlNElT2FNnkkX4fsxjExTSMeWKQYoZjvekpH5cvrYZZlWu3yfA==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [darwin] + + '@biomejs/cli-darwin-x64@2.2.6': + resolution: {integrity: sha512-HOUIquhHVgh/jvxyClpwlpl/oeMqntlteL89YqjuFDiZ091P0vhHccwz+8muu3nTyHWM5FQslt+4Jdcd67+xWQ==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [darwin] + + '@biomejs/cli-linux-arm64-musl@2.2.6': + resolution: {integrity: sha512-TjCenQq3N6g1C+5UT3jE1bIiJb5MWQvulpUngTIpFsL4StVAUXucWD0SL9MCW89Tm6awWfeXBbZBAhJwjyFbRQ==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-arm64@2.2.6': + resolution: {integrity: sha512-BpGtuMJGN+o8pQjvYsUKZ+4JEErxdSmcRD/JG3mXoWc6zrcA7OkuyGFN1mDggO0Q1n7qXxo/PcupHk8gzijt5g==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-x64-musl@2.2.6': + resolution: {integrity: sha512-1ZcBux8zVM3JhWN2ZCPaYf0+ogxXG316uaoXJdgoPZcdK/rmRcRY7PqHdAos2ExzvjIdvhQp72UcveI98hgOog==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-linux-x64@2.2.6': + resolution: {integrity: sha512-1HaM/dpI/1Z68zp8ZdT6EiBq+/O/z97a2AiHMl+VAdv5/ELckFt9EvRb8hDHpk8hUMoz03gXkC7VPXOVtU7faA==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-win32-arm64@2.2.6': + resolution: {integrity: sha512-h3A88G8PGM1ryTeZyLlSdfC/gz3e95EJw9BZmA6Po412DRqwqPBa2Y9U+4ZSGUAXCsnSQE00jLV8Pyrh0d+jQw==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [win32] + + '@biomejs/cli-win32-x64@2.2.6': + resolution: {integrity: sha512-yx0CqeOhPjYQ5ZXgPfu8QYkgBhVJyvWe36as7jRuPrKPO5ylVDfwVtPQ+K/mooNTADW0IhxOZm3aPu16dP8yNQ==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [win32] + + '@commitlint/cli@20.1.0': + resolution: {integrity: sha512-pW5ujjrOovhq5RcYv5xCpb4GkZxkO2+GtOdBW2/qrr0Ll9tl3PX0aBBobGQl3mdZUbOBgwAexEQLeH6uxL0VYg==} + engines: {node: '>=v18'} + hasBin: true + + '@commitlint/config-conventional@20.0.0': + resolution: {integrity: sha512-q7JroPIkDBtyOkVe9Bca0p7kAUYxZMxkrBArCfuD3yN4KjRAenP9PmYwnn7rsw8Q+hHq1QB2BRmBh0/Z19ZoJw==} + engines: {node: '>=v18'} + + '@commitlint/config-validator@20.0.0': + resolution: {integrity: sha512-BeyLMaRIJDdroJuYM2EGhDMGwVBMZna9UiIqV9hxj+J551Ctc6yoGuGSmghOy/qPhBSuhA6oMtbEiTmxECafsg==} + engines: {node: '>=v18'} + + '@commitlint/ensure@20.0.0': + resolution: {integrity: sha512-WBV47Fffvabe68n+13HJNFBqiMH5U1Ryls4W3ieGwPC0C7kJqp3OVQQzG2GXqOALmzrgAB+7GXmyy8N9ct8/Fg==} + engines: {node: '>=v18'} + + '@commitlint/execute-rule@20.0.0': + resolution: {integrity: sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==} + engines: {node: '>=v18'} + + '@commitlint/format@20.0.0': + resolution: {integrity: sha512-zrZQXUcSDmQ4eGGrd+gFESiX0Rw+WFJk7nW4VFOmxub4mAATNKBQ4vNw5FgMCVehLUKG2OT2LjOqD0Hk8HvcRg==} + engines: {node: '>=v18'} + + '@commitlint/is-ignored@20.0.0': + resolution: {integrity: sha512-ayPLicsqqGAphYIQwh9LdAYOVAQ9Oe5QCgTNTj+BfxZb9b/JW222V5taPoIBzYnAP0z9EfUtljgBk+0BN4T4Cw==} + engines: {node: '>=v18'} + + '@commitlint/lint@20.0.0': + resolution: {integrity: sha512-kWrX8SfWk4+4nCexfLaQT3f3EcNjJwJBsSZ5rMBw6JCd6OzXufFHgel2Curos4LKIxwec9WSvs2YUD87rXlxNQ==} + engines: {node: '>=v18'} + + '@commitlint/load@20.1.0': + resolution: {integrity: sha512-qo9ER0XiAimATQR5QhvvzePfeDfApi/AFlC1G+YN+ZAY8/Ua6IRrDrxRvQAr+YXUKAxUsTDSp9KXeXLBPsNRWg==} + engines: {node: '>=v18'} + + '@commitlint/message@20.0.0': + resolution: {integrity: sha512-gLX4YmKnZqSwkmSB9OckQUrI5VyXEYiv3J5JKZRxIp8jOQsWjZgHSG/OgEfMQBK9ibdclEdAyIPYggwXoFGXjQ==} + engines: {node: '>=v18'} + + '@commitlint/parse@20.0.0': + resolution: {integrity: sha512-j/PHCDX2bGM5xGcWObOvpOc54cXjn9g6xScXzAeOLwTsScaL4Y+qd0pFC6HBwTtrH92NvJQc+2Lx9HFkVi48cg==} + engines: {node: '>=v18'} + + '@commitlint/read@20.0.0': + resolution: {integrity: sha512-Ti7Y7aEgxsM1nkwA4ZIJczkTFRX/+USMjNrL9NXwWQHqNqrBX2iMi+zfuzZXqfZ327WXBjdkRaytJ+z5vNqTOA==} + engines: {node: '>=v18'} + + '@commitlint/resolve-extends@20.1.0': + resolution: {integrity: sha512-cxKXQrqHjZT3o+XPdqDCwOWVFQiae++uwd9dUBC7f2MdV58ons3uUvASdW7m55eat5sRiQ6xUHyMWMRm6atZWw==} + engines: {node: '>=v18'} + + '@commitlint/rules@20.0.0': + resolution: {integrity: sha512-gvg2k10I/RfvHn5I5sxvVZKM1fl72Sqrv2YY/BnM7lMHcYqO0E2jnRWoYguvBfEcZ39t+rbATlciggVe77E4zA==} + engines: {node: '>=v18'} + + '@commitlint/to-lines@20.0.0': + resolution: {integrity: sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw==} + engines: {node: '>=v18'} + + '@commitlint/top-level@20.0.0': + resolution: {integrity: sha512-drXaPSP2EcopukrUXvUXmsQMu3Ey/FuJDc/5oiW4heoCfoE5BdLQyuc7veGeE3aoQaTVqZnh4D5WTWe2vefYKg==} + engines: {node: '>=v18'} + + '@commitlint/types@20.0.0': + resolution: {integrity: sha512-bVUNBqG6aznYcYjTjnc3+Cat/iBgbgpflxbIBTnsHTX0YVpnmINPEkSRWymT2Q8aSH3Y7aKnEbunilkYe8TybA==} + engines: {node: '>=v18'} + '@fastify/ajv-compiler@4.0.2': resolution: {integrity: sha512-Rkiu/8wIjpsf46Rr+Fitd3HRP+VsxUFDDeag0hs9L0ksfnwx2g7SPQQTFL0E8Qv+rfXzQOxBJnjUB9ITUDjfWQ==} + '@fastify/busboy@3.2.0': + resolution: {integrity: sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==} + + '@fastify/cors@11.1.0': + resolution: {integrity: sha512-sUw8ed8wP2SouWZTIbA7V2OQtMNpLj2W6qJOYhNdcmINTu6gsxVYXjQiM9mdi8UUDlcoDDJ/W2syPo1WB2QjYA==} + + '@fastify/deepmerge@3.1.0': + resolution: {integrity: sha512-lCVONBQINyNhM6LLezB6+2afusgEYR4G8xenMsfe+AT+iZ7Ca6upM5Ha8UkZuYSnuMw3GWl/BiPXnLMi/gSxuQ==} + '@fastify/error@4.2.0': resolution: {integrity: sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==} @@ -42,15 +375,297 @@ packages: '@fastify/merge-json-schemas@0.2.1': resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==} + '@fastify/multipart@9.3.0': + resolution: {integrity: sha512-NpeKipTOjjL1dA7SSlRMrOWWtrE8/0yKOmeudkdQoEaz4sVDJw5MVdZIahsWhvpc3YTN7f04f9ep/Y65RKoOWA==} + '@fastify/proxy-addr@5.0.0': resolution: {integrity: sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==} + '@google/genai@1.25.0': + resolution: {integrity: sha512-IBNyel/umavam98SQUfvQSvh/Rp6Ql2fysQLqPyWZr5K8d768X9AO+JZU4o+3qvFDUBA0dVYUSkxyYonVcICvA==} + engines: {node: '>=20.0.0'} + peerDependencies: + '@modelcontextprotocol/sdk': ^1.11.4 + peerDependenciesMeta: + '@modelcontextprotocol/sdk': + optional: true + + '@huggingface/jinja@0.2.2': + resolution: {integrity: sha512-/KPde26khDUIPkTGU82jdtTW9UAuvUTumCAbFs/7giR0SxsvZC4hru51PBvpijH6BVkHcROcvZM/lpy5h1jRRA==} + engines: {node: '>=18'} + '@mistralai/mistralai@1.10.0': resolution: {integrity: sha512-tdIgWs4Le8vpvPiUEWne6tK0qbVc+jMenujnvTqOjogrJUsCSQhus0tHTU1avDDh5//Rq2dFgP9mWRAdIEoBqg==} + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + + '@smithy/abort-controller@4.2.3': + resolution: {integrity: sha512-xWL9Mf8b7tIFuAlpjKtRPnHrR8XVrwTj5NPYO/QwZPtc0SDLsPxb56V5tzi5yspSMytISHybifez+4jlrx0vkQ==} + engines: {node: '>=18.0.0'} + + '@smithy/chunked-blob-reader-native@4.2.1': + resolution: {integrity: sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==} + engines: {node: '>=18.0.0'} + + '@smithy/chunked-blob-reader@5.2.0': + resolution: {integrity: sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==} + engines: {node: '>=18.0.0'} + + '@smithy/config-resolver@4.4.0': + resolution: {integrity: sha512-Kkmz3Mup2PGp/HNJxhCWkLNdlajJORLSjwkcfrj0E7nu6STAEdcMR1ir5P9/xOmncx8xXfru0fbUYLlZog/cFg==} + engines: {node: '>=18.0.0'} + + '@smithy/core@3.17.1': + resolution: {integrity: sha512-V4Qc2CIb5McABYfaGiIYLTmo/vwNIK7WXI5aGveBd9UcdhbOMwcvIMxIw/DJj1S9QgOMa/7FBkarMdIC0EOTEQ==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.2.3': + resolution: {integrity: sha512-hA1MQ/WAHly4SYltJKitEsIDVsNmXcQfYBRv2e+q04fnqtAX5qXaybxy/fhUeAMCnQIdAjaGDb04fMHQefWRhw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-codec@4.2.3': + resolution: {integrity: sha512-rcr0VH0uNoMrtgKuY7sMfyKqbHc4GQaQ6Yp4vwgm+Z6psPuOgL+i/Eo/QWdXRmMinL3EgFM0Z1vkfyPyfzLmjw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-browser@4.2.3': + resolution: {integrity: sha512-EcS0kydOr2qJ3vV45y7nWnTlrPmVIMbUFOZbMG80+e2+xePQISX9DrcbRpVRFTS5Nqz3FiEbDcTCAV0or7bqdw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-config-resolver@4.3.3': + resolution: {integrity: sha512-GewKGZ6lIJ9APjHFqR2cUW+Efp98xLu1KmN0jOWxQ1TN/gx3HTUPVbLciFD8CfScBj2IiKifqh9vYFRRXrYqXA==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-node@4.2.3': + resolution: {integrity: sha512-uQobOTQq2FapuSOlmGLUeGTpvcBLE5Fc7XjERUSk4dxEi4AhTwuyHYZNAvL4EMUp7lzxxkKDFaJ1GY0ovrj0Kg==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-universal@4.2.3': + resolution: {integrity: sha512-QIvH/CKOk1BZPz/iwfgbh1SQD5Y0lpaw2kLA8zpLRRtYMPXeYUEWh+moTaJyqDaKlbrB174kB7FSRFiZ735tWw==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.3.4': + resolution: {integrity: sha512-bwigPylvivpRLCm+YK9I5wRIYjFESSVwl8JQ1vVx/XhCw0PtCi558NwTnT2DaVCl5pYlImGuQTSwMsZ+pIavRw==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-blob-browser@4.2.4': + resolution: {integrity: sha512-W7eIxD+rTNsLB/2ynjmbdeP7TgxRXprfvqQxKFEfy9HW2HeD7t+g+KCIrY0pIn/GFjA6/fIpH+JQnfg5TTk76Q==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-node@4.2.3': + resolution: {integrity: sha512-6+NOdZDbfuU6s1ISp3UOk5Rg953RJ2aBLNLLBEcamLjHAg1Po9Ha7QIB5ZWhdRUVuOUrT8BVFR+O2KIPmw027g==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-stream-node@4.2.3': + resolution: {integrity: sha512-EXMSa2yiStVII3x/+BIynyOAZlS7dGvI7RFrzXa/XssBgck/7TXJIvnjnCu328GY/VwHDC4VeDyP1S4rqwpYag==} + engines: {node: '>=18.0.0'} + + '@smithy/invalid-dependency@4.2.3': + resolution: {integrity: sha512-Cc9W5DwDuebXEDMpOpl4iERo8I0KFjTnomK2RMdhhR87GwrSmUmwMxS4P5JdRf+LsjOdIqumcerwRgYMr/tZ9Q==} + engines: {node: '>=18.0.0'} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@4.2.0': + resolution: {integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==} + engines: {node: '>=18.0.0'} + + '@smithy/md5-js@4.2.3': + resolution: {integrity: sha512-5+4bUEJQi/NRgzdA5SVXvAwyvEnD0ZAiKzV3yLO6dN5BG8ScKBweZ8mxXXUtdxq+Dx5k6EshKk0XJ7vgvIPSnA==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-content-length@4.2.3': + resolution: {integrity: sha512-/atXLsT88GwKtfp5Jr0Ks1CSa4+lB+IgRnkNrrYP0h1wL4swHNb0YONEvTceNKNdZGJsye+W2HH8W7olbcPUeA==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-endpoint@4.3.5': + resolution: {integrity: sha512-SIzKVTvEudFWJbxAaq7f2GvP3jh2FHDpIFI6/VAf4FOWGFZy0vnYMPSRj8PGYI8Hjt29mvmwSRgKuO3bK4ixDw==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-retry@4.4.5': + resolution: {integrity: sha512-DCaXbQqcZ4tONMvvdz+zccDE21sLcbwWoNqzPLFlZaxt1lDtOE2tlVpRSwcTOJrjJSUThdgEYn7HrX5oLGlK9A==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-serde@4.2.3': + resolution: {integrity: sha512-8g4NuUINpYccxiCXM5s1/V+uLtts8NcX4+sPEbvYQDZk4XoJfDpq5y2FQxfmUL89syoldpzNzA0R9nhzdtdKnQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-stack@4.2.3': + resolution: {integrity: sha512-iGuOJkH71faPNgOj/gWuEGS6xvQashpLwWB1HjHq1lNNiVfbiJLpZVbhddPuDbx9l4Cgl0vPLq5ltRfSaHfspA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-config-provider@4.3.3': + resolution: {integrity: sha512-NzI1eBpBSViOav8NVy1fqOlSfkLgkUjUTlohUSgAEhHaFWA3XJiLditvavIP7OpvTjDp5u2LhtlBhkBlEisMwA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.4.3': + resolution: {integrity: sha512-MAwltrDB0lZB/H6/2M5PIsISSwdI5yIh6DaBB9r0Flo9nx3y0dzl/qTMJPd7tJvPdsx6Ks/cwVzheGNYzXyNbQ==} + engines: {node: '>=18.0.0'} + + '@smithy/property-provider@4.2.3': + resolution: {integrity: sha512-+1EZ+Y+njiefCohjlhyOcy1UNYjT+1PwGFHCxA/gYctjg3DQWAU19WigOXAco/Ql8hZokNehpzLd0/+3uCreqQ==} + engines: {node: '>=18.0.0'} + + '@smithy/protocol-http@5.3.3': + resolution: {integrity: sha512-Mn7f/1aN2/jecywDcRDvWWWJF4uwg/A0XjFMJtj72DsgHTByfjRltSqcT9NyE9RTdBSN6X1RSXrhn/YWQl8xlw==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-builder@4.2.3': + resolution: {integrity: sha512-LOVCGCmwMahYUM/P0YnU/AlDQFjcu+gWbFJooC417QRB/lDJlWSn8qmPSDp+s4YVAHOgtgbNG4sR+SxF/VOcJQ==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-parser@4.2.3': + resolution: {integrity: sha512-cYlSNHcTAX/wc1rpblli3aUlLMGgKZ/Oqn8hhjFASXMCXjIqeuQBei0cnq2JR8t4RtU9FpG6uyl6PxyArTiwKA==} + engines: {node: '>=18.0.0'} + + '@smithy/service-error-classification@4.2.3': + resolution: {integrity: sha512-NkxsAxFWwsPsQiwFG2MzJ/T7uIR6AQNh1SzcxSUnmmIqIQMlLRQDKhc17M7IYjiuBXhrQRjQTo3CxX+DobS93g==} + engines: {node: '>=18.0.0'} + + '@smithy/shared-ini-file-loader@4.3.3': + resolution: {integrity: sha512-9f9Ixej0hFhroOK2TxZfUUDR13WVa8tQzhSzPDgXe5jGL3KmaM9s8XN7RQwqtEypI82q9KHnKS71CJ+q/1xLtQ==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.3.3': + resolution: {integrity: sha512-CmSlUy+eEYbIEYN5N3vvQTRfqt0lJlQkaQUIf+oizu7BbDut0pozfDjBGecfcfWf7c62Yis4JIEgqQ/TCfodaA==} + engines: {node: '>=18.0.0'} + + '@smithy/smithy-client@4.9.1': + resolution: {integrity: sha512-Ngb95ryR5A9xqvQFT5mAmYkCwbXvoLavLFwmi7zVg/IowFPCfiqRfkOKnbc/ZRL8ZKJ4f+Tp6kSu6wjDQb8L/g==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.8.0': + resolution: {integrity: sha512-QpELEHLO8SsQVtqP+MkEgCYTFW0pleGozfs3cZ183ZBj9z3VC1CX1/wtFMK64p+5bhtZo41SeLK1rBRtd25nHQ==} + engines: {node: '>=18.0.0'} + + '@smithy/url-parser@4.2.3': + resolution: {integrity: sha512-I066AigYvY3d9VlU3zG9XzZg1yT10aNqvCaBTw9EPgu5GrsEl1aUkcMvhkIXascYH1A8W0LQo3B1Kr1cJNcQEw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-base64@4.3.0': + resolution: {integrity: sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-browser@4.2.0': + resolution: {integrity: sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-node@4.2.1': + resolution: {integrity: sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@4.2.0': + resolution: {integrity: sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==} + engines: {node: '>=18.0.0'} + + '@smithy/util-config-provider@4.2.0': + resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-browser@4.3.4': + resolution: {integrity: sha512-qI5PJSW52rnutos8Bln8nwQZRpyoSRN6k2ajyoUHNMUzmWqHnOJCnDELJuV6m5PML0VkHI+XcXzdB+6awiqYUw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-node@4.2.6': + resolution: {integrity: sha512-c6M/ceBTm31YdcFpgfgQAJaw3KbaLuRKnAz91iMWFLSrgxRpYm03c3bu5cpYojNMfkV9arCUelelKA7XQT36SQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-endpoints@3.2.3': + resolution: {integrity: sha512-aCfxUOVv0CzBIkU10TubdgKSx5uRvzH064kaiPEWfNIvKOtNpu642P4FP1hgOFkjQIkDObrfIDnKMKkeyrejvQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-hex-encoding@4.2.0': + resolution: {integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-middleware@4.2.3': + resolution: {integrity: sha512-v5ObKlSe8PWUHCqEiX2fy1gNv6goiw6E5I/PN2aXg3Fb/hse0xeaAnSpXDiWl7x6LamVKq7senB+m5LOYHUAHw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-retry@4.2.3': + resolution: {integrity: sha512-lLPWnakjC0q9z+OtiXk+9RPQiYPNAovt2IXD3CP4LkOnd9NpUsxOjMx1SnoUVB7Orb7fZp67cQMtTBKMFDvOGg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-stream@4.5.4': + resolution: {integrity: sha512-+qDxSkiErejw1BAIXUFBSfM5xh3arbz1MmxlbMCKanDDZtVEQ7PSKW9FQS0Vud1eI/kYn0oCTVKyNzRlq+9MUw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-uri-escape@4.2.0': + resolution: {integrity: sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@4.2.0': + resolution: {integrity: sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-waiter@4.2.3': + resolution: {integrity: sha512-5+nU///E5sAdD7t3hs4uwvCTWQtTR8JwKwOCSJtBRx0bY1isDo1QwH87vRK86vlFLBTISqoDA2V6xvP6nF1isQ==} + engines: {node: '>=18.0.0'} + + '@smithy/uuid@1.1.0': + resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==} + engines: {node: '>=18.0.0'} + + '@types/conventional-commits-parser@5.0.1': + resolution: {integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==} + + '@types/long@4.0.2': + resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} + + '@types/node@24.7.2': + resolution: {integrity: sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA==} + + '@xenova/transformers@2.17.2': + resolution: {integrity: sha512-lZmHqzrVIkSvZdKZEx7IYY51TK0WDrC8eR0c5IMnBsO8di8are1zzw8BlLhyO2TklZKLN5UffNGs1IJwT6oOqQ==} + + JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + abstract-logging@2.0.1: resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + ajv-formats@3.0.1: resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: @@ -62,10 +677,39 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + ansi-escapes@7.1.1: + resolution: {integrity: sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q==} + engines: {node: '>=18'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-ify@1.0.0: + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} @@ -73,13 +717,74 @@ packages: avvio@9.1.0: resolution: {integrity: sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==} + axios@1.13.2: + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + + b4a@1.7.3: + resolution: {integrity: sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==} + peerDependencies: + react-native-b4a: '*' + peerDependenciesMeta: + react-native-b4a: + optional: true + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + bare-events@2.8.0: + resolution: {integrity: sha512-AOhh6Bg5QmFIXdViHbMc2tLDsBIRxdkIaIddPslJF9Z5De3APBScuqGP2uThXnIpqFrgoxMNC6km7uXNIMLHXA==} + peerDependencies: + bare-abort-controller: '*' + peerDependenciesMeta: + bare-abort-controller: + optional: true + + bare-fs@4.4.11: + resolution: {integrity: sha512-Bejmm9zRMvMTRoHS+2adgmXw1ANZnCNx+B5dgZpGwlP1E3x6Yuxea8RToddHUbWtVV0iUMWqsgZr8+jcgUI2SA==} + engines: {bare: '>=1.16.0'} + peerDependencies: + bare-buffer: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + + bare-os@3.6.2: + resolution: {integrity: sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==} + engines: {bare: '>=1.14.0'} + + bare-path@3.0.0: + resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==} + + bare-stream@2.7.0: + resolution: {integrity: sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==} + peerDependencies: + bare-buffer: '*' + bare-events: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + bare-events: + optional: true + + bare-url@2.3.1: + resolution: {integrity: sha512-v2yl0TnaZTdEnelkKtXZGnotiV6qATBlnNuUMrHl6v9Lmmrh9mw9RYyImPU7/4RahumSwQS1k2oKXcRfXcbjJw==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bignumber.js@9.3.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + bowser@2.12.1: + resolution: {integrity: sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==} + brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -87,17 +792,112 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-truncate@5.1.0: + resolution: {integrity: sha512-7JDGG+4Zp0CsknDCedl0DYdaeOhc46QNpXi3NLQblkZpXXgA6LncLDUUyvrjSvZeF3VRQa+KiMGomazQrC1V8g==} + engines: {node: '>=20'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@14.0.1: + resolution: {integrity: sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==} + engines: {node: '>=20'} + + compare-func@2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + conventional-changelog-angular@7.0.0: + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} + engines: {node: '>=16'} + + conventional-changelog-conventionalcommits@7.0.2: + resolution: {integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==} + engines: {node: '>=16'} + + conventional-commits-parser@5.0.0: + resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} + engines: {node: '>=16'} + hasBin: true + cookie@1.0.2: resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} engines: {node: '>=18'} + cosmiconfig-typescript-loader@6.2.0: + resolution: {integrity: sha512-GEN39v7TgdxgIoNcdkRE3uiAzQt3UXLyHbRHD6YoL048XAeOomyxaP+Hh/+2C6C2wYjxJ2onhJcsQp+L4YEkVQ==} + engines: {node: '>=v18'} + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=9' + typescript: '>=5' + + cosmiconfig@9.0.0: + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + dargs@8.1.0: + resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} + engines: {node: '>=12'} + debug@4.4.1: resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} @@ -107,20 +907,103 @@ packages: supports-color: optional: true + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + dot-prop@5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + dotenv@17.2.2: resolution: {integrity: sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==} engines: {node: '>=12'} + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + events-universal@1.0.1: + resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} + + expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + fast-decode-uri-component@1.0.1: resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + fast-json-stringify@6.0.1: resolution: {integrity: sha512-s7SJE83QKBZwg54dIbD5rCtzOBVD43V1ReWXXYqBgwCwHLYAAT0RQc/FmrQglXqWPpz6omtryJQOau5jI4Nrvg==} @@ -134,7 +1017,14 @@ packages: fast-uri@3.1.0: resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} - fastify@5.6.0: + fast-xml-parser@5.2.5: + resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==} + hasBin: true + + fastify-plugin@5.1.0: + resolution: {integrity: sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==} + + fastify@5.6.0: resolution: {integrity: sha512-9j2r9TnwNsfGiCKGYT0Voqy244qwcoYM9qvNi/i+F8sNNWDnqUEVuGYNc9GyjldhXmMlJmVPS6gI1LdvjYGRJw==} fastq@1.19.1: @@ -148,26 +1038,158 @@ packages: resolution: {integrity: sha512-eRoFWQw+Yv2tuYlK2pjFS2jGXSxSppAs3hSQjfxVKxM5amECzIgYYc1FEI8ZmhSh/Ig+FrKEz43NLRKJjYCZVg==} engines: {node: '>=20'} + find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + + flatbuffers@1.12.0: + resolution: {integrity: sha512-c7CZADjRcl6j0PlvFy0ZqXQ67qSEZfrVPynmnL+2zPc+NtMvrF8Y0QceMo7QqnSPc7+uWjUIAbvCQ5WIKlMVdQ==} + + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.4: + resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} + engines: {node: '>= 6'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + fuse.js@7.1.0: + resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==} + engines: {node: '>=10'} + + gaxios@6.7.1: + resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==} + engines: {node: '>=14'} + + gcp-metadata@6.1.1: + resolution: {integrity: sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==} + engines: {node: '>=14'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.4.0: + resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} + engines: {node: '>=18'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + git-raw-commits@4.0.0: + resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} + engines: {node: '>=16'} + hasBin: true + + github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + + google-auth-library@9.15.1: + resolution: {integrity: sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==} + engines: {node: '>=14'} + + google-logging-utils@0.0.2: + resolution: {integrity: sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==} + engines: {node: '>=14'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + gtoken@7.1.0: + resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} + engines: {node: '>=14.0.0'} + + guid-typescript@1.0.9: + resolution: {integrity: sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==} + has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + husky@9.1.7: + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} + engines: {node: '>=18'} + hasBin: true + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore-by-default@1.0.1: resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + ipaddr.js@2.2.0: resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} engines: {node: '>= 10'} + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-arrayish@0.3.4: + resolution: {integrity: sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==} + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -176,6 +1198,14 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-fullwidth-code-point@5.1.0: + resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} + engines: {node: '>=18'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -184,21 +1214,167 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-text-path@2.0.0: + resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} + engines: {node: '>=8'} + + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + json-schema-ref-resolver@2.0.1: resolution: {integrity: sha512-HG0SIB9X4J8bwbxCbnd5FfPEbcXAJYTi1pBJeP/QPON+w8ovSME8iRG+ElHNxZNX2Qh6eYn1GdzJFS4cDFfx0Q==} json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} + + jws@4.0.0: + resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==} + light-my-request@6.6.0: resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==} + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lint-staged@16.2.4: + resolution: {integrity: sha512-Pkyr/wd90oAyXk98i/2KwfkIhoYQUMtss769FIT9hFM5ogYZwrk+GRE46yKXSg2ZGhcJ1p38Gf5gmI5Ohjg2yg==} + engines: {node: '>=20.17'} + hasBin: true + + listr2@9.0.4: + resolution: {integrity: sha512-1wd/kpAdKRLwv7/3OKC8zZ5U8e/fajCfWMxacUvB79S5nLrYGPtUI/8chMQhn3LQjsRVErTb9i1ECAwW0ZIHnQ==} + engines: {node: '>=20.0.0'} + + locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.kebabcase@4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + + lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + + lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + + long@4.0.0: + resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + nano-spawn@2.0.0: + resolution: {integrity: sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==} + engines: {node: '>=20.17'} + + napi-build-utils@2.0.0: + resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} + + node-abi@3.79.0: + resolution: {integrity: sha512-Pr/5KdBQGG8TirdkS0qN3B+f3eo8zTOfZQWAxHoJqopMz2/uvRnG+S4fWu/6AZxKei2CP2p/psdQ5HFC2Ap5BA==} + engines: {node: '>=10'} + + node-addon-api@6.1.0: + resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + nodemon@3.1.10: resolution: {integrity: sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==} engines: {node: '>=10'} @@ -212,6 +1388,46 @@ packages: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + onnx-proto@4.0.4: + resolution: {integrity: sha512-aldMOB3HRoo6q/phyB6QRQxSt895HNNw82BNyZ2CMh4bjeKv7g/c+VpAFtJuEMVfYLMbRx61hbuqnKceLeDcDA==} + + onnxruntime-common@1.14.0: + resolution: {integrity: sha512-3LJpegM2iMNRX2wUmtYfeX/ytfOzNwAWKSq1HbRrKc9+uqG/FsEA0bbKZl1btQeZaXhC26l44NWpNUeXPII7Ew==} + + onnxruntime-node@1.14.0: + resolution: {integrity: sha512-5ba7TWomIV/9b6NH/1x/8QEeowsb+jBEvFzU6z0T4mNsFwdPqXeFUM7uxC6QeSRkEbWu3qEB0VMjrvzN/0S9+w==} + os: [win32, darwin, linux] + + onnxruntime-web@1.14.0: + resolution: {integrity: sha512-Kcqf43UMfW8mCydVGcX9OMXI2VN17c0p6XvR7IPSZzBf/6lteBzXHvcEVWDPmCKuGombl997HgLqj91F11DzXw==} + + p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + pg-cloudflare@1.2.7: resolution: {integrity: sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==} @@ -246,10 +1462,18 @@ packages: pgpass@1.0.5: resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + pino-abstract-transport@2.0.0: resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} @@ -260,6 +1484,9 @@ packages: resolution: {integrity: sha512-d1s98p8/4TfYhsJ09r/Azt30aYELRi6NNnZtEbqFw6BoGsdPVf5lKNK3kUwH8BmJJfpTLNuicjUQjaMbd93dVg==} hasBin: true + platform@1.3.6: + resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} + postgres-array@2.0.0: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} @@ -276,18 +1503,41 @@ packages: resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} engines: {node: '>=0.10.0'} + prebuild-install@7.1.3: + resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} + engines: {node: '>=10'} + hasBin: true + process-warning@4.0.1: resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} process-warning@5.0.0: resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + protobufjs@6.11.4: + resolution: {integrity: sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==} + hasBin: true + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + pstree.remy@1.1.8: resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} + pump@3.0.3: + resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -296,10 +1546,26 @@ packages: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + ret@0.5.0: resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==} engines: {node: '>=10'} @@ -311,6 +1577,9 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-regex2@5.0.0: resolution: {integrity: sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==} @@ -326,13 +1595,39 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true + set-cookie-parser@2.7.1: resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} + sharp@0.32.6: + resolution: {integrity: sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==} + engines: {node: '>=14.15.0'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + + simple-swizzle@0.2.4: + resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==} + simple-update-notifier@2.0.0: resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} engines: {node: '>=10'} + slice-ansi@7.1.2: + resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} + engines: {node: '>=18'} + sonic-boom@4.2.0: resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} @@ -340,13 +1635,76 @@ packages: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} + streamx@2.23.0: + resolution: {integrity: sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string-width@8.1.0: + resolution: {integrity: sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==} + engines: {node: '>=20'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.2: + resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + engines: {node: '>=12'} + + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + + strnum@2.1.1: + resolution: {integrity: sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==} + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} + tar-fs@2.1.4: + resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} + + tar-fs@3.1.1: + resolution: {integrity: sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + tar-stream@3.1.7: + resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + + text-decoder@1.2.3: + resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} + + text-extensions@2.4.0: + resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} + engines: {node: '>=8'} + thread-stream@3.1.0: resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + tinyexec@1.0.1: + resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -359,13 +1717,91 @@ packages: resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} hasBin: true + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + undefsafe@2.0.5: resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} + undici-types@7.14.0: + resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==} + + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yaml@2.8.1: + resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@1.2.1: + resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==} + engines: {node: '>=12.20'} + zod-to-json-schema@3.24.6: resolution: {integrity: sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==} peerDependencies: @@ -376,102 +1812,1385 @@ packages: snapshots: - '@fastify/ajv-compiler@4.0.2': + '@aws-crypto/crc32@5.2.0': dependencies: - ajv: 8.17.1 - ajv-formats: 3.0.1(ajv@8.17.1) - fast-uri: 3.1.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.914.0 + tslib: 2.8.1 - '@fastify/error@4.2.0': {} + '@aws-crypto/crc32c@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.914.0 + tslib: 2.8.1 - '@fastify/fast-json-stringify-compiler@5.0.3': + '@aws-crypto/sha1-browser@5.2.0': dependencies: - fast-json-stringify: 6.0.1 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.914.0 + '@aws-sdk/util-locate-window': 3.893.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.914.0 + '@aws-sdk/util-locate-window': 3.893.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.914.0 + tslib: 2.8.1 - '@fastify/forwarded@3.0.0': {} + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.8.1 - '@fastify/merge-json-schemas@0.2.1': + '@aws-crypto/util@5.2.0': dependencies: - dequal: 2.0.3 + '@aws-sdk/types': 3.914.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 - '@fastify/proxy-addr@5.0.0': + '@aws-sdk/client-s3@3.917.0': dependencies: - '@fastify/forwarded': 3.0.0 - ipaddr.js: 2.2.0 + '@aws-crypto/sha1-browser': 5.2.0 + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.916.0 + '@aws-sdk/credential-provider-node': 3.917.0 + '@aws-sdk/middleware-bucket-endpoint': 3.914.0 + '@aws-sdk/middleware-expect-continue': 3.917.0 + '@aws-sdk/middleware-flexible-checksums': 3.916.0 + '@aws-sdk/middleware-host-header': 3.914.0 + '@aws-sdk/middleware-location-constraint': 3.914.0 + '@aws-sdk/middleware-logger': 3.914.0 + '@aws-sdk/middleware-recursion-detection': 3.914.0 + '@aws-sdk/middleware-sdk-s3': 3.916.0 + '@aws-sdk/middleware-ssec': 3.914.0 + '@aws-sdk/middleware-user-agent': 3.916.0 + '@aws-sdk/region-config-resolver': 3.914.0 + '@aws-sdk/signature-v4-multi-region': 3.916.0 + '@aws-sdk/types': 3.914.0 + '@aws-sdk/util-endpoints': 3.916.0 + '@aws-sdk/util-user-agent-browser': 3.914.0 + '@aws-sdk/util-user-agent-node': 3.916.0 + '@aws-sdk/xml-builder': 3.914.0 + '@smithy/config-resolver': 4.4.0 + '@smithy/core': 3.17.1 + '@smithy/eventstream-serde-browser': 4.2.3 + '@smithy/eventstream-serde-config-resolver': 4.3.3 + '@smithy/eventstream-serde-node': 4.2.3 + '@smithy/fetch-http-handler': 5.3.4 + '@smithy/hash-blob-browser': 4.2.4 + '@smithy/hash-node': 4.2.3 + '@smithy/hash-stream-node': 4.2.3 + '@smithy/invalid-dependency': 4.2.3 + '@smithy/md5-js': 4.2.3 + '@smithy/middleware-content-length': 4.2.3 + '@smithy/middleware-endpoint': 4.3.5 + '@smithy/middleware-retry': 4.4.5 + '@smithy/middleware-serde': 4.2.3 + '@smithy/middleware-stack': 4.2.3 + '@smithy/node-config-provider': 4.3.3 + '@smithy/node-http-handler': 4.4.3 + '@smithy/protocol-http': 5.3.3 + '@smithy/smithy-client': 4.9.1 + '@smithy/types': 4.8.0 + '@smithy/url-parser': 4.2.3 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.4 + '@smithy/util-defaults-mode-node': 4.2.6 + '@smithy/util-endpoints': 3.2.3 + '@smithy/util-middleware': 4.2.3 + '@smithy/util-retry': 4.2.3 + '@smithy/util-stream': 4.5.4 + '@smithy/util-utf8': 4.2.0 + '@smithy/util-waiter': 4.2.3 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso@3.916.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.916.0 + '@aws-sdk/middleware-host-header': 3.914.0 + '@aws-sdk/middleware-logger': 3.914.0 + '@aws-sdk/middleware-recursion-detection': 3.914.0 + '@aws-sdk/middleware-user-agent': 3.916.0 + '@aws-sdk/region-config-resolver': 3.914.0 + '@aws-sdk/types': 3.914.0 + '@aws-sdk/util-endpoints': 3.916.0 + '@aws-sdk/util-user-agent-browser': 3.914.0 + '@aws-sdk/util-user-agent-node': 3.916.0 + '@smithy/config-resolver': 4.4.0 + '@smithy/core': 3.17.1 + '@smithy/fetch-http-handler': 5.3.4 + '@smithy/hash-node': 4.2.3 + '@smithy/invalid-dependency': 4.2.3 + '@smithy/middleware-content-length': 4.2.3 + '@smithy/middleware-endpoint': 4.3.5 + '@smithy/middleware-retry': 4.4.5 + '@smithy/middleware-serde': 4.2.3 + '@smithy/middleware-stack': 4.2.3 + '@smithy/node-config-provider': 4.3.3 + '@smithy/node-http-handler': 4.4.3 + '@smithy/protocol-http': 5.3.3 + '@smithy/smithy-client': 4.9.1 + '@smithy/types': 4.8.0 + '@smithy/url-parser': 4.2.3 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.4 + '@smithy/util-defaults-mode-node': 4.2.6 + '@smithy/util-endpoints': 3.2.3 + '@smithy/util-middleware': 4.2.3 + '@smithy/util-retry': 4.2.3 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.916.0': + dependencies: + '@aws-sdk/types': 3.914.0 + '@aws-sdk/xml-builder': 3.914.0 + '@smithy/core': 3.17.1 + '@smithy/node-config-provider': 4.3.3 + '@smithy/property-provider': 4.2.3 + '@smithy/protocol-http': 5.3.3 + '@smithy/signature-v4': 5.3.3 + '@smithy/smithy-client': 4.9.1 + '@smithy/types': 4.8.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-middleware': 4.2.3 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.916.0': + dependencies: + '@aws-sdk/core': 3.916.0 + '@aws-sdk/types': 3.914.0 + '@smithy/property-provider': 4.2.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 - '@mistralai/mistralai@1.10.0': + '@aws-sdk/credential-provider-http@3.916.0': dependencies: - zod: 3.25.76 - zod-to-json-schema: 3.24.6(zod@3.25.76) + '@aws-sdk/core': 3.916.0 + '@aws-sdk/types': 3.914.0 + '@smithy/fetch-http-handler': 5.3.4 + '@smithy/node-http-handler': 4.4.3 + '@smithy/property-provider': 4.2.3 + '@smithy/protocol-http': 5.3.3 + '@smithy/smithy-client': 4.9.1 + '@smithy/types': 4.8.0 + '@smithy/util-stream': 4.5.4 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.917.0': + dependencies: + '@aws-sdk/core': 3.916.0 + '@aws-sdk/credential-provider-env': 3.916.0 + '@aws-sdk/credential-provider-http': 3.916.0 + '@aws-sdk/credential-provider-process': 3.916.0 + '@aws-sdk/credential-provider-sso': 3.916.0 + '@aws-sdk/credential-provider-web-identity': 3.917.0 + '@aws-sdk/nested-clients': 3.916.0 + '@aws-sdk/types': 3.914.0 + '@smithy/credential-provider-imds': 4.2.3 + '@smithy/property-provider': 4.2.3 + '@smithy/shared-ini-file-loader': 4.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-node@3.917.0': + dependencies: + '@aws-sdk/credential-provider-env': 3.916.0 + '@aws-sdk/credential-provider-http': 3.916.0 + '@aws-sdk/credential-provider-ini': 3.917.0 + '@aws-sdk/credential-provider-process': 3.916.0 + '@aws-sdk/credential-provider-sso': 3.916.0 + '@aws-sdk/credential-provider-web-identity': 3.917.0 + '@aws-sdk/types': 3.914.0 + '@smithy/credential-provider-imds': 4.2.3 + '@smithy/property-provider': 4.2.3 + '@smithy/shared-ini-file-loader': 4.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-process@3.916.0': + dependencies: + '@aws-sdk/core': 3.916.0 + '@aws-sdk/types': 3.914.0 + '@smithy/property-provider': 4.2.3 + '@smithy/shared-ini-file-loader': 4.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.916.0': + dependencies: + '@aws-sdk/client-sso': 3.916.0 + '@aws-sdk/core': 3.916.0 + '@aws-sdk/token-providers': 3.916.0 + '@aws-sdk/types': 3.914.0 + '@smithy/property-provider': 4.2.3 + '@smithy/shared-ini-file-loader': 4.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.917.0': + dependencies: + '@aws-sdk/core': 3.916.0 + '@aws-sdk/nested-clients': 3.916.0 + '@aws-sdk/types': 3.914.0 + '@smithy/property-provider': 4.2.3 + '@smithy/shared-ini-file-loader': 4.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/middleware-bucket-endpoint@3.914.0': + dependencies: + '@aws-sdk/types': 3.914.0 + '@aws-sdk/util-arn-parser': 3.893.0 + '@smithy/node-config-provider': 4.3.3 + '@smithy/protocol-http': 5.3.3 + '@smithy/types': 4.8.0 + '@smithy/util-config-provider': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-expect-continue@3.917.0': + dependencies: + '@aws-sdk/types': 3.914.0 + '@smithy/protocol-http': 5.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-flexible-checksums@3.916.0': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@aws-crypto/crc32c': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/core': 3.916.0 + '@aws-sdk/types': 3.914.0 + '@smithy/is-array-buffer': 4.2.0 + '@smithy/node-config-provider': 4.3.3 + '@smithy/protocol-http': 5.3.3 + '@smithy/types': 4.8.0 + '@smithy/util-middleware': 4.2.3 + '@smithy/util-stream': 4.5.4 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-host-header@3.914.0': + dependencies: + '@aws-sdk/types': 3.914.0 + '@smithy/protocol-http': 5.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-location-constraint@3.914.0': + dependencies: + '@aws-sdk/types': 3.914.0 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-logger@3.914.0': + dependencies: + '@aws-sdk/types': 3.914.0 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-recursion-detection@3.914.0': + dependencies: + '@aws-sdk/types': 3.914.0 + '@aws/lambda-invoke-store': 0.0.1 + '@smithy/protocol-http': 5.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-sdk-s3@3.916.0': + dependencies: + '@aws-sdk/core': 3.916.0 + '@aws-sdk/types': 3.914.0 + '@aws-sdk/util-arn-parser': 3.893.0 + '@smithy/core': 3.17.1 + '@smithy/node-config-provider': 4.3.3 + '@smithy/protocol-http': 5.3.3 + '@smithy/signature-v4': 5.3.3 + '@smithy/smithy-client': 4.9.1 + '@smithy/types': 4.8.0 + '@smithy/util-config-provider': 4.2.0 + '@smithy/util-middleware': 4.2.3 + '@smithy/util-stream': 4.5.4 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-ssec@3.914.0': + dependencies: + '@aws-sdk/types': 3.914.0 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-user-agent@3.916.0': + dependencies: + '@aws-sdk/core': 3.916.0 + '@aws-sdk/types': 3.914.0 + '@aws-sdk/util-endpoints': 3.916.0 + '@smithy/core': 3.17.1 + '@smithy/protocol-http': 5.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.916.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.916.0 + '@aws-sdk/middleware-host-header': 3.914.0 + '@aws-sdk/middleware-logger': 3.914.0 + '@aws-sdk/middleware-recursion-detection': 3.914.0 + '@aws-sdk/middleware-user-agent': 3.916.0 + '@aws-sdk/region-config-resolver': 3.914.0 + '@aws-sdk/types': 3.914.0 + '@aws-sdk/util-endpoints': 3.916.0 + '@aws-sdk/util-user-agent-browser': 3.914.0 + '@aws-sdk/util-user-agent-node': 3.916.0 + '@smithy/config-resolver': 4.4.0 + '@smithy/core': 3.17.1 + '@smithy/fetch-http-handler': 5.3.4 + '@smithy/hash-node': 4.2.3 + '@smithy/invalid-dependency': 4.2.3 + '@smithy/middleware-content-length': 4.2.3 + '@smithy/middleware-endpoint': 4.3.5 + '@smithy/middleware-retry': 4.4.5 + '@smithy/middleware-serde': 4.2.3 + '@smithy/middleware-stack': 4.2.3 + '@smithy/node-config-provider': 4.3.3 + '@smithy/node-http-handler': 4.4.3 + '@smithy/protocol-http': 5.3.3 + '@smithy/smithy-client': 4.9.1 + '@smithy/types': 4.8.0 + '@smithy/url-parser': 4.2.3 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.4 + '@smithy/util-defaults-mode-node': 4.2.6 + '@smithy/util-endpoints': 3.2.3 + '@smithy/util-middleware': 4.2.3 + '@smithy/util-retry': 4.2.3 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/region-config-resolver@3.914.0': + dependencies: + '@aws-sdk/types': 3.914.0 + '@smithy/config-resolver': 4.4.0 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@aws-sdk/signature-v4-multi-region@3.916.0': + dependencies: + '@aws-sdk/middleware-sdk-s3': 3.916.0 + '@aws-sdk/types': 3.914.0 + '@smithy/protocol-http': 5.3.3 + '@smithy/signature-v4': 5.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.916.0': + dependencies: + '@aws-sdk/core': 3.916.0 + '@aws-sdk/nested-clients': 3.916.0 + '@aws-sdk/types': 3.914.0 + '@smithy/property-provider': 4.2.3 + '@smithy/shared-ini-file-loader': 4.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/types@3.914.0': + dependencies: + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@aws-sdk/util-arn-parser@3.893.0': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-endpoints@3.916.0': + dependencies: + '@aws-sdk/types': 3.914.0 + '@smithy/types': 4.8.0 + '@smithy/url-parser': 4.2.3 + '@smithy/util-endpoints': 3.2.3 + tslib: 2.8.1 + + '@aws-sdk/util-locate-window@3.893.0': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-browser@3.914.0': + dependencies: + '@aws-sdk/types': 3.914.0 + '@smithy/types': 4.8.0 + bowser: 2.12.1 + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-node@3.916.0': + dependencies: + '@aws-sdk/middleware-user-agent': 3.916.0 + '@aws-sdk/types': 3.914.0 + '@smithy/node-config-provider': 4.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.914.0': + dependencies: + '@smithy/types': 4.8.0 + fast-xml-parser: 5.2.5 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.0.1': {} + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/helper-validator-identifier@7.27.1': {} + + '@biomejs/biome@2.2.6': + optionalDependencies: + '@biomejs/cli-darwin-arm64': 2.2.6 + '@biomejs/cli-darwin-x64': 2.2.6 + '@biomejs/cli-linux-arm64': 2.2.6 + '@biomejs/cli-linux-arm64-musl': 2.2.6 + '@biomejs/cli-linux-x64': 2.2.6 + '@biomejs/cli-linux-x64-musl': 2.2.6 + '@biomejs/cli-win32-arm64': 2.2.6 + '@biomejs/cli-win32-x64': 2.2.6 + + '@biomejs/cli-darwin-arm64@2.2.6': + optional: true + + '@biomejs/cli-darwin-x64@2.2.6': + optional: true + + '@biomejs/cli-linux-arm64-musl@2.2.6': + optional: true + + '@biomejs/cli-linux-arm64@2.2.6': + optional: true + + '@biomejs/cli-linux-x64-musl@2.2.6': + optional: true + + '@biomejs/cli-linux-x64@2.2.6': + optional: true + + '@biomejs/cli-win32-arm64@2.2.6': + optional: true + + '@biomejs/cli-win32-x64@2.2.6': + optional: true + + '@commitlint/cli@20.1.0(@types/node@24.7.2)(typescript@5.9.3)': + dependencies: + '@commitlint/format': 20.0.0 + '@commitlint/lint': 20.0.0 + '@commitlint/load': 20.1.0(@types/node@24.7.2)(typescript@5.9.3) + '@commitlint/read': 20.0.0 + '@commitlint/types': 20.0.0 + tinyexec: 1.0.1 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/config-conventional@20.0.0': + dependencies: + '@commitlint/types': 20.0.0 + conventional-changelog-conventionalcommits: 7.0.2 + + '@commitlint/config-validator@20.0.0': + dependencies: + '@commitlint/types': 20.0.0 + ajv: 8.17.1 + + '@commitlint/ensure@20.0.0': + dependencies: + '@commitlint/types': 20.0.0 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.upperfirst: 4.3.1 + + '@commitlint/execute-rule@20.0.0': {} + + '@commitlint/format@20.0.0': + dependencies: + '@commitlint/types': 20.0.0 + chalk: 5.6.2 + + '@commitlint/is-ignored@20.0.0': + dependencies: + '@commitlint/types': 20.0.0 + semver: 7.7.2 + + '@commitlint/lint@20.0.0': + dependencies: + '@commitlint/is-ignored': 20.0.0 + '@commitlint/parse': 20.0.0 + '@commitlint/rules': 20.0.0 + '@commitlint/types': 20.0.0 + + '@commitlint/load@20.1.0(@types/node@24.7.2)(typescript@5.9.3)': + dependencies: + '@commitlint/config-validator': 20.0.0 + '@commitlint/execute-rule': 20.0.0 + '@commitlint/resolve-extends': 20.1.0 + '@commitlint/types': 20.0.0 + chalk: 5.6.2 + cosmiconfig: 9.0.0(typescript@5.9.3) + cosmiconfig-typescript-loader: 6.2.0(@types/node@24.7.2)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/message@20.0.0': {} + + '@commitlint/parse@20.0.0': + dependencies: + '@commitlint/types': 20.0.0 + conventional-changelog-angular: 7.0.0 + conventional-commits-parser: 5.0.0 + + '@commitlint/read@20.0.0': + dependencies: + '@commitlint/top-level': 20.0.0 + '@commitlint/types': 20.0.0 + git-raw-commits: 4.0.0 + minimist: 1.2.8 + tinyexec: 1.0.1 + + '@commitlint/resolve-extends@20.1.0': + dependencies: + '@commitlint/config-validator': 20.0.0 + '@commitlint/types': 20.0.0 + global-directory: 4.0.1 + import-meta-resolve: 4.2.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + + '@commitlint/rules@20.0.0': + dependencies: + '@commitlint/ensure': 20.0.0 + '@commitlint/message': 20.0.0 + '@commitlint/to-lines': 20.0.0 + '@commitlint/types': 20.0.0 + + '@commitlint/to-lines@20.0.0': {} + + '@commitlint/top-level@20.0.0': + dependencies: + find-up: 7.0.0 + + '@commitlint/types@20.0.0': + dependencies: + '@types/conventional-commits-parser': 5.0.1 + chalk: 5.6.2 + + '@fastify/ajv-compiler@4.0.2': + dependencies: + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) + fast-uri: 3.1.0 + + '@fastify/busboy@3.2.0': {} + + '@fastify/cors@11.1.0': + dependencies: + fastify-plugin: 5.1.0 + toad-cache: 3.7.0 + + '@fastify/deepmerge@3.1.0': {} + + '@fastify/error@4.2.0': {} + + '@fastify/fast-json-stringify-compiler@5.0.3': + dependencies: + fast-json-stringify: 6.0.1 + + '@fastify/forwarded@3.0.0': {} + + '@fastify/merge-json-schemas@0.2.1': + dependencies: + dequal: 2.0.3 + + '@fastify/multipart@9.3.0': + dependencies: + '@fastify/busboy': 3.2.0 + '@fastify/deepmerge': 3.1.0 + '@fastify/error': 4.2.0 + fastify-plugin: 5.1.0 + secure-json-parse: 4.0.0 + + '@fastify/proxy-addr@5.0.0': + dependencies: + '@fastify/forwarded': 3.0.0 + ipaddr.js: 2.2.0 + + '@google/genai@1.25.0': + dependencies: + google-auth-library: 9.15.1 + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + + '@huggingface/jinja@0.2.2': {} + + '@mistralai/mistralai@1.10.0': + dependencies: + zod: 3.25.76 + zod-to-json-schema: 3.24.6(zod@3.25.76) + + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + + '@smithy/abort-controller@4.2.3': + dependencies: + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/chunked-blob-reader-native@4.2.1': + dependencies: + '@smithy/util-base64': 4.3.0 + tslib: 2.8.1 + + '@smithy/chunked-blob-reader@5.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/config-resolver@4.4.0': + dependencies: + '@smithy/node-config-provider': 4.3.3 + '@smithy/types': 4.8.0 + '@smithy/util-config-provider': 4.2.0 + '@smithy/util-endpoints': 3.2.3 + '@smithy/util-middleware': 4.2.3 + tslib: 2.8.1 + + '@smithy/core@3.17.1': + dependencies: + '@smithy/middleware-serde': 4.2.3 + '@smithy/protocol-http': 5.3.3 + '@smithy/types': 4.8.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-middleware': 4.2.3 + '@smithy/util-stream': 4.5.4 + '@smithy/util-utf8': 4.2.0 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.2.3': + dependencies: + '@smithy/node-config-provider': 4.3.3 + '@smithy/property-provider': 4.2.3 + '@smithy/types': 4.8.0 + '@smithy/url-parser': 4.2.3 + tslib: 2.8.1 + + '@smithy/eventstream-codec@4.2.3': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.8.0 + '@smithy/util-hex-encoding': 4.2.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-browser@4.2.3': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-config-resolver@4.3.3': + dependencies: + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-node@4.2.3': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-universal@4.2.3': + dependencies: + '@smithy/eventstream-codec': 4.2.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.3.4': + dependencies: + '@smithy/protocol-http': 5.3.3 + '@smithy/querystring-builder': 4.2.3 + '@smithy/types': 4.8.0 + '@smithy/util-base64': 4.3.0 + tslib: 2.8.1 + + '@smithy/hash-blob-browser@4.2.4': + dependencies: + '@smithy/chunked-blob-reader': 5.2.0 + '@smithy/chunked-blob-reader-native': 4.2.1 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/hash-node@4.2.3': + dependencies: + '@smithy/types': 4.8.0 + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/hash-stream-node@4.2.3': + dependencies: + '@smithy/types': 4.8.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/invalid-dependency@4.2.3': + dependencies: + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/is-array-buffer@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/md5-js@4.2.3': + dependencies: + '@smithy/types': 4.8.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/middleware-content-length@4.2.3': + dependencies: + '@smithy/protocol-http': 5.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/middleware-endpoint@4.3.5': + dependencies: + '@smithy/core': 3.17.1 + '@smithy/middleware-serde': 4.2.3 + '@smithy/node-config-provider': 4.3.3 + '@smithy/shared-ini-file-loader': 4.3.3 + '@smithy/types': 4.8.0 + '@smithy/url-parser': 4.2.3 + '@smithy/util-middleware': 4.2.3 + tslib: 2.8.1 + + '@smithy/middleware-retry@4.4.5': + dependencies: + '@smithy/node-config-provider': 4.3.3 + '@smithy/protocol-http': 5.3.3 + '@smithy/service-error-classification': 4.2.3 + '@smithy/smithy-client': 4.9.1 + '@smithy/types': 4.8.0 + '@smithy/util-middleware': 4.2.3 + '@smithy/util-retry': 4.2.3 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + + '@smithy/middleware-serde@4.2.3': + dependencies: + '@smithy/protocol-http': 5.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/middleware-stack@4.2.3': + dependencies: + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/node-config-provider@4.3.3': + dependencies: + '@smithy/property-provider': 4.2.3 + '@smithy/shared-ini-file-loader': 4.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.4.3': + dependencies: + '@smithy/abort-controller': 4.2.3 + '@smithy/protocol-http': 5.3.3 + '@smithy/querystring-builder': 4.2.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/property-provider@4.2.3': + dependencies: + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/protocol-http@5.3.3': + dependencies: + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/querystring-builder@4.2.3': + dependencies: + '@smithy/types': 4.8.0 + '@smithy/util-uri-escape': 4.2.0 + tslib: 2.8.1 + + '@smithy/querystring-parser@4.2.3': + dependencies: + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/service-error-classification@4.2.3': + dependencies: + '@smithy/types': 4.8.0 + + '@smithy/shared-ini-file-loader@4.3.3': + dependencies: + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/signature-v4@5.3.3': + dependencies: + '@smithy/is-array-buffer': 4.2.0 + '@smithy/protocol-http': 5.3.3 + '@smithy/types': 4.8.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-middleware': 4.2.3 + '@smithy/util-uri-escape': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/smithy-client@4.9.1': + dependencies: + '@smithy/core': 3.17.1 + '@smithy/middleware-endpoint': 4.3.5 + '@smithy/middleware-stack': 4.2.3 + '@smithy/protocol-http': 5.3.3 + '@smithy/types': 4.8.0 + '@smithy/util-stream': 4.5.4 + tslib: 2.8.1 + + '@smithy/types@4.8.0': + dependencies: + tslib: 2.8.1 + + '@smithy/url-parser@4.2.3': + dependencies: + '@smithy/querystring-parser': 4.2.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/util-base64@4.3.0': + dependencies: + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-body-length-browser@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-body-length-node@4.2.1': + dependencies: + tslib: 2.8.1 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-buffer-from@4.2.0': + dependencies: + '@smithy/is-array-buffer': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-config-provider@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-defaults-mode-browser@4.3.4': + dependencies: + '@smithy/property-provider': 4.2.3 + '@smithy/smithy-client': 4.9.1 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/util-defaults-mode-node@4.2.6': + dependencies: + '@smithy/config-resolver': 4.4.0 + '@smithy/credential-provider-imds': 4.2.3 + '@smithy/node-config-provider': 4.3.3 + '@smithy/property-provider': 4.2.3 + '@smithy/smithy-client': 4.9.1 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/util-endpoints@3.2.3': + dependencies: + '@smithy/node-config-provider': 4.3.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/util-hex-encoding@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-middleware@4.2.3': + dependencies: + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/util-retry@4.2.3': + dependencies: + '@smithy/service-error-classification': 4.2.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/util-stream@4.5.4': + dependencies: + '@smithy/fetch-http-handler': 5.3.4 + '@smithy/node-http-handler': 4.4.3 + '@smithy/types': 4.8.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-uri-escape@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-utf8@4.2.0': + dependencies: + '@smithy/util-buffer-from': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-waiter@4.2.3': + dependencies: + '@smithy/abort-controller': 4.2.3 + '@smithy/types': 4.8.0 + tslib: 2.8.1 + + '@smithy/uuid@1.1.0': + dependencies: + tslib: 2.8.1 + + '@types/conventional-commits-parser@5.0.1': + dependencies: + '@types/node': 24.7.2 + + '@types/long@4.0.2': {} + + '@types/node@24.7.2': + dependencies: + undici-types: 7.14.0 + + '@xenova/transformers@2.17.2': + dependencies: + '@huggingface/jinja': 0.2.2 + onnxruntime-web: 1.14.0 + sharp: 0.32.6 + optionalDependencies: + onnxruntime-node: 1.14.0 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - react-native-b4a + + JSONStream@1.3.5: + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + + abstract-logging@2.0.1: {} + + agent-base@7.1.4: {} + + ajv-formats@3.0.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-escapes@7.1.1: + dependencies: + environment: 1.1.0 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.3: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + argparse@2.0.1: {} + + array-ify@1.0.0: {} + + asynckit@0.4.0: {} + + atomic-sleep@1.0.0: {} + + avvio@9.1.0: + dependencies: + '@fastify/error': 4.2.0 + fastq: 1.19.1 + + axios@1.13.2: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + b4a@1.7.3: {} + + balanced-match@1.0.2: {} + + bare-events@2.8.0: {} + + bare-fs@4.4.11: + dependencies: + bare-events: 2.8.0 + bare-path: 3.0.0 + bare-stream: 2.7.0(bare-events@2.8.0) + bare-url: 2.3.1 + fast-fifo: 1.3.2 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + optional: true + + bare-os@3.6.2: + optional: true + + bare-path@3.0.0: + dependencies: + bare-os: 3.6.2 + optional: true + + bare-stream@2.7.0(bare-events@2.8.0): + dependencies: + streamx: 2.23.0 + optionalDependencies: + bare-events: 2.8.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + optional: true + + bare-url@2.3.1: + dependencies: + bare-path: 3.0.0 + optional: true + + base64-js@1.5.1: {} + + bignumber.js@9.3.1: {} + + binary-extensions@2.3.0: {} + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + bowser@2.12.1: {} + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + buffer-equal-constant-time@1.0.1: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + callsites@3.1.0: {} + + chalk@5.6.2: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chownr@1.1.4: {} + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-truncate@5.1.0: + dependencies: + slice-ansi: 7.1.2 + string-width: 8.1.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.4 + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@14.0.1: {} + + compare-func@2.0.0: + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + + concat-map@0.0.1: {} + + conventional-changelog-angular@7.0.0: + dependencies: + compare-func: 2.0.0 + + conventional-changelog-conventionalcommits@7.0.2: + dependencies: + compare-func: 2.0.0 + + conventional-commits-parser@5.0.0: + dependencies: + JSONStream: 1.3.5 + is-text-path: 2.0.0 + meow: 12.1.1 + split2: 4.2.0 + + cookie@1.0.2: {} + + cosmiconfig-typescript-loader@6.2.0(@types/node@24.7.2)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3): + dependencies: + '@types/node': 24.7.2 + cosmiconfig: 9.0.0(typescript@5.9.3) + jiti: 2.6.1 + typescript: 5.9.3 + + cosmiconfig@9.0.0(typescript@5.9.3): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.9.3 + + dargs@8.1.0: {} + + debug@4.4.1(supports-color@5.5.0): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 5.5.0 + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + deep-extend@0.6.0: {} + + delayed-stream@1.0.0: {} + + dequal@2.0.3: {} - abstract-logging@2.0.1: {} + detect-libc@2.1.2: {} - ajv-formats@3.0.1(ajv@8.17.1): - optionalDependencies: - ajv: 8.17.1 + dot-prop@5.3.0: + dependencies: + is-obj: 2.0.0 - ajv@8.17.1: + dotenv@17.2.2: {} + + dunder-proto@1.0.1: dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 - anymatch@3.1.3: + ecdsa-sig-formatter@1.0.11: dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 + safe-buffer: 5.2.1 - atomic-sleep@1.0.0: {} + emoji-regex@10.6.0: {} - avvio@9.1.0: + emoji-regex@8.0.0: {} + + end-of-stream@1.4.5: dependencies: - '@fastify/error': 4.2.0 - fastq: 1.19.1 + once: 1.4.0 - balanced-match@1.0.2: {} + env-paths@2.2.1: {} - binary-extensions@2.3.0: {} + environment@1.1.0: {} - brace-expansion@1.1.12: + error-ex@1.3.4: dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 + is-arrayish: 0.2.1 - braces@3.0.3: + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: dependencies: - fill-range: 7.1.1 + es-errors: 1.3.0 - chokidar@3.6.0: + es-set-tostringtag@2.1.0: dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 - concat-map@0.0.1: {} + escalade@3.2.0: {} - cookie@1.0.2: {} + eventemitter3@5.0.1: {} - debug@4.4.1(supports-color@5.5.0): + events-universal@1.0.1: dependencies: - ms: 2.1.3 - optionalDependencies: - supports-color: 5.5.0 + bare-events: 2.8.0 + transitivePeerDependencies: + - bare-abort-controller - dequal@2.0.3: {} + expand-template@2.0.3: {} - dotenv@17.2.2: {} + extend@3.0.2: {} fast-decode-uri-component@1.0.1: {} fast-deep-equal@3.1.3: {} + fast-fifo@1.3.2: {} + fast-json-stringify@6.0.1: dependencies: '@fastify/merge-json-schemas': 0.2.1 @@ -489,6 +3208,12 @@ snapshots: fast-uri@3.1.0: {} + fast-xml-parser@5.2.5: + dependencies: + strnum: 2.1.1 + + fastify-plugin@5.1.0: {} + fastify@5.6.0: dependencies: '@fastify/ajv-compiler': 4.0.2 @@ -521,49 +3246,322 @@ snapshots: fast-querystring: 1.1.2 safe-regex2: 5.0.0 + find-up@7.0.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + + flatbuffers@1.12.0: {} + + follow-redirects@1.15.11: {} + + form-data@4.0.4: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + fs-constants@1.0.0: {} + fsevents@2.3.3: optional: true + function-bind@1.1.2: {} + + fuse.js@7.1.0: {} + + gaxios@6.7.1: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + is-stream: 2.0.1 + node-fetch: 2.7.0 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + gcp-metadata@6.1.1: + dependencies: + gaxios: 6.7.1 + google-logging-utils: 0.0.2 + json-bigint: 1.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.4.0: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + git-raw-commits@4.0.0: + dependencies: + dargs: 8.1.0 + meow: 12.1.1 + split2: 4.2.0 + + github-from-package@0.0.0: {} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + + google-auth-library@9.15.1: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 6.7.1 + gcp-metadata: 6.1.1 + gtoken: 7.1.0 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + google-logging-utils@0.0.2: {} + + gopd@1.2.0: {} + + gtoken@7.1.0: + dependencies: + gaxios: 6.7.1 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + guid-typescript@1.0.9: {} + has-flag@3.0.0: {} + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.1(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + + husky@9.1.7: {} + + ieee754@1.2.1: {} + ignore-by-default@1.0.1: {} + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-meta-resolve@4.2.0: {} + + inherits@2.0.4: {} + + ini@1.3.8: {} + + ini@4.1.1: {} + ipaddr.js@2.2.0: {} + is-arrayish@0.2.1: {} + + is-arrayish@0.3.4: {} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 is-extglob@2.1.1: {} + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@5.1.0: + dependencies: + get-east-asian-width: 1.4.0 + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 is-number@7.0.0: {} + is-obj@2.0.0: {} + + is-stream@2.0.1: {} + + is-text-path@2.0.0: + dependencies: + text-extensions: 2.4.0 + + jiti@2.6.1: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.1 + + json-parse-even-better-errors@2.3.1: {} + json-schema-ref-resolver@2.0.1: dependencies: dequal: 2.0.3 json-schema-traverse@1.0.0: {} + jsonparse@1.3.1: {} + + jwa@2.0.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@4.0.0: + dependencies: + jwa: 2.0.1 + safe-buffer: 5.2.1 + light-my-request@6.6.0: dependencies: cookie: 1.0.2 process-warning: 4.0.1 set-cookie-parser: 2.7.1 + lines-and-columns@1.2.4: {} + + lint-staged@16.2.4: + dependencies: + commander: 14.0.1 + listr2: 9.0.4 + micromatch: 4.0.8 + nano-spawn: 2.0.0 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.8.1 + + listr2@9.0.4: + dependencies: + cli-truncate: 5.1.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.2 + + locate-path@7.2.0: + dependencies: + p-locate: 6.0.0 + + lodash.camelcase@4.3.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.kebabcase@4.1.1: {} + + lodash.merge@4.6.2: {} + + lodash.mergewith@4.6.2: {} + + lodash.snakecase@4.1.1: {} + + lodash.startcase@4.4.0: {} + + lodash.uniq@4.5.0: {} + + lodash.upperfirst@4.3.1: {} + + log-update@6.1.0: + dependencies: + ansi-escapes: 7.1.1 + cli-cursor: 5.0.0 + slice-ansi: 7.1.2 + strip-ansi: 7.1.2 + wrap-ansi: 9.0.2 + + long@4.0.0: {} + + math-intrinsics@1.1.0: {} + + meow@12.1.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mimic-function@5.0.1: {} + + mimic-response@3.1.0: {} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.12 + minimist@1.2.8: {} + + mkdirp-classic@0.5.3: {} + ms@2.1.3: {} + nano-spawn@2.0.0: {} + + napi-build-utils@2.0.0: {} + + node-abi@3.79.0: + dependencies: + semver: 7.7.3 + + node-addon-api@6.1.0: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + nodemon@3.1.10: dependencies: chokidar: 3.6.0 @@ -581,6 +3579,55 @@ snapshots: on-exit-leak-free@2.1.2: {} + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + onnx-proto@4.0.4: + dependencies: + protobufjs: 6.11.4 + + onnxruntime-common@1.14.0: {} + + onnxruntime-node@1.14.0: + dependencies: + onnxruntime-common: 1.14.0 + optional: true + + onnxruntime-web@1.14.0: + dependencies: + flatbuffers: 1.12.0 + guid-typescript: 1.0.9 + long: 4.0.0 + onnx-proto: 4.0.4 + onnxruntime-common: 1.14.0 + platform: 1.3.6 + + p-limit@4.0.0: + dependencies: + yocto-queue: 1.2.1 + + p-locate@6.0.0: + dependencies: + p-limit: 4.0.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.27.1 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + path-exists@5.0.0: {} + pg-cloudflare@1.2.7: optional: true @@ -616,8 +3663,12 @@ snapshots: dependencies: split2: 4.2.0 + picocolors@1.1.1: {} + picomatch@2.3.1: {} + pidtree@0.6.0: {} + pino-abstract-transport@2.0.0: dependencies: split2: 4.2.0 @@ -638,6 +3689,8 @@ snapshots: sonic-boom: 4.2.0 thread-stream: 3.1.0 + platform@1.3.6: {} + postgres-array@2.0.0: {} postgres-bytea@1.0.0: {} @@ -648,28 +3701,92 @@ snapshots: dependencies: xtend: 4.0.2 + prebuild-install@7.1.3: + dependencies: + detect-libc: 2.1.2 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 2.0.0 + node-abi: 3.79.0 + pump: 3.0.3 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.4 + tunnel-agent: 0.6.0 + process-warning@4.0.1: {} process-warning@5.0.0: {} + protobufjs@6.11.4: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/long': 4.0.2 + '@types/node': 24.7.2 + long: 4.0.0 + + proxy-from-env@1.1.0: {} + pstree.remy@1.1.8: {} + pump@3.0.3: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + quick-format-unescaped@4.0.4: {} + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 real-require@0.2.0: {} + require-directory@2.1.1: {} + require-from-string@2.0.2: {} + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + ret@0.5.0: {} reusify@1.1.0: {} rfdc@1.4.1: {} + safe-buffer@5.2.1: {} + safe-regex2@5.0.0: dependencies: ret: 0.5.0 @@ -680,26 +3797,154 @@ snapshots: semver@7.7.2: {} + semver@7.7.3: {} + set-cookie-parser@2.7.1: {} + sharp@0.32.6: + dependencies: + color: 4.2.3 + detect-libc: 2.1.2 + node-addon-api: 6.1.0 + prebuild-install: 7.1.3 + semver: 7.7.3 + simple-get: 4.0.1 + tar-fs: 3.1.1 + tunnel-agent: 0.6.0 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - react-native-b4a + + signal-exit@4.1.0: {} + + simple-concat@1.0.1: {} + + simple-get@4.0.1: + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + + simple-swizzle@0.2.4: + dependencies: + is-arrayish: 0.3.4 + simple-update-notifier@2.0.0: dependencies: semver: 7.7.2 + slice-ansi@7.1.2: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + sonic-boom@4.2.0: dependencies: atomic-sleep: 1.0.0 split2@4.2.0: {} + streamx@2.23.0: + dependencies: + events-universal: 1.0.1 + fast-fifo: 1.3.2 + text-decoder: 1.2.3 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + string-argv@0.3.2: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.4.0 + strip-ansi: 7.1.2 + + string-width@8.1.0: + dependencies: + get-east-asian-width: 1.4.0 + strip-ansi: 7.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.2: + dependencies: + ansi-regex: 6.2.2 + + strip-json-comments@2.0.1: {} + + strnum@2.1.1: {} + supports-color@5.5.0: dependencies: has-flag: 3.0.0 + tar-fs@2.1.4: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.3 + tar-stream: 2.2.0 + + tar-fs@3.1.1: + dependencies: + pump: 3.0.3 + tar-stream: 3.1.7 + optionalDependencies: + bare-fs: 4.4.11 + bare-path: 3.0.0 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - react-native-b4a + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + tar-stream@3.1.7: + dependencies: + b4a: 1.7.3 + fast-fifo: 1.3.2 + streamx: 2.23.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + text-decoder@1.2.3: + dependencies: + b4a: 1.7.3 + transitivePeerDependencies: + - react-native-b4a + + text-extensions@2.4.0: {} + thread-stream@3.1.0: dependencies: real-require: 0.2.0 + through@2.3.8: {} + + tinyexec@1.0.1: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -708,10 +3953,69 @@ snapshots: touch@3.1.1: {} + tr46@0.0.3: {} + + tslib@2.8.1: {} + + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 + + typescript@5.9.3: {} + undefsafe@2.0.5: {} + undici-types@7.14.0: {} + + unicorn-magic@0.1.0: {} + + util-deprecate@1.0.2: {} + + uuid@9.0.1: {} + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.1.2 + + wrappy@1.0.2: {} + + ws@8.18.3: {} + xtend@4.0.2: {} + y18n@5.0.8: {} + + yaml@2.8.1: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@1.2.1: {} + zod-to-json-schema@3.24.6(zod@3.25.76): dependencies: zod: 3.25.76 diff --git a/server.js b/server.js new file mode 100644 index 0000000..31236a7 --- /dev/null +++ b/server.js @@ -0,0 +1,42 @@ +// server.js +import "dotenv/config"; +import Fastify from "fastify"; +import { db_initialization } from "./src/database/initialization.js"; +import { pool } from "./src/database/connection.js"; +import toothpasteRoutes from "./src/routes/toothpaste.routes.js"; +import fastifyMultipart from "@fastify/multipart"; +import cors from "@fastify/cors"; + +const fastify = Fastify({ + logger: true, +}); + +await fastify.register(cors, { + origin: "*", + methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], + allowedHeaders: ["Content-Type", "Authorization"], +}); + +fastify.register(fastifyMultipart, { attachFieldsToBody: true }); +fastify.register(toothpasteRoutes, { prefix: "/api/v1" }); + +const start = async () => { + try { + await fastify.listen({ port: 3000 }); + console.log("Server running at http://localhost:3000"); + } catch (err) { + fastify.log.error(err); + process.exit(1); + } +}; + +const shutdown = async () => { + await fastify.close(); + await pool.end(); + process.exit(0); +}; + +process.on("SIGTERM", shutdown); +process.on("SIGINT", shutdown); + +start(); diff --git a/src/controllers/toothpaste.controller.js b/src/controllers/toothpaste.controller.js new file mode 100644 index 0000000..1a6252f --- /dev/null +++ b/src/controllers/toothpaste.controller.js @@ -0,0 +1,95 @@ +import { getAllToothpastes } from "../services/toothpaste.getAll.service.js"; +import { createToothpaste } from "../services/toothpaste.create.service.js"; +import { getToothpasteById } from "../services/toothpaste.getById.service.js"; + +/** + * Get all toothpastes + * GET /toothpastes + */ +export async function getAllToothpastesHandler(request, reply) { + try { + const toothpastes = await getAllToothpastes(); + + return reply.code(200).send({ + success: true, + amount: toothpastes.length, + data: toothpastes, + }); + } catch (error) { + request.log.error(error); + return reply.code(500).send({ + success: false, + error: "Failed to fetch toothpastes", + message: error.message, + }); + } +} + +/** + * Get a single toothpaste by ID + * GET /toothpastes/:id + */ +export async function getToothpasteByIdHandler(request, reply) { + try { + const { id } = request.params; + + const toothpaste = await getToothpasteById(id); + + if (!toothpaste) { + return reply.code(404).send({ + success: false, + error: "Toothpaste not found", + }); + } + + return reply.code(200).send({ + success: true, + data: toothpaste, + }); + } catch (error) { + request.log.error(error); + return reply.code(500).send({ + success: false, + error: "Failed to fetch toothpaste", + message: error.message, + }); + } +} + +export async function createToothpasteHandler(request, reply) { + try { + const file = await request.body.file; + if (!file) { + return reply + .code(400) + .send({ success: false, error: "No file uploaded" }); + } + const name = request.body.name?.value; + const brand = request.body.brand?.value; + const ingredientsRaw = request.body.ingredients?.value; + const ingredientsArray = JSON.parse(ingredientsRaw); + + const mimetype = file.mimetype; + const buffer = await file.toBuffer(); + console.log(ingredientsArray); + + await createToothpaste({ + name: name, + brand: brand, + ingredients_raw: ingredientsArray, + image: buffer, + image_mimetype: mimetype, + }); + + return reply.code(200).send({ + success: true, + }); + } catch (error) { + request.log.error(error); + return reply.code(500).send({ + success: false, + error: "Failed to create", + message: error.message, + }); + } +} diff --git a/src/database/connection.js b/src/database/connection.js new file mode 100644 index 0000000..b0d02bc --- /dev/null +++ b/src/database/connection.js @@ -0,0 +1,22 @@ +import pg from "pg"; + +const { Pool } = pg; + +const pool = new Pool({ + host: process.env.PG_HOST || "localhost", + user: process.env.PG_USER || "postgres", + password: process.env.PG_PASSWORD || "", + database: process.env.PG_DATABASE || "devdb", + port: process.env.PG_PORT || 5433, + max: 50, + idleTimeoutMillis: 15000, + connectionTimeoutMillis: 2000, // Return an error after 2s if connection could not be established +}); + +pool.on("error", (err) => { + console.error("Unexpected PG pool error", err); +}); + +export const query = (text, params) => pool.query(text, params); +export const getClient = () => pool.connect(); +export { pool }; diff --git a/src/database/ingredient_loader.js b/src/database/ingredient_loader.js new file mode 100644 index 0000000..a744a1a --- /dev/null +++ b/src/database/ingredient_loader.js @@ -0,0 +1,155 @@ +import fs from "fs"; +import { getClient } from "./connection.js"; + +// Category mapping from JSON format to DB +const CATEGORY_MAPPING = { + "Flavoring Agent": "flavoring", + Preservative: "preservative", + Abrasive: "abrasive", + "Whitening Agent": "whitening", + "Fluoride Compound": "fluoride", + Humectant: "humectant", + Surfactant: "surfactant", + Binder: "binder", + "Thickening Agent": "binder", + "Binding Agent": "binder", +}; + +// Evidence level mapping +const EVIDENCE_MAPPING = { + High: "high", + Moderate: "moderate", + Low: "low", + Limited: "limited", +}; + +export async function loadIngredients(jsonFilePath) { + const client = await getClient(); + + try { + console.log("Loading ingredients from JSON..."); + + // Read JSON file + const fileContent = fs.readFileSync(jsonFilePath, "utf8"); + const ingredients = JSON.parse(fileContent); + + if (!Array.isArray(ingredients)) { + throw new Error("JSON file must contain an array of ingredients"); + } + + console.log(`Found ${ingredients.length} ingredients to load`); + + let successCount = 0; + let errorCount = 0; + const errors = []; + + for (const ingredient of ingredients) { + try { + const category = ingredient.category || null; + + // Map evidence level to lowercase + const evidenceLevel = ingredient.evidence_level + ? EVIDENCE_MAPPING[ingredient.evidence_level] || null + : null; + + // Parse alternative names (handle both string and array) + let alternativeNames = []; + if (ingredient.alternative_names) { + if (Array.isArray(ingredient.alternative_names)) { + alternativeNames = ingredient.alternative_names; + } else if (typeof ingredient.alternative_names === "string") { + alternativeNames = ingredient.alternative_names + .split(",") + .map((name) => name.trim()) + .filter((name) => name.length > 0); + } + } + + // Insert ingredient + await client.query( + `INSERT INTO ingredients ( + name, + alternative_names, + category, + benefits, + risks, + evidence_level, + labeling_echa, + safety_score, + regulatory_notes, + link_echa, + link_cosing, + link_pubchem, + link_other + ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) + ON CONFLICT (name) DO UPDATE SET + alternative_names = EXCLUDED.alternative_names, + category = EXCLUDED.category, + benefits = EXCLUDED.benefits, + risks = EXCLUDED.risks, + evidence_level = EXCLUDED.evidence_level, + labeling_echa = EXCLUDED.labeling_echa, + safety_score = EXCLUDED.safety_score, + regulatory_notes = EXCLUDED.regulatory_notes, + link_echa = EXCLUDED.link_echa, + link_cosing = EXCLUDED.link_cosing, + link_pubchem = EXCLUDED.link_pubchem, + link_other = EXCLUDED.link_other, + updated_at = NOW()`, + [ + ingredient.name, + alternativeNames, + category, + ingredient.benefits || null, + ingredient.risks || null, + evidenceLevel, + ingredient.labeling_echa || null, + ingredient.safety_score || null, + ingredient.regulatory_notes || null, + ingredient.link_echa || null, + ingredient.link_cosIng || null, + ingredient.link_pubchem || null, + ingredient.link_other || null, + ], + ); + + successCount++; + + if (successCount % 10 === 0) { + console.log( + `✓ Loaded ${successCount}/${ingredients.length} ingredients...`, + ); + } + } catch (error) { + errorCount++; + errors.push({ + ingredient: ingredient.name, + error: error.message, + }); + console.error( + `✗ Error loading ingredient "${ingredient.name}": ${error.message}`, + ); + } + } + + console.log("\n" + "=".repeat(100)); + console.log(`Ingredient loading completed!`); + console.log(`✓ Successfully loaded: ${successCount}`); + console.log(`✗ Errors: ${errorCount}`); + + if (errors.length > 0) { + console.log("\nErrors details:"); + errors.forEach((err) => { + console.log(` - ${err.ingredient}: ${err.error}`); + }); + } + console.log("=".repeat(100) + "\n"); + + return { successCount, errorCount, errors }; + } catch (error) { + console.error("Error loading ingredients:", error); + throw error; + } finally { + client.release(); + } +} diff --git a/src/database/initialization.js b/src/database/initialization.js new file mode 100644 index 0000000..62db190 --- /dev/null +++ b/src/database/initialization.js @@ -0,0 +1,129 @@ +import pg from "pg"; +import { getClient } from "./connection.js"; + +export async function db_initialization() { + /* const client = await getClient(); + + try { + console.log("Starting database cleanup and setup..."); + + // Drop all tables (cascades will handle dependencies) + await client.query(`DROP TABLE IF EXISTS toothpaste_ingredients CASCADE;`); + await client.query(`DROP TABLE IF EXISTS ingredients CASCADE;`); + await client.query(`DROP TABLE IF EXISTS toothpastes CASCADE;`); + console.log("✓ Existing tables dropped"); + + // Drop all ENUM types + await client.query(`DROP TYPE IF EXISTS ingredient_category CASCADE;`); + await client.query(`DROP TYPE IF EXISTS evidence_level_enum CASCADE;`); + await client.query(`DROP TYPE IF EXISTS image_type_enum CASCADE;`); + console.log("✓ Existing ENUM types dropped"); + + // Create vector extension + await client.query(`CREATE EXTENSION IF NOT EXISTS vector;`); + console.log("✓ Vector extension ready"); + + + + await client.query(` + CREATE TYPE evidence_level_enum AS ENUM ('high', 'moderate', 'low', 'limited'); + `); + console.log("✓ evidence_level_enum type created"); + + // Create toothpastes table + await client.query(` + CREATE TABLE toothpastes ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + brand VARCHAR(255), + description TEXT, + image_url VARCHAR(500) NOT NULL, + image_embedding vector(512), + overall_score DECIMAL(3,1), + score_updated_at TIMESTAMP, + name_embedding vector(3072), + is_whitening BOOLEAN DEFAULT false, + for_sensitive_teeth BOOLEAN DEFAULT false, + is_fluoride_free BOOLEAN DEFAULT false, + is_natural BOOLEAN DEFAULT false, + for_kids BOOLEAN DEFAULT false, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() + ); + `); + console.log("✓ toothpastes table created"); + + // Create ingredients table with additional fields from your JSON + await client.query(` + CREATE TABLE ingredients ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL UNIQUE, + alternative_names TEXT[], + category VARCHAR(128), + benefits TEXT, + risks TEXT, + evidence_level evidence_level_enum, + labeling_echa TEXT, + safety_score DECIMAL(3,1), + regulatory_notes TEXT, + link_echa VARCHAR(500), + link_cosing VARCHAR(500), + link_pubchem VARCHAR(500), + link_other VARCHAR(500), + name_embedding vector(3072), + alternative_name_embedding vector(3072), + sources TEXT[], + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() + ); + `); + console.log("✓ ingredients table created"); + + // Create junction table + await client.query(` + CREATE TABLE toothpaste_ingredients ( + toothpaste_id INTEGER REFERENCES toothpastes(id) ON DELETE CASCADE, + ingredient_id INTEGER REFERENCES ingredients(id) ON DELETE CASCADE, + concentration_percentage DECIMAL(5,2), + PRIMARY KEY (toothpaste_id, ingredient_id) + ); + `); + console.log("✓ toothpaste_ingredients table created"); + + // Create standard indexes + await client.query(`CREATE INDEX idx_toothpastes_brand ON toothpastes(brand);`); + await client.query(`CREATE INDEX idx_toothpastes_score ON toothpastes(overall_score DESC);`); + await client.query(`CREATE INDEX idx_toothpastes_filters ON toothpastes(is_whitening, for_sensitive_teeth, is_fluoride_free);`); + await client.query(`CREATE INDEX idx_ingredients_category ON ingredients(category);`); + await client.query(`CREATE INDEX idx_ingredients_safety_score ON ingredients(safety_score DESC);`); + console.log("✓ Standard indexes created"); + + // Create vector similarity indexes + + //await client.query(` + // CREATE INDEX idx_toothpastes_name_embedding ON toothpastes + // USING hnsw (name_embedding vector_cosine_ops); + //`); + //await client.query(` + // CREATE INDEX idx_ingredients_name_embedding ON ingredients + // USING hnsw (name_embedding vector_cosine_ops); + //`); + //await client.query(` + // CREATE INDEX idx_ingredients_alternative_name_embedding ON ingredients + // USING hnsw (alternative_name_embedding vector_cosine_ops); + //`); + //console.log("✓ Vector similarity indexes created"); + + + + console.log("\n" + "=".repeat(100)); + console.log("Database setup completed successfully!"); + console.log("=".repeat(100) + "\n"); + } catch (error) { + console.error("Error setting up database:", error); + throw error; + } finally { + client.release(); + } + */ +} diff --git a/src/parsers/find_links_and_cas.js b/src/parsers/find_links_and_cas.js new file mode 100644 index 0000000..5732ec1 --- /dev/null +++ b/src/parsers/find_links_and_cas.js @@ -0,0 +1,143 @@ +/** + * Finds CAS numbers and generates reference links. + * - Reads raw ingredients (JSON) + * - Uses Gemini to find CAS numbers if missing + * - Generates PubChem, ECHA, and CosIng links (raw, needs manual checking) + * - Writes enriched data to a new JSON file + */ + +import { readFile, writeFile } from "fs/promises"; +import { GoogleGenAI } from "@google/genai"; + +const INPUT_FILE = "raw_ingr_no_links.json"; +const OUTPUT_FILE = "raw_ingr_with_links.json"; +const DELAY_MS = 5000; + +const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +// Extract CAS number via Gemini +async function extractCASNumber(ingredientName, genAI) { + const prompt = `You are a chemical information assistant. Given the ingredient name "${ingredientName}", provide the CAS number (format: XX-XX-X or XXX-XX-X or XXXX-XX-X). If you cannot find it or are unsure, respond with "NOT_FOUND". + Do not include any explanation, just the CAS number or NOT_FOUND.`; + + try { + const response = await genAI.models.generateContent({ + model: "gemini-2.5-flash", + contents: [{ text: prompt }], + }); + + const responseText = response.text.trim(); + const casPattern = /^\d{2,7}-\d{2}-\d$/; + if (casPattern.test(responseText)) { + return responseText; + } + + return null; + } catch (error) { + console.error(`Error extracting CAS for ${ingredientName}:`, error.message); + return null; + } +} + +// Generate links for known CAS +function generateLinks(casNumber) { + if (!casNumber) { + return { + link_echa: null, + link_pubchem: null, + link_cosIng: null, + }; + } + + // For ECHA, we need to convert CAS to substance ID format + // The link format is: https://chem.echa.europa.eu/[SUBSTANCE_ID]/overview?searchText=[CAS] + const echaLink = `https://chem.echa.europa.eu/substance-search?searchText=${casNumber}`; + const pubchemLink = `https://pubchem.ncbi.nlm.nih.gov/compound/${casNumber}`; + const cosIngLink = `https://ec.europa.eu/growth/tools-databases/cosing/index.cfm?fuseaction=search.results&search=${casNumber}`; + + return { + link_echa: echaLink, + link_pubchem: pubchemLink, + link_cosIng: cosIngLink, + }; +} + +// Main process +async function processIngredients() { + console.log("Starting ingredient processing..."); + const genAI = new GoogleGenAI({}); + + // Read input file + let ingredients; + try { + const fileContent = await readFile(INPUT_FILE, "utf-8"); + ingredients = JSON.parse(fileContent); + console.log(`Loaded ${ingredients.length} ingredients`); + } catch (error) { + console.error("Error reading input file:", error.message); + return; + } + + const processedIngredients = []; + + for (let i = 0; i < ingredients.length; i++) { + const ingredient = ingredients[i]; + console.log( + `\nProcessing ${i + 1}/${ingredients.length}: ${ingredient.name}`, + ); + + let casNumber = ingredient.cas_number; + + // If CAS number is missing, try to extract it using Gemini + if (!casNumber) { + console.log(` Extracting CAS number for ${ingredient.name}...`); + casNumber = await extractCASNumber(ingredient.name, genAI); + + if (casNumber) { + console.log(` Found CAS: ${casNumber}`); + } else { + console.log(` Could not find CAS number`); + } + + await delay(DELAY_MS); + } else { + console.log(` Using existing CAS: ${casNumber}`); + } + + // Generate links + const links = generateLinks(casNumber); + + // Create updated ingredient object + const updatedIngredient = { + name: ingredient.name, + cas_number: casNumber, + link_echa: links.link_echa, + link_pubchem: links.link_pubchem, + link_cosIng: links.link_cosIng, + }; + + processedIngredients.push(updatedIngredient); + + if ((i + 1) % 10 === 0) { + await writeFile( + OUTPUT_FILE, + JSON.stringify(processedIngredients, null, 2), + "utf-8", + ); + console.log(` Progress saved (${i + 1}/${ingredients.length})`); + } + } + + // Save final results + await writeFile( + OUTPUT_FILE, + JSON.stringify(processedIngredients, null, 2), + "utf-8", + ); + console.log(`\nProcessing complete! Results saved to ${OUTPUT_FILE}`); +} + +processIngredients().catch((error) => { + console.error("Fatal error:", error); + process.exit(1); +}); diff --git a/src/parsers/ingredients_analyzer.js b/src/parsers/ingredients_analyzer.js new file mode 100644 index 0000000..368e490 --- /dev/null +++ b/src/parsers/ingredients_analyzer.js @@ -0,0 +1,267 @@ +import * as fs from "node:fs"; +import { readFile, writeFile } from "fs/promises"; +import { GoogleGenAI } from "@google/genai"; + +/** + * Extract unique elements from a comma-separated file + * @param {string} inputPath - Path to the input file + * @param {string} outputPath - Path to the output file + * @returns {Promise} + */ +async function extractUniqueElements(inputPath, outputPath) { + try { + const content = fs.readFileSync(inputPath, "utf-8"); + + const lines = content.split("\n"); + const allElements = []; + + lines.forEach((line) => { + const elements = line + .split(",") + .map((item) => item.trim().toLowerCase()) + .filter((item) => item.length > 0); + allElements.push(...elements); + }); + + const uniqueElements = [...new Set(allElements)]; + const output = uniqueElements.join("\n"); + fs.writeFileSync(outputPath, output, "utf-8"); + + console.log(`Found ${uniqueElements.length} unique elements`); + console.log(`Output written to ${outputPath}`); + } catch (error) { + console.error("Error processing file:", error.message); + throw error; + } +} + +/** + * Searches for ingredient data if links not provided + */ +async function findIngredientLinks(ingredientName) { + const searchUrls = { + pubchem: `https://pubchem.ncbi.nlm.nih.gov/compound/${encodeURIComponent(ingredientName)}`, + cosIng: `https://ec.europa.eu/growth/tools-databases/cosing/index.cfm?fuseaction=search.results&search=${encodeURIComponent(ingredientName)}`, + echa: `https://echa.europa.eu/search-for-chemicals?search_box=${encodeURIComponent(ingredientName)}`, + }; + + console.log( + `No links provided. Attempting to find data for: ${ingredientName}`, + ); + return searchUrls; +} + +/** + * system prompt for Gemini + */ +function generateSystemPrompt() { + return `You are an expert chemicals ingredient analyst. Analyze the provided web data about an ingredient and return a structured JSON response. + Your analysis should include: + 1. Extract the ingredient name + 2. Determine the category (e.g., "Preservative", "Surfactant", "Humectant", "Antioxidant", etc.) + 3. List key benefits for cosmetic use + 4. List potential risks or concerns + 5. Extract ECHA labeling information (H-codes, EUH-codes) + 6. Calculate a safety score from 1-10 where: + - 10 = Excellent safety profile, minimal concerns + - 7-9 = Good safety, minor concerns + - 4-6 = Moderate concerns, use with caution + - 1-3 = Significant safety concerns + 7. Extract any regulatory notes or usage restrictions + 8. Preserve the source links + + Base your safety score on: + - Hazard classifications (H-codes) + - Regulatory restrictions + - Known allergenic potential + - Usage concentration limits + - Overall risk-benefit profile + +Return ONLY valid JSON in this exact format (no markdown, no extra text): + { + "name": "ingredient name", + "category": "category type", + "benefits": "key benefits for cosmetic use", + "risks": "potential risks or concerns", + "labeling_echa": "H-codes and EUH-codes", + "safety_score": "number from 1-10", + "regulatory_notes": "any restrictions or required labeling", + "link_echa": "url or empty string", + "link_cosIng": "url or empty string", + "link_pubchem": "url or empty string", + "link_other": "url or empty string" + }`; +} + +/** + * Analyze ingredient data + */ +async function analyzeWithGemini(resourceLinks, ingredientName) { + const genAI = new GoogleGenAI({}); + + const systemPrompt = generateSystemPrompt(); + const resourceLinksText = ` + Ingredient: ${ingredientName} + + Available resource links: + - ECHA: ${resourceLinks.echa || "Not provided"} + - CosIng: ${resourceLinks.cosIng || "Not provided"} + - PubChem: ${resourceLinks.pubchem || "Not provided"} + - Other: ${resourceLinks.other || "Not provided"} + `.trim(); + + const contents = [ + { text: systemPrompt }, + { text: resourceLinksText }, + { + text: "The analysis should be based only on the links mentioned above and return the JSON response:", + }, + ]; + + try { + const response = await genAI.models.generateContent({ + model: "gemini-2.5-flash", + contents: contents, + }); + + const responseText = response.text; + + console.log(contents); + console.log("\n=== GEMINI OUTPUT ==="); + console.log(responseText); + console.log("=== END GEMINI OUTPUT ===\n"); + + return responseText; + } catch (error) { + console.error("Error calling Gemini API:", error); + throw error; + } +} + +/** + * Parses the Gemini response and cleans the JSON + */ +function parseGeminiResponse(responseText) { + let cleanedText = responseText.trim(); + cleanedText = cleanedText.replace(/```json\n?/g, ""); + cleanedText = cleanedText.replace(/```\n?/g, ""); + cleanedText = cleanedText.trim(); + + try { + const parsed = JSON.parse(cleanedText); + return parsed; + } catch (error) { + console.error("Error parsing JSON response:", error); + console.error("Response text:", cleanedText); + throw new Error("Failed to parse Gemini response as JSON"); + } +} + +/** + * JSON file operations + */ +async function saveToFile( + ingredientData, + filename = "processed_ingredients.json", +) { + try { + let existingData = []; + + // Try to read existing file + try { + const fileContent = await readFile(filename, "utf-8"); + existingData = JSON.parse(fileContent); + } catch (error) { + // File doesn't exist or is empty, start fresh + console.log("Creating new processed_ingredients.json file"); + } + + // Add new ingredient + existingData.push(ingredientData); + + // Write back to file + await writeFile(filename, JSON.stringify(existingData, null, 2), "utf-8"); + console.log(`\n✓ Data saved to ${filename}`); + } catch (error) { + console.error("Error saving to file:", error); + throw error; + } +} + +/** + * Main function to process ingredient data + * + * @param {string} ingredientName - Name of the ingredient + * @param {Object} links - Object with links: { echa: 'url', cosIng: 'url', pubchem: 'url', other: 'url' } + */ +async function processIngredient(ingredientName, links = {}) { + console.log(`\n${"=".repeat(60)}`); + console.log(`Processing ingredient: ${ingredientName}`); + console.log("=".repeat(60)); + + try { + let resource_links; + + if (links.echa || links.cosIng || links.pubchem || links.other) { + resource_links = links; + } else { + // Try to find links automatically + console.log("No links provided. Searching for ingredient data..."); + resource_links = await findIngredientLinks(ingredientName); + } + + // Analyze with Gemini + const geminiResponse = await analyzeWithGemini( + resource_links, + ingredientName, + ); + const ingredientData = parseGeminiResponse(geminiResponse); + + // Add metadata about sources + if (Object.keys(resource_links).length === 0) { + ingredientData.name = `${ingredientData.name} (own knowledge)`; + } + + ingredientData.link_echa = ingredientData.link_echa || links.echa || ""; + ingredientData.link_cosIng = + ingredientData.link_cosIng || links.cosIng || ""; + ingredientData.link_pubchem = + ingredientData.link_pubchem || links.pubchem || ""; + ingredientData.link_other = ingredientData.link_other || links.other || ""; + + // Save + await saveToFile(ingredientData); + + console.log("\n✓ Processing complete!"); + console.log("Final data:", JSON.stringify(ingredientData, null, 2)); + + return ingredientData; + } catch (error) { + console.error( + `\n✗ Error processing ingredient "${ingredientName}":`, + error, + ); + throw error; + } +} + +async function main() { + const ingredientsList = JSON.parse( + await readFile("raw_ingr_with_links.json", "utf-8"), + ); + + for (const item of ingredientsList) { + const { name, link_echa, link_cosIng, link_pubchem, link_other } = item; + await processIngredient(name, { + echa: link_echa || "", + cosIng: link_cosIng || "", + pubchem: link_pubchem || "", + other: link_other || "", + }); + } + + await new Promise((res) => setTimeout(res, 5000)); +} + +main().catch(console.error); +export { processIngredient, analyzeWithGemini }; diff --git a/src/parsers/ocr_ingredients.js b/src/parsers/ocr_ingredients.js new file mode 100644 index 0000000..80bdd38 --- /dev/null +++ b/src/parsers/ocr_ingredients.js @@ -0,0 +1,107 @@ +import { GoogleGenAI } from "@google/genai"; +import "dotenv/config"; +import * as fs from "node:fs"; +import * as path from "node:path"; + +/** + * Extract ingredients from an image using OCR + * @param {string} imagePath - Path to the image file + * @returns {Promise} Array of ingredient strings + */ +async function extractIngredients(imagePath) { + const genAI = new GoogleGenAI({}); + const base64ImageFile = fs.readFileSync(imagePath, { + encoding: "base64", + }); + + const prompt = `Analyze this image and extract ONLY the ingredients list. + Return a comma-separated list of ingredients with no additional text, formatting, or markdown. + Remove brand names, descriptions, instructions, and any non-ingredient text. + Just return the ingredient names separated by commas (in one line).`; + + const contents = [ + { + inlineData: { + mimeType: "image/png", + data: base64ImageFile, + }, + }, + { text: prompt }, + ]; + + const response = await genAI.models.generateContent({ + model: "gemini-2.5-flash", + contents: contents, + }); + + const ingredientsText = response.text; + return parseIngredients(ingredientsText); +} + +function parseIngredients(ingredientsText) { + return ingredientsText + .split(",") + .map((ingredient) => ingredient.trim()) + .filter((ingredient) => ingredient.length > 0); +} + +/** + * Delay execution for specified milliseconds + * @param {number} ms - Milliseconds to wait + */ +function delay(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +/** + * Process all images in the images folder + */ +async function processAllImages() { + const imagesFolder = "src/parsers/images"; + const outputFile = "raw_duplicate_ingredients.txt"; + + // Get all PNG files + const files = fs + .readdirSync(imagesFolder) + .filter((file) => file.endsWith(".png")) + .sort((a, b) => { + const numA = parseInt(a.replace(".png", "")); + const numB = parseInt(b.replace(".png", "")); + return numA - numB; + }); + + console.log(`Found ${files.length} images to process`); + + // Clear the output file + fs.writeFileSync(outputFile, ""); + + for (let i = 0; i < files.length; i++) { + const file = files[i]; + const imagePath = path.join(imagesFolder, file); + + console.log(`Processing ${file} (${i + 1}/${files.length})...`); + + try { + const ingredients = await extractIngredients(imagePath); + const ingredientsLine = ingredients.join(", "); + + // Append to file + fs.appendFileSync(outputFile, ingredientsLine + "\n"); + console.log(`✓ ${file}: ${ingredients.length} ingredients found`); + } catch (error) { + console.error(`✗ Error processing ${file}:`, error.message); + fs.appendFileSync(outputFile, `ERROR: ${file}\n`); + } + + // Delay between requests + if (i < files.length - 1) { + const delayTime = 1000 + Math.random() * 1000; + console.log(`Waiting ${(delayTime / 1000).toFixed(2)}s...`); + await delay(delayTime); + } + } + + console.log(`\n✓ All done! Results saved to ${outputFile}`); +} + +processAllImages().catch(console.error); diff --git a/src/parsers/old_ingredient_scraper.js b/src/parsers/old_ingredient_scraper.js new file mode 100644 index 0000000..3c4a633 --- /dev/null +++ b/src/parsers/old_ingredient_scraper.js @@ -0,0 +1,129 @@ +/** + * Scrape toothpaste brand websites for ingredient lists. + * - Fetches HTML from brand URLs + * - Extracts ingredient sections by keywords/patterns + * - Saves results into a timestamped text file + */ + +import https from "https"; +import fs from "fs"; + +// Brand configurations (URLs, selectors, keywords) +const BRAND_CONFIGS = { + colgate: { + url: "", + selectors: [ + "ingredients", + "ingredient-list", + "product-ingredients", + "accordion", + ], + keywords: ["ingredients", "active ingredient", "inactive ingredient"], + }, + oralb: { + url: "", + selectors: ["ingredients", "product-details"], + keywords: ["ingredients"], + }, + marvis: { + url: "", + selectors: ["ingredients", "composition"], + keywords: ["ingredients", "composition"], + }, +}; + +// Choose which brand to scrape +const CURRENT_BRAND = "colgate"; + +// Fetch HTML +function fetchPage(url) { + return new Promise((resolve, reject) => { + https + .get(url, (res) => { + let data = ""; + res.on("data", (chunk) => (data += chunk)); + res.on("end", () => resolve(data)); + }) + .on("error", (err) => reject(err)); + }); +} + +// Extract ingredient sections +function extractIngredients(html, config) { + const ingredients = []; + + // Search by keyword matches + config.keywords.forEach((keyword) => { + const regex = new RegExp(`${keyword}[^a-z]*:?\\s*([^<]+)`, "gi"); + for (const match of html.matchAll(regex)) { + if (match[1]) { + const text = match[1] + .replace(/<[^>]+>/g, "") + .replace(/&[^;]+;/g, " ") + .trim(); + if (text.length > 10) ingredients.push(text); + } + } + }); + + // Search by common HTML patterns + const patterns = [ + /(?:active|inactive)?\s*ingredients?[:\s]+([^<]{20,})/gi, + /]*>[^<]*ingredients?[^<]*:([^<]+)<\/p>/gi, + ]; + patterns.forEach((pattern) => { + for (const match of html.matchAll(pattern)) { + if (match[1]) { + const text = match[1] + .replace(/<[^>]+>/g, "") + .replace(/&[^;]+;/g, " ") + .trim(); + if (text.length > 10) ingredients.push(text); + } + } + }); + + return [...new Set(ingredients)]; // Remove duplicates +} + +// Write to file +function writeToFile(ingredients, brand) { + const timestamp = new Date().toISOString().split("T")[0]; + const filename = `ingredients_${brand}_${timestamp}.txt`; + + let content = `Ingredients for ${brand.toUpperCase()}\n`; + content += `Scraped on: ${new Date().toISOString()}\n`; + content += `URL: ${BRAND_CONFIGS[brand].url}\n`; + content += `${"=".repeat(50)}\n\n`; + + ingredients.forEach( + (ingredient, i) => (content += `${i + 1}. ${ingredient}\n\n`), + ); + fs.writeFileSync(filename, content, "utf8"); + + console.log(`✓ Ingredients written to ${filename}`); +} + +// scraping +async function scrapeIngredients(brand) { + const config = BRAND_CONFIGS[brand]; + if (!config.url) + return console.error(`Error: No URL configured for brand "${brand}"`); + + console.log(`Scraping ${brand}...`); + try { + const html = await fetchPage(config.url); + const ingredients = extractIngredients(html, config); + + if (ingredients.length === 0) { + console.warn("⚠ No ingredients found. Saving HTML for review..."); + fs.writeFileSync(`debug_${brand}.html`, html, "utf8"); + } else { + writeToFile(ingredients, brand); + } + } catch (err) { + console.error("Error scraping page:", err.message); + } +} + +// scrapeIngredients(CURRENT_BRAND); diff --git a/src/parsers/processed_ingredients.json b/src/parsers/processed_ingredients.json new file mode 100644 index 0000000..da1e33e --- /dev/null +++ b/src/parsers/processed_ingredients.json @@ -0,0 +1,2297 @@ +[ + { + "name": "Sodium Fluoride", + "alternative_names": "Sodium monofluoride, Natriumfluorid", + "category": "Anticaries Agent", + "benefits": "Cavity prevention, enamel remineralization, plaque inhibition", + "risks": "Acute toxicity if swallowed (H301), gastrointestinal irritation (nausea, vomiting) if ingested in significant amounts, potential for dental fluorosis with excessive chronic ingestion during tooth development, causes serious eye irritation (H319). Concerns for children under 6 due to swallowing risk.", + "evidence_level": "High", + "labeling_echa": "H301 (Toxic if swallowed), H319 (Causes serious eye irritation)", + "safety_score": 5, + "regulatory_notes": "EU Cosmetics Regulation (CosIng) limits maximum concentration in oral hygiene products (dental care products) to 0.15% (calculated as F). For children up to 6 years, the amount of toothpaste should not exceed a pea-sized amount, and consultation with a dentist or doctor is advised if intake of fluoride from other sources is known. Products must state 'Contains Fluoride' in the ingredient list.", + "link_echa": "https://echa.europa.eu/substance-information/-/substanceinfo/100.029.742", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37869", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7681-49-4", + "link_other": "" + }, + { + "name": "Sorbitol", + "alternative_names": "D-Glucitol, Glucitol", + "category": "Humectant", + "benefits": "Acts as a humectant to prevent toothpaste from drying out and maintain consistency, Provides sweetness without contributing to tooth decay (non-cariogenic), Functions as a bulking agent to contribute to toothpaste texture", + "risks": "No significant risks documented at typical use concentrations. Excessive ingestion may lead to transient gastrointestinal distress.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "Maximum allowed concentration: 50% when used as a humectant in finished products, and 99% when used as a sweetener in oral hygiene products (EU CosIng). Generally Recognized As Safe (GRAS) by the FDA.", + "link_echa": "https://chem.echa.europa.eu/100.000.056/overview?searchText=50-70-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38191", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/50-70-4", + "link_other": "" + }, + { + "name": "Hydrated silica", + "alternative_names": "Silicic acid, hydrated", + "category": "Abrasive", + "benefits": "Cleans teeth, Removes dental plaque, Polishes tooth enamel, Removes surface stains", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.130.425/overview?searchText=10279-57-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/76428", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/10279-57-9", + "link_other": "" + }, + { + "name": "Polyethylene glycol dodecyl ether", + "alternative_names": "PEG dodecyl ether, Brij 35", + "category": "Surfactant", + "benefits": "Aids in effective cleaning by reducing surface tension and facilitating plaque removal, Promotes foaming action, enhancing spreadability and user experience, Functions as an emulsifier and solubilizer, maintaining formulation stability and uniform ingredient distribution", + "risks": "Harmful if swallowed (H302), potential for oral mucosa irritation (H315 - causes skin irritation), and causes serious eye damage (H318). Ingestion is a significant concern for toothpaste formulations, particularly for vulnerable populations like children.", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H315 (Causes skin irritation), H318 (Causes serious eye damage), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 5, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.027.145/overview?searchText=6790-09-6", + "link_cosIng": "", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/6790-09-6", + "link_other": "" + }, + { + "name": "Sodium Lauryl Sulfate", + "alternative_names": "Sodium Dodecyl Sulfate, SDS", + "category": "Surfactant", + "benefits": "Creates foam for perceived cleaning and ingredient distribution, aids in dispersing ingredients, helps emulsify and remove food particles and debris", + "risks": "Potential for oral mucosa irritation, can exacerbate aphthous ulcers (canker sores) in susceptible individuals, skin and serious eye irritation if direct contact, harmful if swallowed in large amounts", + "evidence_level": "High", + "labeling_echa": "H318 (Causes serious eye damage.), H315 (Causes skin irritation.), H412 (Harmful to aquatic life with long lasting effects.)", + "safety_score": 5, + "regulatory_notes": "Conditions of use and warnings which must be printed on the label: Rinse mouth thoroughly after use. Contains Sodium Lauryl Sulfate (as per CosIng)", + "link_echa": "https://chem.echa.europa.eu/100.005.263/overview?searchText=151-21-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37946", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/151-21-3", + "link_other": "" + }, + { + "name": "Cellulose Gum", + "alternative_names": "Carboxymethylcellulose sodium, CMC", + "category": "Thickener", + "benefits": "Provides viscosity and desired texture, Acts as a binding agent to prevent ingredient separation, Enhances product stability and mouthfeel", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.120.377/overview?searchText=9000-11-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/75394", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9000-11-7", + "link_other": "" + }, + { + "name": "potassium hydroxide", + "alternative_names": "Caustic Potash, Potassium hydrate", + "category": "pH Adjuster", + "benefits": "Maintains optimal pH for toothpaste stability, Ensures optimal activity and efficacy of other active ingredients, Prevents product from becoming excessively acidic, protecting enamel from potential erosion", + "risks": "Harmful if swallowed (H302), potential for oral irritation or severe burns if concentration exceeds regulatory limits or product pH is too high (H314), particularly concerning for children due to swallowing risk", + "evidence_level": "High", + "labeling_echa": "H314 (Causes severe skin burns and eye damage), H302 (Harmful if swallowed)", + "safety_score": 4, + "regulatory_notes": "EU Cosmetics Regulation (as per CosIng): Maximum 0.5% in other products as a pH adjuster (calculated as free base). The pH of the finished product must not exceed 11. Prohibited for use in spray products.", + "link_echa": "https://chem.echa.europa.eu/100.013.802/overview?searchText=1310-58-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36981", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1310-58-3", + "link_other": "" + }, + { + "name": "Tetrasodium pyrophosphate", + "alternative_names": "Sodium pyrophosphate, Tetrasodium diphosphate", + "category": "Tartar Control Agent", + "benefits": "Tartar control (inhibits calculus formation), Stain prevention (reduces new stain accumulation), pH buffering", + "risks": "Causes serious eye irritation (H319). Potential for oral irritation in sensitive individuals at high concentrations, though generally safe at typical toothpaste levels. Ingestion of small amounts from toothpaste is not considered harmful.", + "evidence_level": "High", + "labeling_echa": "H319 (Causes serious eye irritation)", + "safety_score": 8, + "regulatory_notes": "Restricted to a maximum concentration of 10% in non-spray cosmetic products (EU Cosmetics Regulation, as per CosIng entry).", + "link_echa": "https://chem.echa.europa.eu/100.028.880/overview?searchText=7722-88-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38571", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7722-88-5", + "link_other": "" + }, + { + "name": "Phosphoric Acid", + "alternative_names": "Orthophosphoric acid", + "category": "pH Adjuster", + "benefits": "pH Adjustment, Stain Removal/Whitening, Tartar Control", + "risks": "Oral irritation/chemical burns, potential for enamel erosion with prolonged low pH exposure, severe digestive tract irritation if ingested, not recommended for children.", + "evidence_level": "High", + "labeling_echa": "H290 (May be corrosive to metals), H314 (Causes severe skin burns and eye damage)", + "safety_score": 5, + "regulatory_notes": "Maximum concentration in oral hygiene products: 0.5% (with a minimum pH of 3.0). Not for use in products for children under 3 years of age, except in toothpastes. Must be labelled with the warning: 'Not recommended for children'.", + "link_echa": "https://chem.echa.europa.eu/100.118.962/overview?searchText=7664-38-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36546", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7664-38-2", + "link_other": "" + }, + { + "name": "Cocamidopropyl Betaine", + "alternative_names": "", + "category": "Surfactant", + "benefits": "Provides foaming action, Aids in cleansing and debris removal, Acts as an emulsifier, Improves mildness of surfactant systems", + "risks": "Potential for oral irritation and allergic reactions (contact dermatitis) in sensitive individuals, especially at higher concentrations. May cause serious eye damage if direct contact occurs.", + "evidence_level": "High", + "labeling_echa": "H318 (Causes serious eye damage), H315 (Causes skin irritation), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 7, + "regulatory_notes": "Maximum concentration 10.0 % (calculated as active matter) in rinse-off products (e.g., toothpaste). Required labeling 'Contains cocamidopropyl betaine' when concentration > 3.0 % in rinse-off products. (EU Cosmetics Regulation, Annex III, 49)", + "link_echa": "https://chem.echa.europa.eu/100.213.335/overview?searchText=61789-40-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/75231", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/61789-40-0", + "link_other": "" + }, + { + "name": "Sodium saccharin", + "alternative_names": "Saccharin, sodium salt, Soluble saccharin", + "category": "Sweetener", + "benefits": "Provides intense sweetness, non-cariogenic (does not promote tooth decay), masks unpleasant tastes of other ingredients", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified in the provided links for oral care products beyond general safety assessments. Approved by FDA as an artificial sweetener.", + "link_echa": "https://chem.echa.europa.eu/100.004.443/overview?searchText=128-44-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80014", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/128-44-9", + "link_other": "" + }, + { + "name": "Benzyl Alcohol", + "alternative_names": "Phenylmethanol, Benzenemethanol", + "category": "Preservative", + "benefits": "Extends product shelf-life by preventing microbial growth, acts as an antimicrobial agent, functions as a solvent for other ingredients.", + "risks": "Harmful if swallowed (H302), may cause allergic skin reactions (H317) on contact, potential for oral mucosal irritation at higher concentrations, moderate acute oral toxicity if significant amounts are ingested.", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H332 (Harmful if inhaled), H319 (Causes serious eye irritation), H317 (May cause an allergic skin reaction)", + "safety_score": 4, + "regulatory_notes": "Maximum concentration in ready for use cosmetic preparations is 1.0% when used as a preservative (EU Cosmetics Regulation Annex V, point 34). Note: The CosIng database also contains a conflicting statement under 'Other conditions of use' stating 'For oral products: No use allowed in oral products'.", + "link_echa": "https://chem.echa.europa.eu/100.002.600/overview?searchText=100-51-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32153", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/100-51-6", + "link_other": "" + }, + { + "name": "Mica", + "alternative_names": "CI 77019", + "category": "Colorant", + "benefits": "Aesthetic enhancement (provides shimmer/sparkle), Opacifying agent (improves product appearance), Mild polishing agent (contributes to surface cleaning)", + "risks": "No significant risks documented at typical use concentrations; inhalation of fine dust is a known respiratory hazard but not relevant for toothpaste use.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified under EU Cosmetic Regulation.", + "link_echa": "https://chem.echa.europa.eu/100.123.963/overview?searchText=12001-26-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35360", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/12001-26-2", + "link_other": "" + }, + { + "name": "Acid Blue 9", + "alternative_names": "Brilliant Blue FCF, Blue 1", + "category": "Colorant", + "benefits": "Provides aesthetic color to toothpaste for consumer appeal", + "risks": "No significant risks documented at typical use concentrations. PubChem notes general potential for serious eye irritation (H319). Oral toxicity in rats is low (LD50 > 2000 mg/kg).", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified within the provided ECHA and PubChem data regarding oral care product concentration limits or required warnings. ECHA's harmonised classification states the substance is not classified as hazardous.", + "link_echa": "https://chem.echa.europa.eu/100.513.043/overview?searchText=3844-45-9", + "link_cosIng": "", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/3844-45-9", + "link_other": "" + }, + { + "name": "Titanium Dioxide", + "alternative_names": "Titania, Titanium(IV) oxide", + "category": "Colorant", + "benefits": "Provides white color and opacity to toothpaste formula, enhances aesthetic appeal", + "risks": "Suspected of causing cancer by inhalation (Carc. 2, H351) for certain powder forms; causes damage to lungs through prolonged or repeated exposure by inhalation (STOT RE 1, H372). While acute oral toxicity is low and absorption is poor, the suspected carcinogen classification for certain forms warrants caution for products that may be ingested.", + "evidence_level": "High", + "labeling_echa": "H351 (Suspected of causing cancer ), H372 (Causes damage to organs (lungs) through prolonged or repeated exposure )", + "safety_score": 6, + "regulatory_notes": "Prohibited in cosmetic products for application that can lead to exposure of the end-user's lungs by inhalation. Classified as Carc. 2 (suspected of causing cancer by inhalation) by Commission Regulation (EU) 2020/217 for powder forms containing 1% or more of particles with diameter ≤ 10 µm. Permitted as a colorant pigment under Article 2(1)(a) of Regulation (EC) No 1223/2009 for other cosmetic uses.", + "link_echa": "https://chem.echa.europa.eu/100.033.327/overview?searchText=13463-67-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/97726", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/13463-67-7", + "link_other": "" + }, + { + "name": "Glycerin", + "alternative_names": "Glycerol", + "category": "Humectant", + "benefits": "Prevents toothpaste from drying out, improves texture and mouthfeel, acts as a solvent for other ingredients, provides mild sweetness without contributing to cavities", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.000.263/overview?searchText=56-81-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34040", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/56-81-5", + "link_other": "" + }, + { + "name": "Sodium Bicarbonate", + "alternative_names": "Baking soda, Monosodium carbonate", + "category": "Abrasive", + "benefits": "Mild abrasive for stain removal, Neutralizes oral acids, Helps remove plaque, Freshens breath", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.005.122/overview?searchText=144-55-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37736", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/144-55-8", + "link_other": "" + }, + { + "name": "Sodium hydroxide", + "alternative_names": "Caustic soda, Lye", + "category": "pH Adjuster", + "benefits": "Controls and adjusts product pH for formulation stability, optimizes efficacy of other active ingredients by maintaining appropriate pH, contributes to microbial stability within the product by maintaining an unfavorable pH for certain microorganisms", + "risks": "Highly corrosive, causes severe skin burns and eye damage. Potential for irritation and tissue damage if used at high concentrations or if product pH is not properly controlled. Harmful if swallowed, can cause severe internal burns.", + "evidence_level": "High", + "labeling_echa": "H314 (Causes severe skin burns and eye damage), H290 (May be corrosive to metals)", + "safety_score": 5, + "regulatory_notes": "Restricted in cosmetic products by EU Cosmetics Regulation (EC) No 1223/2009, Annex III, entry 15a. For 'Other uses' (which includes toothpaste), the final product pH must be less than 11.", + "link_echa": "https://chem.echa.europa.eu/100.013.805/overview?searchText=1310-73-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37890", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1310-73-2", + "link_other": "" + }, + { + "name": "Xanthan Gum", + "alternative_names": "Corn sugar gum", + "category": "Thickener", + "benefits": "Improves product consistency and texture, Binds ingredients to prevent separation, Stabilizes emulsion and suspension in formulations", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified. Generally recognized as safe (GRAS) by FDA for food applications, implying high safety for incidental ingestion in oral care products.", + "link_echa": "https://chem.echa.europa.eu/100.031.255/overview?searchText=11138-66-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80699", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/11138-66-2", + "link_other": "" + }, + { + "name": "Stannous Fluoride", + "alternative_names": "Tin difluoride, Tin(II) fluoride", + "category": "Anticaries Agent", + "benefits": "Prevents dental caries, Relieves dental sensitivity, Reduces plaque and gingivitis", + "risks": "Harmful if swallowed, particularly for children; potential for temporary tooth staining with prolonged use", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H318 (Causes serious eye damage), H411 (Toxic to aquatic life with long lasting effects)", + "safety_score": 7, + "regulatory_notes": "Maximum 0.15 % in cosmetic products (calculated as F). Prohibited in aerosol dispensers.", + "link_echa": "https://chem.echa.europa.eu/100.029.090/overview?searchText=7783-47-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38231", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7783-47-3", + "link_other": "" + }, + { + "name": "Potassium Nitrate", + "alternative_names": "Saltpetre, Niter", + "category": "Desensitizing Agent", + "benefits": "Relieves tooth sensitivity, Blocks nerve pain transmission in dentinal tubules, Reduces discomfort from hot and cold stimuli", + "risks": "Harmful if swallowed (H302) at higher concentrations or if significant amounts are ingested. Potential for irritation to mucous membranes with prolonged or excessive contact.", + "evidence_level": "High", + "labeling_echa": "H272 (May intensify fire; oxidiser), H302 (Harmful if swallowed)", + "safety_score": 8, + "regulatory_notes": "Maximum concentration of 5% in ready-to-use oral products. If oral products contain more than 10% of the substance, warnings must be displayed.", + "link_echa": "https://chem.echa.europa.eu/100.028.926/overview?searchText=7757-79-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37002", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7757-79-1", + "link_other": "" + }, + { + "name": "Yellow 10", + "alternative_names": "CI 47005, Quinoline Yellow", + "category": "Colorant", + "benefits": "Aesthetic enhancement for product appeal, Masking of undesirable natural color of other ingredients, Product differentiation", + "risks": "No significant risks documented at typical use concentrations specific to oral care in the provided sources. Cosmetic dyes can rarely cause allergic reactions in sensitive individuals.", + "evidence_level": "Limited", + "labeling_echa": "None identified", + "safety_score": 8, + "regulatory_notes": "No specific restrictions identified for oral care products in the provided sources. (Note: CosIng lists restrictions for hair dye products: max 0.5% and professional use only).", + "link_echa": "https://chem.echa.europa.eu/100.116.526/overview?searchText=8004-92-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/100075", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/8004-92-0", + "link_other": "" + }, + { + "name": "Xylitol", + "alternative_names": "D-Xylitol, Wood sugar", + "category": "Anticaries Agent", + "benefits": "Reduces dental caries, Acts as a non-cariogenic sweetener, May alleviate dry mouth symptoms", + "risks": "May cause gastrointestinal upset (diarrhea) if ingested in large quantities", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "Generally recognized as safe (GRAS) by the FDA; no specific restrictions identified for oral care products in EU regulations", + "link_echa": "https://chem.echa.europa.eu/100.001.626/overview?searchText=87-99-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38920", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/87-99-0", + "link_other": "" + }, + { + "name": "Sodium Lauroyl Sarcosinate", + "alternative_names": "N-Lauroylsarcosine Sodium Salt, Sarcosyl NL", + "category": "Surfactant", + "benefits": "Effective cleansing agent, Provides foaming action, Contributes to antiplaque effects, May help in caries prevention", + "risks": "Harmful if swallowed; potential for irritation (e.g., eye damage) in concentrated forms", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H318 (Causes serious eye damage), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 6, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.004.801/overview?searchText=137-16-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37941", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/137-16-6", + "link_other": "" + }, + { + "name": "CI 47005", + "alternative_names": "Quinoline Yellow WS, D&C Yellow No. 10", + "category": "Colorant", + "benefits": "None identified for oral health. Serves as an aesthetic colorant for the product.", + "risks": "No significant risks documented at typical use concentrations for oral/dental applications. Generally considered safe at typical cosmetic use levels.", + "evidence_level": "High", + "labeling_echa": "None identified (No harmonised classification and labelling)", + "safety_score": 9, + "regulatory_notes": "Permitted in all cosmetic products under EU Cosmetics Regulation (EC) No 1223/2009 (Annex IV, Entry 104), including those intended for contact with mucous membranes (e.g., toothpaste).", + "link_echa": "https://chem.echa.europa.eu/100.116.526/overview?searchText=8004-92-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/100075", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/8004-92-0", + "link_other": "" + }, + { + "name": "CI 42051", + "alternative_names": "Patent Blue V, Sodium (alpha-(4-sulphonatophenyl)-alpha-(4-sulphonato-4-cyclohexadien-1-ylidene)-o-toluenesulphonato)", + "category": "Colorant", + "benefits": "Enhances visual appeal of toothpaste, Provides a blue color to the product", + "risks": "No significant risks documented at typical use concentrations; however, some self-classifications indicate potential for skin/eye irritation, which may be relevant for sensitive individuals.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 8, + "regulatory_notes": "Approved as a colorant for cosmetic products in the EU (CosIng). No specific restrictions identified for oral care products in the provided data.", + "link_echa": "https://chem.echa.europa.eu/100.020.522/overview?searchText=3536-49-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32753", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/3536-49-0", + "link_other": "" + }, + { + "name": "LIMONENE", + "alternative_names": "D-Limonene, (R)-p-mentha-1,8-diene", + "category": "Flavoring Agent", + "benefits": "Provides a pleasant citrus flavor and aroma, Contributes to a refreshing sensation, Acts as a solvent for other ingredients", + "risks": "Potential for oral irritation and allergic contact dermatitis; May cause an allergic skin reaction; Aspiration hazard if significant amounts are swallowed and enters airways; Can cause gastrointestinal upset if ingested in large quantities", + "evidence_level": "High", + "labeling_echa": "H226 (Flammable liquid and vapour), H304 (May be fatal if swallowed and enters airways), H315 (Causes skin irritation), H317 (May cause an allergic skin reaction), H411 (Toxic to aquatic life with long lasting effects)", + "safety_score": 5, + "regulatory_notes": "EU Cosmetics Regulation 1223/2009, Annex III, Entry 88: Must be indicated in the list of ingredients when its concentration exceeds 0.001 % in leave-on products or 0.01 % in rinse-off products (e.g., toothpaste, mouthwash).", + "link_echa": "https://chem.echa.europa.eu/100.025.284/overview?searchText=5989-27-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/87624", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/5989-27-5", + "link_other": "" + }, + { + "name": "sodium benzoate", + "alternative_names": "Benzoic acid sodium salt, Benzoate of soda", + "category": "Preservative", + "benefits": "Preserves toothpaste formula by inhibiting microbial growth, Extends product shelf life, Ensures product safety and maintains efficacy over time", + "risks": "Potential for irritation of oral mucous membranes, Possible allergic reactions especially in individuals with asthma or aspirin sensitivity, Concerns about toxicity if swallowed in very high concentrations (though unlikely at typical use levels)", + "evidence_level": "High", + "labeling_echa": "H319 (Causes serious eye irritation)", + "safety_score": 8, + "regulatory_notes": "Maximum concentration of 2.5% (expressed as acid) in cosmetic products, as per EU Cosmetics Regulation Annex V. Generally recognized as safe for use as a food additive in specified concentrations.", + "link_echa": "https://chem.echa.europa.eu/100.007.760/overview?searchText=532-32-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37735", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/532-32-1", + "link_other": "" + }, + { + "name": "Dicalcium Phosphate", + "alternative_names": "Calcium hydrogen phosphate, Dibasic calcium phosphate", + "category": "Abrasive", + "benefits": "Aids in plaque removal, helps remove surface stains, contributes to toothpaste consistency, provides opaque appearance", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified for oral care products; generally recognized as safe (GRAS) by FDA", + "link_echa": "https://chem.echa.europa.eu/100.028.933/overview?searchText=7757-93-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/75666", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7757-93-9", + "link_other": "" + }, + { + "name": "Hydroxyapatite", + "alternative_names": "Hydroxylapatite", + "category": "Anticaries Agent", + "benefits": "Abrasive action for cleaning teeth, Supports enamel remineralization, Contributes to anticaries action", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.013.769/overview?searchText=1306-06-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34479", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1306-06-5", + "link_other": "" + }, + { + "name": "SILICA", + "alternative_names": "Silicon dioxide", + "category": "Abrasive", + "benefits": "Plaque removal, Stain removal and whitening, Polishing teeth, Thickening agent for product consistency", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.171.064/overview?searchText=7631-86-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/78845", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7631-86-9", + "link_other": "" + }, + { + "name": "PEG-8", + "alternative_names": "Polyethylene Glycol, Poly(ethylene glycol)", + "category": "Humectant", + "benefits": "Maintains toothpaste consistency and prevents drying, acts as a binder for product stability, aids in ingredient dispersion for uniform product texture", + "risks": "Potential for mild irritation in very sensitive individuals; concerns regarding 1,4-dioxane contamination are manufacturing-dependent and not inherent to PEG-8 itself", + "evidence_level": "Moderate", + "labeling_echa": "None identified", + "safety_score": 8, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/77303", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/25322-68-3", + "link_other": "" + }, + { + "name": "trimagnesium phosphate", + "alternative_names": "Magnesium phosphate tribasic, Magnesium orthophosphate", + "category": "Abrasive", + "benefits": "Abrasive cleaning, Aids in plaque removal, Contributes to stain removal", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "Moderate", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.028.931/overview?searchText=7757-87-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38739", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7757-87-1", + "link_other": "" + }, + { + "name": "Hydrolyzed Conchiolin Protein", + "alternative_names": "", + "category": "Binding Agent", + "benefits": "No specific oral care benefits documented in provided links", + "risks": "No significant risks documented at typical use concentrations based on provided information", + "evidence_level": "Limited", + "labeling_echa": "None identified", + "safety_score": 8, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/56554", + "link_pubchem": "", + "link_other": "" + }, + { + "name": "Glycyrrhetinic acid", + "alternative_names": "Enoxolone, Glycyrrhetic acid", + "category": "Antimicrobial", + "benefits": "Anti-inflammatory (reduces gum inflammation), Antimicrobial/Antiviral (helps fight oral pathogens), Antioxidant (protects oral tissues)", + "risks": "No significant risks documented at typical use concentrations; systemic effects (fluid retention, increased blood pressure) noted only with high doses or prolonged use, which are unlikely in oral care applications", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.006.769/overview?searchText=471-53-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34152", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/471-53-4", + "link_other": "" + }, + { + "name": "Cetylpyridinium Chloride", + "alternative_names": "CPC, 1-Hexadecylpyridinium chloride", + "category": "Antimicrobial", + "benefits": "Antiseptic activity, Inhibits plaque accumulation, Reduces gingivitis, Combats bad breath", + "risks": "Harmful if swallowed (H302), not recommended for children under 3 years of age, not recommended for children under 6 years for mouthwash containing >0.05% CPC", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H314 (Causes severe skin burns and eye damage), H400 (Very toxic to aquatic life), H411 (Toxic to aquatic life with long lasting effects)", + "safety_score": 5, + "regulatory_notes": "Maximum allowed concentration in oral care products (toothpaste, mouthwash) is 0.1%. Not to be used in products for children under 3 years of age. For mouthwash containing >0.05% CPC, 'Not to be used for children under 6 years of age' warning is required. 'Keep out of reach of children' warning for oral care products for children under 6 containing >0.05% CPC. (EU Cosmetics Regulation)", + "link_echa": "https://chem.echa.europa.eu/100.004.177/overview?searchText=123-03-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32626", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/123-03-5", + "link_other": "" + }, + { + "name": "LAURYL DIETHYLENEDIAMINOGLYCINE HCL", + "alternative_names": "Lauryl diethylenediaminoglycine hydrochloride", + "category": "Antimicrobial", + "benefits": "Antimicrobial action to reduce oral bacteria, Helps control plaque development, Supports general oral hygiene", + "risks": "Harmful if swallowed (H302), Potential for irritation or severe burns to oral tissues (H314, H318) if concentration is not strictly controlled, Not recommended for children under 3 years old", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H314 (Causes severe skin burns and eye damage), H318 (Causes serious eye damage), H400 (Very toxic to aquatic life), H410 (Very toxic to aquatic life with long lasting effects)", + "safety_score": 4, + "regulatory_notes": "Maximum concentration of 0.1% in leave-on products (including oral care products). Maximum concentration of 0.2% in rinse-off products. Should not be used for children under 3 years old.", + "link_echa": "https://chem.echa.europa.eu/100.038.253/overview?searchText=18205-85-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/56963", + "link_pubchem": "", + "link_other": "" + }, + { + "name": "PVP", + "alternative_names": "Polyvinylpyrrolidone, Povidone", + "category": "Binding Agent", + "benefits": "Acts as a binding agent, ensuring uniform distribution of ingredients; Provides film-forming properties, which can help reduce stain adhesion to tooth surfaces; Enhances formulation stability and consistency of oral care products", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.184.844/overview?searchText=9003-39-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37364", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9003-39-8", + "link_other": "" + }, + { + "name": "Butylene Glycol", + "alternative_names": "1,3-Butanediol, 1,3-Dihydroxybutane", + "category": "Humectant", + "benefits": "Prevents toothpaste dehydration, Acts as a solvent for other ingredients, Improves product texture and consistency", + "risks": "Harmful if swallowed in significant quantities (H302), potential for mild irritation in sensitive individuals, central nervous system depression if ingested in large amounts", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H319 (Causes serious eye irritation), H315 (Causes skin irritation)", + "safety_score": 8, + "regulatory_notes": "No specific restrictions identified for oral care products", + "link_echa": "https://chem.echa.europa.eu/100.003.209/overview?searchText=107-88-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74756", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/107-88-0", + "link_other": "" + }, + { + "name": "Alcohol", + "alternative_names": "Ethanol, Ethyl Alcohol", + "category": "Antimicrobial", + "benefits": "Antimicrobial/Antiseptic properties, Solvent for other ingredients, Astringent", + "risks": "Potential for oral dryness (xerostomia) and irritation of mucous membranes, can cause burning sensation at higher concentrations, risk of systemic effects if swallowed in large quantities (especially in children).", + "evidence_level": "High", + "labeling_echa": "H225 (Highly flammable liquid and vapour), H319 (Causes serious eye irritation)", + "safety_score": 5, + "regulatory_notes": "Maximum concentration in oral hygiene products (e.g., toothpaste) is restricted to 10% in the EU (CosIng). Not recommended for long-term use at high concentrations due to potential for oral dryness and irritation.", + "link_echa": "https://chem.echa.europa.eu/100.000.526/overview?searchText=64-17-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/31401", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/64-17-5", + "link_other": "" + }, + { + "name": "Pyridoxine Hydrochloride", + "alternative_names": "Pyridoxine HCl, Vitamin B6 Hydrochloride", + "category": "Conditioning Agent", + "benefits": "None specifically for oral care found in provided sources.", + "risks": "Harmful if swallowed (H302), may cause oral mucosa/skin irritation (H315), causes serious eye irritation (H319). Ingestion by children is a concern due to 'Harmful if swallowed' classification.", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H319 (Causes serious eye irritation), H315 (Causes skin irritation), H335 (May cause respiratory irritation)", + "safety_score": 5, + "regulatory_notes": "Under EU Cosmetics Regulation (EC) No 1223/2009, Pyridoxine (and its HCl salt) is restricted for medicinal products. For non-medicinal products (like cosmetics/toothpaste), a maximum daily dose of 40mg is noted, implying a general intake limitation.", + "link_echa": "https://chem.echa.europa.eu/100.000.351/overview?searchText=58-56-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37388", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/58-56-0", + "link_other": "" + }, + { + "name": "Camellia Sinensis Leaf Extract", + "alternative_names": "Green Tea Extract, Tea Leaf Extract", + "category": "Antimicrobial", + "benefits": "Antimicrobial properties (reduces plaque bacteria), Anticaries effect (inhibits S. mutans), Anti-inflammatory (supports gum health), Antioxidant (protects oral tissues)", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "Moderate", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.141.452/overview?searchText=84650-60-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/55224", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84650-60-2", + "link_other": "" + }, + { + "name": "Chamomilla Recutita (Matricaria) Flower Extract", + "alternative_names": "Matricaria chamomilla extract, German Chamomile Extract", + "category": "Antimicrobial", + "benefits": "Anti-inflammatory, Antioxidant, Antimicrobial", + "risks": "Potential for allergic reactions (sensitization) in the oral cavity, suspected endocrine disruptor, under ECHA CoRAP evaluation", + "evidence_level": "Moderate", + "labeling_echa": "None identified", + "safety_score": 5, + "regulatory_notes": "Included in ECHA's Community Rolling Action Plan (CoRAP) for evaluation due to suspected risks (skin sensitisation, endocrine disruption). Future regulatory updates for classification and labelling are anticipated.", + "link_echa": "https://chem.echa.europa.eu/100.074.527/overview?searchText=84082-60-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/55295", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84082-60-0", + "link_other": "" + }, + { + "name": "SALVIA OFFICINALIS LEAF EXTRACT", + "alternative_names": "Sage extract, Salvia officinalis, ext.", + "category": "Antimicrobial", + "benefits": "Antimicrobial (reduces oral bacteria and plaque), Antioxidant (protects oral tissues), Astringent (helps tighten gums), Anti-inflammatory (soothes irritated gums)", + "risks": "Potential for oral mucosa irritation, risk of allergic reactions (sensitization) in the oral cavity, harmful if swallowed in significant quantities", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H315 (Causes skin irritation), H317 (May cause an allergic skin reaction), H319 (Causes serious eye irritation), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 7, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.074.545/overview?searchText=84082-79-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80200", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84082-79-1", + "link_other": "" + }, + { + "name": "ALUMINA", + "alternative_names": "Aluminum oxide, Corundum", + "category": "Abrasive", + "benefits": "Plaque and surface stain removal, tooth polishing, mechanical cleaning", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.207.718/overview?searchText=1344-28-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74191", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1344-28-1", + "link_other": "" + }, + { + "name": "PEG-6", + "alternative_names": "Polyethylene Glycol 300", + "category": "Humectant", + "benefits": "Maintains toothpaste moisture and consistency, Contributes to desirable texture and mouthfeel, Aids in solubilizing other ingredients", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "Limited", + "labeling_echa": "None identified", + "safety_score": 8, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/77118", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/25322-68-3", + "link_other": "" + }, + { + "name": "ANISE ALCOHOL", + "alternative_names": "4-Methoxybenzyl alcohol, p-Anisyl alcohol", + "category": "Flavoring Agent", + "benefits": "Imparts a pleasant anise-like flavor/fragrance, Masks unpleasant tastes of other ingredients, Enhances user experience", + "risks": "Harmful if swallowed (H302), potential for skin irritation (H315), may cause allergic skin reactions (H317) in sensitive individuals, especially at higher concentrations", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H312 (Harmful in contact with skin), H315 (Causes skin irritation), H317 (May cause an allergic skin reaction), H319 (Causes serious eye irritation)", + "safety_score": 5, + "regulatory_notes": "EU Cosmetics Regulation (Annex III, entry 86): Must be indicated in the list of ingredients when its concentration exceeds 0.001 % in leave-on products or 0.01 % in rinse-off products (e.g., toothpaste).", + "link_echa": "https://chem.echa.europa.eu/100.002.976/overview?searchText=105-13-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74308", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/105-13-5", + "link_other": "" + }, + { + "name": "Pentasodium triphosphate", + "alternative_names": "Sodium triphosphate, Sodium tripolyphosphate", + "category": "Tartar Control Agent", + "benefits": "Tartar control, Whitening, pH regulation, Anticaries agent", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.028.944/overview?searchText=7758-29-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36486", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7758-29-4", + "link_other": "" + }, + { + "name": "Carbomer", + "alternative_names": "Poly(acrylic acid)", + "category": "Thickener", + "benefits": "Provides desired viscosity and texture to toothpaste, Stabilizes formulation preventing ingredient separation, Ensures uniform dispersion of active ingredients throughout the product, Enhances user experience due to smooth application", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.113.198/overview?searchText=9007-20-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74820", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9007-20-9", + "link_other": "" + }, + { + "name": "Eugenol", + "alternative_names": "4-allyl-2-methoxyphenol, Eugenic acid", + "category": "Flavoring Agent", + "benefits": "Provides a distinct clove-like flavor, Possesses antimicrobial properties, Offers mild analgesic (pain-relieving) effects", + "risks": "May cause allergic skin reactions (sensitization) even at low concentrations, Causes serious eye irritation, Harmful if swallowed; concerns are concentration-dependent", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H317 (May cause an allergic skin reaction), H319 (Causes serious eye irritation)", + "safety_score": 4, + "regulatory_notes": "Subject to concentration restrictions in cosmetic products by EU Cosmetics Regulation (EC) No 1223/2009, Annex III. Maximum allowed concentrations in ready-for-use preparations are 0.001% for leave-on products and 0.01% for rinse-off products. Must be listed in the ingredient list when its concentration exceeds 0.01% in rinse-off products and 0.001% in leave-on products.", + "link_echa": "https://chem.echa.europa.eu/100.002.355/overview?searchText=97-53-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/33910", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/97-53-0", + "link_other": "" + }, + { + "name": "Carrageenan", + "alternative_names": "Irish moss gum, Kappa-Carrageenan", + "category": "Thickener", + "benefits": "Provides desired toothpaste consistency, stabilizes formulations preventing ingredient separation, acts as a binding agent ensuring uniform dispersion of active ingredients, improves mouthfeel and texture.", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.029.556/overview?searchText=9000-07-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/88730", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9000-07-1", + "link_other": "" + }, + { + "name": "Red 30", + "alternative_names": "CI 15865, Lithol Rubin B", + "category": "Colorant", + "benefits": "Provides aesthetic appeal to oral care products", + "risks": "Harmful if swallowed (H302), May cause damage to organs (spleen, kidney) through prolonged or repeated oral exposure (H373), Not recommended for children under 3 years old in cosmetics, Concentration-dependent toxicity (maximum 3% in toothpaste)", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H332 (Harmful if inhaled), H373 (May cause damage to organs (spleen, kidney) through prolonged or repeated exposure (oral))", + "safety_score": 4, + "regulatory_notes": "EU Cosmetics Regulation (Annex IV): Maximum concentration of 3% in toothpaste. Not allowed in products for children under 3 years old. Subject to ongoing evaluation under ECHA's Community Rolling Action Plan (CoRAP).", + "link_echa": "https://chem.echa.europa.eu/100.024.998/overview?searchText=5858-81-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/93730", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/5858-81-1", + "link_other": "" + }, + { + "name": "Allantoin", + "alternative_names": "5-Ureidohydantoin", + "category": "Soothing Agent", + "benefits": "Soothes gums and oral mucosa, promotes healing of oral tissues, protects oral tissues, provides hydration", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.002.358/overview?searchText=97-59-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/31411", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/97-59-6", + "link_other": "" + }, + { + "name": "Panthenol", + "alternative_names": "Dexpanthenol, Provitamin B5", + "category": "Conditioning Agent", + "benefits": "Soothes irritated oral mucosa, Promotes healing of minor oral lesions, Maintains oral tissue hydration", + "risks": "No significant risks documented at typical use concentrations, although rare allergic reactions may occur", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.001.208/overview?searchText=81-13-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35839", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/81-13-0", + "link_other": "" + }, + { + "name": "Citric acid", + "alternative_names": "2-hydroxypropane-1,2,3-tricarboxylic acid, Anhydrous citric acid", + "category": "pH Adjuster", + "benefits": "pH stabilization, extrinsic stain removal, antimicrobial properties, flavoring agent", + "risks": "Potential for enamel erosion at high concentrations or prolonged exposure, mild oral irritation in sensitive individuals, harmful if swallowed in concentrated forms (H302 classification)", + "evidence_level": "High", + "labeling_echa": "H319 (Causes serious eye irritation), H302 (Harmful if swallowed), H335 (May cause respiratory irritation)", + "safety_score": 7, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.205.812/overview?searchText=77-92-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32858", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/77-92-9", + "link_other": "" + }, + { + "name": "Sodium Chloride", + "alternative_names": "Common salt, Table salt", + "category": "Antimicrobial", + "benefits": "Mild antiseptic/antimicrobial action against oral bacteria, Reduces gum inflammation (gingivitis) through osmotic effect, Aids in plaque control", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.028.726/overview?searchText=sodium%20chloride", + "link_cosIng": "", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7647-14-5", + "link_other": "" + }, + { + "name": "STEVIA REBAUDIANA EXTRACT", + "alternative_names": "Stevia extract, Extract of Stevia rebaudiana", + "category": "Sweetener", + "benefits": "Improves product palatability (masking agent)", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.085.803/overview?searchText=91722-21-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/58821", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/91722-21-3", + "link_other": "" + }, + { + "name": "Maltodextrin", + "alternative_names": "", + "category": "Binding Agent", + "benefits": "Aids in product consistency and stability, contributes to product palatability as a mild sweetener, functions as a bulking agent for formulation", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "Not restricted in cosmetic products according to CosIng", + "link_echa": "https://chem.echa.europa.eu/100.029.934/overview?searchText=9050-36-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35142", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9050-36-6", + "link_other": "" + }, + { + "name": "Potassium sorbate", + "alternative_names": "Sorbic acid potassium salt", + "category": "Preservative", + "benefits": "Preserves product integrity, Inhibits microbial growth (bacteria, molds, yeasts), Extends shelf-life of toothpaste", + "risks": "Potential for skin and eye irritation, may cause allergic reactions, high concentrations may be irritating to oral mucosa", + "evidence_level": "High", + "labeling_echa": "H319 (Causes serious eye irritation)", + "safety_score": 8, + "regulatory_notes": "Maximum concentration in cosmetic products 0.6% (calculated as sorbic acid) as per EU Cosmetics Regulation Annex III/1", + "link_echa": "https://chem.echa.europa.eu/100.205.816/overview?searchText=24634-61-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37025", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/24634-61-5", + "link_other": "" + }, + { + "name": "Sorbic Acid", + "alternative_names": "2,4-Hexadienoic acid, (2E,4E)-2,4-Hexadienoic acid", + "category": "Preservative", + "benefits": "Inhibits microbial growth (molds, yeasts, some bacteria) in toothpaste formulation, Extends toothpaste shelf life and maintains product stability, Ensures product integrity and safety by preventing spoilage", + "risks": "Can cause serious eye irritation, Potential for local irritation in the oral cavity (especially at pH below 3.5), Possible allergic reactions, Gastrointestinal upset if large amounts are ingested", + "evidence_level": "High", + "labeling_echa": "H319 (Causes serious eye irritation)", + "safety_score": 7, + "regulatory_notes": "Maximum authorized concentration in the finished product is 0.6%. Must not be used as a preservative at pH < 3.5, due to potential for local irritation or burns.", + "link_echa": "https://chem.echa.europa.eu/100.003.427/overview?searchText=110-44-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38173", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/110-44-1", + "link_other": "" + }, + { + "name": "CI 77268:1", + "alternative_names": "Carbon Black, oxidized, Carbon Black", + "category": "Colorant", + "benefits": "Provides visual appeal to the product, Contributes to product differentiation, No direct therapeutic dental health benefits", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.014.245/overview?searchText=1339-82-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32822", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1339-82-8", + "link_other": "" + }, + { + "name": "PEG-32", + "alternative_names": "Polyethylene glycol 1500, Macrogol 1500", + "category": "Humectant", + "benefits": "Maintains product moisture to prevent drying, contributes to smooth texture and consistency, helps bind ingredients for a homogeneous paste", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.167.649/overview?searchText=25322-68-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/78305", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/25322-68-3", + "link_other": "" + }, + { + "name": "PVM/MA COPOLYMER", + "alternative_names": "Poly(methyl vinyl ether/maleic anhydride), Maleic acid, methyl vinyl ether polymer", + "category": "Binding Agent", + "benefits": "Enhances retention of active ingredients (e.g., fluoride, antimicrobials) on tooth surfaces, Forms a protective film on teeth, contributing to anti-plaque effects, Acts as a binder, stabilizing toothpaste formulation and preventing ingredient separation", + "risks": "No significant risks documented at typical use concentrations. High concentrations of the raw material may cause skin, eye, or respiratory irritation, but generally considered safe for oral care use.", + "evidence_level": "High", + "labeling_echa": "H315 (Causes skin irritation), H319 (Causes serious eye irritation), H335 (May cause respiratory irritation), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified for oral care products within the provided data.", + "link_echa": "https://chem.echa.europa.eu/100.111.639/overview?searchText=9011-16-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/79129", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9011-16-9", + "link_other": "" + }, + { + "name": "zinc gluconate", + "alternative_names": "Zinc digluconate, Zinc(II) D-gluconate", + "category": "Antimicrobial", + "benefits": "Antimicrobial action, Reduces bad breath, Antiplaque effect", + "risks": "Ingestion of high doses can cause gastrointestinal upset (nausea, vomiting, diarrhea, abdominal pain); Chronic overconsumption can lead to copper deficiency; Causes serious eye irritation; Harmful if swallowed.", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H319 (Causes serious eye irritation), H335 (May cause respiratory irritation)", + "safety_score": 7, + "regulatory_notes": "No specific restrictions identified for oral care products based on the provided links. Generally recognized as safe (GRAS) by the FDA for use as a dietary supplement.", + "link_echa": "https://chem.echa.europa.eu/100.022.489/overview?searchText=zinc%20gluconate", + "link_cosIng": "", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/4468-02-6", + "link_other": "" + }, + { + "name": "Titanium dioxide", + "alternative_names": "CI 77891", + "category": "Colorant", + "benefits": "Provides white color, Enhances product aesthetics, Acts as an opacifying agent", + "risks": "H351 (Suspected of causing cancer) classification applies to inhalation of powder form. General concerns about genotoxicity for ingested forms (E171) have led to its ban as a food additive in the EU, which may indicate broader safety considerations for ingested products like toothpaste, especially regarding nanoparticles. No significant acute risks documented for topical oral use at typical concentrations.", + "evidence_level": "High", + "labeling_echa": "H351 (Suspected of causing cancer)", + "safety_score": 5, + "regulatory_notes": "The harmonised classification H351 (Carc. 2) for titanium dioxide is specifically applicable to substances and mixtures in powder form containing 1% or more of titanium dioxide that are hazardous by inhalation (Entry 27 of Annex XVII to REACH). This classification is not directly applicable to liquid or paste formulations like toothpaste. However, the EU has banned titanium dioxide (E171) as a food additive due to genotoxicity concerns for nanoparticles, which suggests increased scrutiny for products that may be ingested. No specific maximum allowed concentrations or restrictions for cosmetic/oral care use are listed in CosIng.", + "link_echa": "https://chem.echa.europa.eu/100.171.063/overview?searchText=13463-67-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/97171", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/13463-67-7", + "link_other": "" + }, + { + "name": "CI 74160", + "alternative_names": "Copper Phthalocyanine, Phthalocyanine Blue", + "category": "Colorant", + "benefits": "None documented for dental health (provides aesthetic blue color to the product)", + "risks": "Potential for eye irritation (H319). A significant number of registered companies self-classify this substance as harmful if swallowed (H302), which is a concern for oral care products where incidental ingestion can occur.", + "evidence_level": "High", + "labeling_echa": "H319 (Causes serious eye irritation), H302 (Harmful if swallowed)", + "safety_score": 5, + "regulatory_notes": "No specific restrictions identified for oral care products; however, hazard classifications (self-reported) indicate potential for irritation and harm if swallowed.", + "link_echa": "https://chem.echa.europa.eu/100.005.169/overview?searchText=147-14-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32799", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/147-14-8", + "link_other": "" + }, + { + "name": "CI 74260", + "alternative_names": "Copper phthalocyanine, chloromethyl derivative, Polychloro Copper Phthalocyanine", + "category": "Colorant", + "benefits": "Provides green color to oral care products for aesthetic purposes.", + "risks": "Potential for irritation to skin, eyes, and respiratory tract upon direct exposure. Low acute oral toxicity. No significant risks documented at typical use concentrations in oral care products.", + "evidence_level": "Moderate", + "labeling_echa": "None identified", + "safety_score": 8, + "regulatory_notes": "No specific restrictions identified. Approved for use as a colorant in cosmetic products in the EU.", + "link_echa": "https://chem.echa.europa.eu/100.026.292/overview?searchText=6373-74-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/31618", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/6373-74-6", + "link_other": "" + }, + { + "name": "Hydroxyethylcellulose", + "alternative_names": "HEC", + "category": "Thickener", + "benefits": "Improves toothpaste consistency and texture, prevents separation of solid ingredients, enhances product stability", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.116.562/overview?searchText=9004-62-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/76845", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9004-62-0", + "link_other": "" + }, + { + "name": "Olaflur", + "alternative_names": "", + "category": "Anticaries Agent", + "benefits": "Cavity prevention by inhibiting demineralization, Promotes remineralization of tooth enamel, Forms a protective layer on tooth surfaces, Antimicrobial action", + "risks": "Potential for systemic toxicity if swallowed in significant quantities (due to fluoride content), especially for children. Causes serious eye irritation (H319). Concentration-dependent concerns for children under 6 years, requiring specific usage and labeling.", + "evidence_level": "High", + "labeling_echa": "H319 (Causes serious eye irritation), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 8, + "regulatory_notes": "Maximum allowed concentration in oral hygiene products: 0.15% (as F). For children under 6 years, the total quantity of fluoride (as F) must not exceed 0.15% and products must be labelled with specific usage instructions (e.g., 'For children of 6 years and younger: Use a pea-sized amount for supervised brushing to minimize swallowing. In case of intake of fluoride from other sources consult a dentist or doctor.'). (EU Cosmetics Regulation (EC) No 1223/2009, Annex III, entry 159)", + "link_echa": "https://chem.echa.europa.eu/100.027.174/overview?searchText=6818-37-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35640", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/6818-37-7", + "link_other": "" + }, + { + "name": "PEG-40 Hydrogenated Castor Oil", + "alternative_names": "Polyoxyethylene (40) hydrogenated castor oil, Cremophor RH 40", + "category": "Surfactant", + "benefits": "Solubilizes flavor oils and oil-soluble ingredients, enhancing product taste and consumer acceptance; Functions as a surfactant, promoting uniform dispersion of ingredients throughout the toothpaste; Aids in the formation of foam, contributing to the cleaning sensation during brushing", + "risks": "No significant risks documented at typical use concentrations based on available regulatory data.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified by EU regulatory bodies (CosIng, ECHA).", + "link_echa": "https://chem.echa.europa.eu/100.105.643/overview?searchText=61788-85-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/78452", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/61788-85-0", + "link_other": "" + }, + { + "name": "Sodium Saccharin", + "alternative_names": "Saccharin sodium, Saccharin, sodium salt", + "category": "Sweetener", + "benefits": "Provides non-cariogenic sweetness to toothpaste, Enhances palatability and user compliance with brushing, Masks unpleasant tastes of other ingredients", + "risks": "No significant risks documented at typical use concentrations for oral/dental applications. High doses in animal studies showed bladder cancer, but human relevance is not established.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "Generally recognized as safe (GRAS) by FDA for use as an artificial sweetener. No specific concentration limits or restrictions identified for cosmetic/oral care use by CosIng.", + "link_echa": "https://chem.echa.europa.eu/100.004.443/overview?searchText=128-44-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80014", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/128-44-9", + "link_other": "" + }, + { + "name": "Chitosan", + "alternative_names": "Poly(D-glucosamine), Deacetylated chitin", + "category": "Antimicrobial", + "benefits": "Antimicrobial activity, Film-forming properties for protective barrier, Antiplaque potential", + "risks": "Potential for eye irritation (H319 reported by some registrants), which may imply mucous membrane irritation upon direct contact; generally considered low hazard for oral use at typical concentrations", + "evidence_level": "Moderate", + "labeling_echa": "H319 (Causes serious eye irritation)", + "safety_score": 7, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.122.259/overview?searchText=9012-76-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/75065", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9012-76-4", + "link_other": "" + }, + { + "name": "Sodium Gluconate", + "alternative_names": "D-Gluconic acid, monosodium salt, Gluconate sodium", + "category": "Tartar Control Agent", + "benefits": "Chelates calcium to prevent tartar formation, helps reduce plaque accumulation, aids in removing insoluble metal salt deposits, prevents precipitation of metal ions in the oral cavity", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.220.571/overview?searchText=527-07-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/79485", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/527-07-1", + "link_other": "" + }, + { + "name": "Stannous Chloride", + "alternative_names": "Tin dichloride, Tin(II) chloride", + "category": "Antimicrobial", + "benefits": "Reduces plaque formation, aids in gingivitis reduction, helps prevent dental caries, provides relief from dentin hypersensitivity", + "risks": "Harmful if swallowed, may cause severe burns and irritation to mucous membranes, potential for allergic skin reactions. Not suitable for children under 7 years of age.", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H314 (Causes severe skin burns and eye damage), H317 (May cause an allergic skin reaction), H335 (May cause respiratory irritation), H400 (Very toxic to aquatic life), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 5, + "regulatory_notes": "EU Cosmetics Regulation (CosIng): Conditions of use and warnings which must be printed on the label include 'rinse mouth thoroughly after use' and 'not suitable for children under 7 years of age'.", + "link_echa": "https://chem.echa.europa.eu/100.028.971/overview?searchText=7772-99-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38230", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7772-99-8", + "link_other": "" + }, + { + "name": "Sucralose", + "alternative_names": "Trichlorogalactosucrose, E955", + "category": "Sweetener", + "benefits": "Provides intense sweetness to improve product palatability, Non-cariogenic (does not promote tooth decay)", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "Approved as a food additive (E955) in the EU, implying safety for ingestion within set limits for food. No specific restrictions on concentration or warnings for cosmetic use are listed in the provided CosIng or ECHA data.", + "link_echa": "https://chem.echa.europa.eu/100.054.484/overview?searchText=56038-13-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/59924", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/56038-13-2", + "link_other": "" + }, + { + "name": "Cinnamal", + "alternative_names": "Cinnamaldehyde, 3-Phenyl-2-propenal", + "category": "Flavoring Agent", + "benefits": "Provides a distinctive cinnamon flavor, improves product palatability, exhibits antimicrobial properties (potential), masks undesirable odors.", + "risks": "Potential for allergic reactions (skin sensitization) in susceptible individuals, even at typical use concentrations. May cause irritation to mucous membranes or eyes, particularly in sensitive individuals or at higher concentrations.", + "evidence_level": "High", + "labeling_echa": "H317 (May cause an allergic skin reaction), H319 (Causes serious eye irritation), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 5, + "regulatory_notes": "Listed in EU Cosmetics Regulation Annex III, entry 86. Requires labeling in the ingredient list when its concentration exceeds 0.001% in leave-on products and 0.01% in rinse-off products (e.g., toothpaste) due to its sensitizing potential. ECHA classification includes Skin Sens. 1 (H317).", + "link_echa": "https://chem.echa.europa.eu/100.002.922/overview?searchText=104-55-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32846", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/104-55-2", + "link_other": "" + }, + { + "name": "Aqua", + "alternative_names": "Water", + "category": "Solvent", + "benefits": "Acts as a solvent for active ingredients, Aids in creating desired toothpaste consistency, Facilitates rinsing of oral cavity", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.205.267/overview?searchText=7732-18-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/92472", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7732-18-5", + "link_other": "" + }, + { + "name": "POLOXAMER 407", + "alternative_names": "Pluronic F-127, Kolliphor P 407", + "category": "Surfactant", + "benefits": "Aids in foaming and cleaning action, improves texture and stability of toothpaste formulations, enhances solubility and dispersion of active ingredients.", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://echa.europa.eu/substance-information/-/substanceinfo/100.027.674", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36666", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9003-11-6", + "link_other": "" + }, + { + "name": "FD&C Blue No. 1", + "alternative_names": "CI 42090, Brilliant Blue FCF", + "category": "Colorant", + "benefits": "Aesthetic enhancement for product appeal, aids product differentiation for consumers, can improve user experience and adherence by making product visually attractive", + "risks": "Rare potential for allergic reactions in sensitive individuals. No significant risks documented at typical use concentrations for oral/dental health.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "EU Cosmetics Regulation (Annex IV, entry 104): Maximum 0.2% for products coming into contact with mucous membranes (e.g., toothpaste).", + "link_echa": "https://chem.echa.europa.eu/100.021.219/overview?searchText=3844-45-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32756", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/3844-45-9", + "link_other": "" + }, + { + "name": "Tartrazine", + "alternative_names": "FD&C Yellow No. 5, CI 19140", + "category": "Colorant", + "benefits": "Aesthetic enhancement for product appeal (provides yellow color to toothpaste)", + "risks": "Potential for allergic reactions (e.g., urticaria, asthma, rhinitis) in sensitive individuals, particularly those sensitive to aspirin. No significant risks documented at typical use concentrations for the general population.", + "evidence_level": "High", + "labeling_echa": "None identified (based on harmonised classification and labelling)", + "safety_score": 6, + "regulatory_notes": "Permitted as a cosmetic colorant in the EU (Annex V, entry 10 of EU Cosmetics Regulation 1223/2009) with specific purity criteria (E 102). It is allowed in oral hygiene products. Known as FD&C Yellow No. 5 in the US, indicating FDA approval for use in food, drugs, and cosmetics under specified conditions. Labeling may be required to warn about potential allergic reactions in sensitive individuals in some regions.", + "link_echa": "https://chem.echa.europa.eu/100.512.755/overview?searchText=1934-21-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32737", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1934-21-0", + "link_other": "" + }, + { + "name": "Calcium silicate", + "alternative_names": "Silicic acid, calcium salt", + "category": "Abrasive", + "benefits": "Assists in mechanical plaque removal, Contributes to the removal of surface stains for a whitening effect, Acts as a mild abrasive for effective tooth cleaning", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.014.282/overview?searchText=1344-95-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32345", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1344-95-2", + "link_other": "" + }, + { + "name": "Trisodium phosphate", + "alternative_names": "Sodium phosphate tribasic, TSP", + "category": "pH Adjuster, Tartar Control Agent", + "benefits": "Helps maintain optimal oral pH, contributes to tartar control by chelating calcium ions", + "risks": "Potential for irritation of oral tissues (gums, mucous membranes) due to its alkaline nature and irritant properties; gastrointestinal upset (nausea, vomiting, diarrhea) if swallowed in large quantities", + "evidence_level": "High", + "labeling_echa": "H315 (Causes skin irritation), H319 (Causes serious eye irritation), H335 (May cause respiratory irritation)", + "safety_score": 7, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.028.645/overview?searchText=7601-54-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38776", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7601-54-9", + "link_other": "" + }, + { + "name": "SODIUM PHOSPHATE", + "alternative_names": "Trisodium phosphate, Sodium phosphate tribasic", + "category": "pH Adjuster", + "benefits": "pH buffering to maintain optimal oral environment, chelating agent for metal ions, contributes to overall oral hygiene", + "risks": "Potential for irritation of oral mucosa and respiratory tract, especially at higher concentrations. Serious eye irritation if direct contact occurs.", + "evidence_level": "High", + "labeling_echa": "H315 (Causes skin irritation), H319 (Causes serious eye irritation), H335 (May cause respiratory irritation)", + "safety_score": 8, + "regulatory_notes": "No specific restrictions identified for use in cosmetics or oral care products in the provided links. Harmonised classification exists.", + "link_echa": "https://chem.echa.europa.eu/100.028.645/overview?searchText=7601-54-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38776", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7601-54-9", + "link_other": "" + }, + { + "name": "Reaction products of tall oil fatty acids with polyglycol 600", + "alternative_names": "Fatty acids, tall-oil, reaction products with polyethylene glycol (PEG) 600, Polyglycol 600, reaction products with tall-oil fatty acids", + "category": "Surfactant", + "benefits": "Aids in foam generation, helps disperse toothpaste ingredients uniformly, acts as an emulsifier for flavor oils and other insoluble compounds", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "Moderate", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.105.643/overview?searchText=61788-85-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/77219", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/61788-85-0", + "link_other": "" + }, + { + "name": "Synthetic fluorphlogopite", + "alternative_names": "Synthetic mica, Fluorophlogopite, synthetic", + "category": "Bulking Agent", + "benefits": "Enhances product aesthetics, Improves texture and consistency, Acts as a bulking agent", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.031.283/overview?searchText=12003-38-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80520", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/12003-38-2", + "link_other": "" + }, + { + "name": "Polyacrylic Acid", + "alternative_names": "Carbomer", + "category": "Thickener", + "benefits": "Provides desired toothpaste consistency, ensures uniform distribution of active ingredients, enhances product stability and prevents ingredient separation", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.115.375/overview?searchText=9003-01-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/78561", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9003-01-4", + "link_other": "" + }, + { + "name": "Tin Oxide", + "alternative_names": "Tin dioxide, Stannic oxide", + "category": "Abrasive", + "benefits": "Plaque removal, stain removal, teeth polishing", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.038.311/overview?searchText=18282-10-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80260", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/18282-10-5", + "link_other": "" + }, + { + "name": "Sorbitol", + "alternative_names": "D-Glucitol, Glucitol", + "category": "Humectant", + "benefits": "Provides a sweet taste without promoting tooth decay, Acts as a humectant to prevent toothpaste from drying out, Contributes to the texture and consistency of toothpaste", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified; FDA Generally Recognized As Safe (GRAS) status", + "link_echa": "https://chem.echa.europa.eu/100.000.056/overview?searchText=50-70-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38191", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/50-70-4", + "link_other": "" + }, + { + "name": "Kaolin", + "alternative_names": "China Clay, Hydrated Aluminum Silicate", + "category": "Abrasive", + "benefits": "Gentle abrasive for effective plaque and stain removal, Aids in polishing tooth surfaces for a smoother feel, Contributes to a clean and fresh mouthfeel", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.100.108/overview?searchText=1332-58-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34795", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1332-58-7", + "link_other": "" + }, + { + "name": "Aloe barbadensis leaf juice", + "alternative_names": "Aloe vera leaf juice, Aloe extract", + "category": "Soothing Agent", + "benefits": "Soothing irritated gums, Moisturizing oral tissues, Anti-inflammatory properties, Mild antimicrobial effects", + "risks": "Potential for irritation of skin and eyes (H315, H319), and may cause respiratory irritation (H335), as notified by manufacturers for the extract. Rare allergic reactions are possible.", + "evidence_level": "High", + "labeling_echa": "H315 (Causes skin irritation), H319 (Causes serious eye irritation), H335 (May cause respiratory irritation)", + "safety_score": 7, + "regulatory_notes": "No specific restrictions identified for cosmetic use in the EU (CosIng database).", + "link_echa": "https://chem.echa.europa.eu/100.079.418/overview?searchText=85507-69-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/54347", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/85507-69-3", + "link_other": "" + }, + { + "name": "Sodium Coco-Sulfate", + "alternative_names": "Sulfuric acid, monococo alkyl esters, sodium salts, Sodium cocosulfate", + "category": "Surfactant", + "benefits": "Cleansing agent, Foaming agent, Aids in removal of food debris and plaque", + "risks": "Potential for oral mucosal irritation, may exacerbate canker sores in sensitive individuals, harmful if swallowed, can cause gastrointestinal upset if large quantities are swallowed", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H315 (Causes skin irritation), H318 (Causes serious eye damage), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 5, + "regulatory_notes": "No specific restrictions identified in the provided sources.", + "link_echa": "https://chem.echa.europa.eu/100.066.578/overview?searchText=68955-19-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37946", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68955-19-1", + "link_other": "" + }, + { + "name": "MELISSA OFFICINALIS LEAF EXTRACT", + "alternative_names": "Melissa officinalis, ext.", + "category": "Antimicrobial", + "benefits": "Antimicrobial activity (helps control oral bacteria, plaque), Antioxidant properties (can help protect oral tissues), Potential soothing and anti-inflammatory effects (beneficial for gum health)", + "risks": "Potential for allergic skin reactions (sensitization) in some individuals, as indicated by some self-classifications", + "evidence_level": "Moderate", + "labeling_echa": "H317 (May cause an allergic skin reaction) - based on self-classification by some notifiers; Harmonised classification is 'Not Classified'", + "safety_score": 8, + "regulatory_notes": "No specific restrictions identified in the provided sources for use in oral care products.", + "link_echa": "https://chem.echa.europa.eu/100.074.528/overview?searchText=84082-61-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35212", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84082-61-1", + "link_other": "" + }, + { + "name": "Disodium Cocoyl Glutamate", + "alternative_names": "", + "category": "Surfactant", + "benefits": "Effective cleansing of oral surfaces, Gentle foaming agent, Aids in dispersion of other active ingredients", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.062.785/overview?searchText=%0968187-30-4%20", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/75827", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68187-30-4", + "link_other": "" + }, + { + "name": "Maris Sal", + "alternative_names": "Sodium chloride, Sea salt", + "category": "Abrasive", + "benefits": "Mild abrasive to help remove plaque and surface stains, Astringent/Tonic effect that may contribute to gum health, Osmotic properties that can help reduce oral swelling", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.028.726/overview?searchText=7647-14-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37813", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7647-14-5", + "link_other": "" + }, + { + "name": "Sodium Cocoyl Glutamate", + "alternative_names": "N-Coco Acyl-L-Glutamic Acid Monosodium Salt", + "category": "Surfactant", + "benefits": "Cleanses oral surfaces, aids in distributing toothpaste ingredients, generates foam for enhanced cleaning sensation", + "risks": "No significant risks documented at typical use concentrations; ECHA and PubChem report no hazard classifications", + "evidence_level": "Moderate", + "labeling_echa": "None identified", + "safety_score": 8, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.062.787/overview?searchText=68187-32-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37832", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68187-32-6", + "link_other": "" + }, + { + "name": "Sodium Cocoyl Glutamate", + "alternative_names": "", + "category": "Surfactant", + "benefits": "Cleansing, Foaming, Aids in plaque removal, Facilitates even distribution of toothpaste", + "risks": "Potential for mild irritation in sensitive individuals at typical use concentrations, classified as an irritant to skin and eyes in concentrated form", + "evidence_level": "High", + "labeling_echa": "H315 (Causes skin irritation), H319 (Causes serious eye irritation)", + "safety_score": 8, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.062.787/overview?searchText=68187-32-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37832", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68187-32-6", + "link_other": "" + }, + { + "name": "Sodium Hydroxide", + "alternative_names": "Caustic soda, Lye", + "category": "pH Adjuster", + "benefits": "Maintains product pH for stability, Optimizes the activity of other pH-sensitive ingredients, Contributes to neutralizing oral acids, supporting a healthy oral environment", + "risks": "Corrosive in concentrated form; can cause severe irritation or burns to oral tissues if pH is not adequately controlled or concentration is too high. Harmful if swallowed in significant amounts. Not recommended for direct, undiluted use.", + "evidence_level": "High", + "labeling_echa": "H290 (May be corrosive to metals), H314 (Causes severe skin burns and eye damage)", + "safety_score": 5, + "regulatory_notes": "Restricted under EU Cosmetics Regulation 1223/2009, Annex III. Maximum concentration in ready-to-use preparations is 5% for pH adjustment (among other uses), and the pH of the ready-to-use preparation must not exceed 11.", + "link_echa": "https://chem.echa.europa.eu/100.013.805/overview?searchText=1310-73-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37890", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1310-73-2", + "link_other": "" + }, + { + "name": "Sodium Hexametaphosphate", + "alternative_names": "Sodium polymetaphosphate, Graham's salt", + "category": "Tartar Control Agent", + "benefits": "Tartar control, Stain removal, Anticaries properties, pH buffering", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.214.884/overview?searchText=10124-56-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/79493", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/10124-56-8", + "link_other": "" + }, + { + "name": "Sodium Citrate", + "alternative_names": "Trisodium citrate", + "category": "pH Adjuster", + "benefits": "Reduces dentinal hypersensitivity, Helps control tartar/calculus formation, Acts as a pH buffer", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.000.614/overview?searchText=68-04-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37816", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68-04-2", + "link_other": "" + }, + { + "name": "Menthol", + "alternative_names": "L-Menthol, DL-Menthol", + "category": "Flavoring Agent", + "benefits": "Provides a refreshing and cooling sensation, Improves product taste and masks undesirable odors, Possesses mild antimicrobial properties, May offer minor relief for oral irritation", + "risks": "Potential for oral irritation and allergic reactions/sensitization, Toxicity if swallowed in high doses, Not recommended for children under two years old due to potential for severe breathing problems", + "evidence_level": "High", + "labeling_echa": "H315 (Causes skin irritation), H319 (Causes serious eye irritation), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 6, + "regulatory_notes": "Not recommended for children under two years old due to potential for severe breathing problems. Use concentrations in oral care products are typically low to avoid irritation and adverse effects.", + "link_echa": "https://chem.echa.europa.eu/100.001.763/overview?searchText=89-78-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35228", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/89-78-1", + "link_other": "" + }, + { + "name": "Mentha Viridis Leaf Oil", + "alternative_names": "Spearmint oil, Mentha Spicata Oil", + "category": "Flavoring Agent, Oral care agent", + "benefits": "Provides fresh, minty flavor; Masks undesirable odors/flavors; Contributes to overall oral hygiene; Delivers a cooling/refreshing sensation", + "risks": "May cause an allergic skin reaction (sensitization); Causes serious eye irritation; Potentially fatal if swallowed and enters airways (significant concern for accidental ingestion, especially in children); Not recommended for use in high concentrations due to irritation potential.", + "evidence_level": "High", + "labeling_echa": "H304 (May be fatal if swallowed and enters airways), H317 (May cause an allergic skin reaction), H319 (Causes serious eye irritation), H411 (Toxic to aquatic life with long lasting effects)", + "safety_score": 5, + "regulatory_notes": "Classified as a 'Fragrance allergen' in CosIng, requiring declaration in cosmetic products (including oral care) under EU Cosmetics Regulation (EC) No 1223/2009 if its concentration exceeds certain thresholds (0.01% in rinse-off products, 0.001% in leave-on products). May contain constituents (e.g., Menthol) that are subject to specific maximum concentration limits in oral care products (e.g., Menthol is restricted under Annex III/144 of the EU Cosmetics Regulation). ECHA indicates hazards (H304, H317, H319, H411) that necessitate proper handling and labeling according to CLP Regulation.", + "link_echa": "https://chem.echa.europa.eu/100.076.023/overview?searchText=84696-51-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/57942", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84696-51-5", + "link_other": "" + }, + { + "name": "Carvone", + "alternative_names": "(R)-(-)-Carvone, L-Carvone", + "category": "Flavoring Agent", + "benefits": "Provides minty/spearmint flavor, Improves product palatability, Contributes to fresh breath sensation", + "risks": "Harmful if swallowed, May cause an allergic reaction, Potential for oral irritation in sensitive individuals", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H317 (May cause an allergic skin reaction), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 6, + "regulatory_notes": "No specific restrictions identified. However, its classification as 'May cause an allergic skin reaction' (H317) implies that product safety assessments should consider its sensitizing potential, especially at higher concentrations. The 'Harmful if swallowed' (H302) classification should be considered for products intended for oral use, although typical toothpaste ingestion amounts are low.", + "link_echa": "https://chem.echa.europa.eu/100.002.508/overview?searchText=99-49-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74838", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/99-49-0", + "link_other": "" + }, + { + "name": "Anethole", + "alternative_names": "trans-Anethole, p-Anisylpropene", + "category": "Flavoring Agent", + "benefits": "Enhances product palatability with a sweet, licorice-like flavor profile; effective in masking less desirable tastes in oral care formulations.", + "risks": "Harmful if swallowed (H302), may cause allergic skin reactions (H317). Suspected of causing genetic defects (H341) and suspected of causing cancer (H351). Ingestion is a specific concern for oral care products like toothpaste.", + "evidence_level": "High", + "labeling_echa": "H227 (Combustible liquid), H302 (Harmful if swallowed), H317 (May cause an allergic skin reaction), H341 (Suspected of causing genetic defects), H351 (Suspected of causing cancer), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 4, + "regulatory_notes": "Restricted in cosmetic products according to EU Cosmetics Regulation. Maximum allowed concentration in toothpastes is 0.1% and in mouthwashes is 0.05% (as per CosIng).", + "link_echa": "https://chem.echa.europa.eu/100.002.914/overview?searchText=104-46-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74302", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/104-46-1", + "link_other": "" + }, + { + "name": "POLOXAMER 105", + "alternative_names": "Poly(oxypropylene)-poly(oxyethylene)-poly(oxypropylene) block copolymer, Pluronic 105", + "category": "Surfactant", + "benefits": "Aids in dispersing active ingredients, Contributes to foaming for mechanical cleaning, Solubilizes flavors and other hydrophobic compounds", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.118.740/overview?searchText=9003-11-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80123", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9003-11-6", + "link_other": "" + }, + { + "name": "Calcium pyrophosphate", + "alternative_names": "Dicalcium diphosphate, Calcium diphosphate", + "category": "Abrasive", + "benefits": "Gentle cleaning and polishing of tooth surfaces, Aids in the removal of plaque, Helps remove surface stains from teeth", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.029.292/overview?searchText=7790-76-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74915", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7790-76-3", + "link_other": "" + }, + { + "name": "PEG/PPG-116/66 Copolymer", + "alternative_names": "Poly(ethylene glycol-ran-propylene glycol)", + "category": "Thickener", + "benefits": "Viscosity control, Binding agent, Film forming agent", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.118.740/overview?searchText=9003-11-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/57106", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9003-11-6", + "link_other": "" + }, + { + "name": "Potassium caroate", + "alternative_names": "Potassium peroxymonosulfate, Potassium monopersulfate", + "category": "Whitening Agent", + "benefits": "Oxidative whitening, Antimicrobial action, Stain removal", + "risks": "Harmful if swallowed, causes severe skin burns and eye damage, may cause an allergic skin reaction, may cause allergy or asthma symptoms or breathing difficulties if inhaled. Corrosive nature is a significant concern for oral tissues.", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H314 (Causes severe skin burns and eye damage), H317 (May cause an allergic skin reaction), H334 (May cause allergy or asthma symptoms or breathing difficulties if inhaled), H400 (Very toxic to aquatic life), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 3, + "regulatory_notes": "No specific restrictions identified in the provided links for oral care products. However, the severe hazard classifications (corrosive, harmful if swallowed, sensitizer) imply strict formulation control, very low concentrations, and prominent warnings would be necessary for any oral care application.", + "link_echa": "https://chem.echa.europa.eu/100.030.158/overview?searchText=10058-23-8", + "link_cosIng": "", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/10058-23-8", + "link_other": "" + }, + { + "name": "Disodium Pyrophosphate", + "alternative_names": "Disodium Dihydrogen Pyrophosphate, Sodium pyrophosphate dibasic", + "category": "Tartar Control Agent", + "benefits": "Tartar control, pH adjustment, Chelating action, General oral care functionality", + "risks": "May cause serious eye irritation (H319) at concentrations ≥10%. No significant risks to oral tissues or systemic toxicity documented at typical use concentrations in toothpaste; generally recognized as safe for ingestion at typical food additive levels.", + "evidence_level": "High", + "labeling_echa": "H319 (Causes serious eye irritation)", + "safety_score": 9, + "regulatory_notes": "No specific maximum allowed concentrations or restrictions for Disodium Pyrophosphate in oral care products are identified by CosIng. ECHA notes a specific concentration limit of C ≥ 10% for the hazard H319 (Causes serious eye irritation).", + "link_echa": "https://chem.echa.europa.eu/100.028.941/overview?searchText=7758-16-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/75795", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7758-16-9", + "link_other": "" + }, + { + "name": "Magnesium carbonate", + "alternative_names": "Magnesite, Carbonic acid magnesium salt", + "category": "Abrasive", + "benefits": "Plaque removal, Stain removal, Tooth polishing, pH balancing", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.008.106/overview?searchText=546-93-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/77618", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/546-93-0", + "link_other": "" + }, + { + "name": "Sodium monofluorophosphate", + "alternative_names": "Sodium fluorophosphate, Fluorofos", + "category": "Anticaries Agent", + "benefits": "Prevents dental caries, strengthens tooth enamel, remineralizes early enamel lesions", + "risks": "Harmful if swallowed (acute toxicity), potential for dental fluorosis if excessive amounts are ingested during tooth development, particularly in young children. Risks are concentration-dependent.", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed)", + "safety_score": 8, + "regulatory_notes": "Total fluorine content in ready-to-use oral care preparations must not exceed 0.15% (1500 ppm F). Required labeling for toothpastes: 'Children of 6 years and younger: Use a pea-sized amount for supervised brushing to minimise swallowing. In case of intake of fluoride from other sources consult a dentist or doctor.' (EU Cosmetics Regulation).", + "link_echa": "https://chem.echa.europa.eu/100.030.381/overview?searchText=10163-15-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/87604", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/10163-15-5", + "link_other": "" + }, + { + "name": "Calcium Carbonate", + "alternative_names": "Limestone, Chalk", + "category": "Abrasive", + "benefits": "Removes plaque and surface stains (mild abrasive), Helps neutralize oral acids (pH buffer), Supports tooth remineralization (source of calcium)", + "risks": "Potential for enamel abrasion if used in excessively coarse forms or high concentrations (unlikely with dental-grade formulations). Excessive ingestion may lead to hypercalcemia or constipation, but amounts swallowed from toothpaste are typically negligible.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified for oral care products in EU (CosIng). ECHA does not classify it as hazardous. Generally recognized as safe (GRAS) by FDA for certain uses.", + "link_echa": "https://chem.echa.europa.eu/100.006.765/overview?searchText=471-34-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32314", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/471-34-1", + "link_other": "" + }, + { + "name": "Tetrapotassium pyrophosphate", + "alternative_names": "Potassium pyrophosphate", + "category": "Tartar Control Agent", + "benefits": "Tartar control, Plaque control, Prevents mineral deposition", + "risks": "Potential for serious eye irritation if contact occurs. Low acute oral toxicity, no significant oral irritation documented at typical use concentrations.", + "evidence_level": "High", + "labeling_echa": "H319 (Causes serious eye irritation)", + "safety_score": 8, + "regulatory_notes": "No specific restrictions identified for oral care products in provided sources. However, it is classified with H319 (Causes serious eye irritation) according to ECHA CLP.", + "link_echa": "https://chem.echa.europa.eu/100.027.986/overview?searchText=7320-34-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80751", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7320-34-5", + "link_other": "" + }, + { + "name": "sodium methyl cocoyl taurate", + "alternative_names": "sodium cocoyl methyl taurate", + "category": "Surfactant", + "benefits": "Improves cleansing and removal of plaque and food debris, Aids in foaming for enhanced user experience, Helps disperse active ingredients evenly in the mouth", + "risks": "Potential for oral mucosal irritation (H315); Strong irritant potential (H318 eye damage) indicates need for careful formulation; Ingestion of large quantities may cause gastrointestinal upset", + "evidence_level": "High", + "labeling_echa": "H315 (Causes skin irritation), H318 (Causes serious eye damage), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 5, + "regulatory_notes": "Maximum concentration allowed in rinse-off products (e.g., toothpaste): 3% (EU Cosmetics Regulation)", + "link_echa": "https://chem.echa.europa.eu/100.123.200/overview?searchText=12765-39-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/79777", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/12765-39-8", + "link_other": "" + }, + { + "name": "CI 73360", + "alternative_names": "Acid Red 52, D&C Red No. 28", + "category": "Colorant", + "benefits": "No direct dental health benefits. Functions as a cosmetic colorant to enhance product appeal and consumer acceptance.", + "risks": "Potential for serious eye irritation (H319). No significant oral irritation or systemic toxicity documented at typical use concentrations in toothpaste.", + "evidence_level": "High", + "labeling_echa": "H319 (Causes serious eye irritation), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 8, + "regulatory_notes": "Allowed as a colorant in cosmetic products under EU Cosmetics Regulation (EC) No 1223/2009. No specific maximum concentration limits for toothpaste identified in provided sources, but generally restricted in hair dye products.", + "link_echa": "https://chem.echa.europa.eu/100.017.422/overview?searchText=2379-74-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32794", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/2379-74-0", + "link_other": "" + }, + { + "name": "Propylene Glycol", + "alternative_names": "1,2-Propanediol, Propane-1,2-diol", + "category": "Humectant", + "benefits": "Prevents toothpaste from drying out and hardening, ensures consistent product texture and flow, facilitates uniform distribution of active ingredients, acts as a solvent for flavors and other excipients", + "risks": "No significant risks documented at typical use concentrations; rare cases of contact dermatitis or mild irritation reported in highly sensitive individuals", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified in EU Cosmetics Regulation. Generally Recognized As Safe (GRAS) by the FDA.", + "link_echa": "https://chem.echa.europa.eu/100.417.077/overview?searchText=57-55-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37269", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/57-55-6", + "link_other": "" + }, + { + "name": "Zinc Lactate", + "alternative_names": "Zinc dilactate", + "category": "Antimicrobial", + "benefits": "Antimicrobial action, reduces plaque formation, prevents gingivitis, reduces bad breath", + "risks": "No significant risks documented at typical use concentrations; rare allergic reactions are possible.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "Maximum concentration of 1% (expressed as zinc) in oral products according to EU Cosmetics Regulation Annex III/Entry 34. For oral products, if the zinc concentration exceeds 0.1% (expressed as zinc), the warning 'Keep out of reach of children' is required.", + "link_echa": "https://chem.echa.europa.eu/100.036.510/overview?searchText=16039-53-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38964", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/16039-53-5", + "link_other": "" + }, + { + "name": "Lauryl Glucoside", + "alternative_names": "D-Glucopyranose, oligomeric, decyl octyl glycosides", + "category": "Surfactant", + "benefits": "Cleansing action, Foaming agent, Emulsifying properties", + "risks": "Potential for irritation of oral mucosa in sensitive individuals or at high concentrations. If swallowed in large quantities, may cause gastrointestinal upset.", + "evidence_level": "High", + "labeling_echa": "H318 (Causes serious eye damage), H315 (Causes skin irritation)", + "safety_score": 7, + "regulatory_notes": "No specific restrictions identified for oral care products in the provided sources. Generally considered safe and well-tolerated in topical applications.", + "link_echa": "https://chem.echa.europa.eu/100.123.133/overview?searchText=110615-47-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/56967", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/110615-47-9", + "link_other": "" + }, + { + "name": "Zinc Citrate", + "alternative_names": "Zinc Citrate Hydrate, Trizinc dicitrate tetrahydrate", + "category": "Antiplaque Agent", + "benefits": "Plaque prevention, Gingivitis reduction, Bad breath control, Tartar control, Antimicrobial properties", + "risks": "Harmful if swallowed (H302), which is a concern for toothpaste due to potential ingestion, especially by young children. Causes serious eye damage (H318) for the raw material.", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H318 (Causes serious eye damage), H400 (Very toxic to aquatic life), H410 (Very toxic to aquatic life with long lasting effects)", + "safety_score": 7, + "regulatory_notes": "No specific restrictions identified from the provided links for oral care products.", + "link_echa": "https://chem.echa.europa.eu/100.121.410/overview?searchText=5990-32-9", + "link_cosIng": "", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/5990-32-9", + "link_other": "" + }, + { + "name": "Papain", + "alternative_names": "Papayotin, Vegetable Pepsin", + "category": "Antiplaque Agent", + "benefits": "Plaque control, Stain removal, Chemo-mechanical caries removal", + "risks": "May cause skin/mucosal irritation and allergic reactions, including severe hypersensitivity reactions (asthma, rhinitis) if inhaled. Not for prolonged contact; restricted to 0.5% in rinse-off products.", + "evidence_level": "High", + "labeling_echa": "H315 (Causes skin irritation), H317 (May cause an allergic skin reaction), H319 (Causes serious eye irritation), H334 (May cause allergy or asthma symptoms or breathing difficulties if inhaled), H335 (May cause respiratory irritation)", + "safety_score": 4, + "regulatory_notes": "EU Cosmetics Regulation (CosIng): Restricted to a maximum concentration of 0.5% in rinse-off products. Not for products intended for prolonged contact with the skin.", + "link_echa": "https://chem.echa.europa.eu/100.029.649/overview?searchText=9001-73-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35846", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9001-73-4", + "link_other": "" + }, + { + "name": "Bromelain", + "alternative_names": "Pineapple enzyme, Ananase", + "category": "Whitening Agent", + "benefits": "Stain removal/whitening, Plaque reduction, Anti-inflammatory properties", + "risks": "Allergic reactions (especially for individuals with pineapple allergy), potential for oral irritation, increased risk of bleeding (though less likely with topical use), not recommended for children under 3 years of age in oral products.", + "evidence_level": "High", + "labeling_echa": "H315 (Causes skin irritation), H317 (May cause an allergic skin reaction), H319 (Causes serious eye irritation), H334 (May cause allergy or asthma symptoms or breathing difficulties if inhaled), H335 (May cause respiratory irritation)", + "safety_score": 6, + "regulatory_notes": "Not to be used in oral products for children under 3 years of age (EU Cosmetics Regulation, as per CosIng).", + "link_echa": "https://chem.echa.europa.eu/100.029.599/overview?searchText=9001-00-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/54967", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9001-00-7", + "link_other": "" + }, + { + "name": "Glyceryl Caprylate", + "alternative_names": "Glyceryl Monocaprylate, Monooctanoin", + "category": "Antimicrobial", + "benefits": "Antimicrobial activity (helps control oral bacteria and fungi), Surfactant/Emulsifier (aids in cleaning and ingredient dispersion), Preservative (contributes to product stability)", + "risks": "No significant risks documented at typical use concentrations; low toxicity and non-irritating properties reported.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified for use in oral care products.", + "link_echa": "https://chem.echa.europa.eu/100.043.320/overview?searchText=26402-26-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34049", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/26402-26-6", + "link_other": "" + }, + { + "name": "Mentha Arvensis Leaf Oil", + "alternative_names": "Cornmint oil, Wild mint oil", + "category": "Flavoring Agent", + "benefits": "Provides fresh breath, imparts a refreshing flavor, offers a cooling sensation", + "risks": "Potential for allergic reactions (skin sensitization), causes skin and serious eye irritation, harmful if swallowed at higher concentrations. Contains known fragrance allergens.", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H312 (Harmful in contact with skin), H315 (Causes skin irritation), H317 (May cause an allergic skin reaction), H319 (Causes serious eye irritation), H411 (Toxic to aquatic life with long lasting effects)", + "safety_score": 5, + "regulatory_notes": "Restricted in Annex III, Part I of EU Cosmetics Regulation (EC) No 1223/2009. Contains known fragrance allergens (e.g., Limonene, Linalool, Citral) which may require individual labeling if exceeding certain concentrations.", + "link_echa": "https://chem.echa.europa.eu/100.081.839/overview?searchText=90063-97-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/96196", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/90063-97-1", + "link_other": "" + }, + { + "name": "Mentha Piperita Oil", + "alternative_names": "Peppermint oil", + "category": "Flavoring Agent", + "benefits": "Flavoring agent, improving taste of oral products, masks unpleasant mouth odors, provides fresh breath, offers a cooling and refreshing sensation, possesses mild antiseptic properties", + "risks": "Potential for allergic reactions and sensitization (H317). May cause irritation to mucous membranes, particularly at higher concentrations (implied by H319). Ingestion of large amounts may cause gastrointestinal upset.", + "evidence_level": "Moderate", + "labeling_echa": "H317 (May cause an allergic skin reaction), H319 (Causes serious eye irritation), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 6, + "regulatory_notes": "No specific restrictions identified in the provided sources.", + "link_echa": "https://chem.echa.europa.eu/100.126.669/overview?searchText=8006-81-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/86971", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/8006-81-3", + "link_other": "" + }, + { + "name": "Calcium glycerophosphate", + "alternative_names": "Calcium glycerol phosphate, Glycophosphate calcium", + "category": "Anticaries Agent", + "benefits": "Promotes dental enamel remineralization, Provides essential calcium and phosphate ions for hydroxyapatite formation, Enhances fluoride efficacy in preventing cavities", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.043.920/overview?searchText=27214-00-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74900", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/27214-00-2", + "link_other": "" + }, + { + "name": "Stevia Rebaudiana Leaf/Stem Extract", + "alternative_names": "Stevia Extract, Stevia Leaf Extract", + "category": "Sweetener", + "benefits": "Provides non-cariogenic sweetness, Sugar substitute, Masks undesirable flavors, Contributes to product palatability without promoting tooth decay", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "Generally recognized as safe (GRAS) by the U.S. FDA for food use (components like steviol glycosides). No specific restrictions identified in EU cosmetics regulations (CosIng database).", + "link_echa": "https://chem.echa.europa.eu/100.085.803/overview?searchText=91722-21-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/58821", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/139174-88-8", + "link_other": "" + }, + { + "name": "Caprylhydroxamic Acid", + "alternative_names": "N-Hydroxyoctanamide, Octanohydroxamic acid", + "category": "Antimicrobial", + "benefits": "Antimicrobial activity, Contributes to plaque control, Preserves toothpaste from microbial spoilage", + "risks": "Harmful if swallowed, potential for allergic skin reactions (including oral mucosa), and general irritation. Ingestion risks are concentration-dependent, especially for children.", + "evidence_level": "Moderate", + "labeling_echa": "H302 (Harmful if swallowed), H317 (May cause an allergic skin reaction), H319 (Causes serious eye irritation)", + "safety_score": 6, + "regulatory_notes": "No specific restrictions identified under the EU Cosmetics Regulation (EC) No 1223/2009; however, its hazard classifications (H302, H317, H319) require careful consideration for oral care product formulation and labeling, especially concerning ingestion by vulnerable populations.", + "link_echa": "https://chem.echa.europa.eu/100.028.124/overview?searchText=7377-03-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/86262", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7377-03-9", + "link_other": "" + }, + { + "name": "Sodium Metabisulfite", + "alternative_names": "Disodium disulfite, Sodium disulfite", + "category": "Antioxidant", + "benefits": "Maintains product formulation stability, acts as an antioxidant to prevent ingredient degradation, helps preserve the efficacy of other active dental ingredients", + "risks": "Harmful if swallowed, may cause allergic skin reactions, causes serious eye damage, may cause respiratory irritation. Can trigger severe allergic reactions (including anaphylactic shock) upon ingestion in sensitive individuals, particularly asthmatics or those with sulfite hypersensitivity.", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H317 (May cause an allergic skin reaction), H318 (Causes serious eye damage), H335 (May cause respiratory irritation)", + "safety_score": 5, + "regulatory_notes": "Concentration limits in cosmetic products (including oral care) are subject to specific national legislation within the EU; details not specified in provided links.", + "link_echa": "https://chem.echa.europa.eu/100.028.991/overview?searchText=7681-57-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37956", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7681-57-4", + "link_other": "" + }, + { + "name": "Steviol Glycosides", + "alternative_names": "Stevia Extract, Rebaudioside A", + "category": "Sweetener", + "benefits": "Provides sweet taste, non-cariogenic, masks unpleasant flavors", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.055.414/overview?searchText=57817-89-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/79199", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/57817-89-7", + "link_other": "" + }, + { + "name": "Linalool", + "alternative_names": "3,7-Dimethylocta-1,6-dien-3-ol, Linalol", + "category": "Flavoring Agent", + "benefits": "Provides pleasant aroma and flavor to oral care products, masks undesirable base odors", + "risks": "Potential for allergic reactions (skin sensitization, which can extend to oral mucosa), irritation of oral tissues in sensitive individuals", + "evidence_level": "High", + "labeling_echa": "H317 (May cause an allergic skin reaction), H319 (Causes serious eye irritation)", + "safety_score": 7, + "regulatory_notes": "Presence must be indicated in the ingredient list when concentration exceeds 0.01% in rinse-off products (e.g., toothpaste), due to its potential as an allergen (EU Cosmetics Regulation).", + "link_echa": "https://chem.echa.europa.eu/100.001.032/overview?searchText=78-70-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35016", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/78-70-6", + "link_other": "" + }, + { + "name": "CI 77492", + "alternative_names": "Iron Oxide Yellow, Iron hydroxide oxide yellow", + "category": "Colorant", + "benefits": "Provides yellow/brown color to toothpaste, enhances product aesthetics, no direct therapeutic oral health benefits", + "risks": "No significant risks documented at typical use concentrations for oral care products. Generally regarded as safe for ingestion at cosmetic levels.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified for use in cosmetic or oral care products within the EU. Permitted as a colorant without concentration limits by CosIng.", + "link_echa": "https://chem.echa.europa.eu/100.051.890/overview?searchText=51274-00-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/31177", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/51274-00-1", + "link_other": "" + }, + { + "name": "Potassium Citrate", + "alternative_names": "Tripotassium citrate, Citric acid, tripotassium salt", + "category": "Desensitizing Agent", + "benefits": "Reduces dentin hypersensitivity, Acts as a buffering agent, Chelating agent for oral environment", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.011.596/overview?searchText=866-84-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36949", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/866-84-2", + "link_other": "" + }, + { + "name": "CI 77491", + "alternative_names": "Iron Oxides, Ferric Oxide", + "category": "Colorant", + "benefits": "Enhances product aesthetic appeal, Improves consumer acceptance and compliance, Masks undesirable natural ingredient colors", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.013.790/overview?searchText=1309-37-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32829", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1309-37-1", + "link_other": "" + }, + { + "name": "Aloe barbadensis leaf extract", + "alternative_names": "Aloe vera leaf extract", + "category": "Soothing Agent", + "benefits": "Soothes oral tissues, provides anti-inflammatory effects, possesses antimicrobial properties, supports general oral hygiene", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.079.418/overview?searchText=85507-69-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/54346", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/85507-69-3", + "link_other": "" + }, + { + "name": "Mentha Arvensis Herb Oil", + "alternative_names": "Cornmint Oil, Wild Mint Oil", + "category": "Flavoring Agent", + "benefits": "Freshens breath, provides pleasant taste, contributes to general oral hygiene", + "risks": "Potential for oral mucosa irritation and allergic reactions (sensitization). Harmful if swallowed (H302) and may be fatal if swallowed and enters airways (H304), especially in young children. Causes serious eye irritation (H319). Not recommended for children under 3 years old.", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H304 (May be fatal if swallowed and enters airways), H315 (Causes skin irritation), H317 (May cause an allergic skin reaction), H319 (Causes serious eye irritation), H335 (May cause respiratory irritation), H411 (Toxic to aquatic life with long lasting effects)", + "safety_score": 5, + "regulatory_notes": "Restricted in Annex III, entry 185 of the EU Cosmetics Regulation (EC) No 1223/2009. Not to be used in products intended for children under 3 years old.", + "link_echa": "https://chem.echa.europa.eu/100.111.474/overview?searchText=68917-18-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/57860", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68917-18-0", + "link_other": "" + }, + { + "name": "Magnesium aluminium silicate", + "alternative_names": "Aluminium magnesium silicate, Smectite", + "category": "Thickener", + "benefits": "Maintains product consistency and stability, Improves texture and mouthfeel, Aids in mild mechanical cleaning", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified. Approved for use in cosmetic and oral care products within the EU.", + "link_echa": "https://chem.echa.europa.eu/100.014.072/overview?searchText=1327-43-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35080", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1327-43-1", + "link_other": "" + }, + { + "name": "PHENOXYETHANOL", + "alternative_names": "2-Phenoxyethanol, Phenoxetol", + "category": "Preservative", + "benefits": "Preserves product integrity by inhibiting microbial growth, Extends product shelf life, Provides broad-spectrum antimicrobial activity", + "risks": "Harmful if swallowed (H302), May cause irritation to mucous membranes, Potential systemic toxicity if ingested in significant amounts, especially for young children", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H319 (Causes serious eye irritation), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 6, + "regulatory_notes": "Maximum concentration allowed in cosmetic products (including toothpaste) is 1.0% (EU Cosmetics Regulation, Annex V). Not to be used in products for the nappy area of children under 3 years of age, indicating general caution for young children's products due to potential absorption/ingestion.", + "link_echa": "https://chem.echa.europa.eu/100.004.173/overview?searchText=122-99-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36522", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/122-99-6", + "link_other": "" + }, + { + "name": "Potassium Chloride", + "alternative_names": "Sylvite", + "category": "Desensitizing Agent", + "benefits": "Reduces dentin hypersensitivity, Blocks nerve signals in the teeth, Provides relief from pain caused by exposed dentin", + "risks": "No significant risks documented at typical use concentrations. Large ingestion may cause mild gastrointestinal upset.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.207.258/overview?searchText=7447-40-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36948", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7447-40-7", + "link_other": "" + }, + { + "name": "Sodium Sulfate", + "alternative_names": "Sodium Sulphate, Disodium Sulfate", + "category": "Binding Agent", + "benefits": "Acts as a bulking agent, controls product viscosity, helps maintain product consistency", + "risks": "No significant risks documented at typical use concentrations for oral care. Low acute toxicity if swallowed.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified for oral care products.", + "link_echa": "https://chem.echa.europa.eu/100.215.944/overview?searchText=7757-82-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38093", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7757-82-6", + "link_other": "" + }, + { + "name": "Stevioside", + "alternative_names": "", + "category": "Sweetener", + "benefits": "Non-cariogenic (does not cause tooth decay), Provides sweetness to enhance palatability, Masks unpleasant tastes in formulations, Natural origin often preferred by consumers", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.055.414/overview?searchText=57817-89-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/79199", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/57817-89-7", + "link_other": "" + }, + { + "name": "Acacia senegal gum", + "alternative_names": "Gum arabic, Acacia gum", + "category": "Thickener", + "benefits": "Thickening agent, Binding agent, Emulsion stabilizer, Film-forming", + "risks": "Rare cases of allergic reactions reported. No significant risks documented at typical use concentrations.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "Generally Recognized As Safe (GRAS) by FDA. No specific restrictions identified under EU Cosmetics Regulation.", + "link_echa": "https://chem.echa.europa.eu/100.029.551/overview?searchText=9000-01-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/54244", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9000-01-5", + "link_other": "" + }, + { + "name": "Lactobacillus", + "alternative_names": "Bacteria, Lactobacillus", + "category": "Antimicrobial", + "benefits": "Modulates oral microbiome to inhibit harmful bacteria, Supports gum health by reducing inflammation and gingivitis, Helps reduce plaque formation", + "risks": "No significant risks documented at typical use concentrations; ECHA classifies as non-hazardous", + "evidence_level": "Moderate", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified. ECHA classifies the substance as non-hazardous according to CLP Regulation and notes its use in cosmetics and personal care products.", + "link_echa": "https://chem.echa.europa.eu/100.110.946/overview?searchText=68333-14-2", + "link_cosIng": "", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68333-14-2", + "link_other": "" + }, + { + "name": "Eucalyptus Oil", + "alternative_names": "Eucalyptus globulus oil, Oleum eucalypti", + "category": "Flavoring Agent, Antimicrobial", + "benefits": "Provides refreshing flavor, Acts as an antimicrobial/antiseptic agent, Helps mask bad breath", + "risks": "May cause an allergic skin reaction, Causes serious eye irritation, May be fatal if swallowed and enters airways (aspiration hazard), Potentially toxic if swallowed (lethal dose in children reported for 4-5 mL orally)", + "evidence_level": "High", + "labeling_echa": "H226 (Flammable liquid and vapour), H304 (May be fatal if swallowed and enters airways), H317 (May cause an allergic skin reaction), H319 (Causes serious eye irritation), H411 (Toxic to aquatic life with long lasting effects)", + "safety_score": 4, + "regulatory_notes": "No specific concentration restrictions identified for rinse-off products (like toothpaste) in the EU CosIng database for Eucalyptus Globulus Leaf Oil itself. However, components like 1,8-cineole, often present in eucalyptus oil, are subject to concentration restrictions in Annex III of the EU Cosmetics Regulation for certain product types or concentrations when used as fragrance ingredients. PubChem notes that a lethal dose in children is reported to be 4-5 mL orally, highlighting a significant ingestion risk.", + "link_echa": "https://chem.echa.europa.eu/100.116.165/overview?searchText=8000-48-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/98790", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/8000-48-4", + "link_other": "" + }, + { + "name": "Zeolite", + "alternative_names": "", + "category": "Abrasive", + "benefits": "Aids in mechanical removal of plaque, Contributes to removal of surface stains for whitening, Assists in cleaning tooth surfaces", + "risks": "No specific oral/dental risks documented at typical use concentrations. General substance hazards noted in ECHA include potential for serious eye irritation (H319) and skin irritation (H315). Inhalation risks (H372, H334) are primarily relevant for occupational exposure to airborne particles and less for toothpaste use.", + "evidence_level": "Moderate", + "labeling_echa": "H372 (Causes damage to organs (lungs) through prolonged or repeated exposure (inhalation)), H319 (Causes serious eye irritation), H315 (Causes skin irritation), H334 (May cause allergy or asthma symptoms or breathing difficulties if inhaled)", + "safety_score": 8, + "regulatory_notes": "No specific restrictions identified for oral care products in CosIng. ECHA notes no harmonised classification, but individual notifications indicate potential hazards, primarily related to inhalation, skin, and eye exposure. No maximum concentration limits or specific warnings for oral care are listed.", + "link_echa": "https://chem.echa.europa.eu/100.110.564/overview?searchText=1318-02-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80740", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1318-02-1", + "link_other": "" + }, + { + "name": "sodium coco-sulfate", + "alternative_names": "Sulfuric acid, monococonut alkyl esters, sodium salts", + "category": "Surfactant", + "benefits": "Aids in cleansing and plaque removal, provides foaming for user experience, helps disperse ingredients", + "risks": "Potential for oral mucosa irritation, harmful if swallowed, potential for serious eye damage if splashed", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H315 (Causes skin irritation), H318 (Causes serious eye damage), H412 (Harmful to aquatic life with long lasting effects)", + "safety_score": 6, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.096.939/overview?searchText=97375-27-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37829", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/97375-27-4", + "link_other": "" + }, + { + "name": "Chamomilla Recutita (Matricaria) Flower Extract", + "alternative_names": "Matricaria recutita extract, German chamomile extract", + "category": "Antimicrobial", + "benefits": "Anti-inflammatory (soothes irritated gums and oral tissues), Antimicrobial (helps reduce oral bacteria), Antioxidant (protects oral cells from oxidative stress)", + "risks": "Harmful if swallowed, may cause serious eye irritation, potential for allergic reactions especially in individuals sensitive to Asteraceae family plants", + "evidence_level": "High", + "labeling_echa": "H302 (Harmful if swallowed), H319 (Causes serious eye irritation)", + "safety_score": 5, + "regulatory_notes": "No specific restrictions identified for the flower extract in CosIng database. However, H302 (Harmful if swallowed) classification from ECHA implies general safety considerations for oral products, especially regarding ingestion.", + "link_echa": "https://chem.echa.europa.eu/100.075.853/overview?searchText=84649-86-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/54548", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84649-86-5", + "link_other": "" + }, + { + "name": "citrus aurantium dulcis (orange) peel oil", + "alternative_names": "Orange Oil, Sweet Orange Oil", + "category": "Flavoring Agent", + "benefits": "Flavoring agent for improved taste, provides refreshing sensation, potential antimicrobial properties", + "risks": "Potential for oral mucosa irritation (H315), risk of allergic reactions/sensitization (H317), aspiration hazard if swallowed in significant, undiluted quantities (H304). Concentration-dependent effects may increase risks.", + "evidence_level": "High", + "labeling_echa": "H226 (Flammable liquid and vapour), H304 (May be fatal if swallowed and enters airways), H315 (Causes skin irritation), H317 (May cause an allergic skin reaction), H400 (Very toxic to aquatic life), H410 (Very toxic to aquatic life with long lasting effects)", + "safety_score": 5, + "regulatory_notes": "EU Cosmetics Regulation (EC) No 1223/2009 Annex III, entry 358: Maximum concentration for rinse-off products (including toothpaste) is 1.0% to avoid phototoxicity. Ingredient may require warnings regarding potential skin sensitization.", + "link_echa": "https://chem.echa.europa.eu/100.214.954/overview?searchText=84929-31-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/85121", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84929-31-7", + "link_other": "" + }, + { + "name": "Citral", + "alternative_names": "Geranial, Neral", + "category": "Flavoring Agent", + "benefits": "Provides a pleasant lemon/citrus flavor, imparts fresh aroma, improves product palatability", + "risks": "May cause allergic skin reactions (sensitization), causes skin irritation, causes serious eye irritation. Known to be an allergen, especially in sensitive individuals. Potential for oral irritation/allergic reactions, concentration-dependent concerns.", + "evidence_level": "High", + "labeling_echa": "H317 (May cause an allergic skin reaction), H315 (Causes skin irritation), H319 (Causes serious eye irritation)", + "safety_score": 5, + "regulatory_notes": "The presence of Citral must be indicated in the list of ingredients if its concentration exceeds 0.01% in rinse-off products (e.g., toothpaste). Banned for use when used as a mixture of flavouring substances or as a flavouring substance in concentrations exceeding the maximum levels (EU Cosmetics Regulation, Annex III/191).", + "link_echa": "https://chem.echa.europa.eu/100.023.994/overview?searchText=5392-40-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32857", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/5392-40-5", + "link_other": "" + }, + { + "name": "Hydroxypropyl methylcellulose", + "alternative_names": "HPMC, Hypromellose", + "category": "Thickener", + "benefits": "Controls toothpaste viscosity and texture, Binds ingredients for product stability, Forms a film for improved mouthfeel, Enhances ingredient dispersion", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.115.379/overview?searchText=9004-65-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34537", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9004-65-3", + "link_other": "" + }, + { + "name": "Disodium EDTA", + "alternative_names": "Disodium edetate, Ethylenediaminetetraacetic acid disodium salt", + "category": "Tartar Control Agent, Chelating Agent", + "benefits": "Tartar control (by chelating calcium ions), Product stabilization (prevents metal-catalyzed degradation), Enhances preservative efficacy", + "risks": "Potential for irritation or contact dermatitis in highly sensitive individuals; significant ingestion (beyond typical oral care use) may lead to gastrointestinal upset.", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 8, + "regulatory_notes": "Maximum allowed concentration of 1.3% in rinse-off products (e.g., toothpaste) as part of the broader 'EDTA and its salts' regulation (EU Cosmetics Regulation Annex III, Ref. 78).", + "link_echa": "https://chem.echa.europa.eu/100.004.872/overview?searchText=139-33-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/33604", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/139-33-3", + "link_other": "" + }, + { + "name": "Arginine", + "alternative_names": "L-Arginine", + "category": "Desensitizing Agent", + "benefits": "Reduces dentin hypersensitivity, Helps neutralize plaque acids, Supports remineralization of tooth enamel, Maintains oral moisture as a humectant", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.000.738/overview?searchText=74-79-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74314", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/74-79-3", + "link_other": "" + }, + { + "name": "Betaine", + "alternative_names": "Glycine betaine, Trimethylglycine", + "category": "Humectant", + "benefits": "Moisturizes oral tissues, Protects and soothes oral mucosa, Osmoprotectant", + "risks": "No significant risks documented at typical use concentrations. While some ECHA C&L notifications report eye irritation (H319) and skin irritation (H315), there is no harmonized classification, and the substance is generally considered to have low oral toxicity (LD50 > 10,000 mg/kg).", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.003.174/overview?searchText=107-43-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74520", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/107-43-7", + "link_other": "" + }, + { + "name": "OLEA EUROPAEA (OLIVE) LEAF EXTRACT", + "alternative_names": "Olive Leaf Extract", + "category": "Antimicrobial", + "benefits": "Antimicrobial properties (reduces oral bacteria), Anti-inflammatory effects (soothes gum irritation), Antioxidant activity (protects oral tissues)", + "risks": "No significant risks documented at typical use concentrations.", + "evidence_level": "Limited", + "labeling_echa": "None identified for OLEA EUROPAEA (OLIVE) LEAF EXTRACT. Note: The provided ECHA link refers to Linalool.", + "safety_score": 9, + "regulatory_notes": "No specific restrictions identified for OLEA EUROPAEA (OLIVE) LEAF EXTRACT in the provided CosIng data.", + "link_echa": "https://chem.echa.europa.eu/100.112.288/overview?searchText=8060-29-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/104139", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/8060-29-5#section=Structures", + "link_other": "" + }, + { + "name": "HYDROXYPROPYL METHYLCELLULOSE", + "alternative_names": "Hypromellose", + "category": "Thickener", + "benefits": "Improves toothpaste consistency and mouthfeel, Acts as a binding agent to maintain product stability and prevent ingredient separation, Contributes to the smooth flow and spreadability of toothpaste during brushing", + "risks": "No significant risks documented at typical use concentrations", + "evidence_level": "High", + "labeling_echa": "None identified", + "safety_score": 10, + "regulatory_notes": "No specific restrictions identified", + "link_echa": "https://chem.echa.europa.eu/100.115.379/overview?searchText=9004-65-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34537", + "link_pubchem": "", + "link_other": "" + } +] \ No newline at end of file diff --git a/src/parsers/raw_ingr_no_links.json b/src/parsers/raw_ingr_no_links.json new file mode 100644 index 0000000..4f06f1a --- /dev/null +++ b/src/parsers/raw_ingr_no_links.json @@ -0,0 +1,1157 @@ +[ + { + "name": "sodium fluoride", + "cas_number": "7681-49-4", + "link_echa": "https://chem.echa.europa.eu/100.028.789/overview?searchText=sodium%20fluoride", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/5235", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/87608" + }, + { + "name": "sorbitol", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "hydrated silica", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "peg-12", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium lauryl sulfate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "flavor", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "cellulose gum", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "potassium hydroxide", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "tetrasodium pyrophosphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "phosphoric acid", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "cocamidopropyl betaine", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium saccharin", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "benzyl alcohol", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "mica", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "blue 1", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "titanium dioxide", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "glycerin", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium bicarbonate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium hydroxide", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "xanthan gum", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "stannous fluoride", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "potassium nitrate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "yellow 10", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "xylitol", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "aroma", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium lauroyl sarcosinate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "ci 47005", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "ci 42051", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "limonene", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium benzoate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "dicalcium phosphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "hydroxyapatite (nano)", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "silica", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "peg-8", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "trimagnesium phosphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "hydrolyzed conchiolin protein", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "glycyrrhetinic acid", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "cetylpyridinium chloride", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "lauryl diethylenediaminoglycine hcl", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "pvp", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "butylene glycol", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "alcohol", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "pyridoxine hcl", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "camellia sinensis leaf extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "chamomillarecutilla extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "salvia officinalis leaf extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "alumina", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "peg-6", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "anise alcohol", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "pentasodium triphosphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "carbomer", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "eugenol", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "carrageenan", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "red 30", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "allantoin", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "panthenol", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "citric acid", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium chloride", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "glycolipids", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "stevia rebaudiana extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "maltodextrin", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "potassium sorbate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sorbic acid", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "ci 77268:1", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "peg-32", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "pvm/ma copolymer", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "zinc gluconate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "ci 77891", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "ci 74160", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "ci 74260", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "hydroxyethylcellulose", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "olaflur", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "peg-40 hydrogenated castor oil", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium saracchin", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "chitosan", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium gluconate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "stannous chloride", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sucralose", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "cinnamal", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "olaflur (amine fluoride)", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "water (aqua)", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "poloxamer 407", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "fd&c blue no. 1 (ci 42090)", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "fd&c yellow no. 5 (ci 19140)", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "calcium silicate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "trisodium phosphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium phosphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "peg-60", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "synthetic fluorphlogopite", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "polyacrylic acid", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "tin oxide", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sorbit", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "xylit", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "caolin clay", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "aloe barbensis (aloe vera) leaf juice", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium coco sulphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "mentha piperita leaf extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "salvia officinalis (sage) leaf extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "melissa officinalis leaf extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "salvadora persica bark/root extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "disodium cocoyl glutamate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "maris sal", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium cocoyl glutamate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium cocoyl glutamate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium hydroxyde", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium hexametaphosphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium citrate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "menthol", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "mentha viridis leaf oil", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "carvone", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "anethole", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "poloxamer 105", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "calcium pyrophosphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "peg/ppg-116/66 copolymer", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "potassium caroate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "disodium pyrophosphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "magnesium carbonate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium monofluorophosphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "calcium carbonate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "tetrapotassium pyrophosphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium methyl cocoyl taurate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "ci 73360", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "propylene glycol", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "zinc lactate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "lauryl glucoside", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "zinc citrate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "papain", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "bromelain", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "glyceryl caprylate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "mentha arvensis leaf oil", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "mentha piperita oil", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "calcium glycerophosphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "stevia rebaudiana leaf/stem extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "caprylhydroxamic acid", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "lactobacillus lysate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium metabisulfite", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "steviol glycosides", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "linalool", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "cl 77492", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "potassium citrate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "ci 77491", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "aloe barbadensis leaf extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "commiphora myrrha gum oil", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "mentha arvensis oil", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "magnolia officinalis bark extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "magnesium aluminium silicate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "phenoxyethanol", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "potassium chloride", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium sulphate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "stevioside", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "acacia senegal gum", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "lactobacillus", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "eucalyptus oil", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "zeolite", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "sodium coco-sulfate", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "chamomilla recutita (matricaria) flower extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "citrus aurantium dulcis (orange) peel oil", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "zingiber officinale (ginger) root extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "citral", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "hydroxypropyl methyl cellulose", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "disodium edta", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "arginine", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "betaine", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "olive leaf extract", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + }, + { + "name": "hydroxypropyl methylcellulose", + "cas_number": null, + "link_echa": null, + "link_pubchem": null, + "link_cosIng": null + } +] \ No newline at end of file diff --git a/src/parsers/raw_ingr_with_links.json b/src/parsers/raw_ingr_with_links.json new file mode 100644 index 0000000..c5264fe --- /dev/null +++ b/src/parsers/raw_ingr_with_links.json @@ -0,0 +1,1073 @@ +[ + { + "name": "sodium fluoride", + "cas_number": "7681-49-4", + "link_echa": "https://chem.echa.europa.eu/substance-search?searchText=7681-49-4", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7681-49-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37869" + }, + { + "name": "sorbitol", + "cas_number": "50-70-4", + "link_echa": "https://chem.echa.europa.eu/100.000.056/overview?searchText=50-70-4", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/50-70-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38191" + }, + { + "name": "hydrated silica", + "cas_number": "10279-57-9", + "link_echa": "https://chem.echa.europa.eu/100.130.425/overview?searchText=10279-57-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/10279-57-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/76428" + }, + { + "name": "peg-12", + "cas_number": "6790-09-6", + "link_echa": "https://chem.echa.europa.eu/100.027.145/overview?searchText=6790-09-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/6790-09-6", + "link_cosIng": null + }, + { + "name": "sodium lauryl sulfate", + "cas_number": "151-21-3", + "link_echa": "https://chem.echa.europa.eu/100.005.263/overview?searchText=151-21-3", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/151-21-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37946" + }, + { + "name": "cellulose gum", + "cas_number": "9000-11-7", + "link_echa": "https://chem.echa.europa.eu/100.120.377/overview?searchText=9000-11-7", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9000-11-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/75394" + }, + { + "name": "potassium hydroxide", + "cas_number": "1310-58-3", + "link_echa": "https://chem.echa.europa.eu/100.013.802/overview?searchText=1310-58-3", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1310-58-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36981" + }, + { + "name": "tetrasodium pyrophosphate", + "cas_number": "7722-88-5", + "link_echa": "https://chem.echa.europa.eu/100.028.880/overview?searchText=7722-88-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7722-88-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38571" + }, + { + "name": "phosphoric acid", + "cas_number": "7664-38-2", + "link_echa": "https://chem.echa.europa.eu/100.118.962/overview?searchText=7664-38-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7664-38-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36546" + }, + { + "name": "cocamidopropyl betaine", + "cas_number": "61789-40-0", + "link_echa": "https://chem.echa.europa.eu/100.213.335/overview?searchText=61789-40-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/61789-40-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/75231" + }, + { + "name": "sodium saccharin", + "cas_number": "128-44-9", + "link_echa": "https://chem.echa.europa.eu/100.004.443/overview?searchText=128-44-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/128-44-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80014" + }, + { + "name": "benzyl alcohol", + "cas_number": "100-51-6", + "link_echa": "https://chem.echa.europa.eu/100.002.600/overview?searchText=100-51-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/100-51-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32153" + }, + { + "name": "mica", + "cas_number": "12001-26-2", + "link_echa": "https://chem.echa.europa.eu/100.123.963/overview?searchText=12001-26-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/12001-26-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35360" + }, + { + "name": "blue 1", + "cas_number": "3844-45-9", + "link_echa": "https://chem.echa.europa.eu/100.513.043/overview?searchText=3844-45-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/3844-45-9", + "link_cosIng": null + }, + { + "name": "titanium dioxide", + "cas_number": "13463-67-7", + "link_echa": "https://chem.echa.europa.eu/100.033.327/overview?searchText=13463-67-7", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/13463-67-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/97726" + }, + { + "name": "glycerin", + "cas_number": "56-81-5", + "link_echa": "https://chem.echa.europa.eu/100.000.263/overview?searchText=56-81-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/56-81-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34040" + }, + { + "name": "sodium bicarbonate", + "cas_number": "144-55-8", + "link_echa": "https://chem.echa.europa.eu/100.005.122/overview?searchText=144-55-8", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/144-55-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37736" + }, + { + "name": "sodium hydroxide", + "cas_number": "1310-73-2", + "link_echa": "https://chem.echa.europa.eu/100.013.805/overview?searchText=1310-73-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1310-73-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37890" + }, + { + "name": "xanthan gum", + "cas_number": "11138-66-2", + "link_echa": "https://chem.echa.europa.eu/100.031.255/overview?searchText=11138-66-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/11138-66-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80699" + }, + { + "name": "stannous fluoride", + "cas_number": "7783-47-3", + "link_echa": "https://chem.echa.europa.eu/100.029.090/overview?searchText=7783-47-3", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7783-47-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38231" + }, + { + "name": "potassium nitrate", + "cas_number": "7757-79-1", + "link_echa": "https://chem.echa.europa.eu/100.028.926/overview?searchText=7757-79-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7757-79-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37002" + }, + { + "name": "yellow 10", + "cas_number": "8004-92-0", + "link_echa": "https://chem.echa.europa.eu/100.116.526/overview?searchText=8004-92-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/8004-92-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/100075" + }, + { + "name": "xylitol", + "cas_number": "87-99-0", + "link_echa": "https://chem.echa.europa.eu/100.001.626/overview?searchText=87-99-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/87-99-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38920" + }, + { + "name": "sodium lauroyl sarcosinate", + "cas_number": "137-16-6", + "link_echa": "https://chem.echa.europa.eu/100.004.801/overview?searchText=137-16-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/137-16-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37941" + }, + { + "name": "ci 47005", + "cas_number": "8004-92-0", + "link_echa": "https://chem.echa.europa.eu/100.116.526/overview?searchText=8004-92-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/8004-92-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/100075" + }, + { + "name": "ci 42051", + "cas_number": "3536-49-0", + "link_echa": "https://chem.echa.europa.eu/100.020.522/overview?searchText=3536-49-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/3536-49-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32753" + }, + { + "name": "limonene", + "cas_number": "5989-27-5", + "link_echa": "https://chem.echa.europa.eu/100.025.284/overview?searchText=5989-27-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/5989-27-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/87624" + }, + { + "name": "sodium benzoate", + "cas_number": "532-32-1", + "link_echa": "https://chem.echa.europa.eu/100.007.760/overview?searchText=532-32-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/532-32-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37735" + }, + { + "name": "dicalcium phosphate", + "cas_number": "7757-93-9", + "link_echa": "https://chem.echa.europa.eu/100.028.933/overview?searchText=7757-93-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7757-93-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/75666" + }, + { + "name": "hydroxyapatite (nano)", + "cas_number": "1306-06-5", + "link_echa": "https://chem.echa.europa.eu/100.013.769/overview?searchText=1306-06-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1306-06-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34479" + }, + { + "name": "silica", + "cas_number": "7631-86-9", + "link_echa": "https://chem.echa.europa.eu/100.171.064/overview?searchText=7631-86-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7631-86-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/78845" + }, + { + "name": "peg-8", + "cas_number": "25322-68-3", + "link_echa": null, + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/25322-68-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/77303" + }, + { + "name": "trimagnesium phosphate", + "cas_number": "7757-87-1", + "link_echa": "https://chem.echa.europa.eu/100.028.931/overview?searchText=7757-87-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7757-87-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38739" + }, + { + "name": "hydrolyzed conchiolin protein", + "cas_number": "169590-57-2", + "link_echa": null, + "link_pubchem": null, + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/56554" + }, + { + "name": "glycyrrhetinic acid", + "cas_number": "471-53-4", + "link_echa": "https://chem.echa.europa.eu/100.006.769/overview?searchText=471-53-4", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/471-53-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34152" + }, + { + "name": "cetylpyridinium chloride", + "cas_number": "123-03-5", + "link_echa": "https://chem.echa.europa.eu/100.004.177/overview?searchText=123-03-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/123-03-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32626" + }, + { + "name": "lauryl diethylenediaminoglycine hcl", + "cas_number": "18205-85-1", + "link_echa": "https://chem.echa.europa.eu/100.038.253/overview?searchText=18205-85-1", + "link_pubchem": null, + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/56963" + }, + { + "name": "pvp", + "cas_number": "9003-39-8", + "link_echa": "https://chem.echa.europa.eu/100.184.844/overview?searchText=9003-39-8", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9003-39-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37364" + }, + { + "name": "butylene glycol", + "cas_number": "107-88-0", + "link_echa": "https://chem.echa.europa.eu/100.003.209/overview?searchText=107-88-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/107-88-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74756" + }, + { + "name": "alcohol", + "cas_number": "64-17-5", + "link_echa": "https://chem.echa.europa.eu/100.000.526/overview?searchText=64-17-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/64-17-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/31401" + }, + { + "name": "pyridoxine hcl", + "cas_number": "58-56-0", + "link_echa": "https://chem.echa.europa.eu/100.000.351/overview?searchText=58-56-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/58-56-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37388" + }, + { + "name": "camellia sinensis leaf extract", + "cas_number": "84650-60-2", + "link_echa": "https://chem.echa.europa.eu/100.141.452/overview?searchText=84650-60-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84650-60-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/55224" + }, + { + "name": "chamomillarecutilla extract", + "cas_number": "84082-60-0", + "link_echa": "https://chem.echa.europa.eu/100.074.527/overview?searchText=84082-60-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84082-60-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/55295" + }, + { + "name": "salvia officinalis leaf extract", + "cas_number": "84082-79-1", + "link_echa": "https://chem.echa.europa.eu/100.074.545/overview?searchText=84082-79-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84082-79-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80200" + }, + { + "name": "alumina", + "cas_number": "1344-28-1", + "link_echa": "https://chem.echa.europa.eu/100.207.718/overview?searchText=1344-28-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1344-28-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74191" + }, + { + "name": "peg-6", + "cas_number": "25322-68-3", + "link_echa": null, + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/25322-68-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/77118" + }, + { + "name": "anise alcohol", + "cas_number": "105-13-5", + "link_echa": "https://chem.echa.europa.eu/100.002.976/overview?searchText=105-13-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/105-13-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74308" + }, + { + "name": "pentasodium triphosphate", + "cas_number": "7758-29-4", + "link_echa": "https://chem.echa.europa.eu/100.028.944/overview?searchText=7758-29-4", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7758-29-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36486" + }, + { + "name": "carbomer", + "cas_number": "9007-20-9", + "link_echa": "https://chem.echa.europa.eu/100.113.198/overview?searchText=9007-20-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9007-20-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74820" + }, + { + "name": "eugenol", + "cas_number": "97-53-0", + "link_echa": "https://chem.echa.europa.eu/100.002.355/overview?searchText=97-53-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/97-53-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/33910" + }, + { + "name": "carrageenan", + "cas_number": "9000-07-1", + "link_echa": "https://chem.echa.europa.eu/100.029.556/overview?searchText=9000-07-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9000-07-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/88730" + }, + { + "name": "red 30", + "cas_number": "5858-81-1", + "link_echa": "https://chem.echa.europa.eu/100.024.998/overview?searchText=5858-81-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/5858-81-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/93730" + }, + { + "name": "allantoin", + "cas_number": "97-59-6", + "link_echa": "https://chem.echa.europa.eu/100.002.358/overview?searchText=97-59-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/97-59-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/31411" + }, + { + "name": "panthenol", + "cas_number": "81-13-0", + "link_echa": "https://chem.echa.europa.eu/100.001.208/overview?searchText=81-13-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/81-13-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35839" + }, + { + "name": "citric acid", + "cas_number": "77-92-9", + "link_echa": "https://chem.echa.europa.eu/100.205.812/overview?searchText=77-92-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/77-92-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32858" + }, + { + "name": "sodium chloride", + "cas_number": "7647-14-5", + "link_echa": "https://chem.echa.europa.eu/100.028.726/overview?searchText=sodium%20chloride", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7647-14-5", + "link_cosIng": null + }, + { + "name": "stevia rebaudiana extract", + "cas_number": "91722-21-3", + "link_echa": "https://chem.echa.europa.eu/100.085.803/overview?searchText=91722-21-3", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/91722-21-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/58821" + }, + { + "name": "maltodextrin", + "cas_number": "9050-36-6", + "link_echa": "https://chem.echa.europa.eu/100.029.934/overview?searchText=9050-36-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9050-36-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35142" + }, + { + "name": "potassium sorbate", + "cas_number": "24634-61-5", + "link_echa": "https://chem.echa.europa.eu/100.205.816/overview?searchText=24634-61-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/24634-61-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37025" + }, + { + "name": "sorbic acid", + "cas_number": "110-44-1", + "link_echa": "https://chem.echa.europa.eu/100.003.427/overview?searchText=110-44-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/110-44-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38173" + }, + { + "name": "ci 77268:1", + "cas_number": "1339-82-8", + "link_echa": "https://chem.echa.europa.eu/100.014.245/overview?searchText=1339-82-8", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1339-82-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32822" + }, + { + "name": "peg-32", + "cas_number": "25322-68-3", + "link_echa": "https://chem.echa.europa.eu/100.167.649/overview?searchText=25322-68-3", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/25322-68-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/78305" + }, + { + "name": "pvm/ma copolymer", + "cas_number": "9011-16-9", + "link_echa": "https://chem.echa.europa.eu/100.111.639/overview?searchText=9011-16-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9011-16-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/79129" + }, + { + "name": "zinc gluconate", + "cas_number": "4468-02-6", + "link_echa": "https://chem.echa.europa.eu/100.022.489/overview?searchText=zinc%20gluconate", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/4468-02-6", + "link_cosIng": null + }, + { + "name": "ci 77891", + "cas_number": "13463-67-7", + "link_echa": "https://chem.echa.europa.eu/100.171.063/overview?searchText=13463-67-7", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/13463-67-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/97171" + }, + { + "name": "ci 74160", + "cas_number": "147-14-8", + "link_echa": "https://chem.echa.europa.eu/100.005.169/overview?searchText=147-14-8", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/147-14-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32799" + }, + { + "name": "ci 74260", + "cas_number": "6373-74-6", + "link_echa": "https://chem.echa.europa.eu/100.026.292/overview?searchText=6373-74-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/6373-74-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/31618" + }, + { + "name": "hydroxyethylcellulose", + "cas_number": "9004-62-0", + "link_echa": "https://chem.echa.europa.eu/100.116.562/overview?searchText=9004-62-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9004-62-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/76845" + }, + { + "name": "olaflur", + "cas_number": "6818-37-7", + "link_echa": "https://chem.echa.europa.eu/100.027.174/overview?searchText=6818-37-7", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/6818-37-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35640" + }, + { + "name": "peg-40 hydrogenated castor oil", + "cas_number": "61788-85-0", + "link_echa": "https://chem.echa.europa.eu/100.105.643/overview?searchText=61788-85-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/61788-85-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/78452" + }, + { + "name": "sodium saracchin", + "cas_number": "128-44-9", + "link_echa": "https://chem.echa.europa.eu/100.004.443/overview?searchText=128-44-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/128-44-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80014" + }, + { + "name": "chitosan", + "cas_number": "9012-76-4", + "link_echa": "https://chem.echa.europa.eu/100.122.259/overview?searchText=9012-76-4", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9012-76-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/75065" + }, + { + "name": "sodium gluconate", + "cas_number": "527-07-1", + "link_echa": "https://chem.echa.europa.eu/100.220.571/overview?searchText=527-07-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/527-07-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/79485" + }, + { + "name": "stannous chloride", + "cas_number": "7772-99-8", + "link_echa": "https://chem.echa.europa.eu/100.028.971/overview?searchText=7772-99-8", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7772-99-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38230" + }, + { + "name": "sucralose", + "cas_number": "56038-13-2", + "link_echa": "https://chem.echa.europa.eu/100.054.484/overview?searchText=56038-13-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/56038-13-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/59924" + }, + { + "name": "cinnamal", + "cas_number": "104-55-2", + "link_echa": "https://chem.echa.europa.eu/100.002.922/overview?searchText=104-55-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/104-55-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32846" + }, + { + "name": "water (aqua)", + "cas_number": "7732-18-5", + "link_echa": "https://chem.echa.europa.eu/100.205.267/overview?searchText=7732-18-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7732-18-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/92472" + }, + { + "name": "poloxamer 407", + "cas_number": "9003-11-6", + "link_echa": "https://chem.echa.europa.eu/substance-search?searchText=9003-11-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9003-11-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36666" + }, + { + "name": "fd&c blue no. 1 (ci 42090)", + "cas_number": "3844-45-9", + "link_echa": "https://chem.echa.europa.eu/100.021.219/overview?searchText=3844-45-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/3844-45-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32756" + }, + { + "name": "fd&c yellow no. 5 (ci 19140)", + "cas_number": "1934-21-0", + "link_echa": "https://chem.echa.europa.eu/100.512.755/overview?searchText=1934-21-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1934-21-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32737" + }, + { + "name": "calcium silicate", + "cas_number": "1344-95-2", + "link_echa": "https://chem.echa.europa.eu/100.014.282/overview?searchText=1344-95-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1344-95-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32345" + }, + { + "name": "trisodium phosphate", + "cas_number": "7601-54-9", + "link_echa": "https://chem.echa.europa.eu/100.028.645/overview?searchText=7601-54-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7601-54-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38776" + }, + { + "name": "sodium phosphate", + "cas_number": "7601-54-9", + "link_echa": "https://chem.echa.europa.eu/100.028.645/overview?searchText=7601-54-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7601-54-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38776" + }, + { + "name": "peg-60", + "cas_number": "61788-85-0", + "link_echa": "https://chem.echa.europa.eu/100.105.643/overview?searchText=61788-85-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/61788-85-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/77219" + }, + { + "name": "synthetic fluorphlogopite", + "cas_number": "12003-38-2", + "link_echa": "https://chem.echa.europa.eu/100.031.283/overview?searchText=12003-38-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/12003-38-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80520" + }, + { + "name": "polyacrylic acid", + "cas_number": "9003-01-4", + "link_echa": "https://chem.echa.europa.eu/100.115.375/overview?searchText=9003-01-4", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9003-01-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/78561" + }, + { + "name": "tin oxide", + "cas_number": "18282-10-5", + "link_echa": "https://chem.echa.europa.eu/100.038.311/overview?searchText=18282-10-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/18282-10-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80260" + }, + { + "name": "sorbit", + "cas_number": "50-70-4", + "link_echa": "https://chem.echa.europa.eu/100.000.056/overview?searchText=50-70-4", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/50-70-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38191" + }, + { + "name": "caolin clay", + "cas_number": "1332-58-7", + "link_echa": "https://chem.echa.europa.eu/100.100.108/overview?searchText=1332-58-7", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1332-58-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34795" + }, + { + "name": "aloe barbensis (aloe vera) leaf juice", + "cas_number": " 85507-69-3 / 94349-62-9 ", + "link_echa": "https://chem.echa.europa.eu/100.079.418/overview?searchText=85507-69-3", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/85507-69-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/54347" + }, + { + "name": "sodium coco sulphate", + "cas_number": "68955-19-1", + "link_echa": "https://chem.echa.europa.eu/100.066.578/overview?searchText=68955-19-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68955-19-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37946" + }, + { + "name": "melissa officinalis leaf extract", + "cas_number": "84082-61-1", + "link_echa": "https://chem.echa.europa.eu/100.074.528/overview?searchText=84082-61-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84082-61-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35212" + }, + { + "name": "disodium cocoyl glutamate", + "cas_number": "68187-30-4", + "link_echa": "https://chem.echa.europa.eu/100.062.785/overview?searchText=%0968187-30-4%20", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68187-30-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/75827" + }, + { + "name": "maris sal", + "cas_number": "7647-14-5", + "link_echa": "https://chem.echa.europa.eu/100.028.726/overview?searchText=7647-14-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7647-14-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37813" + }, + { + "name": "sodium cocoyl glutamate", + "cas_number": "68187-32-6", + "link_echa": "https://chem.echa.europa.eu/100.062.787/overview?searchText=68187-32-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68187-32-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37832" + }, + { + "name": "sodium cocoyl glutamate", + "cas_number": "68187-32-6", + "link_echa": "https://chem.echa.europa.eu/100.062.787/overview?searchText=68187-32-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68187-32-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37832" + }, + { + "name": "sodium hydroxyde", + "cas_number": "1310-73-2", + "link_echa": "https://chem.echa.europa.eu/100.013.805/overview?searchText=1310-73-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1310-73-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37890" + }, + { + "name": "sodium hexametaphosphate", + "cas_number": "10124-56-8", + "link_echa": "https://chem.echa.europa.eu/100.214.884/overview?searchText=10124-56-8", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/10124-56-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/79493" + }, + { + "name": "sodium citrate", + "cas_number": "68-04-2", + "link_echa": "https://chem.echa.europa.eu/100.000.614/overview?searchText=68-04-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68-04-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37816" + }, + { + "name": "menthol", + "cas_number": "89-78-1", + "link_echa": "https://chem.echa.europa.eu/100.001.763/overview?searchText=89-78-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/89-78-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35228" + }, + { + "name": "mentha viridis leaf oil", + "cas_number": "84696-51-5", + "link_echa": "https://chem.echa.europa.eu/100.076.023/overview?searchText=84696-51-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84696-51-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/57942" + }, + { + "name": "carvone", + "cas_number": "99-49-0", + "link_echa": "https://chem.echa.europa.eu/100.002.508/overview?searchText=99-49-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/99-49-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74838" + }, + { + "name": "anethole", + "cas_number": "104-46-1", + "link_echa": "https://chem.echa.europa.eu/100.002.914/overview?searchText=104-46-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/104-46-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74302" + }, + { + "name": "poloxamer 105", + "cas_number": "9003-11-6", + "link_echa": "https://chem.echa.europa.eu/100.118.740/overview?searchText=9003-11-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9003-11-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80123" + }, + { + "name": "calcium pyrophosphate", + "cas_number": "7790-76-3", + "link_echa": "https://chem.echa.europa.eu/100.029.292/overview?searchText=7790-76-3", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7790-76-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74915" + }, + { + "name": "peg/ppg-116/66 copolymer", + "cas_number": "9003-11-6", + "link_echa": "https://chem.echa.europa.eu/100.118.740/overview?searchText=9003-11-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9003-11-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/57106" + }, + { + "name": "potassium caroate", + "cas_number": "10058-23-8", + "link_echa": "https://chem.echa.europa.eu/100.030.158/overview?searchText=10058-23-8", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/10058-23-8", + "link_cosIng": null + }, + { + "name": "disodium pyrophosphate", + "cas_number": "7758-16-9", + "link_echa": "https://chem.echa.europa.eu/100.028.941/overview?searchText=7758-16-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7758-16-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/75795" + }, + { + "name": "magnesium carbonate", + "cas_number": "546-93-0", + "link_echa": "https://chem.echa.europa.eu/100.008.106/overview?searchText=546-93-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/546-93-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/77618" + }, + { + "name": "sodium monofluorophosphate", + "cas_number": "10163-15-2", + "link_echa": "https://chem.echa.europa.eu/100.030.381/overview?searchText=10163-15-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/10163-15-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/87604" + }, + { + "name": "calcium carbonate", + "cas_number": "471-34-1", + "link_echa": "https://chem.echa.europa.eu/100.006.765/overview?searchText=471-34-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/471-34-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32314" + }, + { + "name": "tetrapotassium pyrophosphate", + "cas_number": "7320-34-5", + "link_echa": "https://chem.echa.europa.eu/100.027.986/overview?searchText=7320-34-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7320-34-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80751" + }, + { + "name": "sodium methyl cocoyl taurate", + "cas_number": "12765-39-8", + "link_echa": "https://chem.echa.europa.eu/100.123.200/overview?searchText=12765-39-8", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/12765-39-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/79777" + }, + { + "name": "ci 73360", + "cas_number": "2379-74-0", + "link_echa": "https://chem.echa.europa.eu/100.017.422/overview?searchText=2379-74-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/2379-74-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32794" + }, + { + "name": "propylene glycol", + "cas_number": "57-55-6", + "link_echa": "https://chem.echa.europa.eu/100.417.077/overview?searchText=57-55-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/57-55-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37269" + }, + { + "name": "zinc lactate", + "cas_number": "16039-53-5", + "link_echa": "https://chem.echa.europa.eu/100.036.510/overview?searchText=16039-53-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/16039-53-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38964" + }, + { + "name": "lauryl glucoside", + "cas_number": "110615-47-9", + "link_echa": "https://chem.echa.europa.eu/100.123.133/overview?searchText=110615-47-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/110615-47-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/56967" + }, + { + "name": "zinc citrate", + "cas_number": "5990-32-9", + "link_echa": "https://chem.echa.europa.eu/100.121.410/overview?searchText=5990-32-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/5990-32-9", + "link_cosIng": null + }, + { + "name": "papain", + "cas_number": "9001-73-4", + "link_echa": "https://chem.echa.europa.eu/100.029.649/overview?searchText=9001-73-4", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9001-73-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35846" + }, + { + "name": "bromelain", + "cas_number": "9001-00-7", + "link_echa": "https://chem.echa.europa.eu/100.029.599/overview?searchText=9001-00-7", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9001-00-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/54967" + }, + { + "name": "glyceryl caprylate", + "cas_number": "26402-26-6", + "link_echa": "https://chem.echa.europa.eu/100.043.320/overview?searchText=26402-26-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/26402-26-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34049" + }, + { + "name": "mentha arvensis leaf oil", + "cas_number": "90063-97-1", + "link_echa": "https://chem.echa.europa.eu/100.081.839/overview?searchText=90063-97-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/90063-97-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/96196" + }, + { + "name": "mentha piperita oil", + "cas_number": "8006-81-3", + "link_echa": "https://chem.echa.europa.eu/100.126.669/overview?searchText=8006-81-3", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/8006-81-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/86971" + }, + { + "name": "calcium glycerophosphate", + "cas_number": "27214-00-2", + "link_echa": "https://chem.echa.europa.eu/100.043.920/overview?searchText=27214-00-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/27214-00-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74900" + }, + { + "name": "stevia rebaudiana leaf/stem extract", + "cas_number": "91722-21-3", + "link_echa": "https://chem.echa.europa.eu/100.085.803/overview?searchText=91722-21-3", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/139174-88-8", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/58821" + }, + { + "name": "caprylhydroxamic acid", + "cas_number": "7377-03-9", + "link_echa": "https://chem.echa.europa.eu/100.028.124/overview?searchText=7377-03-9", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7377-03-9", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/86262" + }, + { + "name": "sodium metabisulfite", + "cas_number": "7681-57-4", + "link_echa": "https://chem.echa.europa.eu/100.028.991/overview?searchText=7681-57-4", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7681-57-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37956" + }, + { + "name": "steviol glycosides", + "cas_number": "57817-89-7", + "link_echa": "https://chem.echa.europa.eu/100.055.414/overview?searchText=57817-89-7", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/57817-89-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/79199" + }, + { + "name": "linalool", + "cas_number": "78-70-6", + "link_echa": "https://chem.echa.europa.eu/100.001.032/overview?searchText=78-70-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/78-70-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35016" + }, + { + "name": "cl 77492", + "cas_number": "51274-00-1", + "link_echa": "https://chem.echa.europa.eu/100.051.890/overview?searchText=51274-00-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/51274-00-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/31177" + }, + { + "name": "potassium citrate", + "cas_number": "866-84-2", + "link_echa": "https://chem.echa.europa.eu/100.011.596/overview?searchText=866-84-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/866-84-2", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36949" + }, + { + "name": "ci 77491", + "cas_number": "1309-37-1", + "link_echa": "https://chem.echa.europa.eu/100.013.790/overview?searchText=1309-37-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1309-37-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32829" + }, + { + "name": "aloe barbadensis leaf extract", + "cas_number": "85507-69-3", + "link_echa": "https://chem.echa.europa.eu/100.079.418/overview?searchText=85507-69-3", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/85507-69-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/54346" + }, + { + "name": "mentha arvensis oil", + "cas_number": "68917-18-0", + "link_echa": "https://chem.echa.europa.eu/100.111.474/overview?searchText=68917-18-0", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68917-18-0", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/57860" + }, + { + "name": "magnesium aluminium silicate", + "cas_number": "1327-43-1", + "link_echa": "https://chem.echa.europa.eu/100.014.072/overview?searchText=1327-43-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1327-43-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/35080" + }, + { + "name": "phenoxyethanol", + "cas_number": "122-99-6", + "link_echa": "https://chem.echa.europa.eu/100.004.173/overview?searchText=122-99-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/122-99-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36522" + }, + { + "name": "potassium chloride", + "cas_number": "7447-40-7", + "link_echa": "https://chem.echa.europa.eu/100.207.258/overview?searchText=7447-40-7", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7447-40-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/36948" + }, + { + "name": "sodium sulphate", + "cas_number": "7757-82-6", + "link_echa": "https://chem.echa.europa.eu/100.215.944/overview?searchText=7757-82-6", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/7757-82-6", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/38093" + }, + { + "name": "stevioside", + "cas_number": "57817-89-7", + "link_echa": "https://chem.echa.europa.eu/100.055.414/overview?searchText=57817-89-7", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/57817-89-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/79199" + }, + { + "name": "acacia senegal gum", + "cas_number": "9000-01-5", + "link_echa": "https://chem.echa.europa.eu/100.029.551/overview?searchText=9000-01-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9000-01-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/54244" + }, + { + "name": "lactobacillus", + "cas_number": "68333-14-2", + "link_echa": "https://chem.echa.europa.eu/100.110.946/overview?searchText=68333-14-2", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/68333-14-2", + "link_cosIng": null + }, + { + "name": "eucalyptus oil", + "cas_number": "8000-48-4", + "link_echa": "https://chem.echa.europa.eu/100.116.165/overview?searchText=8000-48-4", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/8000-48-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/98790" + }, + { + "name": "zeolite", + "cas_number": "1318-02-1", + "link_echa": "https://chem.echa.europa.eu/100.110.564/overview?searchText=1318-02-1", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/1318-02-1", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/80740" + }, + { + "name": "sodium coco-sulfate", + "cas_number": "97375-27-4", + "link_echa": "https://chem.echa.europa.eu/100.096.939/overview?searchText=97375-27-4", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/97375-27-4", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/37829" + }, + { + "name": "chamomilla recutita (matricaria) flower extract", + "cas_number": "84649-86-5", + "link_echa": "https://chem.echa.europa.eu/100.075.853/overview?searchText=84649-86-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84649-86-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/54548" + }, + { + "name": "citrus aurantium dulcis (orange) peel oil", + "cas_number": "84929-31-7", + "link_echa": "https://chem.echa.europa.eu/100.214.954/overview?searchText=84929-31-7", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/84929-31-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/85121" + }, + { + "name": "citral", + "cas_number": "5392-40-5", + "link_echa": "https://chem.echa.europa.eu/100.023.994/overview?searchText=5392-40-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/5392-40-5", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/32857" + }, + { + "name": "hydroxypropyl methyl cellulose", + "cas_number": "9004-65-3", + "link_echa": "https://chem.echa.europa.eu/100.115.379/overview?searchText=9004-65-3", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/9004-65-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34537" + }, + { + "name": "disodium edta", + "cas_number": "139-33-3", + "link_echa": "https://chem.echa.europa.eu/100.004.872/overview?searchText=139-33-3", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/139-33-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/33604" + }, + { + "name": "arginine", + "cas_number": "74-79-3", + "link_echa": "https://chem.echa.europa.eu/100.000.738/overview?searchText=74-79-3", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/74-79-3", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74314" + }, + { + "name": "betaine", + "cas_number": "107-43-7", + "link_echa": "https://chem.echa.europa.eu/100.003.174/overview?searchText=107-43-7", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/107-43-7", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/74520" + }, + { + "name": "olive leaf extract", + "cas_number": "8060-29-5", + "link_echa": "https://chem.echa.europa.eu/100.112.288/overview?searchText=8060-29-5", + "link_pubchem": "https://pubchem.ncbi.nlm.nih.gov/compound/8060-29-5#section=Structures", + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/104139" + }, + { + "name": "hydroxypropyl methylcellulose", + "cas_number": "9004-65-3", + "link_echa": "https://chem.echa.europa.eu/100.115.379/overview?searchText=9004-65-3", + "link_pubchem": null, + "link_cosIng": "https://ec.europa.eu/growth/tools-databases/cosing/details/34537" + } +] \ No newline at end of file diff --git a/src/parsers/raw_unique_ingredients.txt b/src/parsers/raw_unique_ingredients.txt new file mode 100644 index 0000000..bb1343c --- /dev/null +++ b/src/parsers/raw_unique_ingredients.txt @@ -0,0 +1,164 @@ +sodium fluoride +sorbitol +hydrated silica +peg-12 +sodium lauryl sulfate +flavor +cellulose gum +potassium hydroxide +tetrasodium pyrophosphate +phosphoric acid +cocamidopropyl betaine +sodium saccharin +benzyl alcohol +mica +blue 1 +titanium dioxide +glycerin +sodium bicarbonate +sodium hydroxide +xanthan gum +stannous fluoride +potassium nitrate +yellow 10 +xylitol +aroma +sodium lauroyl sarcosinate +ci 47005 +ci 42051 +limonene +sodium benzoate +dicalcium phosphate +hydroxyapatite (nano) +silica +peg-8 +trimagnesium phosphate +hydrolyzed conchiolin protein +glycyrrhetinic acid +cetylpyridinium chloride +lauryl diethylenediaminoglycine hcl +pvp +butylene glycol +alcohol +pyridoxine hcl +camellia sinensis leaf extract +chamomillarecutilla extract +salvia officinalis leaf extract +alumina +peg-6 +anise alcohol +pentasodium triphosphate +carbomer +eugenol +carrageenan +red 30 +allantoin +panthenol +citric acid +sodium chloride +glycolipids +stevia rebaudiana extract +maltodextrin +potassium sorbate +sorbic acid +ci 77268:1 +peg-32 +pvm/ma copolymer +zinc gluconate +ci 77891 +ci 74160 +ci 74260 +hydroxyethylcellulose +olaflur +peg-40 hydrogenated castor oil +sodium saracchin +chitosan +sodium gluconate +stannous chloride +sucralose +cinnamal +olaflur (amine fluoride) +water (aqua) +poloxamer 407 +fd&c blue no. 1 (ci 42090) +fd&c yellow no. 5 (ci 19140) +calcium silicate +trisodium phosphate +sodium phosphate +peg-60 +synthetic fluorphlogopite +polyacrylic acid +tin oxide +sorbit +xylit +caolin clay +aloe barbensis (aloe vera) leaf juice +sodium coco sulphate +mentha piperita leaf extract +salvia officinalis (sage) leaf extract +melissa officinalis leaf extract +salvadora persica bark/root extract +disodium cocoyl glutamate +maris sal +sodium cocoyl glutamate +sodium hydroxyde +sodium hexametaphosphate +sodium citrate +menthol +mentha viridis leaf oil +carvone +anethole +poloxamer 105 +calcium pyrophosphate +peg/ppg-116/66 copolymer +potassium caroate +disodium pyrophosphate +magnesium carbonate +sodium monofluorophosphate +calcium carbonate +tetrapotassium pyrophosphate +sodium methyl cocoyl taurate +ci 73360 +propylene glycol +zinc lactate +lauryl glucoside +zinc citrate +papain +bromelain +glyceryl caprylate +mentha arvensis leaf oil +mentha piperita oil +calcium glycerophosphate +stevia rebaudiana leaf/stem extract +caprylhydroxamic acid +lactobacillus lysate +sodium metabisulfite +steviol glycosides +linalool +cl 77492 +potassium citrate +ci 77491 +aloe barbadensis leaf extract +commiphora myrrha gum oil +mentha arvensis oil +magnolia officinalis bark extract +magnesium aluminium silicate +phenoxyethanol +potassium chloride +sodium sulphate +stevioside +acacia senegal gum +lactobacillus +eucalyptus oil +zeolite +sodium coco-sulfate +chamomilla recutita (matricaria) flower extract +citrus aurantium dulcis (orange) peel oil +zingiber officinale (ginger) root extract +citral +hydroxypropyl methyl cellulose +disodium edta +arginine +betaine +olive leaf extract +hydroxypropyl methylcellulose \ No newline at end of file diff --git a/src/routes/toothpaste.routes.js b/src/routes/toothpaste.routes.js new file mode 100644 index 0000000..9a070b7 --- /dev/null +++ b/src/routes/toothpaste.routes.js @@ -0,0 +1,11 @@ +import { + createToothpasteHandler, + getAllToothpastesHandler, + getToothpasteByIdHandler, +} from "../controllers/toothpaste.controller.js"; + +export default async function toothpasteRoutes(fastify, options) { + fastify.post("/toothpastes/new", createToothpasteHandler); + fastify.get("/toothpastes", getAllToothpastesHandler); + fastify.get("/toothpastes/:id", getToothpasteByIdHandler); +} diff --git a/src/schemas/toothpastes.schema.js b/src/schemas/toothpastes.schema.js new file mode 100644 index 0000000..e69de29 diff --git a/src/services/ai/analysis_system_prompt.js b/src/services/ai/analysis_system_prompt.js new file mode 100644 index 0000000..da104b9 --- /dev/null +++ b/src/services/ai/analysis_system_prompt.js @@ -0,0 +1,90 @@ +export const TOOTHPASTE_ANALYSIS_SYSTEM_PROMPT = `You are a dental health expert analyzing a toothpaste product. You will be provided with a list of ingredient objects. Each object contains fields like 'name', 'category', 'safety_score', 'benefits', 'risks', 'regulatory_notes', and 'note'. + +Your task is to generate a JSON analysis based *exclusively* on this provided data. Do not use external knowledge (except for ingredients explicitly marked with note: not found in the database). + +ANALYSIS REQUIREMENTS: + +1. OVERALL SCORE (0-10 scale, 1 decimal) + + CRITICAL SCORING INSTRUCTIONS: + + Step 1: Calculate the Base Safety Score. + - Look at all ingredients that have a 'safety_score' (i.e., 'safety_score' is not null). + - The Base Safety Score is the mathematical average of these 'safety_score' values. + - (Example: If scores are 9.0, 10.0, and 7.0, the Base Safety Score = 8.66, which you can round to 8.7). + - If no ingredients have a 'safety_score', start at 5.0. + + Step 2: Apply Adjustments for Efficacy (Benefits) & Drawbacks (Risks/Unknowns). + - Start with your Base Safety Score from Step 1 and add/subtract points based on the following: + + - POSITIVE ADJUSTMENTS (Efficacy Bonus): + - Check the 'benefits' and 'name' fields for key active ingredients. + - +0.5 to +0.7 if 'benefits' include 'remineralization' AND 'name' is 'nano-hydroxyapatite'. + - +0.3 to +0.5 if 'benefits' include 'cavity prevention' OR 'name' contains 'fluoride' (e.g., 'sodium fluoride', 'stannous fluoride'). + - +0.2 to +0.3 if 'name' is 'xylitol' and 'category' is 'Sweetener' (implies high concentration). + - +0.3 to +0.5 if 'benefits' include 'desensitizing' (e.g., from 'potassium nitrate', 'stannous fluoride'). + - +0.2 to +0.3 for other 'high' evidence 'benefits' (e.g., 'calcium carbonate' for 'remineralization', natural antibacterials like 'tea tree oil'). + + - NEGATIVE ADJUSTMENTS (Penalties): + - **Unknown Ingredients:** For *each* ingredient where 'note' is 'not found in the database' OR 'safety_score' is null: -0.5 to -1.0. (This is a significant penalty). + - **Documented Risks:** For ingredients with non-null 'risks': + - -0.3 to -0.5 for 'mild irritation' or 'sensitivity' (e.g., from 'sodium lauryl sulfate'). + - -0.5 to -0.7 for 'parabens' or significant 'artificial dyes' (e.g., 'FD&C Blue 1'). + - -0.8 to -1.0 for major concerns like 'triclosan' or 'endocrine disruptor' risks. + - **Regulatory Notes:** If 'regulatory_notes' field contains warnings or restrictions (e.g., "restricted in EU", "FDA warning"): -0.5 to -1.5. + - **Low Evidence:** If key *beneficial* ingredients have an 'evidence_level' of 'low': -0.2 to -0.4 (penalizes relying on unproven claims). + + Step 3: Final Score & Sanity Check. + - Final Score = Base Safety Score + All Adjustments. + - The score must be capped between 0.0 and 10.0. + - **Efficacy Gate:** If no significant active ingredients are found (i.e., no 'cavity prevention', 'remineralization', or 'desensitizing' benefits), the final score *cannot exceed 8.0*, even if all ingredients are 10/10 safe. (A safe-but-useless product is not a 10/10). + - **Logic Check:** A product with a high Base Safety Score (e.g., 9.5) and strong actives (e.g., fluoride) should score very high (8.0+). A product with a good Base Safety Score (e.g., 8.0) but with unknown ingredients and SLS should score much lower (e.g., 6.0-7.0). + +2. CATEGORY CLASSIFICATIONS (boolean flags) + + Base these *entirely* on the provided data fields: + + - is_whitening: + * TRUE if any ingredient 'benefits' explicitly state 'whitening', 'removes surface stains', 'polishes'. + * OR if any ingredient 'name' is 'hydrogen peroxide', 'carbamide peroxide', 'activated charcoal', or 'blue covarine'. + + - for_sensitive_teeth: + * TRUE if any ingredient 'benefits' explicitly state 'desensitizing', 'for sensitive teeth', 'occludes dentinal tubules'. + * OR if any ingredient 'name' is 'potassium nitrate', 'stannous fluoride', 'arginine', or 'strontium chloride'. + + - is_fluoride_free: + * TRUE if NO ingredient 'name' in the list contains 'fluoride' or 'monofluorophosphate'. + + - is_natural: + * TRUE only if *all* of the following are met: + 1. No ingredients with 'names' or 'risks' indicating artificial dyes (e.g., 'FD&C', 'D&C', 'CI 42090'), artificial sweeteners ('saccharin'), parabens, triclosan, or 'sodium lauryl sulfate'. + 2. A high percentage (>70%) of ingredients are clearly plant/mineral-derived (check 'name' for 'oil', 'extract', 'stevia', 'silica', 'calcium carbonate', 'charcoal', 'sea salt'). + + - for_kids: + * TRUE if any ingredient 'benefits' mention 'for children', 'mild formula', 'safe if swallowed' or 'low fluoride'. + +3. ANALYSIS NOTES (2-4 concise sentences) + + Justify your score and findings using the provided data. + + - Sentence 1: Lead with the final score, justifying it with the Base Safety Score and the key efficacy adjustments. + * Example: "Scores 8.8/10, starting from a high average safety score of 9.2 which was boosted by the inclusion of 'sodium fluoride' for 'cavity prevention'." + * Example: "Scores 6.5/10, based on a decent average safety score of 8.0, but penalized for containing 'sodium lauryl sulfate' (lists 'mild irritation' risk) and two ingredients that were 'not found in the database'." + + - Sentence 2: Mention other primary findings based on the data, such as classifications. + * Example: "The formula is designed for 'whitening' and 'sensitive teeth' according to the benefits listed for its silica and potassium nitrate." + + - Sentence 3: Conclude with an overall assessment based *only* on the data. + * Example: "This is a high-safety, effective anti-cavity toothpaste, though users sensitive to SLS should take note." + * Example: "While this product uses many safe ingredients, the presence of unknown substances and lack of proven actives makes it a questionable choice." + +OUTPUT FORMAT (strict JSON only, no markdown, no code blocks, no extra text): +{ + "overall_score": , + "is_whitening": , + "for_sensitive_teeth": , + "is_fluoride_free": , + "is_natural": , + "for_kids": , + "analysis_notes": "" +}`; diff --git a/src/services/ai/analyzer.service.js b/src/services/ai/analyzer.service.js new file mode 100644 index 0000000..6f63936 --- /dev/null +++ b/src/services/ai/analyzer.service.js @@ -0,0 +1,74 @@ +import { GoogleGenAI } from "@google/genai"; +import { TOOTHPASTE_ANALYSIS_SYSTEM_PROMPT } from "./analysis_system_prompt.js"; +import { Mistral } from "@mistralai/mistralai"; + +const genAI = new GoogleGenAI({}); +const client = new Mistral({ apiKey: process.env.MISTRAL_API_KEY }); + +/** + * Analyze toothpaste to generate overall score and characteristics + * @param {Object} data - Toothpaste data + * @param {string} data.name - Toothpaste name + * @param {string} data.brand - Brand name + * @param {Array} data.ingredients - Array of ingredient objects with safety scores + * @param {string} data.imageUrl - URL of product image + * @returns {Promise} Analysis results + */ +export async function analyzeToothpaste(data) { + try { + const { name, brand, ingredients } = data; + + const chatResponse = await client.chat.complete({ + model: "mistral-medium-latest", + messages: [ + { role: "system", content: TOOTHPASTE_ANALYSIS_SYSTEM_PROMPT }, + { role: "user", content: JSON.stringify({ ingredients: ingredients }) }, + ], + }); + + const responseText = chatResponse.choices[0].message.content; + + const match = responseText.match(/```json([\s\S]*?)```/); + let jsonString; + if (match) { + jsonString = match[1].trim(); + } else { + jsonString = responseText.trim(); + } + const analysis = JSON.parse(jsonString); + + // Validate + const validatedAnalysis = { + overall_score: Number(analysis.overall_score), + is_whitening: Boolean(analysis.is_whitening), + for_sensitive_teeth: Boolean(analysis.for_sensitive_teeth), + is_fluoride_free: Boolean(analysis.is_fluoride_free), + is_natural: Boolean(analysis.is_natural), + for_kids: Boolean(analysis.for_kids), + analysis_notes: analysis.analysis_notes || "", + }; + + validatedAnalysis.overall_score = Math.max( + 0, + Math.min(10, validatedAnalysis.overall_score), + ); + + console.log("response", responseText); + console.log( + `Analysis complete - Score: ${validatedAnalysis.overall_score}/10`, + ); + console.log( + `Characteristics: ${ + Object.entries(validatedAnalysis) + .filter(([key, val]) => typeof val === "boolean" && val) + .map(([key]) => key.replace("is_", "").replace("for_", "")) + .join(", ") || "standard" + }`, + ); + + return validatedAnalysis; + } catch (error) { + console.error("Error analyzing toothpaste:", error); + throw error; + } +} diff --git a/src/services/ai/embedding.service.js b/src/services/ai/embedding.service.js new file mode 100644 index 0000000..2341ca2 --- /dev/null +++ b/src/services/ai/embedding.service.js @@ -0,0 +1,107 @@ +import { getClient, query } from "../../database/connection.js"; +import Fuse from "fuse.js"; + +let fuzzyIngredientCache = null; +let fuzzyToothpasteCache = null; + +export function resetFuzzyCache() { + fuzzyIngredientCache = null; + fuzzyToothpasteCache = null; + console.log("Fuzzy search cache reset"); +} + +export async function fuzzyFindSimilarIngredient(ingredient, threshold = 0.45) { + const dbClient = await getClient(); + + console.log("Finding similar ingredients..."); + try { + const result = await dbClient.query( + "SELECT id, name, alternative_names, category, safety_score, benefits, risks, evidence_level, regulatory_notes FROM ingredients", + ); + const ingredients = result.rows; + + if (!fuzzyIngredientCache) { + fuzzyIngredientCache = new Fuse(ingredients, { + keys: ["name", "alternative_names"], + includeScore: true, + threshold: threshold, + minMatchCharLength: 2, + }); + } + + const response = fuzzyIngredientCache.search(ingredient.toLowerCase()); + if (response.length === 0) { + console.log("No similar ingredient found"); + return null; + } + + if (response[0].score <= threshold) { + console.log("Below threschold"); + return response[0].item; + } + console.log("Other case"); + return null; + } catch (err) { + console.error("Error finding similar ingredients:", err); + throw err; + } finally { + dbClient.release(); + } +} + +export async function fuzzyFindSimilarToothpaste(toothpaste, threshold = 0.35) { + const dbClient = await getClient(); + + console.log("Finding similar toothpastes..."); + try { + const result = await query("SELECT id, name FROM toothpastes"); + const toothpastes = result.rows; + + if (!fuzzyToothpasteCache) { + fuzzyToothpasteCache = new Fuse(toothpastes, { + keys: ["name"], + includeScore: true, + threshold: threshold, + minMatchCharLength: 2, + }); + } + + const response = fuzzyToothpasteCache.search(toothpaste.toLowerCase()); + if (response.length === 0) { + return null; + } + + if (response[0].score <= threshold) { + return response[0].item; + } + + return null; + } catch (err) { + console.error("Error finding similar ingredients:", err); + throw err; + } finally { + dbClient.release(); + } +} +/** + * Insert new ingredient into database + * @param {string} name - Ingredient name + * @param {number[]} embedding - Ingredient embedding vector + * @returns {Promise} Inserted ingredient + */ +export async function insertIngredient(name, embedding) { + const dbClient = await getClient(); + + try { + const result = await dbClient.query( + `INSERT INTO ingredients (name, created_at, updated_at) + VALUES ($1, NOW(), NOW()) + RETURNING id, name`, + [name], + ); + + return result.rows[0]; + } finally { + dbClient.release(); + } +} diff --git a/src/services/ai/ocr.service.js b/src/services/ai/ocr.service.js new file mode 100644 index 0000000..d805954 --- /dev/null +++ b/src/services/ai/ocr.service.js @@ -0,0 +1,123 @@ +import { Mistral } from "@mistralai/mistralai"; +import { GoogleGenAI } from "@google/genai"; +import * as fs from "node:fs"; + +const apiKey = process.env.MISTRAL_API_KEY; +const client = new Mistral({ apiKey }); + +/** + * Extract ingredients from an image using OCR + * @param {Object} options - Configuration options + * @param {string} options.imageUrl - URL of the image + * @param {boolean} options.includeImageBase64 - Include base64 in response + * @returns {Promise} Array of ingredient strings + */ +export async function extractIngredients(options) { + const { + imageUrl, + includeImageBase64 = true, + provider = "gemini", // 'mistral' or 'gemini' + } = options; + + if (!imageUrl) { + throw new Error("imageUrl must be provided"); + } + + if (provider === "mistral") { + return extractWithMistral(imageUrl, includeImageBase64); + } else if (provider === "gemini") { + return extractWithGemini(imageUrl); + } else { + throw new Error('Invalid provider. Use "mistral" or "gemini"'); + } +} + +async function extractWithMistral(imageUrl, includeImageBase64) { + // OCR + const ocrResponse = await client.ocr.process({ + model: "mistral-ocr-latest", + document: { type: "image_url", imageUrl }, + includeImageBase64, + }); + + // Extract ingredients using AI + const ingredientsResponse = await client.chat.complete({ + model: "mistral-medium-latest", + messages: [ + { + role: "system", + content: `Extract the ingredients from this OCR data: ${JSON.stringify(ocrResponse)}. +Return ONLY a comma-separated list of ingredients. Remove any non-ingredient text like brand names, descriptions, or instructions. +Return plain text with no formatting, no asterisks, no markdown, just the ingredient names separated by commas.`, + }, + ], + }); + + const ingredientsText = + ingredientsResponse.choices?.[0]?.message?.content || ""; + return parseIngredients(ingredientsText); +} + +async function extractWithGemini(imageUrl) { + const genAI = new GoogleGenAI({}); + const base64ImageFile = fs.readFileSync( + "/Users/null/WebstormProjects/PastePick-server/src/services/ai/sg.jpeg", + { + encoding: "base64", + }, + ); + + const prompt = `Analyze this image and extract ONLY the ingredients list. +Return a comma-separated list of ingredients with no additional text, formatting, or markdown. +Remove brand names, descriptions, instructions, and any non-ingredient text. +Just return the ingredient names separated by commas.`; + + const contents = [ + { + inlineData: { + mimeType: "image/jpeg", + data: base64ImageFile, + }, + }, + { text: prompt }, + ]; + + const response = await genAI.models.generateContent({ + model: "gemini-2.5-flash", + contents: contents, + }); + + const ingredientsText = response.text; + return parseIngredients(ingredientsText); +} + +async function fetchImageAsBase64(imageUrl) { + const response = await fetch(imageUrl); + const buffer = await response.arrayBuffer(); + return Buffer.from(buffer).toString("base64"); +} + +function parseIngredients(ingredientsText) { + return ingredientsText + .split(",") + .map((ingredient) => ingredient.trim()) + .filter((ingredient) => ingredient.length > 0); +} + +/** + * Extract ingredients from a URL + * @param {string} imageUrl - URL of the image + * @returns {Promise} Array of ingredient strings + */ +export async function extractIngredientsFromUrl(imageUrl) { + return extractIngredients({ imageUrl }); +} + +/** + * Extract ingredients from base64 encoded image + * @param {string} imageBase64 - Base64 encoded image string + * @returns {Promise} Array of ingredient strings + */ +/*export async function extractIngredientsFromBase64(imageBase64) { + return extractIngredients({ imageBase64 }); +}*/ diff --git a/src/services/image.service.js b/src/services/image.service.js new file mode 100644 index 0000000..6146adf --- /dev/null +++ b/src/services/image.service.js @@ -0,0 +1,33 @@ +import FormData from "form-data"; +import axios from "axios"; + +/** + * Upload and process toothpaste image to Allas object storage + * @param {Buffer|string} image - Image buffer or base64 string + * @param {mimeType|string} mimeType - Image mimetype string + * @returns {Promise} Public URL of uploaded image + */ +export async function uploadImageToAllas(image, mimeType) { + try { + const filename = `toothpaste_${Date.now()}_${Math.random().toString(36).substring(7)}.webp`; + const formData = new FormData(); + formData.append("file", image, { + filename: filename, + contentType: mimeType, + }); + + const response = await axios.post( + process.env.ALLAS_UPLOAD_ENDPOINT, + formData, + { + headers: formData.getHeaders(), + }, + ); + + return response.data; + } catch (error) { + console.error("Error uploading image to Allas:", error); + const errorMsg = error.response?.data?.detail || error.message; + throw new Error(`Image upload failed: ${errorMsg}`); + } +} diff --git a/src/services/ingredient.extractor.service.js b/src/services/ingredient.extractor.service.js new file mode 100644 index 0000000..f4435e9 --- /dev/null +++ b/src/services/ingredient.extractor.service.js @@ -0,0 +1,58 @@ +import { + fuzzyFindSimilarIngredient, + insertIngredient, +} from "./ai/embedding.service.js"; + +/** + * Process ingredients from text: embed, lookup, and insert if needed + * @param {string[]} ingredientsText - Array of ingredient names + * @returns {Promise} Array of processed ingredients with database info + */ +export async function processIngredientsFromText(ingredientsText) { + const processedIngredients = []; + + for (let i = 0; i < ingredientsText.length; i++) { + const ingredientName = ingredientsText[i]; + + console.log(`Processing ingredient: ${ingredientName}`); + + const existingIngredient = await fuzzyFindSimilarIngredient(ingredientName); + + let ingredientData; + + if (existingIngredient) { + console.log(`Found existing: ${existingIngredient.name}`); + ingredientData = { + id: existingIngredient.id, + name: existingIngredient.name, + alternative_names: existingIngredient.alternative_names, + category: existingIngredient.category, + safety_score: existingIngredient.safety_score, + benefits: existingIngredient.benefits, + risks: existingIngredient.risks, + regulatory_notes: existingIngredient.regulatory_notes, + evidence_level: existingIngredient.evidence_level, + original_name: ingredientName, + }; + } else { + console.log( + ` + Adding new ingredient: ${ingredientName}, existing: ${existingIngredient}`, + ); + const newIngredient = await insertIngredient(ingredientName); + ingredientData = { + id: newIngredient.id, + name: newIngredient.name, + category: null, + safety_score: null, + benefits: null, + risks: null, + original_name: ingredientName, + note: "not found in the database", + }; + } + + processedIngredients.push(ingredientData); + } + + return processedIngredients; +} diff --git a/src/services/legacy.extractor.service.js b/src/services/legacy.extractor.service.js new file mode 100644 index 0000000..78ab2b4 --- /dev/null +++ b/src/services/legacy.extractor.service.js @@ -0,0 +1,63 @@ +import { extractIngredients } from "../services/ai/ocr.service.js"; +import { + fuzzyFindSimilarIngredient, + insertIngredient, +} from "../services/ai/embedding.service.js"; + +/** + * Process ingredients from image: extract, embed, lookup, and insert if needed + * @returns {Promise} Array of processed ingredients with database info + */ +export async function processIngredientsFromImage(options) { + /*const ingredients = await extractIngredients(options); + const embeddings = []; + const processedIngredients = []; + + for (let i = 0; i < ingredients.length; i++) { + const ingredientName = ingredients[i]; + const embedding = embeddings[i].embedding; + + console.log(`Processing ingredient: ${ingredientName}`); + + // Step 3a: Look up similar ingredient in database + const existingIngredient = await fuzzyFindSimilarIngredient(embedding); + + let ingredientData; + + if (existingIngredient) { + // Found similar ingredient + console.log(` ✓ Found existing: ${existingIngredient.name} (distance: ${existingIngredient.distance})`); + ingredientData = { + id: existingIngredient.id, + name: existingIngredient.name, + category: existingIngredient.category, + safety_score: existingIngredient.safety_score, + benefits: existingIngredient.benefits, + risks: existingIngredient.risks, + matched: true, + original_name: ingredientName + }; + } else { + // Step 3b: Insert new ingredient if not found + console.log(` + Adding new ingredient: ${ingredientName}`); + const newIngredient = await insertIngredient(ingredientName, embedding); + + ingredientData = { + id: newIngredient.id, + name: newIngredient.name, + category: newIngredient.category, + safety_score: newIngredient.safety_score, + benefits: newIngredient.benefits, + risks: newIngredient.risks, + matched: false, + original_name: ingredientName + }; + } + + processedIngredients.push(ingredientData); + } + + return processedIngredients; + + */ +} diff --git a/src/services/toothpaste.create.service.js b/src/services/toothpaste.create.service.js new file mode 100644 index 0000000..cb40d1c --- /dev/null +++ b/src/services/toothpaste.create.service.js @@ -0,0 +1,97 @@ +import { getClient, query } from "../database/connection.js"; +import { processIngredientsFromText } from "./ingredient.extractor.service.js"; +import { + fuzzyFindSimilarToothpaste, + generateEmbeddings, + resetFuzzyCache, +} from "./ai/embedding.service.js"; +import { analyzeToothpaste } from "./ai/analyzer.service.js"; +import { uploadImageToAllas } from "./image.service.js"; + +/** + * Get a single toothpaste by ID with its ingredients + * @param {string} id - Toothpaste UUID + * @returns {Promise} Toothpaste object with ingredients + */ + +export async function createToothpaste({ + name, + brand, + ingredients_raw, + image, + image_mimetype, +}) { + const dbClient = await getClient(); + + try { + // 1. Check if similar toothpaste exists by name embedding + const existing_toothpaste = await fuzzyFindSimilarToothpaste(name); + + if (existing_toothpaste) { + await dbClient.query("ROLLBACK"); + throw new Error( + `Similar toothpaste already exists: ${existing_toothpaste}`, + ); + } + + // 2. Process ingredients from text (extract and match/create in DB) + const ingredients = await processIngredientsFromText(ingredients_raw); + + // 3. Upload and process image to get URL + const image_data = await uploadImageToAllas(image, image_mimetype); + + // 4. Analyze toothpaste + const analysis = await analyzeToothpaste({ + name, + brand, + ingredients, + image: image_data.url, + }); + + // 5. Insert toothpaste into database + const toothpasteResult = await dbClient.query( + ` + INSERT INTO toothpastes (name, brand, image_url, image_embedding, overall_score, score_updated_at, + is_whitening, for_sensitive_teeth, + is_fluoride_free, is_natural, for_kids) + VALUES ($1, $2, $3, $4::vector, $5, NOW(), $6, $7, $8, $9, $10) + RETURNING * + `, + [ + name, + brand, + image_data.url, + `[${image_data.embedding.join(",")}]`, + analysis.overall_score, + analysis.is_whitening, + analysis.for_sensitive_teeth, + analysis.is_fluoride_free, + analysis.is_natural, + analysis.for_kids, + ], + ); + + const toothpasteId = toothpasteResult.rows[0].id; + + // 6. Insert toothpaste-ingredient relationships + for (const ingredient of ingredients) { + await dbClient.query( + ` + INSERT INTO toothpaste_ingredients (toothpaste_id, ingredient_id, concentration_percentage) + VALUES ($1, $2, $3) + ON CONFLICT (toothpaste_id, ingredient_id) DO NOTHING + `, + [ + toothpasteId, + ingredient.id, + ingredient.concentration_percentage || null, + ], + ); + } + + await dbClient.query("COMMIT"); + resetFuzzyCache(); + } catch (error) { + console.log(error); + } +} diff --git a/src/services/toothpaste.getAll.service.js b/src/services/toothpaste.getAll.service.js new file mode 100644 index 0000000..9ebd0a5 --- /dev/null +++ b/src/services/toothpaste.getAll.service.js @@ -0,0 +1,32 @@ +import { query } from "../database/connection.js"; + +/** + * Get all toothpastes with their basic information + * @returns {Promise} Array of toothpaste objects + */ +export async function getAllToothpastes() { + try { + const result = await query(` + SELECT + id, + name, + brand, + description, + image_url, + overall_score, + is_whitening, + for_sensitive_teeth, + is_fluoride_free, + is_natural, + for_kids, + updated_at + FROM toothpastes + ORDER BY overall_score DESC NULLS LAST, name ASC + `); + + return result.rows; + } catch (error) { + console.error("Error fetching all toothpastes:", error); + throw error; + } +} diff --git a/src/services/toothpaste.getById.service.js b/src/services/toothpaste.getById.service.js new file mode 100644 index 0000000..6cd5f02 --- /dev/null +++ b/src/services/toothpaste.getById.service.js @@ -0,0 +1,67 @@ +import { query } from "../database/connection.js"; + +/** + * Get a single toothpaste by ID with its ingredients + * @param {string} id - Toothpaste UUID + * @returns {Promise} Toothpaste object with ingredients + */ +export async function getToothpasteById(id) { + try { + const toothpasteResult = await query( + ` + SELECT + id, + name, + brand, + description, + image_url, + overall_score, + score_updated_at, + is_whitening, + for_sensitive_teeth, + is_fluoride_free, + is_natural, + for_kids, + updated_at + FROM toothpastes + WHERE id = $1 + `, + [id], + ); + + if (toothpasteResult.rows.length === 0) { + return null; + } + + const toothpaste = toothpasteResult.rows[0]; + + // Get ingredients for this toothpaste + const ingredientsResult = await query( + ` + SELECT + i.id, + i.name, + i.category, + i.benefits, + i.risks, + i.evidence_level, + i.safety_score, + i.regulatory_notes, + i.sources, + ti.concentration_percentage + FROM ingredients i + INNER JOIN toothpaste_ingredients ti ON i.id = ti.ingredient_id + WHERE ti.toothpaste_id = $1 + ORDER BY i.safety_score DESC NULLS LAST, i.name ASC + `, + [id], + ); + + toothpaste.ingredients = ingredientsResult.rows; + + return toothpaste; + } catch (error) { + console.error("Error fetching toothpaste by ID:", error); + throw error; + } +} diff --git a/src/utils/cache.js b/src/utils/cache.js new file mode 100644 index 0000000..e69de29 diff --git a/src/utils/helpers.js b/src/utils/helpers.js new file mode 100644 index 0000000..e69de29