diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e4aa1fc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +# 1. Ignore everything +**/* + +# 2. Add files and directories that should be included +!apps/** +!packages/** +!.npmrc +!package.json +!pnpm-lock.yaml +!pnpm-workspace.yaml +!turbo.json + +# 3. Bonus step: ignore any unnecessary files that may be inside those allowed directories in 2 +**/.DS_Store +**/Thumbs.db diff --git a/.env b/.env new file mode 100644 index 0000000..5c67ea1 --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +DB_HOST=localhost +DB_USER=aqs-api +DB_PASS=localPassword +DB_NAME=aqs diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..5c67ea1 --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +DB_HOST=localhost +DB_USER=aqs-api +DB_PASS=localPassword +DB_NAME=aqs diff --git a/.env.prod b/.env.prod new file mode 100644 index 0000000..cc5c489 --- /dev/null +++ b/.env.prod @@ -0,0 +1,4 @@ +DB_HOST=aqs-db +DB_USER=aqs-api +DB_PASS=52135gtfw3tk46ky029q309jg +DB_NAME=aqs diff --git a/.gitignore b/.gitignore index 0eebeb3..c7d9192 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ yarn-error.log* # turbo .turbo + +.volumes \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/aqs.iml b/.idea/aqs.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/.idea/aqs.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..7170db5 --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,12 @@ + + + + + postgresql + true + org.postgresql.Driver + jdbc:postgresql://192.168.0.140:5432/aqs + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..6d52f16 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/prettier.xml b/.idea/prettier.xml new file mode 100644 index 0000000..01baece --- /dev/null +++ b/.idea/prettier.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 44a73ec..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "eslint.workingDirectories": [ - { - "mode": "auto" - } - ] -} diff --git a/apps/docs/.eslintignore b/apps/docs/.eslintignore deleted file mode 100644 index 3897265..0000000 --- a/apps/docs/.eslintignore +++ /dev/null @@ -1,13 +0,0 @@ -.DS_Store -node_modules -/build -/.svelte-kit -/package -.env -.env.* -!.env.example - -# Ignore files for PNPM, NPM and YARN -pnpm-lock.yaml -package-lock.json -yarn.lock diff --git a/apps/docs/.eslintrc.cjs b/apps/docs/.eslintrc.cjs deleted file mode 100644 index ecdc496..0000000 --- a/apps/docs/.eslintrc.cjs +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ['@repo/eslint-config/index.js'] -}; diff --git a/apps/docs/.gitignore b/apps/docs/.gitignore deleted file mode 100644 index 6635cf5..0000000 --- a/apps/docs/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -.DS_Store -node_modules -/build -/.svelte-kit -/package -.env -.env.* -!.env.example -vite.config.js.timestamp-* -vite.config.ts.timestamp-* diff --git a/apps/docs/.npmrc b/apps/docs/.npmrc deleted file mode 100644 index b6f27f1..0000000 --- a/apps/docs/.npmrc +++ /dev/null @@ -1 +0,0 @@ -engine-strict=true diff --git a/apps/docs/.prettierignore b/apps/docs/.prettierignore deleted file mode 100644 index 7438ef3..0000000 --- a/apps/docs/.prettierignore +++ /dev/null @@ -1,14 +0,0 @@ -.DS_Store -node_modules -/build -/.svelte-kit -/package -.env -.env.* -!.env.example - -# Ignore files for PNPM, NPM and YARN -pnpm-lock.yaml -package-lock.json -yarn.lock -vite.config.*.timestamp-* diff --git a/apps/docs/.prettierrc b/apps/docs/.prettierrc deleted file mode 100644 index a77fdde..0000000 --- a/apps/docs/.prettierrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "useTabs": true, - "singleQuote": true, - "trailingComma": "none", - "printWidth": 100, - "plugins": ["prettier-plugin-svelte"], - "pluginSearchDirs": ["."], - "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] -} diff --git a/apps/docs/README.md b/apps/docs/README.md deleted file mode 100644 index 5c91169..0000000 --- a/apps/docs/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# create-svelte - -Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte). - -## Creating a project - -If you're seeing this, you've probably already done this step. Congrats! - -```bash -# create a new project in the current directory -npm create svelte@latest - -# create a new project in my-app -npm create svelte@latest my-app -``` - -## Developing - -Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: - -```bash -npm run dev - -# or start the server and open the app in a new browser tab -npm run dev -- --open -``` - -## Building - -To create a production version of your app: - -```bash -npm run build -``` - -You can preview the production build with `npm run preview`. - -> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. diff --git a/apps/docs/package.json b/apps/docs/package.json deleted file mode 100644 index 4a90b53..0000000 --- a/apps/docs/package.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "docs", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "dev": "vite dev", - "build": "vite build", - "preview": "vite preview", - "test": "npm run test:integration && npm run test:unit", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "lint": "eslint .", - "test:integration": "playwright test", - "test:unit": "vitest" - }, - "dependencies": { - "@repo/ui": "workspace:*" - }, - "devDependencies": { - "@playwright/test": "^1.42.1", - "@sveltejs/adapter-auto": "^3.1.1", - "@sveltejs/kit": "^2.5.2", - "@sveltejs/vite-plugin-svelte": "^3.0.2", - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", - "eslint": "^8.57.0", - "@repo/eslint-config": "workspace:*", - "prettier": "^3.2.5", - "prettier-plugin-svelte": "^3.2.2", - "svelte": "^4.2.12", - "svelte-check": "^3.6.6", - "tslib": "^2.6.2", - "typescript": "^5.3.3", - "vite": "^5.1.4", - "vitest": "^1.3.1" - } -} diff --git a/apps/docs/playwright.config.ts b/apps/docs/playwright.config.ts deleted file mode 100644 index 1c5d7a1..0000000 --- a/apps/docs/playwright.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; - -const config: PlaywrightTestConfig = { - webServer: { - command: 'npm run build && npm run preview', - port: 4173 - }, - testDir: 'tests', - testMatch: /(.+\.)?(test|spec)\.[jt]s/ -}; - -export default config; diff --git a/apps/docs/src/app.d.ts b/apps/docs/src/app.d.ts deleted file mode 100644 index f59b884..0000000 --- a/apps/docs/src/app.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -// See https://kit.svelte.dev/docs/types#app -// for information about these interfaces -declare global { - namespace App { - // interface Error {} - // interface Locals {} - // interface PageData {} - // interface Platform {} - } -} - -export {}; diff --git a/apps/docs/src/app.html b/apps/docs/src/app.html deleted file mode 100644 index 6769ed5..0000000 --- a/apps/docs/src/app.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - %sveltekit.head% - - -
%sveltekit.body%
- - diff --git a/apps/docs/src/index.test.ts b/apps/docs/src/index.test.ts deleted file mode 100644 index e07cbbd..0000000 --- a/apps/docs/src/index.test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { describe, it, expect } from 'vitest'; - -describe('sum test', () => { - it('adds 1 + 2 to equal 3', () => { - expect(1 + 2).toBe(3); - }); -}); diff --git a/apps/docs/src/lib/index.ts b/apps/docs/src/lib/index.ts deleted file mode 100644 index 856f2b6..0000000 --- a/apps/docs/src/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -// place files you want to import through the `$lib` alias in this folder. diff --git a/apps/docs/src/routes/+page.svelte b/apps/docs/src/routes/+page.svelte deleted file mode 100644 index e9034fe..0000000 --- a/apps/docs/src/routes/+page.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - -

Docs

- -

Visit kit.svelte.dev to read the documentation

diff --git a/apps/docs/static/favicon.png b/apps/docs/static/favicon.png deleted file mode 100644 index 825b9e6..0000000 Binary files a/apps/docs/static/favicon.png and /dev/null differ diff --git a/apps/docs/svelte.config.js b/apps/docs/svelte.config.js deleted file mode 100644 index 186735e..0000000 --- a/apps/docs/svelte.config.js +++ /dev/null @@ -1,17 +0,0 @@ -import adapter from '@sveltejs/adapter-auto'; -import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; - -/** @type {import('@sveltejs/kit').Config} */ -const config = { - // Consult https://kit.svelte.dev/docs/integrations#preprocessors - // for more information about preprocessors - preprocess: vitePreprocess(), - kit: { - // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. - // If your environment is not supported or you settled on a specific environment, switch out the adapter. - // See https://kit.svelte.dev/docs/adapters for more information about adapters. - adapter: adapter() - } -}; - -export default config; diff --git a/apps/docs/tests/test.ts b/apps/docs/tests/test.ts deleted file mode 100644 index 8fefdc8..0000000 --- a/apps/docs/tests/test.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { expect, test } from '@playwright/test'; - -test('index page has expected h1', async ({ page }) => { - await page.goto('/'); - await expect(page.getByRole('heading', { name: 'Docs' })).toBeVisible(); -}); diff --git a/apps/docs/tsconfig.json b/apps/docs/tsconfig.json deleted file mode 100644 index 6ae0c8c..0000000 --- a/apps/docs/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "extends": "./.svelte-kit/tsconfig.json", - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true - } - // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias - // - // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes - // from the referenced tsconfig.json - TypeScript does not merge them in -} diff --git a/apps/docs/vite.config.ts b/apps/docs/vite.config.ts deleted file mode 100644 index 88c48d3..0000000 --- a/apps/docs/vite.config.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { sveltekit } from '@sveltejs/kit/vite'; -import { defineConfig } from 'vitest/config'; - -export default defineConfig({ - plugins: [sveltekit()], - test: { - include: ['src/**/*.{test,spec}.{js,ts}'] - }, - build: { - commonjsOptions: { - include: [/@repo-ui/, /node_modules/], - }, - }, -}); diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile new file mode 100644 index 0000000..ba2602f --- /dev/null +++ b/apps/web/Dockerfile @@ -0,0 +1,21 @@ +# syntax=docker/dockerfile:1 + +ARG NODE_VERSION=20.4.0 +ARG PNPM_VERSION=8.6.7 + +FROM node:${NODE_VERSION}-alpine as base + +WORKDIR /app + +RUN npm install -g pnpm@${PNPM_VERSION} + +COPY . . + +RUN pnpm install + +RUN pnpm build + +USER node +ENV NODE_ENV production + +CMD pnpm --filter ./packages/database migrate && node apps/web/build/index.js diff --git a/apps/web/package.json b/apps/web/package.json index 45f7936..c35b2de 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,5 +1,5 @@ { - "name": "web", + "name": "web", "version": "0.0.1", "private": true, "type": "module", @@ -15,21 +15,28 @@ "test:unit": "vitest" }, "dependencies": { - "@repo/ui": "workspace:*" + "@repo/db": "workspace:*", + "@repo/shared-types": "workspace:*", + "@repo/ui": "workspace:*", + "chart.js": "^4.4.2", + "postgres": "^3.4.3" }, "devDependencies": { "@playwright/test": "^1.42.1", - "@sveltejs/adapter-auto": "^3.1.1", + "@repo/eslint-config": "workspace:*", + "@sveltejs/adapter-node": "^5.0.1", "@sveltejs/kit": "^2.5.2", "@sveltejs/vite-plugin-svelte": "^3.0.2", "@typescript-eslint/eslint-plugin": "^7.1.0", "@typescript-eslint/parser": "^7.1.0", + "autoprefixer": "^10.4.18", "eslint": "^8.57.0", - "@repo/eslint-config": "workspace:*", + "postcss": "^8.4.36", "prettier": "^3.2.5", "prettier-plugin-svelte": "^3.2.2", "svelte": "^4.2.12", "svelte-check": "^3.6.6", + "tailwindcss": "^3.4.1", "tslib": "^2.6.2", "typescript": "^5.3.3", "vite": "^5.1.4", diff --git a/apps/web/postcss.config.js b/apps/web/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/apps/web/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/apps/web/src/app.css b/apps/web/src/app.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/apps/web/src/app.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/apps/web/src/app.html b/apps/web/src/app.html index 6769ed5..ab2998d 100644 --- a/apps/web/src/app.html +++ b/apps/web/src/app.html @@ -1,12 +1,12 @@ - - + + %sveltekit.head% - +
%sveltekit.body%
diff --git a/apps/web/src/hooks.server.ts b/apps/web/src/hooks.server.ts new file mode 100644 index 0000000..879afc8 --- /dev/null +++ b/apps/web/src/hooks.server.ts @@ -0,0 +1,9 @@ +import type { Handle } from '@sveltejs/kit'; + +export const handle: Handle = async ({ event, resolve }) => { + const start = Date.now(); + console.log(event.request.method, event.request.url); + const result = await resolve(event); + console.log(event.request.method, event.request.url, result.status, Date.now() - start + 'ms'); + return result; +}; diff --git a/apps/web/src/lib/components/chart.svelte b/apps/web/src/lib/components/chart.svelte new file mode 100644 index 0000000..e24ea63 --- /dev/null +++ b/apps/web/src/lib/components/chart.svelte @@ -0,0 +1,234 @@ + + +
+

+ {model.title} + + {data[data.length - 1]?.value} {model.unit} +

+ +
+ +
+ + + +
diff --git a/apps/web/src/lib/components/charts.svelte b/apps/web/src/lib/components/charts.svelte new file mode 100644 index 0000000..f714167 --- /dev/null +++ b/apps/web/src/lib/components/charts.svelte @@ -0,0 +1,18 @@ + + +
+ + {#each models as model} + {#if !model.isForDebugOnly || isDebugParamInURL} + + {/if} + {/each} +
\ No newline at end of file diff --git a/apps/web/src/lib/components/filter.svelte b/apps/web/src/lib/components/filter.svelte new file mode 100644 index 0000000..adf3116 --- /dev/null +++ b/apps/web/src/lib/components/filter.svelte @@ -0,0 +1,23 @@ + + +
+ +
diff --git a/apps/web/src/lib/components/index.ts b/apps/web/src/lib/components/index.ts new file mode 100644 index 0000000..96180fd --- /dev/null +++ b/apps/web/src/lib/components/index.ts @@ -0,0 +1,2 @@ +export {default as Filter} from './filter.svelte'; +export {default as Charts} from './charts.svelte'; \ No newline at end of file diff --git a/apps/web/src/lib/components/models.ts b/apps/web/src/lib/components/models.ts new file mode 100644 index 0000000..ea8bdd2 --- /dev/null +++ b/apps/web/src/lib/components/models.ts @@ -0,0 +1,211 @@ +import type { Measurement } from '@repo/shared-types'; + +export const chartReferenceBoxTransparency = 0.2; +const colorCodes = { + GOOD: [33, 166, 5], + OK: [239, 200, 2], + BAD: [255, 153, 0], + VERY_BAD: [255, 68, 0], + DANGER: [253, 0, 0] +}; + +export interface ChartReference { + title: string; + color: string | number[]; + max: number; + min: number; + placement?: 'start' | 'end'; +} + +export interface Model { + title: string; + field: keyof Measurement; + fieldTitle?: string; + color: string; + yMin: number; + yMax?: number; + unit?: string; + references?: ChartReference[]; + isForDebugOnly?: boolean; +} + +export const models: Model[] = [ + { + title: `Freshness, CO2`, + field: 'co2', + fieldTitle: 'CO2', + color: 'rgb(75, 192, 192)', + yMin: 400, + yMax: 1200, + unit: 'ppm', + references: [ + { + title: 'Headache', + color: colorCodes.VERY_BAD, + max: 2000, + min: 1500, + placement: 'end' + }, + { + title: 'Low productivity, Laziness', + color: colorCodes.BAD, + max: 1500, + min: 1200, + placement: 'end' + }, + { + title: 'Time to refresh air', + color: colorCodes.OK, + max: 1200, + min: 800 + }, + { + title: 'Fresh air', + color: colorCodes.GOOD, + max: 800, + min: 400 + } + ] + }, + { + title: 'Pollution, PM 2.5', + field: 'pm2p5', + fieldTitle: 'PM 2.5', + color: 'orange', + yMin: 0, + yMax: 35, + unit: 'μg/m3', + references: [ + { + title: 'Hazardous', + color: colorCodes.DANGER, + max: 500, + min: 100, + placement: 'end' + }, + { + title: 'Very Unhealthy', + color: colorCodes.VERY_BAD, + max: 100, + min: 55, + placement: 'end' + }, + { + title: 'Unhealthy', + color: colorCodes.BAD, + max: 55, + min: 35, + placement: 'end' + }, + { + title: 'Moderate', + color: colorCodes.OK, + max: 35, + min: 12 + }, + { + title: 'Clean', + color: colorCodes.GOOD, + max: 12, + min: 0 + } + ] + }, + { + title: 'Temperature', + field: 'temperature', + fieldTitle: '', + color: 'red', + unit: '°C', + yMin: 20, + yMax: 30, + references: [ + { + title: 'Too hot', + color: colorCodes.DANGER, + max: 50, + min: 32, + placement: 'end' + }, + { + title: 'Hot', + color: colorCodes.OK, + max: 32, + min: 27 + }, + { + title: 'Optimum', + color: colorCodes.GOOD, + max: 27, + min: 22 + }, + { + title: 'Chill', + color: `rgba(0,255,233,${chartReferenceBoxTransparency})`, + max: 22, + min: 15, + placement: 'start' + }, + { + title: 'Cold', + color: `rgba(0,33,255,${chartReferenceBoxTransparency})`, + max: 15, + min: -50, + placement: 'start' + } + ] + }, + { + title: 'Humidity', + field: 'humidity', + fieldTitle: '', + color: 'blue', + unit: '%', + yMin: 25, + yMax: 70, + references: [ + { + title: 'Too humid', + color: colorCodes.BAD, + max: 100, + min: 70, + placement: 'end' + }, + { + title: 'Moderate', + color: colorCodes.OK, + max: 70, + min: 60 + }, + { + title: 'Optimum', + color: colorCodes.GOOD, + max: 60, + min: 40 + }, + { + title: 'Moderate', + color: colorCodes.OK, + max: 40, + min: 25 + }, + { + title: 'Too dry', + color: colorCodes.BAD, + max: 25, + min: 0, + placement: 'start' + } + ] + }, + + { + title: 'Time alive', + isForDebugOnly: true, + field: 'uptime', + fieldTitle: '', + color: 'forestgreen', + yMin: 0, + unit: 'Sec' + } +]; diff --git a/apps/web/src/lib/index.ts b/apps/web/src/lib/index.ts deleted file mode 100644 index 856f2b6..0000000 --- a/apps/web/src/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -// place files you want to import through the `$lib` alias in this folder. diff --git a/apps/web/src/lib/stores/data.ts b/apps/web/src/lib/stores/data.ts new file mode 100644 index 0000000..41dbaeb --- /dev/null +++ b/apps/web/src/lib/stores/data.ts @@ -0,0 +1,47 @@ +import type {Measurement} from "@repo/shared-types"; +import {get, writable} from "svelte/store"; +import {browser} from "$app/environment"; + +interface Store { + fetchedAt: null | Date; + measurements: Measurement[]; + filterHours: number; + isLoading: boolean; + error: null | string; +} + +const initialStore: Store = { + fetchedAt: null, + measurements: [], + filterHours: 1, + isLoading: false, + error: null, +} + +const store = writable(initialStore); + +async function load(filterHours?: number) { + if(!filterHours) { + filterHours = get(store).filterHours; + } + store.update(state => ({...state, filterHours: filterHours || 1, isLoading: true, error: null})); + try { + const response = await fetch(`/api/aqs?hours=${filterHours}`); + const measurements = await response.json(); + store.update(state => ({...state, measurements, isLoading: false, error: null, fetchedAt: new Date()})); + } catch (e: unknown) { + store.update(state => ({...state, isLoading: false, error: (e as Error).message})); + } +} + +export const data = { + subscribe: store.subscribe, + setFilterHours: async (hours: number): Promise => { + await load(hours); + } +} + +if (browser) { + void load(initialStore.filterHours); + setInterval(() => void load(), 2 * 60 * 1000); +} \ No newline at end of file diff --git a/apps/web/src/lib/stores/index.ts b/apps/web/src/lib/stores/index.ts new file mode 100644 index 0000000..b7e2a5f --- /dev/null +++ b/apps/web/src/lib/stores/index.ts @@ -0,0 +1 @@ +export * from './data' \ No newline at end of file diff --git a/apps/web/src/routes/+layout.svelte b/apps/web/src/routes/+layout.svelte new file mode 100644 index 0000000..1fe2550 --- /dev/null +++ b/apps/web/src/routes/+layout.svelte @@ -0,0 +1,5 @@ + + + diff --git a/apps/web/src/routes/+page.svelte b/apps/web/src/routes/+page.svelte index 3b6d759..9b02f5e 100644 --- a/apps/web/src/routes/+page.svelte +++ b/apps/web/src/routes/+page.svelte @@ -1,7 +1,30 @@ -

Web

- -

Visit kit.svelte.dev to read the documentation

+
+

Air Quality

+ {#if $data.isLoading} +

Loading...

+ {:else if $data.error} +

Error: {$data.error}

+ {:else} +

Last updated {updatedSecondsAgo} seconds ago

+ {/if} + + data.setFilterHours(e.detail.hours)} /> + + +
diff --git a/apps/web/src/routes/api/aqs/+server.ts b/apps/web/src/routes/api/aqs/+server.ts new file mode 100644 index 0000000..7fefd4e --- /dev/null +++ b/apps/web/src/routes/api/aqs/+server.ts @@ -0,0 +1,34 @@ +import { type RequestHandler, json } from '@sveltejs/kit'; +import { SensorDataSchema } from '@repo/shared-types'; +import { db } from '@repo/db'; + +export const GET: RequestHandler = async ({ url }) => { + const hours = Number(url.searchParams.get('hours')) || 1; + const measurements = await db.measurements.findMany(hours); + return json(measurements); +}; + +export const POST: RequestHandler = async ({ request }) => { + const jsonPayload = await request.json(); + const parseResult = SensorDataSchema.safeParse(jsonPayload); + if (!parseResult.success) { + return jsonPayload(parseResult.error.formErrors, 400); + } + const payload = parseResult.data; + + const originalUptimeMoment = payload.u * 1000; + const now = Date.now(); + + await db.measurements.createMany( + payload.d.map((v) => ({ + co2: v.c, + pm2p5: v.pm2p5, + temperature: v.t, + humidity: v.h, + uptime: v.u, + createdAt: new Date(now - (originalUptimeMoment - v.u * 1000)) + })) + ); + + return json({ success: true }); +}; diff --git a/apps/web/svelte.config.js b/apps/web/svelte.config.js index 9041ab6..512a225 100644 --- a/apps/web/svelte.config.js +++ b/apps/web/svelte.config.js @@ -1,4 +1,4 @@ -import adapter from '@sveltejs/adapter-auto'; +import adapter from '@sveltejs/adapter-node'; import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; /** @type {import('@sveltejs/kit').Config} */ @@ -10,8 +10,16 @@ const config = { // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. // If your environment is not supported or you settled on a specific environment, switch out the adapter. // See https://kit.svelte.dev/docs/adapters for more information about adapters. - adapter: adapter() - }, + adapter: adapter(), + + alias: { + '@components': './src/lib/components', + '@stores': './src/lib/stores' + }, + env: { + dir: '../..' + } + } }; export default config; diff --git a/apps/web/tailwind.config.js b/apps/web/tailwind.config.js new file mode 100644 index 0000000..bfe0bc2 --- /dev/null +++ b/apps/web/tailwind.config.js @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./src/**/*.{html,js,svelte,ts}'], + theme: { + extend: {} + }, + plugins: [] +}; diff --git a/dev.compose.yml b/dev.compose.yml new file mode 100644 index 0000000..99b1b2e --- /dev/null +++ b/dev.compose.yml @@ -0,0 +1,17 @@ +version: '3.8' + +name: aqs + +services: + aqs-db: + container_name: aqs-db + image: postgres:15-alpine + restart: always + environment: + POSTGRES_USER: aqs-api + POSTGRES_PASSWORD: localPassword + POSTGRES_DB: aqs + ports: + - 5432:5432 + volumes: + - ./.volumes/postgres:/var/lib/postgresql/data \ No newline at end of file diff --git a/package.json b/package.json index ae3f0c1..12dd71c 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,10 @@ "build": "turbo run build", "dev": "turbo run dev", "lint": "turbo run lint", - "format": "prettier --write ." + "format": "prettier --write .", + "prod:deploy": "pnpm prod:deploy:copy && pnpm prod:deploy:run", + "prod:deploy:copy": "rsync -avz -e 'ssh' . homelab:~/apps/aqs --include-from='prod.deploy.files.txt' --exclude '*'", + "prod:deploy:run": "ssh homelab 'cd apps/aqs && docker compose -f prod.compose.yml build && docker compose --env-file=.env.prod --env-file=../.env -f prod.compose.yml down && docker compose --env-file=.env.prod --env-file=../.env -f prod.compose.yml up -d'" }, "devDependencies": { "eslint": "^8.57.0", diff --git a/packages/database/env.ts b/packages/database/env.ts new file mode 100644 index 0000000..292545f --- /dev/null +++ b/packages/database/env.ts @@ -0,0 +1,21 @@ +import { config } from 'dotenv'; + +const isProd = process.env.NODE_ENV === 'prod' || process.env.NODE_ENV === 'production'; + +const isEnvLoadedAlready = + process.env.DB_HOST && process.env.DB_USER && process.env.DB_PASS && process.env.DB_NAME; + +if (!isEnvLoadedAlready) { + const basePath = `../..`; + config({ path: isProd ? `${basePath}/.env.prod` : `${basePath}/.env` }); +} + +export const env = { + isProd, + db: { + host: process.env.DB_HOST, + user: process.env.DB_USER, + pass: process.env.DB_PASS, + db: process.env.DB_NAME + } +}; diff --git a/packages/database/index.ts b/packages/database/index.ts new file mode 100644 index 0000000..2dcce47 --- /dev/null +++ b/packages/database/index.ts @@ -0,0 +1,23 @@ +import type { Measurement, MeasurementBase } from '@repo/shared-types'; +import { sql } from './lib'; + +// Uncomment for debugging queries +sql.options.debug = (_, query, parameters) => + console.log(query, parameters.length ? parameters : ''); +// TODO: automatically log if query takes too long + +export const db = { + $connect: async (): Promise => { + await sql`SELECT 1`; + }, + $shutdown: async (): Promise => sql.end({ timeout: 5 }), + measurements: { + createMany: async (measurements: MeasurementBase[]): Promise => { + await sql`INSERT INTO measurements ${sql(measurements)}`; + }, + findMany: async (hours: number): Promise => { + const createdAtGt = new Date(Date.now() - hours * 60 * 60 * 1000); + return await sql`SELECT * FROM measurements WHERE created_at > ${createdAtGt} ORDER BY created_at ASC`; + } + } +}; diff --git a/packages/database/lib.ts b/packages/database/lib.ts new file mode 100644 index 0000000..e8a7e64 --- /dev/null +++ b/packages/database/lib.ts @@ -0,0 +1,7 @@ +import postgres from 'postgres'; +import { env } from './env'; + +export const sql = postgres({ + ...env.db, + transform: postgres.camel +}); diff --git a/packages/database/migrate.ts b/packages/database/migrate.ts new file mode 100644 index 0000000..d9e6322 --- /dev/null +++ b/packages/database/migrate.ts @@ -0,0 +1,73 @@ +import { readdirSync, readFileSync } from 'fs'; +import { extname, join } from 'path'; +import { sql } from './lib'; + +const migrationsFolder: string = './migrations'; +const fileExtension: string = '.sql'; + +async function applyMigrations(): Promise { + try { + const tableExists: { exists: boolean }[] = + await sql`SELECT exists (SELECT FROM information_schema.tables WHERE table_name = 'migrations')`; + + if (!tableExists[0].exists) { + await sql` + CREATE TABLE migrations ( + id SERIAL PRIMARY KEY, + name VARCHAR(100) NOT NULL, + created_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP + ) + `; + console.log('Migrations table was created.\n'); + } + } catch (err) { + console.error('❌ Failed to create migrations table', err); + process.exit(1); + } + + let migrations: string[] = []; + + try { + const migrationsResult: any = await sql`SELECT name FROM migrations`; + migrations = migrationsResult.map(({ name }: { name: string }) => name); + } catch (err) { + console.error('❌ Failed to get migrations from database', err); + process.exit(1); + } + + try { + const files: string[] = readdirSync(migrationsFolder); + + const migrationsToApply: string[] = files + .filter((file: string) => extname(file) === fileExtension) + .map((file: string) => file.replace(fileExtension, '')) + .filter((file: string) => !migrations.includes(file)) + .sort(); + + if (!migrationsToApply.length) { + console.log('✅ No new migrations to apply.'); + process.exit(0); + } + console.log(`Applying ${migrationsToApply.length} migration(s):`); + + for (let migration of migrationsToApply) { + console.log('- ' + migration); + const sqlScript: string = readFileSync( + join(migrationsFolder, migration + fileExtension), + 'utf8' + ); + await sql.begin(async (tx: any) => { + await tx.unsafe(sqlScript); + await tx`INSERT INTO migrations (name) VALUES (${migration})`; + }); + } + + console.log('\n✅ Migrations successfully applied.'); + process.exit(0); + } catch (err) { + console.error('\n❌ Failed to apply migrations\n', err); + process.exit(1); + } +} + +void applyMigrations(); diff --git a/packages/database/migrations/20240128_0838_init.sql b/packages/database/migrations/20240128_0838_init.sql new file mode 100644 index 0000000..0d439ed --- /dev/null +++ b/packages/database/migrations/20240128_0838_init.sql @@ -0,0 +1,9 @@ +CREATE TABLE measurements ( + id SERIAL PRIMARY KEY, + temperature FLOAT NOT NULL, + humidity FLOAT NOT NULL, + co2 INT2 NOT NULL, + pm2p5 INT2 NOT NULL, + uptime INT4 NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT NOW() +) diff --git a/packages/database/package.json b/packages/database/package.json new file mode 100644 index 0000000..ee50178 --- /dev/null +++ b/packages/database/package.json @@ -0,0 +1,22 @@ +{ + "name": "@repo/db", + "version": "0.0.0", + "type": "module", + "module": "index.ts", + "main": "index.ts", + "scripts": { + "lint": "eslint .", + "migrate": "tsx ./migrate.ts", + "purge": "tsx ./purge.ts" + }, + "dependencies": { + "@repo/shared-types": "workspace:*", + "dotenv": "^16.4.5", + "postgres": "^3.4.3" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@types/node": "^20.11.30", + "tsx": "^4.7.1" + } +} diff --git a/packages/database/purge.ts b/packages/database/purge.ts new file mode 100644 index 0000000..b2befe2 --- /dev/null +++ b/packages/database/purge.ts @@ -0,0 +1,45 @@ +import { sql } from './lib'; +import { env } from './env'; + +/** Drops all tables from the database. + * if NODE_ENV!='prod' || 'production' and not --prod - then abort */ +async function purge(): Promise { + if (env.isProd && !process.argv.includes('--prod')) { + console.error('❌ Cannot purge database in production'); + process.exit(1); + } + let tables: string[] = []; + try { + console.log('Fetching table names...'); + const result = await sql<{ tableName: string }[]>` + SELECT table_name + FROM information_schema.tables + WHERE table_schema = 'public' + AND table_type = 'BASE TABLE' + `; + tables = result.map(({ tableName }) => tableName); + } catch (err) { + console.error('❌ Failed to fetch table names', err); + process.exit(1); + } + + if (!tables.length) { + console.log('\n✅ No tables to purge.'); + process.exit(0); + } + + try { + console.log(`Purging ${tables.length} tables:`); + for (let table of tables) { + console.log('- ' + table); + await sql`DROP TABLE ${sql(table)} CASCADE`; + } + console.log('\n✅ Database purged.'); + process.exit(0); + } catch (err) { + console.error('\n❌ Failed to purge database\n', err); + process.exit(1); + } +} + +void purge(); diff --git a/packages/database/tsconfig.json b/packages/database/tsconfig.json new file mode 100644 index 0000000..32e2698 --- /dev/null +++ b/packages/database/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "bundler", + "target": "ESNext", + "isolatedModules": true, + "esModuleInterop": true, + "noEmit": true, + "allowImportingTsExtensions": true, + "outDir": "dist", + "lib": ["esnext"], + "types": ["node"], + "baseUrl": "./", + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true + }, + "exclude": ["node_modules"], + "include": ["./*.ts"] +} diff --git a/packages/shared-types/.eslintrc.cjs b/packages/shared-types/.eslintrc.cjs new file mode 100644 index 0000000..09b87ad --- /dev/null +++ b/packages/shared-types/.eslintrc.cjs @@ -0,0 +1,3 @@ +module.exports = { + extends: ['@repo/eslint-config/index.js'] +}; diff --git a/packages/shared-types/index.ts b/packages/shared-types/index.ts new file mode 100644 index 0000000..3982881 --- /dev/null +++ b/packages/shared-types/index.ts @@ -0,0 +1,37 @@ +import { z } from 'zod'; + +export const SensorDataSchema = z.object({ + u: z.number(), + d: z.array( + z.object({ + u: z.number(), + c: z.number(), + pm2p5: z.number(), + t: z.number(), + h: z.number() + }) + ) +}); +export type SensorData = z.infer; + +export const IdSchema = z.object({ + id: z.number().int().positive() +}); +export const CreatedAtSchema = z.object({ + createdAt: z.date() +}); +export const BaseSchema = IdSchema.merge(CreatedAtSchema); + +export const MeasurementBaseSchema = CreatedAtSchema.merge( + z.object({ + co2: z.number().int().positive(), + pm2p5: z.number().int().positive(), + temperature: z.number().min(-273.15).max(100), + humidity: z.number().min(0).max(100), + uptime: z.number().int().positive() + }) +); + +export type MeasurementBase = z.infer; +export const MeasurementSchema = MeasurementBaseSchema.merge(BaseSchema); +export type Measurement = z.infer; diff --git a/packages/shared-types/package.json b/packages/shared-types/package.json new file mode 100644 index 0000000..8ed1ec8 --- /dev/null +++ b/packages/shared-types/package.json @@ -0,0 +1,17 @@ +{ + "name": "@repo/shared-types", + "version": "0.0.0", + "type": "module", + "module": "index.ts", + "main": "index.ts", + "types": "index.ts", + "scripts": { + "lint": "eslint ." + }, + "dependencies": { + "zod": "^3.22.4" + }, + "devDependencies": { + "@repo/eslint-config": "*" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 045fdda..582c895 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,66 +24,23 @@ importers: specifier: latest version: 1.12.5 - apps/docs: - dependencies: - '@repo/ui': - specifier: workspace:* - version: link:../../packages/ui - devDependencies: - '@playwright/test': - specifier: ^1.42.1 - version: 1.42.1 - '@repo/eslint-config': - specifier: workspace:* - version: link:../../packages/config-eslint - '@sveltejs/adapter-auto': - specifier: ^3.1.1 - version: 3.1.1(@sveltejs/kit@2.5.2) - '@sveltejs/kit': - specifier: ^2.5.2 - version: 2.5.2(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@4.2.12)(vite@5.1.4) - '@sveltejs/vite-plugin-svelte': - specifier: ^3.0.2 - version: 3.0.2(svelte@4.2.12)(vite@5.1.4) - '@typescript-eslint/eslint-plugin': - specifier: ^7.1.0 - version: 7.1.0(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.3.3) - '@typescript-eslint/parser': - specifier: ^7.1.0 - version: 7.1.0(eslint@8.57.0)(typescript@5.3.3) - eslint: - specifier: ^8.57.0 - version: 8.57.0 - prettier: - specifier: ^3.2.5 - version: 3.2.5 - prettier-plugin-svelte: - specifier: ^3.2.2 - version: 3.2.2(prettier@3.2.5)(svelte@4.2.12) - svelte: - specifier: ^4.2.12 - version: 4.2.12 - svelte-check: - specifier: ^3.6.6 - version: 3.6.6(svelte@4.2.12) - tslib: - specifier: ^2.6.2 - version: 2.6.2 - typescript: - specifier: ^5.3.3 - version: 5.3.3 - vite: - specifier: ^5.1.4 - version: 5.1.4 - vitest: - specifier: ^1.3.1 - version: 1.3.1 - apps/web: dependencies: + '@repo/db': + specifier: workspace:* + version: link:../../packages/database + '@repo/shared-types': + specifier: workspace:* + version: link:../../packages/shared-types '@repo/ui': specifier: workspace:* version: link:../../packages/ui + chart.js: + specifier: ^4.4.2 + version: 4.4.2 + postgres: + specifier: ^3.4.3 + version: 3.4.3 devDependencies: '@playwright/test': specifier: ^1.42.1 @@ -91,9 +48,9 @@ importers: '@repo/eslint-config': specifier: workspace:* version: link:../../packages/config-eslint - '@sveltejs/adapter-auto': - specifier: ^3.1.1 - version: 3.1.1(@sveltejs/kit@2.5.2) + '@sveltejs/adapter-node': + specifier: ^5.0.1 + version: 5.0.1(@sveltejs/kit@2.5.2) '@sveltejs/kit': specifier: ^2.5.2 version: 2.5.2(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@4.2.12)(vite@5.1.4) @@ -106,9 +63,15 @@ importers: '@typescript-eslint/parser': specifier: ^7.1.0 version: 7.1.0(eslint@8.57.0)(typescript@5.3.3) + autoprefixer: + specifier: ^10.4.18 + version: 10.4.18(postcss@8.4.36) eslint: specifier: ^8.57.0 version: 8.57.0 + postcss: + specifier: ^8.4.36 + version: 8.4.36 prettier: specifier: ^3.2.5 version: 3.2.5 @@ -120,7 +83,10 @@ importers: version: 4.2.12 svelte-check: specifier: ^3.6.6 - version: 3.6.6(svelte@4.2.12) + version: 3.6.6(postcss@8.4.36)(svelte@4.2.12) + tailwindcss: + specifier: ^3.4.1 + version: 3.4.1 tslib: specifier: ^2.6.2 version: 2.6.2 @@ -152,6 +118,38 @@ importers: specifier: ^2.35.1 version: 2.35.1(eslint@8.57.0)(svelte@4.2.12) + packages/database: + dependencies: + '@repo/shared-types': + specifier: workspace:* + version: link:../shared-types + dotenv: + specifier: ^16.4.5 + version: 16.4.5 + postgres: + specifier: ^3.4.3 + version: 3.4.3 + devDependencies: + '@repo/eslint-config': + specifier: workspace:* + version: link:../config-eslint + '@types/node': + specifier: ^20.11.30 + version: 20.11.30 + tsx: + specifier: ^4.7.1 + version: 4.7.1 + + packages/shared-types: + dependencies: + zod: + specifier: ^3.22.4 + version: 3.22.4 + devDependencies: + '@repo/eslint-config': + specifier: '*' + version: link:../config-eslint + packages/ui: devDependencies: '@repo/eslint-config': @@ -167,6 +165,11 @@ packages: resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} engines: {node: '>=0.10.0'} + /@alloc/quick-lru@5.2.0: + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + dev: true + /@ampproject/remapping@2.3.0: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} @@ -174,6 +177,24 @@ packages: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 + /@esbuild/aix-ppc64@0.19.12: + resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.19.12: + resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm64@0.19.7: resolution: {integrity: sha512-YEDcw5IT7hW3sFKZBkCAQaOCJQLONVcD4bOyTXMZz5fr66pTHnAet46XAtbXAkJRfIn2YVhdC6R9g4xa27jQ1w==} engines: {node: '>=12'} @@ -183,6 +204,15 @@ packages: dev: true optional: true + /@esbuild/android-arm@0.19.12: + resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm@0.19.7: resolution: {integrity: sha512-YGSPnndkcLo4PmVl2tKatEn+0mlVMr3yEpOOT0BeMria87PhvoJb5dg5f5Ft9fbCVgtAz4pWMzZVgSEGpDAlww==} engines: {node: '>=12'} @@ -192,6 +222,15 @@ packages: dev: true optional: true + /@esbuild/android-x64@0.19.12: + resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-x64@0.19.7: resolution: {integrity: sha512-jhINx8DEjz68cChFvM72YzrqfwJuFbfvSxZAk4bebpngGfNNRm+zRl4rtT9oAX6N9b6gBcFaJHFew5Blf6CvUw==} engines: {node: '>=12'} @@ -201,6 +240,15 @@ packages: dev: true optional: true + /@esbuild/darwin-arm64@0.19.12: + resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-arm64@0.19.7: resolution: {integrity: sha512-dr81gbmWN//3ZnBIm6YNCl4p3pjnabg1/ZVOgz2fJoUO1a3mq9WQ/1iuEluMs7mCL+Zwv7AY5e3g1hjXqQZ9Iw==} engines: {node: '>=12'} @@ -210,6 +258,15 @@ packages: dev: true optional: true + /@esbuild/darwin-x64@0.19.12: + resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-x64@0.19.7: resolution: {integrity: sha512-Lc0q5HouGlzQEwLkgEKnWcSazqr9l9OdV2HhVasWJzLKeOt0PLhHaUHuzb8s/UIya38DJDoUm74GToZ6Wc7NGQ==} engines: {node: '>=12'} @@ -219,6 +276,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-arm64@0.19.12: + resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-arm64@0.19.7: resolution: {integrity: sha512-+y2YsUr0CxDFF7GWiegWjGtTUF6gac2zFasfFkRJPkMAuMy9O7+2EH550VlqVdpEEchWMynkdhC9ZjtnMiHImQ==} engines: {node: '>=12'} @@ -228,6 +294,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-x64@0.19.12: + resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-x64@0.19.7: resolution: {integrity: sha512-CdXOxIbIzPJmJhrpmJTLx+o35NoiKBIgOvmvT+jeSadYiWJn0vFKsl+0bSG/5lwjNHoIDEyMYc/GAPR9jxusTA==} engines: {node: '>=12'} @@ -237,6 +312,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm64@0.19.12: + resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm64@0.19.7: resolution: {integrity: sha512-inHqdOVCkUhHNvuQPT1oCB7cWz9qQ/Cz46xmVe0b7UXcuIJU3166aqSunsqkgSGMtUCWOZw3+KMwI6otINuC9g==} engines: {node: '>=12'} @@ -246,6 +330,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm@0.19.12: + resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm@0.19.7: resolution: {integrity: sha512-Y+SCmWxsJOdQtjcBxoacn/pGW9HDZpwsoof0ttL+2vGcHokFlfqV666JpfLCSP2xLxFpF1lj7T3Ox3sr95YXww==} engines: {node: '>=12'} @@ -255,6 +348,15 @@ packages: dev: true optional: true + /@esbuild/linux-ia32@0.19.12: + resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ia32@0.19.7: resolution: {integrity: sha512-2BbiL7nLS5ZO96bxTQkdO0euGZIUQEUXMTrqLxKUmk/Y5pmrWU84f+CMJpM8+EHaBPfFSPnomEaQiG/+Gmh61g==} engines: {node: '>=12'} @@ -264,6 +366,15 @@ packages: dev: true optional: true + /@esbuild/linux-loong64@0.19.12: + resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-loong64@0.19.7: resolution: {integrity: sha512-BVFQla72KXv3yyTFCQXF7MORvpTo4uTA8FVFgmwVrqbB/4DsBFWilUm1i2Oq6zN36DOZKSVUTb16jbjedhfSHw==} engines: {node: '>=12'} @@ -273,6 +384,15 @@ packages: dev: true optional: true + /@esbuild/linux-mips64el@0.19.12: + resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-mips64el@0.19.7: resolution: {integrity: sha512-DzAYckIaK+pS31Q/rGpvUKu7M+5/t+jI+cdleDgUwbU7KdG2eC3SUbZHlo6Q4P1CfVKZ1lUERRFP8+q0ob9i2w==} engines: {node: '>=12'} @@ -282,6 +402,15 @@ packages: dev: true optional: true + /@esbuild/linux-ppc64@0.19.12: + resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ppc64@0.19.7: resolution: {integrity: sha512-JQ1p0SmUteNdUaaiRtyS59GkkfTW0Edo+e0O2sihnY4FoZLz5glpWUQEKMSzMhA430ctkylkS7+vn8ziuhUugQ==} engines: {node: '>=12'} @@ -291,6 +420,15 @@ packages: dev: true optional: true + /@esbuild/linux-riscv64@0.19.12: + resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-riscv64@0.19.7: resolution: {integrity: sha512-xGwVJ7eGhkprY/nB7L7MXysHduqjpzUl40+XoYDGC4UPLbnG+gsyS1wQPJ9lFPcxYAaDXbdRXd1ACs9AE9lxuw==} engines: {node: '>=12'} @@ -300,6 +438,15 @@ packages: dev: true optional: true + /@esbuild/linux-s390x@0.19.12: + resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-s390x@0.19.7: resolution: {integrity: sha512-U8Rhki5PVU0L0nvk+E8FjkV8r4Lh4hVEb9duR6Zl21eIEYEwXz8RScj4LZWA2i3V70V4UHVgiqMpszXvG0Yqhg==} engines: {node: '>=12'} @@ -309,6 +456,15 @@ packages: dev: true optional: true + /@esbuild/linux-x64@0.19.12: + resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-x64@0.19.7: resolution: {integrity: sha512-ZYZopyLhm4mcoZXjFt25itRlocKlcazDVkB4AhioiL9hOWhDldU9n38g62fhOI4Pth6vp+Mrd5rFKxD0/S+7aQ==} engines: {node: '>=12'} @@ -318,6 +474,15 @@ packages: dev: true optional: true + /@esbuild/netbsd-x64@0.19.12: + resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/netbsd-x64@0.19.7: resolution: {integrity: sha512-/yfjlsYmT1O3cum3J6cmGG16Fd5tqKMcg5D+sBYLaOQExheAJhqr8xOAEIuLo8JYkevmjM5zFD9rVs3VBcsjtQ==} engines: {node: '>=12'} @@ -327,6 +492,15 @@ packages: dev: true optional: true + /@esbuild/openbsd-x64@0.19.12: + resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/openbsd-x64@0.19.7: resolution: {integrity: sha512-MYDFyV0EW1cTP46IgUJ38OnEY5TaXxjoDmwiTXPjezahQgZd+j3T55Ht8/Q9YXBM0+T9HJygrSRGV5QNF/YVDQ==} engines: {node: '>=12'} @@ -336,6 +510,15 @@ packages: dev: true optional: true + /@esbuild/sunos-x64@0.19.12: + resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + /@esbuild/sunos-x64@0.19.7: resolution: {integrity: sha512-JcPvgzf2NN/y6X3UUSqP6jSS06V0DZAV/8q0PjsZyGSXsIGcG110XsdmuWiHM+pno7/mJF6fjH5/vhUz/vA9fw==} engines: {node: '>=12'} @@ -345,6 +528,15 @@ packages: dev: true optional: true + /@esbuild/win32-arm64@0.19.12: + resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-arm64@0.19.7: resolution: {integrity: sha512-ZA0KSYti5w5toax5FpmfcAgu3ZNJxYSRm0AW/Dao5up0YV1hDVof1NvwLomjEN+3/GMtaWDI+CIyJOMTRSTdMw==} engines: {node: '>=12'} @@ -354,6 +546,15 @@ packages: dev: true optional: true + /@esbuild/win32-ia32@0.19.12: + resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-ia32@0.19.7: resolution: {integrity: sha512-CTOnijBKc5Jpk6/W9hQMMvJnsSYRYgveN6O75DTACCY18RA2nqka8dTZR+x/JqXCRiKk84+5+bRKXUSbbwsS0A==} engines: {node: '>=12'} @@ -363,6 +564,15 @@ packages: dev: true optional: true + /@esbuild/win32-x64@0.19.12: + resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-x64@0.19.7: resolution: {integrity: sha512-gRaP2sk6hc98N734luX4VpF318l3w+ofrtTu9j5L8EQXF+FzQKV6alCOHMVoJJHvVK/mGbwBXfOL1HETQu9IGQ==} engines: {node: '>=12'} @@ -422,6 +632,18 @@ packages: /@humanwhocodes/object-schema@2.0.2: resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + string-width-cjs: /string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: /strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: true + /@jest/schemas@29.6.3: resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -454,6 +676,10 @@ packages: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 + /@kurkle/color@0.3.2: + resolution: {integrity: sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==} + dev: false + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -472,6 +698,13 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: true + optional: true + /@playwright/test@1.42.1: resolution: {integrity: sha512-Gq9rmS54mjBL/7/MvBaNOBwbfnh7beHvS6oS4srqXFcQHpQCV1+c8JXWE8VLPyRDhgS3H8x8A7hztqI9VnwrAQ==} engines: {node: '>=16'} @@ -483,6 +716,78 @@ packages: resolution: {integrity: sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==} dev: true + /@rollup/plugin-commonjs@25.0.7(rollup@4.13.0): + resolution: {integrity: sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.13.0) + commondir: 1.0.1 + estree-walker: 2.0.2 + glob: 8.1.0 + is-reference: 1.2.1 + magic-string: 0.30.8 + rollup: 4.13.0 + dev: true + + /@rollup/plugin-json@6.1.0(rollup@4.13.0): + resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.13.0) + rollup: 4.13.0 + dev: true + + /@rollup/plugin-node-resolve@15.2.3(rollup@4.13.0): + resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.13.0) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-builtin-module: 3.2.1 + is-module: 1.0.0 + resolve: 1.22.8 + rollup: 4.13.0 + dev: true + + /@rollup/pluginutils@5.1.0(rollup@4.13.0): + resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 2.3.1 + rollup: 4.13.0 + dev: true + + /@rollup/rollup-android-arm-eabi@4.13.0: + resolution: {integrity: sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-android-arm-eabi@4.5.2: resolution: {integrity: sha512-ee7BudTwwrglFYSc3UnqInDDjCLWHKrFmGNi4aK7jlEyg4CyPa1DCMrZfsN1O13YT76UFEqXz2CoN7BCGpUlJw==} cpu: [arm] @@ -491,6 +796,14 @@ packages: dev: true optional: true + /@rollup/rollup-android-arm64@4.13.0: + resolution: {integrity: sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-android-arm64@4.5.2: resolution: {integrity: sha512-xOuhj9HHtn8128ir8veoQsBbAUBasDbHIBniYTEx02pAmu9EXL+ZjJqngnNEy6ZgZ4h1JwL33GMNu3yJL5Mzow==} cpu: [arm64] @@ -499,6 +812,14 @@ packages: dev: true optional: true + /@rollup/rollup-darwin-arm64@4.13.0: + resolution: {integrity: sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-darwin-arm64@4.5.2: resolution: {integrity: sha512-NTGJWoL8bKyqyWFn9/RzSv4hQ4wTbaAv0lHHRwf4OnpiiP4P8W0jiXbm8Nc5BCXKmWAwuvJY82mcIU2TayC20g==} cpu: [arm64] @@ -507,6 +828,14 @@ packages: dev: true optional: true + /@rollup/rollup-darwin-x64@4.13.0: + resolution: {integrity: sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-darwin-x64@4.5.2: resolution: {integrity: sha512-hlKqj7bpPvU15sZo4za14u185lpMzdwWLMc9raMqPK4wywt0wR23y1CaVQ4oAFXat3b5/gmRntyfpwWTKl+vvA==} cpu: [x64] @@ -515,6 +844,14 @@ packages: dev: true optional: true + /@rollup/rollup-linux-arm-gnueabihf@4.13.0: + resolution: {integrity: sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-arm-gnueabihf@4.5.2: resolution: {integrity: sha512-7ZIZx8c3u+pfI0ohQsft/GywrXez0uR6dUP0JhBuCK3sFO5TfdLn/YApnVkvPxuTv3+YKPIZend9Mt7Cz6sS3Q==} cpu: [arm] @@ -523,6 +860,14 @@ packages: dev: true optional: true + /@rollup/rollup-linux-arm64-gnu@4.13.0: + resolution: {integrity: sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-arm64-gnu@4.5.2: resolution: {integrity: sha512-7Pk/5mO11JW/cH+a8lL/i0ZxmRGrbpYqN0VwO2DHhU+SJWWOH2zE1RAcPaj8KqiwC8DCDIJOSxjV9+9lLb6aeA==} cpu: [arm64] @@ -531,6 +876,14 @@ packages: dev: true optional: true + /@rollup/rollup-linux-arm64-musl@4.13.0: + resolution: {integrity: sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-arm64-musl@4.5.2: resolution: {integrity: sha512-KrRnuG5phJx756e62wxvWH2e+TK84MP2IVuPwfge+GBvWqIUfVzFRn09TKruuQBXzZp52Vyma7FjMDkwlA9xpg==} cpu: [arm64] @@ -539,6 +892,22 @@ packages: dev: true optional: true + /@rollup/rollup-linux-riscv64-gnu@4.13.0: + resolution: {integrity: sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-gnu@4.13.0: + resolution: {integrity: sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-x64-gnu@4.5.2: resolution: {integrity: sha512-My+53GasPa2D2tU5dXiyHYwrELAUouSfkNlZ3bUKpI7btaztO5vpALEs3mvFjM7aKTvEbc7GQckuXeXIDKQ0fg==} cpu: [x64] @@ -547,6 +916,14 @@ packages: dev: true optional: true + /@rollup/rollup-linux-x64-musl@4.13.0: + resolution: {integrity: sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-x64-musl@4.5.2: resolution: {integrity: sha512-/f0Q6Sc+Vw54Ws6N8fxaEe4R7at3b8pFyv+O/F2VaQ4hODUJcRUcCBJh6zuqtgQQt7w845VTkGLFgWZkP3tUoQ==} cpu: [x64] @@ -555,6 +932,14 @@ packages: dev: true optional: true + /@rollup/rollup-win32-arm64-msvc@4.13.0: + resolution: {integrity: sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-win32-arm64-msvc@4.5.2: resolution: {integrity: sha512-NCKuuZWLht6zj7s6EIFef4BxCRX1GMr83S2W4HPCA0RnJ4iHE4FS1695q6Ewoa6A9nFjJe1//yUu0kgBU07Edw==} cpu: [arm64] @@ -563,6 +948,14 @@ packages: dev: true optional: true + /@rollup/rollup-win32-ia32-msvc@4.13.0: + resolution: {integrity: sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-win32-ia32-msvc@4.5.2: resolution: {integrity: sha512-J5zL3riR4AOyU/J3M/i4k/zZ8eP1yT+nTmAKztCXJtnI36jYH0eepvob22mAQ/kLwfsK2TB6dbyVY1F8c/0H5A==} cpu: [ia32] @@ -571,6 +964,14 @@ packages: dev: true optional: true + /@rollup/rollup-win32-x64-msvc@4.13.0: + resolution: {integrity: sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-win32-x64-msvc@4.5.2: resolution: {integrity: sha512-pL0RXRHuuGLhvs7ayX/SAHph1hrDPXOM5anyYUQXWJEENxw3nfHkzv8FfVlEVcLyKPAEgDRkd6RKZq2SMqS/yg==} cpu: [x64] @@ -583,18 +984,22 @@ packages: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true - /@sveltejs/adapter-auto@3.1.1(@sveltejs/kit@2.5.2): - resolution: {integrity: sha512-6LeZft2Fo/4HfmLBi5CucMYmgRxgcETweQl/yQoZo/895K3S9YWYN4Sfm/IhwlIpbJp3QNvhKmwCHbsqQNYQpw==} + /@sveltejs/adapter-node@5.0.1(@sveltejs/kit@2.5.2): + resolution: {integrity: sha512-eYdmxdUWMW+dad1JfMsWBPY2vjXz9eE+52A2AQnXPScPJlIxIVk5mmbaEEzrZivLfO2wEcLTZ5vdC03W69x+iA==} peerDependencies: - '@sveltejs/kit': ^2.0.0 + '@sveltejs/kit': ^2.4.0 dependencies: + '@rollup/plugin-commonjs': 25.0.7(rollup@4.13.0) + '@rollup/plugin-json': 6.1.0(rollup@4.13.0) + '@rollup/plugin-node-resolve': 15.2.3(rollup@4.13.0) '@sveltejs/kit': 2.5.2(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@4.2.12)(vite@5.1.4) - import-meta-resolve: 4.0.0 + rollup: 4.13.0 dev: true /@sveltejs/kit@2.5.2(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@4.2.12)(vite@5.1.4): resolution: {integrity: sha512-1Pm2lsBYURQsjnLyZa+jw75eVD4gYHxGRwPyFe4DAmB3FjTVR8vRNWGeuDLGFcKMh/B1ij6FTUrc9GrerogCng==} engines: {node: '>=18.13'} + hasBin: true requiresBuild: true peerDependencies: '@sveltejs/vite-plugin-svelte': ^3.0.0 @@ -664,10 +1069,20 @@ packages: /@types/json-schema@7.0.15: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + /@types/node@20.11.30: + resolution: {integrity: sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==} + dependencies: + undici-types: 5.26.5 + dev: true + /@types/pug@2.0.10: resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==} dev: true + /@types/resolve@1.20.2: + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + dev: true + /@types/semver@7.5.6: resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} @@ -865,6 +1280,11 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + /ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -876,6 +1296,15 @@ packages: engines: {node: '>=10'} dev: true + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: true + /anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -884,6 +1313,10 @@ packages: picomatch: 2.3.1 dev: true + /arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + dev: true + /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -900,6 +1333,22 @@ packages: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} dev: true + /autoprefixer@10.4.18(postcss@8.4.36): + resolution: {integrity: sha512-1DKbDfsr6KUElM6wg+0zRNkB/Q7WcKYAaK+pzXn+Xqmszm/5Xa9coeNdtP88Vi+dPzZnMjhge8GIV49ZQkDa+g==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.23.0 + caniuse-lite: 1.0.30001599 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.0.0 + postcss: 8.4.36 + postcss-value-parser: 4.2.0 + dev: true + /axobject-query@4.0.0: resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==} dependencies: @@ -930,10 +1379,26 @@ packages: dependencies: fill-range: 7.0.1 + /browserslist@4.23.0: + resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001599 + electron-to-chromium: 1.4.710 + node-releases: 2.0.14 + update-browserslist-db: 1.0.13(browserslist@4.23.0) + dev: true + /buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} dev: true + /builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + dev: true + /cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -943,6 +1408,15 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + /camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + dev: true + + /caniuse-lite@1.0.30001599: + resolution: {integrity: sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA==} + dev: true + /chai@4.3.10: resolution: {integrity: sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==} engines: {node: '>=4'} @@ -963,6 +1437,13 @@ packages: ansi-styles: 4.3.0 supports-color: 7.2.0 + /chart.js@4.4.2: + resolution: {integrity: sha512-6GD7iKwFpP5kbSD4MeRRRlTnQvxfQREy36uEtm1hzHzcOqwWx0YEHuspuoNlslu+nciLIB7fjjsHkUv/FzFcOg==} + engines: {pnpm: '>=8'} + dependencies: + '@kurkle/color': 0.3.2 + dev: false + /check-error@1.0.3: resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} dependencies: @@ -1002,6 +1483,15 @@ packages: /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + /commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + dev: true + + /commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + dev: true + /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -1028,7 +1518,6 @@ packages: /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} - dev: false /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} @@ -1069,6 +1558,10 @@ packages: resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==} dev: true + /didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dev: true + /diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1080,6 +1573,10 @@ packages: dependencies: path-type: 4.0.0 + /dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dev: true + /doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} @@ -1091,10 +1588,62 @@ packages: engines: {node: '>=12'} dev: false + /dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + dev: false + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + + /electron-to-chromium@1.4.710: + resolution: {integrity: sha512-w+9yAVHoHhysCa+gln7AzbO9CdjFcL/wN/5dd+XW/Msl2d/4+WisEaCF1nty0xbAKaxdaJfgLB2296U7zZB7BA==} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + /es6-promise@3.3.1: resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} dev: true + /esbuild@0.19.12: + resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.19.12 + '@esbuild/android-arm': 0.19.12 + '@esbuild/android-arm64': 0.19.12 + '@esbuild/android-x64': 0.19.12 + '@esbuild/darwin-arm64': 0.19.12 + '@esbuild/darwin-x64': 0.19.12 + '@esbuild/freebsd-arm64': 0.19.12 + '@esbuild/freebsd-x64': 0.19.12 + '@esbuild/linux-arm': 0.19.12 + '@esbuild/linux-arm64': 0.19.12 + '@esbuild/linux-ia32': 0.19.12 + '@esbuild/linux-loong64': 0.19.12 + '@esbuild/linux-mips64el': 0.19.12 + '@esbuild/linux-ppc64': 0.19.12 + '@esbuild/linux-riscv64': 0.19.12 + '@esbuild/linux-s390x': 0.19.12 + '@esbuild/linux-x64': 0.19.12 + '@esbuild/netbsd-x64': 0.19.12 + '@esbuild/openbsd-x64': 0.19.12 + '@esbuild/sunos-x64': 0.19.12 + '@esbuild/win32-arm64': 0.19.12 + '@esbuild/win32-ia32': 0.19.12 + '@esbuild/win32-x64': 0.19.12 + dev: true + /esbuild@0.19.7: resolution: {integrity: sha512-6brbTZVqxhqgbpqBR5MzErImcpA0SQdoKOkcWK/U30HtQxnokIpG3TX2r0IJqbFUzqLjhU/zC1S5ndgakObVCQ==} engines: {node: '>=12'} @@ -1124,6 +1673,11 @@ packages: '@esbuild/win32-x64': 0.19.7 dev: true + /escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + dev: true + /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -1139,6 +1693,7 @@ packages: /eslint-config-prettier@9.1.0(eslint@8.57.0): resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: @@ -1171,9 +1726,9 @@ packages: eslint-compat-utils: 0.1.2(eslint@8.57.0) esutils: 2.0.3 known-css-properties: 0.29.0 - postcss: 8.4.31 - postcss-load-config: 3.1.4(postcss@8.4.31) - postcss-safe-parser: 6.0.0(postcss@8.4.31) + postcss: 8.4.35 + postcss-load-config: 3.1.4(postcss@8.4.35) + postcss-safe-parser: 6.0.0(postcss@8.4.35) postcss-selector-parser: 6.0.13 semver: 7.5.4 svelte: 4.2.12 @@ -1276,6 +1831,10 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: true + /estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} dependencies: @@ -1354,6 +1913,18 @@ packages: /flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + /foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + dev: true + + /fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + dev: true + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -1373,6 +1944,10 @@ packages: dev: true optional: true + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true + /get-func-name@2.0.2: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} dev: true @@ -1382,6 +1957,12 @@ packages: engines: {node: '>=16'} dev: true + /get-tsconfig@4.7.3: + resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==} + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1394,6 +1975,18 @@ packages: dependencies: is-glob: 4.0.3 + /glob@10.3.10: + resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + dependencies: + foreground-child: 3.1.1 + jackspeak: 2.3.6 + minimatch: 9.0.3 + minipass: 7.0.4 + path-scurry: 1.10.1 + dev: true + /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} dependencies: @@ -1404,6 +1997,17 @@ packages: once: 1.4.0 path-is-absolute: 1.0.1 + /glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + dev: true + /globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} @@ -1440,6 +2044,13 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + /human-signals@5.0.0: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} @@ -1480,16 +2091,38 @@ packages: binary-extensions: 2.2.0 dev: true + /is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + dependencies: + builtin-modules: 3.3.0 + dev: true + + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.2 + dev: true + /is-extglob@2.1.1: 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'} + dev: true + /is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 + /is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + dev: true + /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -1498,6 +2131,12 @@ packages: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} + /is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + dependencies: + '@types/estree': 1.0.5 + dev: true + /is-reference@3.0.2: resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} dependencies: @@ -1511,6 +2150,20 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + /jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: true + + /jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + hasBin: true + dev: true + /js-tokens@8.0.3: resolution: {integrity: sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==} dev: true @@ -1557,7 +2210,15 @@ packages: /lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} - dev: false + + /lilconfig@3.1.1: + resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==} + engines: {node: '>=14'} + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true /local-pkg@0.5.0: resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} @@ -1585,6 +2246,11 @@ packages: get-func-name: 2.0.2 dev: true + /lru-cache@10.2.0: + resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} + engines: {node: 14 || >=16.14} + dev: true + /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -1630,6 +2296,13 @@ packages: dependencies: brace-expansion: 1.1.11 + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + /minimatch@9.0.3: resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} engines: {node: '>=16 || 14 >=14.17'} @@ -1640,6 +2313,11 @@ packages: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: true + /minipass@7.0.4: + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + engines: {node: '>=16 || 14 >=14.17'} + dev: true + /mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} dependencies: @@ -1668,6 +2346,14 @@ packages: /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + /mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: true + /nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -1675,11 +2361,20 @@ packages: /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + /node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + dev: true + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} dev: true + /normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + dev: true + /npm-run-path@5.2.0: resolution: {integrity: sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1687,6 +2382,16 @@ packages: path-key: 4.0.0 dev: true + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + dev: true + /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: @@ -1752,6 +2457,18 @@ packages: engines: {node: '>=12'} dev: true + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-scurry@1.10.1: + resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + lru-cache: 10.2.0 + minipass: 7.0.4 + dev: true + /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -1778,6 +2495,16 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + /pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + dev: true + + /pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + dev: true + /pkg-types@1.0.3: resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} dependencies: @@ -1800,7 +2527,29 @@ packages: fsevents: 2.3.2 dev: true - /postcss-load-config@3.1.4(postcss@8.4.31): + /postcss-import@15.1.0(postcss@8.4.36): + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss: 8.4.36 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + dev: true + + /postcss-js@4.0.1(postcss@8.4.36): + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.36 + dev: true + + /postcss-load-config@3.1.4(postcss@8.4.35): resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} engines: {node: '>= 10'} peerDependencies: @@ -1813,17 +2562,44 @@ packages: optional: true dependencies: lilconfig: 2.1.0 - postcss: 8.4.31 + postcss: 8.4.35 yaml: 1.10.2 dev: false - /postcss-safe-parser@6.0.0(postcss@8.4.31): + /postcss-load-config@4.0.2(postcss@8.4.36): + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 3.1.1 + postcss: 8.4.36 + yaml: 2.4.1 + dev: true + + /postcss-nested@6.0.1(postcss@8.4.36): + resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + dependencies: + postcss: 8.4.36 + postcss-selector-parser: 6.0.13 + dev: true + + /postcss-safe-parser@6.0.0(postcss@8.4.35): resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.3.3 dependencies: - postcss: 8.4.31 + postcss: 8.4.35 dev: false /postcss-scss@4.0.9(postcss@8.4.35): @@ -1841,16 +2617,10 @@ packages: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - dev: false - /postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.0.2 - dev: false + /postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: true /postcss@8.4.35: resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} @@ -1859,6 +2629,21 @@ packages: nanoid: 3.3.7 picocolors: 1.0.0 source-map-js: 1.0.2 + dev: false + + /postcss@8.4.36: + resolution: {integrity: sha512-/n7eumA6ZjFHAsbX30yhHup/IMkOmlmvtEi7P+6RMYf+bGJSUHc3geH4a0NSZxAz/RJfiS9tooCTs9LAVYUZKw==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.1.0 + dev: true + + /postgres@3.4.3: + resolution: {integrity: sha512-iHJn4+M9vbTdHSdDzNkC0crHq+1CUdFhx+YqCE+SqWxPjm+Zu63jq7yZborOBF64c8pc58O5uMudyL1FQcHacA==} + engines: {node: '>=12'} + dev: false /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} @@ -1899,6 +2684,12 @@ packages: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} dev: true + /read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + dependencies: + pify: 2.3.0 + dev: true + /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -1910,6 +2701,19 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -1925,6 +2729,29 @@ packages: dependencies: glob: 7.2.3 + /rollup@4.13.0: + resolution: {integrity: sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.13.0 + '@rollup/rollup-android-arm64': 4.13.0 + '@rollup/rollup-darwin-arm64': 4.13.0 + '@rollup/rollup-darwin-x64': 4.13.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.13.0 + '@rollup/rollup-linux-arm64-gnu': 4.13.0 + '@rollup/rollup-linux-arm64-musl': 4.13.0 + '@rollup/rollup-linux-riscv64-gnu': 4.13.0 + '@rollup/rollup-linux-x64-gnu': 4.13.0 + '@rollup/rollup-linux-x64-musl': 4.13.0 + '@rollup/rollup-win32-arm64-msvc': 4.13.0 + '@rollup/rollup-win32-ia32-msvc': 4.13.0 + '@rollup/rollup-win32-x64-msvc': 4.13.0 + fsevents: 2.3.3 + dev: true + /rollup@4.5.2: resolution: {integrity: sha512-CRK1uoROBfkcqrZKyaFcqCcZWNsvJ6yVYZkqTlRocZhO2s5yER6Z3f/QaYtO8RGyloPnmhwgzuPQpNGeK210xQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -2020,6 +2847,11 @@ packages: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} + /source-map-js@1.1.0: + resolution: {integrity: sha512-9vC2SfsJzlej6MAaMPLu8HiBSHGdRAJ9hVFYN1ibZoNkeanmDmLUcIrj6G9DGL7XMJ54AKg/G75akXl1/izTOw==} + engines: {node: '>=0.10.0'} + dev: true + /stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} dev: true @@ -2028,12 +2860,37 @@ packages: resolution: {integrity: sha512-JGUEaALvL0Mf6JCfYnJOTcobY+Nc7sG/TemDRBqCA0wEr4DER7zDchaaixTlmOxAjG1uRJmX82EQcxwTQTkqVA==} dev: true + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: true + /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} dependencies: ansi-regex: 5.0.1 + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + /strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} @@ -2056,14 +2913,34 @@ packages: js-tokens: 8.0.3 dev: true + /sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.3.10 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + dev: true + /supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} dependencies: has-flag: 4.0.0 - /svelte-check@3.6.6(svelte@4.2.12): + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /svelte-check@3.6.6(postcss@8.4.36)(svelte@4.2.12): resolution: {integrity: sha512-b9q9rOHOMYF3U8XllK7LmXTq1LeWQ98waGfEJzrFutViadkNl1tgdEtxIQ8yuPx+VQ4l7YrknYol+0lfZocaZw==} + hasBin: true peerDependencies: svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 dependencies: @@ -2074,7 +2951,7 @@ packages: picocolors: 1.0.0 sade: 1.8.1 svelte: 4.2.12 - svelte-preprocess: 5.1.3(svelte@4.2.12)(typescript@5.3.3) + svelte-preprocess: 5.1.3(postcss@8.4.36)(svelte@4.2.12)(typescript@5.3.3) typescript: 5.3.3 transitivePeerDependencies: - '@babel/core' @@ -2114,7 +2991,7 @@ packages: svelte: 4.2.12 dev: true - /svelte-preprocess@5.1.3(svelte@4.2.12)(typescript@5.3.3): + /svelte-preprocess@5.1.3(postcss@8.4.36)(svelte@4.2.12)(typescript@5.3.3): resolution: {integrity: sha512-xxAkmxGHT+J/GourS5mVJeOXZzne1FR5ljeOUAMXUkfEhkLEllRreXpbl3dIYJlcJRfL1LO1uIAPpBpBfiqGPw==} engines: {node: '>= 16.0.0', pnpm: ^8.0.0} requiresBuild: true @@ -2155,6 +3032,7 @@ packages: '@types/pug': 2.0.10 detect-indent: 6.1.0 magic-string: 0.30.8 + postcss: 8.4.36 sorcery: 0.11.0 strip-indent: 3.0.0 svelte: 4.2.12 @@ -2180,9 +3058,53 @@ packages: magic-string: 0.30.8 periscopic: 3.1.0 + /tailwindcss@3.4.1: + resolution: {integrity: sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.5.3 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.0 + lilconfig: 2.1.0 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.0 + postcss: 8.4.36 + postcss-import: 15.1.0(postcss@8.4.36) + postcss-js: 4.0.1(postcss@8.4.36) + postcss-load-config: 4.0.2(postcss@8.4.36) + postcss-nested: 6.0.1(postcss@8.4.36) + postcss-selector-parser: 6.0.13 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + dev: true + /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + /thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: true + + /thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: true + /tiny-glob@0.2.9: resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} dependencies: @@ -2223,10 +3145,25 @@ packages: dependencies: typescript: 5.3.3 + /ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + dev: true + /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} dev: true + /tsx@4.7.1: + resolution: {integrity: sha512-8d6VuibXHtlN5E3zFkgY8u4DX7Y3Z27zvvPKVmLon/D4AjuKzarkUBTLDBgj9iTQ0hg5xM7c/mYiRVM+HETf0g==} + engines: {node: '>=18.0.0'} + hasBin: true + dependencies: + esbuild: 0.19.12 + get-tsconfig: 4.7.3 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /turbo-darwin-64@1.12.5: resolution: {integrity: sha512-0GZ8reftwNQgIQLHkHjHEXTc/Z1NJm+YjsrBP+qhM/7yIZ3TEy9gJhuogDt2U0xIWwFgisTyzbtU7xNaQydtoA==} cpu: [x64] @@ -2310,6 +3247,21 @@ packages: resolution: {integrity: sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==} dev: true + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true + + /update-browserslist-db@1.0.13(browserslist@4.23.0): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.23.0 + escalade: 3.1.2 + picocolors: 1.0.0 + dev: true + /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: @@ -2317,7 +3269,6 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: false /vite-node@1.3.1: resolution: {integrity: sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng==} @@ -2342,6 +3293,7 @@ packages: /vite@5.1.4: resolution: {integrity: sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==} engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true peerDependencies: '@types/node': ^18.0.0 || >=20.0.0 less: '*' @@ -2367,7 +3319,7 @@ packages: optional: true dependencies: esbuild: 0.19.7 - postcss: 8.4.35 + postcss: 8.4.36 rollup: 4.5.2 optionalDependencies: fsevents: 2.3.3 @@ -2387,6 +3339,7 @@ packages: /vitest@1.3.1: resolution: {integrity: sha512-/1QJqXs8YbCrfv/GPQ05wAZf2eakUPLPa18vkJAKE7RXOKfVHqMZZ1WlTjiwl6Gcn65M5vpNUB6EFLnEdRdEXQ==} engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/node': ^18.0.0 || >=20.0.0 @@ -2452,6 +3405,24 @@ packages: stackback: 0.0.2 dev: true + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: true + /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -2463,6 +3434,12 @@ packages: engines: {node: '>= 6'} dev: false + /yaml@2.4.1: + resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} + engines: {node: '>= 14'} + hasBin: true + dev: true + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -2471,3 +3448,7 @@ packages: resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} engines: {node: '>=12.20'} dev: true + + /zod@3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + dev: false diff --git a/prod.compose.yml b/prod.compose.yml new file mode 100644 index 0000000..efe587a --- /dev/null +++ b/prod.compose.yml @@ -0,0 +1,72 @@ +version: '3.8' + +name: aqs + +networks: + proxy: + external: true + +services: + aqs-app: + container_name: aqs-app + build: + context: . + dockerfile: apps/web/Dockerfile + restart: unless-stopped + networks: + - proxy + - default + env_file: + - .env.prod + deploy: + resources: + limits: + cpus: '0.5' + memory: 512M + depends_on: + aqs-db: + condition: service_healthy + security_opt: + - no-new-privileges:true + labels: + - 'traefik.enable=true' + - "traefik.docker.network=proxy" + - 'traefik.http.routers.aqs-app.rule=Host(`home.antonshubin.com`) || Host(`aqs.antonshubin.com`)' + - 'traefik.http.routers.aqs-app.entrypoints=websecure' + - 'traefik.http.routers.aqs-app.tls=true' + - 'traefik.http.routers.aqs-app.tls.certresolver=myresolver' + - 'traefik.http.services.aqs-app.loadbalancer.server.port=3000' + logging: + driver: json-file + options: + max-size: '10m' + max-file: '3' + + aqs-db: + container_name: aqs-db + image: postgres:15-alpine + restart: unless-stopped + deploy: + resources: + limits: + cpus: '0.25' + memory: 512M + environment: + - PGUSER=${DB_USER} + - POSTGRES_USER=${DB_USER} + - POSTGRES_PASSWORD=${DB_PASS} + - POSTGRES_DB=${DB_NAME} + ports: + - 5432:5432 + volumes: + - ../.volumes/aqs/postgres:/var/lib/postgresql/data + healthcheck: + test: ["CMD", "pg_isready", '-d', '${DB_NAME}', '-U', '${DB_USER}'] + interval: 10s + timeout: 5s + retries: 5 + logging: + driver: json-file + options: + max-size: '10m' + max-file: '3' diff --git a/prod.deploy.files.txt b/prod.deploy.files.txt new file mode 100644 index 0000000..e22f4f3 --- /dev/null +++ b/prod.deploy.files.txt @@ -0,0 +1,11 @@ +apps/*** +packages/*** +.npmrc +package.json +pnpm-lock.yaml +pnpm-workspace.yaml +.dockerignore +prod.dockerfile +prod.compose.yml +.env.prod +turbo.json