From e0d66cf181df00b94ce6bdda1f3de51f7213fba8 Mon Sep 17 00:00:00 2001 From: JCNoguera <88061365+VmMad@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:43:39 +0200 Subject: [PATCH] refactor: migrate to monorepo (#138) * feat: migrate to monorepo * fix: format * chore: remove old workflow --- .eslintrc.js | 6 + .github/workflows/check-linter.yaml | 14 +- .../workflows/monorepo-package-release.yml | 125 + .github/workflows/package-release.yml | 81 - .gitignore | 44 +- .husky/pre-commit | 2 +- .npmrc | 1 - .prettierignore | 6 + .prettierrc | 3 +- .vscode/settings.json | 7 + README.md | 211 +- .../app => cookie-manager/core}/constants.ts | 0 .../app => cookie-manager/core}/cookieLib.ts | 0 {src/lib/app => cookie-manager/core}/enums.ts | 0 {src/lib/app => cookie-manager/core}/types.ts | 2 +- cookie-manager/core/utils.ts | 37 + cookie-manager/react/.eslintignore | 1 + cookie-manager/react/.eslintrc.cjs | 17 + cookie-manager/react/.gitignore | 0 cookie-manager/react/.lintstagedrc.cjs | 1 + cookie-manager/react/README.md | 0 cookie-manager/react/index.html | 13 + cookie-manager/react/package.json | 50 + cookie-manager/react/postcss.config.js | 6 + cookie-manager/react/public/vite.svg | 1 + cookie-manager/react/src/App.tsx | 44 + cookie-manager/react/src/index.css | 70 + cookie-manager/react/src/lib/app/types.ts | 0 .../CookieLibrary/CookieLibrary.tsx | 13 + .../src/lib/components/CookieLibrary/index.ts | 1 + .../src/lib/components/CookieManager.tsx | 8 + .../react/src/lib/components/index.ts | 3 + cookie-manager/react/src/main.tsx | 10 + cookie-manager/react/src/vite-env.d.ts | 1 + cookie-manager/react/tailwind.config.js | 8 + cookie-manager/react/tsconfig.json | 15 + cookie-manager/react/tsconfig.package.json | 14 + cookie-manager/react/vite.config.ts | 52 + .../sveltekit/.env.example | 0 cookie-manager/sveltekit/.eslintignore | 1 + cookie-manager/sveltekit/.eslintrc.cjs | 5 + cookie-manager/sveltekit/.gitignore | 9 + cookie-manager/sveltekit/.lintstagedrc.cjs | 1 + cookie-manager/sveltekit/.npmrc | 1 + LICENSE => cookie-manager/sveltekit/LICENSE | 0 NOTICE => cookie-manager/sveltekit/NOTICE | 0 cookie-manager/sveltekit/README.md | 209 + cookie-manager/sveltekit/package.json | 49 + .../sveltekit/src}/app.d.ts | 0 .../sveltekit/src}/app.html | 2 +- cookie-manager/sveltekit/src/lib/app/index.ts | 2 + .../sveltekit/src}/lib/app/services.ts | 7 +- .../sveltekit/src}/lib/app/store.ts | 64 +- .../src}/lib/components/Button.svelte | 0 .../CookieLibrary/AdditionalCookies.svelte | 0 .../CookieLibrary/NecessaryCookies.svelte | 0 .../lib/components/CookieLibrary/cookies.json | 0 .../lib/components/CookieLibrary/index.svelte | 6 +- .../src}/lib/components/CookieManager.svelte | 7 +- .../src}/lib/components/Disclaimer.svelte | 6 +- .../sveltekit/src/lib/components/index.ts | 0 .../sveltekit/src}/lib/index.ts | 0 .../sveltekit/src}/lib/style/style.scss | 0 .../sveltekit/src}/routes/+layout.svelte | 2 +- .../sveltekit/src}/routes/+page.svelte | 2 +- cookie-manager/sveltekit/svelte.config.js | 37 + .../sveltekit/tsconfig.json | 4 +- .../sveltekit/vite.config.js | 0 package-lock.json | 10594 ---------------- package.json | 56 +- packages/eslint-config/README.md | 3 + packages/eslint-config/index.js | 38 + packages/eslint-config/package.json | 27 + .../eslint-config/rules.js | 67 +- packages/eslint-config/svelte.js | 45 + packages/lint-staged-config/index.js | 4 + packages/lint-staged-config/package.json | 8 + packages/typescript-config/package.json | 9 + packages/typescript-config/react.json | 18 + pnpm-lock.yaml | 6174 +++++++++ pnpm-workspace.yaml | 3 + src/lib/app/index.ts | 7 - src/lib/app/utils.ts | 95 - svelte.config.js | 19 - turbo.json | 18 + 85 files changed, 7321 insertions(+), 11145 deletions(-) create mode 100644 .eslintrc.js create mode 100644 .github/workflows/monorepo-package-release.yml delete mode 100644 .github/workflows/package-release.yml create mode 100644 .prettierignore create mode 100644 .vscode/settings.json rename {src/lib/app => cookie-manager/core}/constants.ts (100%) rename {src/lib/app => cookie-manager/core}/cookieLib.ts (100%) rename {src/lib/app => cookie-manager/core}/enums.ts (100%) rename {src/lib/app => cookie-manager/core}/types.ts (96%) create mode 100644 cookie-manager/core/utils.ts create mode 100644 cookie-manager/react/.eslintignore create mode 100644 cookie-manager/react/.eslintrc.cjs create mode 100644 cookie-manager/react/.gitignore create mode 100644 cookie-manager/react/.lintstagedrc.cjs create mode 100644 cookie-manager/react/README.md create mode 100644 cookie-manager/react/index.html create mode 100644 cookie-manager/react/package.json create mode 100644 cookie-manager/react/postcss.config.js create mode 100644 cookie-manager/react/public/vite.svg create mode 100644 cookie-manager/react/src/App.tsx create mode 100644 cookie-manager/react/src/index.css create mode 100644 cookie-manager/react/src/lib/app/types.ts create mode 100644 cookie-manager/react/src/lib/components/CookieLibrary/CookieLibrary.tsx create mode 100644 cookie-manager/react/src/lib/components/CookieLibrary/index.ts create mode 100644 cookie-manager/react/src/lib/components/CookieManager.tsx create mode 100644 cookie-manager/react/src/lib/components/index.ts create mode 100644 cookie-manager/react/src/main.tsx create mode 100644 cookie-manager/react/src/vite-env.d.ts create mode 100644 cookie-manager/react/tailwind.config.js create mode 100644 cookie-manager/react/tsconfig.json create mode 100644 cookie-manager/react/tsconfig.package.json create mode 100644 cookie-manager/react/vite.config.ts rename .env.example => cookie-manager/sveltekit/.env.example (100%) create mode 100644 cookie-manager/sveltekit/.eslintignore create mode 100644 cookie-manager/sveltekit/.eslintrc.cjs create mode 100644 cookie-manager/sveltekit/.gitignore create mode 100644 cookie-manager/sveltekit/.lintstagedrc.cjs create mode 100644 cookie-manager/sveltekit/.npmrc rename LICENSE => cookie-manager/sveltekit/LICENSE (100%) rename NOTICE => cookie-manager/sveltekit/NOTICE (100%) create mode 100644 cookie-manager/sveltekit/README.md create mode 100644 cookie-manager/sveltekit/package.json rename {src => cookie-manager/sveltekit/src}/app.d.ts (100%) rename {src => cookie-manager/sveltekit/src}/app.html (93%) create mode 100644 cookie-manager/sveltekit/src/lib/app/index.ts rename {src => cookie-manager/sveltekit/src}/lib/app/services.ts (90%) rename {src => cookie-manager/sveltekit/src}/lib/app/store.ts (52%) rename {src => cookie-manager/sveltekit/src}/lib/components/Button.svelte (100%) rename {src => cookie-manager/sveltekit/src}/lib/components/CookieLibrary/AdditionalCookies.svelte (100%) rename {src => cookie-manager/sveltekit/src}/lib/components/CookieLibrary/NecessaryCookies.svelte (100%) rename {src => cookie-manager/sveltekit/src}/lib/components/CookieLibrary/cookies.json (100%) rename {src => cookie-manager/sveltekit/src}/lib/components/CookieLibrary/index.svelte (90%) rename {src => cookie-manager/sveltekit/src}/lib/components/CookieManager.svelte (90%) rename {src => cookie-manager/sveltekit/src}/lib/components/Disclaimer.svelte (92%) rename src/lib/components/index.js => cookie-manager/sveltekit/src/lib/components/index.ts (100%) rename {src => cookie-manager/sveltekit/src}/lib/index.ts (100%) rename {src => cookie-manager/sveltekit/src}/lib/style/style.scss (100%) rename {src => cookie-manager/sveltekit/src}/routes/+layout.svelte (93%) rename {src => cookie-manager/sveltekit/src}/routes/+page.svelte (84%) create mode 100644 cookie-manager/sveltekit/svelte.config.js rename tsconfig.json => cookie-manager/sveltekit/tsconfig.json (88%) rename vite.config.js => cookie-manager/sveltekit/vite.config.js (100%) delete mode 100644 package-lock.json create mode 100644 packages/eslint-config/README.md create mode 100644 packages/eslint-config/index.js create mode 100644 packages/eslint-config/package.json rename .eslintrc.cjs => packages/eslint-config/rules.js (74%) create mode 100644 packages/eslint-config/svelte.js create mode 100644 packages/lint-staged-config/index.js create mode 100644 packages/lint-staged-config/package.json create mode 100644 packages/typescript-config/package.json create mode 100644 packages/typescript-config/react.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml delete mode 100644 src/lib/app/index.ts delete mode 100644 src/lib/app/utils.ts delete mode 100644 svelte.config.js create mode 100644 turbo.json diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..724f1bb --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,6 @@ +/** @type {import("eslint").Linter.Config} */ +module.exports = { + env: { + es6: true + } +} diff --git a/.github/workflows/check-linter.yaml b/.github/workflows/check-linter.yaml index d33ef55..0af1c09 100644 --- a/.github/workflows/check-linter.yaml +++ b/.github/workflows/check-linter.yaml @@ -6,8 +6,16 @@ jobs: linter: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4.0.0 + + - name: Install Nodejs + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # pin@v4.0.2 + with: + node-version: '18' + cache: 'pnpm' + - name: Install modules - run: yarn + run: pnpm i - name: Run Prettier ESLint check - run: yarn lint + run: pnpm lint diff --git a/.github/workflows/monorepo-package-release.yml b/.github/workflows/monorepo-package-release.yml new file mode 100644 index 0000000..8d1a1ba --- /dev/null +++ b/.github/workflows/monorepo-package-release.yml @@ -0,0 +1,125 @@ +name: Notification Manager package release + +on: + push: + tags: + - 'react-cookie-manager@[0-9]+.[0-9]+.[0-9]+' + - 'sveltekit-cookie-manager@[0-9]+.[0-9]+.[0-9]+' + +jobs: + publish-npm-package: + outputs: + library_dir: ${{ steps.detect_tag.outputs.library_dir }} + tag: ${{ github.ref_name }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 16 + registry-url: https://registry.npmjs.org/ + - name: Detect tag and set variable + id: detect_tag + run: | + # Set the library name based on the tag + if [[ ${{ github.ref }} =~ ^refs/tags/(.*)-cookie-manager.* ]]; then + library_name=${BASH_REMATCH[1]} + echo "library_dir=$library_name" >> "$GITHUB_OUTPUT" + else + echo "Invalid tag" + exit 1 + fi + + - name: Publish package + # The package directory is the library name e.g "apps/sveltekit | apps/react" + run: | + cd cookie-manager/${{ steps.detect_tag.outputs.library_dir }} && \ + pnpm i && \ + pnpm package && \ + cp ../../LICENSE ../../NOTICE . && \ + npm publish --access=public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + github_draft_release: + needs: publish-npm-package + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Prepare repository tags + run: | + # Fetch all tags + if git rev-parse --is-shallow-repository | grep -q 'true'; then + git fetch --prune --unshallow --tags -f + else + git fetch --prune --tags -f + fi + - name: Build changelog + id: build_changelog + run: | + echo "Building changelog..." + + # Create a changelog file with a header: + echo "# What's Changed" > CHANGELOG.md + + # Get the current tag from the workflow + current_tag="${{ needs.publish-npm-package.outputs.tag }}" + + # Extract the tag type from the current tag + current_tag_type=$(echo "$current_tag" | awk -F'@' '{print $1}') + + library_tags=$(git tag -l "$current_tag_type@*" --sort=-v:refname) + + tag_array=() + while IFS= read -r line; do + tag_array+=("$line") + done <<< "$library_tags" + + current_tag_index=-1 + for i in "${!tag_array[@]}"; do + if [ "${tag_array[$i]}" == "$current_tag" ]; then + current_tag_index=$i + break + fi + done + + if [ "$current_tag_index" -eq -1 ]; then + echo "Current tag $current_tag not found in the available tags." + exit 1 + fi + + if [ "$current_tag_index" -lt $((${#tag_array[@]} - 1)) ]; then + prev_tag="${tag_array[$((current_tag_index + 1))]}" + else + prev_tag=$(git rev-list --max-parents=0 HEAD) + fi + + last_commit=$(git rev-list -n 1 "$prev_tag") + + # Fill the changelog file with the commits since the last tag + # Set max tries to equal the maximum number of commits as protection + max_tries=$(git rev-list --count HEAD) + i=0 + while [ "$(git rev-parse HEAD~$i)" != "$last_commit" ] && [ $i -lt $((max_tries-1)) ]; do + commit_message=$(git show -s --format=%s HEAD~$i) + echo "- $commit_message" >> CHANGELOG.md + i=$((i+1)) + done + + # Set the complete changelog URL + echo >> CHANGELOG.md + compare="${prev_tag}...${current_tag}" + + echo "Appending full changelog URL to CHANGELOG.md..." + echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${compare}" >> CHANGELOG.md + + echo "Changelog built successfully." + + - name: Create draft release + uses: softprops/action-gh-release@v1 + with: + name: '@boxfish-studio/${{ github.ref_name }}' + tag_name: ${{ github.ref_name }} + body_path: CHANGELOG.md + draft: true diff --git a/.github/workflows/package-release.yml b/.github/workflows/package-release.yml deleted file mode 100644 index 5c2ac90..0000000 --- a/.github/workflows/package-release.yml +++ /dev/null @@ -1,81 +0,0 @@ -name: SvelteKit Cookie Manager Release - -on: - push: - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - -jobs: - publish-npm-package: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 16 - registry-url: https://registry.npmjs.org/ - - run: npm ci - - run: npm run build - - run: npm run package - - run: cd package && npm publish --access=public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - github_draft_release: - needs: publish-npm-package - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Prepare repository tags - run: | - if git rev-parse --is-shallow-repository | grep -q 'true'; then - git fetch --prune --unshallow --tags -f - else - git fetch --prune --tags -f - fi - - name: Build changelog - id: build_changelog - run: | - echo "Building changelog..." - - # Create a changelog file with a header: - echo "# What's Changed" > CHANGELOG.md - # Check repository tags and the last tagged commit - n_tags=`git tag -l 'v*' --sort=-v:refname | wc -l` - prev_tag=`git tag -l 'v*' --sort=-v:refname | sed '2q;d'` - if [ $n_tags -eq 1 ]; then - last_commit=`git rev-list --max-parents=0 HEAD` - else - last_commit=`git rev-list -n 1 $prev_tag` - fi - - # Fill the changelog file with the commits since the last tag - # Set max tries to equal the maximum number of commits as protection - max_tries=`git rev-list --count HEAD` - i=0 - while [ `git rev-parse HEAD~$i` != $last_commit ] && [ $i -lt $((max_tries-1)) ] - do - echo '- ' `git show -s --format=%s HEAD~$i` >> CHANGELOG.md - i=$((i+1)) - done - - # Set the complete changelog url - echo >> CHANGELOG.md - compare="" - if [ $n_tags -eq 1 ]; then - compare=$last_commit - else - compare=$prev_tag - fi - compare="${compare}...`git tag -l 'v*' --sort=-v:refname | sed '1q;d'`" - echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${compare}" >> CHANGELOG.md - - echo "Changelog built successfully." - - name: Create draft release - uses: softprops/action-gh-release@v1 - with: - name: SvelteKit Cookie Manager ${{ github.ref_name }} - tag_name: ${{ github.ref_name }} - body_path: CHANGELOG.md - draft: true diff --git a/.gitignore b/.gitignore index e71d7f9..5aa13a5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,41 @@ -.DS_Store +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# Dependencies node_modules -/build -/.svelte-kit -/package +.pnp +.pnp.js + +# Local env files .env -.env.* -!.env.example +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Testing +coverage + +# Turbo +.turbo + +# Vercel +.vercel + +# Build Outputs +.next/ +out/ +build +dist + +# Debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Misc +.DS_Store +*.pem .eslintcache + +# Cookie Manager Package Specific +cookie-manager/*/src/lib/cookie-core diff --git a/.husky/pre-commit b/.husky/pre-commit index abf1181..b7fbc57 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" -npx lint-staged --allow-empty +pnpm exec lint-staged --allow-empty diff --git a/.npmrc b/.npmrc index b6f27f1..e69de29 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +0,0 @@ -engine-strict=true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..3096115 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +pnpm-lock.yaml +yarn.lock +node_modules +dist +.svelte-kit +.turbo diff --git a/.prettierrc b/.prettierrc index b1dc1d6..4dd7a5f 100644 --- a/.prettierrc +++ b/.prettierrc @@ -3,5 +3,6 @@ "singleQuote": true, "trailingComma": "none", "printWidth": 100, - "semi": false + "semi": false, + "plugins": ["prettier-plugin-svelte"] } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3a99786 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "eslint.workingDirectories": [ + { + "mode": "auto" + } + ] +} diff --git a/README.md b/README.md index c79e7da..a761def 100644 --- a/README.md +++ b/README.md @@ -1,209 +1,6 @@ -# Sveltekit Cookie Manager 🍪 +# Cookie Manager Monorepo -Sveltekit Cookie Manager is an easy-use Svelte package to help control the visitor's cookie consent. +This is a monorepo for the Cookie Manager project. It contains the following packages: -### Disclaimer - -Minimum required SvelteKit version: `1.0.0-next.581`. - -## About 📝 - -**Sveltekit Cookie Manager** reduces the workload of creating and mantaining multiple cookie consents by centralizing them into this package. Enables cookie management of following services: - -- Google Analytics Universal. -- Google Analytics 4. - -## Features ✨ - -- Display a customizable popup to accept or reject cookies. -- Create a cookie library showing: - - Tables with details about site's necessary cookies and additional cookies: cookie name, provider name and url, cookie category, purpose, expiry and type. - - Radio inputs (allow or reject all cookies) and a button to update preferences. - -## Installation 🧰 - -```shell -$ npm i @boxfish-studio/sveltekit-cookie-manager -``` - -or yarn - -```shell -$ yarn add @boxfish-studio/sveltekit-cookie-manager -``` - -
- -## How to use 📝 - -### Show a popup - -Import the `CookieManager` component to your Svelte page and pass the configuration with your desired settings: - -```svelte - - - -``` - -### Show the cookie library - -Import the `CookieLibrary` component to your svelte file and pass the configuration with your desired settings, as shown in the example below. - -You can also use the library without any configuration or you can pass a `theme` to the configuration: - -```svelte - - - -``` - -### Using the internal store - -You can use the `servicesInitialized` writable to know whether the services are running or not. - -```ts -import { servicesInitialized } from '@boxfish-studio/sveltekit-cookie-manager' -import { get } from 'svelte/store' - -const isRunning = get(servicesInitialized) -``` - -## Configuration 🪛 - -Custom configuration must be of type `SKCMConfiguration`. All available props are shown below: - -```ts -type SKCMConfiguration = { - disclaimer: { - title?: string - body?: string - policyText?: string - policyUrl?: string - acceptButtonText?: string - rejectButtonText?: string - } - services: { - googleAnalyticsUniversalId?: string - googleAnalytics4Id?: string - adCookiesEnabled?: boolean - customNecessaryCookies?: { - name: string - provider: string - providerUrl: string - purpose: string - expiry: string - type: string - showDisclaimerIfMissing?: boolean - }[] - } - theme: { - primary?: string - dark?: string - medium?: string - light?: string - } -} -``` - -### Disclaimer props - -| Name | Description | Default value | -| ---------------- | --------------------------------- | -------------------------------------------------------- | -| title | The title of the popup | "Cookie Preferences" | -| body | Body message of the popup | "By using this site, you agree with our use of cookies." | -| policyText | Text that links to Privacy Policy | "Read our Cookie Policy" | -| policyUrl | Privacy Policy url | "/privacy-policy" | -| acceptButtonText | Text shown in 'Accept' button | "Accept Additional Cookies" | -| rejectButtonText | Text shown in 'Reject' button | "Reject Additional Cookies" | - -### Services props - -You must use `googleAnalyticsUniversalId` or `googleAnalytics4Id`. - -| Name | Description | Default value | -| -------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------- | -| googleAnalyticsUniversalId | Your Google Analytics Universal key | | -| googleAnalytics4Id | Your Google Analytics 4 key | | -| adCookiesEnabled | Whether cookies with the category Advertising should be set in the browser and shown in the library | true | -| customNecessaryCookies | Cookies that should be present in the Necessary Cookies table to inform the user their usage. To configure them see below | | - -### Custom necessary cookies - -You can configure extra cookies that will also appear in the Cookie library by specifying them in the `customNecessaryCookies` property. -They accept the following options: - -| Name | Description | Default value | Required | Example | -| ---------------------- | -------------------------------------------------------------------------- | ------------- | -------- | --------------------------- | -| name | Name of the cookie | | Yes | Boxfish Cookie | -| provider | Name of it's provider | | No | Boxfish | -| providerUrl | URL of it's provider | | No | https://boxfish.studio | -| purpose | Usage of the cookie | | Yes | "Stores the user's consent" | -| expiry | Time that the cookie with remain in the user's browser since it's creation | | Yes | "30 days" | -| type | Type of cookie | | Yes | "HTTP" | -| showDisclamerIfMissing | Show the accept/reject popup if this cookie is missing | false | No | true | - -### Theme props - -A 4-colour palette has been predefined following a custom style guide. You may overwrite these values in your custom configuration variable. - -| Name | Description | Default value | -| ------- | ----------------------------------------------------- | --------------- | -| primary | Used in buttons backgrounds, anchors | #14cabf (teal) | -| dark | Used in headings, body | #131f37 (black) | -| medium | Used in table headings, table borders | #b0bfd9 (gray) | -| light | Used in banner background colour, buttons text colour | #fff (white) | - -### Built with - -- Sveltekit. -- Typescript. - -## Release Package - -`npm run package && cd package && npm publish --access=public` - -## License - -[Apache 2.0](./LICENSE) © [Boxfish Studio] - -[Boxfish Studio]: https://boxfish.studio - -
- -
- Made with :heart: by Boxfish Studio.

- Boxfish Logo -
+- [SvelteKit](./cookie-manager/sveltekit/). +- [React](./cookie-manager/react/). diff --git a/src/lib/app/constants.ts b/cookie-manager/core/constants.ts similarity index 100% rename from src/lib/app/constants.ts rename to cookie-manager/core/constants.ts diff --git a/src/lib/app/cookieLib.ts b/cookie-manager/core/cookieLib.ts similarity index 100% rename from src/lib/app/cookieLib.ts rename to cookie-manager/core/cookieLib.ts diff --git a/src/lib/app/enums.ts b/cookie-manager/core/enums.ts similarity index 100% rename from src/lib/app/enums.ts rename to cookie-manager/core/enums.ts diff --git a/src/lib/app/types.ts b/cookie-manager/core/types.ts similarity index 96% rename from src/lib/app/types.ts rename to cookie-manager/core/types.ts index 6d54db8..0cc6088 100644 --- a/src/lib/app/types.ts +++ b/cookie-manager/core/types.ts @@ -1,4 +1,4 @@ -import type { CookieCategory } from './' +import type { CookieCategory } from './enums' export enum SupportedService { GoogleAnalyticsUniversal = 'googleAnalyticsUniversal', diff --git a/cookie-manager/core/utils.ts b/cookie-manager/core/utils.ts new file mode 100644 index 0000000..b2ae045 --- /dev/null +++ b/cookie-manager/core/utils.ts @@ -0,0 +1,37 @@ +import { DEFAULT_THEME_COLORS } from './constants' +import type { Theme } from './types' + +/* + * General utils for managing cookies in Typescript. + * Source: https://gist.github.com/joduplessis/7b3b4340353760e945f972a69e855d11 + */ +export function getCookie(name: string): string | undefined { + const value = '; ' + document.cookie + const parts = value.split('; ' + name + '=') + + if (parts?.length == 2) { + return parts?.pop()?.split(';')?.shift() ?? undefined + } +} +export const setCookie = (name: string, val: string, expDays: number): void => { + const date = new Date() + const value = val + date.setTime(date.getTime() + expDays * 24 * 60 * 60 * 1000) + document.cookie = name + '=' + value + '; expires=' + date.toUTCString() + '; path=/' +} +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export function deleteCookie(name: string) { + const date = new Date() + date.setTime(date.getTime() + -1 * 24 * 60 * 60 * 1000) + document.cookie = name + '=; expires=' + date.toUTCString() + '; path=/' +} + +export const formatStyles = (theme: Theme): string => + Object.entries(theme) + .map((colorVariable) => `--${colorVariable[0]}:${colorVariable[1]};`) + .join(' ') + +export const getInlineStyle = (theme: Theme = {}): string => { + const mergedTheme = { ...DEFAULT_THEME_COLORS, ...theme } + return formatStyles(mergedTheme) +} diff --git a/cookie-manager/react/.eslintignore b/cookie-manager/react/.eslintignore new file mode 100644 index 0000000..cf64a52 --- /dev/null +++ b/cookie-manager/react/.eslintignore @@ -0,0 +1 @@ +.eslintrc.cjs diff --git a/cookie-manager/react/.eslintrc.cjs b/cookie-manager/react/.eslintrc.cjs new file mode 100644 index 0000000..71a6a4b --- /dev/null +++ b/cookie-manager/react/.eslintrc.cjs @@ -0,0 +1,17 @@ +/** @type {import("eslint").Linter.Config} */ +module.exports = { + globals: { + React: true + }, + root: true, + extends: ['@repo/eslint-config/index.js', 'plugin:react/recommended'], + parser: '@typescript-eslint/parser', + settings: { + react: { + version: 'detect' + } + }, + parserOptions: { + project: true + } +} diff --git a/cookie-manager/react/.gitignore b/cookie-manager/react/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/cookie-manager/react/.lintstagedrc.cjs b/cookie-manager/react/.lintstagedrc.cjs new file mode 100644 index 0000000..fbd4eca --- /dev/null +++ b/cookie-manager/react/.lintstagedrc.cjs @@ -0,0 +1 @@ +module.exports = require('@repo/lint-staged-config') diff --git a/cookie-manager/react/README.md b/cookie-manager/react/README.md new file mode 100644 index 0000000..e69de29 diff --git a/cookie-manager/react/index.html b/cookie-manager/react/index.html new file mode 100644 index 0000000..ef80c79 --- /dev/null +++ b/cookie-manager/react/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + + +
+ + + diff --git a/cookie-manager/react/package.json b/cookie-manager/react/package.json new file mode 100644 index 0000000..137fe30 --- /dev/null +++ b/cookie-manager/react/package.json @@ -0,0 +1,50 @@ +{ + "name": "@boxfish-studio/react-cookie-manager", + "version": "0.0.0", + "private": true, + "type": "module", + "main": "./dist/index.umd.js", + "module": "./dist/index.es.js", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "exports": { + ".": { + "import": "./dist/index.es.js", + "require": "./dist/index.umd.js", + "types": "./dist/index.d.ts" + }, + "./dist/style.css": "./dist/style.css" + }, + "scripts": { + "dev": "vite dev", + "build": "tsc -b && vite build", + "preview": "vite preview", + "lint": "eslint .", + "build:package": "tsc -d && cross-env BUILDING_PACKAGE=true vite build" + }, + "dependencies": { + "cross-env": "^7.0.3", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/lint-staged-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@types/node": "^20.16.5", + "@types/react": "^18", + "@types/react-dom": "^18", + "@vitejs/plugin-react": "^4.3.1", + "@vitejs/plugin-react-swc": "^3.7.0", + "autoprefixer": "^10.4.20", + "eslint": "^8.57.1", + "postcss": "^8.4.47", + "tailwindcss": "^3.4.12", + "typescript": "^5.4.5", + "vite": "^4.4.11", + "vite-plugin-dts": "^3.9.1", + "vite-tsconfig-paths": "^4.2.1" + } +} diff --git a/cookie-manager/react/postcss.config.js b/cookie-manager/react/postcss.config.js new file mode 100644 index 0000000..35237eb --- /dev/null +++ b/cookie-manager/react/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +} diff --git a/cookie-manager/react/public/vite.svg b/cookie-manager/react/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/cookie-manager/react/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cookie-manager/react/src/App.tsx b/cookie-manager/react/src/App.tsx new file mode 100644 index 0000000..5f918da --- /dev/null +++ b/cookie-manager/react/src/App.tsx @@ -0,0 +1,44 @@ +import { CookieLibrary, CookieManager } from '@components' +import { SKCMConfiguration } from '@core/types' + +function App(): React.JSX.Element { + const configuration: SKCMConfiguration = { + disclaimer: { + title: 'Custom Title', + body: 'Custom Body' + }, + services: { + googleAnalyticsUniversalId: 'UA-XXXXXXXXX', + googleAnalytics4Id: 'G-XXXXXXX', + adCookiesEnabled: true, + customNecessaryCookies: [ + { + name: '1st Cookie Test', + provider: 'Boxfish', + providerUrl: 'boxfish.studio', + purpose: 'Stores the user´s preferences.', + expiry: '2 months', + type: 'HTTP', + showDisclaimerIfMissing: true + }, + { + name: 'Cookie 2', + provider: 'Boxfish', + providerUrl: 'boxfish.studio', + purpose: 'Stores the user´s cookies consent state for the current domain', + expiry: '30 days', + type: 'HTTP', + showDisclaimerIfMissing: true + } + ] + } + } + return ( + <> + + + + ) +} + +export default App diff --git a/cookie-manager/react/src/index.css b/cookie-manager/react/src/index.css new file mode 100644 index 0000000..78e9b84 --- /dev/null +++ b/cookie-manager/react/src/index.css @@ -0,0 +1,70 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + align-items: center; + justify-content: center; + min-width: 320px; + min-height: 100vh; + max-width: 1200px; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/cookie-manager/react/src/lib/app/types.ts b/cookie-manager/react/src/lib/app/types.ts new file mode 100644 index 0000000..e69de29 diff --git a/cookie-manager/react/src/lib/components/CookieLibrary/CookieLibrary.tsx b/cookie-manager/react/src/lib/components/CookieLibrary/CookieLibrary.tsx new file mode 100644 index 0000000..5b01f4b --- /dev/null +++ b/cookie-manager/react/src/lib/components/CookieLibrary/CookieLibrary.tsx @@ -0,0 +1,13 @@ +import { SKCMConfiguration } from '@core/types' + +interface CookieLibraryProps { + configuration: SKCMConfiguration +} + +export function CookieLibrary({ configuration }: CookieLibraryProps): React.JSX.Element { + return ( +
+

Library

+
+ ) +} diff --git a/cookie-manager/react/src/lib/components/CookieLibrary/index.ts b/cookie-manager/react/src/lib/components/CookieLibrary/index.ts new file mode 100644 index 0000000..299ce58 --- /dev/null +++ b/cookie-manager/react/src/lib/components/CookieLibrary/index.ts @@ -0,0 +1 @@ +export * from './CookieLibrary' diff --git a/cookie-manager/react/src/lib/components/CookieManager.tsx b/cookie-manager/react/src/lib/components/CookieManager.tsx new file mode 100644 index 0000000..d026b5d --- /dev/null +++ b/cookie-manager/react/src/lib/components/CookieManager.tsx @@ -0,0 +1,8 @@ +import { SKCMConfiguration } from '@core/types' + +interface CookieManagerProps { + configuration: SKCMConfiguration +} +export function CookieManager({ configuration }: CookieManagerProps): React.JSX.Element { + return
CookieManager
+} diff --git a/cookie-manager/react/src/lib/components/index.ts b/cookie-manager/react/src/lib/components/index.ts new file mode 100644 index 0000000..50537e3 --- /dev/null +++ b/cookie-manager/react/src/lib/components/index.ts @@ -0,0 +1,3 @@ +export * from './CookieLibrary' + +export * from './CookieManager' diff --git a/cookie-manager/react/src/main.tsx b/cookie-manager/react/src/main.tsx new file mode 100644 index 0000000..4b9e95a --- /dev/null +++ b/cookie-manager/react/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import App from './App.tsx' +import './index.css' + +createRoot(document.getElementById('root') as HTMLElement).render( + + + +) diff --git a/cookie-manager/react/src/vite-env.d.ts b/cookie-manager/react/src/vite-env.d.ts new file mode 100644 index 0000000..14fa749 --- /dev/null +++ b/cookie-manager/react/src/vite-env.d.ts @@ -0,0 +1 @@ +// / diff --git a/cookie-manager/react/tailwind.config.js b/cookie-manager/react/tailwind.config.js new file mode 100644 index 0000000..82d87c3 --- /dev/null +++ b/cookie-manager/react/tailwind.config.js @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./src/**/*.{js,ts,jsx,tsx}'], + theme: { + extend: {} + }, + plugins: [] +} diff --git a/cookie-manager/react/tsconfig.json b/cookie-manager/react/tsconfig.json new file mode 100644 index 0000000..fe082e5 --- /dev/null +++ b/cookie-manager/react/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "@repo/typescript-config/react.json", + "compilerOptions": { + "baseUrl": "./", + "allowImportingTsExtensions": true, + "paths": { + "@components": ["src/lib/components"], + "@components/*": ["src/lib/components/*"], + "@core": ["../core"], + "@core/*": ["../core/*"] + } + }, + "include": ["src", "*.config.js", "*.config.ts"], + "exclude": ["node_modules"] +} diff --git a/cookie-manager/react/tsconfig.package.json b/cookie-manager/react/tsconfig.package.json new file mode 100644 index 0000000..a4d64c2 --- /dev/null +++ b/cookie-manager/react/tsconfig.package.json @@ -0,0 +1,14 @@ +{ + "extends": "@repo/typescript-config/react.json", + "compilerOptions": { + "baseUrl": "./", + "paths": { + "@components": ["src/lib/components"], + "@components/*": ["src/lib/components/*"], + "@core": ["src/lib/cookie-core"], + "@core/*": ["src/lib/cookie-core/*"] + } + }, + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/cookie-manager/react/vite.config.ts b/cookie-manager/react/vite.config.ts new file mode 100644 index 0000000..4812bff --- /dev/null +++ b/cookie-manager/react/vite.config.ts @@ -0,0 +1,52 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' +import { resolve } from 'path' +import dts from 'vite-plugin-dts' +import tailwindcss from 'tailwindcss' +import tsconfigPaths from 'vite-tsconfig-paths' + +const isPackageProduction = process.env.BUILDING_PACKAGE === 'true' + +const packageBuildConfig = { + lib: { + entry: resolve(__dirname, './src/lib/index.ts'), + name: '@boxfish-studio/react-cookie-manager', + fileName: (format) => `index.${format}.js` + }, + rollupOptions: { + external: ['react', 'react-dom', 'tailwindcss'], + output: { + globals: { + react: 'React', + 'react-dom': 'ReactDOM', + tailwindcss: 'tailwindcss' + } + } + }, + sourcemap: true, + emptyOutDir: true +} +const plugins = isPackageProduction + ? [ + tsconfigPaths({ + root: __dirname + }), + react(), + dts({ rollupTypes: true }) + ] + : [ + tsconfigPaths({ + root: __dirname + }), + react() + ] + +export default defineConfig({ + build: isPackageProduction ? packageBuildConfig : {}, + plugins, + css: { + postcss: { + plugins: [tailwindcss] + } + } +}) diff --git a/.env.example b/cookie-manager/sveltekit/.env.example similarity index 100% rename from .env.example rename to cookie-manager/sveltekit/.env.example diff --git a/cookie-manager/sveltekit/.eslintignore b/cookie-manager/sveltekit/.eslintignore new file mode 100644 index 0000000..cf64a52 --- /dev/null +++ b/cookie-manager/sveltekit/.eslintignore @@ -0,0 +1 @@ +.eslintrc.cjs diff --git a/cookie-manager/sveltekit/.eslintrc.cjs b/cookie-manager/sveltekit/.eslintrc.cjs new file mode 100644 index 0000000..c59dca8 --- /dev/null +++ b/cookie-manager/sveltekit/.eslintrc.cjs @@ -0,0 +1,5 @@ +/** @type {import("eslint").Linter.Config} */ +module.exports = { + root: true, + extends: ['@repo/eslint-config/svelte.js'] +} diff --git a/cookie-manager/sveltekit/.gitignore b/cookie-manager/sveltekit/.gitignore new file mode 100644 index 0000000..e71d7f9 --- /dev/null +++ b/cookie-manager/sveltekit/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +node_modules +/build +/.svelte-kit +/package +.env +.env.* +!.env.example +.eslintcache diff --git a/cookie-manager/sveltekit/.lintstagedrc.cjs b/cookie-manager/sveltekit/.lintstagedrc.cjs new file mode 100644 index 0000000..fbd4eca --- /dev/null +++ b/cookie-manager/sveltekit/.lintstagedrc.cjs @@ -0,0 +1 @@ +module.exports = require('@repo/lint-staged-config') diff --git a/cookie-manager/sveltekit/.npmrc b/cookie-manager/sveltekit/.npmrc new file mode 100644 index 0000000..b6f27f1 --- /dev/null +++ b/cookie-manager/sveltekit/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/LICENSE b/cookie-manager/sveltekit/LICENSE similarity index 100% rename from LICENSE rename to cookie-manager/sveltekit/LICENSE diff --git a/NOTICE b/cookie-manager/sveltekit/NOTICE similarity index 100% rename from NOTICE rename to cookie-manager/sveltekit/NOTICE diff --git a/cookie-manager/sveltekit/README.md b/cookie-manager/sveltekit/README.md new file mode 100644 index 0000000..c79e7da --- /dev/null +++ b/cookie-manager/sveltekit/README.md @@ -0,0 +1,209 @@ +# Sveltekit Cookie Manager 🍪 + +Sveltekit Cookie Manager is an easy-use Svelte package to help control the visitor's cookie consent. + +### Disclaimer + +Minimum required SvelteKit version: `1.0.0-next.581`. + +## About 📝 + +**Sveltekit Cookie Manager** reduces the workload of creating and mantaining multiple cookie consents by centralizing them into this package. Enables cookie management of following services: + +- Google Analytics Universal. +- Google Analytics 4. + +## Features ✨ + +- Display a customizable popup to accept or reject cookies. +- Create a cookie library showing: + - Tables with details about site's necessary cookies and additional cookies: cookie name, provider name and url, cookie category, purpose, expiry and type. + - Radio inputs (allow or reject all cookies) and a button to update preferences. + +## Installation 🧰 + +```shell +$ npm i @boxfish-studio/sveltekit-cookie-manager +``` + +or yarn + +```shell +$ yarn add @boxfish-studio/sveltekit-cookie-manager +``` + +
+ +## How to use 📝 + +### Show a popup + +Import the `CookieManager` component to your Svelte page and pass the configuration with your desired settings: + +```svelte + + + +``` + +### Show the cookie library + +Import the `CookieLibrary` component to your svelte file and pass the configuration with your desired settings, as shown in the example below. + +You can also use the library without any configuration or you can pass a `theme` to the configuration: + +```svelte + + + +``` + +### Using the internal store + +You can use the `servicesInitialized` writable to know whether the services are running or not. + +```ts +import { servicesInitialized } from '@boxfish-studio/sveltekit-cookie-manager' +import { get } from 'svelte/store' + +const isRunning = get(servicesInitialized) +``` + +## Configuration 🪛 + +Custom configuration must be of type `SKCMConfiguration`. All available props are shown below: + +```ts +type SKCMConfiguration = { + disclaimer: { + title?: string + body?: string + policyText?: string + policyUrl?: string + acceptButtonText?: string + rejectButtonText?: string + } + services: { + googleAnalyticsUniversalId?: string + googleAnalytics4Id?: string + adCookiesEnabled?: boolean + customNecessaryCookies?: { + name: string + provider: string + providerUrl: string + purpose: string + expiry: string + type: string + showDisclaimerIfMissing?: boolean + }[] + } + theme: { + primary?: string + dark?: string + medium?: string + light?: string + } +} +``` + +### Disclaimer props + +| Name | Description | Default value | +| ---------------- | --------------------------------- | -------------------------------------------------------- | +| title | The title of the popup | "Cookie Preferences" | +| body | Body message of the popup | "By using this site, you agree with our use of cookies." | +| policyText | Text that links to Privacy Policy | "Read our Cookie Policy" | +| policyUrl | Privacy Policy url | "/privacy-policy" | +| acceptButtonText | Text shown in 'Accept' button | "Accept Additional Cookies" | +| rejectButtonText | Text shown in 'Reject' button | "Reject Additional Cookies" | + +### Services props + +You must use `googleAnalyticsUniversalId` or `googleAnalytics4Id`. + +| Name | Description | Default value | +| -------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------- | +| googleAnalyticsUniversalId | Your Google Analytics Universal key | | +| googleAnalytics4Id | Your Google Analytics 4 key | | +| adCookiesEnabled | Whether cookies with the category Advertising should be set in the browser and shown in the library | true | +| customNecessaryCookies | Cookies that should be present in the Necessary Cookies table to inform the user their usage. To configure them see below | | + +### Custom necessary cookies + +You can configure extra cookies that will also appear in the Cookie library by specifying them in the `customNecessaryCookies` property. +They accept the following options: + +| Name | Description | Default value | Required | Example | +| ---------------------- | -------------------------------------------------------------------------- | ------------- | -------- | --------------------------- | +| name | Name of the cookie | | Yes | Boxfish Cookie | +| provider | Name of it's provider | | No | Boxfish | +| providerUrl | URL of it's provider | | No | https://boxfish.studio | +| purpose | Usage of the cookie | | Yes | "Stores the user's consent" | +| expiry | Time that the cookie with remain in the user's browser since it's creation | | Yes | "30 days" | +| type | Type of cookie | | Yes | "HTTP" | +| showDisclamerIfMissing | Show the accept/reject popup if this cookie is missing | false | No | true | + +### Theme props + +A 4-colour palette has been predefined following a custom style guide. You may overwrite these values in your custom configuration variable. + +| Name | Description | Default value | +| ------- | ----------------------------------------------------- | --------------- | +| primary | Used in buttons backgrounds, anchors | #14cabf (teal) | +| dark | Used in headings, body | #131f37 (black) | +| medium | Used in table headings, table borders | #b0bfd9 (gray) | +| light | Used in banner background colour, buttons text colour | #fff (white) | + +### Built with + +- Sveltekit. +- Typescript. + +## Release Package + +`npm run package && cd package && npm publish --access=public` + +## License + +[Apache 2.0](./LICENSE) © [Boxfish Studio] + +[Boxfish Studio]: https://boxfish.studio + +
+ +
+ Made with :heart: by Boxfish Studio.

+ Boxfish Logo +
diff --git a/cookie-manager/sveltekit/package.json b/cookie-manager/sveltekit/package.json new file mode 100644 index 0000000..175c103 --- /dev/null +++ b/cookie-manager/sveltekit/package.json @@ -0,0 +1,49 @@ +{ + "name": "@boxfish-studio/sveltekit-cookie-manager", + "version": "1.0.3", + "author": "Boxfish Studio ", + "license": "Apache-2.0", + "repository": "github:boxfish-studio/sveltekit-cookie-manager", + "homepage": "https://github.com/boxfish-studio/sveltekit-cookie-manager", + "bugs": "https://github.com/boxfish-studio/sveltekit-cookie-manager/issues", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "pre-package": "cp ../core ./src/lib/cookie-core -r", + "build:package": "pnpm pre-package && svelte-package", + "postpackage": "pnpm clean", + "clean": "rm -r ./package ./src/lib/cookie-core", + "package": "cross-env BUILDING_PACKAGE=true pnpm build:package", + "preview": "vite preview", + "check": "svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch", + "lint": "prettier --check . && eslint .", + "format": "prettier --write .", + "prepare": "svelte-kit sync" + }, + "dependencies": { + "sass": "^1.57.1", + "svelte": "^3.55.0" + }, + "devDependencies": { + "@repo/lint-staged-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@repo/eslint-config": "workspace:*", + "@sveltejs/adapter-auto": "1.0.0", + "@sveltejs/kit": "1.0.7", + "@sveltejs/package": "^1.0.2", + "@typescript-eslint/eslint-plugin": "^7.18.0", + "@typescript-eslint/parser": "^7.18.0", + "cross-env": "^7.0.3", + "eslint-config-prettier": "^9.1.0", + "prettier": "^3.2.5", + "prettier-plugin-svelte": "^3.2.6", + "svelte-check": "^3.0.2", + "svelte-eslint-parser": "^0.32.1", + "svelte-preprocess": "^5.0.0", + "tslib": "^2.4.1", + "typescript": "^5.4.5", + "vite": "^4.4.11" + }, + "type": "module" +} diff --git a/src/app.d.ts b/cookie-manager/sveltekit/src/app.d.ts similarity index 100% rename from src/app.d.ts rename to cookie-manager/sveltekit/src/app.d.ts diff --git a/src/app.html b/cookie-manager/sveltekit/src/app.html similarity index 93% rename from src/app.html rename to cookie-manager/sveltekit/src/app.html index f454f12..9da5ac1 100644 --- a/src/app.html +++ b/cookie-manager/sveltekit/src/app.html @@ -1,4 +1,4 @@ - + diff --git a/cookie-manager/sveltekit/src/lib/app/index.ts b/cookie-manager/sveltekit/src/lib/app/index.ts new file mode 100644 index 0000000..4d18ef3 --- /dev/null +++ b/cookie-manager/sveltekit/src/lib/app/index.ts @@ -0,0 +1,2 @@ +export * from './services' +export * from './store' diff --git a/src/lib/app/services.ts b/cookie-manager/sveltekit/src/lib/app/services.ts similarity index 90% rename from src/lib/app/services.ts rename to cookie-manager/sveltekit/src/lib/app/services.ts index d4c499c..268e63a 100644 --- a/src/lib/app/services.ts +++ b/cookie-manager/sveltekit/src/lib/app/services.ts @@ -1,9 +1,8 @@ -import { COOKIE_EXPIRATION_DAYS, GOOGLE_ANALYTICS_EXPIRATION_DAYS } from './constants' +import { GOOGLE_ANALYTICS_EXPIRATION_DAYS } from '$core/constants' import { browser } from '$app/environment' import { get } from 'svelte/store' -import { configuredServices, servicesInitialized } from './store' -import { SupportedService } from './types' -import { removeAdditionalCookies } from './utils' +import { configuredServices, servicesInitialized, removeAdditionalCookies } from './store' +import { SupportedService } from '$core/types' export const initializeServices = (): void => { if (!get(servicesInitialized)) { diff --git a/src/lib/app/store.ts b/cookie-manager/sveltekit/src/lib/app/store.ts similarity index 52% rename from src/lib/app/store.ts rename to cookie-manager/sveltekit/src/lib/app/store.ts index bdfb208..50f9f40 100644 --- a/src/lib/app/store.ts +++ b/cookie-manager/sveltekit/src/lib/app/store.ts @@ -1,14 +1,14 @@ -import type { Readable, Writable } from 'svelte/store' -import { derived, writable } from 'svelte/store' +import { type Readable, type Writable, derived, get, writable } from 'svelte/store' import { GoogleOwnCookies, SKCM_GA_GOOGLE_ANALYTICS_4_COOKIE, SKCM_GA_GOOGLE_ANALYTICS_UNIVERSAL_COOKIE -} from './cookieLib' -import { CookieCategory } from './enums' -import type { Service, ServiceCookie } from './types' -import { SupportedService } from './types' -import { getCookie } from './utils' +} from '$core/cookieLib' +import { CookieCategory } from '$core/enums' +import type { Service, ServiceCookie } from '$core/types' +import { SupportedService } from '$core/types' +import { deleteCookie, getCookie, setCookie } from '$core/utils' +import { COOKIE_EXPIRATION_DAYS } from '$core/constants' export const showCookieDisclaimer: Writable = writable(false) export const configuredServices: Writable = writable([]) @@ -63,3 +63,53 @@ export function initConfiguredServices( configuredServices.set(_configuredServices) necessaryCookies.set(_necessaryCookies) } + +// Check user has all needed necessary cookies already set +export const hasAllNeededNecessaryCookies = (): boolean => { + const neededCookies = + get(necessaryCookies)?.filter((cookie) => cookie?.showDisclaimerIfMissing) ?? [] + for (let i = 0; i < neededCookies?.length; i++) { + if (!getCookie(neededCookies[i].name)?.length) { + return false + } + } + return true +} + +export const submitNecessaryCookies = (value: 'true' | 'false'): void => { + const SKCM_NECESSARY_COOKIES: string[] = [ + SKCM_GA_GOOGLE_ANALYTICS_UNIVERSAL_COOKIE?.name, + SKCM_GA_GOOGLE_ANALYTICS_4_COOKIE?.name + ] + // set cookies + const neededCookies = + get(necessaryCookies)?.filter( + (cookie) => cookie?.showDisclaimerIfMissing && SKCM_NECESSARY_COOKIES.includes(cookie?.name) + ) ?? [] + for (let i = 0; i < neededCookies?.length; i++) { + setCookie(neededCookies[i]?.name, value, COOKIE_EXPIRATION_DAYS) + } + // enable services + const _configuredServices = get(configuredServices)?.map((service) => ({ + ...service, + enabled: value === 'true' + })) + configuredServices.set(_configuredServices) +} + +export const isServiceEnabled = (serviceType: SupportedService): boolean => { + const serviceConfig = get(configuredServices)?.find(({ type }) => type === serviceType) + return serviceConfig?.enabled +} + +export const removeAdditionalCookies = (): void => { + const _necessaryCookies = get(necessaryCookies).map((cookie) => cookie.name) + document.cookie + ?.split('; ') + ?.map((cookie) => cookie.split('=')[0]) + .forEach((cookie) => { + if (!_necessaryCookies.includes(cookie)) { + deleteCookie(cookie) + } + }) +} diff --git a/src/lib/components/Button.svelte b/cookie-manager/sveltekit/src/lib/components/Button.svelte similarity index 100% rename from src/lib/components/Button.svelte rename to cookie-manager/sveltekit/src/lib/components/Button.svelte diff --git a/src/lib/components/CookieLibrary/AdditionalCookies.svelte b/cookie-manager/sveltekit/src/lib/components/CookieLibrary/AdditionalCookies.svelte similarity index 100% rename from src/lib/components/CookieLibrary/AdditionalCookies.svelte rename to cookie-manager/sveltekit/src/lib/components/CookieLibrary/AdditionalCookies.svelte diff --git a/src/lib/components/CookieLibrary/NecessaryCookies.svelte b/cookie-manager/sveltekit/src/lib/components/CookieLibrary/NecessaryCookies.svelte similarity index 100% rename from src/lib/components/CookieLibrary/NecessaryCookies.svelte rename to cookie-manager/sveltekit/src/lib/components/CookieLibrary/NecessaryCookies.svelte diff --git a/src/lib/components/CookieLibrary/cookies.json b/cookie-manager/sveltekit/src/lib/components/CookieLibrary/cookies.json similarity index 100% rename from src/lib/components/CookieLibrary/cookies.json rename to cookie-manager/sveltekit/src/lib/components/CookieLibrary/cookies.json diff --git a/src/lib/components/CookieLibrary/index.svelte b/cookie-manager/sveltekit/src/lib/components/CookieLibrary/index.svelte similarity index 90% rename from src/lib/components/CookieLibrary/index.svelte rename to cookie-manager/sveltekit/src/lib/components/CookieLibrary/index.svelte index 6f732b6..8a1b1df 100644 --- a/src/lib/components/CookieLibrary/index.svelte +++ b/cookie-manager/sveltekit/src/lib/components/CookieLibrary/index.svelte @@ -1,9 +1,9 @@