diff --git a/.env.example b/.env.example index 5b043a624..926bb071e 100644 --- a/.env.example +++ b/.env.example @@ -29,6 +29,13 @@ PUBLIC_NHOST_FUNCTIONS_URL=${NHOST_FUNCTIONS_URL} # Hasura HASURA_GRAPHQL_ENDPOINT=https://${NHOST_SUBDOMAIN}.hasura.${NHOST_REGION}.nhost.run +# Cloudflare Turnstile +## https://developers.cloudflare.com/turnstile/troubleshooting/testing/ +PUBLIC_CLOUDFLARE_TURNSTILE_CHALLENGE_URL=https://challenges.cloudflare.com/turnstile/v0/siteverify +PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY=0x4AAAAAAA4jAyA4ZpiXqCVy +PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY_ALWAYS_PASSES=1x00000000000000000000AA +PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY_ALWAYS_BLOCKS=2x00000000000000000000AB + # Runtime APP_NAME=Spectacular APP_DESCRIPTION=Spectacular Console App @@ -45,9 +52,10 @@ PUBLIC_TERMS_PRIVACY_COUNTRY='United States' ## feature flags (to enable, uncomment the variable). ## if variable present, it is considered as `true` no matter what the actual value is. +FEATURE_SIMULATE_LOADING_STATE=false FEATURE_SHOW_MAGIC_LINK_LOGIN=true FEATURE_SHOW_SOCIAL_LOGIN=true -FEATURE_SIMULATE_LOADING_STATE=false +FEATURE_SHOW_BOT_PROTECTION=true ########################################################################### # Application Properties (Web) @@ -62,5 +70,5 @@ API_VERSION=v1 ########################################################################### # Application Properties (Docs) ########################################################################### -GH_SITE_URL= -GH_BASE_PATH= +GH_SITE_URL=https://xmlking.github.io +GH_BASE_PATH=/spectacular diff --git a/.env.production.example b/.env.production.example index 601a2e8a4..7d6d9dc21 100644 --- a/.env.production.example +++ b/.env.production.example @@ -28,6 +28,13 @@ PUBLIC_NHOST_FUNCTIONS_URL=${NHOST_FUNCTIONS_URL} # Hasura HASURA_GRAPHQL_ENDPOINT=https://${NHOST_SUBDOMAIN}.hasura.${NHOST_REGION}.nhost.run +# Cloudflare Turnstile +## https://developers.cloudflare.com/turnstile/troubleshooting/testing/ +PUBLIC_CLOUDFLARE_TURNSTILE_CHALLENGE_URL=https://challenges.cloudflare.com/turnstile/v0/siteverify +PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY=0x4AAAAAAA4jAyA4ZpiXqCVy +PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY_ALWAYS_PASSES=1x00000000000000000000AA +PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY_ALWAYS_BLOCKS=2x00000000000000000000AB + # Runtime APP_NAME=Spectacular APP_DESCRIPTION=Spectacular Console App @@ -44,9 +51,10 @@ PUBLIC_TERMS_PRIVACY_COUNTRY='United States' ## feature flags (to enable, uncomment the variable). ## if variable present, it is considered as `true` no matter what the actual value is. +FEATURE_SIMULATE_LOADING_STATE=false FEATURE_SHOW_MAGIC_LINK_LOGIN=true FEATURE_SHOW_SOCIAL_LOGIN=true -FEATURE_SIMULATE_LOADING_STATE=false +FEATURE_SHOW_BOT_PROTECTION=true ########################################################################### # Application Properties (Web) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7bd1b524..9c82446fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,7 @@ env: IMAGE_NAME: ${{ github.repository }}/${{ inputs.app || 'console' }} TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ vars.TURBO_TEAM }} + TURBO_REMOTE_ONLY: true ## app build time environment variables VERCEL_ENV: ${{ vars.VERCEL_ENV }} PUBLIC_TERMS_PRIVACY_COMPANY: ${{ vars.PUBLIC_TERMS_PRIVACY_COMPANY }} diff --git a/.gitignore b/.gitignore index 23ec3c4cf..d9421aff3 100644 --- a/.gitignore +++ b/.gitignore @@ -122,3 +122,4 @@ $houdini # traefik.me certs apps/console/config/certs/traefik.me.crt apps/console/config/certs/traefik.me.key +kubernetes diff --git a/.secrets.example b/.secrets.example index e43ca8d8f..c300e475e 100644 --- a/.secrets.example +++ b/.secrets.example @@ -23,6 +23,12 @@ AUTH_PROVIDER_GOOGLE_CLIENT_SECRET = 'FIXME' AUTH_PROVIDER_GITHUB_CLIENT_ID = 'FIXME' AUTH_PROVIDER_GITHUB_CLIENT_SECRET = 'FIXME' +# CLOUDFLARE TURNSTILE +## https://developers.cloudflare.com/turnstile/troubleshooting/testing/ +CLOUDFLARE_TURNSTILE_SECRET_KEY = 'FIXME' +CLOUDFLARE_TURNSTILE_SECRET_KEY_ALWAYS_PASSES = '1x0000000000000000000000000000000AA' +CLOUDFLARE_TURNSTILE_SECRET_KEY_ALWAYS_FAILS = '2x0000000000000000000000000000000AA' + ## SMTP AUTH_SMTP_AUTH_METHOD = 'PLAIN' AUTH_SMTP_HOST = 'mailhog' diff --git a/.secrets.production.example b/.secrets.production.example index fe1c67247..df2448a43 100644 --- a/.secrets.production.example +++ b/.secrets.production.example @@ -23,6 +23,12 @@ AUTH_PROVIDER_GOOGLE_CLIENT_SECRET = 'FIXME' AUTH_PROVIDER_GITHUB_CLIENT_ID = 'FIXME' AUTH_PROVIDER_GITHUB_CLIENT_SECRET = 'FIXME' +# CLOUDFLARE TURNSTILE +## https://developers.cloudflare.com/turnstile/troubleshooting/testing/ +CLOUDFLARE_TURNSTILE_SECRET_KEY = 'FIXME' +CLOUDFLARE_TURNSTILE_SECRET_KEY_ALWAYS_PASSES = '1x0000000000000000000000000000000AA' +CLOUDFLARE_TURNSTILE_SECRET_KEY_ALWAYS_FAILS = '2x0000000000000000000000000000000AA' + ## SMTP AUTH_SMTP_AUTH_METHOD = 'PLAIN' AUTH_SMTP_HOST = 'smtp.gmail.com' diff --git a/.vscode/settings.json b/.vscode/settings.json index 3533a80ff..8d5b4f683 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -55,7 +55,7 @@ // To make tailwindcss-intellisense work in .svelte files "editor.quickSuggestions": { "comments": false, - "strings": "on" + "strings": "on" }, ////////// Search ////////// "search.followSymlinks": false, diff --git a/Dockerfile b/Dockerfile index 658391851..9f297f552 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,7 @@ ENV SCOPE=${SCOPE} #https://github.com/vercel/turbo/tree/main/examples/with-docker # Install pnpm +# RUN corepack enable pnpm ENV PNPM_HOME="/root/.local/share/pnpm" ENV PATH="${PATH}:${PNPM_HOME}" SHELL ["/bin/bash", "-c"] @@ -70,8 +71,11 @@ COPY turbo.json turbo.json ARG TURBO_TEAM ENV TURBO_TEAM=$TURBO_TEAM -ARG TURBO_TOKEN -ENV TURBO_TOKEN=$TURBO_TOKEN +ARG TURBO_TEAM +ENV TURBO_TEAM=$TURBO_TEAM + +ARG TURBO_REMOTE_ONLY=true +ENV TURBO_REMOTE_ONLY=$TURBO_REMOTE_ONLY ENV NODE_OPTIONS="--max-old-space-size=4096" RUN pnpm turbo run build --filter=${SCOPE}... diff --git a/apps/console/README.md b/apps/console/README.md index c1dcc8abc..16bcc687d 100644 --- a/apps/console/README.md +++ b/apps/console/README.md @@ -102,15 +102,3 @@ You can preview the production build with `turbo preview`. ```shell gcloud run deploy --allow-unauthenticated ``` - -To reset deleted (soft) `policies` and `rules` - -```sql -UPDATE public.rules SET deleted_at = null WHERE deleted_at is not null; -UPDATE public.policies SET deleted_at = null WHERE deleted_at is not null; -``` - -## TODO - -- After user record created for first-time (i.e., after user login), have admins assign `organization` and `groups` via Web UI: -- use [lcl.host](https://anchor.dev/docs/lcl-host/why-lcl) diff --git a/apps/console/houdini.config.js b/apps/console/houdini.config.js index 2125ed060..29d013432 100644 --- a/apps/console/houdini.config.js +++ b/apps/console/houdini.config.js @@ -17,23 +17,27 @@ const config = { // HINT: we need to generate scheam for highest role level that app support. headers: { 'X-Hasura-Admin-Secret': (env) => env.HASURA_GRAPHQL_ADMIN_SECRET, - 'x-hasura-allowed-roles': 'user me supervisor manager', - 'x-hasura-role': 'manager', + 'x-hasura-allowed-roles': 'user me sys:admin org:member org:admin org:billing org:owner', + 'x-hasura-role': 'org:owner', + }, + }, + types: { + memberships: { + keys: ['userId', 'orgId'], + }, + }, + features: { + runtimeScalars: { + UserIdFromSession: { + type: 'uuid', + resolve: ({ session }) => session?.userId, + }, + OrgIdFromSession: { + type: 'uuid', + resolve: ({ session }) => session?.orgId, + }, }, }, - // types: { - // user: { - // keys: ['id'], - // }, - // }, - // features: { - // runtimeScalars: { - // UserId: { - // type: 'uuid', - // resolve: ({ session }) => session?.userId, - // }, - // }, - // }, plugins: { // 'houdini-plugin-svelte-global-stores': { // generate: 'all' @@ -58,9 +62,8 @@ const config = { return date?.toISOString(); }, }, - Decimal: { - type: 'number', + type: 'Number', unmarshal(val) { return new Number(val); }, @@ -69,7 +72,7 @@ const config = { }, }, smallint: { - type: 'number', + type: 'Number', unmarshal(val) { return new Number(val); }, @@ -77,6 +80,10 @@ const config = { return number.toString(); }, }, + bigint: { + type: 'Number', + ...defaultMarshall, + }, URL: { type: 'URL', unmarshal(val) { @@ -120,7 +127,7 @@ const config = { ...defaultMarshall, }, jsonb: { - type: 'object', + type: 'Object', ...defaultMarshall, }, timestamp: { @@ -139,18 +146,14 @@ const config = { // const server = new Date(val); // const offset = server.getTimezoneOffset(); // return new Date(server.getTime() + offset * 60000); - return new Date(val); + return val ? new Date(val) : null; }, marshal(date) { return date?.toISOString(); }, }, - bigint: { - type: 'number', - ...defaultMarshall, - }, bytea: { - type: 'binary', + type: 'Binary', ...defaultMarshall, }, }, diff --git a/apps/console/package.json b/apps/console/package.json index 6ea789d8d..1e963a0ef 100644 --- a/apps/console/package.json +++ b/apps/console/package.json @@ -6,8 +6,10 @@ "scripts": { "build": "dotenv-run -f .env -f .secrets -v -- vite build", "build:production": "NODE_ENV=production dotenv-run -f .env -f .secrets -v -- vite build", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "sv:check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "sv:check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "check": "biome check .", + "check:fix": "biome check . --write", "clean": "git clean -xdf -e .vercel -e config", "dev": "dotenv-run -f .env -f .secrets -v -- vite dev", "dev:debug": "DEBUG=* dotenv-run -f .env -f .secrets -v '.*' -u -- vite dev", @@ -31,17 +33,16 @@ "test:unit:ui": "dotenv-run -f .env -f .secrets -v -- vitest --ui" }, "devDependencies": { - "@ai-sdk/azure": "1.0.7", - "@ai-sdk/openai": "1.0.5", - "@ai-sdk/svelte": "1.0.3", - "@aibrow/dom-types": "1.2.1", - "@floating-ui/dom": "1.6.12", - "@fontsource-variable/inter": "5.1.0", + "@ai-sdk/azure": "1.0.20", + "@ai-sdk/openai": "1.0.18", + "@ai-sdk/svelte": "1.0.10", + "@aibrow/dom-types": "1.3.5", + "@floating-ui/dom": "1.6.13", + "@fontsource-variable/inter": "5.1.1", "@inlang/cli": "2.18.1", - "@inlang/paraglide-js": "1.11.3", - "@inlang/paraglide-js-adapter-sveltekit": "0.6.7", - "@nhost/nhost-js": "3.2.1", - "@skeletonlabs/skeleton": "2.10.3", + "@inlang/paraglide-sveltekit": "0.14.0", + "@nhost/nhost-js": "3.2.3", + "@skeletonlabs/skeleton": "2.10.4", "@skeletonlabs/tw-plugin": "0.4.0", "@spectacular/biome-config": "workspace:*", "@spectacular/role-houdini": "workspace:*", @@ -51,71 +52,72 @@ "@spectacular/utils": "workspace:*", "@svelte-plugins/datepicker": "1.0.9", "@sveltejs/adapter-auto": "3.3.1", - "@sveltejs/adapter-node": "5.2.9", - "@sveltejs/adapter-vercel": "5.5.0", + "@sveltejs/adapter-node": "5.2.11", + "@sveltejs/adapter-vercel": "5.5.2", "@sveltejs/enhanced-img": "0.3.10", - "@sveltejs/kit": "2.8.5", + "@sveltejs/kit": "2.15.2", "@sveltejs/vite-plugin-svelte": "3.1.2", "@tailwindcss/container-queries": "0.1.1", - "@tailwindcss/forms": "0.5.9", - "@tailwindcss/typography": "0.5.15", + "@tailwindcss/forms": "0.5.10", + "@tailwindcss/typography": "0.5.16", "@testing-library/jest-dom": "6.6.3", "@testing-library/svelte": "5.2.6", "@types/d3-scale": "4.0.8", "@types/dom-chromium-ai": "0.0.4", "@types/js-cookie": "3.0.6", - "@types/node": "22.10.1", - "@unovis/svelte": "1.5.0-beta.3", - "@unovis/ts": "1.5.0-beta.3", + "@types/node": "22.10.6", + "@unovis/svelte": "1.5.0", + "@unovis/ts": "1.5.0", "@vercel/analytics": "1.4.1", "@vercel/flags": "2.6.3", "@vercel/speed-insights": "1.1.0", - "@vercel/toolbar": "0.1.27", - "@vincjo/datatables": "1.14.10", + "@vercel/toolbar": "0.1.30", + "@vincjo/datatables": "2.2.0", "@vitest/coverage-v8": "2.1.8", - "@xyflow/svelte": "0.1.24", - "ai": "4.0.10", + "@xyflow/svelte": "0.1.26", + "ai": "4.0.34", "autoprefixer": "10.4.20", "chrome-ai": "1.11.1", "date-fns": "4.1.0", "formsnap": "1.0.1", - "graphql": "16.9.0", - "graphql-ws": "5.16.0", - "houdini": "1.3.1", - "houdini-svelte": "2.0.1", + "graphql": "16.10.0", + "graphql-ws": "5.16.2", + "houdini": "1.4.0", + "houdini-svelte": "2.1.0", "js-cookie": "3.0.5", - "jsdom": "25.0.1", - "lucide-svelte": "0.462.0", + "jsdom": "26.0.0", + "lucide-svelte": "0.471.0", "neverthrow": "8.1.1", - "ollama-ai-provider": "1.0.0", + "ollama-ai-provider": "1.1.0", "openai-zod-to-json-schema": "1.0.3", "paneforge": "0.0.6", - "postcss": "8.4.49", + "postcss": "8.5.0", "svelte": "4.2.19", "svelte-adapter-bun": "0.5.2", - "svelte-check": "4.1.0", + "svelte-check": "4.1.4", "svelte-meta-tags": "3.1.4", "svelte-persisted-store": "0.12.0", "svelte-select": "5.8.3", - "sveltekit-flash-message": "2.4.4", + "svelte-turnstile": "0.10.0", + "sveltekit-flash-message": "2.4.5", "sveltekit-rate-limiter": "0.6.1", "sveltekit-search-params": "3.0.0", - "sveltekit-superforms": "2.21.0", + "sveltekit-superforms": "2.22.1", "sveltekit-view-transition": "0.5.3", - "swapy": "0.4.2", - "tailwind-merge": "2.5.5", + "swapy": "1.0.3", + "tailwind-merge": "2.6.0", "tailwind-variants": "0.3.0", - "tailwindcss": "3.4.15", + "tailwindcss": "3.4.17", "tailwindcss-animate": "1.0.7", "tslib": "2.8.1", - "typescript": "5.7.2", + "typescript": "5.7.3", "vite": "5.4.11", "vitest": "2.1.8", "xstate": "4.38.3", - "zod": "3.23.8" + "zod": "3.24.1" }, "optionalDependencies": { - "@playwright/test": "1.49.0", + "@playwright/test": "1.49.1", "@vitest/ui": "2.1.8" } } diff --git a/apps/console/project.inlang/es.json b/apps/console/project.inlang/es.json index 1c5810064..b157ea78d 100644 --- a/apps/console/project.inlang/es.json +++ b/apps/console/project.inlang/es.json @@ -1,26 +1,86 @@ { "$schema": "https://inlang.com/schema/inlang-message-format", "language": "Idioma", - "signin": "Iniciar sesión", - "signup": "Registrarse", - "signout": "Cerrar sesión", - "forgotPassword": "¿Olvidaste tu contraseña?", - "contact": "Contacto", - "privacy": "Privacidad", - "terms": "Términos", - "email": "Dirección de correo electrónico", - "password": "Contraseña", - "firstName": "Nombre", - "lastName": "Apellido", - "profile": "Perfil", - "home": "Inicio", - "protected": "Protegido", - "auth_password_reset_success_emailSent": "Correo electrónico de restablecimiento de contraseña enviado", - "auth_password_reset_success_checkEmail": "Verifique su cuenta de correo electrónico para obtener un enlace para restablecer su contraseña. Si no aparece en unos minutos, verifique su carpeta de correo no deseado.", - "auth_password_reset_resetProblem": "Problema al restablecer la contraseña", - "auth_password_reset_sendResetEmail": "Enviar correo electrónico de restablecimiento de contraseña", - "auth_password_update_success_updated": "Contraseña actualizada correctamente", - "auth_password_update_changePassword": "Cambiar contraseña", - "auth_password_update_passwordProblem": "Problema al cambiar la contraseña", - "auth_password_update_updatePassword": "Actualizar contraseña" + "welcome": "Bienvenido a SvelteKit", + "current_language_tag": "La etiqueta de idioma actual es \"{languageTag}\".", + "greeting": "¡Bienvenido {name}! Tienes {count} mensajes.", + "change_language_to": "Cambiar idioma a {languageTag}", + "buttons_search": "Buscar", + "buttons_add": "Añadir", + "buttons_remove": "Eliminar", + "buttons_create": "Crear", + "buttons_edit": "Editar", + "buttons_update": "Actualizar", + "buttons_delte": "Eliminar", + "buttons_back": "Atrás", + "buttons_submit": "Enviar", + "buttons_save": "Guardar", + "buttons_reset": "Reiniciar", + "buttons_logout": "Cerrar sesión", + "buttons_login_youtube": "Iniciar sesión con YouTube", + "labels_menu_home": "Inicio", + "labels_menu_dashboard": "Tablero", + "labels_title": "Título", + "labels_description": "Descripción", + "labels_visibility": "Visibilidad", + "labels_views": "{0} vistas", + "labels_filter": "Filtrar", + "labels_privacy": "Privacidad", + "labels_terms": "Términos", + "errors_title_required": "El título no puede estar vacío.", + "errors_description_required": "La descripción no puede estar vacía.", + "errors_not_found": "No encontrado.", + "messages_please_wait": "Por favor espere...", + "log": "¡Este registro fue llamado desde {fileName}!", + "auth_labels_signin": "Iniciar sesión", + "auth_labels_signin_with_email": "Iniciar sesión con", + "auth_labels_signin_with_webauthn": "Iniciar sesión con", + "auth_labels_signin_problem": "Problema al iniciar sesión", + "auth_labels_signup": "Registrarse", + "auth_labels_signout": "Cerrar sesión", + "auth_labels_passkey": "Clave de paso", + "auth_labels_magic_link": "Enlace mágico", + "auth_labels_without_account": "¿No tienes una cuenta?", + "auth_labels_with_account": "¿Ya tienes", + "auth_labels_back_to": "Volver a", + "auth_labels_forgot_password": "¿Olvidaste tu contraseña?", + "auth_labels_change_password": "Cambiar tu contraseña", + "auth_labels_password_problem": "Problema al cambiar la contraseña", + "auth_labels_update_password": "Actualizar contraseña", + "auth_labels_reset_password": "Enviar correo electrónico de restablecimiento de contraseña", + "auth_labels_reset_password_problem": "Problema al restablecer la contraseña", + "auth_messages_reset_password_healding": "Restablece tu contraseña", + "auth_messages_reset_password_subheading": "Recibe instrucciones por correo electrónico para restablecer tu contraseña.", + "auth_messages_aaa": "Enviar correo electrónico de restablecimiento de contraseña", + "auth_forms_first_organization_label": "Organización", + "auth_forms_first_organization_placeholder": "Organización", + "auth_forms_first_name_label": "Nombre", + "auth_forms_first_name_placeholder": "Nombre", + "auth_forms_last_name_label": "Apellido", + "auth_forms_last_name_placeholder": "Apellido", + "auth_forms_email_label": "Correo electrónico", + "auth_forms_email_placeholder": "Dirección de correo electrónico", + "auth_forms_password_label": "Contraseña", + "auth_forms_password_placeholder": "Contraseña", + "auth_forms_confirm_password_label": "Confirmar contraseña", + "auth_forms_confirm_password_placeholder": "Confirmar contraseña", + "about_path": "/acerca-de", + "dashboard_labels_create_list": "Haz clic en Crear para comenzar.", + "dashboard_messages_tagline": "Presentando la mejor experiencia de YouTube. Ya sea que esté buscando contenido nuevo para ver o quiera compartir su propia lista seleccionada con amigos, nuestra aplicación lo tiene cubierto.", + "error_page_message": "Lo sentimos, la página que está buscando no se pudo encontrar.", + "profile_forms_change_password_label": "Contraseña", + "profile_forms_change_password_placeholder": "Contraseña", + "profile_forms_change_password_description": "Introduzca su nueva contraseña", + "profile_forms_change_password_confirm_label": "Confirmar contraseña", + "profile_forms_change_password_confirm_placeholder": "Confirmar contraseña", + "profile_forms_change_password_confirm_description": "Confirme su nueva contraseña", + "profile_forms_change_email_label": "Cambiar correo electrónico", + "profile_forms_change_email_placeholder": "Correo electrónico", + "profile_forms_change_email_description": "Introduzca su nuevo correo electrónico", + "profile_forms_create_pat_button": "Crear token de acceso personal", + "profile_forms_nickname_label": "Apodo", + "profile_forms_nickname_placeholder": "Apodo para el dispositivo (opcional)", + "profile_forms_nickname_description": "Asegúrese de recordar el nombre de su dispositivo", + "profile_hasura_jwt_claims_label": "Reclamaciones de Hasura JWT", + "profile_nhost_refresh_session_label": "Actualizar ficha" } diff --git a/apps/console/project.inlang/settings.json b/apps/console/project.inlang/settings.json index 4746c68dc..023621dd4 100644 --- a/apps/console/project.inlang/settings.json +++ b/apps/console/project.inlang/settings.json @@ -1,14 +1,12 @@ { "$schema": "https://inlang.com/schema/project-settings", - "sourceLanguageTag": "en", - "languageTags": ["en", "de"], "modules": [ "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@latest/dist/index.js", "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-identical-pattern@latest/dist/index.js", "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@latest/dist/index.js", "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-without-source@latest/dist/index.js", "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-valid-js-identifier@latest/dist/index.js", - "https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@latest/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@2/dist/index.js", "https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@latest/dist/index.js", "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-snake-case-id@latest/dist/index.js" ], @@ -18,5 +16,7 @@ "messageLintRuleLevels": { "messageLintRule.inlang.missingTranslation": "error", "messageLintRule.inlang.validJsIdentifier": "error" - } + }, + "sourceLanguageTag": "en", + "languageTags": ["en", "es", "de"] } diff --git a/apps/console/schema.graphql b/apps/console/schema.graphql index e7ecfba4c..9487a1ca0 100644 --- a/apps/console/schema.graphql +++ b/apps/console/schema.graphql @@ -159,29 +159,12 @@ input String_comparison_exp { _similar: String } -"""action enum""" +"""policy action enum""" type action { description: String! value: String! } -""" -aggregated selection of "action" -""" -type action_aggregate { - aggregate: action_aggregate_fields - nodes: [action!]! -} - -""" -aggregate fields of "action" -""" -type action_aggregate_fields { - count(columns: [action_select_column!], distinct: Boolean): Int! - max: action_max_fields - min: action_min_fields -} - """ Boolean expression to filter rows from the table "action". All fields are combined with a logical 'AND'. """ @@ -221,18 +204,6 @@ input action_enum_comparison_exp { _nin: [action_enum!] } -"""aggregate max on columns""" -type action_max_fields { - description: String - value: String -} - -"""aggregate min on columns""" -type action_min_fields { - description: String - value: String -} - """Ordering options when selecting data from "action".""" input action_order_by { description: order_by @@ -304,6 +275,34 @@ type authRefreshTokens { userId: uuid! } +""" +aggregated selection of "auth.refresh_tokens" +""" +type authRefreshTokens_aggregate { + aggregate: authRefreshTokens_aggregate_fields + nodes: [authRefreshTokens!]! +} + +input authRefreshTokens_aggregate_bool_exp { + count: authRefreshTokens_aggregate_bool_exp_count +} + +input authRefreshTokens_aggregate_bool_exp_count { + arguments: [authRefreshTokens_select_column!] + distinct: Boolean + filter: authRefreshTokens_bool_exp + predicate: Int_comparison_exp! +} + +""" +aggregate fields of "auth.refresh_tokens" +""" +type authRefreshTokens_aggregate_fields { + count(columns: [authRefreshTokens_select_column!], distinct: Boolean): Int! + max: authRefreshTokens_max_fields + min: authRefreshTokens_min_fields +} + """ order by aggregate values of table "auth.refresh_tokens" """ @@ -329,6 +328,14 @@ input authRefreshTokens_bool_exp { userId: uuid_comparison_exp } +"""aggregate max on columns""" +type authRefreshTokens_max_fields { + createdAt: timestamptz + expiresAt: timestamptz + id: uuid + userId: uuid +} + """ order by max() on columns of table "auth.refresh_tokens" """ @@ -339,6 +346,14 @@ input authRefreshTokens_max_order_by { userId: order_by } +"""aggregate min on columns""" +type authRefreshTokens_min_fields { + createdAt: timestamptz + expiresAt: timestamptz + id: uuid + userId: uuid +} + """ order by min() on columns of table "auth.refresh_tokens" """ @@ -430,6 +445,34 @@ type authUserProviders { userId: uuid! } +""" +aggregated selection of "auth.user_providers" +""" +type authUserProviders_aggregate { + aggregate: authUserProviders_aggregate_fields + nodes: [authUserProviders!]! +} + +input authUserProviders_aggregate_bool_exp { + count: authUserProviders_aggregate_bool_exp_count +} + +input authUserProviders_aggregate_bool_exp_count { + arguments: [authUserProviders_select_column!] + distinct: Boolean + filter: authUserProviders_bool_exp + predicate: Int_comparison_exp! +} + +""" +aggregate fields of "auth.user_providers" +""" +type authUserProviders_aggregate_fields { + count(columns: [authUserProviders_select_column!], distinct: Boolean): Int! + max: authUserProviders_max_fields + min: authUserProviders_min_fields +} + """ order by aggregate values of table "auth.user_providers" """ @@ -455,6 +498,16 @@ input authUserProviders_bool_exp { userId: uuid_comparison_exp } +"""aggregate max on columns""" +type authUserProviders_max_fields { + createdAt: timestamptz + id: uuid + providerId: String + providerUserId: String + updatedAt: timestamptz + userId: uuid +} + """ order by max() on columns of table "auth.user_providers" """ @@ -467,6 +520,16 @@ input authUserProviders_max_order_by { userId: order_by } +"""aggregate min on columns""" +type authUserProviders_min_fields { + createdAt: timestamptz + id: uuid + providerId: String + providerUserId: String + updatedAt: timestamptz + userId: uuid +} + """ order by min() on columns of table "auth.user_providers" """ @@ -609,29 +672,6 @@ input authUserRoles_bool_exp { userId: uuid_comparison_exp } -""" -unique or primary key constraints on table "auth.user_roles" -""" -enum authUserRoles_constraint { - """ - unique or primary key constraint on columns "id" - """ - user_roles_pkey - - """ - unique or primary key constraint on columns "user_id", "role" - """ - user_roles_user_id_role_key -} - -""" -input type for inserting data into table "auth.user_roles" -""" -input authUserRoles_insert_input { - role: String - userId: uuid -} - """aggregate max on columns""" type authUserRoles_max_fields { createdAt: timestamptz @@ -679,15 +719,6 @@ type authUserRoles_mutation_response { returning: [authUserRoles!]! } -""" -on_conflict condition type for table "auth.user_roles" -""" -input authUserRoles_on_conflict { - constraint: authUserRoles_constraint! - update_columns: [authUserRoles_update_column!]! = [] - where: authUserRoles_bool_exp -} - """Ordering options when selecting data from "auth.user_roles".""" input authUserRoles_order_by { createdAt: order_by @@ -733,14 +764,6 @@ input authUserRoles_stream_cursor_value_input { userId: uuid } -""" -placeholder for update columns of table "auth.user_roles" (current role has no relevant permissions) -""" -enum authUserRoles_update_column { - """placeholder (do not use)""" - _PLACEHOLDER -} - """ User webauthn security keys. Don't modify its structure as Hasura Auth relies on it to function properly. """ @@ -753,6 +776,34 @@ type authUserSecurityKeys { userId: uuid! } +""" +aggregated selection of "auth.user_security_keys" +""" +type authUserSecurityKeys_aggregate { + aggregate: authUserSecurityKeys_aggregate_fields + nodes: [authUserSecurityKeys!]! +} + +input authUserSecurityKeys_aggregate_bool_exp { + count: authUserSecurityKeys_aggregate_bool_exp_count +} + +input authUserSecurityKeys_aggregate_bool_exp_count { + arguments: [authUserSecurityKeys_select_column!] + distinct: Boolean + filter: authUserSecurityKeys_bool_exp + predicate: Int_comparison_exp! +} + +""" +aggregate fields of "auth.user_security_keys" +""" +type authUserSecurityKeys_aggregate_fields { + count(columns: [authUserSecurityKeys_select_column!], distinct: Boolean): Int! + max: authUserSecurityKeys_max_fields + min: authUserSecurityKeys_min_fields +} + """ order by aggregate values of table "auth.user_security_keys" """ @@ -775,6 +826,13 @@ input authUserSecurityKeys_bool_exp { userId: uuid_comparison_exp } +"""aggregate max on columns""" +type authUserSecurityKeys_max_fields { + id: uuid + nickname: String + userId: uuid +} + """ order by max() on columns of table "auth.user_security_keys" """ @@ -784,6 +842,13 @@ input authUserSecurityKeys_max_order_by { userId: order_by } +"""aggregate min on columns""" +type authUserSecurityKeys_min_fields { + id: uuid + nickname: String + userId: uuid +} + """ order by min() on columns of table "auth.user_security_keys" """ @@ -908,12 +973,19 @@ enum cursor_ordering { DESC } -"""device to pool bridge table""" +input device_associated_pools_args { + device_row: devices_scalar +} + +input device_dissociated_pools_args { + device_row: devices_scalar +} + +"""Device to Pool association table""" type device_pools { """An object relationship""" device: devices! deviceId: uuid! - id: uuid! """An object relationship""" pool: pools! @@ -928,17 +1000,6 @@ type device_pools_aggregate { nodes: [device_pools!]! } -input device_pools_aggregate_bool_exp { - count: device_pools_aggregate_bool_exp_count -} - -input device_pools_aggregate_bool_exp_count { - arguments: [device_pools_select_column!] - distinct: Boolean - filter: device_pools_bool_exp - predicate: Int_comparison_exp! -} - """ aggregate fields of "device_pools" """ @@ -948,25 +1009,6 @@ type device_pools_aggregate_fields { min: device_pools_min_fields } -""" -order by aggregate values of table "device_pools" -""" -input device_pools_aggregate_order_by { - count: order_by - max: device_pools_max_order_by - min: device_pools_min_order_by -} - -""" -input type for inserting array relation for remote table "device_pools" -""" -input device_pools_arr_rel_insert_input { - data: [device_pools_insert_input!]! - - """upsert condition""" - on_conflict: device_pools_on_conflict -} - """ Boolean expression to filter rows from the table "device_pools". All fields are combined with a logical 'AND'. """ @@ -976,7 +1018,6 @@ input device_pools_bool_exp { _or: [device_pools_bool_exp!] device: devices_bool_exp deviceId: uuid_comparison_exp - id: uuid_comparison_exp pool: pools_bool_exp poolId: uuid_comparison_exp } @@ -985,15 +1026,10 @@ input device_pools_bool_exp { unique or primary key constraints on table "device_pools" """ enum device_pools_constraint { - """ - unique or primary key constraint on columns "id" - """ - device_pools_pkey - """ unique or primary key constraint on columns "pool_id", "device_id" """ - device_pools_pool_id_device_id_key + device_pools_pkey } """ @@ -1008,35 +1044,15 @@ input device_pools_insert_input { """aggregate max on columns""" type device_pools_max_fields { deviceId: uuid - id: uuid poolId: uuid } -""" -order by max() on columns of table "device_pools" -""" -input device_pools_max_order_by { - deviceId: order_by - id: order_by - poolId: order_by -} - """aggregate min on columns""" type device_pools_min_fields { deviceId: uuid - id: uuid poolId: uuid } -""" -order by min() on columns of table "device_pools" -""" -input device_pools_min_order_by { - deviceId: order_by - id: order_by - poolId: order_by -} - """ response of any mutation on the table "device_pools" """ @@ -1061,7 +1077,6 @@ input device_pools_on_conflict { input device_pools_order_by { device: devices_order_by deviceId: order_by - id: order_by pool: pools_order_by poolId: order_by } @@ -1073,9 +1088,6 @@ enum device_pools_select_column { """column name""" deviceId - """column name""" - id - """column name""" poolId } @@ -1094,7 +1106,6 @@ input device_pools_stream_cursor_input { """Initial value of the column from where the streaming should start""" input device_pools_stream_cursor_value_input { deviceId: uuid - id: uuid poolId: uuid } @@ -1106,10 +1117,9 @@ enum device_pools_update_column { _PLACEHOLDER } -"""Devices Metadata""" +"""Table containing devices data""" type devices { alternateDns: Boolean - annotations: hstore """Used as Computed Field on Devices Table""" associatedPools( @@ -1129,7 +1139,7 @@ type devices { where: pools_bool_exp ): [pools!] createdAt: timestamptz! - createdBy: String! + createdBy: uuid! description: String displayName: String! @@ -1152,12 +1162,16 @@ type devices { ): [pools!] id: uuid! ip: String! - organization: String! + metadata( + """JSON select path""" + path: String + ): jsonb + orgId: uuid! proxyIp: Boolean publicIp: String tags: [String!] updatedAt: timestamptz! - updatedBy: String! + updatedBy: uuid! version: String } @@ -1169,6 +1183,33 @@ type devices_aggregate { nodes: [devices!]! } +input devices_aggregate_bool_exp { + bool_and: devices_aggregate_bool_exp_bool_and + bool_or: devices_aggregate_bool_exp_bool_or + count: devices_aggregate_bool_exp_count +} + +input devices_aggregate_bool_exp_bool_and { + arguments: devices_select_column_devices_aggregate_bool_exp_bool_and_arguments_columns! + distinct: Boolean + filter: devices_bool_exp + predicate: Boolean_comparison_exp! +} + +input devices_aggregate_bool_exp_bool_or { + arguments: devices_select_column_devices_aggregate_bool_exp_bool_or_arguments_columns! + distinct: Boolean + filter: devices_bool_exp + predicate: Boolean_comparison_exp! +} + +input devices_aggregate_bool_exp_count { + arguments: [devices_select_column!] + distinct: Boolean + filter: devices_bool_exp + predicate: Int_comparison_exp! +} + """ aggregate fields of "devices" """ @@ -1178,6 +1219,20 @@ type devices_aggregate_fields { min: devices_min_fields } +""" +order by aggregate values of table "devices" +""" +input devices_aggregate_order_by { + count: order_by + max: devices_max_order_by + min: devices_min_order_by +} + +"""append existing jsonb value of filtered columns with new jsonb value""" +input devices_append_input { + metadata: jsonb +} + """ Boolean expression to filter rows from the table "devices". All fields are combined with a logical 'AND'. """ @@ -1186,71 +1241,127 @@ input devices_bool_exp { _not: devices_bool_exp _or: [devices_bool_exp!] alternateDns: Boolean_comparison_exp - annotations: hstore_comparison_exp associatedPools: pools_bool_exp createdAt: timestamptz_comparison_exp - createdBy: String_comparison_exp + createdBy: uuid_comparison_exp description: String_comparison_exp displayName: String_comparison_exp dissociatedPools: pools_bool_exp id: uuid_comparison_exp ip: String_comparison_exp - organization: String_comparison_exp + metadata: jsonb_comparison_exp + orgId: uuid_comparison_exp proxyIp: Boolean_comparison_exp publicIp: String_comparison_exp tags: String_array_comparison_exp updatedAt: timestamptz_comparison_exp - updatedBy: String_comparison_exp + updatedBy: uuid_comparison_exp version: String_comparison_exp } +""" +delete the field or element with specified path (for JSON arrays, negative integers count from the end) +""" +input devices_delete_at_path_input { + metadata: [String!] +} + +""" +delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array +""" +input devices_delete_elem_input { + metadata: Int +} + +""" +delete key/value pair or string element. key/value pairs are matched based on their key value +""" +input devices_delete_key_input { + metadata: String +} + """aggregate max on columns""" type devices_max_fields { createdAt: timestamptz - createdBy: String + createdBy: uuid description: String displayName: String id: uuid ip: String - organization: String + orgId: uuid publicIp: String tags: [String!] updatedAt: timestamptz - updatedBy: String + updatedBy: uuid version: String } +""" +order by max() on columns of table "devices" +""" +input devices_max_order_by { + createdAt: order_by + createdBy: order_by + description: order_by + displayName: order_by + id: order_by + ip: order_by + orgId: order_by + publicIp: order_by + tags: order_by + updatedAt: order_by + updatedBy: order_by + version: order_by +} + """aggregate min on columns""" type devices_min_fields { createdAt: timestamptz - createdBy: String + createdBy: uuid description: String displayName: String id: uuid ip: String - organization: String + orgId: uuid publicIp: String tags: [String!] updatedAt: timestamptz - updatedBy: String + updatedBy: uuid version: String } """ -response of any mutation on the table "devices" +order by min() on columns of table "devices" """ -type devices_mutation_response { - """number of rows affected by the mutation""" - affected_rows: Int! - - """data from the rows affected by the mutation""" - returning: [devices!]! -} - -"""Ordering options when selecting data from "devices".""" -input devices_order_by { +input devices_min_order_by { + createdAt: order_by + createdBy: order_by + description: order_by + displayName: order_by + id: order_by + ip: order_by + orgId: order_by + publicIp: order_by + tags: order_by + updatedAt: order_by + updatedBy: order_by + version: order_by +} + +""" +response of any mutation on the table "devices" +""" +type devices_mutation_response { + """number of rows affected by the mutation""" + affected_rows: Int! + + """data from the rows affected by the mutation""" + returning: [devices!]! +} + +"""Ordering options when selecting data from "devices".""" +input devices_order_by { alternateDns: order_by - annotations: order_by associatedPools_aggregate: pools_aggregate_order_by createdAt: order_by createdBy: order_by @@ -1259,7 +1370,8 @@ input devices_order_by { dissociatedPools_aggregate: pools_aggregate_order_by id: order_by ip: order_by - organization: order_by + metadata: order_by + orgId: order_by proxyIp: order_by publicIp: order_by tags: order_by @@ -1273,6 +1385,13 @@ input devices_pk_columns_input { id: uuid! } +"""prepend existing jsonb value of filtered columns with new jsonb value""" +input devices_prepend_input { + metadata: jsonb +} + +scalar devices_scalar + """ select columns of table "devices" """ @@ -1280,9 +1399,6 @@ enum devices_select_column { """column name""" alternateDns - """column name""" - annotations - """column name""" createdAt @@ -1302,7 +1418,10 @@ enum devices_select_column { ip """column name""" - organization + metadata + + """column name""" + orgId """column name""" proxyIp @@ -1323,13 +1442,36 @@ enum devices_select_column { version } +""" +select "devices_aggregate_bool_exp_bool_and_arguments_columns" columns of table "devices" +""" +enum devices_select_column_devices_aggregate_bool_exp_bool_and_arguments_columns { + """column name""" + alternateDns + + """column name""" + proxyIp +} + +""" +select "devices_aggregate_bool_exp_bool_or_arguments_columns" columns of table "devices" +""" +enum devices_select_column_devices_aggregate_bool_exp_bool_or_arguments_columns { + """column name""" + alternateDns + + """column name""" + proxyIp +} + """ input type for updating data in table "devices" """ input devices_set_input { - annotations: hstore - deletedAt: timestamptz + alternateDns: Boolean description: String + metadata: jsonb + proxyIp: Boolean tags: [String!] } @@ -1347,23 +1489,44 @@ input devices_stream_cursor_input { """Initial value of the column from where the streaming should start""" input devices_stream_cursor_value_input { alternateDns: Boolean - annotations: hstore createdAt: timestamptz - createdBy: String + createdBy: uuid description: String displayName: String id: uuid ip: String - organization: String + metadata: jsonb + orgId: uuid proxyIp: Boolean publicIp: String tags: [String!] updatedAt: timestamptz - updatedBy: String + updatedBy: uuid version: String } input devices_updates { + """append existing jsonb value of filtered columns with new jsonb value""" + _append: devices_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: devices_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: devices_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: devices_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: devices_prepend_input + """sets the columns of the filtered rows to the given values""" _set: devices_set_input @@ -1371,29 +1534,12 @@ input devices_updates { where: devices_bool_exp! } -"""direction enum""" +"""policy direction enum""" type direction { description: String! value: String! } -""" -aggregated selection of "direction" -""" -type direction_aggregate { - aggregate: direction_aggregate_fields - nodes: [direction!]! -} - -""" -aggregate fields of "direction" -""" -type direction_aggregate_fields { - count(columns: [direction_select_column!], distinct: Boolean): Int! - max: direction_max_fields - min: direction_min_fields -} - """ Boolean expression to filter rows from the table "direction". All fields are combined with a logical 'AND'. """ @@ -1424,18 +1570,6 @@ input direction_enum_comparison_exp { _nin: [direction_enum!] } -"""aggregate max on columns""" -type direction_max_fields { - description: String - value: String -} - -"""aggregate min on columns""" -type direction_min_fields { - description: String - value: String -} - """Ordering options when selecting data from "direction".""" input direction_order_by { description: order_by @@ -1643,36 +1777,76 @@ enum files_update_column { _PLACEHOLDER } -"""User groups defined per organization""" +"""Table containing user groups that belongs to an organization""" type groups { - annotations: hstore createdAt: timestamptz! - createdBy: String! + createdBy: uuid! description: String displayName: String! + id: uuid! + metadata( + """JSON select path""" + path: String + ): jsonb + orgId: uuid! - """An array relationship""" - group_users( - """distinct select on columns""" - distinct_on: [user_groups_select_column!] + """An object relationship""" + organization: organizations! + tags: [String!] + updatedAt: timestamptz! + updatedBy: uuid! +} - """limit the number of rows returned""" - limit: Int +""" +aggregated selection of "groups" +""" +type groups_aggregate { + aggregate: groups_aggregate_fields + nodes: [groups!]! +} - """skip the first n rows. Use only with order_by""" - offset: Int +input groups_aggregate_bool_exp { + count: groups_aggregate_bool_exp_count +} - """sort the rows by one or more columns""" - order_by: [user_groups_order_by!] +input groups_aggregate_bool_exp_count { + arguments: [groups_select_column!] + distinct: Boolean + filter: groups_bool_exp + predicate: Int_comparison_exp! +} - """filter the rows returned""" - where: user_groups_bool_exp - ): [user_groups!]! - id: uuid! - organization: String! - tags: [String!] - updatedAt: timestamptz! - updatedBy: String! +""" +aggregate fields of "groups" +""" +type groups_aggregate_fields { + count(columns: [groups_select_column!], distinct: Boolean): Int! + max: groups_max_fields + min: groups_min_fields +} + +""" +order by aggregate values of table "groups" +""" +input groups_aggregate_order_by { + count: order_by + max: groups_max_order_by + min: groups_min_order_by +} + +"""append existing jsonb value of filtered columns with new jsonb value""" +input groups_append_input { + metadata: jsonb +} + +""" +input type for inserting array relation for remote table "groups" +""" +input groups_arr_rel_insert_input { + data: [groups_insert_input!]! + + """upsert condition""" + on_conflict: groups_on_conflict } """ @@ -1682,17 +1856,17 @@ input groups_bool_exp { _and: [groups_bool_exp!] _not: groups_bool_exp _or: [groups_bool_exp!] - annotations: hstore_comparison_exp createdAt: timestamptz_comparison_exp - createdBy: String_comparison_exp + createdBy: uuid_comparison_exp description: String_comparison_exp displayName: String_comparison_exp - group_users: user_groups_bool_exp id: uuid_comparison_exp - organization: String_comparison_exp + metadata: jsonb_comparison_exp + orgId: uuid_comparison_exp + organization: organizations_bool_exp tags: String_array_comparison_exp updatedAt: timestamptz_comparison_exp - updatedBy: String_comparison_exp + updatedBy: uuid_comparison_exp } """ @@ -1700,9 +1874,9 @@ unique or primary key constraints on table "groups" """ enum groups_constraint { """ - unique or primary key constraint on columns "display_name", "organization" + unique or primary key constraint on columns "display_name", "org_id" """ - groups_display_name_organization_unique + groups_org_id_display_name_key """ unique or primary key constraint on columns "id" @@ -1710,16 +1884,92 @@ enum groups_constraint { groups_pkey } +""" +delete the field or element with specified path (for JSON arrays, negative integers count from the end) +""" +input groups_delete_at_path_input { + metadata: [String!] +} + +""" +delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array +""" +input groups_delete_elem_input { + metadata: Int +} + +""" +delete key/value pair or string element. key/value pairs are matched based on their key value +""" +input groups_delete_key_input { + metadata: String +} + """ input type for inserting data into table "groups" """ input groups_insert_input { - annotations: hstore description: String displayName: String - group_users: user_groups_arr_rel_insert_input - organization: String + metadata: jsonb + organization: organizations_obj_rel_insert_input + tags: [String!] +} + +"""aggregate max on columns""" +type groups_max_fields { + createdAt: timestamptz + createdBy: uuid + description: String + displayName: String + id: uuid + orgId: uuid + tags: [String!] + updatedAt: timestamptz + updatedBy: uuid +} + +""" +order by max() on columns of table "groups" +""" +input groups_max_order_by { + createdAt: order_by + createdBy: order_by + description: order_by + displayName: order_by + id: order_by + orgId: order_by + tags: order_by + updatedAt: order_by + updatedBy: order_by +} + +"""aggregate min on columns""" +type groups_min_fields { + createdAt: timestamptz + createdBy: uuid + description: String + displayName: String + id: uuid + orgId: uuid tags: [String!] + updatedAt: timestamptz + updatedBy: uuid +} + +""" +order by min() on columns of table "groups" +""" +input groups_min_order_by { + createdAt: order_by + createdBy: order_by + description: order_by + displayName: order_by + id: order_by + orgId: order_by + tags: order_by + updatedAt: order_by + updatedBy: order_by } """ @@ -1754,14 +2004,14 @@ input groups_on_conflict { """Ordering options when selecting data from "groups".""" input groups_order_by { - annotations: order_by createdAt: order_by createdBy: order_by description: order_by displayName: order_by - group_users_aggregate: user_groups_aggregate_order_by id: order_by - organization: order_by + metadata: order_by + orgId: order_by + organization: organizations_order_by tags: order_by updatedAt: order_by updatedBy: order_by @@ -1772,13 +2022,15 @@ input groups_pk_columns_input { id: uuid! } +"""prepend existing jsonb value of filtered columns with new jsonb value""" +input groups_prepend_input { + metadata: jsonb +} + """ select columns of table "groups" """ enum groups_select_column { - """column name""" - annotations - """column name""" createdAt @@ -1795,7 +2047,10 @@ enum groups_select_column { id """column name""" - organization + metadata + + """column name""" + orgId """column name""" tags @@ -1811,10 +2066,9 @@ enum groups_select_column { input type for updating data in table "groups" """ input groups_set_input { - annotations: hstore - deletedAt: timestamptz description: String displayName: String + metadata: jsonb tags: [String!] } @@ -1831,39 +2085,57 @@ input groups_stream_cursor_input { """Initial value of the column from where the streaming should start""" input groups_stream_cursor_value_input { - annotations: hstore createdAt: timestamptz - createdBy: String + createdBy: uuid description: String displayName: String id: uuid - organization: String + metadata: jsonb + orgId: uuid tags: [String!] updatedAt: timestamptz - updatedBy: String + updatedBy: uuid } """ update columns of table "groups" """ enum groups_update_column { - """column name""" - annotations - - """column name""" - deletedAt - """column name""" description """column name""" displayName + """column name""" + metadata + """column name""" tags } input groups_updates { + """append existing jsonb value of filtered columns with new jsonb value""" + _append: groups_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: groups_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: groups_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: groups_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: groups_prepend_input + """sets the columns of the filtered rows to the given values""" _set: groups_set_input @@ -1871,23 +2143,6 @@ input groups_updates { where: groups_bool_exp! } -scalar hstore - -""" -Boolean expression to compare columns of type "hstore". All fields are combined with logical 'AND'. -""" -input hstore_comparison_exp { - _eq: hstore - _gt: hstore - _gte: hstore - _in: [hstore!] - _is_null: Boolean - _lt: hstore - _lte: hstore - _neq: hstore - _nin: [hstore!] -} - scalar jsonb input jsonb_cast_exp { @@ -1925,11 +2180,270 @@ input jsonb_comparison_exp { _nin: [jsonb!] } -"""mutation root""" -type mutation_root { - """ - delete single row from the table: "auth.refresh_tokens" - """ +"""Table containing user's org and org's default_role""" +type memberships { + createdAt: timestamptz! + createdBy: uuid! + orgId: uuid! + + """An object relationship""" + organization: organizations! + role: String! + updatedAt: timestamptz! + updatedBy: uuid! + + """An object relationship""" + user: users! + userId: uuid! +} + +""" +aggregated selection of "memberships" +""" +type memberships_aggregate { + aggregate: memberships_aggregate_fields + nodes: [memberships!]! +} + +input memberships_aggregate_bool_exp { + count: memberships_aggregate_bool_exp_count +} + +input memberships_aggregate_bool_exp_count { + arguments: [memberships_select_column!] + distinct: Boolean + filter: memberships_bool_exp + predicate: Int_comparison_exp! +} + +""" +aggregate fields of "memberships" +""" +type memberships_aggregate_fields { + count(columns: [memberships_select_column!], distinct: Boolean): Int! + max: memberships_max_fields + min: memberships_min_fields +} + +""" +order by aggregate values of table "memberships" +""" +input memberships_aggregate_order_by { + count: order_by + max: memberships_max_order_by + min: memberships_min_order_by +} + +""" +input type for inserting array relation for remote table "memberships" +""" +input memberships_arr_rel_insert_input { + data: [memberships_insert_input!]! + + """upsert condition""" + on_conflict: memberships_on_conflict +} + +""" +Boolean expression to filter rows from the table "memberships". All fields are combined with a logical 'AND'. +""" +input memberships_bool_exp { + _and: [memberships_bool_exp!] + _not: memberships_bool_exp + _or: [memberships_bool_exp!] + createdAt: timestamptz_comparison_exp + createdBy: uuid_comparison_exp + orgId: uuid_comparison_exp + organization: organizations_bool_exp + role: String_comparison_exp + updatedAt: timestamptz_comparison_exp + updatedBy: uuid_comparison_exp + user: users_bool_exp + userId: uuid_comparison_exp +} + +""" +unique or primary key constraints on table "memberships" +""" +enum memberships_constraint { + """ + unique or primary key constraint on columns "user_id", "org_id" + """ + memberships_pkey +} + +""" +input type for inserting data into table "memberships" +""" +input memberships_insert_input { + organization: organizations_obj_rel_insert_input + role: String + userId: uuid +} + +"""aggregate max on columns""" +type memberships_max_fields { + createdAt: timestamptz + createdBy: uuid + orgId: uuid + role: String + updatedAt: timestamptz + updatedBy: uuid + userId: uuid +} + +""" +order by max() on columns of table "memberships" +""" +input memberships_max_order_by { + createdAt: order_by + createdBy: order_by + orgId: order_by + role: order_by + updatedAt: order_by + updatedBy: order_by + userId: order_by +} + +"""aggregate min on columns""" +type memberships_min_fields { + createdAt: timestamptz + createdBy: uuid + orgId: uuid + role: String + updatedAt: timestamptz + updatedBy: uuid + userId: uuid +} + +""" +order by min() on columns of table "memberships" +""" +input memberships_min_order_by { + createdAt: order_by + createdBy: order_by + orgId: order_by + role: order_by + updatedAt: order_by + updatedBy: order_by + userId: order_by +} + +""" +response of any mutation on the table "memberships" +""" +type memberships_mutation_response { + """number of rows affected by the mutation""" + affected_rows: Int! + + """data from the rows affected by the mutation""" + returning: [memberships!]! +} + +""" +on_conflict condition type for table "memberships" +""" +input memberships_on_conflict { + constraint: memberships_constraint! + update_columns: [memberships_update_column!]! = [] + where: memberships_bool_exp +} + +"""Ordering options when selecting data from "memberships".""" +input memberships_order_by { + createdAt: order_by + createdBy: order_by + orgId: order_by + organization: organizations_order_by + role: order_by + updatedAt: order_by + updatedBy: order_by + user: users_order_by + userId: order_by +} + +"""primary key columns input for table: memberships""" +input memberships_pk_columns_input { + orgId: uuid! + userId: uuid! +} + +""" +select columns of table "memberships" +""" +enum memberships_select_column { + """column name""" + createdAt + + """column name""" + createdBy + + """column name""" + orgId + + """column name""" + role + + """column name""" + updatedAt + + """column name""" + updatedBy + + """column name""" + userId +} + +""" +input type for updating data in table "memberships" +""" +input memberships_set_input { + role: String +} + +""" +Streaming cursor of the table "memberships" +""" +input memberships_stream_cursor_input { + """Stream column input with initial value""" + initial_value: memberships_stream_cursor_value_input! + + """cursor ordering""" + ordering: cursor_ordering +} + +"""Initial value of the column from where the streaming should start""" +input memberships_stream_cursor_value_input { + createdAt: timestamptz + createdBy: uuid + orgId: uuid + role: String + updatedAt: timestamptz + updatedBy: uuid + userId: uuid +} + +""" +update columns of table "memberships" +""" +enum memberships_update_column { + """column name""" + role +} + +input memberships_updates { + """sets the columns of the filtered rows to the given values""" + _set: memberships_set_input + + """filter the rows which have to be updated""" + where: memberships_bool_exp! +} + +"""mutation root""" +type mutation_root { + """ + delete single row from the table: "auth.refresh_tokens" + """ deleteAuthRefreshToken(id: uuid!): authRefreshTokens """ @@ -2003,7 +2517,59 @@ type mutation_root { """ delete single row from the table: "device_pools" """ - delete_device_pools_by_pk(id: uuid!): device_pools + delete_device_pools_by_pk(deviceId: uuid!, poolId: uuid!): device_pools + + """ + delete data from the table: "devices" + """ + delete_devices( + """filter the rows which have to be deleted""" + where: devices_bool_exp! + ): devices_mutation_response + + """ + delete single row from the table: "devices" + """ + delete_devices_by_pk(id: uuid!): devices + + """ + delete data from the table: "groups" + """ + delete_groups( + """filter the rows which have to be deleted""" + where: groups_bool_exp! + ): groups_mutation_response + + """ + delete single row from the table: "groups" + """ + delete_groups_by_pk(id: uuid!): groups + + """ + delete data from the table: "memberships" + """ + delete_memberships( + """filter the rows which have to be deleted""" + where: memberships_bool_exp! + ): memberships_mutation_response + + """ + delete single row from the table: "memberships" + """ + delete_memberships_by_pk(orgId: uuid!, userId: uuid!): memberships + + """ + delete data from the table: "org_settings" + """ + delete_org_settings( + """filter the rows which have to be deleted""" + where: org_settings_bool_exp! + ): org_settings_mutation_response + + """ + delete single row from the table: "org_settings" + """ + delete_org_settings_by_pk(key: String!, org_id: uuid!): org_settings """ delete data from the table: "organizations" @@ -2016,55 +2582,59 @@ type mutation_root { """ delete single row from the table: "organizations" """ - delete_organizations_by_pk(organization: String!): organizations + delete_organizations_by_pk(id: uuid!): organizations """ - delete data from the table: "user_groups" + delete data from the table: "policies" """ - delete_user_groups( + delete_policies( """filter the rows which have to be deleted""" - where: user_groups_bool_exp! - ): user_groups_mutation_response + where: policies_bool_exp! + ): policies_mutation_response """ - delete single row from the table: "user_groups" + delete single row from the table: "policies" """ - delete_user_groups_by_pk(id: uuid!): user_groups + delete_policies_by_pk(id: uuid!): policies """ - delete data from the table: "user_org_roles" + delete data from the table: "pools" """ - delete_user_org_roles( + delete_pools( """filter the rows which have to be deleted""" - where: user_org_roles_bool_exp! - ): user_org_roles_mutation_response + where: pools_bool_exp! + ): pools_mutation_response """ - delete single row from the table: "user_org_roles" + delete single row from the table: "pools" """ - delete_user_org_roles_by_pk(id: uuid!): user_org_roles + delete_pools_by_pk(id: uuid!): pools """ - insert a single row into the table: "auth.user_roles" + delete data from the table: "rules" """ - insertAuthUserRole( - """the row to be inserted""" - object: authUserRoles_insert_input! + delete_rules( + """filter the rows which have to be deleted""" + where: rules_bool_exp! + ): rules_mutation_response - """upsert condition""" - on_conflict: authUserRoles_on_conflict - ): authUserRoles + """ + delete single row from the table: "rules" + """ + delete_rules_by_pk(id: uuid!): rules """ - insert data into the table: "auth.user_roles" + delete data from the table: "user_groups" """ - insertAuthUserRoles( - """the rows to be inserted""" - objects: [authUserRoles_insert_input!]! + delete_user_groups( + """filter the rows which have to be deleted""" + where: user_groups_bool_exp! + ): user_groups_mutation_response - """upsert condition""" - on_conflict: authUserRoles_on_conflict - ): authUserRoles_mutation_response + """ + delete single row from the table: "user_groups" + """ + delete_user_groups_by_pk(groupId: uuid!, userId: uuid!): user_groups """ insert a single row into the table: "storage.files" @@ -2133,44 +2703,88 @@ type mutation_root { ): groups """ - insert data into the table: "organizations" + insert data into the table: "memberships" """ - insert_organizations( + insert_memberships( """the rows to be inserted""" - objects: [organizations_insert_input!]! + objects: [memberships_insert_input!]! """upsert condition""" - on_conflict: organizations_on_conflict - ): organizations_mutation_response + on_conflict: memberships_on_conflict + ): memberships_mutation_response """ - insert a single row into the table: "organizations" + insert a single row into the table: "memberships" """ - insert_organizations_one( + insert_memberships_one( """the row to be inserted""" - object: organizations_insert_input! + object: memberships_insert_input! """upsert condition""" - on_conflict: organizations_on_conflict - ): organizations + on_conflict: memberships_on_conflict + ): memberships """ - insert data into the table: "policies" + insert data into the table: "org_settings" """ - insert_policies( + insert_org_settings( """the rows to be inserted""" - objects: [policies_insert_input!]! + objects: [org_settings_insert_input!]! """upsert condition""" - on_conflict: policies_on_conflict - ): policies_mutation_response + on_conflict: org_settings_on_conflict + ): org_settings_mutation_response """ - insert a single row into the table: "policies" + insert a single row into the table: "org_settings" """ - insert_policies_one( + insert_org_settings_one( """the row to be inserted""" - object: policies_insert_input! + object: org_settings_insert_input! + + """upsert condition""" + on_conflict: org_settings_on_conflict + ): org_settings + + """ + insert data into the table: "organizations" + """ + insert_organizations( + """the rows to be inserted""" + objects: [organizations_insert_input!]! + + """upsert condition""" + on_conflict: organizations_on_conflict + ): organizations_mutation_response + + """ + insert a single row into the table: "organizations" + """ + insert_organizations_one( + """the row to be inserted""" + object: organizations_insert_input! + + """upsert condition""" + on_conflict: organizations_on_conflict + ): organizations + + """ + insert data into the table: "policies" + """ + insert_policies( + """the rows to be inserted""" + objects: [policies_insert_input!]! + + """upsert condition""" + on_conflict: policies_on_conflict + ): policies_mutation_response + + """ + insert a single row into the table: "policies" + """ + insert_policies_one( + """the row to be inserted""" + object: policies_insert_input! """upsert condition""" on_conflict: policies_on_conflict @@ -2242,28 +2856,6 @@ type mutation_root { on_conflict: user_groups_on_conflict ): user_groups - """ - insert data into the table: "user_org_roles" - """ - insert_user_org_roles( - """the rows to be inserted""" - objects: [user_org_roles_insert_input!]! - - """upsert condition""" - on_conflict: user_org_roles_on_conflict - ): user_org_roles_mutation_response - - """ - insert a single row into the table: "user_org_roles" - """ - insert_user_org_roles_one( - """the row to be inserted""" - object: user_org_roles_insert_input! - - """upsert condition""" - on_conflict: user_org_roles_on_conflict - ): user_org_roles - """ update single row of the table: "auth.users" """ @@ -2330,6 +2922,27 @@ type mutation_root { update data of the table: "devices" """ update_devices( + """append existing jsonb value of filtered columns with new jsonb value""" + _append: devices_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: devices_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: devices_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: devices_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: devices_prepend_input + """sets the columns of the filtered rows to the given values""" _set: devices_set_input @@ -2341,6 +2954,27 @@ type mutation_root { update single row of the table: "devices" """ update_devices_by_pk( + """append existing jsonb value of filtered columns with new jsonb value""" + _append: devices_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: devices_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: devices_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: devices_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: devices_prepend_input + """sets the columns of the filtered rows to the given values""" _set: devices_set_input pk_columns: devices_pk_columns_input! @@ -2358,6 +2992,27 @@ type mutation_root { update data of the table: "groups" """ update_groups( + """append existing jsonb value of filtered columns with new jsonb value""" + _append: groups_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: groups_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: groups_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: groups_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: groups_prepend_input + """sets the columns of the filtered rows to the given values""" _set: groups_set_input @@ -2369,6 +3024,27 @@ type mutation_root { update single row of the table: "groups" """ update_groups_by_pk( + """append existing jsonb value of filtered columns with new jsonb value""" + _append: groups_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: groups_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: groups_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: groups_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: groups_prepend_input + """sets the columns of the filtered rows to the given values""" _set: groups_set_input pk_columns: groups_pk_columns_input! @@ -2382,10 +3058,129 @@ type mutation_root { updates: [groups_updates!]! ): [groups_mutation_response] + """ + update data of the table: "memberships" + """ + update_memberships( + """sets the columns of the filtered rows to the given values""" + _set: memberships_set_input + + """filter the rows which have to be updated""" + where: memberships_bool_exp! + ): memberships_mutation_response + + """ + update single row of the table: "memberships" + """ + update_memberships_by_pk( + """sets the columns of the filtered rows to the given values""" + _set: memberships_set_input + pk_columns: memberships_pk_columns_input! + ): memberships + + """ + update multiples rows of table: "memberships" + """ + update_memberships_many( + """updates to execute, in order""" + updates: [memberships_updates!]! + ): [memberships_mutation_response] + + """ + update data of the table: "org_settings" + """ + update_org_settings( + """append existing jsonb value of filtered columns with new jsonb value""" + _append: org_settings_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: org_settings_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: org_settings_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: org_settings_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: org_settings_prepend_input + + """sets the columns of the filtered rows to the given values""" + _set: org_settings_set_input + + """filter the rows which have to be updated""" + where: org_settings_bool_exp! + ): org_settings_mutation_response + + """ + update single row of the table: "org_settings" + """ + update_org_settings_by_pk( + """append existing jsonb value of filtered columns with new jsonb value""" + _append: org_settings_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: org_settings_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: org_settings_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: org_settings_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: org_settings_prepend_input + + """sets the columns of the filtered rows to the given values""" + _set: org_settings_set_input + pk_columns: org_settings_pk_columns_input! + ): org_settings + + """ + update multiples rows of table: "org_settings" + """ + update_org_settings_many( + """updates to execute, in order""" + updates: [org_settings_updates!]! + ): [org_settings_mutation_response] + """ update data of the table: "organizations" """ update_organizations( + """append existing jsonb value of filtered columns with new jsonb value""" + _append: organizations_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: organizations_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: organizations_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: organizations_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: organizations_prepend_input + """sets the columns of the filtered rows to the given values""" _set: organizations_set_input @@ -2397,6 +3192,27 @@ type mutation_root { update single row of the table: "organizations" """ update_organizations_by_pk( + """append existing jsonb value of filtered columns with new jsonb value""" + _append: organizations_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: organizations_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: organizations_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: organizations_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: organizations_prepend_input + """sets the columns of the filtered rows to the given values""" _set: organizations_set_input pk_columns: organizations_pk_columns_input! @@ -2448,6 +3264,27 @@ type mutation_root { update data of the table: "pools" """ update_pools( + """append existing jsonb value of filtered columns with new jsonb value""" + _append: pools_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: pools_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: pools_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: pools_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: pools_prepend_input + """sets the columns of the filtered rows to the given values""" _set: pools_set_input @@ -2459,6 +3296,27 @@ type mutation_root { update single row of the table: "pools" """ update_pools_by_pk( + """append existing jsonb value of filtered columns with new jsonb value""" + _append: pools_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: pools_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: pools_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: pools_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: pools_prepend_input + """sets the columns of the filtered rows to the given values""" _set: pools_set_input pk_columns: pools_pk_columns_input! @@ -2476,23 +3334,65 @@ type mutation_root { update data of the table: "rules" """ update_rules( - """increments the numeric columns with given value of the filtered values""" - _inc: rules_inc_input + """append existing jsonb value of filtered columns with new jsonb value""" + _append: rules_append_input - """sets the columns of the filtered rows to the given values""" - _set: rules_set_input + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: rules_delete_at_path_input - """filter the rows which have to be updated""" - where: rules_bool_exp! - ): rules_mutation_response + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: rules_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: rules_delete_key_input + + """increments the numeric columns with given value of the filtered values""" + _inc: rules_inc_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: rules_prepend_input + + """sets the columns of the filtered rows to the given values""" + _set: rules_set_input + + """filter the rows which have to be updated""" + where: rules_bool_exp! + ): rules_mutation_response """ update single row of the table: "rules" """ update_rules_by_pk( + """append existing jsonb value of filtered columns with new jsonb value""" + _append: rules_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: rules_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: rules_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: rules_delete_key_input + """increments the numeric columns with given value of the filtered values""" _inc: rules_inc_input + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: rules_prepend_input + """sets the columns of the filtered rows to the given values""" _set: rules_set_input pk_columns: rules_pk_columns_input! @@ -2507,32 +3407,32 @@ type mutation_root { ): [rules_mutation_response] """ - update data of the table: "user_org_roles" + update data of the table: "subscriptions" """ - update_user_org_roles( + update_subscriptions( """sets the columns of the filtered rows to the given values""" - _set: user_org_roles_set_input + _set: subscriptions_set_input """filter the rows which have to be updated""" - where: user_org_roles_bool_exp! - ): user_org_roles_mutation_response + where: subscriptions_bool_exp! + ): subscriptions_mutation_response """ - update single row of the table: "user_org_roles" + update single row of the table: "subscriptions" """ - update_user_org_roles_by_pk( + update_subscriptions_by_pk( """sets the columns of the filtered rows to the given values""" - _set: user_org_roles_set_input - pk_columns: user_org_roles_pk_columns_input! - ): user_org_roles + _set: subscriptions_set_input + pk_columns: subscriptions_pk_columns_input! + ): subscriptions """ - update multiples rows of table: "user_org_roles" + update multiples rows of table: "subscriptions" """ - update_user_org_roles_many( + update_subscriptions_many( """updates to execute, in order""" - updates: [user_org_roles_updates!]! - ): [user_org_roles_mutation_response] + updates: [subscriptions_updates!]! + ): [subscriptions_mutation_response] """ update multiples rows of table: "auth.users" @@ -2564,444 +3464,445 @@ enum order_by { desc_nulls_last } -"""organizations in multitenant env""" -type organizations { - allowedEmailDomains: [String!] - allowedEmails: [String!] - description: String! - organization: String! +"""Table containing organization's settings and feature flags""" +type org_settings { + created_at: timestamptz! + created_by: uuid! + key: String! + org_id: uuid! + updated_at: timestamptz! + updated_by: uuid! + value( + """JSON select path""" + path: String + ): jsonb +} + +""" +aggregated selection of "org_settings" +""" +type org_settings_aggregate { + aggregate: org_settings_aggregate_fields + nodes: [org_settings!]! +} + +input org_settings_aggregate_bool_exp { + count: org_settings_aggregate_bool_exp_count +} + +input org_settings_aggregate_bool_exp_count { + arguments: [org_settings_select_column!] + distinct: Boolean + filter: org_settings_bool_exp + predicate: Int_comparison_exp! +} + +""" +aggregate fields of "org_settings" +""" +type org_settings_aggregate_fields { + count(columns: [org_settings_select_column!], distinct: Boolean): Int! + max: org_settings_max_fields + min: org_settings_min_fields } """ -order by aggregate values of table "organizations" +order by aggregate values of table "org_settings" """ -input organizations_aggregate_order_by { +input org_settings_aggregate_order_by { count: order_by - max: organizations_max_order_by - min: organizations_min_order_by + max: org_settings_max_order_by + min: org_settings_min_order_by +} + +"""append existing jsonb value of filtered columns with new jsonb value""" +input org_settings_append_input { + value: jsonb } """ -Boolean expression to filter rows from the table "organizations". All fields are combined with a logical 'AND'. +input type for inserting array relation for remote table "org_settings" """ -input organizations_bool_exp { - _and: [organizations_bool_exp!] - _not: organizations_bool_exp - _or: [organizations_bool_exp!] - allowedEmailDomains: String_array_comparison_exp - allowedEmails: String_array_comparison_exp - description: String_comparison_exp - organization: String_comparison_exp +input org_settings_arr_rel_insert_input { + data: [org_settings_insert_input!]! + + """upsert condition""" + on_conflict: org_settings_on_conflict } """ -unique or primary key constraints on table "organizations" +Boolean expression to filter rows from the table "org_settings". All fields are combined with a logical 'AND'. """ -enum organizations_constraint { +input org_settings_bool_exp { + _and: [org_settings_bool_exp!] + _not: org_settings_bool_exp + _or: [org_settings_bool_exp!] + created_at: timestamptz_comparison_exp + created_by: uuid_comparison_exp + key: String_comparison_exp + org_id: uuid_comparison_exp + updated_at: timestamptz_comparison_exp + updated_by: uuid_comparison_exp + value: jsonb_comparison_exp +} + +""" +unique or primary key constraints on table "org_settings" +""" +enum org_settings_constraint { """ - unique or primary key constraint on columns "organization" + unique or primary key constraint on columns "key", "org_id" """ - organization_pkey + org_settings_pkey } """ -input type for inserting data into table "organizations" +delete the field or element with specified path (for JSON arrays, negative integers count from the end) """ -input organizations_insert_input { - allowedEmailDomains: [String!] - allowedEmails: [String!] - description: String - organization: String +input org_settings_delete_at_path_input { + value: [String!] } """ -order by max() on columns of table "organizations" +delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array """ -input organizations_max_order_by { - allowedEmailDomains: order_by - allowedEmails: order_by - description: order_by - organization: order_by +input org_settings_delete_elem_input { + value: Int } """ -order by min() on columns of table "organizations" +delete key/value pair or string element. key/value pairs are matched based on their key value """ -input organizations_min_order_by { - allowedEmailDomains: order_by - allowedEmails: order_by - description: order_by - organization: order_by +input org_settings_delete_key_input { + value: String } """ -response of any mutation on the table "organizations" +input type for inserting data into table "org_settings" """ -type organizations_mutation_response { +input org_settings_insert_input { + key: String + value: jsonb +} + +"""aggregate max on columns""" +type org_settings_max_fields { + created_at: timestamptz + created_by: uuid + key: String + org_id: uuid + updated_at: timestamptz + updated_by: uuid +} + +""" +order by max() on columns of table "org_settings" +""" +input org_settings_max_order_by { + created_at: order_by + created_by: order_by + key: order_by + org_id: order_by + updated_at: order_by + updated_by: order_by +} + +"""aggregate min on columns""" +type org_settings_min_fields { + created_at: timestamptz + created_by: uuid + key: String + org_id: uuid + updated_at: timestamptz + updated_by: uuid +} + +""" +order by min() on columns of table "org_settings" +""" +input org_settings_min_order_by { + created_at: order_by + created_by: order_by + key: order_by + org_id: order_by + updated_at: order_by + updated_by: order_by +} + +""" +response of any mutation on the table "org_settings" +""" +type org_settings_mutation_response { """number of rows affected by the mutation""" affected_rows: Int! """data from the rows affected by the mutation""" - returning: [organizations!]! + returning: [org_settings!]! } """ -on_conflict condition type for table "organizations" +on_conflict condition type for table "org_settings" """ -input organizations_on_conflict { - constraint: organizations_constraint! - update_columns: [organizations_update_column!]! = [] - where: organizations_bool_exp +input org_settings_on_conflict { + constraint: org_settings_constraint! + update_columns: [org_settings_update_column!]! = [] + where: org_settings_bool_exp } -"""Ordering options when selecting data from "organizations".""" -input organizations_order_by { - allowedEmailDomains: order_by - allowedEmails: order_by - description: order_by - organization: order_by +"""Ordering options when selecting data from "org_settings".""" +input org_settings_order_by { + created_at: order_by + created_by: order_by + key: order_by + org_id: order_by + updated_at: order_by + updated_by: order_by + value: order_by } -"""primary key columns input for table: organizations""" -input organizations_pk_columns_input { - organization: String! +"""primary key columns input for table: org_settings""" +input org_settings_pk_columns_input { + key: String! + org_id: uuid! +} + +"""prepend existing jsonb value of filtered columns with new jsonb value""" +input org_settings_prepend_input { + value: jsonb } """ -select columns of table "organizations" +select columns of table "org_settings" """ -enum organizations_select_column { +enum org_settings_select_column { """column name""" - allowedEmailDomains + created_at """column name""" - allowedEmails + created_by """column name""" - description + key + + """column name""" + org_id + + """column name""" + updated_at + + """column name""" + updated_by """column name""" - organization + value } """ -input type for updating data in table "organizations" +input type for updating data in table "org_settings" """ -input organizations_set_input { - allowedEmailDomains: [String!] - allowedEmails: [String!] - description: String - organization: String +input org_settings_set_input { + value: jsonb } """ -Streaming cursor of the table "organizations" +Streaming cursor of the table "org_settings" """ -input organizations_stream_cursor_input { +input org_settings_stream_cursor_input { """Stream column input with initial value""" - initial_value: organizations_stream_cursor_value_input! + initial_value: org_settings_stream_cursor_value_input! """cursor ordering""" ordering: cursor_ordering } """Initial value of the column from where the streaming should start""" -input organizations_stream_cursor_value_input { - allowedEmailDomains: [String!] - allowedEmails: [String!] - description: String - organization: String +input org_settings_stream_cursor_value_input { + created_at: timestamptz + created_by: uuid + key: String + org_id: uuid + updated_at: timestamptz + updated_by: uuid + value: jsonb } """ -update columns of table "organizations" +update columns of table "org_settings" """ -enum organizations_update_column { - """column name""" - allowedEmailDomains - - """column name""" - allowedEmails - +enum org_settings_update_column { """column name""" - description - - """column name""" - organization -} - -input organizations_updates { - """sets the columns of the filtered rows to the given values""" - _set: organizations_set_input - - """filter the rows which have to be updated""" - where: organizations_bool_exp! + value } -"""Joint table associating subjects polymorphically with rules""" -type policies { - active: Boolean! - createdAt: timestamptz! - createdBy: String! - id: uuid! - organization: String! - - """An object relationship""" - rule: rules! - ruleId: uuid! - subjectDisplayName: String! - subjectId: uuid! - subjectSecondaryId: String! - subjectType: subject_type_enum! - updatedAt: timestamptz! - updatedBy: String! - validFrom: timestamptz! - validTo: timestamptz - weight: smallint! -} +input org_settings_updates { + """append existing jsonb value of filtered columns with new jsonb value""" + _append: org_settings_append_input -""" -Boolean expression to filter rows from the table "policies". All fields are combined with a logical 'AND'. -""" -input policies_bool_exp { - _and: [policies_bool_exp!] - _not: policies_bool_exp - _or: [policies_bool_exp!] - active: Boolean_comparison_exp - createdAt: timestamptz_comparison_exp - createdBy: String_comparison_exp - id: uuid_comparison_exp - organization: String_comparison_exp - rule: rules_bool_exp - ruleId: uuid_comparison_exp - subjectDisplayName: String_comparison_exp - subjectId: uuid_comparison_exp - subjectSecondaryId: String_comparison_exp - subjectType: subject_type_enum_comparison_exp - updatedAt: timestamptz_comparison_exp - updatedBy: String_comparison_exp - validFrom: timestamptz_comparison_exp - validTo: timestamptz_comparison_exp - weight: smallint_comparison_exp -} + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: org_settings_delete_at_path_input -""" -unique or primary key constraints on table "policies" -""" -enum policies_constraint { """ - unique or primary key constraint on columns "id" + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array """ - policies_pkey + _delete_elem: org_settings_delete_elem_input """ - unique or primary key constraint on columns "subject_id", "organization", "rule_id", "subject_type" + delete key/value pair or string element. key/value pairs are matched based on their key value """ - policies_subject_id_subject_type_rule_id_organization_unique -} + _delete_key: org_settings_delete_key_input -""" -input type for incrementing numeric columns in table "policies" -""" -input policies_inc_input { - weight: smallint -} + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: org_settings_prepend_input -""" -input type for inserting data into table "policies" -""" -input policies_insert_input { - active: Boolean - organization: String - rule: rules_obj_rel_insert_input - ruleId: uuid - subjectDisplayName: String - subjectId: uuid - subjectSecondaryId: String - subjectType: subject_type_enum - validFrom: timestamptz - validTo: timestamptz - weight: smallint -} + """sets the columns of the filtered rows to the given values""" + _set: org_settings_set_input -""" -response of any mutation on the table "policies" -""" -type policies_mutation_response { - """number of rows affected by the mutation""" - affected_rows: Int! + """filter the rows which have to be updated""" + where: org_settings_bool_exp! +} - """data from the rows affected by the mutation""" - returning: [policies!]! +input org_settings_with_defaults_args { + org_row: organizations_scalar } """ -on_conflict condition type for table "policies" +Table containing organizations owned by users. Auto-enroll members based on email domain """ -input policies_on_conflict { - constraint: policies_constraint! - update_columns: [policies_update_column!]! = [] - where: policies_bool_exp -} +type organizations { + allowedEmailDomains: [String!] + allowedEmails: [String!] + autoEnroll: Boolean + avatarUrl: String + blockedEmailDomains: [String!] + blockedEmails: [String!] + createdAt: timestamptz + createdBy: uuid + description: String -"""Ordering options when selecting data from "policies".""" -input policies_order_by { - active: order_by - createdAt: order_by - createdBy: order_by - id: order_by - organization: order_by - rule: rules_order_by - ruleId: order_by - subjectDisplayName: order_by - subjectId: order_by - subjectSecondaryId: order_by - subjectType: order_by - updatedAt: order_by - updatedBy: order_by - validFrom: order_by - validTo: order_by - weight: order_by -} + """An array relationship""" + devices( + """distinct select on columns""" + distinct_on: [devices_select_column!] -"""primary key columns input for table: policies""" -input policies_pk_columns_input { - id: uuid! -} + """limit the number of rows returned""" + limit: Int -""" -select columns of table "policies" -""" -enum policies_select_column { - """column name""" - active + """skip the first n rows. Use only with order_by""" + offset: Int - """column name""" - createdAt + """sort the rows by one or more columns""" + order_by: [devices_order_by!] - """column name""" - createdBy + """filter the rows returned""" + where: devices_bool_exp + ): [devices!]! - """column name""" - id + """An aggregate relationship""" + devices_aggregate( + """distinct select on columns""" + distinct_on: [devices_select_column!] - """column name""" - organization + """limit the number of rows returned""" + limit: Int - """column name""" - ruleId + """skip the first n rows. Use only with order_by""" + offset: Int - """column name""" - subjectDisplayName + """sort the rows by one or more columns""" + order_by: [devices_order_by!] - """column name""" - subjectId + """filter the rows returned""" + where: devices_bool_exp + ): devices_aggregate! + displayName: String! - """column name""" - subjectSecondaryId + """An array relationship""" + groups( + """distinct select on columns""" + distinct_on: [groups_select_column!] - """column name""" - subjectType + """limit the number of rows returned""" + limit: Int - """column name""" - updatedAt + """skip the first n rows. Use only with order_by""" + offset: Int - """column name""" - updatedBy + """sort the rows by one or more columns""" + order_by: [groups_order_by!] - """column name""" - validFrom + """filter the rows returned""" + where: groups_bool_exp + ): [groups!]! - """column name""" - validTo + """An aggregate relationship""" + groups_aggregate( + """distinct select on columns""" + distinct_on: [groups_select_column!] - """column name""" - weight -} + """limit the number of rows returned""" + limit: Int -""" -input type for updating data in table "policies" -""" -input policies_set_input { - active: Boolean - deletedAt: timestamptz - validFrom: timestamptz - validTo: timestamptz - weight: smallint -} + """skip the first n rows. Use only with order_by""" + offset: Int -""" -Streaming cursor of the table "policies" -""" -input policies_stream_cursor_input { - """Stream column input with initial value""" - initial_value: policies_stream_cursor_value_input! + """sort the rows by one or more columns""" + order_by: [groups_order_by!] - """cursor ordering""" - ordering: cursor_ordering -} + """filter the rows returned""" + where: groups_bool_exp + ): groups_aggregate! + id: uuid! -"""Initial value of the column from where the streaming should start""" -input policies_stream_cursor_value_input { - active: Boolean - createdAt: timestamptz - createdBy: String - id: uuid - organization: String - ruleId: uuid - subjectDisplayName: String - subjectId: uuid - subjectSecondaryId: String - subjectType: subject_type_enum - updatedAt: timestamptz - updatedBy: String - validFrom: timestamptz - validTo: timestamptz - weight: smallint -} + """An array relationship""" + memberships( + """distinct select on columns""" + distinct_on: [memberships_select_column!] -""" -update columns of table "policies" -""" -enum policies_update_column { - """column name""" - active + """limit the number of rows returned""" + limit: Int - """column name""" - deletedAt + """skip the first n rows. Use only with order_by""" + offset: Int - """column name""" - validFrom + """sort the rows by one or more columns""" + order_by: [memberships_order_by!] - """column name""" - validTo + """filter the rows returned""" + where: memberships_bool_exp + ): [memberships!]! - """column name""" - weight -} + """An aggregate relationship""" + memberships_aggregate( + """distinct select on columns""" + distinct_on: [memberships_select_column!] -input policies_updates { - """increments the numeric columns with given value of the filtered values""" - _inc: policies_inc_input + """limit the number of rows returned""" + limit: Int - """sets the columns of the filtered rows to the given values""" - _set: policies_set_input + """skip the first n rows. Use only with order_by""" + offset: Int - """filter the rows which have to be updated""" - where: policies_bool_exp! -} + """sort the rows by one or more columns""" + order_by: [memberships_order_by!] -"""Device pools""" -type pools { - annotations: hstore - createdAt: timestamptz! - createdBy: String! - description: String + """filter the rows returned""" + where: memberships_bool_exp + ): memberships_aggregate! + metadata( + """JSON select path""" + path: String + ): jsonb + + """An object relationship""" + owner: users! + ownerId: uuid! """An array relationship""" - devices( + policies( """distinct select on columns""" - distinct_on: [device_pools_select_column!] + distinct_on: [policies_select_column!] """limit the number of rows returned""" limit: Int @@ -3010,16 +3911,16 @@ type pools { offset: Int """sort the rows by one or more columns""" - order_by: [device_pools_order_by!] + order_by: [policies_order_by!] """filter the rows returned""" - where: device_pools_bool_exp - ): [device_pools!]! + where: policies_bool_exp + ): [policies!]! """An aggregate relationship""" - devices_aggregate( + policies_aggregate( """distinct select on columns""" - distinct_on: [device_pools_select_column!] + distinct_on: [policies_select_column!] """limit the number of rows returned""" limit: Int @@ -3028,205 +3929,425 @@ type pools { offset: Int """sort the rows by one or more columns""" - order_by: [device_pools_order_by!] + order_by: [policies_order_by!] """filter the rows returned""" - where: device_pools_bool_exp - ): device_pools_aggregate! - displayName: String! - id: uuid! - organization: String! - tags: [String!] - updatedAt: timestamptz! - updatedBy: String! -} + where: policies_bool_exp + ): policies_aggregate! -""" -aggregated selection of "pools" -""" -type pools_aggregate { - aggregate: pools_aggregate_fields - nodes: [pools!]! -} + """An array relationship""" + pools( + """distinct select on columns""" + distinct_on: [pools_select_column!] -""" -aggregate fields of "pools" -""" -type pools_aggregate_fields { - count(columns: [pools_select_column!], distinct: Boolean): Int! - max: pools_max_fields - min: pools_min_fields -} + """limit the number of rows returned""" + limit: Int -""" -order by aggregate values of table "pools" -""" -input pools_aggregate_order_by { - count: order_by - max: pools_max_order_by - min: pools_min_order_by -} + """skip the first n rows. Use only with order_by""" + offset: Int -""" -Boolean expression to filter rows from the table "pools". All fields are combined with a logical 'AND'. -""" -input pools_bool_exp { - _and: [pools_bool_exp!] - _not: pools_bool_exp - _or: [pools_bool_exp!] - annotations: hstore_comparison_exp + """sort the rows by one or more columns""" + order_by: [pools_order_by!] + + """filter the rows returned""" + where: pools_bool_exp + ): [pools!]! + + """An aggregate relationship""" + pools_aggregate( + """distinct select on columns""" + distinct_on: [pools_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [pools_order_by!] + + """filter the rows returned""" + where: pools_bool_exp + ): pools_aggregate! + + """An array relationship""" + rules( + """distinct select on columns""" + distinct_on: [rules_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [rules_order_by!] + + """filter the rows returned""" + where: rules_bool_exp + ): [rules!]! + + """An aggregate relationship""" + rules_aggregate( + """distinct select on columns""" + distinct_on: [rules_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [rules_order_by!] + + """filter the rows returned""" + where: rules_bool_exp + ): rules_aggregate! + + """An array relationship""" + settings( + """distinct select on columns""" + distinct_on: [org_settings_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [org_settings_order_by!] + + """filter the rows returned""" + where: org_settings_bool_exp + ): [org_settings!]! + + """Used as Computed Field on Organizations Table""" + settingsWithDefaults( + """distinct select on columns""" + distinct_on: [org_settings_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [org_settings_order_by!] + + """filter the rows returned""" + where: org_settings_bool_exp + ): [org_settings!] + + """An aggregate relationship""" + settings_aggregate( + """distinct select on columns""" + distinct_on: [org_settings_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [org_settings_order_by!] + + """filter the rows returned""" + where: org_settings_bool_exp + ): org_settings_aggregate! + + """An array relationship""" + subscriptions( + """distinct select on columns""" + distinct_on: [subscriptions_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [subscriptions_order_by!] + + """filter the rows returned""" + where: subscriptions_bool_exp + ): [subscriptions!]! + + """An aggregate relationship""" + subscriptions_aggregate( + """distinct select on columns""" + distinct_on: [subscriptions_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [subscriptions_order_by!] + + """filter the rows returned""" + where: subscriptions_bool_exp + ): subscriptions_aggregate! + tags: [String!] + updatedAt: timestamptz + updatedBy: uuid +} + +""" +aggregated selection of "organizations" +""" +type organizations_aggregate { + aggregate: organizations_aggregate_fields + nodes: [organizations!]! +} + +""" +aggregate fields of "organizations" +""" +type organizations_aggregate_fields { + count(columns: [organizations_select_column!], distinct: Boolean): Int! + max: organizations_max_fields + min: organizations_min_fields +} + +"""append existing jsonb value of filtered columns with new jsonb value""" +input organizations_append_input { + metadata: jsonb +} + +""" +Boolean expression to filter rows from the table "organizations". All fields are combined with a logical 'AND'. +""" +input organizations_bool_exp { + _and: [organizations_bool_exp!] + _not: organizations_bool_exp + _or: [organizations_bool_exp!] + allowedEmailDomains: String_array_comparison_exp + allowedEmails: String_array_comparison_exp + autoEnroll: Boolean_comparison_exp + avatarUrl: String_comparison_exp + blockedEmailDomains: String_array_comparison_exp + blockedEmails: String_array_comparison_exp createdAt: timestamptz_comparison_exp - createdBy: String_comparison_exp + createdBy: uuid_comparison_exp description: String_comparison_exp - devices: device_pools_bool_exp - devices_aggregate: device_pools_aggregate_bool_exp + devices: devices_bool_exp + devices_aggregate: devices_aggregate_bool_exp displayName: String_comparison_exp + groups: groups_bool_exp + groups_aggregate: groups_aggregate_bool_exp id: uuid_comparison_exp - organization: String_comparison_exp + memberships: memberships_bool_exp + memberships_aggregate: memberships_aggregate_bool_exp + metadata: jsonb_comparison_exp + owner: users_bool_exp + ownerId: uuid_comparison_exp + policies: policies_bool_exp + policies_aggregate: policies_aggregate_bool_exp + pools: pools_bool_exp + pools_aggregate: pools_aggregate_bool_exp + rules: rules_bool_exp + rules_aggregate: rules_aggregate_bool_exp + settings: org_settings_bool_exp + settingsWithDefaults: org_settings_bool_exp + settings_aggregate: org_settings_aggregate_bool_exp + subscriptions: subscriptions_bool_exp + subscriptions_aggregate: subscriptions_aggregate_bool_exp tags: String_array_comparison_exp updatedAt: timestamptz_comparison_exp - updatedBy: String_comparison_exp + updatedBy: uuid_comparison_exp } """ -unique or primary key constraints on table "pools" +unique or primary key constraints on table "organizations" """ -enum pools_constraint { - """ - unique or primary key constraint on columns "display_name", "organization" - """ - pools_display_name_organization_unique - +enum organizations_constraint { """ unique or primary key constraint on columns "id" """ - pools_pkey + organizations_pkey } """ -input type for inserting data into table "pools" +delete the field or element with specified path (for JSON arrays, negative integers count from the end) """ -input pools_insert_input { - annotations: hstore +input organizations_delete_at_path_input { + metadata: [String!] +} + +""" +delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array +""" +input organizations_delete_elem_input { + metadata: Int +} + +""" +delete key/value pair or string element. key/value pairs are matched based on their key value +""" +input organizations_delete_key_input { + metadata: String +} + +""" +input type for inserting data into table "organizations" +""" +input organizations_insert_input { + allowedEmailDomains: [String!] + allowedEmails: [String!] + autoEnroll: Boolean + avatarUrl: String + blockedEmailDomains: [String!] + blockedEmails: [String!] description: String - devices: device_pools_arr_rel_insert_input displayName: String - organization: String + groups: groups_arr_rel_insert_input + memberships: memberships_arr_rel_insert_input + metadata: jsonb + policies: policies_arr_rel_insert_input + pools: pools_arr_rel_insert_input + rules: rules_arr_rel_insert_input + settings: org_settings_arr_rel_insert_input tags: [String!] } """aggregate max on columns""" -type pools_max_fields { +type organizations_max_fields { + allowedEmailDomains: [String!] + allowedEmails: [String!] + avatarUrl: String + blockedEmailDomains: [String!] + blockedEmails: [String!] createdAt: timestamptz - createdBy: String + createdBy: uuid description: String displayName: String id: uuid - organization: String + ownerId: uuid tags: [String!] updatedAt: timestamptz - updatedBy: String -} - -""" -order by max() on columns of table "pools" -""" -input pools_max_order_by { - createdAt: order_by - createdBy: order_by - description: order_by - displayName: order_by - id: order_by - organization: order_by - tags: order_by - updatedAt: order_by - updatedBy: order_by + updatedBy: uuid } """aggregate min on columns""" -type pools_min_fields { +type organizations_min_fields { + allowedEmailDomains: [String!] + allowedEmails: [String!] + avatarUrl: String + blockedEmailDomains: [String!] + blockedEmails: [String!] createdAt: timestamptz - createdBy: String + createdBy: uuid description: String displayName: String id: uuid - organization: String + ownerId: uuid tags: [String!] updatedAt: timestamptz - updatedBy: String -} - -""" -order by min() on columns of table "pools" -""" -input pools_min_order_by { - createdAt: order_by - createdBy: order_by - description: order_by - displayName: order_by - id: order_by - organization: order_by - tags: order_by - updatedAt: order_by - updatedBy: order_by + updatedBy: uuid } """ -response of any mutation on the table "pools" +response of any mutation on the table "organizations" """ -type pools_mutation_response { +type organizations_mutation_response { """number of rows affected by the mutation""" affected_rows: Int! """data from the rows affected by the mutation""" - returning: [pools!]! + returning: [organizations!]! } """ -input type for inserting object relation for remote table "pools" +input type for inserting object relation for remote table "organizations" """ -input pools_obj_rel_insert_input { - data: pools_insert_input! +input organizations_obj_rel_insert_input { + data: organizations_insert_input! """upsert condition""" - on_conflict: pools_on_conflict + on_conflict: organizations_on_conflict } """ -on_conflict condition type for table "pools" +on_conflict condition type for table "organizations" """ -input pools_on_conflict { - constraint: pools_constraint! - update_columns: [pools_update_column!]! = [] - where: pools_bool_exp +input organizations_on_conflict { + constraint: organizations_constraint! + update_columns: [organizations_update_column!]! = [] + where: organizations_bool_exp } -"""Ordering options when selecting data from "pools".""" -input pools_order_by { - annotations: order_by +"""Ordering options when selecting data from "organizations".""" +input organizations_order_by { + allowedEmailDomains: order_by + allowedEmails: order_by + autoEnroll: order_by + avatarUrl: order_by + blockedEmailDomains: order_by + blockedEmails: order_by createdAt: order_by createdBy: order_by description: order_by - devices_aggregate: device_pools_aggregate_order_by + devices_aggregate: devices_aggregate_order_by displayName: order_by + groups_aggregate: groups_aggregate_order_by id: order_by - organization: order_by + memberships_aggregate: memberships_aggregate_order_by + metadata: order_by + owner: users_order_by + ownerId: order_by + policies_aggregate: policies_aggregate_order_by + pools_aggregate: pools_aggregate_order_by + rules_aggregate: rules_aggregate_order_by + settingsWithDefaults_aggregate: org_settings_aggregate_order_by + settings_aggregate: org_settings_aggregate_order_by + subscriptions_aggregate: subscriptions_aggregate_order_by tags: order_by updatedAt: order_by updatedBy: order_by } -"""primary key columns input for table: pools""" -input pools_pk_columns_input { - id: uuid! +"""primary key columns input for table: organizations""" +input organizations_pk_columns_input { + id: uuid! +} + +"""prepend existing jsonb value of filtered columns with new jsonb value""" +input organizations_prepend_input { + metadata: jsonb } +scalar organizations_scalar + """ -select columns of table "pools" +select columns of table "organizations" """ -enum pools_select_column { +enum organizations_select_column { + """column name""" + allowedEmailDomains + + """column name""" + allowedEmails + + """column name""" + autoEnroll + + """column name""" + avatarUrl + + """column name""" + blockedEmailDomains + """column name""" - annotations + blockedEmails """column name""" createdAt @@ -3244,7 +4365,10 @@ enum pools_select_column { id """column name""" - organization + metadata + + """column name""" + ownerId """column name""" tags @@ -3257,50 +4381,74 @@ enum pools_select_column { } """ -input type for updating data in table "pools" +input type for updating data in table "organizations" """ -input pools_set_input { - annotations: hstore - deletedAt: timestamptz +input organizations_set_input { + allowedEmailDomains: [String!] + allowedEmails: [String!] + autoEnroll: Boolean + avatarUrl: String + blockedEmailDomains: [String!] + blockedEmails: [String!] description: String displayName: String + metadata: jsonb + ownerId: uuid tags: [String!] } """ -Streaming cursor of the table "pools" +Streaming cursor of the table "organizations" """ -input pools_stream_cursor_input { +input organizations_stream_cursor_input { """Stream column input with initial value""" - initial_value: pools_stream_cursor_value_input! + initial_value: organizations_stream_cursor_value_input! """cursor ordering""" ordering: cursor_ordering } """Initial value of the column from where the streaming should start""" -input pools_stream_cursor_value_input { - annotations: hstore +input organizations_stream_cursor_value_input { + allowedEmailDomains: [String!] + allowedEmails: [String!] + autoEnroll: Boolean + avatarUrl: String + blockedEmailDomains: [String!] + blockedEmails: [String!] createdAt: timestamptz - createdBy: String + createdBy: uuid description: String displayName: String id: uuid - organization: String + metadata: jsonb + ownerId: uuid tags: [String!] updatedAt: timestamptz - updatedBy: String + updatedBy: uuid } """ -update columns of table "pools" +update columns of table "organizations" """ -enum pools_update_column { +enum organizations_update_column { + """column name""" + allowedEmailDomains + + """column name""" + allowedEmails + + """column name""" + autoEnroll + + """column name""" + avatarUrl + """column name""" - annotations + blockedEmailDomains """column name""" - deletedAt + blockedEmails """column name""" description @@ -3308,151 +4456,1684 @@ enum pools_update_column { """column name""" displayName + """column name""" + metadata + + """column name""" + ownerId + """column name""" tags } -input pools_updates { +input organizations_updates { + """append existing jsonb value of filtered columns with new jsonb value""" + _append: organizations_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: organizations_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: organizations_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: organizations_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: organizations_prepend_input + """sets the columns of the filtered rows to the given values""" - _set: pools_set_input + _set: organizations_set_input """filter the rows which have to be updated""" - where: pools_bool_exp! + where: organizations_bool_exp! } -"""network protocol enum""" -type protocol { +"""plan enum""" +type plan { description: String! value: String! } -""" -aggregated selection of "protocol" -""" -type protocol_aggregate { - aggregate: protocol_aggregate_fields - nodes: [protocol!]! -} +""" +Boolean expression to filter rows from the table "plan". All fields are combined with a logical 'AND'. +""" +input plan_bool_exp { + _and: [plan_bool_exp!] + _not: plan_bool_exp + _or: [plan_bool_exp!] + description: String_comparison_exp + value: String_comparison_exp +} + +enum plan_enum { + """Enterprise""" + enterprise + + """Pro""" + pro + + """Starter""" + starter +} + +""" +Boolean expression to compare columns of type "plan_enum". All fields are combined with logical 'AND'. +""" +input plan_enum_comparison_exp { + _eq: plan_enum + _in: [plan_enum!] + _is_null: Boolean + _neq: plan_enum + _nin: [plan_enum!] +} + +"""Ordering options when selecting data from "plan".""" +input plan_order_by { + description: order_by + value: order_by +} + +""" +select columns of table "plan" +""" +enum plan_select_column { + """column name""" + description + + """column name""" + value +} + +""" +Streaming cursor of the table "plan" +""" +input plan_stream_cursor_input { + """Stream column input with initial value""" + initial_value: plan_stream_cursor_value_input! + + """cursor ordering""" + ordering: cursor_ordering +} + +"""Initial value of the column from where the streaming should start""" +input plan_stream_cursor_value_input { + description: String + value: String +} + +"""Joint table associating subjects polymorphically with rules""" +type policies { + active: Boolean! + createdAt: timestamptz! + createdBy: uuid! + id: uuid! + orgId: uuid! + + """An object relationship""" + organization: organizations! + + """An object relationship""" + rule: rules! + ruleId: uuid! + subjectDisplayName: String! + subjectId: uuid! + subjectSecondaryId: String! + subjectType: subject_type_enum! + updatedAt: timestamptz! + updatedBy: uuid! + validFrom: timestamptz! + validTo: timestamptz + weight: smallint! +} + +""" +aggregated selection of "policies" +""" +type policies_aggregate { + aggregate: policies_aggregate_fields + nodes: [policies!]! +} + +input policies_aggregate_bool_exp { + bool_and: policies_aggregate_bool_exp_bool_and + bool_or: policies_aggregate_bool_exp_bool_or + count: policies_aggregate_bool_exp_count +} + +input policies_aggregate_bool_exp_bool_and { + arguments: policies_select_column_policies_aggregate_bool_exp_bool_and_arguments_columns! + distinct: Boolean + filter: policies_bool_exp + predicate: Boolean_comparison_exp! +} + +input policies_aggregate_bool_exp_bool_or { + arguments: policies_select_column_policies_aggregate_bool_exp_bool_or_arguments_columns! + distinct: Boolean + filter: policies_bool_exp + predicate: Boolean_comparison_exp! +} + +input policies_aggregate_bool_exp_count { + arguments: [policies_select_column!] + distinct: Boolean + filter: policies_bool_exp + predicate: Int_comparison_exp! +} + +""" +aggregate fields of "policies" +""" +type policies_aggregate_fields { + avg: policies_avg_fields + count(columns: [policies_select_column!], distinct: Boolean): Int! + max: policies_max_fields + min: policies_min_fields + stddev: policies_stddev_fields + stddev_pop: policies_stddev_pop_fields + stddev_samp: policies_stddev_samp_fields + sum: policies_sum_fields + var_pop: policies_var_pop_fields + var_samp: policies_var_samp_fields + variance: policies_variance_fields +} + +""" +order by aggregate values of table "policies" +""" +input policies_aggregate_order_by { + avg: policies_avg_order_by + count: order_by + max: policies_max_order_by + min: policies_min_order_by + stddev: policies_stddev_order_by + stddev_pop: policies_stddev_pop_order_by + stddev_samp: policies_stddev_samp_order_by + sum: policies_sum_order_by + var_pop: policies_var_pop_order_by + var_samp: policies_var_samp_order_by + variance: policies_variance_order_by +} + +""" +input type for inserting array relation for remote table "policies" +""" +input policies_arr_rel_insert_input { + data: [policies_insert_input!]! + + """upsert condition""" + on_conflict: policies_on_conflict +} + +"""aggregate avg on columns""" +type policies_avg_fields { + weight: Float +} + +""" +order by avg() on columns of table "policies" +""" +input policies_avg_order_by { + weight: order_by +} + +""" +Boolean expression to filter rows from the table "policies". All fields are combined with a logical 'AND'. +""" +input policies_bool_exp { + _and: [policies_bool_exp!] + _not: policies_bool_exp + _or: [policies_bool_exp!] + active: Boolean_comparison_exp + createdAt: timestamptz_comparison_exp + createdBy: uuid_comparison_exp + id: uuid_comparison_exp + orgId: uuid_comparison_exp + organization: organizations_bool_exp + rule: rules_bool_exp + ruleId: uuid_comparison_exp + subjectDisplayName: String_comparison_exp + subjectId: uuid_comparison_exp + subjectSecondaryId: String_comparison_exp + subjectType: subject_type_enum_comparison_exp + updatedAt: timestamptz_comparison_exp + updatedBy: uuid_comparison_exp + validFrom: timestamptz_comparison_exp + validTo: timestamptz_comparison_exp + weight: smallint_comparison_exp +} + +""" +unique or primary key constraints on table "policies" +""" +enum policies_constraint { + """ + unique or primary key constraint on columns "subject_id", "rule_id", "subject_type", "org_id" + """ + policies_org_id_rule_id_subject_id_subject_type_key + + """ + unique or primary key constraint on columns "id" + """ + policies_pkey +} + +""" +input type for incrementing numeric columns in table "policies" +""" +input policies_inc_input { + weight: smallint +} + +""" +input type for inserting data into table "policies" +""" +input policies_insert_input { + active: Boolean + organization: organizations_obj_rel_insert_input + rule: rules_obj_rel_insert_input + ruleId: uuid + subjectDisplayName: String + subjectId: uuid + subjectSecondaryId: String + subjectType: subject_type_enum + validFrom: timestamptz + validTo: timestamptz + weight: smallint +} + +"""aggregate max on columns""" +type policies_max_fields { + createdAt: timestamptz + createdBy: uuid + id: uuid + orgId: uuid + ruleId: uuid + subjectDisplayName: String + subjectId: uuid + subjectSecondaryId: String + updatedAt: timestamptz + updatedBy: uuid + validFrom: timestamptz + validTo: timestamptz + weight: smallint +} + +""" +order by max() on columns of table "policies" +""" +input policies_max_order_by { + createdAt: order_by + createdBy: order_by + id: order_by + orgId: order_by + ruleId: order_by + subjectDisplayName: order_by + subjectId: order_by + subjectSecondaryId: order_by + updatedAt: order_by + updatedBy: order_by + validFrom: order_by + validTo: order_by + weight: order_by +} + +"""aggregate min on columns""" +type policies_min_fields { + createdAt: timestamptz + createdBy: uuid + id: uuid + orgId: uuid + ruleId: uuid + subjectDisplayName: String + subjectId: uuid + subjectSecondaryId: String + updatedAt: timestamptz + updatedBy: uuid + validFrom: timestamptz + validTo: timestamptz + weight: smallint +} + +""" +order by min() on columns of table "policies" +""" +input policies_min_order_by { + createdAt: order_by + createdBy: order_by + id: order_by + orgId: order_by + ruleId: order_by + subjectDisplayName: order_by + subjectId: order_by + subjectSecondaryId: order_by + updatedAt: order_by + updatedBy: order_by + validFrom: order_by + validTo: order_by + weight: order_by +} + +""" +response of any mutation on the table "policies" +""" +type policies_mutation_response { + """number of rows affected by the mutation""" + affected_rows: Int! + + """data from the rows affected by the mutation""" + returning: [policies!]! +} + +""" +on_conflict condition type for table "policies" +""" +input policies_on_conflict { + constraint: policies_constraint! + update_columns: [policies_update_column!]! = [] + where: policies_bool_exp +} + +"""Ordering options when selecting data from "policies".""" +input policies_order_by { + active: order_by + createdAt: order_by + createdBy: order_by + id: order_by + orgId: order_by + organization: organizations_order_by + rule: rules_order_by + ruleId: order_by + subjectDisplayName: order_by + subjectId: order_by + subjectSecondaryId: order_by + subjectType: order_by + updatedAt: order_by + updatedBy: order_by + validFrom: order_by + validTo: order_by + weight: order_by +} + +"""primary key columns input for table: policies""" +input policies_pk_columns_input { + id: uuid! +} + +""" +select columns of table "policies" +""" +enum policies_select_column { + """column name""" + active + + """column name""" + createdAt + + """column name""" + createdBy + + """column name""" + id + + """column name""" + orgId + + """column name""" + ruleId + + """column name""" + subjectDisplayName + + """column name""" + subjectId + + """column name""" + subjectSecondaryId + + """column name""" + subjectType + + """column name""" + updatedAt + + """column name""" + updatedBy + + """column name""" + validFrom + + """column name""" + validTo + + """column name""" + weight +} + +""" +select "policies_aggregate_bool_exp_bool_and_arguments_columns" columns of table "policies" +""" +enum policies_select_column_policies_aggregate_bool_exp_bool_and_arguments_columns { + """column name""" + active +} + +""" +select "policies_aggregate_bool_exp_bool_or_arguments_columns" columns of table "policies" +""" +enum policies_select_column_policies_aggregate_bool_exp_bool_or_arguments_columns { + """column name""" + active +} + +""" +input type for updating data in table "policies" +""" +input policies_set_input { + active: Boolean + validFrom: timestamptz + validTo: timestamptz + weight: smallint +} + +"""aggregate stddev on columns""" +type policies_stddev_fields { + weight: Float +} + +""" +order by stddev() on columns of table "policies" +""" +input policies_stddev_order_by { + weight: order_by +} + +"""aggregate stddev_pop on columns""" +type policies_stddev_pop_fields { + weight: Float +} + +""" +order by stddev_pop() on columns of table "policies" +""" +input policies_stddev_pop_order_by { + weight: order_by +} + +"""aggregate stddev_samp on columns""" +type policies_stddev_samp_fields { + weight: Float +} + +""" +order by stddev_samp() on columns of table "policies" +""" +input policies_stddev_samp_order_by { + weight: order_by +} + +""" +Streaming cursor of the table "policies" +""" +input policies_stream_cursor_input { + """Stream column input with initial value""" + initial_value: policies_stream_cursor_value_input! + + """cursor ordering""" + ordering: cursor_ordering +} + +"""Initial value of the column from where the streaming should start""" +input policies_stream_cursor_value_input { + active: Boolean + createdAt: timestamptz + createdBy: uuid + id: uuid + orgId: uuid + ruleId: uuid + subjectDisplayName: String + subjectId: uuid + subjectSecondaryId: String + subjectType: subject_type_enum + updatedAt: timestamptz + updatedBy: uuid + validFrom: timestamptz + validTo: timestamptz + weight: smallint +} + +"""aggregate sum on columns""" +type policies_sum_fields { + weight: smallint +} + +""" +order by sum() on columns of table "policies" +""" +input policies_sum_order_by { + weight: order_by +} + +""" +update columns of table "policies" +""" +enum policies_update_column { + """column name""" + active + + """column name""" + validFrom + + """column name""" + validTo + + """column name""" + weight +} + +input policies_updates { + """increments the numeric columns with given value of the filtered values""" + _inc: policies_inc_input + + """sets the columns of the filtered rows to the given values""" + _set: policies_set_input + + """filter the rows which have to be updated""" + where: policies_bool_exp! +} + +"""aggregate var_pop on columns""" +type policies_var_pop_fields { + weight: Float +} + +""" +order by var_pop() on columns of table "policies" +""" +input policies_var_pop_order_by { + weight: order_by +} + +"""aggregate var_samp on columns""" +type policies_var_samp_fields { + weight: Float +} + +""" +order by var_samp() on columns of table "policies" +""" +input policies_var_samp_order_by { + weight: order_by +} + +"""aggregate variance on columns""" +type policies_variance_fields { + weight: Float +} + +""" +order by variance() on columns of table "policies" +""" +input policies_variance_order_by { + weight: order_by +} + +"""Table containing device pools data""" +type pools { + alternateDns: Boolean + createdAt: timestamptz! + createdBy: uuid! + description: String + displayName: String! + id: uuid! + metadata( + """JSON select path""" + path: String + ): jsonb + orgId: uuid! + proxyIp: Boolean + tags: [String!] + updatedAt: timestamptz! + updatedBy: uuid! + version: String +} + +""" +aggregated selection of "pools" +""" +type pools_aggregate { + aggregate: pools_aggregate_fields + nodes: [pools!]! +} + +input pools_aggregate_bool_exp { + bool_and: pools_aggregate_bool_exp_bool_and + bool_or: pools_aggregate_bool_exp_bool_or + count: pools_aggregate_bool_exp_count +} + +input pools_aggregate_bool_exp_bool_and { + arguments: pools_select_column_pools_aggregate_bool_exp_bool_and_arguments_columns! + distinct: Boolean + filter: pools_bool_exp + predicate: Boolean_comparison_exp! +} + +input pools_aggregate_bool_exp_bool_or { + arguments: pools_select_column_pools_aggregate_bool_exp_bool_or_arguments_columns! + distinct: Boolean + filter: pools_bool_exp + predicate: Boolean_comparison_exp! +} + +input pools_aggregate_bool_exp_count { + arguments: [pools_select_column!] + distinct: Boolean + filter: pools_bool_exp + predicate: Int_comparison_exp! +} + +""" +aggregate fields of "pools" +""" +type pools_aggregate_fields { + count(columns: [pools_select_column!], distinct: Boolean): Int! + max: pools_max_fields + min: pools_min_fields +} + +""" +order by aggregate values of table "pools" +""" +input pools_aggregate_order_by { + count: order_by + max: pools_max_order_by + min: pools_min_order_by +} + +"""append existing jsonb value of filtered columns with new jsonb value""" +input pools_append_input { + metadata: jsonb +} + +""" +input type for inserting array relation for remote table "pools" +""" +input pools_arr_rel_insert_input { + data: [pools_insert_input!]! + + """upsert condition""" + on_conflict: pools_on_conflict +} + +""" +Boolean expression to filter rows from the table "pools". All fields are combined with a logical 'AND'. +""" +input pools_bool_exp { + _and: [pools_bool_exp!] + _not: pools_bool_exp + _or: [pools_bool_exp!] + alternateDns: Boolean_comparison_exp + createdAt: timestamptz_comparison_exp + createdBy: uuid_comparison_exp + description: String_comparison_exp + displayName: String_comparison_exp + id: uuid_comparison_exp + metadata: jsonb_comparison_exp + orgId: uuid_comparison_exp + proxyIp: Boolean_comparison_exp + tags: String_array_comparison_exp + updatedAt: timestamptz_comparison_exp + updatedBy: uuid_comparison_exp + version: String_comparison_exp +} + +""" +unique or primary key constraints on table "pools" +""" +enum pools_constraint { + """ + unique or primary key constraint on columns "display_name", "org_id" + """ + pools_org_id_display_name_key + + """ + unique or primary key constraint on columns "id" + """ + pools_pkey +} + +""" +delete the field or element with specified path (for JSON arrays, negative integers count from the end) +""" +input pools_delete_at_path_input { + metadata: [String!] +} + +""" +delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array +""" +input pools_delete_elem_input { + metadata: Int +} + +""" +delete key/value pair or string element. key/value pairs are matched based on their key value +""" +input pools_delete_key_input { + metadata: String +} + +""" +input type for inserting data into table "pools" +""" +input pools_insert_input { + alternateDns: Boolean + description: String + displayName: String + metadata: jsonb + proxyIp: Boolean + tags: [String!] + version: String +} + +"""aggregate max on columns""" +type pools_max_fields { + createdAt: timestamptz + createdBy: uuid + description: String + displayName: String + id: uuid + orgId: uuid + tags: [String!] + updatedAt: timestamptz + updatedBy: uuid + version: String +} + +""" +order by max() on columns of table "pools" +""" +input pools_max_order_by { + createdAt: order_by + createdBy: order_by + description: order_by + displayName: order_by + id: order_by + orgId: order_by + tags: order_by + updatedAt: order_by + updatedBy: order_by + version: order_by +} + +"""aggregate min on columns""" +type pools_min_fields { + createdAt: timestamptz + createdBy: uuid + description: String + displayName: String + id: uuid + orgId: uuid + tags: [String!] + updatedAt: timestamptz + updatedBy: uuid + version: String +} + +""" +order by min() on columns of table "pools" +""" +input pools_min_order_by { + createdAt: order_by + createdBy: order_by + description: order_by + displayName: order_by + id: order_by + orgId: order_by + tags: order_by + updatedAt: order_by + updatedBy: order_by + version: order_by +} + +""" +response of any mutation on the table "pools" +""" +type pools_mutation_response { + """number of rows affected by the mutation""" + affected_rows: Int! + + """data from the rows affected by the mutation""" + returning: [pools!]! +} + +""" +input type for inserting object relation for remote table "pools" +""" +input pools_obj_rel_insert_input { + data: pools_insert_input! + + """upsert condition""" + on_conflict: pools_on_conflict +} + +""" +on_conflict condition type for table "pools" +""" +input pools_on_conflict { + constraint: pools_constraint! + update_columns: [pools_update_column!]! = [] + where: pools_bool_exp +} + +"""Ordering options when selecting data from "pools".""" +input pools_order_by { + alternateDns: order_by + createdAt: order_by + createdBy: order_by + description: order_by + displayName: order_by + id: order_by + metadata: order_by + orgId: order_by + proxyIp: order_by + tags: order_by + updatedAt: order_by + updatedBy: order_by + version: order_by +} + +"""primary key columns input for table: pools""" +input pools_pk_columns_input { + id: uuid! +} + +"""prepend existing jsonb value of filtered columns with new jsonb value""" +input pools_prepend_input { + metadata: jsonb +} + +""" +select columns of table "pools" +""" +enum pools_select_column { + """column name""" + alternateDns + + """column name""" + createdAt + + """column name""" + createdBy + + """column name""" + description + + """column name""" + displayName + + """column name""" + id + + """column name""" + metadata + + """column name""" + orgId + + """column name""" + proxyIp + + """column name""" + tags + + """column name""" + updatedAt + + """column name""" + updatedBy + + """column name""" + version +} + +""" +select "pools_aggregate_bool_exp_bool_and_arguments_columns" columns of table "pools" +""" +enum pools_select_column_pools_aggregate_bool_exp_bool_and_arguments_columns { + """column name""" + alternateDns + + """column name""" + proxyIp +} + +""" +select "pools_aggregate_bool_exp_bool_or_arguments_columns" columns of table "pools" +""" +enum pools_select_column_pools_aggregate_bool_exp_bool_or_arguments_columns { + """column name""" + alternateDns + + """column name""" + proxyIp +} + +""" +input type for updating data in table "pools" +""" +input pools_set_input { + alternateDns: Boolean + description: String + displayName: String + metadata: jsonb + proxyIp: Boolean + tags: [String!] + version: String +} + +""" +Streaming cursor of the table "pools" +""" +input pools_stream_cursor_input { + """Stream column input with initial value""" + initial_value: pools_stream_cursor_value_input! + + """cursor ordering""" + ordering: cursor_ordering +} + +"""Initial value of the column from where the streaming should start""" +input pools_stream_cursor_value_input { + alternateDns: Boolean + createdAt: timestamptz + createdBy: uuid + description: String + displayName: String + id: uuid + metadata: jsonb + orgId: uuid + proxyIp: Boolean + tags: [String!] + updatedAt: timestamptz + updatedBy: uuid + version: String +} + +""" +update columns of table "pools" +""" +enum pools_update_column { + """column name""" + alternateDns + + """column name""" + description + + """column name""" + displayName + + """column name""" + metadata + + """column name""" + proxyIp + + """column name""" + tags + + """column name""" + version +} + +input pools_updates { + """append existing jsonb value of filtered columns with new jsonb value""" + _append: pools_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: pools_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: pools_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: pools_delete_key_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: pools_prepend_input + + """sets the columns of the filtered rows to the given values""" + _set: pools_set_input + + """filter the rows which have to be updated""" + where: pools_bool_exp! +} + +"""policy network protocol enum""" +type protocol { + description: String! + value: String! +} + +""" +Boolean expression to filter rows from the table "protocol". All fields are combined with a logical 'AND'. +""" +input protocol_bool_exp { + _and: [protocol_bool_exp!] + _not: protocol_bool_exp + _or: [protocol_bool_exp!] + description: String_comparison_exp + value: String_comparison_exp +} + +enum protocol_enum { + """Any""" + Any + + """ICMP""" + ICMP + + """ICMPV6""" + ICMPV6 + + """IGMP""" + IGMP + + """IP""" + IP + + """IPV6""" + IPV6 + + """RM""" + RM + + """TCP""" + TCP + + """UDP""" + UDP +} + +""" +Boolean expression to compare columns of type "protocol_enum". All fields are combined with logical 'AND'. +""" +input protocol_enum_comparison_exp { + _eq: protocol_enum + _in: [protocol_enum!] + _is_null: Boolean + _neq: protocol_enum + _nin: [protocol_enum!] +} + +"""Ordering options when selecting data from "protocol".""" +input protocol_order_by { + description: order_by + value: order_by +} + +""" +select columns of table "protocol" +""" +enum protocol_select_column { + """column name""" + description + + """column name""" + value +} + +""" +Streaming cursor of the table "protocol" +""" +input protocol_stream_cursor_input { + """Stream column input with initial value""" + initial_value: protocol_stream_cursor_value_input! + + """cursor ordering""" + ordering: cursor_ordering +} + +"""Initial value of the column from where the streaming should start""" +input protocol_stream_cursor_value_input { + description: String + value: String +} + +type query_root { + """Universities API""" + ListUniversities(arg1: ListUniversitiesInput!): [ListUniversitiesOutput] + + """Restrooms API""" + SearchRestrooms(arg1: SearchRestroomsInput!): [SearchRestroomsOutput] + + """ + fetch data from the table: "action" + """ + action( + """distinct select on columns""" + distinct_on: [action_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [action_order_by!] + + """filter the rows returned""" + where: action_bool_exp + ): [action!]! + + """fetch data from the table: "action" using primary key columns""" + action_by_pk(value: String!): action + + """ + fetch data from the table: "auth.refresh_tokens" using primary key columns + """ + authRefreshToken(id: uuid!): authRefreshTokens + + """ + fetch data from the table: "auth.refresh_tokens" + """ + authRefreshTokens( + """distinct select on columns""" + distinct_on: [authRefreshTokens_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authRefreshTokens_order_by!] + + """filter the rows returned""" + where: authRefreshTokens_bool_exp + ): [authRefreshTokens!]! + + """ + fetch aggregated fields from the table: "auth.refresh_tokens" + """ + authRefreshTokensAggregate( + """distinct select on columns""" + distinct_on: [authRefreshTokens_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authRefreshTokens_order_by!] + + """filter the rows returned""" + where: authRefreshTokens_bool_exp + ): authRefreshTokens_aggregate! + + """ + fetch data from the table: "auth.user_providers" using primary key columns + """ + authUserProvider(id: uuid!): authUserProviders + + """ + fetch data from the table: "auth.user_providers" + """ + authUserProviders( + """distinct select on columns""" + distinct_on: [authUserProviders_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authUserProviders_order_by!] + + """filter the rows returned""" + where: authUserProviders_bool_exp + ): [authUserProviders!]! + + """ + fetch aggregated fields from the table: "auth.user_providers" + """ + authUserProvidersAggregate( + """distinct select on columns""" + distinct_on: [authUserProviders_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authUserProviders_order_by!] + + """filter the rows returned""" + where: authUserProviders_bool_exp + ): authUserProviders_aggregate! + + """fetch data from the table: "auth.user_roles" using primary key columns""" + authUserRole(id: uuid!): authUserRoles + + """ + fetch data from the table: "auth.user_roles" + """ + authUserRoles( + """distinct select on columns""" + distinct_on: [authUserRoles_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authUserRoles_order_by!] + + """filter the rows returned""" + where: authUserRoles_bool_exp + ): [authUserRoles!]! + + """ + fetch aggregated fields from the table: "auth.user_roles" + """ + authUserRolesAggregate( + """distinct select on columns""" + distinct_on: [authUserRoles_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authUserRoles_order_by!] + + """filter the rows returned""" + where: authUserRoles_bool_exp + ): authUserRoles_aggregate! + + """ + fetch data from the table: "auth.user_security_keys" using primary key columns + """ + authUserSecurityKey(id: uuid!): authUserSecurityKeys + + """ + fetch data from the table: "auth.user_security_keys" + """ + authUserSecurityKeys( + """distinct select on columns""" + distinct_on: [authUserSecurityKeys_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authUserSecurityKeys_order_by!] + + """filter the rows returned""" + where: authUserSecurityKeys_bool_exp + ): [authUserSecurityKeys!]! + + """ + fetch aggregated fields from the table: "auth.user_security_keys" + """ + authUserSecurityKeysAggregate( + """distinct select on columns""" + distinct_on: [authUserSecurityKeys_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authUserSecurityKeys_order_by!] + + """filter the rows returned""" + where: authUserSecurityKeys_bool_exp + ): authUserSecurityKeys_aggregate! + + """ + execute function "device_associated_pools" which returns "pools" + """ + device_associated_pools( + """ + input parameters for function "device_associated_pools" + """ + args: device_associated_pools_args! + + """distinct select on columns""" + distinct_on: [pools_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [pools_order_by!] + + """filter the rows returned""" + where: pools_bool_exp + ): [pools!]! + + """ + execute function "device_associated_pools" and query aggregates on result of table type "pools" + """ + device_associated_pools_aggregate( + """ + input parameters for function "device_associated_pools_aggregate" + """ + args: device_associated_pools_args! + + """distinct select on columns""" + distinct_on: [pools_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [pools_order_by!] + + """filter the rows returned""" + where: pools_bool_exp + ): pools_aggregate! + + """ + execute function "device_dissociated_pools" which returns "pools" + """ + device_dissociated_pools( + """ + input parameters for function "device_dissociated_pools" + """ + args: device_dissociated_pools_args! + + """distinct select on columns""" + distinct_on: [pools_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [pools_order_by!] + + """filter the rows returned""" + where: pools_bool_exp + ): [pools!]! + + """ + execute function "device_dissociated_pools" and query aggregates on result of table type "pools" + """ + device_dissociated_pools_aggregate( + """ + input parameters for function "device_dissociated_pools_aggregate" + """ + args: device_dissociated_pools_args! + + """distinct select on columns""" + distinct_on: [pools_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [pools_order_by!] + + """filter the rows returned""" + where: pools_bool_exp + ): pools_aggregate! + + """ + fetch data from the table: "device_pools" + """ + device_pools( + """distinct select on columns""" + distinct_on: [device_pools_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [device_pools_order_by!] + + """filter the rows returned""" + where: device_pools_bool_exp + ): [device_pools!]! + + """ + fetch aggregated fields from the table: "device_pools" + """ + device_pools_aggregate( + """distinct select on columns""" + distinct_on: [device_pools_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [device_pools_order_by!] + + """filter the rows returned""" + where: device_pools_bool_exp + ): device_pools_aggregate! + + """fetch data from the table: "device_pools" using primary key columns""" + device_pools_by_pk(deviceId: uuid!, poolId: uuid!): device_pools + + """An array relationship""" + devices( + """distinct select on columns""" + distinct_on: [devices_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [devices_order_by!] + + """filter the rows returned""" + where: devices_bool_exp + ): [devices!]! + + """An aggregate relationship""" + devices_aggregate( + """distinct select on columns""" + distinct_on: [devices_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [devices_order_by!] + + """filter the rows returned""" + where: devices_bool_exp + ): devices_aggregate! + + """fetch data from the table: "devices" using primary key columns""" + devices_by_pk(id: uuid!): devices + + """ + fetch data from the table: "direction" + """ + direction( + """distinct select on columns""" + distinct_on: [direction_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [direction_order_by!] + + """filter the rows returned""" + where: direction_bool_exp + ): [direction!]! + + """fetch data from the table: "direction" using primary key columns""" + direction_by_pk(value: String!): direction + + """fetch data from the table: "storage.files" using primary key columns""" + file(id: uuid!): files + + """ + fetch data from the table: "storage.files" + """ + files( + """distinct select on columns""" + distinct_on: [files_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [files_order_by!] + + """filter the rows returned""" + where: files_bool_exp + ): [files!]! -""" -aggregate fields of "protocol" -""" -type protocol_aggregate_fields { - count(columns: [protocol_select_column!], distinct: Boolean): Int! - max: protocol_max_fields - min: protocol_min_fields -} + """An array relationship""" + groups( + """distinct select on columns""" + distinct_on: [groups_select_column!] -""" -Boolean expression to filter rows from the table "protocol". All fields are combined with a logical 'AND'. -""" -input protocol_bool_exp { - _and: [protocol_bool_exp!] - _not: protocol_bool_exp - _or: [protocol_bool_exp!] - description: String_comparison_exp - value: String_comparison_exp -} + """limit the number of rows returned""" + limit: Int -enum protocol_enum { - """Any""" - Any + """skip the first n rows. Use only with order_by""" + offset: Int - """ICMP""" - ICMP + """sort the rows by one or more columns""" + order_by: [groups_order_by!] - """ICMPV6""" - ICMPV6 + """filter the rows returned""" + where: groups_bool_exp + ): [groups!]! - """IGMP""" - IGMP + """An aggregate relationship""" + groups_aggregate( + """distinct select on columns""" + distinct_on: [groups_select_column!] - """IP""" - IP + """limit the number of rows returned""" + limit: Int - """IPV6""" - IPV6 + """skip the first n rows. Use only with order_by""" + offset: Int - """RM""" - RM + """sort the rows by one or more columns""" + order_by: [groups_order_by!] - """TCP""" - TCP + """filter the rows returned""" + where: groups_bool_exp + ): groups_aggregate! - """UDP""" - UDP -} + """fetch data from the table: "groups" using primary key columns""" + groups_by_pk(id: uuid!): groups -""" -Boolean expression to compare columns of type "protocol_enum". All fields are combined with logical 'AND'. -""" -input protocol_enum_comparison_exp { - _eq: protocol_enum - _in: [protocol_enum!] - _is_null: Boolean - _neq: protocol_enum - _nin: [protocol_enum!] -} + """An array relationship""" + memberships( + """distinct select on columns""" + distinct_on: [memberships_select_column!] -"""aggregate max on columns""" -type protocol_max_fields { - description: String - value: String -} + """limit the number of rows returned""" + limit: Int -"""aggregate min on columns""" -type protocol_min_fields { - description: String - value: String -} + """skip the first n rows. Use only with order_by""" + offset: Int -"""Ordering options when selecting data from "protocol".""" -input protocol_order_by { - description: order_by - value: order_by -} + """sort the rows by one or more columns""" + order_by: [memberships_order_by!] -""" -select columns of table "protocol" -""" -enum protocol_select_column { - """column name""" - description + """filter the rows returned""" + where: memberships_bool_exp + ): [memberships!]! - """column name""" - value -} + """An aggregate relationship""" + memberships_aggregate( + """distinct select on columns""" + distinct_on: [memberships_select_column!] -""" -Streaming cursor of the table "protocol" -""" -input protocol_stream_cursor_input { - """Stream column input with initial value""" - initial_value: protocol_stream_cursor_value_input! + """limit the number of rows returned""" + limit: Int - """cursor ordering""" - ordering: cursor_ordering -} + """skip the first n rows. Use only with order_by""" + offset: Int -"""Initial value of the column from where the streaming should start""" -input protocol_stream_cursor_value_input { - description: String - value: String -} + """sort the rows by one or more columns""" + order_by: [memberships_order_by!] -type query_root { - """Universities API""" - ListUniversities(arg1: ListUniversitiesInput!): [ListUniversitiesOutput] + """filter the rows returned""" + where: memberships_bool_exp + ): memberships_aggregate! - """Restrooms API""" - SearchRestrooms(arg1: SearchRestroomsInput!): [SearchRestroomsOutput] + """fetch data from the table: "memberships" using primary key columns""" + memberships_by_pk(orgId: uuid!, userId: uuid!): memberships """ - fetch data from the table: "action" + fetch data from the table: "org_settings" """ - action( + org_settings( """distinct select on columns""" - distinct_on: [action_select_column!] + distinct_on: [org_settings_select_column!] """limit the number of rows returned""" limit: Int @@ -3461,18 +6142,18 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [action_order_by!] + order_by: [org_settings_order_by!] """filter the rows returned""" - where: action_bool_exp - ): [action!]! + where: org_settings_bool_exp + ): [org_settings!]! """ - fetch aggregated fields from the table: "action" + fetch aggregated fields from the table: "org_settings" """ - action_aggregate( + org_settings_aggregate( """distinct select on columns""" - distinct_on: [action_select_column!] + distinct_on: [org_settings_select_column!] """limit the number of rows returned""" limit: Int @@ -3481,26 +6162,26 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [action_order_by!] + order_by: [org_settings_order_by!] """filter the rows returned""" - where: action_bool_exp - ): action_aggregate! + where: org_settings_bool_exp + ): org_settings_aggregate! - """fetch data from the table: "action" using primary key columns""" - action_by_pk(value: String!): action + """fetch data from the table: "org_settings" using primary key columns""" + org_settings_by_pk(key: String!, org_id: uuid!): org_settings """ - fetch data from the table: "auth.refresh_tokens" using primary key columns + execute function "org_settings_with_defaults" which returns "org_settings" """ - authRefreshToken(id: uuid!): authRefreshTokens + org_settings_with_defaults( + """ + input parameters for function "org_settings_with_defaults" + """ + args: org_settings_with_defaults_args! - """ - fetch data from the table: "auth.refresh_tokens" - """ - authRefreshTokens( """distinct select on columns""" - distinct_on: [authRefreshTokens_select_column!] + distinct_on: [org_settings_select_column!] """limit the number of rows returned""" limit: Int @@ -3509,23 +6190,23 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [authRefreshTokens_order_by!] + order_by: [org_settings_order_by!] """filter the rows returned""" - where: authRefreshTokens_bool_exp - ): [authRefreshTokens!]! + where: org_settings_bool_exp + ): [org_settings!]! """ - fetch data from the table: "auth.user_providers" using primary key columns + execute function "org_settings_with_defaults" and query aggregates on result of table type "org_settings" """ - authUserProvider(id: uuid!): authUserProviders + org_settings_with_defaults_aggregate( + """ + input parameters for function "org_settings_with_defaults_aggregate" + """ + args: org_settings_with_defaults_args! - """ - fetch data from the table: "auth.user_providers" - """ - authUserProviders( """distinct select on columns""" - distinct_on: [authUserProviders_select_column!] + distinct_on: [org_settings_select_column!] """limit the number of rows returned""" limit: Int @@ -3534,21 +6215,18 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [authUserProviders_order_by!] + order_by: [org_settings_order_by!] """filter the rows returned""" - where: authUserProviders_bool_exp - ): [authUserProviders!]! - - """fetch data from the table: "auth.user_roles" using primary key columns""" - authUserRole(id: uuid!): authUserRoles + where: org_settings_bool_exp + ): org_settings_aggregate! """ - fetch data from the table: "auth.user_roles" + fetch data from the table: "organizations" """ - authUserRoles( + organizations( """distinct select on columns""" - distinct_on: [authUserRoles_select_column!] + distinct_on: [organizations_select_column!] """limit the number of rows returned""" limit: Int @@ -3557,18 +6235,18 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [authUserRoles_order_by!] + order_by: [organizations_order_by!] """filter the rows returned""" - where: authUserRoles_bool_exp - ): [authUserRoles!]! + where: organizations_bool_exp + ): [organizations!]! """ - fetch aggregated fields from the table: "auth.user_roles" + fetch aggregated fields from the table: "organizations" """ - authUserRolesAggregate( + organizations_aggregate( """distinct select on columns""" - distinct_on: [authUserRoles_select_column!] + distinct_on: [organizations_select_column!] """limit the number of rows returned""" limit: Int @@ -3577,23 +6255,21 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [authUserRoles_order_by!] + order_by: [organizations_order_by!] """filter the rows returned""" - where: authUserRoles_bool_exp - ): authUserRoles_aggregate! + where: organizations_bool_exp + ): organizations_aggregate! - """ - fetch data from the table: "auth.user_security_keys" using primary key columns - """ - authUserSecurityKey(id: uuid!): authUserSecurityKeys + """fetch data from the table: "organizations" using primary key columns""" + organizations_by_pk(id: uuid!): organizations """ - fetch data from the table: "auth.user_security_keys" + fetch data from the table: "plan" """ - authUserSecurityKeys( + plan( """distinct select on columns""" - distinct_on: [authUserSecurityKeys_select_column!] + distinct_on: [plan_select_column!] """limit the number of rows returned""" limit: Int @@ -3602,18 +6278,19 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [authUserSecurityKeys_order_by!] + order_by: [plan_order_by!] """filter the rows returned""" - where: authUserSecurityKeys_bool_exp - ): [authUserSecurityKeys!]! + where: plan_bool_exp + ): [plan!]! - """ - fetch data from the table: "device_pools" - """ - device_pools( + """fetch data from the table: "plan" using primary key columns""" + plan_by_pk(value: String!): plan + + """An array relationship""" + policies( """distinct select on columns""" - distinct_on: [device_pools_select_column!] + distinct_on: [policies_select_column!] """limit the number of rows returned""" limit: Int @@ -3622,18 +6299,16 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [device_pools_order_by!] + order_by: [policies_order_by!] """filter the rows returned""" - where: device_pools_bool_exp - ): [device_pools!]! + where: policies_bool_exp + ): [policies!]! - """ - fetch aggregated fields from the table: "device_pools" - """ - device_pools_aggregate( + """An aggregate relationship""" + policies_aggregate( """distinct select on columns""" - distinct_on: [device_pools_select_column!] + distinct_on: [policies_select_column!] """limit the number of rows returned""" limit: Int @@ -3642,21 +6317,37 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [device_pools_order_by!] + order_by: [policies_order_by!] """filter the rows returned""" - where: device_pools_bool_exp - ): device_pools_aggregate! + where: policies_bool_exp + ): policies_aggregate! - """fetch data from the table: "device_pools" using primary key columns""" - device_pools_by_pk(id: uuid!): device_pools + """fetch data from the table: "policies" using primary key columns""" + policies_by_pk(id: uuid!): policies - """ - fetch data from the table: "devices" - """ - devices( + """An array relationship""" + pools( """distinct select on columns""" - distinct_on: [devices_select_column!] + distinct_on: [pools_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [pools_order_by!] + + """filter the rows returned""" + where: pools_bool_exp + ): [pools!]! + + """An aggregate relationship""" + pools_aggregate( + """distinct select on columns""" + distinct_on: [pools_select_column!] """limit the number of rows returned""" limit: Int @@ -3665,18 +6356,21 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [devices_order_by!] + order_by: [pools_order_by!] """filter the rows returned""" - where: devices_bool_exp - ): [devices!]! + where: pools_bool_exp + ): pools_aggregate! + + """fetch data from the table: "pools" using primary key columns""" + pools_by_pk(id: uuid!): pools """ - fetch aggregated fields from the table: "devices" + fetch data from the table: "protocol" """ - devices_aggregate( + protocol( """distinct select on columns""" - distinct_on: [devices_select_column!] + distinct_on: [protocol_select_column!] """limit the number of rows returned""" limit: Int @@ -3685,21 +6379,19 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [devices_order_by!] + order_by: [protocol_order_by!] """filter the rows returned""" - where: devices_bool_exp - ): devices_aggregate! + where: protocol_bool_exp + ): [protocol!]! - """fetch data from the table: "devices" using primary key columns""" - devices_by_pk(id: uuid!): devices + """fetch data from the table: "protocol" using primary key columns""" + protocol_by_pk(value: String!): protocol - """ - fetch data from the table: "direction" - """ - direction( + """An array relationship""" + rules( """distinct select on columns""" - distinct_on: [direction_select_column!] + distinct_on: [rules_select_column!] """limit the number of rows returned""" limit: Int @@ -3708,18 +6400,16 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [direction_order_by!] + order_by: [rules_order_by!] """filter the rows returned""" - where: direction_bool_exp - ): [direction!]! + where: rules_bool_exp + ): [rules!]! - """ - fetch aggregated fields from the table: "direction" - """ - direction_aggregate( + """An aggregate relationship""" + rules_aggregate( """distinct select on columns""" - distinct_on: [direction_select_column!] + distinct_on: [rules_select_column!] """limit the number of rows returned""" limit: Int @@ -3728,24 +6418,21 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [direction_order_by!] + order_by: [rules_order_by!] """filter the rows returned""" - where: direction_bool_exp - ): direction_aggregate! - - """fetch data from the table: "direction" using primary key columns""" - direction_by_pk(value: String!): direction + where: rules_bool_exp + ): rules_aggregate! - """fetch data from the table: "storage.files" using primary key columns""" - file(id: uuid!): files + """fetch data from the table: "rules" using primary key columns""" + rules_by_pk(id: uuid!): rules """ - fetch data from the table: "storage.files" + fetch data from the table: "setting_keys" """ - files( + setting_keys( """distinct select on columns""" - distinct_on: [files_select_column!] + distinct_on: [setting_keys_select_column!] """limit the number of rows returned""" limit: Int @@ -3754,18 +6441,18 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [files_order_by!] + order_by: [setting_keys_order_by!] """filter the rows returned""" - where: files_bool_exp - ): [files!]! + where: setting_keys_bool_exp + ): [setting_keys!]! """ - fetch data from the table: "groups" + fetch aggregated fields from the table: "setting_keys" """ - groups( + setting_keys_aggregate( """distinct select on columns""" - distinct_on: [groups_select_column!] + distinct_on: [setting_keys_select_column!] """limit the number of rows returned""" limit: Int @@ -3774,21 +6461,21 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [groups_order_by!] + order_by: [setting_keys_order_by!] """filter the rows returned""" - where: groups_bool_exp - ): [groups!]! + where: setting_keys_bool_exp + ): setting_keys_aggregate! - """fetch data from the table: "groups" using primary key columns""" - groups_by_pk(id: uuid!): groups + """fetch data from the table: "setting_keys" using primary key columns""" + setting_keys_by_pk(key: String!): setting_keys """ - fetch data from the table: "organizations" + fetch data from the table: "status" """ - organizations( + status( """distinct select on columns""" - distinct_on: [organizations_select_column!] + distinct_on: [status_select_column!] """limit the number of rows returned""" limit: Int @@ -3797,21 +6484,21 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [organizations_order_by!] + order_by: [status_order_by!] """filter the rows returned""" - where: organizations_bool_exp - ): [organizations!]! + where: status_bool_exp + ): [status!]! - """fetch data from the table: "organizations" using primary key columns""" - organizations_by_pk(organization: String!): organizations + """fetch data from the table: "status" using primary key columns""" + status_by_pk(value: String!): status """ - fetch data from the table: "policies" + fetch data from the table: "subject_type" """ - policies( + subject_type( """distinct select on columns""" - distinct_on: [policies_select_column!] + distinct_on: [subject_type_select_column!] """limit the number of rows returned""" limit: Int @@ -3820,21 +6507,19 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [policies_order_by!] + order_by: [subject_type_order_by!] """filter the rows returned""" - where: policies_bool_exp - ): [policies!]! + where: subject_type_bool_exp + ): [subject_type!]! - """fetch data from the table: "policies" using primary key columns""" - policies_by_pk(id: uuid!): policies + """fetch data from the table: "subject_type" using primary key columns""" + subject_type_by_pk(value: String!): subject_type - """ - fetch data from the table: "pools" - """ - pools( + """An array relationship""" + subscriptions( """distinct select on columns""" - distinct_on: [pools_select_column!] + distinct_on: [subscriptions_select_column!] """limit the number of rows returned""" limit: Int @@ -3843,18 +6528,16 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [pools_order_by!] + order_by: [subscriptions_order_by!] """filter the rows returned""" - where: pools_bool_exp - ): [pools!]! + where: subscriptions_bool_exp + ): [subscriptions!]! - """ - fetch aggregated fields from the table: "pools" - """ - pools_aggregate( + """An aggregate relationship""" + subscriptions_aggregate( """distinct select on columns""" - distinct_on: [pools_select_column!] + distinct_on: [subscriptions_select_column!] """limit the number of rows returned""" limit: Int @@ -3863,21 +6546,29 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [pools_order_by!] + order_by: [subscriptions_order_by!] """filter the rows returned""" - where: pools_bool_exp - ): pools_aggregate! + where: subscriptions_bool_exp + ): subscriptions_aggregate! - """fetch data from the table: "pools" using primary key columns""" - pools_by_pk(id: uuid!): pools + """fetch data from the table: "subscriptions" using primary key columns""" + subscriptions_by_pk(id: uuid!): subscriptions + + """fetch data from the table: "auth.users" using primary key columns""" + user(id: uuid!): users """ - fetch data from the table: "protocol" + execute function "user_associated_groups" which returns "groups" """ - protocol( + user_associated_groups( + """ + input parameters for function "user_associated_groups" + """ + args: user_associated_groups_args! + """distinct select on columns""" - distinct_on: [protocol_select_column!] + distinct_on: [groups_select_column!] """limit the number of rows returned""" limit: Int @@ -3886,18 +6577,23 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [protocol_order_by!] + order_by: [groups_order_by!] """filter the rows returned""" - where: protocol_bool_exp - ): [protocol!]! + where: groups_bool_exp + ): [groups!]! """ - fetch aggregated fields from the table: "protocol" + execute function "user_associated_groups" and query aggregates on result of table type "groups" """ - protocol_aggregate( + user_associated_groups_aggregate( + """ + input parameters for function "user_associated_groups_aggregate" + """ + args: user_associated_groups_args! + """distinct select on columns""" - distinct_on: [protocol_select_column!] + distinct_on: [groups_select_column!] """limit the number of rows returned""" limit: Int @@ -3906,21 +6602,23 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [protocol_order_by!] + order_by: [groups_order_by!] """filter the rows returned""" - where: protocol_bool_exp - ): protocol_aggregate! - - """fetch data from the table: "protocol" using primary key columns""" - protocol_by_pk(value: String!): protocol + where: groups_bool_exp + ): groups_aggregate! """ - fetch data from the table: "rules" + execute function "user_dissociated_groups" which returns "groups" """ - rules( + user_dissociated_groups( + """ + input parameters for function "user_dissociated_groups" + """ + args: user_dissociated_groups_args! + """distinct select on columns""" - distinct_on: [rules_select_column!] + distinct_on: [groups_select_column!] """limit the number of rows returned""" limit: Int @@ -3929,21 +6627,23 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [rules_order_by!] + order_by: [groups_order_by!] """filter the rows returned""" - where: rules_bool_exp - ): [rules!]! - - """fetch data from the table: "rules" using primary key columns""" - rules_by_pk(id: uuid!): rules + where: groups_bool_exp + ): [groups!]! """ - fetch data from the table: "subject_type" + execute function "user_dissociated_groups" and query aggregates on result of table type "groups" """ - subject_type( + user_dissociated_groups_aggregate( + """ + input parameters for function "user_dissociated_groups_aggregate" + """ + args: user_dissociated_groups_args! + """distinct select on columns""" - distinct_on: [subject_type_select_column!] + distinct_on: [groups_select_column!] """limit the number of rows returned""" limit: Int @@ -3952,17 +6652,11 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [subject_type_order_by!] + order_by: [groups_order_by!] """filter the rows returned""" - where: subject_type_bool_exp - ): [subject_type!]! - - """fetch data from the table: "subject_type" using primary key columns""" - subject_type_by_pk(value: String!): subject_type - - """fetch data from the table: "auth.users" using primary key columns""" - user(id: uuid!): users + where: groups_bool_exp + ): groups_aggregate! """ fetch data from the table: "user_groups" @@ -3984,15 +6678,12 @@ type query_root { where: user_groups_bool_exp ): [user_groups!]! - """fetch data from the table: "user_groups" using primary key columns""" - user_groups_by_pk(id: uuid!): user_groups - """ - fetch data from the table: "user_org_roles" + fetch aggregated fields from the table: "user_groups" """ - user_org_roles( + user_groups_aggregate( """distinct select on columns""" - distinct_on: [user_org_roles_select_column!] + distinct_on: [user_groups_select_column!] """limit the number of rows returned""" limit: Int @@ -4001,18 +6692,21 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [user_org_roles_order_by!] + order_by: [user_groups_order_by!] """filter the rows returned""" - where: user_org_roles_bool_exp - ): [user_org_roles!]! + where: user_groups_bool_exp + ): user_groups_aggregate! + + """fetch data from the table: "user_groups" using primary key columns""" + user_groups_by_pk(groupId: uuid!, userId: uuid!): user_groups """ - fetch aggregated fields from the table: "user_org_roles" + fetch data from the table: "auth.users" """ - user_org_roles_aggregate( + users( """distinct select on columns""" - distinct_on: [user_org_roles_select_column!] + distinct_on: [users_select_column!] """limit the number of rows returned""" limit: Int @@ -4021,19 +6715,16 @@ type query_root { offset: Int """sort the rows by one or more columns""" - order_by: [user_org_roles_order_by!] + order_by: [users_order_by!] """filter the rows returned""" - where: user_org_roles_bool_exp - ): user_org_roles_aggregate! - - """fetch data from the table: "user_org_roles" using primary key columns""" - user_org_roles_by_pk(id: uuid!): user_org_roles + where: users_bool_exp + ): [users!]! """ - fetch data from the table: "auth.users" + fetch aggregated fields from the table: "auth.users" """ - users( + usersAggregate( """distinct select on columns""" distinct_on: [users_select_column!] @@ -4048,23 +6739,62 @@ type query_root { """filter the rows returned""" where: users_bool_exp - ): [users!]! + ): users_aggregate! } -"""5-tuple firewalls rules""" +"""Table containing shared or single-use 5-tuple firewalls rules""" type rules { action: action_enum! - annotations: hstore appId: String createdAt: timestamptz! - createdBy: String! + createdBy: uuid! description: String destination: String destinationPort: String direction: direction_enum! displayName: String! id: uuid! - organization: String! + metadata( + """JSON select path""" + path: String + ): jsonb + orgId: uuid! + + """An array relationship""" + policies( + """distinct select on columns""" + distinct_on: [policies_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [policies_order_by!] + + """filter the rows returned""" + where: policies_bool_exp + ): [policies!]! + + """An aggregate relationship""" + policies_aggregate( + """distinct select on columns""" + distinct_on: [policies_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [policies_order_by!] + + """filter the rows returned""" + where: policies_bool_exp + ): policies_aggregate! protocol: protocol_enum! shared: Boolean! source: String @@ -4072,10 +6802,106 @@ type rules { tags: [String!] throttleRate: String updatedAt: timestamptz! - updatedBy: String! + updatedBy: uuid! weight: smallint! } +""" +aggregated selection of "rules" +""" +type rules_aggregate { + aggregate: rules_aggregate_fields + nodes: [rules!]! +} + +input rules_aggregate_bool_exp { + bool_and: rules_aggregate_bool_exp_bool_and + bool_or: rules_aggregate_bool_exp_bool_or + count: rules_aggregate_bool_exp_count +} + +input rules_aggregate_bool_exp_bool_and { + arguments: rules_select_column_rules_aggregate_bool_exp_bool_and_arguments_columns! + distinct: Boolean + filter: rules_bool_exp + predicate: Boolean_comparison_exp! +} + +input rules_aggregate_bool_exp_bool_or { + arguments: rules_select_column_rules_aggregate_bool_exp_bool_or_arguments_columns! + distinct: Boolean + filter: rules_bool_exp + predicate: Boolean_comparison_exp! +} + +input rules_aggregate_bool_exp_count { + arguments: [rules_select_column!] + distinct: Boolean + filter: rules_bool_exp + predicate: Int_comparison_exp! +} + +""" +aggregate fields of "rules" +""" +type rules_aggregate_fields { + avg: rules_avg_fields + count(columns: [rules_select_column!], distinct: Boolean): Int! + max: rules_max_fields + min: rules_min_fields + stddev: rules_stddev_fields + stddev_pop: rules_stddev_pop_fields + stddev_samp: rules_stddev_samp_fields + sum: rules_sum_fields + var_pop: rules_var_pop_fields + var_samp: rules_var_samp_fields + variance: rules_variance_fields +} + +""" +order by aggregate values of table "rules" +""" +input rules_aggregate_order_by { + avg: rules_avg_order_by + count: order_by + max: rules_max_order_by + min: rules_min_order_by + stddev: rules_stddev_order_by + stddev_pop: rules_stddev_pop_order_by + stddev_samp: rules_stddev_samp_order_by + sum: rules_sum_order_by + var_pop: rules_var_pop_order_by + var_samp: rules_var_samp_order_by + variance: rules_variance_order_by +} + +"""append existing jsonb value of filtered columns with new jsonb value""" +input rules_append_input { + metadata: jsonb +} + +""" +input type for inserting array relation for remote table "rules" +""" +input rules_arr_rel_insert_input { + data: [rules_insert_input!]! + + """upsert condition""" + on_conflict: rules_on_conflict +} + +"""aggregate avg on columns""" +type rules_avg_fields { + weight: Float +} + +""" +order by avg() on columns of table "rules" +""" +input rules_avg_order_by { + weight: order_by +} + """ Boolean expression to filter rows from the table "rules". All fields are combined with a logical 'AND'. """ @@ -4084,17 +6910,19 @@ input rules_bool_exp { _not: rules_bool_exp _or: [rules_bool_exp!] action: action_enum_comparison_exp - annotations: hstore_comparison_exp appId: String_comparison_exp createdAt: timestamptz_comparison_exp - createdBy: String_comparison_exp + createdBy: uuid_comparison_exp description: String_comparison_exp destination: String_comparison_exp destinationPort: String_comparison_exp direction: direction_enum_comparison_exp displayName: String_comparison_exp id: uuid_comparison_exp - organization: String_comparison_exp + metadata: jsonb_comparison_exp + orgId: uuid_comparison_exp + policies: policies_bool_exp + policies_aggregate: policies_aggregate_bool_exp protocol: protocol_enum_comparison_exp shared: Boolean_comparison_exp source: String_comparison_exp @@ -4102,7 +6930,7 @@ input rules_bool_exp { tags: String_array_comparison_exp throttleRate: String_comparison_exp updatedAt: timestamptz_comparison_exp - updatedBy: String_comparison_exp + updatedBy: uuid_comparison_exp weight: smallint_comparison_exp } @@ -4111,9 +6939,9 @@ unique or primary key constraints on table "rules" """ enum rules_constraint { """ - unique or primary key constraint on columns "display_name", "organization" + unique or primary key constraint on columns "display_name", "org_id" """ - rules_display_name_organization_unique + rules_org_id_display_name_key """ unique or primary key constraint on columns "id" @@ -4121,6 +6949,27 @@ enum rules_constraint { rules_pkey } +""" +delete the field or element with specified path (for JSON arrays, negative integers count from the end) +""" +input rules_delete_at_path_input { + metadata: [String!] +} + +""" +delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array +""" +input rules_delete_elem_input { + metadata: Int +} + +""" +delete key/value pair or string element. key/value pairs are matched based on their key value +""" +input rules_delete_key_input { + metadata: String +} + """ input type for incrementing numeric columns in table "rules" """ @@ -4133,14 +6982,14 @@ input type for inserting data into table "rules" """ input rules_insert_input { action: action_enum - annotations: hstore appId: String description: String destination: String destinationPort: String direction: direction_enum displayName: String - organization: String + metadata: jsonb + policies: policies_arr_rel_insert_input protocol: protocol_enum shared: Boolean source: String @@ -4150,6 +6999,90 @@ input rules_insert_input { weight: smallint } +"""aggregate max on columns""" +type rules_max_fields { + appId: String + createdAt: timestamptz + createdBy: uuid + description: String + destination: String + destinationPort: String + displayName: String + id: uuid + orgId: uuid + source: String + sourcePort: String + tags: [String!] + throttleRate: String + updatedAt: timestamptz + updatedBy: uuid + weight: smallint +} + +""" +order by max() on columns of table "rules" +""" +input rules_max_order_by { + appId: order_by + createdAt: order_by + createdBy: order_by + description: order_by + destination: order_by + destinationPort: order_by + displayName: order_by + id: order_by + orgId: order_by + source: order_by + sourcePort: order_by + tags: order_by + throttleRate: order_by + updatedAt: order_by + updatedBy: order_by + weight: order_by +} + +"""aggregate min on columns""" +type rules_min_fields { + appId: String + createdAt: timestamptz + createdBy: uuid + description: String + destination: String + destinationPort: String + displayName: String + id: uuid + orgId: uuid + source: String + sourcePort: String + tags: [String!] + throttleRate: String + updatedAt: timestamptz + updatedBy: uuid + weight: smallint +} + +""" +order by min() on columns of table "rules" +""" +input rules_min_order_by { + appId: order_by + createdAt: order_by + createdBy: order_by + description: order_by + destination: order_by + destinationPort: order_by + displayName: order_by + id: order_by + orgId: order_by + source: order_by + sourcePort: order_by + tags: order_by + throttleRate: order_by + updatedAt: order_by + updatedBy: order_by + weight: order_by +} + """ response of any mutation on the table "rules" """ @@ -4183,7 +7116,6 @@ input rules_on_conflict { """Ordering options when selecting data from "rules".""" input rules_order_by { action: order_by - annotations: order_by appId: order_by createdAt: order_by createdBy: order_by @@ -4193,7 +7125,9 @@ input rules_order_by { direction: order_by displayName: order_by id: order_by - organization: order_by + metadata: order_by + orgId: order_by + policies_aggregate: policies_aggregate_order_by protocol: order_by shared: order_by source: order_by @@ -4210,6 +7144,11 @@ input rules_pk_columns_input { id: uuid! } +"""prepend existing jsonb value of filtered columns with new jsonb value""" +input rules_prepend_input { + metadata: jsonb +} + """ select columns of table "rules" """ @@ -4217,9 +7156,6 @@ enum rules_select_column { """column name""" action - """column name""" - annotations - """column name""" appId @@ -4248,7 +7184,10 @@ enum rules_select_column { id """column name""" - organization + metadata + + """column name""" + orgId """column name""" protocol @@ -4278,20 +7217,34 @@ enum rules_select_column { weight } +""" +select "rules_aggregate_bool_exp_bool_and_arguments_columns" columns of table "rules" +""" +enum rules_select_column_rules_aggregate_bool_exp_bool_and_arguments_columns { + """column name""" + shared +} + +""" +select "rules_aggregate_bool_exp_bool_or_arguments_columns" columns of table "rules" +""" +enum rules_select_column_rules_aggregate_bool_exp_bool_or_arguments_columns { + """column name""" + shared +} + """ input type for updating data in table "rules" """ input rules_set_input { action: action_enum - annotations: hstore appId: String - deletedAt: timestamptz description: String destination: String destinationPort: String direction: direction_enum displayName: String - organization: String + metadata: jsonb protocol: protocol_enum shared: Boolean source: String @@ -4301,6 +7254,42 @@ input rules_set_input { weight: smallint } +"""aggregate stddev on columns""" +type rules_stddev_fields { + weight: Float +} + +""" +order by stddev() on columns of table "rules" +""" +input rules_stddev_order_by { + weight: order_by +} + +"""aggregate stddev_pop on columns""" +type rules_stddev_pop_fields { + weight: Float +} + +""" +order by stddev_pop() on columns of table "rules" +""" +input rules_stddev_pop_order_by { + weight: order_by +} + +"""aggregate stddev_samp on columns""" +type rules_stddev_samp_fields { + weight: Float +} + +""" +order by stddev_samp() on columns of table "rules" +""" +input rules_stddev_samp_order_by { + weight: order_by +} + """ Streaming cursor of the table "rules" """ @@ -4315,17 +7304,17 @@ input rules_stream_cursor_input { """Initial value of the column from where the streaming should start""" input rules_stream_cursor_value_input { action: action_enum - annotations: hstore appId: String createdAt: timestamptz - createdBy: String + createdBy: uuid description: String destination: String destinationPort: String direction: direction_enum displayName: String id: uuid - organization: String + metadata: jsonb + orgId: uuid protocol: protocol_enum shared: Boolean source: String @@ -4333,10 +7322,22 @@ input rules_stream_cursor_value_input { tags: [String!] throttleRate: String updatedAt: timestamptz - updatedBy: String + updatedBy: uuid + weight: smallint +} + +"""aggregate sum on columns""" +type rules_sum_fields { weight: smallint } +""" +order by sum() on columns of table "rules" +""" +input rules_sum_order_by { + weight: order_by +} + """ update columns of table "rules" """ @@ -4344,15 +7345,9 @@ enum rules_update_column { """column name""" action - """column name""" - annotations - """column name""" appId - """column name""" - deletedAt - """column name""" description @@ -4365,43 +7360,202 @@ enum rules_update_column { """column name""" direction - """column name""" - displayName + """column name""" + displayName + + """column name""" + metadata + + """column name""" + protocol + + """column name""" + shared + + """column name""" + source + + """column name""" + sourcePort + + """column name""" + tags + + """column name""" + throttleRate + + """column name""" + weight +} + +input rules_updates { + """append existing jsonb value of filtered columns with new jsonb value""" + _append: rules_append_input + + """ + delete the field or element with specified path (for JSON arrays, negative integers count from the end) + """ + _delete_at_path: rules_delete_at_path_input + + """ + delete the array element with specified index (negative integers count from the end). throws an error if top level container is not an array + """ + _delete_elem: rules_delete_elem_input + + """ + delete key/value pair or string element. key/value pairs are matched based on their key value + """ + _delete_key: rules_delete_key_input + + """increments the numeric columns with given value of the filtered values""" + _inc: rules_inc_input + + """prepend existing jsonb value of filtered columns with new jsonb value""" + _prepend: rules_prepend_input + + """sets the columns of the filtered rows to the given values""" + _set: rules_set_input + + """filter the rows which have to be updated""" + where: rules_bool_exp! +} + +"""aggregate var_pop on columns""" +type rules_var_pop_fields { + weight: Float +} + +""" +order by var_pop() on columns of table "rules" +""" +input rules_var_pop_order_by { + weight: order_by +} + +"""aggregate var_samp on columns""" +type rules_var_samp_fields { + weight: Float +} + +""" +order by var_samp() on columns of table "rules" +""" +input rules_var_samp_order_by { + weight: order_by +} + +"""aggregate variance on columns""" +type rules_variance_fields { + weight: Float +} + +""" +order by variance() on columns of table "rules" +""" +input rules_variance_order_by { + weight: order_by +} + +""" +Table containing Organization unique Setting keys and Feature Flags, act like enum +""" +type setting_keys { + allowed_values( + """JSON select path""" + path: String + ): jsonb + default_value( + """JSON select path""" + path: String + ): jsonb + description: String + key: String! +} + +""" +aggregated selection of "setting_keys" +""" +type setting_keys_aggregate { + aggregate: setting_keys_aggregate_fields + nodes: [setting_keys!]! +} + +""" +aggregate fields of "setting_keys" +""" +type setting_keys_aggregate_fields { + count(columns: [setting_keys_select_column!], distinct: Boolean): Int! + max: setting_keys_max_fields + min: setting_keys_min_fields +} - """column name""" - organization +""" +Boolean expression to filter rows from the table "setting_keys". All fields are combined with a logical 'AND'. +""" +input setting_keys_bool_exp { + _and: [setting_keys_bool_exp!] + _not: setting_keys_bool_exp + _or: [setting_keys_bool_exp!] + allowed_values: jsonb_comparison_exp + default_value: jsonb_comparison_exp + description: String_comparison_exp + key: String_comparison_exp +} - """column name""" - protocol +"""aggregate max on columns""" +type setting_keys_max_fields { + description: String + key: String +} - """column name""" - shared +"""aggregate min on columns""" +type setting_keys_min_fields { + description: String + key: String +} - """column name""" - source +"""Ordering options when selecting data from "setting_keys".""" +input setting_keys_order_by { + allowed_values: order_by + default_value: order_by + description: order_by + key: order_by +} +""" +select columns of table "setting_keys" +""" +enum setting_keys_select_column { """column name""" - sourcePort + allowed_values """column name""" - tags + default_value """column name""" - throttleRate + description """column name""" - weight + key } -input rules_updates { - """increments the numeric columns with given value of the filtered values""" - _inc: rules_inc_input +""" +Streaming cursor of the table "setting_keys" +""" +input setting_keys_stream_cursor_input { + """Stream column input with initial value""" + initial_value: setting_keys_stream_cursor_value_input! - """sets the columns of the filtered rows to the given values""" - _set: rules_set_input + """cursor ordering""" + ordering: cursor_ordering +} - """filter the rows which have to be updated""" - where: rules_bool_exp! +"""Initial value of the column from where the streaming should start""" +input setting_keys_stream_cursor_value_input { + allowed_values: jsonb + default_value: jsonb + description: String + key: String } scalar smallint @@ -4421,7 +7575,80 @@ input smallint_comparison_exp { _nin: [smallint!] } -"""subject enum""" +"""status enum""" +type status { + description: String! + value: String! +} + +""" +Boolean expression to filter rows from the table "status". All fields are combined with a logical 'AND'. +""" +input status_bool_exp { + _and: [status_bool_exp!] + _not: status_bool_exp + _or: [status_bool_exp!] + description: String_comparison_exp + value: String_comparison_exp +} + +enum status_enum { + """Active""" + active + + """Closed""" + closed + + """Disabled""" + disabled +} + +""" +Boolean expression to compare columns of type "status_enum". All fields are combined with logical 'AND'. +""" +input status_enum_comparison_exp { + _eq: status_enum + _in: [status_enum!] + _is_null: Boolean + _neq: status_enum + _nin: [status_enum!] +} + +"""Ordering options when selecting data from "status".""" +input status_order_by { + description: order_by + value: order_by +} + +""" +select columns of table "status" +""" +enum status_select_column { + """column name""" + description + + """column name""" + value +} + +""" +Streaming cursor of the table "status" +""" +input status_stream_cursor_input { + """Stream column input with initial value""" + initial_value: status_stream_cursor_value_input! + + """cursor ordering""" + ordering: cursor_ordering +} + +"""Initial value of the column from where the streaming should start""" +input status_stream_cursor_value_input { + description: String + value: String +} + +"""policy subject type enum""" type subject_type { description: String! value: String! @@ -4521,26 +7748,6 @@ type subscription_root { where: action_bool_exp ): [action!]! - """ - fetch aggregated fields from the table: "action" - """ - action_aggregate( - """distinct select on columns""" - distinct_on: [action_select_column!] - - """limit the number of rows returned""" - limit: Int - - """skip the first n rows. Use only with order_by""" - offset: Int - - """sort the rows by one or more columns""" - order_by: [action_order_by!] - - """filter the rows returned""" - where: action_bool_exp - ): action_aggregate! - """fetch data from the table: "action" using primary key columns""" action_by_pk(value: String!): action @@ -4583,6 +7790,26 @@ type subscription_root { where: authRefreshTokens_bool_exp ): [authRefreshTokens!]! + """ + fetch aggregated fields from the table: "auth.refresh_tokens" + """ + authRefreshTokensAggregate( + """distinct select on columns""" + distinct_on: [authRefreshTokens_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authRefreshTokens_order_by!] + + """filter the rows returned""" + where: authRefreshTokens_bool_exp + ): authRefreshTokens_aggregate! + """ fetch data from the table in a streaming manner: "auth.refresh_tokens" """ @@ -4622,6 +7849,26 @@ type subscription_root { where: authUserProviders_bool_exp ): [authUserProviders!]! + """ + fetch aggregated fields from the table: "auth.user_providers" + """ + authUserProvidersAggregate( + """distinct select on columns""" + distinct_on: [authUserProviders_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authUserProviders_order_by!] + + """filter the rows returned""" + where: authUserProviders_bool_exp + ): authUserProviders_aggregate! + """ fetch data from the table in a streaming manner: "auth.user_providers" """ @@ -4633,18 +7880,136 @@ type subscription_root { cursor: [authUserProviders_stream_cursor_input]! """filter the rows returned""" - where: authUserProviders_bool_exp - ): [authUserProviders!]! - - """fetch data from the table: "auth.user_roles" using primary key columns""" - authUserRole(id: uuid!): authUserRoles + where: authUserProviders_bool_exp + ): [authUserProviders!]! + + """fetch data from the table: "auth.user_roles" using primary key columns""" + authUserRole(id: uuid!): authUserRoles + + """ + fetch data from the table: "auth.user_roles" + """ + authUserRoles( + """distinct select on columns""" + distinct_on: [authUserRoles_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authUserRoles_order_by!] + + """filter the rows returned""" + where: authUserRoles_bool_exp + ): [authUserRoles!]! + + """ + fetch aggregated fields from the table: "auth.user_roles" + """ + authUserRolesAggregate( + """distinct select on columns""" + distinct_on: [authUserRoles_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authUserRoles_order_by!] + + """filter the rows returned""" + where: authUserRoles_bool_exp + ): authUserRoles_aggregate! + + """ + fetch data from the table in a streaming manner: "auth.user_roles" + """ + authUserRoles_stream( + """maximum number of rows returned in a single batch""" + batch_size: Int! + + """cursor to stream the results returned by the query""" + cursor: [authUserRoles_stream_cursor_input]! + + """filter the rows returned""" + where: authUserRoles_bool_exp + ): [authUserRoles!]! + + """ + fetch data from the table: "auth.user_security_keys" using primary key columns + """ + authUserSecurityKey(id: uuid!): authUserSecurityKeys + + """ + fetch data from the table: "auth.user_security_keys" + """ + authUserSecurityKeys( + """distinct select on columns""" + distinct_on: [authUserSecurityKeys_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authUserSecurityKeys_order_by!] + + """filter the rows returned""" + where: authUserSecurityKeys_bool_exp + ): [authUserSecurityKeys!]! + + """ + fetch aggregated fields from the table: "auth.user_security_keys" + """ + authUserSecurityKeysAggregate( + """distinct select on columns""" + distinct_on: [authUserSecurityKeys_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authUserSecurityKeys_order_by!] + + """filter the rows returned""" + where: authUserSecurityKeys_bool_exp + ): authUserSecurityKeys_aggregate! + + """ + fetch data from the table in a streaming manner: "auth.user_security_keys" + """ + authUserSecurityKeys_stream( + """maximum number of rows returned in a single batch""" + batch_size: Int! + + """cursor to stream the results returned by the query""" + cursor: [authUserSecurityKeys_stream_cursor_input]! + + """filter the rows returned""" + where: authUserSecurityKeys_bool_exp + ): [authUserSecurityKeys!]! """ - fetch data from the table: "auth.user_roles" + execute function "device_associated_pools" which returns "pools" """ - authUserRoles( + device_associated_pools( + """ + input parameters for function "device_associated_pools" + """ + args: device_associated_pools_args! + """distinct select on columns""" - distinct_on: [authUserRoles_select_column!] + distinct_on: [pools_select_column!] """limit the number of rows returned""" limit: Int @@ -4653,18 +8018,23 @@ type subscription_root { offset: Int """sort the rows by one or more columns""" - order_by: [authUserRoles_order_by!] + order_by: [pools_order_by!] """filter the rows returned""" - where: authUserRoles_bool_exp - ): [authUserRoles!]! + where: pools_bool_exp + ): [pools!]! """ - fetch aggregated fields from the table: "auth.user_roles" + execute function "device_associated_pools" and query aggregates on result of table type "pools" """ - authUserRolesAggregate( + device_associated_pools_aggregate( + """ + input parameters for function "device_associated_pools_aggregate" + """ + args: device_associated_pools_args! + """distinct select on columns""" - distinct_on: [authUserRoles_select_column!] + distinct_on: [pools_select_column!] """limit the number of rows returned""" limit: Int @@ -4673,37 +8043,23 @@ type subscription_root { offset: Int """sort the rows by one or more columns""" - order_by: [authUserRoles_order_by!] - - """filter the rows returned""" - where: authUserRoles_bool_exp - ): authUserRoles_aggregate! - - """ - fetch data from the table in a streaming manner: "auth.user_roles" - """ - authUserRoles_stream( - """maximum number of rows returned in a single batch""" - batch_size: Int! - - """cursor to stream the results returned by the query""" - cursor: [authUserRoles_stream_cursor_input]! + order_by: [pools_order_by!] """filter the rows returned""" - where: authUserRoles_bool_exp - ): [authUserRoles!]! + where: pools_bool_exp + ): pools_aggregate! """ - fetch data from the table: "auth.user_security_keys" using primary key columns + execute function "device_dissociated_pools" which returns "pools" """ - authUserSecurityKey(id: uuid!): authUserSecurityKeys + device_dissociated_pools( + """ + input parameters for function "device_dissociated_pools" + """ + args: device_dissociated_pools_args! - """ - fetch data from the table: "auth.user_security_keys" - """ - authUserSecurityKeys( """distinct select on columns""" - distinct_on: [authUserSecurityKeys_select_column!] + distinct_on: [pools_select_column!] """limit the number of rows returned""" limit: Int @@ -4712,25 +8068,36 @@ type subscription_root { offset: Int """sort the rows by one or more columns""" - order_by: [authUserSecurityKeys_order_by!] + order_by: [pools_order_by!] """filter the rows returned""" - where: authUserSecurityKeys_bool_exp - ): [authUserSecurityKeys!]! + where: pools_bool_exp + ): [pools!]! """ - fetch data from the table in a streaming manner: "auth.user_security_keys" + execute function "device_dissociated_pools" and query aggregates on result of table type "pools" """ - authUserSecurityKeys_stream( - """maximum number of rows returned in a single batch""" - batch_size: Int! + device_dissociated_pools_aggregate( + """ + input parameters for function "device_dissociated_pools_aggregate" + """ + args: device_dissociated_pools_args! - """cursor to stream the results returned by the query""" - cursor: [authUserSecurityKeys_stream_cursor_input]! + """distinct select on columns""" + distinct_on: [pools_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [pools_order_by!] """filter the rows returned""" - where: authUserSecurityKeys_bool_exp - ): [authUserSecurityKeys!]! + where: pools_bool_exp + ): pools_aggregate! """ fetch data from the table: "device_pools" @@ -4773,7 +8140,7 @@ type subscription_root { ): device_pools_aggregate! """fetch data from the table: "device_pools" using primary key columns""" - device_pools_by_pk(id: uuid!): device_pools + device_pools_by_pk(deviceId: uuid!, poolId: uuid!): device_pools """ fetch data from the table in a streaming manner: "device_pools" @@ -4789,9 +8156,7 @@ type subscription_root { where: device_pools_bool_exp ): [device_pools!]! - """ - fetch data from the table: "devices" - """ + """An array relationship""" devices( """distinct select on columns""" distinct_on: [devices_select_column!] @@ -4809,9 +8174,7 @@ type subscription_root { where: devices_bool_exp ): [devices!]! - """ - fetch aggregated fields from the table: "devices" - """ + """An aggregate relationship""" devices_aggregate( """distinct select on columns""" distinct_on: [devices_select_column!] @@ -4866,26 +8229,6 @@ type subscription_root { where: direction_bool_exp ): [direction!]! - """ - fetch aggregated fields from the table: "direction" - """ - direction_aggregate( - """distinct select on columns""" - distinct_on: [direction_select_column!] - - """limit the number of rows returned""" - limit: Int - - """skip the first n rows. Use only with order_by""" - offset: Int - - """sort the rows by one or more columns""" - order_by: [direction_order_by!] - - """filter the rows returned""" - where: direction_bool_exp - ): direction_aggregate! - """fetch data from the table: "direction" using primary key columns""" direction_by_pk(value: String!): direction @@ -4940,9 +8283,7 @@ type subscription_root { where: files_bool_exp ): [files!]! - """ - fetch data from the table: "groups" - """ + """An array relationship""" groups( """distinct select on columns""" distinct_on: [groups_select_column!] @@ -4960,6 +8301,24 @@ type subscription_root { where: groups_bool_exp ): [groups!]! + """An aggregate relationship""" + groups_aggregate( + """distinct select on columns""" + distinct_on: [groups_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [groups_order_by!] + + """filter the rows returned""" + where: groups_bool_exp + ): groups_aggregate! + """fetch data from the table: "groups" using primary key columns""" groups_by_pk(id: uuid!): groups @@ -4977,10 +8336,190 @@ type subscription_root { where: groups_bool_exp ): [groups!]! + """An array relationship""" + memberships( + """distinct select on columns""" + distinct_on: [memberships_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [memberships_order_by!] + + """filter the rows returned""" + where: memberships_bool_exp + ): [memberships!]! + + """An aggregate relationship""" + memberships_aggregate( + """distinct select on columns""" + distinct_on: [memberships_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [memberships_order_by!] + + """filter the rows returned""" + where: memberships_bool_exp + ): memberships_aggregate! + + """fetch data from the table: "memberships" using primary key columns""" + memberships_by_pk(orgId: uuid!, userId: uuid!): memberships + + """ + fetch data from the table in a streaming manner: "memberships" + """ + memberships_stream( + """maximum number of rows returned in a single batch""" + batch_size: Int! + + """cursor to stream the results returned by the query""" + cursor: [memberships_stream_cursor_input]! + + """filter the rows returned""" + where: memberships_bool_exp + ): [memberships!]! + + """ + fetch data from the table: "org_settings" + """ + org_settings( + """distinct select on columns""" + distinct_on: [org_settings_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [org_settings_order_by!] + + """filter the rows returned""" + where: org_settings_bool_exp + ): [org_settings!]! + + """ + fetch aggregated fields from the table: "org_settings" + """ + org_settings_aggregate( + """distinct select on columns""" + distinct_on: [org_settings_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [org_settings_order_by!] + + """filter the rows returned""" + where: org_settings_bool_exp + ): org_settings_aggregate! + + """fetch data from the table: "org_settings" using primary key columns""" + org_settings_by_pk(key: String!, org_id: uuid!): org_settings + + """ + fetch data from the table in a streaming manner: "org_settings" + """ + org_settings_stream( + """maximum number of rows returned in a single batch""" + batch_size: Int! + + """cursor to stream the results returned by the query""" + cursor: [org_settings_stream_cursor_input]! + + """filter the rows returned""" + where: org_settings_bool_exp + ): [org_settings!]! + + """ + execute function "org_settings_with_defaults" which returns "org_settings" + """ + org_settings_with_defaults( + """ + input parameters for function "org_settings_with_defaults" + """ + args: org_settings_with_defaults_args! + + """distinct select on columns""" + distinct_on: [org_settings_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [org_settings_order_by!] + + """filter the rows returned""" + where: org_settings_bool_exp + ): [org_settings!]! + + """ + execute function "org_settings_with_defaults" and query aggregates on result of table type "org_settings" + """ + org_settings_with_defaults_aggregate( + """ + input parameters for function "org_settings_with_defaults_aggregate" + """ + args: org_settings_with_defaults_args! + + """distinct select on columns""" + distinct_on: [org_settings_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [org_settings_order_by!] + + """filter the rows returned""" + where: org_settings_bool_exp + ): org_settings_aggregate! + """ fetch data from the table: "organizations" """ - organizations( + organizations( + """distinct select on columns""" + distinct_on: [organizations_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [organizations_order_by!] + + """filter the rows returned""" + where: organizations_bool_exp + ): [organizations!]! + + """ + fetch aggregated fields from the table: "organizations" + """ + organizations_aggregate( """distinct select on columns""" distinct_on: [organizations_select_column!] @@ -4995,10 +8534,10 @@ type subscription_root { """filter the rows returned""" where: organizations_bool_exp - ): [organizations!]! + ): organizations_aggregate! """fetch data from the table: "organizations" using primary key columns""" - organizations_by_pk(organization: String!): organizations + organizations_by_pk(id: uuid!): organizations """ fetch data from the table in a streaming manner: "organizations" @@ -5015,8 +8554,43 @@ type subscription_root { ): [organizations!]! """ - fetch data from the table: "policies" + fetch data from the table: "plan" + """ + plan( + """distinct select on columns""" + distinct_on: [plan_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [plan_order_by!] + + """filter the rows returned""" + where: plan_bool_exp + ): [plan!]! + + """fetch data from the table: "plan" using primary key columns""" + plan_by_pk(value: String!): plan + + """ + fetch data from the table in a streaming manner: "plan" """ + plan_stream( + """maximum number of rows returned in a single batch""" + batch_size: Int! + + """cursor to stream the results returned by the query""" + cursor: [plan_stream_cursor_input]! + + """filter the rows returned""" + where: plan_bool_exp + ): [plan!]! + + """An array relationship""" policies( """distinct select on columns""" distinct_on: [policies_select_column!] @@ -5034,6 +8608,24 @@ type subscription_root { where: policies_bool_exp ): [policies!]! + """An aggregate relationship""" + policies_aggregate( + """distinct select on columns""" + distinct_on: [policies_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [policies_order_by!] + + """filter the rows returned""" + where: policies_bool_exp + ): policies_aggregate! + """fetch data from the table: "policies" using primary key columns""" policies_by_pk(id: uuid!): policies @@ -5051,9 +8643,7 @@ type subscription_root { where: policies_bool_exp ): [policies!]! - """ - fetch data from the table: "pools" - """ + """An array relationship""" pools( """distinct select on columns""" distinct_on: [pools_select_column!] @@ -5071,9 +8661,7 @@ type subscription_root { where: pools_bool_exp ): [pools!]! - """ - fetch aggregated fields from the table: "pools" - """ + """An aggregate relationship""" pools_aggregate( """distinct select on columns""" distinct_on: [pools_select_column!] @@ -5128,26 +8716,6 @@ type subscription_root { where: protocol_bool_exp ): [protocol!]! - """ - fetch aggregated fields from the table: "protocol" - """ - protocol_aggregate( - """distinct select on columns""" - distinct_on: [protocol_select_column!] - - """limit the number of rows returned""" - limit: Int - - """skip the first n rows. Use only with order_by""" - offset: Int - - """sort the rows by one or more columns""" - order_by: [protocol_order_by!] - - """filter the rows returned""" - where: protocol_bool_exp - ): protocol_aggregate! - """fetch data from the table: "protocol" using primary key columns""" protocol_by_pk(value: String!): protocol @@ -5165,9 +8733,7 @@ type subscription_root { where: protocol_bool_exp ): [protocol!]! - """ - fetch data from the table: "rules" - """ + """An array relationship""" rules( """distinct select on columns""" distinct_on: [rules_select_column!] @@ -5185,6 +8751,24 @@ type subscription_root { where: rules_bool_exp ): [rules!]! + """An aggregate relationship""" + rules_aggregate( + """distinct select on columns""" + distinct_on: [rules_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [rules_order_by!] + + """filter the rows returned""" + where: rules_bool_exp + ): rules_aggregate! + """fetch data from the table: "rules" using primary key columns""" rules_by_pk(id: uuid!): rules @@ -5202,6 +8786,100 @@ type subscription_root { where: rules_bool_exp ): [rules!]! + """ + fetch data from the table: "setting_keys" + """ + setting_keys( + """distinct select on columns""" + distinct_on: [setting_keys_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [setting_keys_order_by!] + + """filter the rows returned""" + where: setting_keys_bool_exp + ): [setting_keys!]! + + """ + fetch aggregated fields from the table: "setting_keys" + """ + setting_keys_aggregate( + """distinct select on columns""" + distinct_on: [setting_keys_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [setting_keys_order_by!] + + """filter the rows returned""" + where: setting_keys_bool_exp + ): setting_keys_aggregate! + + """fetch data from the table: "setting_keys" using primary key columns""" + setting_keys_by_pk(key: String!): setting_keys + + """ + fetch data from the table in a streaming manner: "setting_keys" + """ + setting_keys_stream( + """maximum number of rows returned in a single batch""" + batch_size: Int! + + """cursor to stream the results returned by the query""" + cursor: [setting_keys_stream_cursor_input]! + + """filter the rows returned""" + where: setting_keys_bool_exp + ): [setting_keys!]! + + """ + fetch data from the table: "status" + """ + status( + """distinct select on columns""" + distinct_on: [status_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [status_order_by!] + + """filter the rows returned""" + where: status_bool_exp + ): [status!]! + + """fetch data from the table: "status" using primary key columns""" + status_by_pk(value: String!): status + + """ + fetch data from the table in a streaming manner: "status" + """ + status_stream( + """maximum number of rows returned in a single batch""" + batch_size: Int! + + """cursor to stream the results returned by the query""" + cursor: [status_stream_cursor_input]! + + """filter the rows returned""" + where: status_bool_exp + ): [status!]! + """ fetch data from the table: "subject_type" """ @@ -5239,15 +8917,73 @@ type subscription_root { where: subject_type_bool_exp ): [subject_type!]! + """An array relationship""" + subscriptions( + """distinct select on columns""" + distinct_on: [subscriptions_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [subscriptions_order_by!] + + """filter the rows returned""" + where: subscriptions_bool_exp + ): [subscriptions!]! + + """An aggregate relationship""" + subscriptions_aggregate( + """distinct select on columns""" + distinct_on: [subscriptions_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [subscriptions_order_by!] + + """filter the rows returned""" + where: subscriptions_bool_exp + ): subscriptions_aggregate! + + """fetch data from the table: "subscriptions" using primary key columns""" + subscriptions_by_pk(id: uuid!): subscriptions + + """ + fetch data from the table in a streaming manner: "subscriptions" + """ + subscriptions_stream( + """maximum number of rows returned in a single batch""" + batch_size: Int! + + """cursor to stream the results returned by the query""" + cursor: [subscriptions_stream_cursor_input]! + + """filter the rows returned""" + where: subscriptions_bool_exp + ): [subscriptions!]! + """fetch data from the table: "auth.users" using primary key columns""" user(id: uuid!): users """ - fetch data from the table: "user_groups" + execute function "user_associated_groups" which returns "groups" """ - user_groups( + user_associated_groups( + """ + input parameters for function "user_associated_groups" + """ + args: user_associated_groups_args! + """distinct select on columns""" - distinct_on: [user_groups_select_column!] + distinct_on: [groups_select_column!] """limit the number of rows returned""" limit: Int @@ -5256,35 +8992,93 @@ type subscription_root { offset: Int """sort the rows by one or more columns""" - order_by: [user_groups_order_by!] + order_by: [groups_order_by!] """filter the rows returned""" - where: user_groups_bool_exp - ): [user_groups!]! + where: groups_bool_exp + ): [groups!]! - """fetch data from the table: "user_groups" using primary key columns""" - user_groups_by_pk(id: uuid!): user_groups + """ + execute function "user_associated_groups" and query aggregates on result of table type "groups" + """ + user_associated_groups_aggregate( + """ + input parameters for function "user_associated_groups_aggregate" + """ + args: user_associated_groups_args! + + """distinct select on columns""" + distinct_on: [groups_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [groups_order_by!] + + """filter the rows returned""" + where: groups_bool_exp + ): groups_aggregate! """ - fetch data from the table in a streaming manner: "user_groups" + execute function "user_dissociated_groups" which returns "groups" """ - user_groups_stream( - """maximum number of rows returned in a single batch""" - batch_size: Int! + user_dissociated_groups( + """ + input parameters for function "user_dissociated_groups" + """ + args: user_dissociated_groups_args! - """cursor to stream the results returned by the query""" - cursor: [user_groups_stream_cursor_input]! + """distinct select on columns""" + distinct_on: [groups_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [groups_order_by!] """filter the rows returned""" - where: user_groups_bool_exp - ): [user_groups!]! + where: groups_bool_exp + ): [groups!]! + + """ + execute function "user_dissociated_groups" and query aggregates on result of table type "groups" + """ + user_dissociated_groups_aggregate( + """ + input parameters for function "user_dissociated_groups_aggregate" + """ + args: user_dissociated_groups_args! + + """distinct select on columns""" + distinct_on: [groups_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [groups_order_by!] + + """filter the rows returned""" + where: groups_bool_exp + ): groups_aggregate! """ - fetch data from the table: "user_org_roles" + fetch data from the table: "user_groups" """ - user_org_roles( + user_groups( """distinct select on columns""" - distinct_on: [user_org_roles_select_column!] + distinct_on: [user_groups_select_column!] """limit the number of rows returned""" limit: Int @@ -5293,18 +9087,18 @@ type subscription_root { offset: Int """sort the rows by one or more columns""" - order_by: [user_org_roles_order_by!] + order_by: [user_groups_order_by!] """filter the rows returned""" - where: user_org_roles_bool_exp - ): [user_org_roles!]! + where: user_groups_bool_exp + ): [user_groups!]! """ - fetch aggregated fields from the table: "user_org_roles" + fetch aggregated fields from the table: "user_groups" """ - user_org_roles_aggregate( + user_groups_aggregate( """distinct select on columns""" - distinct_on: [user_org_roles_select_column!] + distinct_on: [user_groups_select_column!] """limit the number of rows returned""" limit: Int @@ -5313,28 +9107,28 @@ type subscription_root { offset: Int """sort the rows by one or more columns""" - order_by: [user_org_roles_order_by!] + order_by: [user_groups_order_by!] """filter the rows returned""" - where: user_org_roles_bool_exp - ): user_org_roles_aggregate! + where: user_groups_bool_exp + ): user_groups_aggregate! - """fetch data from the table: "user_org_roles" using primary key columns""" - user_org_roles_by_pk(id: uuid!): user_org_roles + """fetch data from the table: "user_groups" using primary key columns""" + user_groups_by_pk(groupId: uuid!, userId: uuid!): user_groups """ - fetch data from the table in a streaming manner: "user_org_roles" + fetch data from the table in a streaming manner: "user_groups" """ - user_org_roles_stream( + user_groups_stream( """maximum number of rows returned in a single batch""" batch_size: Int! """cursor to stream the results returned by the query""" - cursor: [user_org_roles_stream_cursor_input]! + cursor: [user_groups_stream_cursor_input]! """filter the rows returned""" - where: user_org_roles_bool_exp - ): [user_org_roles!]! + where: user_groups_bool_exp + ): [user_groups!]! """ fetch data from the table: "auth.users" @@ -5356,6 +9150,26 @@ type subscription_root { where: users_bool_exp ): [users!]! + """ + fetch aggregated fields from the table: "auth.users" + """ + usersAggregate( + """distinct select on columns""" + distinct_on: [users_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [users_order_by!] + + """filter the rows returned""" + where: users_bool_exp + ): users_aggregate! + """ fetch data from the table in a streaming manner: "auth.users" """ @@ -5371,459 +9185,545 @@ type subscription_root { ): [users!]! } -scalar timestamptz +"""Table containing subscriptions for an organization""" +type subscriptions { + createdAt: timestamptz! + createdBy: uuid! + credits: Int! + id: uuid! + orgId: uuid! + + """An object relationship""" + organization: organizations! + plan: plan_enum! + status: status_enum! + stripeCheckoutSessionId: String + stripeCustomerId: String + stripeSubscriptionId: String + updatedAt: timestamptz! + updatedBy: uuid! + validUntil: timestamptz! +} """ -Boolean expression to compare columns of type "timestamptz". All fields are combined with logical 'AND'. +aggregated selection of "subscriptions" """ -input timestamptz_comparison_exp { - _eq: timestamptz - _gt: timestamptz - _gte: timestamptz - _in: [timestamptz!] - _is_null: Boolean - _lt: timestamptz - _lte: timestamptz - _neq: timestamptz - _nin: [timestamptz!] +type subscriptions_aggregate { + aggregate: subscriptions_aggregate_fields + nodes: [subscriptions!]! } -"""User to Group association table""" -type user_groups { - createdAt: timestamptz! - - """An object relationship""" - group: groups! - groupId: uuid! - id: uuid! +input subscriptions_aggregate_bool_exp { + count: subscriptions_aggregate_bool_exp_count +} - """An object relationship""" - user: users! - userId: uuid! +input subscriptions_aggregate_bool_exp_count { + arguments: [subscriptions_select_column!] + distinct: Boolean + filter: subscriptions_bool_exp + predicate: Int_comparison_exp! } """ -order by aggregate values of table "user_groups" +aggregate fields of "subscriptions" """ -input user_groups_aggregate_order_by { - count: order_by - max: user_groups_max_order_by - min: user_groups_min_order_by +type subscriptions_aggregate_fields { + avg: subscriptions_avg_fields + count(columns: [subscriptions_select_column!], distinct: Boolean): Int! + max: subscriptions_max_fields + min: subscriptions_min_fields + stddev: subscriptions_stddev_fields + stddev_pop: subscriptions_stddev_pop_fields + stddev_samp: subscriptions_stddev_samp_fields + sum: subscriptions_sum_fields + var_pop: subscriptions_var_pop_fields + var_samp: subscriptions_var_samp_fields + variance: subscriptions_variance_fields } """ -input type for inserting array relation for remote table "user_groups" +order by aggregate values of table "subscriptions" """ -input user_groups_arr_rel_insert_input { - data: [user_groups_insert_input!]! +input subscriptions_aggregate_order_by { + avg: subscriptions_avg_order_by + count: order_by + max: subscriptions_max_order_by + min: subscriptions_min_order_by + stddev: subscriptions_stddev_order_by + stddev_pop: subscriptions_stddev_pop_order_by + stddev_samp: subscriptions_stddev_samp_order_by + sum: subscriptions_sum_order_by + var_pop: subscriptions_var_pop_order_by + var_samp: subscriptions_var_samp_order_by + variance: subscriptions_variance_order_by +} - """upsert condition""" - on_conflict: user_groups_on_conflict +"""aggregate avg on columns""" +type subscriptions_avg_fields { + credits: Float } """ -Boolean expression to filter rows from the table "user_groups". All fields are combined with a logical 'AND'. +order by avg() on columns of table "subscriptions" """ -input user_groups_bool_exp { - _and: [user_groups_bool_exp!] - _not: user_groups_bool_exp - _or: [user_groups_bool_exp!] - createdAt: timestamptz_comparison_exp - group: groups_bool_exp - groupId: uuid_comparison_exp - id: uuid_comparison_exp - user: users_bool_exp - userId: uuid_comparison_exp +input subscriptions_avg_order_by { + credits: order_by } """ -unique or primary key constraints on table "user_groups" +Boolean expression to filter rows from the table "subscriptions". All fields are combined with a logical 'AND'. """ -enum user_groups_constraint { - """ - unique or primary key constraint on columns "id" - """ - user_groups_pkey +input subscriptions_bool_exp { + _and: [subscriptions_bool_exp!] + _not: subscriptions_bool_exp + _or: [subscriptions_bool_exp!] + createdAt: timestamptz_comparison_exp + createdBy: uuid_comparison_exp + credits: Int_comparison_exp + id: uuid_comparison_exp + orgId: uuid_comparison_exp + organization: organizations_bool_exp + plan: plan_enum_comparison_exp + status: status_enum_comparison_exp + stripeCheckoutSessionId: String_comparison_exp + stripeCustomerId: String_comparison_exp + stripeSubscriptionId: String_comparison_exp + updatedAt: timestamptz_comparison_exp + updatedBy: uuid_comparison_exp + validUntil: timestamptz_comparison_exp } -""" -input type for inserting data into table "user_groups" -""" -input user_groups_insert_input { - group: groups_obj_rel_insert_input - groupId: uuid - userId: uuid +"""aggregate max on columns""" +type subscriptions_max_fields { + createdAt: timestamptz + createdBy: uuid + credits: Int + id: uuid + orgId: uuid + stripeCheckoutSessionId: String + stripeCustomerId: String + stripeSubscriptionId: String + updatedAt: timestamptz + updatedBy: uuid + validUntil: timestamptz } """ -order by max() on columns of table "user_groups" +order by max() on columns of table "subscriptions" """ -input user_groups_max_order_by { +input subscriptions_max_order_by { createdAt: order_by - groupId: order_by + createdBy: order_by + credits: order_by id: order_by - userId: order_by + orgId: order_by + stripeCheckoutSessionId: order_by + stripeCustomerId: order_by + stripeSubscriptionId: order_by + updatedAt: order_by + updatedBy: order_by + validUntil: order_by +} + +"""aggregate min on columns""" +type subscriptions_min_fields { + createdAt: timestamptz + createdBy: uuid + credits: Int + id: uuid + orgId: uuid + stripeCheckoutSessionId: String + stripeCustomerId: String + stripeSubscriptionId: String + updatedAt: timestamptz + updatedBy: uuid + validUntil: timestamptz } """ -order by min() on columns of table "user_groups" +order by min() on columns of table "subscriptions" """ -input user_groups_min_order_by { +input subscriptions_min_order_by { createdAt: order_by - groupId: order_by + createdBy: order_by + credits: order_by id: order_by - userId: order_by + orgId: order_by + stripeCheckoutSessionId: order_by + stripeCustomerId: order_by + stripeSubscriptionId: order_by + updatedAt: order_by + updatedBy: order_by + validUntil: order_by } """ -response of any mutation on the table "user_groups" +response of any mutation on the table "subscriptions" """ -type user_groups_mutation_response { +type subscriptions_mutation_response { """number of rows affected by the mutation""" affected_rows: Int! """data from the rows affected by the mutation""" - returning: [user_groups!]! -} - -""" -on_conflict condition type for table "user_groups" -""" -input user_groups_on_conflict { - constraint: user_groups_constraint! - update_columns: [user_groups_update_column!]! = [] - where: user_groups_bool_exp + returning: [subscriptions!]! } -"""Ordering options when selecting data from "user_groups".""" -input user_groups_order_by { +"""Ordering options when selecting data from "subscriptions".""" +input subscriptions_order_by { createdAt: order_by - group: groups_order_by - groupId: order_by + createdBy: order_by + credits: order_by id: order_by - user: users_order_by - userId: order_by + orgId: order_by + organization: organizations_order_by + plan: order_by + status: order_by + stripeCheckoutSessionId: order_by + stripeCustomerId: order_by + stripeSubscriptionId: order_by + updatedAt: order_by + updatedBy: order_by + validUntil: order_by +} + +"""primary key columns input for table: subscriptions""" +input subscriptions_pk_columns_input { + id: uuid! } """ -select columns of table "user_groups" +select columns of table "subscriptions" """ -enum user_groups_select_column { +enum subscriptions_select_column { """column name""" createdAt """column name""" - groupId + createdBy + + """column name""" + credits """column name""" id """column name""" - userId + orgId + + """column name""" + plan + + """column name""" + status + + """column name""" + stripeCheckoutSessionId + + """column name""" + stripeCustomerId + + """column name""" + stripeSubscriptionId + + """column name""" + updatedAt + + """column name""" + updatedBy + + """column name""" + validUntil } """ -Streaming cursor of the table "user_groups" +input type for updating data in table "subscriptions" """ -input user_groups_stream_cursor_input { +input subscriptions_set_input { + plan: plan_enum + stripeCheckoutSessionId: String + stripeCustomerId: String + stripeSubscriptionId: String +} + +"""aggregate stddev on columns""" +type subscriptions_stddev_fields { + credits: Float +} + +""" +order by stddev() on columns of table "subscriptions" +""" +input subscriptions_stddev_order_by { + credits: order_by +} + +"""aggregate stddev_pop on columns""" +type subscriptions_stddev_pop_fields { + credits: Float +} + +""" +order by stddev_pop() on columns of table "subscriptions" +""" +input subscriptions_stddev_pop_order_by { + credits: order_by +} + +"""aggregate stddev_samp on columns""" +type subscriptions_stddev_samp_fields { + credits: Float +} + +""" +order by stddev_samp() on columns of table "subscriptions" +""" +input subscriptions_stddev_samp_order_by { + credits: order_by +} + +""" +Streaming cursor of the table "subscriptions" +""" +input subscriptions_stream_cursor_input { """Stream column input with initial value""" - initial_value: user_groups_stream_cursor_value_input! + initial_value: subscriptions_stream_cursor_value_input! """cursor ordering""" ordering: cursor_ordering } """Initial value of the column from where the streaming should start""" -input user_groups_stream_cursor_value_input { +input subscriptions_stream_cursor_value_input { createdAt: timestamptz - groupId: uuid + createdBy: uuid + credits: Int id: uuid - userId: uuid + orgId: uuid + plan: plan_enum + status: status_enum + stripeCheckoutSessionId: String + stripeCustomerId: String + stripeSubscriptionId: String + updatedAt: timestamptz + updatedBy: uuid + validUntil: timestamptz +} + +"""aggregate sum on columns""" +type subscriptions_sum_fields { + credits: Int } """ -placeholder for update columns of table "user_groups" (current role has no relevant permissions) +order by sum() on columns of table "subscriptions" """ -enum user_groups_update_column { - """placeholder (do not use)""" - _PLACEHOLDER +input subscriptions_sum_order_by { + credits: order_by } -"""Roles of User for a given Org.""" -type user_org_roles { - createdAt: timestamptz! - createdBy: uuid! - id: uuid! - isDefaultRole: Boolean! - organization: String! - role: String! - userId: uuid! +input subscriptions_updates { + """sets the columns of the filtered rows to the given values""" + _set: subscriptions_set_input + + """filter the rows which have to be updated""" + where: subscriptions_bool_exp! +} + +"""aggregate var_pop on columns""" +type subscriptions_var_pop_fields { + credits: Float } """ -aggregated selection of "user_org_roles" +order by var_pop() on columns of table "subscriptions" """ -type user_org_roles_aggregate { - aggregate: user_org_roles_aggregate_fields - nodes: [user_org_roles!]! +input subscriptions_var_pop_order_by { + credits: order_by } -input user_org_roles_aggregate_bool_exp { - bool_and: user_org_roles_aggregate_bool_exp_bool_and - bool_or: user_org_roles_aggregate_bool_exp_bool_or - count: user_org_roles_aggregate_bool_exp_count +"""aggregate var_samp on columns""" +type subscriptions_var_samp_fields { + credits: Float } -input user_org_roles_aggregate_bool_exp_bool_and { - arguments: user_org_roles_select_column_user_org_roles_aggregate_bool_exp_bool_and_arguments_columns! - distinct: Boolean - filter: user_org_roles_bool_exp - predicate: Boolean_comparison_exp! +""" +order by var_samp() on columns of table "subscriptions" +""" +input subscriptions_var_samp_order_by { + credits: order_by } -input user_org_roles_aggregate_bool_exp_bool_or { - arguments: user_org_roles_select_column_user_org_roles_aggregate_bool_exp_bool_or_arguments_columns! - distinct: Boolean - filter: user_org_roles_bool_exp - predicate: Boolean_comparison_exp! +"""aggregate variance on columns""" +type subscriptions_variance_fields { + credits: Float } -input user_org_roles_aggregate_bool_exp_count { - arguments: [user_org_roles_select_column!] - distinct: Boolean - filter: user_org_roles_bool_exp - predicate: Int_comparison_exp! +""" +order by variance() on columns of table "subscriptions" +""" +input subscriptions_variance_order_by { + credits: order_by +} + +scalar timestamptz + +""" +Boolean expression to compare columns of type "timestamptz". All fields are combined with logical 'AND'. +""" +input timestamptz_comparison_exp { + _eq: timestamptz + _gt: timestamptz + _gte: timestamptz + _in: [timestamptz!] + _is_null: Boolean + _lt: timestamptz + _lte: timestamptz + _neq: timestamptz + _nin: [timestamptz!] +} + +input user_associated_groups_args { + user_row: users_scalar +} + +input user_dissociated_groups_args { + user_row: users_scalar +} + +"""User to Group association table""" +type user_groups { + """An object relationship""" + group: groups! + groupId: uuid! + + """An object relationship""" + user: users! + userId: uuid! } """ -aggregate fields of "user_org_roles" +aggregated selection of "user_groups" """ -type user_org_roles_aggregate_fields { - count(columns: [user_org_roles_select_column!], distinct: Boolean): Int! - max: user_org_roles_max_fields - min: user_org_roles_min_fields +type user_groups_aggregate { + aggregate: user_groups_aggregate_fields + nodes: [user_groups!]! } """ -order by aggregate values of table "user_org_roles" +aggregate fields of "user_groups" """ -input user_org_roles_aggregate_order_by { - count: order_by - max: user_org_roles_max_order_by - min: user_org_roles_min_order_by +type user_groups_aggregate_fields { + count(columns: [user_groups_select_column!], distinct: Boolean): Int! + max: user_groups_max_fields + min: user_groups_min_fields } """ -Boolean expression to filter rows from the table "user_org_roles". All fields are combined with a logical 'AND'. +Boolean expression to filter rows from the table "user_groups". All fields are combined with a logical 'AND'. """ -input user_org_roles_bool_exp { - _and: [user_org_roles_bool_exp!] - _not: user_org_roles_bool_exp - _or: [user_org_roles_bool_exp!] - createdAt: timestamptz_comparison_exp - createdBy: uuid_comparison_exp - id: uuid_comparison_exp - isDefaultRole: Boolean_comparison_exp - organization: String_comparison_exp - role: String_comparison_exp +input user_groups_bool_exp { + _and: [user_groups_bool_exp!] + _not: user_groups_bool_exp + _or: [user_groups_bool_exp!] + group: groups_bool_exp + groupId: uuid_comparison_exp + user: users_bool_exp userId: uuid_comparison_exp } """ -unique or primary key constraints on table "user_org_roles" +unique or primary key constraints on table "user_groups" """ -enum user_org_roles_constraint { - """ - unique or primary key constraint on columns "id" - """ - user_org_roles_pkey - - """ - unique or primary key constraint on columns "user_id", "organization" - """ - user_org_roles_user_id_organization_default_role_unique - +enum user_groups_constraint { """ - unique or primary key constraint on columns "user_id", "organization", "role" + unique or primary key constraint on columns "user_id", "group_id" """ - user_org_roles_user_id_role_organization_key + user_groups_pkey } """ -input type for inserting data into table "user_org_roles" +input type for inserting data into table "user_groups" """ -input user_org_roles_insert_input { - isDefaultRole: Boolean - organization: String - role: String +input user_groups_insert_input { + group: groups_obj_rel_insert_input + groupId: uuid userId: uuid } """aggregate max on columns""" -type user_org_roles_max_fields { - createdAt: timestamptz - createdBy: uuid - id: uuid - organization: String - role: String +type user_groups_max_fields { + groupId: uuid userId: uuid } -""" -order by max() on columns of table "user_org_roles" -""" -input user_org_roles_max_order_by { - createdAt: order_by - createdBy: order_by - id: order_by - organization: order_by - role: order_by - userId: order_by -} - """aggregate min on columns""" -type user_org_roles_min_fields { - createdAt: timestamptz - createdBy: uuid - id: uuid - organization: String - role: String +type user_groups_min_fields { + groupId: uuid userId: uuid } """ -order by min() on columns of table "user_org_roles" -""" -input user_org_roles_min_order_by { - createdAt: order_by - createdBy: order_by - id: order_by - organization: order_by - role: order_by - userId: order_by -} - -""" -response of any mutation on the table "user_org_roles" +response of any mutation on the table "user_groups" """ -type user_org_roles_mutation_response { +type user_groups_mutation_response { """number of rows affected by the mutation""" affected_rows: Int! """data from the rows affected by the mutation""" - returning: [user_org_roles!]! + returning: [user_groups!]! } """ -on_conflict condition type for table "user_org_roles" +on_conflict condition type for table "user_groups" """ -input user_org_roles_on_conflict { - constraint: user_org_roles_constraint! - update_columns: [user_org_roles_update_column!]! = [] - where: user_org_roles_bool_exp +input user_groups_on_conflict { + constraint: user_groups_constraint! + update_columns: [user_groups_update_column!]! = [] + where: user_groups_bool_exp } -"""Ordering options when selecting data from "user_org_roles".""" -input user_org_roles_order_by { - createdAt: order_by - createdBy: order_by - id: order_by - isDefaultRole: order_by - organization: order_by - role: order_by +"""Ordering options when selecting data from "user_groups".""" +input user_groups_order_by { + group: groups_order_by + groupId: order_by + user: users_order_by userId: order_by } -"""primary key columns input for table: user_org_roles""" -input user_org_roles_pk_columns_input { - id: uuid! -} - """ -select columns of table "user_org_roles" +select columns of table "user_groups" """ -enum user_org_roles_select_column { - """column name""" - createdAt - - """column name""" - createdBy - - """column name""" - id - - """column name""" - isDefaultRole - - """column name""" - organization - +enum user_groups_select_column { """column name""" - role + groupId """column name""" userId } """ -select "user_org_roles_aggregate_bool_exp_bool_and_arguments_columns" columns of table "user_org_roles" -""" -enum user_org_roles_select_column_user_org_roles_aggregate_bool_exp_bool_and_arguments_columns { - """column name""" - isDefaultRole -} - -""" -select "user_org_roles_aggregate_bool_exp_bool_or_arguments_columns" columns of table "user_org_roles" -""" -enum user_org_roles_select_column_user_org_roles_aggregate_bool_exp_bool_or_arguments_columns { - """column name""" - isDefaultRole -} - -""" -input type for updating data in table "user_org_roles" -""" -input user_org_roles_set_input { - isDefaultRole: Boolean -} - -""" -Streaming cursor of the table "user_org_roles" +Streaming cursor of the table "user_groups" """ -input user_org_roles_stream_cursor_input { +input user_groups_stream_cursor_input { """Stream column input with initial value""" - initial_value: user_org_roles_stream_cursor_value_input! + initial_value: user_groups_stream_cursor_value_input! """cursor ordering""" ordering: cursor_ordering } """Initial value of the column from where the streaming should start""" -input user_org_roles_stream_cursor_value_input { - createdAt: timestamptz - createdBy: uuid - id: uuid - isDefaultRole: Boolean - organization: String - role: String +input user_groups_stream_cursor_value_input { + groupId: uuid userId: uuid } """ -update columns of table "user_org_roles" +placeholder for update columns of table "user_groups" (current role has no relevant permissions) """ -enum user_org_roles_update_column { - """column name""" - isDefaultRole -} - -input user_org_roles_updates { - """sets the columns of the filtered rows to the given values""" - _set: user_org_roles_set_input - - """filter the rows which have to be updated""" - where: user_org_roles_bool_exp! +enum user_groups_update_column { + """placeholder (do not use)""" + _PLACEHOLDER } """ @@ -5832,12 +9732,10 @@ User account information. Don't modify its structure as Hasura Auth relies on it type users { activeMfaType: String - """ - A computed field, executes function "user_allowed_orgs" - """ + """An array relationship""" allowedOrgs( """distinct select on columns""" - distinct_on: [organizations_select_column!] + distinct_on: [memberships_select_column!] """limit the number of rows returned""" limit: Int @@ -5846,21 +9744,74 @@ type users { offset: Int """sort the rows by one or more columns""" - order_by: [organizations_order_by!] + order_by: [memberships_order_by!] """filter the rows returned""" - where: organizations_bool_exp - ): [organizations!] + where: memberships_bool_exp + ): [memberships!]! + + """An aggregate relationship""" + allowedOrgs_aggregate( + """distinct select on columns""" + distinct_on: [memberships_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [memberships_order_by!] + + """filter the rows returned""" + where: memberships_bool_exp + ): memberships_aggregate! + + """Used as Computed Field on Users Table""" + associatedGroups( + """distinct select on columns""" + distinct_on: [groups_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [groups_order_by!] + + """filter the rows returned""" + where: groups_bool_exp + ): [groups!] avatarUrl: String! createdAt: timestamptz! - """ - A computed field, executes function "user_default_org" - """ - defaultOrg: String + """An object relationship""" + currentOrg: organizations + defaultOrg: uuid defaultRole: String! - disabled: Boolean! + disabled: Boolean displayName: String! + + """Used as Computed Field on Users Table""" + dissociatedGroups( + """distinct select on columns""" + distinct_on: [groups_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [groups_order_by!] + + """filter the rows returned""" + where: groups_bool_exp + ): [groups!] email: citext emailVerified: Boolean! id: uuid! @@ -5892,6 +9843,24 @@ type users { where: authRefreshTokens_bool_exp ): [authRefreshTokens!]! + """An aggregate relationship""" + refreshTokens_aggregate( + """distinct select on columns""" + distinct_on: [authRefreshTokens_select_column!] + + """limit the number of rows returned""" + limit: Int + + """skip the first n rows. Use only with order_by""" + offset: Int + + """sort the rows by one or more columns""" + order_by: [authRefreshTokens_order_by!] + + """filter the rows returned""" + where: authRefreshTokens_bool_exp + ): authRefreshTokens_aggregate! + """An array relationship""" roles( """distinct select on columns""" @@ -5945,12 +9914,11 @@ type users { """filter the rows returned""" where: authUserSecurityKeys_bool_exp ): [authUserSecurityKeys!]! - updatedAt: timestamptz! - """An array relationship""" - userOrgRoles( + """An aggregate relationship""" + securityKeys_aggregate( """distinct select on columns""" - distinct_on: [user_org_roles_select_column!] + distinct_on: [authUserSecurityKeys_select_column!] """limit the number of rows returned""" limit: Int @@ -5959,16 +9927,17 @@ type users { offset: Int """sort the rows by one or more columns""" - order_by: [user_org_roles_order_by!] + order_by: [authUserSecurityKeys_order_by!] """filter the rows returned""" - where: user_org_roles_bool_exp - ): [user_org_roles!]! + where: authUserSecurityKeys_bool_exp + ): authUserSecurityKeys_aggregate! + updatedAt: timestamptz! - """An aggregate relationship""" - userOrgRoles_aggregate( + """An array relationship""" + userProviders( """distinct select on columns""" - distinct_on: [user_org_roles_select_column!] + distinct_on: [authUserProviders_select_column!] """limit the number of rows returned""" limit: Int @@ -5977,14 +9946,14 @@ type users { offset: Int """sort the rows by one or more columns""" - order_by: [user_org_roles_order_by!] + order_by: [authUserProviders_order_by!] """filter the rows returned""" - where: user_org_roles_bool_exp - ): user_org_roles_aggregate! + where: authUserProviders_bool_exp + ): [authUserProviders!]! - """An array relationship""" - userProviders( + """An aggregate relationship""" + userProviders_aggregate( """distinct select on columns""" distinct_on: [authUserProviders_select_column!] @@ -5999,7 +9968,24 @@ type users { """filter the rows returned""" where: authUserProviders_bool_exp - ): [authUserProviders!]! + ): authUserProviders_aggregate! +} + +""" +aggregated selection of "auth.users" +""" +type users_aggregate { + aggregate: users_aggregate_fields + nodes: [users!]! +} + +""" +aggregate fields of "auth.users" +""" +type users_aggregate_fields { + count(columns: [users_select_column!], distinct: Boolean): Int! + max: users_max_fields + min: users_min_fields } """append existing jsonb value of filtered columns with new jsonb value""" @@ -6015,13 +10001,17 @@ input users_bool_exp { _not: users_bool_exp _or: [users_bool_exp!] activeMfaType: String_comparison_exp - allowedOrgs: organizations_bool_exp + allowedOrgs: memberships_bool_exp + allowedOrgs_aggregate: memberships_aggregate_bool_exp + associatedGroups: groups_bool_exp avatarUrl: String_comparison_exp createdAt: timestamptz_comparison_exp - defaultOrg: String_comparison_exp + currentOrg: organizations_bool_exp + defaultOrg: uuid_comparison_exp defaultRole: String_comparison_exp disabled: Boolean_comparison_exp displayName: String_comparison_exp + dissociatedGroups: groups_bool_exp email: citext_comparison_exp emailVerified: Boolean_comparison_exp id: uuid_comparison_exp @@ -6032,13 +10022,14 @@ input users_bool_exp { phoneNumber: String_comparison_exp phoneNumberVerified: Boolean_comparison_exp refreshTokens: authRefreshTokens_bool_exp + refreshTokens_aggregate: authRefreshTokens_aggregate_bool_exp roles: authUserRoles_bool_exp roles_aggregate: authUserRoles_aggregate_bool_exp securityKeys: authUserSecurityKeys_bool_exp + securityKeys_aggregate: authUserSecurityKeys_aggregate_bool_exp updatedAt: timestamptz_comparison_exp - userOrgRoles: user_org_roles_bool_exp - userOrgRoles_aggregate: user_org_roles_aggregate_bool_exp userProviders: authUserProviders_bool_exp + userProviders_aggregate: authUserProviders_aggregate_bool_exp } """ @@ -6062,6 +10053,38 @@ input users_delete_key_input { metadata: String } +"""aggregate max on columns""" +type users_max_fields { + activeMfaType: String + avatarUrl: String + createdAt: timestamptz + defaultOrg: uuid + defaultRole: String + displayName: String + email: citext + id: uuid + lastSeen: timestamptz + locale: String + phoneNumber: String + updatedAt: timestamptz +} + +"""aggregate min on columns""" +type users_min_fields { + activeMfaType: String + avatarUrl: String + createdAt: timestamptz + defaultOrg: uuid + defaultRole: String + displayName: String + email: citext + id: uuid + lastSeen: timestamptz + locale: String + phoneNumber: String + updatedAt: timestamptz +} + """ response of any mutation on the table "auth.users" """ @@ -6076,13 +10099,16 @@ type users_mutation_response { """Ordering options when selecting data from "auth.users".""" input users_order_by { activeMfaType: order_by - allowedOrgs_aggregate: organizations_aggregate_order_by + allowedOrgs_aggregate: memberships_aggregate_order_by + associatedGroups_aggregate: groups_aggregate_order_by avatarUrl: order_by createdAt: order_by + currentOrg: organizations_order_by defaultOrg: order_by defaultRole: order_by disabled: order_by displayName: order_by + dissociatedGroups_aggregate: groups_aggregate_order_by email: order_by emailVerified: order_by id: order_by @@ -6096,7 +10122,6 @@ input users_order_by { roles_aggregate: authUserRoles_aggregate_order_by securityKeys_aggregate: authUserSecurityKeys_aggregate_order_by updatedAt: order_by - userOrgRoles_aggregate: user_org_roles_aggregate_order_by userProviders_aggregate: authUserProviders_aggregate_order_by } @@ -6110,6 +10135,8 @@ input users_prepend_input { metadata: jsonb } +scalar users_scalar + """ select columns of table "auth.users" """ @@ -6123,6 +10150,9 @@ enum users_select_column { """column name""" createdAt + """column name""" + defaultOrg + """column name""" defaultRole @@ -6168,10 +10198,8 @@ input type for updating data in table "auth.users" """ input users_set_input { avatarUrl: String - defaultRole: String - disabled: Boolean + defaultOrg: uuid displayName: String - email: citext locale: String metadata: jsonb phoneNumber: String @@ -6193,6 +10221,7 @@ input users_stream_cursor_value_input { activeMfaType: String avatarUrl: String createdAt: timestamptz + defaultOrg: uuid defaultRole: String disabled: Boolean displayName: String diff --git a/apps/console/src/app.d.ts b/apps/console/src/app.d.ts index 5c958c582..4023023a4 100644 --- a/apps/console/src/app.d.ts +++ b/apps/console/src/app.d.ts @@ -1,16 +1,20 @@ // See https://kit.svelte.dev/docs/types#app // for information about these interfaces import type AI from '@aibrow/dom-types'; -type NhostClient = import('@nhost/nhost-js').NhostClient; -type ToastSettings = import('@skeletonlabs/skeleton').ToastSettings; -type AvailableLanguageTag = import('$i18n/runtime').AvailableLanguageTag; +// type NhostClient = import('@nhost/nhost-js').NhostClient; +import type { NhostClient } from '@nhost/nhost-js'; +import type { AvailableLanguageTag } from '$lib/paraglide/runtime'; +import type { ParaglideLocals } from '@inlang/paraglide-sveltekit'; +import type { ToastSettings } from '@skeletonlabs/skeleton'; declare global { namespace App { // houdini session interface Session { accessToken?: string; - // TODO: currentOrg?: string; // active user's org. default value is user's default_org + role?: string; + orgId?: string; + userId?: string; } namespace Superforms { type Message = Pick & { @@ -25,6 +29,9 @@ declare global { interface Locals { nhost: NhostClient; } + interface Locals { + paraglide: ParaglideLocals; + } interface PageData { // user?: Omit; /** @@ -53,5 +60,3 @@ declare global { readonly aibrow: typeof AI; } } - -export type {}; diff --git a/apps/console/src/hooks.client.ts b/apps/console/src/hooks.client.ts index a7177e201..7d209fa65 100644 --- a/apps/console/src/hooks.client.ts +++ b/apps/console/src/hooks.client.ts @@ -1,11 +1,33 @@ import { dev } from '$app/environment'; +import { NHOST_SESSION_KEY } from '$lib/constants'; import { Logger } from '@spectacular/utils'; -import type { HandleClientError } from '@sveltejs/kit'; +import type { ClientInit, HandleClientError } from '@sveltejs/kit'; -// Setup logger -if (!dev) { - Logger.enableProductionMode(); -} +/** + * Code in `init` method in `hooks.client.ts` will run one-time in browser, when the application starts up, + * making them useful for initializing database clients, logger, Sentry and so on. + */ +export const init: ClientInit = async () => { + console.log('in hooks.client.ts init:'); + // Setup logger + if (!dev) { + Logger.enableProductionMode(); + } + + // for debug cookies in development mode. + if (dev) { + // @ts-ignore + cookieStore.onchange = (event: CookieChangeEvent) => { + // console.log("cookie changed", {event}); + if (event.deleted[0] && event.deleted[0].name === NHOST_SESSION_KEY) { + console.log('cookie deleted', { deleted: event.deleted[0].value }); + } + if (event.changed[0] && event.changed[0].name === NHOST_SESSION_KEY) { + console.log('cookie changed', { changed: event.changed[0].value }); + } + }; + } +}; const log = new Logger('hooks:client'); diff --git a/apps/console/src/hooks.server.ts b/apps/console/src/hooks.server.ts index 8ee903efb..1a086e775 100644 --- a/apps/console/src/hooks.server.ts +++ b/apps/console/src/hooks.server.ts @@ -5,21 +5,23 @@ import * as flags from '$lib/flags'; import { i18n } from '$lib/i18n'; import { auth, guard, houdini, theme } from '$lib/server/hooks'; import { Logger, sleep } from '@spectacular/utils'; -import type { Handle, HandleFetch, HandleServerError } from '@sveltejs/kit'; +import type { Handle, HandleFetch, HandleServerError, ServerInit } from '@sveltejs/kit'; import { sequence } from '@sveltejs/kit/hooks'; import { createHandle } from '@vercel/flags/sveltekit'; import { GraphQLError } from 'graphql'; import { ZodError } from 'zod'; /** - * Code in hooks.server.ts will run when the application starts up, + * Code in `init` method in `hooks.server.ts` will run one-time on server, when the application starts up, * making them useful for initializing database clients, logger, Sentry and so on. */ - -// Setup logger -if (!dev) { - Logger.enableProductionMode(); -} +export const init: ServerInit = async () => { + console.log('in hooks.server.ts init:'); + // Setup logger + if (!dev) { + Logger.enableProductionMode(); + } +}; const log = new Logger('hooks:server'); diff --git a/apps/console/src/hooks.ts b/apps/console/src/hooks.ts index 81a481174..42e482f90 100644 --- a/apps/console/src/hooks.ts +++ b/apps/console/src/hooks.ts @@ -1,5 +1,13 @@ import { i18n } from '$lib/i18n'; +import { SerializableDate } from '$lib/types'; // export { dead_links as reroute } from "$lib/middleware/dead-links"; -import type { Reroute } from '@sveltejs/kit'; +import type { Reroute, Transport } from '@sveltejs/kit'; export const reroute = i18n.reroute() satisfies Reroute; + +export const transport: Transport = { + SerializableDate: { + encode: (value: unknown) => value instanceof SerializableDate && value.raw, + decode: (rawDate: string) => new SerializableDate(rawDate), + }, +}; diff --git a/apps/console/src/lib/api/search-rules.ts b/apps/console/src/lib/api/search-rules.ts index bdc0fddc0..e20fa18d5 100644 --- a/apps/console/src/lib/api/search-rules.ts +++ b/apps/console/src/lib/api/search-rules.ts @@ -1,4 +1,4 @@ -import { CachePolicy, type SearchRules$result, graphql, order_by } from '$houdini'; +import { CachePolicy, type SearchRulesAPI$result, graphql, order_by } from '$houdini'; import type { PartialGraphQLErrors, Subject } from '$lib/types'; import { Logger } from '@spectacular/utils'; import { type Result, err, ok } from 'neverthrow'; @@ -11,7 +11,7 @@ import { type Result, err, ok } from 'neverthrow'; const log = new Logger('api:rules:search'); const searchRules = graphql(` - query SearchRules( + query SearchRulesAPI( $where: rules_bool_exp $limit: Int = 50 $offset: Int = 0 @@ -22,7 +22,7 @@ const searchRules = graphql(` displayName description tags - annotations + metadata shared source sourcePort @@ -46,7 +46,7 @@ const orderBy = [{ updatedAt: order_by.desc_nulls_last }]; // TODO: throttle-debounce , prevent double calling, finish export async function searchRulesFn( displayNameTerm: string, -): Promise> { +): Promise> { if (displayNameTerm.length < 4) return ok([]); const where = { diff --git a/apps/console/src/lib/components/layout/avatar.svelte b/apps/console/src/lib/components/layout/avatar.svelte index 77de7d0c3..45d4cfefa 100644 --- a/apps/console/src/lib/components/layout/avatar.svelte +++ b/apps/console/src/lib/components/layout/avatar.svelte @@ -1,6 +1,13 @@ @@ -46,12 +66,10 @@ export let online = true;
  • -
    - -
    +
  • diff --git a/apps/console/src/lib/components/layout/go-to-top.svelte b/apps/console/src/lib/components/layout/go-to-top.svelte index a489fc46c..1c6269d3a 100644 --- a/apps/console/src/lib/components/layout/go-to-top.svelte +++ b/apps/console/src/lib/components/layout/go-to-top.svelte @@ -36,7 +36,7 @@ const showGotoTop = derived(scroll, ($scroll) => { class={cn( 'fixed bottom-10 right-10 z-50 text-white', 'transform transition hover:-translate-y-1 motion-reduce:transition-none motion-reduce:hover:transform-none', - 'variant-filled-secondary btn-icon btn-icon-lg', + 'variant-filled btn-icon btn-icon-lg', className, )} > diff --git a/apps/console/src/lib/components/layout/header.svelte b/apps/console/src/lib/components/layout/header.svelte index 0576d3f28..68df1c66c 100644 --- a/apps/console/src/lib/components/layout/header.svelte +++ b/apps/console/src/lib/components/layout/header.svelte @@ -6,12 +6,13 @@ import LangSwitch from '$lib/components/layout/lang-switch.svelte'; // import LoadingIndicatorSpinner from '$lib/components/layout/loading-indicator-spinner.svelte'; import LoadingIndicatorBar from '$lib/components/layout/loading-indicator-bar.svelte'; import { storeTheme } from '$lib/stores'; -import { online } from '$lib/stores/window'; import { getNhostClient } from '$lib/stores/nhost'; +import { online } from '$lib/stores/window'; import type { DrawerSettings, ModalSettings } from '@skeletonlabs/skeleton'; import { AppBar, LightSwitch, getDrawerStore, getModalStore, popup } from '@skeletonlabs/skeleton'; import { LogoIcon } from '@spectacular/skeleton/components/logos'; import type { SubmitFunction } from '@sveltejs/kit'; +import OrgSwitcher from './org-switcher.svelte'; import { BookText, ChevronDown, @@ -111,6 +112,8 @@ const setTheme: SubmitFunction = ({ formData }) => { + + - diff --git a/apps/console/src/routes/(app)/features/+page.svelte b/apps/console/src/routes/(app)/features/+page.svelte new file mode 100644 index 000000000..6fac87242 --- /dev/null +++ b/apps/console/src/routes/(app)/features/+page.svelte @@ -0,0 +1,22 @@ + + + + Datablocks | Settings + + + +
    +
    +

    Setting

    +

    Here you can change user settings

    +
    + +
    +

    AI Settings

    +

    Update AI model settings

    + +
    +
    + diff --git a/apps/console/src/routes/(app)/groups/+page.svelte b/apps/console/src/routes/(app)/groups/+page.svelte index 291181ba6..4bdb762bc 100644 --- a/apps/console/src/routes/(app)/groups/+page.svelte +++ b/apps/console/src/routes/(app)/groups/+page.svelte @@ -6,7 +6,7 @@ import { popup } from '@skeletonlabs/skeleton'; import { DebugShell } from '@spectacular/skeleton'; import * as Table from '@spectacular/skeleton/components/table'; import { Logger } from '@spectacular/utils'; -import { DataHandler } from '@vincjo/datatables'; +import { DataHandler } from '@vincjo/datatables/legacy'; import { CircleAlert, Plus, Search, UsersRound } from 'lucide-svelte'; import SuperDebug from 'sveltekit-superforms'; import { superForm } from 'sveltekit-superforms/client'; diff --git a/apps/console/src/routes/(app)/memberships/+page.gql b/apps/console/src/routes/(app)/memberships/+page.gql new file mode 100644 index 000000000..6a54cfb8d --- /dev/null +++ b/apps/console/src/routes/(app)/memberships/+page.gql @@ -0,0 +1,13 @@ +query Memberships($id: OrgIdFromSession!) { + memberships(where: { orgId: { _eq: $id } })@list(name: "Search_Memberships") { + userId + orgId + role + updatedAt + user { + displayName + avatarUrl + email + } + } +} diff --git a/apps/console/src/routes/(app)/memberships/+page.svelte b/apps/console/src/routes/(app)/memberships/+page.svelte new file mode 100644 index 000000000..89c1e5ae4 --- /dev/null +++ b/apps/console/src/routes/(app)/memberships/+page.svelte @@ -0,0 +1,111 @@ + + +
    +
    + +
    +
    +

    Team Members

    +

    + Manage your organization members and their roles. +

    +
    + + +
    + + +
    +
    + + +
    + +
    + + + {#if $Memberships.errors} + + {:else if $Memberships.data} + + {/if} +
    +
    + +{#if showAddForm} +
    +
    +
    +

    Add New Member

    +
    + {#if $Memberships.errors} + + {:else if $Memberships.data} + (showAddForm = false)} /> + {/if} +
    +
    +{/if} diff --git a/apps/console/src/routes/(app)/memberships/components/MemberForm.svelte b/apps/console/src/routes/(app)/memberships/components/MemberForm.svelte new file mode 100644 index 000000000..e230731f5 --- /dev/null +++ b/apps/console/src/routes/(app)/memberships/components/MemberForm.svelte @@ -0,0 +1,256 @@ + + +
    +
    +
    + + + {#if errors.email} +

    {errors.email}

    + {/if} +
    + +
    + + +
    +
    + +
    + + +
    +
    diff --git a/apps/console/src/routes/(app)/memberships/components/search-members-result.svelte b/apps/console/src/routes/(app)/memberships/components/search-members-result.svelte new file mode 100644 index 000000000..e635c9ba3 --- /dev/null +++ b/apps/console/src/routes/(app)/memberships/components/search-members-result.svelte @@ -0,0 +1,248 @@ + + +
    +
    + {#each $rows as member (member.user.id)} +
    +
    + {member.user.displayName} +
    +

    {member.user.displayName}

    +

    {member.user.email}

    +
    +
    + +
    + + {member.role} + + +
    + + + {#if showActionsFor === member.user.id} +
    +
    + Change role to: +
    + {#each ["org:admin", "org:member"] as role} + {#if role !== member.role} + + {/if} + {/each} +
    + +
    + {/if} +
    +
    +
    + {:else} +
    + No members found matching your search criteria. +
    + {/each} +
    +
    diff --git a/apps/console/src/routes/(app)/memberships/mutations.ts b/apps/console/src/routes/(app)/memberships/mutations.ts new file mode 100644 index 000000000..ece439596 --- /dev/null +++ b/apps/console/src/routes/(app)/memberships/mutations.ts @@ -0,0 +1,27 @@ +import { graphql } from '$houdini'; + +export const CreateMembership = graphql(` + mutation CreateMembership($data: memberships_insert_input!) { + insert_memberships_one(object: $data) { + ...Search_Memberships_insert @prepend + } + } + `); + +export const UpdateMembership = graphql(` + mutation UpdateMembership($orgId: uuid!, $userId: uuid!, $role: String!) { + update_memberships_by_pk(pk_columns: {orgId: $orgId, userId: $userId}, _set: { role: $role }) { + orgId + userId + role + } + } + `); + +export const DeleteMembership = graphql(` + mutation DeleteMembership($orgId: uuid!, $userId: uuid!) { + delete_memberships_by_pk(orgId: $orgId, userId: $userId) { + ...Search_Memberships_remove + } + } + `); diff --git a/apps/console/src/routes/(app)/network/components/network.svelte b/apps/console/src/routes/(app)/network/components/network.svelte index 10ab0c8a2..f9373d761 100644 --- a/apps/console/src/routes/(app)/network/components/network.svelte +++ b/apps/console/src/routes/(app)/network/components/network.svelte @@ -1,8 +1,8 @@ + + + Datablocks | Organizations + + + +
    +
    +

    Organizations

    +

    Update organization details

    +
    + + + {#if organizations_by_pk} +
    +

    User Details

    +

    Update your account information

    + +
    + {/if} +
    +
    diff --git a/apps/console/src/routes/(app)/organization/components/update-organization-details.svelte b/apps/console/src/routes/(app)/organization/components/update-organization-details.svelte new file mode 100644 index 000000000..258cd3dd2 --- /dev/null +++ b/apps/console/src/routes/(app)/organization/components/update-organization-details.svelte @@ -0,0 +1,424 @@ + + +
    + + + + {#if gqlErrors} + + {/if} + +
    +
    +
    Update Organization
    + +
    +
    +
    + + + Display Name + + Enter the org display name + + + +
    +
    + + + Description + + + Enter the org description + + +
    +
    + + + Avatar URL + + + Org's Avatar URL + + +
    +
    + + + Tags + + + Enter the tags and press Enter + + +
    +
    + + + Metadata + + + Enter the metadata + + +
    +
    + + + Allowed Emails + + + Type valid email address and press Enter + + +
    +
    + + + Allowed Email Domains + + + Type valid email domains name and press Enter + + +
    +
    + + + Blocked Emails + + + Type valid email address and press Enter + + +
    +
    + + + Blocked Email Domains + + + Type valid email domains name and press Enter + + +
    +
    +
    + + + + + Auto Enroll {$formData.autoEnroll ? "ON" : "OFF"} + + + + +
    + + + +
    +
    +
    +
    + +
    + + + +
    + +
    + +
    + +
    + + +
    +
    diff --git a/apps/console/src/routes/(app)/organizations/+page.gql b/apps/console/src/routes/(app)/organizations/+page.gql new file mode 100644 index 000000000..61a7b36ed --- /dev/null +++ b/apps/console/src/routes/(app)/organizations/+page.gql @@ -0,0 +1,20 @@ +query SearchOrganizations( + $where: organizations_bool_exp + $limit: Int = 50 + $offset: Int = 0 + $orderBy: [organizations_order_by!] = [{ updatedAt: desc_nulls_last }] +) @loading(cascade: true) { + organizations(where: $where, order_by: $orderBy, limit: $limit, offset: $offset) @list(name: "Search_Organizations") { + id + displayName + description + ownerId + updatedAt + avatarUrl + autoEnroll + allowedEmailDomains + allowedEmails + blockedEmailDomains + blockedEmails + } +} diff --git a/apps/console/src/routes/(app)/organizations/+page.svelte b/apps/console/src/routes/(app)/organizations/+page.svelte index da0150438..e8f5df65f 100644 --- a/apps/console/src/routes/(app)/organizations/+page.svelte +++ b/apps/console/src/routes/(app)/organizations/+page.svelte @@ -1,128 +1,44 @@ + + Datablocks | Organizations + + +
    -
    - - - -
    +
    +

    Organizations

    +

    Search, create, update, delete Organizations

    +
    + +
    + +
    + +
    + + + - - - - Organization - Description - Allowed_Emails - Allowed_Email_Domains - Action - - - - {#each $rows as row} - - - - - - - -
    -
    -

    Alert

    -

    - Are you sure you want to delete organization {row.organization}? -

    -
    - - -
    - {/each} - -
    {row.description} - {#each row.allowedEmails ?? [] as allowedEmail} - {allowedEmail} - {/each} - - {#each row.allowedEmailDomains ?? [] as allowedDomain} - {allowedDomain} - {/each} - -
    - -
    - -
    -
    -
    + {#if $SearchOrganizations.errors} + + {:else if $SearchOrganizations.data} + + {/if} +
    -
    - - -
    diff --git a/apps/console/src/routes/(app)/organizations/+page.ts b/apps/console/src/routes/(app)/organizations/+page.ts index acc79c10e..40dca947b 100644 --- a/apps/console/src/routes/(app)/organizations/+page.ts +++ b/apps/console/src/routes/(app)/organizations/+page.ts @@ -1,22 +1,46 @@ -import { GetOrganizationsStore } from '$houdini'; -import { error } from '@sveltejs/kit'; +import { order_by } from '$houdini'; +import { searchOrganizationSchema } from '$lib/schema/organization'; +import { Logger } from '@spectacular/utils'; +import { superValidate } from 'sveltekit-superforms'; +import { zod } from 'sveltekit-superforms/adapters'; +import type { BeforeLoadEvent, SearchOrganizationsVariables as Variables } from './$houdini'; -const getOrganizationsStore = new GetOrganizationsStore(); +const log = new Logger('organizations:search:browser'); +/** + * Note: `_houdini_beforeLoad` run first, then `_SearchOrganizationsVariables` then load GQL + */ -export async function load(event) { - const { errors, data } = await getOrganizationsStore.fetch({ - event, - blocking: true, - }); +/** + * Validate input and return `form` object which is send along with `data` to +page.svelte + */ +export async function _houdini_beforeLoad({ url }: BeforeLoadEvent) { + log.debug('in _houdini_beforeLoad'); + const form = await superValidate(url, zod(searchOrganizationSchema)); + if (!form.valid) return { status: 400, form }; + // if (!form.valid) return fail(400, { form }); + // if (!form.valid) throw error(400, 'invalid input'); + return { form }; +} - if (errors) { - for (const error of errors) { - console.log('list Organizations api error', error); - } +/** + * Set query Variables for +page.gql + */ +export const _SearchOrganizationsVariables: Variables = async (event) => { + const { url } = event; + log.debug('in _SearchOrganizationsVariables', { url }); + const { + data: { limit, offset, displayName }, + } = await superValidate(url, zod(searchOrganizationSchema)); + // const dataCopy = cleanClone(form.data, { empty: 'strip' }); + const orderBy = [{ updatedAt: order_by.desc_nulls_first }]; + const where = { + ...(displayName ? { displayName: { _ilike: `%${displayName}%` } } : {}), + }; - return { status: 500 }; - } - const OrganizationsList = data?.organizations; - if (!OrganizationsList) error(404, 'Organizations not found'); - return { OrganizationsList }; -} + return { + limit, + offset, + orderBy, + where, + }; +}; diff --git a/apps/console/src/routes/(app)/organizations/[id=uuid]/+page.gql b/apps/console/src/routes/(app)/organizations/[id=uuid]/+page.gql new file mode 100644 index 000000000..6c0317fa3 --- /dev/null +++ b/apps/console/src/routes/(app)/organizations/[id=uuid]/+page.gql @@ -0,0 +1,16 @@ +query OrganizationData1($id: uuid!) { + organizations_by_pk(id: $id) { + id + displayName + description + tags + metadata + ownerId + allowedEmailDomains @include(if: true) + allowedEmails @skip(if: false) + blockedEmailDomains + blockedEmails + autoEnroll + avatarUrl + } +} diff --git a/apps/console/src/routes/(app)/organizations/[id=uuid]/+page.svelte b/apps/console/src/routes/(app)/organizations/[id=uuid]/+page.svelte new file mode 100644 index 000000000..355b00439 --- /dev/null +++ b/apps/console/src/routes/(app)/organizations/[id=uuid]/+page.svelte @@ -0,0 +1,400 @@ + + + + Organizations + + + +
    +
    +

    Organizations

    +

    updte organization

    +
    + +
    + + + + {#if gqlErrors} + + {/if} + +
    +
    +
    Update Organization
    + +
    +
    +
    + + + Display Name + + Enter the org display name + + + +
    +
    + + + Description + + + Enter the org description + + +
    +
    + + + Avatar URL + + + Org's Avatar URL + + +
    +
    + + + Tags + + + Enter the tags and press Enter + + +
    +
    + + + Metadata + + + Enter the metadata + + +
    +
    + + + Allowed Emails + + + Type valid email address and press Enter + + +
    +
    + + + Allowed Email Domains + + + Type valid email domains name and press Enter + + +
    +
    + + + Blocked Emails + + + Type valid email address and press Enter + + +
    +
    + + + Blocked Email Domains + + + Type valid email domains name and press Enter + + +
    +
    +
    + + + + + Auto Enroll {$formData.autoEnroll ? "ON" : "OFF"} + + + + +
    + + + +
    +
    +
    +
    + +
    + + + +
    + +
    + +
    + +
    + + +
    +
    +
    diff --git a/apps/console/src/routes/(app)/organizations/components/search-organizations-form.svelte b/apps/console/src/routes/(app)/organizations/components/search-organizations-form.svelte new file mode 100644 index 000000000..8b5e44fe6 --- /dev/null +++ b/apps/console/src/routes/(app)/organizations/components/search-organizations-form.svelte @@ -0,0 +1,122 @@ + + + + + +{#if gqlErrors} + +{/if} + +
    + + + + + + +
    +
    + +
    + + + + + + +
    + + + Add Organization + +
    + + + + + + + + + +
    + +
    + +
    + +
    + + +
    diff --git a/apps/console/src/routes/(app)/organizations/components/search-organizations-result.svelte b/apps/console/src/routes/(app)/organizations/components/search-organizations-result.svelte new file mode 100644 index 000000000..28cb6fdb9 --- /dev/null +++ b/apps/console/src/routes/(app)/organizations/components/search-organizations-result.svelte @@ -0,0 +1,171 @@ + + +
    +
    +
    + + +
    + + + + Name + Owner + Updated + row.autoEnroll}>Auto Enroll + Allowed Email Domains + Allowed Emails + Blocked Email Domains + Blocked Emails + Delete + + + + + + row.autoEnroll} comparator={check.isLike} /> + + + + + + + + + + {#each $rows as row} + {#if row.id === PendingValue} + + + + + + + + + + + + {:else} + + + + + + + + + + + + {/if} + {/each} + +
    + {row.displayName} + + {@html row.ownerId}{row.autoEnroll}{@html row.allowedEmailDomains}{@html row.allowedEmails}{@html row.blockedEmailDomains}{@html row.blockedEmails} + +
    +
    + + +
    +
    +
    diff --git a/apps/console/src/routes/(app)/organizations/create/+page.server.ts b/apps/console/src/routes/(app)/organizations/create/+page.server.ts deleted file mode 100644 index 3c2bb4490..000000000 --- a/apps/console/src/routes/(app)/organizations/create/+page.server.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { goto } from '$app/navigation'; -import { CreateOrgStore } from '$houdini'; -import type { organizations_insert_input } from '$houdini'; -import { handleMessage } from '$lib/components/layout/toast-manager'; -import { organizationsCreateSchema as schema } from '$lib/schema/organization'; -import { getToastStore, popup } from '@skeletonlabs/skeleton'; -import { Logger, cleanClone } from '@spectacular/utils'; -import { fail } from '@sveltejs/kit'; -import type { GraphQLError } from 'graphql'; -import { redirect } from 'sveltekit-flash-message/server'; -import { zod } from 'sveltekit-superforms/adapters'; -import { setError, setMessage, superValidate } from 'sveltekit-superforms/server'; - -const log = new Logger('organizations.create.server'); -const createOrg = new CreateOrgStore(); -export const actions = { - default: async (event) => { - const { request } = event; - - console.log('server'); - const form = await superValidate(request, zod(schema)); - console.log('form -', form); - - if (!form.valid) return fail(400, { form }); - - log.debug('before cleanClone with strip:', form.data); - const dataCopy = cleanClone(form.data, { empty: 'strip' }); - log.debug('after cleanClone with strip:', dataCopy); - const payload: organizations_insert_input = { - ...dataCopy, - }; - const variables = { data: payload }; - const { errors, data } = await createOrg.mutate(variables, { - metadata: { logResult: true }, - event, - }); - if (errors) { - for (const error of errors) { - log.error('create rule api error', error); - if (error.message.includes('organization')) { - if (error.message.includes('Uniqueness violation')) { - setError(form, 'organization', 'Organization already exit'); - } else { - setError(form, '', (error as GraphQLError).message); - } - } - } - - return setMessage(form, { type: 'error', message: 'Create organizations failed' }); - } - const result = data?.insert_organizations_one; - - if (!result) - return setMessage(form, { type: 'error', message: 'Create policy failed: response empty' }, { status: 404 }); - throw redirect(302, '/organizations', null, event); - }, -}; diff --git a/apps/console/src/routes/(app)/organizations/create/+page.svelte b/apps/console/src/routes/(app)/organizations/create/+page.svelte index 796b12f98..5cbbf63de 100644 --- a/apps/console/src/routes/(app)/organizations/create/+page.svelte +++ b/apps/console/src/routes/(app)/organizations/create/+page.svelte @@ -1,35 +1,112 @@ - Organizations - + Organizations + +
    -

    Create Organization

    -
    +
    +

    Organizations

    +

    create organization

    +
    - +
    + -
    -
    - - -
    - - - -
    -
    -
    -
    -
    - - -
    - - -
    -
    - -
    -
    -
    - - -
    - - -
    -
    - -
    -
    -
    - - -
    - - -
    -
    - -
    -
    -
    - - - - - - + + {#if gqlErrors} + + {/if} + +
    +
    +
    Create Organization
    + +
    +
    +
    + + + Display Name + + Enter the org display name + + + +
    +
    + + + Description + + + Enter the org description + + +
    +
    + + + Avatar URL + + + Org's Avatar URL + + +
    +
    + + + Tags + + + Enter the tags and press Enter + + +
    +
    + + + Metadata + + + Enter the metadata + + +
    +
    + + + Allowed Emails + + + Type valid email address and press Enter + + +
    +
    + + + Allowed Email Domains + + + Type valid email domains name and press Enter + + +
    +
    + + + Blocked Emails + + + Type valid email address and press Enter + + +
    +
    + + + Blocked Email Domains + + + Type valid email domains name and press Enter + + +
    +
    +
    + + + + + Auto Enroll {$formData.autoEnroll ? "ON" : "OFF"} + + + + +
    + + + +
    +
    +
    +
    - - -
    - -
    - -
    - -
    - -
    +
    + + + +
    + +
    + +
    + +
    + + +
    +
    diff --git a/apps/console/src/routes/(app)/organizations/create/+page.ts b/apps/console/src/routes/(app)/organizations/create/+page.ts deleted file mode 100644 index 2ba7bfeef..000000000 --- a/apps/console/src/routes/(app)/organizations/create/+page.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { organizationsCreateSchema } from '$lib/schema/organization'; -import { superValidate } from 'sveltekit-superforms'; -import { zod } from 'sveltekit-superforms/adapters'; - -export async function load() { - const form = await superValidate(zod(organizationsCreateSchema)); - - return { form, organizationsCreateSchema }; -} diff --git a/apps/console/src/routes/(app)/organizations/mutations.ts b/apps/console/src/routes/(app)/organizations/mutations.ts new file mode 100644 index 000000000..f28611641 --- /dev/null +++ b/apps/console/src/routes/(app)/organizations/mutations.ts @@ -0,0 +1,17 @@ +import { graphql } from '$houdini'; + +export const UpdateOrganizationDetails = graphql(` + mutation UpdateOrganizationDetails($id: uuid!, $data: organizations_set_input!) { + update_organizations_by_pk(pk_columns: {id: $id}, _set: $data) { + displayName + } + } + `); + +export const DeleteOrganization = graphql(` + mutation DeleteOrganization($id: uuid! ) { + delete_organizations_by_pk(id: $id) { + ...Search_Organizations_remove + } + } + `); diff --git a/apps/console/src/routes/(app)/organizations/page.svelte.bak b/apps/console/src/routes/(app)/organizations/page.svelte.bak deleted file mode 100644 index ea09b0f1b..000000000 --- a/apps/console/src/routes/(app)/organizations/page.svelte.bak +++ /dev/null @@ -1,6 +0,0 @@ - - - - diff --git a/apps/console/src/routes/(app)/organizations/update/+page.server.ts b/apps/console/src/routes/(app)/organizations/update/+page.server.ts deleted file mode 100644 index 630147c08..000000000 --- a/apps/console/src/routes/(app)/organizations/update/+page.server.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { UpdateOrgsStore, type organizations_set_input } from '$houdini'; -import { updateOrganizationsSchema as schema } from '$lib/schema/organization'; -import { Logger, cleanClone } from '@spectacular/utils'; -import { fail } from '@sveltejs/kit'; -import type { GraphQLError } from 'graphql'; -import { redirect } from 'sveltekit-flash-message/server'; -import { zod } from 'sveltekit-superforms/adapters'; -import { setError, setMessage, superValidate } from 'sveltekit-superforms/server'; -const log = new Logger('subscriber.update.server'); -const updateOrgsStore = new UpdateOrgsStore(); -export const actions = { - default: async (event) => { - const { url, request } = event; - const organization = url.searchParams.get('organization'); - const form = await superValidate(request, zod(schema)); - log.debug({ form }); - - // superform validation - if (!form.valid) return fail(400, { form }); - - log.debug('before cleanClone with null:', form.data); - const dataCopy = cleanClone(form.data, { empty: 'null' }); - log.debug('after cleanClone with null:', dataCopy); - - const payload: organizations_set_input = { - ...dataCopy, - }; - const variables = { organization, data: payload }; - log.debug('UPDATE action variables:', variables); - const { errors, data } = await updateOrgsStore.mutate(variables, { - metadata: { logResult: true }, - event, - }); - if (errors) { - for (const error of errors) { - log.error('update organization api error', error); - if (error.message.includes('Uniqueness violation')) { - setError(form, '', (error as GraphQLError).message); - } - } - - return setMessage(form, { type: 'error', message: 'Update organization failed' }); - } - const result = data?.update_organizations_by_pk; - if (!result) - return setMessage( - form, - { type: 'error', message: 'Update organization failed: responce empty' }, - { status: 404 }, - ); - - const message = { - message: `Organization: ${result.organization} updated`, - dismissible: true, - duration: 10000, - type: 'success', - } as const; - throw redirect(302, '/organizations', message, event); - }, -}; diff --git a/apps/console/src/routes/(app)/organizations/update/+page.svelte b/apps/console/src/routes/(app)/organizations/update/+page.svelte deleted file mode 100644 index d85c06b6a..000000000 --- a/apps/console/src/routes/(app)/organizations/update/+page.svelte +++ /dev/null @@ -1,174 +0,0 @@ - - - - Organizations - - - -
    -
    - - - - -
    -
    - - -
    - - -
    -
    - -
    -
    -
    - - -
    - - -
    -
    - -
    -
    -
    - - -
    - - -
    -
    -
    -
    -
    - - -
    - - -
    -
    -
    -
    -
    - - - - - - - - - -
    - -
    - -
    - -
    - -
    -
    diff --git a/apps/console/src/routes/(app)/organizations/update/+page.ts b/apps/console/src/routes/(app)/organizations/update/+page.ts deleted file mode 100644 index a1a8af082..000000000 --- a/apps/console/src/routes/(app)/organizations/update/+page.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { CachePolicy, GetOrgsbyOrgStore } from '$houdini'; -import { updateOrganizationsSchema as schema } from '$lib/schema/organization'; -import { error } from '@sveltejs/kit'; -import type { GraphQLError } from 'graphql'; -import { superValidate } from 'sveltekit-superforms'; -import { zod } from 'sveltekit-superforms/adapters'; - -const getOrgsbyOrgStore = new GetOrgsbyOrgStore(); -export async function load({ params, url }) { - console.log(params, url.searchParams); - const organization = url.searchParams.get('organization'); - const variables = { organization }; // TODO: validate `id` - const { errors, data } = await getOrgsbyOrgStore.fetch({ - policy: CachePolicy.NetworkOnly, - variables, - }); - if (errors) error(400, errors[0] as GraphQLError); - const orgdata = data?.organizations_by_pk; - if (!orgdata) error(404, 'organization not found'); - const form = await superValidate(orgdata, zod(schema)); - return { orgdata, form }; -} diff --git a/apps/console/src/routes/(app)/policies/+page.gql b/apps/console/src/routes/(app)/policies/+page.gql index fc86465e3..ab03eed4c 100644 --- a/apps/console/src/routes/(app)/policies/+page.gql +++ b/apps/console/src/routes/(app)/policies/+page.gql @@ -4,6 +4,11 @@ query SearchPolicies( $offset: Int = 0 $orderBy: [policies_order_by!] = [{ updatedAt: desc_nulls_last }] ) @loading(cascade: true) { + policies_aggregate(where: $where) { + aggregate { + totalCount: count + } + } policies(where: $where, order_by: $orderBy, limit: $limit, offset: $offset) @list(name: "Search_Policies") { ... on policies { id diff --git a/apps/console/src/routes/(app)/policies/+page.svelte b/apps/console/src/routes/(app)/policies/+page.svelte index 7b15a932c..bc82d7f3d 100644 --- a/apps/console/src/routes/(app)/policies/+page.svelte +++ b/apps/console/src/routes/(app)/policies/+page.svelte @@ -1,10 +1,9 @@ - Policies + Datablocks | Policies @@ -30,15 +29,14 @@ $: ({ SearchPolicies } = data);
    - - - - - {#if $SearchPolicies.errors} - - {:else if $SearchPolicies.data} - - {/if} + + +
    diff --git a/apps/console/src/routes/(app)/policies/+page.ts b/apps/console/src/routes/(app)/policies/+page.ts index c94804431..eac934050 100644 --- a/apps/console/src/routes/(app)/policies/+page.ts +++ b/apps/console/src/routes/(app)/policies/+page.ts @@ -1,12 +1,12 @@ import { order_by } from '$houdini'; import { policySearchSchema } from '$lib/schema/policy'; -import { Logger, sleep } from '@spectacular/utils'; +import { Logger } from '@spectacular/utils'; import { error, fail } from '@sveltejs/kit'; import { superValidate } from 'sveltekit-superforms'; import { zod } from 'sveltekit-superforms/adapters'; import type { BeforeLoadEvent, SearchPoliciesVariables as Variables } from './$houdini'; -const log = new Logger('policies:search-ts:browser'); +const log = new Logger('policies:search:browser'); /** * Note: `_houdini_beforeLoad` run first, then `_SearchPoliciesVariables` then load GQL */ diff --git a/apps/console/src/routes/(app)/policies/components/search-policies-form.svelte b/apps/console/src/routes/(app)/policies/components/search-policies-form.svelte index bcc1634d4..a6a7be93c 100644 --- a/apps/console/src/routes/(app)/policies/components/search-policies-form.svelte +++ b/apps/console/src/routes/(app)/policies/components/search-policies-form.svelte @@ -13,8 +13,8 @@ import { Logger } from '@spectacular/utils'; import * as Form from 'formsnap'; import { LoaderIcon, MoreHorizontalIcon, ScaleIcon, SearchIcon, ShieldCheckIcon } from 'lucide-svelte'; import type { FormEventHandler } from 'svelte/elements'; +import { queryParameters, ssp } from 'sveltekit-search-params'; import SuperDebug, { superForm, type SuperValidated } from 'sveltekit-superforms'; -import { ssp, queryParameters } from 'sveltekit-search-params'; const log = new Logger('policies:search-form:browser'); @@ -121,7 +121,9 @@ $: loadingState.setFormLoading($delayed); - +{#if gqlErrors} + +{/if}
    -import { PendingValue, type SearchPolicies$result, graphql } from '$houdini'; +import { + type DeletePolicy$result, + type DeleteRule$result, + PendingValue, + type SearchPolicies$result, + cache, + fragment, + graphql, + type SearchPoliciesFragment, +} from '$houdini'; import { handleMessage } from '$lib/components/layout/toast-manager'; import { loaded } from '$lib/graphql/loading'; import { getLoadingState } from '$lib/stores/loading'; import { getToastStore } from '@skeletonlabs/skeleton'; import { DateTime } from '@spectacular/skeleton/components'; import * as Table from '@spectacular/skeleton/components/table'; -import { Logger, sleep } from '@spectacular/utils'; -import { DataHandler, type Row, check } from '@vincjo/datatables'; +import { Logger } from '@spectacular/utils'; +import { DataHandler, type Row, check } from '@vincjo/datatables/legacy'; import { Trash2 } from 'lucide-svelte'; import type { MouseEventHandler } from 'svelte/elements'; +import { message } from 'sveltekit-superforms'; +import { DeletePolicy, DeleteRule } from '../mutations'; const log = new Logger('policies:search-results:browser'); // Variables -export let data: SearchPolicies$result; -let { policies } = data; -$: ({ policies } = data); +export let policies: SearchPolicies$result['policies']; const toastStore = getToastStore(); const loadingState = getLoadingState(); @@ -28,49 +37,54 @@ const rows = handler.getRows(); // Functions /** * Delete Polcy action + * FIXME: Cache bust: `policies {id @policies_delete }` is empty !!! */ let isDeleting = false; -const deletePolicy = graphql(` - mutation DeletePolicy( - $policyId: uuid! - $ruleId: uuid! - $deletedAt: timestamptz! - ) { - update_policies_by_pk( - pk_columns: { id: $policyId } - _set: { deletedAt: $deletedAt } - ) { - id - ...Search_Policies_remove - } - update_rules( - where: { shared: { _eq: false }, id: { _eq: $ruleId } } - _set: { deletedAt: $deletedAt } - ) { - affected_rows - # ...Search_Rules_remove - } - } - `); + const handleDelete: MouseEventHandler = async (event) => { - const { policyId, ruleId, displayName } = event.currentTarget.dataset; - if (!policyId || !ruleId || !displayName) { + const { id, ruleId, ruleShared, displayName } = event.currentTarget.dataset; + if (!id || !ruleId || !displayName) { log.error('Misconfiguration: did you mess adding `data-id/data-rule-id/data-display-name` attributes?'); return; } // before isDeleting = true; - await sleep(1300); - const deletedAt = new Date(); - const { data, errors: gqlErrors } = await deletePolicy.mutate({ - policyId, - ruleId, - deletedAt, - }); - if (gqlErrors) { + let deletedId: string | undefined; + let message: string | undefined; + let error: string | undefined; + // Delete role if not shared, this will cascade delete the policy as well. + if (ruleShared === 'false') { + const { data, errors: gqlErrors } = await DeleteRule.mutate({ + id: ruleId, + }); + // TODO: `policyId @policies_delete` ??? + // WORKAROUND: Manuvally delete the policy from cache as policy is deleted via cascade by database when parent `rule` is deleted. + const policy = cache.get('policies', { id }); + policy.delete(); + + if (gqlErrors) { + error = `Error deleteing policy: "${displayName}", cause: ${gqlErrors[0].message} `; + } else { + message = `Policy and associated rule: "${displayName}" deleted`; + deletedId = data?.delete_rules_by_pk?.id; + } + } else { + const { data, errors: gqlErrors } = await DeletePolicy.mutate({ + id, + }); + + if (gqlErrors) { + error = `Error deleteing policy: "${displayName}", cause: ${gqlErrors[0].message} `; + } else { + message = `Policy "${displayName}" deleted`; + deletedId = data?.delete_policies_by_pk?.id; + } + } + + if (error) { handleMessage( { - message: `Error deleteing policy: "${displayName}", cause: ${gqlErrors[0].message} `, + message: error, hideDismiss: false, timeout: 10000, type: 'error', @@ -79,20 +93,11 @@ const handleDelete: MouseEventHandler = async (event) => { ); return; } - if (data?.update_policies_by_pk && data?.update_rules?.affected_rows) { - handleMessage( - { - message: `Policy and associated rule: "${displayName}" deleted`, - hideDismiss: false, - timeout: 10000, - type: 'success', - }, - toastStore, - ); - } else if (data?.update_policies_by_pk) { + + if (deletedId && message) { handleMessage( { - message: `Policy "${displayName}" deleted`, + message, hideDismiss: false, timeout: 10000, type: 'success', @@ -102,7 +107,7 @@ const handleDelete: MouseEventHandler = async (event) => { } else { handleMessage( { - message: `Policy not found for ID: ${policyId}`, + message: `Policy not found for ID: ${id}`, hideDismiss: false, timeout: 50000, type: 'error', @@ -202,8 +207,9 @@ $: loadingState.setFormLoading(isDeleting); +
    + + + + + Active {$formData.active ? "ON" : "OFF"} + + + + +
    + + + +
    @@ -881,12 +841,14 @@ $: loadingState.setFormLoading($delayed); status={false} data={{ message: $message, + isTainted: isTainted, submitting: $submitting, delayed: $delayed, + timeout: $timeout, }} />
    - +

    @@ -900,46 +862,41 @@ $: loadingState.setFormLoading($delayed); diff --git a/apps/console/src/routes/(app)/policies/mutations.ts b/apps/console/src/routes/(app)/policies/mutations.ts new file mode 100644 index 000000000..6bf485dc2 --- /dev/null +++ b/apps/console/src/routes/(app)/policies/mutations.ts @@ -0,0 +1,33 @@ +import { graphql } from '$houdini'; + +// FIXME: ...Search_Rules_insert @when(shared: false) +// `shared` has to be the arguments of the field marked with @list ??? +export const CreatePolicy = graphql(` + mutation CreatePolicy($data: policies_insert_input!) { + insert_policies_one(object: $data) { + ...Search_Policies_insert @prepend + rule { + ...Search_Rules_insert @when(shared: false) @prepend + } + } + } + `); + +export const DeleteRule = graphql(` + mutation DeleteRule($id: uuid!) { + delete_rules_by_pk(id: $id) { + ...Search_Rules_remove + policies { + id @policies_delete + } + } + } + `); + +export const DeletePolicy = graphql(` + mutation DeletePolicy($id: uuid!) { + delete_policies_by_pk(id: $id) { + ...Search_Policies_remove + } + } + `); diff --git a/apps/console/src/routes/(app)/profile/+page.gql b/apps/console/src/routes/(app)/profile/+page.gql index fc159279d..a984e6c4d 100644 --- a/apps/console/src/routes/(app)/profile/+page.gql +++ b/apps/console/src/routes/(app)/profile/+page.gql @@ -2,13 +2,13 @@ # We are leveraging Houdini's Optimistic updates for this usecase # HINT: If you find yourself wanting @loading on every field in your document (fragment or query), # you can put it on the document definition to implicitly add it to every field. -# ex: query GetUser($userId: uuid!) @loading @role(name: "me") -query GetUser($userId: uuid!) @role(name: "me") { +# ex: query ProfileData($id: UserIdFromSession!) @loading @role(name: "me") +query ProfileData($id: UserIdFromSession!) @role(name: "me") { # get all fragments needed for profile page. - user(id: $userId) @loading(cascade: true) { + user(id: $id) @loading(cascade: true) { email ...UserDetailsFragment - ...UserOrgRolesFragment + ...MembershipsFragment ...PersonalAccessTokensFragment ...AuthProvidersFragment ...SecurityKeysFragment diff --git a/apps/console/src/routes/(app)/profile/+page.svelte b/apps/console/src/routes/(app)/profile/+page.svelte index f870b1f60..ce4fcfe4d 100644 --- a/apps/console/src/routes/(app)/profile/+page.svelte +++ b/apps/console/src/routes/(app)/profile/+page.svelte @@ -3,6 +3,7 @@ import { page } from '$app/stores'; import { PendingValue } from '$houdini'; import { Meta } from '$lib/components'; import { allLoaded, loaded, loading } from '$lib/graphql/loading'; +import MaybeError from '$lib/components/layout/maybe-error.svelte'; import { GraphQLErrors } from '@spectacular/skeleton/components'; import type { PageData } from './$houdini'; import ChangeEmailForm from './components/change-email.svelte'; @@ -15,7 +16,7 @@ import PersonalAccessTokens from './components/personal-access-tokens.svelte'; import SecurityKeyForm from './components/security-key-form.svelte'; import SecurityKeys from './components/security-keys.svelte'; import UserDetails from './components/user-details.svelte'; -import UserOrgRoles from './components/user-org-roles.svelte'; +import Memberships from './components/memberships.svelte'; /** * Loading states example: https://houdini-intro.pages.dev/ @@ -28,8 +29,8 @@ export let data: PageData; // Functions // Reactivity -let { GetUser } = data; -$: ({ GetUser } = data); +let { ProfileData } = data; +$: ({ ProfileData } = data); $: meta = { title: 'Datablocks | Profile', @@ -49,10 +50,12 @@ $: meta = {

    Update your profile details

    - {#if $GetUser.errors} - - {:else if $GetUser.data?.user} - {@const user = $GetUser.data.user} + + {#if user} {@const { email } = user}
    @@ -62,9 +65,9 @@ $: meta = {
    -

    User Org Roles

    +

    Memberships

    Orgs and roles you are granted

    - +
    @@ -122,4 +125,5 @@ $: meta = {
    {/if} +
    diff --git a/apps/console/src/routes/(app)/profile/+page.ts b/apps/console/src/routes/(app)/profile/+page.ts deleted file mode 100644 index c935ca9bb..000000000 --- a/apps/console/src/routes/(app)/profile/+page.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { load_GetUser } from '$houdini'; -import { Logger } from '@spectacular/utils'; -import { error } from '@sveltejs/kit'; -import type { PageLoad, GetUserVariables as Variables } from './$houdini'; - -const log = new Logger('user.profile.browser'); - -export const _GetUserVariables: Variables = async (event) => { - const { session } = await event.parent(); - const userId = session?.user.id; - if (!userId) { - log.error('not authenticated'); - throw error(400, 'not authenticated'); - } - return { userId }; -}; - -/** - * if you need more customizations - */ -// export const load: PageLoad = async (event) => { -// const { session } = await event.parent(); -// const userId = session?.user.id; -// if (!userId) { -// log.error('not authenticated'); -// throw error(400, 'not authenticated'); -// } -// // this load function will be rerun if manually invalidated elsewhere by calling `invalidate('app:profile')`. -// // event.depends('app:profile'); -// return { -// ...(await load_GetUser({ -// event, -// variables: { -// userId, -// }, -// metadata: { -// useRole: 'me', -// }, -// })), -// }; -// }; diff --git a/apps/console/src/routes/(app)/profile/components/change-email.svelte b/apps/console/src/routes/(app)/profile/components/change-email.svelte index 518d68da9..fe7477fe6 100644 --- a/apps/console/src/routes/(app)/profile/components/change-email.svelte +++ b/apps/console/src/routes/(app)/profile/components/change-email.svelte @@ -72,7 +72,7 @@ const { delayed, timeout, tainted, - posted, + isTainted, allErrors, enhance, } = form; @@ -104,7 +104,7 @@ $: loadingState.setFormLoading($delayed); placeholder={m.profile_forms_change_email_placeholder()} /> +
    + + + +
    - + - + +
    + +
    + +
    + +
    + +
    diff --git a/apps/console/src/routes/(app)/profile/mutations.ts b/apps/console/src/routes/(app)/profile/mutations.ts new file mode 100644 index 000000000..0913082ac --- /dev/null +++ b/apps/console/src/routes/(app)/profile/mutations.ts @@ -0,0 +1,13 @@ +import { graphql } from '$houdini'; + +export const UpdateUserDetails = graphql(` + mutation UpdateUserDetails($id: uuid!, $data: users_set_input!) { + updateUser(pk_columns: { id: $id }, _set: $data) { + displayName + phoneNumber + locale + note: metadata(path: "note") + avatarUrl + } + } + `); diff --git a/apps/console/src/routes/(app)/reports/+page.svelte b/apps/console/src/routes/(app)/reports/+page.svelte index 5bed53761..e2823bc08 100644 --- a/apps/console/src/routes/(app)/reports/+page.svelte +++ b/apps/console/src/routes/(app)/reports/+page.svelte @@ -1,8 +1,8 @@ diff --git a/apps/console/src/routes/(app)/reports/components/dagre.svelte b/apps/console/src/routes/(app)/reports/components/dagre.svelte index 07712715e..72b1c53e1 100644 --- a/apps/console/src/routes/(app)/reports/components/dagre.svelte +++ b/apps/console/src/routes/(app)/reports/components/dagre.svelte @@ -1,7 +1,7 @@ @@ -15,7 +15,7 @@ $: rules = $RulesData.data?.rules ?? [];

    Rules

    - {#if $RulesData.fetching} + {#if $SearchRulesData.fetching} loading... {:else} done.... diff --git a/apps/console/src/routes/(app)/rules/+page.ts b/apps/console/src/routes/(app)/rules/+page.ts new file mode 100644 index 000000000..ee801c077 --- /dev/null +++ b/apps/console/src/routes/(app)/rules/+page.ts @@ -0,0 +1,48 @@ +import { order_by } from '$houdini'; +import { searchRuleSchema } from '$lib/schema/rule'; +import { Logger } from '@spectacular/utils'; +import { error, fail } from '@sveltejs/kit'; +import { superValidate } from 'sveltekit-superforms'; +import { zod } from 'sveltekit-superforms/adapters'; +import type { BeforeLoadEvent, SearchRulesVariables as Variables } from './$houdini'; + +const log = new Logger('rules:search:browser'); +/** + * Note: `_houdini_beforeLoad` run first, then `_SearchRulesVariables` then load GQL + */ + +/** + * Validate input and return `form` object which is send along with `data` to +page.svelte + */ +export async function _houdini_beforeLoad({ url }: BeforeLoadEvent) { + log.debug('in _houdini_beforeLoad'); + const form = await superValidate(url, zod(searchRuleSchema)); + if (!form.valid) return { status: 400, form }; + // if (!form.valid) return fail(400, { form }); + // if (!form.valid) throw error(400, 'invalid input'); + return { form }; +} + +/** + * Set query Variables for +page.gql + */ +export const _SearchRulesVariables: Variables = async (event) => { + const { url } = event; + log.debug('in _SearchRulesVariables', { url }); + const { + data: { limit, offset, displayName, shared }, + } = await superValidate(url, zod(searchRuleSchema)); + // const dataCopy = cleanClone(form.data, { empty: 'strip' }); + const orderBy = [{ updatedAt: order_by.desc_nulls_first }]; + const where = { + ...(displayName ? { displayName: { _ilike: `%${displayName}%` } } : {}), + ...(shared !== undefined ? { shared: { _eq: shared } } : {}), + }; + + return { + limit, + offset, + orderBy, + where, + }; +}; diff --git a/apps/console/src/routes/(app)/rules/get.gql.bak b/apps/console/src/routes/(app)/rules/get.gql.bak new file mode 100644 index 000000000..310a1e31c --- /dev/null +++ b/apps/console/src/routes/(app)/rules/get.gql.bak @@ -0,0 +1,44 @@ +query SearchRules( + $limit: Int = 50 + $offset: Int = 0 + $orderBy: [rules_order_by!] = [{ updatedAt: desc_nulls_last }] + $shared: Boolean = true + $displayName: String = "%%" +) @loading(cascade: true) { + rules( + limit: $limit + offset: $offset + order_by: $orderBy + where: { shared: { _eq: $shared }, displayName: { _ilike: $displayName } } + ) @list(name: "Search_Rules") { + action + metadata + appId + description + destination + destinationPort + direction + displayName + protocol + shared + source + sourcePort + throttleRate + updatedAt + updatedBy + weight + ...RuleCardFields + } +} + +# sample to delete cache +mutation DeleteRule($id: ID!) { + deletePage(id: $id) { + ... on MutationDeletePageSuccess { + data { + title + id @Rule_delete + } + } + } +} diff --git a/apps/console/src/routes/(app)/rules/rule.svelte b/apps/console/src/routes/(app)/rules/rule.svelte index 6d57c1134..75ac2447b 100644 --- a/apps/console/src/routes/(app)/rules/rule.svelte +++ b/apps/console/src/routes/(app)/rules/rule.svelte @@ -11,13 +11,13 @@ $: data = fragment( id createdAt updatedAt - organization + orgId tags } `), ); -$: ({ id, createdAt, updatedAt, organization, tags } = $data); +$: ({ id, createdAt, updatedAt, orgId, tags } = $data);
    {id}

    {createdAt}

    {updatedAt}

    -

    {organization}

    +

    {orgId}

    {tags}

    diff --git a/apps/console/src/routes/(app)/segments/components/layered-graph-layout.svelte b/apps/console/src/routes/(app)/segments/components/layered-graph-layout.svelte index 2c5ff9228..f2ed65f0a 100644 --- a/apps/console/src/routes/(app)/segments/components/layered-graph-layout.svelte +++ b/apps/console/src/routes/(app)/segments/components/layered-graph-layout.svelte @@ -1,7 +1,7 @@ +
    @@ -19,27 +25,25 @@ $: handler.setRows(UsersList); - Avatar - First name - EMail - Organization + Avatar + Name + OrganizationRole - Edit + Email + Phone + Last Seen {#each $rows as row} - - - - - + + + + + + {/each} diff --git a/apps/console/src/routes/(app)/users/+page.ts b/apps/console/src/routes/(app)/users/+page.ts deleted file mode 100644 index c8a3410d8..000000000 --- a/apps/console/src/routes/(app)/users/+page.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { GetUsersStore } from '$houdini'; -import { error } from '@sveltejs/kit'; - -const getUsersStore = new GetUsersStore(); - -export async function load(event) { - const { errors, data } = await getUsersStore.fetch({ - event, - blocking: true, - }); - - if (errors) { - for (const error of errors) { - console.log('list subscriber api error', error); - } - return { status: 500 }; - } - const UsersList = data?.users; - if (!UsersList) error(404, 'Users not found'); - return { UsersList }; -} diff --git a/apps/console/src/routes/(app)/users/[id=uuid]/+page.server.ts b/apps/console/src/routes/(app)/users/[id=uuid]/+page.server.ts deleted file mode 100644 index b22da0495..000000000 --- a/apps/console/src/routes/(app)/users/[id=uuid]/+page.server.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { UpdateRoleStore, type users_set_input } from '$houdini'; -import { updateUserSchema as schema, userSchema } from '$lib/schema/delegation'; -import { Logger, cleanClone } from '@spectacular/utils'; -import { fail } from '@sveltejs/kit'; -import type { GraphQLError } from 'graphql'; -import { redirect } from 'sveltekit-flash-message/server'; -import { zod } from 'sveltekit-superforms/adapters'; -import { setError, setMessage, superValidate } from 'sveltekit-superforms/server'; -const log = new Logger('user.update.server'); -const uuidSchema = userSchema.shape.id; -const updateRoleStore = new UpdateRoleStore(); -export const actions = { - default: async (event) => { - const { params, request } = event; - const id = uuidSchema.parse(params.id); - - const form = await superValidate(request, zod(schema)); - log.debug({ form }); - - // superform validation - if (!form.valid) return fail(400, { form }); - - log.debug('before cleanClone with null:', form.data); - const dataCopy = cleanClone(form.data, { empty: 'null' }); - log.debug('after cleanClone with null:', dataCopy); - const payload: users_set_input = { - ...dataCopy, - }; - const variables = { id: id, data: payload }; - log.debug('UPDATE action variables:', variables); - const { errors, data } = await updateRoleStore.mutate(variables, { - metadata: { logResult: true }, - event, - }); - if (errors) { - for (const error of errors) { - log.error('update subscriber api error', error); - if (error.message.includes('Uniqueness violation')) { - setError(form, 'defaultRole', 'Role is already taken'); - } else { - setError(form, '', (error as GraphQLError).message); - } - } - return setMessage(form, { type: 'error', message: 'Update user failed' }); - } - - throw redirect(302, '/users', null, event); - }, -}; diff --git a/apps/console/src/routes/(app)/users/[id=uuid]/+page.svelte b/apps/console/src/routes/(app)/users/[id=uuid]/+page.svelte index 0cb3bd7ac..c65158e7c 100644 --- a/apps/console/src/routes/(app)/users/[id=uuid]/+page.svelte +++ b/apps/console/src/routes/(app)/users/[id=uuid]/+page.svelte @@ -1,8 +1 @@ - - - - +

    TODO

    diff --git a/apps/console/src/routes/(app)/users/[id=uuid]/+page.ts b/apps/console/src/routes/(app)/users/[id=uuid]/+page.ts deleted file mode 100644 index 1651d7dd5..000000000 --- a/apps/console/src/routes/(app)/users/[id=uuid]/+page.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { CachePolicy, GetUserByIdStore } from '$houdini'; -import { updateUserSchema as schema } from '$lib/schema/delegation'; -import { error } from '@sveltejs/kit'; -import type { GraphQLError } from 'graphql'; -import { superValidate } from 'sveltekit-superforms'; -import { zod } from 'sveltekit-superforms/adapters'; - -const getUsersByIdStore = new GetUserByIdStore(); -export const load = async (event) => { - const { - params: { id }, - } = event; - const variables = { id }; // TODO: validate `id` - const { errors, data } = await getUsersByIdStore.fetch({ - event, - blocking: true, - policy: CachePolicy.NetworkOnly, - variables, - }); - if (errors) error(400, errors[0] as GraphQLError); - const user = data?.user; - const orgRoles = data?.user_org_roles; - const organizations = data?.organizations; - const roles = data?.authUserRoles; - console.log('user:', user); - if (!user) error(404, 'User not found'); - const form = await superValidate(user, zod(schema)); - return { form, user, orgRoles, organizations, roles }; -}; diff --git a/apps/console/src/routes/(app)/users/[id=uuid]/components/delegation.svelte b/apps/console/src/routes/(app)/users/[id=uuid]/components/delegation.svelte deleted file mode 100644 index 180cf3483..000000000 --- a/apps/console/src/routes/(app)/users/[id=uuid]/components/delegation.svelte +++ /dev/null @@ -1,383 +0,0 @@ - - -
    -
    -

    - {data.user.displayName} -

    -
    - -
    - -
    -
    {row.displayName}{row.email}{row.metadata?.default_org}{row.defaultRole} - - {row?.displayName}{row?.currentOrg?.displayName}{row?.defaultRole}{row?.email}{row?.phoneNumber}{row?.lastSeen}
    - - - Organization - Allowed Roles - Edit - - - - {#each $rows as row} - - - - - -
    -
    -

    Update Action

    - - - - - -
    -
    - {/each} - -
    - {#if row[0] == def_org} - def - {/if}{row[0]} -
    {#each row[1] as tag} - - {#if tag == data.orgRoles.find((role) => role.isDefaultRole === true && role.organization === row[0]).role} - - {/if} - {tag} -   - {/each}
    - -
    -
    -
    - - -
    -
    - -
    -
    -

    Add Action

    - - - {#if $newroles[1]} - - {/if} - - -
    -
    diff --git a/apps/console/src/routes/(app)/users/[id=uuid]/components/user-details.svelte b/apps/console/src/routes/(app)/users/[id=uuid]/components/user-details.svelte deleted file mode 100644 index e6d9b472c..000000000 --- a/apps/console/src/routes/(app)/users/[id=uuid]/components/user-details.svelte +++ /dev/null @@ -1,200 +0,0 @@ - - -
    -
    -

    - User Details -

    - -
    - -
    - - - - -
    -
    - - -
    - - - -
    -
    -
    -
    -
    - - -
    - - - -
    -
    -
    -
    -
    - - -
    - - - -
    -
    -
    -
    -
    - - -
    - - - -
    -
    -
    -
    -
    - - - - - - - - - - -
    - -
    - -
    - -
    - -
    -
    - - diff --git a/apps/console/src/routes/(auth)/+layout.server.ts b/apps/console/src/routes/(auth)/+layout.server.ts new file mode 100644 index 000000000..f3239d640 --- /dev/null +++ b/apps/console/src/routes/(auth)/+layout.server.ts @@ -0,0 +1,13 @@ +import { env as secrets } from '$env/dynamic/private'; +import { enableBotProtection, showMagicLinkLogin, showSocialLogin } from '$lib/flags'; +import { Logger } from '@spectacular/utils'; + +const log = new Logger('server:auth:signin'); + +export const load = async () => { + const showBotProtection = await enableBotProtection(); + const showMagicLink = await showMagicLinkLogin(); + const showSocial = await showSocialLogin(); + + return { flags: { showBotProtection, showMagicLink, showSocial } }; // TODO: use flags +}; diff --git a/apps/console/src/routes/(auth)/+layout.svelte b/apps/console/src/routes/(auth)/+layout.svelte index af047d75f..7995642ce 100644 --- a/apps/console/src/routes/(auth)/+layout.svelte +++ b/apps/console/src/routes/(auth)/+layout.svelte @@ -1,11 +1,49 @@
    + {#if data.flags.showBotProtection} +
    + +
    + {/if}
    diff --git a/apps/console/src/routes/(auth)/reset/+page.server.ts b/apps/console/src/routes/(auth)/reset/+page.server.ts deleted file mode 100644 index b5edca8cf..000000000 --- a/apps/console/src/routes/(auth)/reset/+page.server.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { i18n } from '$lib/i18n'; -import { resetPasswordSchema } from '$lib/schema/user'; -import { limiter } from '$lib/server/limiter/limiter'; -import { Logger, sleep } from '@spectacular/utils'; -import { fail } from '@sveltejs/kit'; -import { redirect as redirectWithFlash } from 'sveltekit-flash-message/server'; -import { message, setError, superValidate } from 'sveltekit-superforms'; -import { zod } from 'sveltekit-superforms/adapters'; - -const log = new Logger('auth:reset:server'); - -export const load = async (event) => { - const { - locals: { nhost }, - } = event; - /** - * Preflight prevents direct posting. If preflight option for the - * cookie limiter is true and this function isn't called before posting, - * request will be limited. - * - * Remember to await, so the cookie will be set before returning! - */ - await limiter.cookieLimiter?.preflight(event); - - const isAuthenticated = nhost.auth.isAuthenticated(); - if (isAuthenticated) redirectWithFlash(302, i18n.resolveRoute('/dashboard')); -}; - -export const actions = { - default: async (event) => { - log.debug('in reset action'); - const { - request, - cookies, - locals: { - paraglide: { lang }, - nhost, - }, - } = event; - - const form = await superValidate(request, zod(resetPasswordSchema)); - - const { limited, retryAfter } = await limiter.check(event); - if (limited) { - event.setHeaders({ - 'Retry-After': retryAfter.toString(), - }); - return message( - form, - { - type: 'error', - message: `Rate limit has been reached. Please retry after ${retryAfter} seconds`, - }, - { status: 429 }, - ); - } - - const origin = new URL(event.url).origin; - - if (!form.valid) return fail(400, { form }); - const { email } = form.data; - const { error } = await nhost.auth.resetPassword({ - email, - options: { - redirectTo: `${origin}/profile`, - }, - }); - if (error) { - log.error(error); - return setError(form, `Failed to send reset password instructions: ${error.message}`, { status: 409 }); // 424 ??? - } - - return message(form, { type: 'success', message: 'Send reset password instructions to email provided' }); - }, -}; diff --git a/apps/console/src/routes/(auth)/reset/+page.svelte b/apps/console/src/routes/(auth)/reset/+page.svelte index ad5dc3d31..72d552744 100644 --- a/apps/console/src/routes/(auth)/reset/+page.svelte +++ b/apps/console/src/routes/(auth)/reset/+page.svelte @@ -1,42 +1,77 @@ diff --git a/apps/console/src/routes/(auth)/signin/components/magic-link.svelte b/apps/console/src/routes/(auth)/signin/components/magic-link.svelte deleted file mode 100644 index b98b545ee..000000000 --- a/apps/console/src/routes/(auth)/signin/components/magic-link.svelte +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -
    -
    - - - {m.auth_forms_email_label()} - - - - -
    -
    - -
    -
    - - - - diff --git a/apps/console/src/routes/(auth)/signin/components/password.svelte b/apps/console/src/routes/(auth)/signin/components/password.svelte index 6fe4d64e7..dbe249e9b 100644 --- a/apps/console/src/routes/(auth)/signin/components/password.svelte +++ b/apps/console/src/routes/(auth)/signin/components/password.svelte @@ -1,40 +1,71 @@ -
    +
    @@ -128,7 +158,6 @@ $formData.redirectTo = $page.url.searchParams.get('redirectTo') ?? $formData.red submitting: $submitting, delayed: $delayed, timeout: $timeout, - posted: $posted, formData: $formData, errors: $errors, constraints: $constraints, diff --git a/apps/console/src/routes/(auth)/signin/components/passwordless.svelte b/apps/console/src/routes/(auth)/signin/components/passwordless.svelte index fa2368100..d1f9ec4a6 100644 --- a/apps/console/src/routes/(auth)/signin/components/passwordless.svelte +++ b/apps/console/src/routes/(auth)/signin/components/passwordless.svelte @@ -1,43 +1,67 @@ @@ -104,8 +139,8 @@ $formData.redirectTo = $page.url.searchParams.get('redirectTo') ?? $formData.red
    @@ -135,7 +170,6 @@ $formData.redirectTo = $page.url.searchParams.get('redirectTo') ?? $formData.red submitting: $submitting, delayed: $delayed, timeout: $timeout, - posted: $posted, formData: $formData, errors: $errors, constraints: $constraints, diff --git a/apps/console/src/routes/(auth)/signin/components/social.svelte b/apps/console/src/routes/(auth)/signin/components/social.svelte index ac0264098..1bc84c8aa 100644 --- a/apps/console/src/routes/(auth)/signin/components/social.svelte +++ b/apps/console/src/routes/(auth)/signin/components/social.svelte @@ -1,16 +1,32 @@
    - - - +
    diff --git a/apps/console/src/routes/(auth)/signout/+page.server.ts b/apps/console/src/routes/(auth)/signout/+page.server.ts deleted file mode 100644 index 81b4a6439..000000000 --- a/apps/console/src/routes/(auth)/signout/+page.server.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { NHOST_SESSION_KEY } from '$lib/constants'; -import { i18n } from '$lib/i18n'; -import { Logger } from '@spectacular/utils'; -import { redirect as redirectWithFlash } from 'sveltekit-flash-message/server'; -import type { Actions } from './$types'; - -const log = new Logger('server:auth:signout'); - -export const actions = { - default: async (event) => { - const { - cookies, - locals: { - paraglide: { lang }, - nhost, - }, - } = event; - log.debug('signout', lang); - - await nhost.auth.signOut(); - cookies.delete(NHOST_SESSION_KEY, { path: '/' }); - const message: App.Superforms.Message = { type: 'success', message: 'Signout sucessfull 😎' } as const; - redirectWithFlash(303, i18n.resolveRoute('/'), message, event); - // redirectWithFlash(303, i18n.resolveRoute('/signin'), message, event); - }, -} satisfies Actions; diff --git a/apps/console/src/routes/(auth)/signup/+page.gql b/apps/console/src/routes/(auth)/signup/+page.gql deleted file mode 100644 index 139702a10..000000000 --- a/apps/console/src/routes/(auth)/signup/+page.gql +++ /dev/null @@ -1,6 +0,0 @@ -query ListOrganizations @cache(policy: CacheOrNetwork) { - organizations(order_by: [{ organization: desc_nulls_last }]) { - organization - description - } -} diff --git a/apps/console/src/routes/(auth)/signup/+page.server.ts b/apps/console/src/routes/(auth)/signup/+page.server.ts deleted file mode 100644 index 36757a992..000000000 --- a/apps/console/src/routes/(auth)/signup/+page.server.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { i18n } from '$lib/i18n'; -import { signUpSchema } from '$lib/schema/user'; -import { limiter } from '$lib/server/limiter/limiter'; -import { setNhostSessionInCookies } from '$lib/server/utils/nhost'; -import { Logger, sleep } from '@spectacular/utils'; -import { error, fail } from '@sveltejs/kit'; -import type { GraphQLError } from 'graphql'; -import { redirect as redirectWithFlash } from 'sveltekit-flash-message/server'; -import { message, setError, setMessage, superValidate } from 'sveltekit-superforms'; -import { zod } from 'sveltekit-superforms/adapters'; - -const log = new Logger('server:auth:signup'); - -export const load = async (event) => { - const { - locals: { nhost }, - } = event; - /** - * Preflight prevents direct posting. If preflight option for the - * cookie limiter is true and this function isn't called before posting, - * request will be limited. - * - * Remember to await, so the cookie will be set before returning! - */ - await limiter.cookieLimiter?.preflight(event); - - const isAuthenticated = nhost.auth.isAuthenticated(); - if (isAuthenticated) redirectWithFlash(302, i18n.resolveRoute('/dashboard')); -}; - -export const actions = { - default: async (event) => { - const { - request, - cookies, - locals: { - paraglide: { lang }, - nhost, - }, - } = event; - - const form = await superValidate(request, zod(signUpSchema)); - - const status = await limiter.check(event); - if (status.limited) { - event.setHeaders({ - 'Retry-After': status.retryAfter.toString(), - }); - return message( - form, - { - type: 'error', - message: `Rate limit has been reached. Please retry after ${status.retryAfter} seconds`, - }, - { status: 429 }, - ); - } - - await sleep(8000); - - if (!form.valid) return fail(400, { form }); - - const { organization, firstName, lastName, email, password, redirectTo } = form.data; - - const { session: sessionBad, error } = await nhost.auth.signUp({ - email, - password, - options: { - displayName: `${firstName} ${lastName}`, - // defaultRole: 'user', - // It's possible to give users a subset of allowed roles during signup. - // allowedRoles: ['me', 'user'], - locale: lang, - metadata: { - plan: 'free', - default_org: organization, - }, - }, - }); - if (error) { - log.error(error); - return setError(form, `Failed creating account: ${error.message}`, { status: 409 }); // 424 ??? - } - const session = nhost.auth.getSession(); - if (session) { - setNhostSessionInCookies(cookies, session); - const message: App.Superforms.Message = { type: 'success', message: 'Signup sucessfull 😎' } as const; - redirectWithFlash(303, i18n.resolveRoute(redirectTo), message, event); - } - - // This line should never reach. - return message(form, { type: 'success', message: 'Signup sucessfull-no 😎' }); - }, -}; diff --git a/apps/console/src/routes/(auth)/signup/+page.svelte b/apps/console/src/routes/(auth)/signup/+page.svelte index cbfdbe077..3827f8adf 100644 --- a/apps/console/src/routes/(auth)/signup/+page.svelte +++ b/apps/console/src/routes/(auth)/signup/+page.svelte @@ -1,45 +1,114 @@ @@ -84,27 +146,6 @@ $formData.redirectTo = $page.url.searchParams.get('redirectTo') ?? $formData.red -
    - - - {m.auth_forms_first_organization_label()} - - - - -
    @@ -193,6 +234,24 @@ $formData.redirectTo = $page.url.searchParams.get('redirectTo') ?? $formData.red
    +
    + + + Locale + + + + + +
    @@ -240,8 +299,7 @@ $formData.redirectTo = $page.url.searchParams.get('redirectTo') ?? $formData.red message: $message, submitting: $submitting, delayed: $delayed, - timeout: $timeout, - posted: $posted, + timeout: $timeout }} />
    diff --git a/apps/console/src/routes/+error.svelte b/apps/console/src/routes/+error.svelte index a1dd88516..7bb20761d 100644 --- a/apps/console/src/routes/+error.svelte +++ b/apps/console/src/routes/+error.svelte @@ -2,7 +2,7 @@ import { page } from '$app/stores'; import * as m from '$i18n/messages'; import { i18n } from '$lib/i18n'; -import { ParaglideJS } from '@inlang/paraglide-js-adapter-sveltekit'; +import { ParaglideJS } from '@inlang/paraglide-sveltekit'; import { LogoAnim } from '@spectacular/skeleton/components/logos'; const details = $page.error?.details; diff --git a/apps/console/src/routes/+layout.server.ts b/apps/console/src/routes/+layout.server.ts index 4965d416d..9c096d727 100644 --- a/apps/console/src/routes/+layout.server.ts +++ b/apps/console/src/routes/+layout.server.ts @@ -11,13 +11,15 @@ export const load = loadFlash( nhost, }, }) => { + const claims = nhost.auth.getHasuraClaims(); log.debug(lang, textDirection); - const session = nhost.auth.getSession(); - // pass locale information from "server-context" to "shared server + client context" return { vercelEnv: secrets.VERCEL_ENV ?? 'development', - session, + // HINT: svelte pages and components can access them from anyware via '$page.data.userId' etc + userId: claims?.['x-hasura-user-id'], + orgId: claims?.['x-hasura-default-org'], + role: claims?.['x-hasura-default-role'], }; }, ); diff --git a/apps/console/src/routes/+layout.svelte b/apps/console/src/routes/+layout.svelte index 2bf2e2785..a5a114c6e 100644 --- a/apps/console/src/routes/+layout.svelte +++ b/apps/console/src/routes/+layout.svelte @@ -14,7 +14,7 @@ import { scroll, storeTheme, storeVercelProductionMode } from '$lib/stores'; import { setLoadingState } from '$lib/stores/loading'; import { online, orientation, size } from '$lib/stores/window'; import { arrow, autoUpdate, computePosition, flip, offset, shift } from '@floating-ui/dom'; -import { ParaglideJS } from '@inlang/paraglide-js-adapter-sveltekit'; +import { ParaglideJS } from '@inlang/paraglide-sveltekit'; import { Modal, initializeStores, prefersReducedMotionStore, storePopup } from '@skeletonlabs/skeleton'; import type { ModalComponent } from '@skeletonlabs/skeleton'; // biome-ignore lint/style/useImportType: biome still don't understand svelte @@ -95,39 +95,6 @@ function scrollHandler(event: ComponentEvents['scroll']) { // Disable left sidebar on homepage $: slotSidebarLeft = matchNoSidebarPaths($page.url.pathname) ? 'w-0' : 'bg-surface-50-900-token lg:w-auto'; $: allyPageSmoothScroll = !$prefersReducedMotionStore ? 'scroll-smooth' : ''; - -// update nhost session -// HINT: https://blog.flotes.app/posts/performant-reactivity -$: ({ session } = data); -$: if (browser) { - if (session) { - log.debug('trigger SESSION_UPDATE', { session }); - nhost.auth.client.interpreter?.send('SESSION_UPDATE', { - data: { session }, - }); - } else { - log.debug('session empty, trigger SIGNOUT'); - // nhost.auth.client.interpreter?.send('SIGNOUT'); - (async () => { - const { error } = await nhost.auth.signOut(); - if (error) log.error({ error }); - })(); - } -} - -// if(browser) { -// cookieStore.onchange = (event: CookieChangeEvent) => { -// console.log("cookie changed", {event}); -// if(event.deleted[0] && event.deleted[0].name === NHOST_SESSION_KEY) { -// console.log("cookie deleted", {deleted: event.deleted[0].name}); -// init(); -// } -// if(event.changed[0] && event.changed[0].name === NHOST_SESSION_KEY) { -// console.log("cookie changed", {changed: event.changed[0].name}); -// init(); -// } -// }; -// } diff --git a/apps/console/src/routes/+page.server.ts b/apps/console/src/routes/+page.server.ts index f2aea8db7..979fd5932 100644 --- a/apps/console/src/routes/+page.server.ts +++ b/apps/console/src/routes/+page.server.ts @@ -1,10 +1,11 @@ +const in2035 = new Date('2035-01-01'); export const actions = { // This action is called when the user clicks the theme button setTheme: async ({ cookies, request }) => { const formData = await request.formData(); const theme = formData.get('theme')?.toString() ?? 'skeleton'; // Sets the selected theme to the cookie - cookies.set('theme', theme, { path: '/' }); + cookies.set('theme', theme, { path: '/', expires: in2035 }); return { theme }; }, }; diff --git a/apps/console/static/assets/avatars/01.png b/apps/console/static/assets/avatars/01.png new file mode 100644 index 000000000..05f11d491 Binary files /dev/null and b/apps/console/static/assets/avatars/01.png differ diff --git a/apps/console/static/assets/avatars/02.png b/apps/console/static/assets/avatars/02.png new file mode 100644 index 000000000..d919d304c Binary files /dev/null and b/apps/console/static/assets/avatars/02.png differ diff --git a/apps/console/static/assets/avatars/03.png b/apps/console/static/assets/avatars/03.png new file mode 100644 index 000000000..34f92d098 Binary files /dev/null and b/apps/console/static/assets/avatars/03.png differ diff --git a/apps/console/static/assets/avatars/04.png b/apps/console/static/assets/avatars/04.png new file mode 100644 index 000000000..b31bfef63 Binary files /dev/null and b/apps/console/static/assets/avatars/04.png differ diff --git a/apps/console/static/assets/avatars/05.png b/apps/console/static/assets/avatars/05.png new file mode 100644 index 000000000..74510b095 Binary files /dev/null and b/apps/console/static/assets/avatars/05.png differ diff --git a/apps/console/static/assets/avatars/shadcn.jpg b/apps/console/static/assets/avatars/shadcn.jpg new file mode 100644 index 000000000..7d3b7a4da Binary files /dev/null and b/apps/console/static/assets/avatars/shadcn.jpg differ diff --git a/apps/console/turbo.json b/apps/console/turbo.json index 541e48899..2afee9a55 100644 --- a/apps/console/turbo.json +++ b/apps/console/turbo.json @@ -2,11 +2,11 @@ "$schema": "https://turbo.build/schema.json", "extends": ["//"], "tasks": { - "check:watch": { + "sv:check:watch": { "persistent": true, "outputs": [".svelte-kit/**"] }, - "check": { + "sv:check": { "outputs": [".svelte-kit/**"] }, "sync": { @@ -102,7 +102,7 @@ "dependsOn": ["sync", "^test:unit:coverage"] }, "test:integration": { - "dependsOn": ["build"] + "dependsOn": ["^build"] }, "lang:lint": {}, "lang:validate": {}, diff --git a/apps/console/vite.config.ts b/apps/console/vite.config.ts index af7cc4c16..c2d3b659b 100644 --- a/apps/console/vite.config.ts +++ b/apps/console/vite.config.ts @@ -1,5 +1,5 @@ import * as child_process from 'node:child_process'; -import { paraglide } from '@inlang/paraglide-js-adapter-sveltekit/vite'; +import { paraglide } from '@inlang/paraglide-sveltekit/vite'; import { enhancedImages } from '@sveltejs/enhanced-img'; import { sveltekit } from '@sveltejs/kit/vite'; import { vercelToolbar } from '@vercel/toolbar/plugins/vite'; @@ -28,6 +28,7 @@ export default defineConfig({ paraglide({ project: './project.inlang', outdir: './src/i18n', + // experimentalUseVirtualModules: true, // TODO not working with svelte 4 }), vercelToolbar(), ], diff --git a/apps/console/vitest.config.ts b/apps/console/vitest.config.ts index 9810a3b1f..50b96e90a 100644 --- a/apps/console/vitest.config.ts +++ b/apps/console/vitest.config.ts @@ -1,5 +1,4 @@ import { sveltekit } from '@sveltejs/kit/vite'; -import { svelte } from '@sveltejs/vite-plugin-svelte'; import { svelteTesting } from '@testing-library/svelte/vite'; import { configDefaults, defineConfig } from 'vitest/config'; diff --git a/apps/docs/astro.config.mjs b/apps/docs/astro.config.mjs index f05d2c933..9b2d50f37 100644 --- a/apps/docs/astro.config.mjs +++ b/apps/docs/astro.config.mjs @@ -141,7 +141,6 @@ export default defineConfig({ applyBaseStyles: false, }), ], - output: process.env.CI ? 'static' : 'hybrid', // HINT: To set build output, same way like sveltekit for Dockerfile build: { server: './build', diff --git a/apps/docs/package.json b/apps/docs/package.json index d4b3fe63d..fa34004b8 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -5,6 +5,8 @@ "scripts": { "astro": "astro", "build": "astro check && astro build", + "check": "biome check .", + "check:fix": "biome check . --write", "clean": "git clean -xdf", "dev": "astro dev", "format": "biome format --write", @@ -15,17 +17,17 @@ }, "dependencies": { "@astrojs/check": "0.9.4", - "@astrojs/node": "8.3.4", - "@astrojs/starlight": "0.29.2", - "@astrojs/starlight-tailwind": "2.0.3", - "@astrojs/tailwind": "5.1.2", - "@astrojs/vercel": "7.8.2", - "@fontsource-variable/inter": "5.1.0", - "@fontsource/source-code-pro": "5.1.0", - "astro": "4.16.16", + "@astrojs/node": "9.0.1", + "@astrojs/starlight": "0.31.0", + "@astrojs/starlight-tailwind": "3.0.0", + "@astrojs/tailwind": "5.1.4", + "@astrojs/vercel": "8.0.2", + "@fontsource-variable/inter": "5.1.1", + "@fontsource/source-code-pro": "5.1.1", + "astro": "5.1.6", "sharp": "0.33.5", - "tailwindcss": "3.4.15", - "typescript": "5.7.2" + "tailwindcss": "3.4.17", + "typescript": "5.7.3" }, "devDependencies": { "@spectacular/biome-config": "workspace:*" diff --git a/apps/docs/src/content.config.ts b/apps/docs/src/content.config.ts new file mode 100644 index 000000000..e54e72fa2 --- /dev/null +++ b/apps/docs/src/content.config.ts @@ -0,0 +1,8 @@ +import { defineCollection } from 'astro:content'; +import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; +import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }), +}; diff --git a/apps/docs/src/content/config.ts b/apps/docs/src/content/config.ts deleted file mode 100644 index 02ea2ac07..000000000 --- a/apps/docs/src/content/config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineCollection } from 'astro:content'; -import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; - -export const collections = { - docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), -}; diff --git a/apps/smart/.gitignore b/apps/smart/.gitignore index 7ea7f78fc..962b5f093 100644 --- a/apps/smart/.gitignore +++ b/apps/smart/.gitignore @@ -6,3 +6,4 @@ node_modules vite.config.js.timestamp-* vite.config.ts.timestamp-* test-results +src/i18n diff --git a/apps/smart/package.json b/apps/smart/package.json index 3ce59dee6..2f1b0310c 100644 --- a/apps/smart/package.json +++ b/apps/smart/package.json @@ -6,8 +6,10 @@ "scripts": { "build": "dotenv-run -f .env -f .secrets -v -- vite build", "build:production": "NODE_ENV=production dotenv-run -f .env -f .secrets -v -- vite build", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "sv:check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "sv:check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "check": "biome check .", + "check:fix": "biome check . --write", "clean": "git clean -xdf -e .vercel -e config", "dev": "dotenv-run -f .env -f .secrets -v -- vite dev", "dev:debug": "DEBUG=* dotenv-run -f .env -f .secrets -v '.*' -u -- vite dev", @@ -26,45 +28,50 @@ "test:e2e": "dotenv-run -f .env -f .secrets -v -- playwright test" }, "devDependencies": { - "@aibrow/dom-types": "1.2.1", - "@inlang/paraglide-sveltekit": "0.12.1", - "@playwright/test": "1.49.0", + "@ai-sdk/azure": "1.0.20", + "@ai-sdk/openai": "1.0.18", + "@ai-sdk/svelte": "1.0.10", + "@aibrow/dom-types": "1.3.5", + "@inlang/paraglide-sveltekit": "0.15.5", + "@playwright/test": "1.49.1", "@spectacular/biome-config": "workspace:*", "@spectacular/typescript-config": "workspace:*", "@spectacular/ui": "workspace:*", "@spectacular/utils": "workspace:*", "@sveltejs/adapter-auto": "3.3.1", - "@sveltejs/enhanced-img": "0.4.1", - "@sveltejs/kit": "2.9.0", - "@sveltejs/vite-plugin-svelte": "5.0.1", - "@tailwindcss/aspect-ratio": "0.4.2", + "@sveltejs/adapter-node": "5.2.11", + "@sveltejs/adapter-vercel": "5.5.2", + "@sveltejs/enhanced-img": "0.4.4", + "@sveltejs/kit": "2.15.2", + "@sveltejs/vite-plugin-svelte": "5.0.3", "@tailwindcss/container-queries": "0.1.1", - "@tailwindcss/forms": "0.5.9", - "@tailwindcss/typography": "0.5.15", + "@tailwindcss/forms": "0.5.10", + "@tailwindcss/typography": "0.5.16", "@tanstack/table-core": "8.20.5", "@types/dom-chromium-ai": "0.0.4", + "ai": "4.0.34", "autoprefixer": "10.4.20", - "bits-ui": "1.0.0-next.51", + "bits-ui": "1.0.0-next.71", "clsx": "2.1.1", - "formsnap": "2.0.0-next.1", - "lucide-svelte": "0.462.0", + "formsnap": "2.0.0", + "lucide-svelte": "0.471.0", "mode-watcher": "0.5.0", - "openai-zod-to-json-schema": "^1.0.3", - "runed": "0.16.1", - "svelte": "5.4.0", - "svelte-check": "4.1.0", + "openai-zod-to-json-schema": "1.0.3", + "runed": "0.23.0", + "svelte": "5.17.4", + "svelte-check": "4.1.4", "svelte-persisted-store": "0.12.0", "svelte-radix": "2.0.1", "svelte-sonner": "0.3.28", - "sveltekit-superforms": "2.21.0", - "tailwind-merge": "2.5.5", + "sveltekit-superforms": "2.22.1", + "tailwind-merge": "2.6.0", "tailwind-variants": "0.3.0", - "tailwindcss": "3.4.15", + "tailwindcss": "3.4.17", "tailwindcss-animate": "1.0.7", - "typescript": "5.7.2", - "vaul-svelte": "1.0.0-next.2", - "vite": "6.0.2", + "typescript": "5.7.3", + "vaul-svelte": "1.0.0-next.3", + "vite": "6.0.7", "vitest": "2.1.8", - "zod": "3.23.8" + "zod": "3.24.1" } } diff --git a/apps/smart/src/app.d.ts b/apps/smart/src/app.d.ts index 9637f21fc..ea7f56d6a 100644 --- a/apps/smart/src/app.d.ts +++ b/apps/smart/src/app.d.ts @@ -1,10 +1,15 @@ // See https://svelte.dev/docs/kit/types#app.d.ts // for information about these interfaces +import type { AvailableLanguageTag } from '$lib/paraglide/runtime'; import type AI from '@aibrow/dom-types'; +import type { ParaglideLocals } from '@inlang/paraglide-sveltekit'; declare global { namespace App { + interface Locals { + paraglide: ParaglideLocals; + } // interface Error {} // interface Locals {} // interface PageData {} diff --git a/apps/smart/src/demo.spec.ts b/apps/smart/src/demo.spec.ts index 964d28725..aa9342637 100644 --- a/apps/smart/src/demo.spec.ts +++ b/apps/smart/src/demo.spec.ts @@ -1,4 +1,4 @@ -import { describe, it, expect } from 'vitest'; +import { describe, expect, it } from 'vitest'; describe('sum test', () => { it('adds 1 + 2 to equal 3', () => { diff --git a/apps/smart/src/hooks.server.ts b/apps/smart/src/hooks.server.ts index 03f35d111..8d2cd839f 100644 --- a/apps/smart/src/hooks.server.ts +++ b/apps/smart/src/hooks.server.ts @@ -1,4 +1,4 @@ -import type { Handle } from '@sveltejs/kit'; import { i18n } from '$lib/i18n'; +import type { Handle } from '@sveltejs/kit'; const handleParaglide: Handle = i18n.handle(); export const handle: Handle = handleParaglide; diff --git a/apps/smart/src/lib/ai/actions/smart-paste.svelte.ts b/apps/smart/src/lib/ai/actions/smart-paste.svelte.ts index acb31cd66..4e75d1563 100644 --- a/apps/smart/src/lib/ai/actions/smart-paste.svelte.ts +++ b/apps/smart/src/lib/ai/actions/smart-paste.svelte.ts @@ -1,6 +1,6 @@ import type { Action } from 'svelte/action'; -import type { JSONSchema } from 'sveltekit-superforms'; import type { Writable } from 'svelte/store'; +import type { JSONSchema } from 'sveltekit-superforms'; type Options = { api: string; diff --git a/apps/smart/src/lib/ai/components/settings.svelte b/apps/smart/src/lib/ai/components/settings.svelte index 9f387ce07..23b9e7ac0 100644 --- a/apps/smart/src/lib/ai/components/settings.svelte +++ b/apps/smart/src/lib/ai/components/settings.svelte @@ -1,18 +1,18 @@ diff --git a/apps/smart/src/lib/components/layout/app-header.svelte b/apps/smart/src/lib/components/layout/app-header.svelte index 8899cdf25..581b13424 100644 --- a/apps/smart/src/lib/components/layout/app-header.svelte +++ b/apps/smart/src/lib/components/layout/app-header.svelte @@ -1,13 +1,13 @@
    diff --git a/apps/smart/src/lib/components/layout/app-sidebar.svelte b/apps/smart/src/lib/components/layout/app-sidebar.svelte index 33dedcae1..22a6a5fc7 100644 --- a/apps/smart/src/lib/components/layout/app-sidebar.svelte +++ b/apps/smart/src/lib/components/layout/app-sidebar.svelte @@ -4,13 +4,13 @@ import BookOpen from 'lucide-svelte/icons/book-open'; import Bot from 'lucide-svelte/icons/bot'; import ChartPie from 'lucide-svelte/icons/chart-pie'; import Command from 'lucide-svelte/icons/command'; +import FlaskRound from 'lucide-svelte/icons/flask-round'; import Frame from 'lucide-svelte/icons/frame'; import GalleryVerticalEnd from 'lucide-svelte/icons/gallery-vertical-end'; import Map from 'lucide-svelte/icons/map'; import Settings2 from 'lucide-svelte/icons/settings-2'; -import SquareTerminal from 'lucide-svelte/icons/square-terminal'; import Sparkles from 'lucide-svelte/icons/sparkles'; -import FlaskRound from 'lucide-svelte/icons/flask-round'; +import SquareTerminal from 'lucide-svelte/icons/square-terminal'; // This is sample data. const data = { diff --git a/apps/smart/src/lib/components/layout/command-menu.svelte b/apps/smart/src/lib/components/layout/command-menu.svelte index c71f02250..b7f1bae42 100644 --- a/apps/smart/src/lib/components/layout/command-menu.svelte +++ b/apps/smart/src/lib/components/layout/command-menu.svelte @@ -1,15 +1,15 @@ diff --git a/apps/smart/src/lib/stores/context.ts b/apps/smart/src/lib/stores/context.ts new file mode 100644 index 000000000..76ffbe283 --- /dev/null +++ b/apps/smart/src/lib/stores/context.ts @@ -0,0 +1,11 @@ +import { Context } from 'runed'; + +/** + * Usage + * @example + * import { myTheme } from "./context"; + * myTheme.set(data.theme); + * const theme = myTheme.get(); + * const theme = myTheme.getOr("light"); + */ +export const myTheme = new Context<'light' | 'dark'>('theme'); diff --git a/apps/smart/src/lib/stores/state.svelte.ts b/apps/smart/src/lib/stores/state.svelte.ts index d41593b50..f0263e434 100644 --- a/apps/smart/src/lib/stores/state.svelte.ts +++ b/apps/smart/src/lib/stores/state.svelte.ts @@ -1,6 +1,6 @@ // See https://dev.to/jdgamble555/using-sharable-runes-with-typescript-in-svelte5-5hcp -import { writable, readable } from 'svelte/store'; +import { readable, writable } from 'svelte/store'; import { useSharedStore } from './use-shared.svelte'; export const rune = (initialValue?: T) => { diff --git a/apps/smart/src/routes/+layout.svelte b/apps/smart/src/routes/+layout.svelte index a6e2d6756..c933ad2a8 100644 --- a/apps/smart/src/routes/+layout.svelte +++ b/apps/smart/src/routes/+layout.svelte @@ -1,18 +1,18 @@ diff --git a/apps/smart/src/routes/examples/data-table/data-table-checkbox.svelte b/apps/smart/src/routes/examples/data-table/data-table-checkbox.svelte index 089763650..dd9e14fb9 100644 --- a/apps/smart/src/routes/examples/data-table/data-table-checkbox.svelte +++ b/apps/smart/src/routes/examples/data-table/data-table-checkbox.svelte @@ -1,6 +1,6 @@ diff --git a/apps/smart/src/routes/examples/data-table/data-table-email-button.svelte b/apps/smart/src/routes/examples/data-table/data-table-email-button.svelte index fd2d067f3..e5acb119d 100644 --- a/apps/smart/src/routes/examples/data-table/data-table-email-button.svelte +++ b/apps/smart/src/routes/examples/data-table/data-table-email-button.svelte @@ -1,7 +1,7 @@ diff --git a/apps/smart/src/routes/examples/data-table/data-table.svelte b/apps/smart/src/routes/examples/data-table/data-table.svelte index d7f92e1d8..3450222f8 100644 --- a/apps/smart/src/routes/examples/data-table/data-table.svelte +++ b/apps/smart/src/routes/examples/data-table/data-table.svelte @@ -1,5 +1,9 @@ + +
    +
    + +
    +

    Organization Members

    + +
    + + +
    + + +
    + + + {#if filteredMembers.length > 0} +
    + +
    + {:else} +
    No members found
    + {/if} +
    + + + {#if showAddDialog} + (showAddDialog = false)} onAdd={handleAddMember} /> + {/if} +
    diff --git a/apps/smart/src/routes/examples/members/AddMemberDialog.svelte b/apps/smart/src/routes/examples/members/AddMemberDialog.svelte new file mode 100644 index 000000000..a0e1bd1a2 --- /dev/null +++ b/apps/smart/src/routes/examples/members/AddMemberDialog.svelte @@ -0,0 +1,68 @@ + + +
    +
    +
    +

    Add New Member

    + +
    + + +
    + + +
    + +
    + + + +
    + +
    + + +
    + +
    +
    diff --git a/apps/smart/src/routes/examples/members/MemberList.svelte b/apps/smart/src/routes/examples/members/MemberList.svelte new file mode 100644 index 000000000..c35501503 --- /dev/null +++ b/apps/smart/src/routes/examples/members/MemberList.svelte @@ -0,0 +1,48 @@ + + +
    + {#each members as member (member.id)} +
    +
    + {member.name} +
    +

    {member.name}

    +

    + {member.role.charAt(0).toUpperCase() + member.role.slice(1)} +

    +
    +
    + +
    + + + + +
    +
    + {/each} +
    diff --git a/apps/smart/turbo.json b/apps/smart/turbo.json index 15e09caf4..7cd17c506 100644 --- a/apps/smart/turbo.json +++ b/apps/smart/turbo.json @@ -2,11 +2,11 @@ "$schema": "https://turbo.build/schema.json", "extends": ["//"], "tasks": { - "check:watch": { + "sv:check:watch": { "persistent": true, "outputs": [".svelte-kit/**"] }, - "check": { + "sv:check": { "outputs": [".svelte-kit/**"] }, "sync": { diff --git a/apps/smart/vite.config.ts b/apps/smart/vite.config.ts index 44f55e692..268d02f9a 100644 --- a/apps/smart/vite.config.ts +++ b/apps/smart/vite.config.ts @@ -1,7 +1,7 @@ import { paraglide } from '@inlang/paraglide-sveltekit/vite'; -import { defineConfig } from 'vitest/config'; -import { sveltekit } from '@sveltejs/kit/vite'; import { enhancedImages } from '@sveltejs/enhanced-img'; +import { sveltekit } from '@sveltejs/kit/vite'; +import { defineConfig } from 'vitest/config'; export default defineConfig({ plugins: [ @@ -10,6 +10,7 @@ export default defineConfig({ paraglide({ project: './project.inlang', outdir: './src/i18n', + experimentalUseVirtualModules: true, }), ], test: { diff --git a/apps/web/astro.config.mjs b/apps/web/astro.config.mjs index 1ee6abc67..24a96ee6b 100644 --- a/apps/web/astro.config.mjs +++ b/apps/web/astro.config.mjs @@ -15,7 +15,7 @@ const SITE_URL = process.env.VERCEL_ENV === 'production' ? process.env.SITE_URL export default defineConfig({ site: SITE_URL, integrations: [ - starlight({ title: 'Web' }), + starlight({ title: 'Web', disable404Route: true }), tailwind({ // Disable the default base styles: // Example: Disable injecting a basic `base.css` import on every page. @@ -28,7 +28,6 @@ export default defineConfig({ expressiveCode(), mdx(), ], - output: 'hybrid', // HINT: To set build output, same way like sveltekit for Dockerfile build: { server: './build', @@ -51,34 +50,31 @@ export default defineConfig({ prefetchAll: true, defaultStrategy: 'hover', }, - experimental: { - serverIslands: true, - clientPrerender: true, - env: { - schema: { - API_VERSION: envField.enum({ - context: 'server', - access: 'secret', - values: ['v1', 'v2'], - optional: true, - }), - API_PORT: envField.number({ - context: 'server', - access: 'secret', - gt: 1024, - default: 7000, - }), - PUBLIC_SOME_SERVER_FEATURE_FLAG: envField.boolean({ - context: 'server', - access: 'public', - default: false, - }), - PUBLIC_SOME_CLIENT_FEATURE_FLAG: envField.boolean({ - context: 'client', - access: 'public', - default: false, - }), - }, + + env: { + schema: { + API_VERSION: envField.enum({ + context: 'server', + access: 'secret', + values: ['v1', 'v2'], + optional: true, + }), + API_PORT: envField.number({ + context: 'server', + access: 'secret', + gt: 1024, + default: 7000, + }), + PUBLIC_SOME_SERVER_FEATURE_FLAG: envField.boolean({ + context: 'server', + access: 'public', + default: false, + }), + PUBLIC_SOME_CLIENT_FEATURE_FLAG: envField.boolean({ + context: 'client', + access: 'public', + default: false, + }), }, }, }); diff --git a/apps/web/package.json b/apps/web/package.json index 080a98486..6aef8ad0c 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -5,6 +5,8 @@ "scripts": { "astro": "astro", "build": "astro check && astro build", + "check": "biome check .", + "check:fix": "biome check . --write", "clean": "git clean -xdf", "dev": "astro dev", "format": "biome format --write", @@ -20,30 +22,30 @@ }, "devDependencies": { "@astrojs/check": "0.9.4", - "@astrojs/mdx": "3.1.9", - "@astrojs/node": "8.3.4", - "@astrojs/partytown": "2.1.2", + "@astrojs/mdx": "4.0.5", + "@astrojs/node": "9.0.1", + "@astrojs/partytown": "2.1.3", "@astrojs/sitemap": "3.2.1", - "@astrojs/starlight": "0.29.2", - "@astrojs/svelte": "6.0.2", - "@astrojs/tailwind": "5.1.2", - "@astrojs/vercel": "7.8.2", - "@fontsource-variable/inter": "5.1.0", - "@fontsource/source-code-pro": "5.1.0", + "@astrojs/starlight": "0.31.0", + "@astrojs/svelte": "7.0.3", + "@astrojs/tailwind": "5.1.4", + "@astrojs/vercel": "8.0.2", + "@fontsource-variable/inter": "5.1.1", + "@fontsource/source-code-pro": "5.1.1", "@spectacular/biome-config": "workspace:*", "@spectacular/typescript-config": "workspace:*", "@spectacular/utils": "workspace:*", - "@tailwindcss/typography": "0.5.15", + "@tailwindcss/typography": "0.5.16", "@vitest/coverage-v8": "2.1.8", - "astro": "4.16.16", - "astro-expressive-code": "0.38.3", + "astro": "5.1.6", + "astro-expressive-code": "0.40.0", "astro-seo": "0.8.4", - "lucide-svelte": "0.462.0", + "lucide-svelte": "0.471.0", "mode-watcher": "0.5.0", - "svelte": "5.4.0", - "tailwind-merge": "2.5.5", - "tailwindcss": "3.4.15", - "typescript": "5.7.2", + "svelte": "5.17.4", + "tailwind-merge": "2.6.0", + "tailwindcss": "3.4.17", + "typescript": "5.7.3", "vitest": "2.1.8" } } diff --git a/apps/web/src/content/config.ts b/apps/web/src/content.config.ts similarity index 100% rename from apps/web/src/content/config.ts rename to apps/web/src/content.config.ts diff --git a/apps/web/src/content/newsletter/.gitkeep b/apps/web/src/content/newsletter/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/web/src/layouts/layout.astro b/apps/web/src/layouts/layout.astro index 2a339bd0f..9b5e935d3 100644 --- a/apps/web/src/layouts/layout.astro +++ b/apps/web/src/layouts/layout.astro @@ -2,6 +2,7 @@ // import '@fontsource-variable/inter'; // import '@fontsource/source-code-pro'; import '@styles/tailwind.css'; +import { ClientRouter } from 'astro:transitions'; import AppFooter from '@components/app-footer.astro'; import AppHeader from '@components/app-header.astro'; import { SEO } from 'astro-seo'; @@ -49,6 +50,7 @@ const { title } = Astro.props; }, }} /> + diff --git a/apps/web/tailwind.config.mjs b/apps/web/tailwind.config.mjs index 00ea8010c..b44fb5f87 100644 --- a/apps/web/tailwind.config.mjs +++ b/apps/web/tailwind.config.mjs @@ -1,5 +1,5 @@ -import colors from 'tailwindcss/colors'; import typography from '@tailwindcss/typography'; +import colors from 'tailwindcss/colors'; import defaultTheme from 'tailwindcss/defaultTheme'; /** @type {import('tailwindcss').Config} */ diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index 7ae3865f9..313a4da6e 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -13,5 +13,6 @@ "@styles/*": ["styles/*"] } }, + "include": [".astro/types.d.ts", "**/*"], "exclude": ["node_modules", "dist", ".vercel"] } diff --git a/docs/awesome-sveltekit.md b/docs/awesome-sveltekit.md index 59905bf11..f7e274cc0 100644 --- a/docs/awesome-sveltekit.md +++ b/docs/awesome-sveltekit.md @@ -77,6 +77,10 @@ Awesome **SvelteKit** Links - [Konsta UI](https://konstaui.com) Pixel perfect mobile UI components built with Tailwind CSS - [Framework7 Svelte](https://framework7.io/svelte/) Build full featured iOS, Android & Desktop apps +- Desktop/ Native + + - [powersync-tauri](https://github.com/MrLightful/powersync-tauri) - An exhaustive boilerplate project of `Tauri` + `Shadcn UI` + `PowerSync`. + - Security - [lucia](https://lucia-auth.com/) OIDC auth with [SvelteKit](https://lucia-auth.com/guidebook/github-oauth/sveltekit) @@ -105,6 +109,7 @@ Awesome **SvelteKit** Links - [Motion](https://motion.dev/) (preferred) - [lottiefiles](https://lottiefiles.github.io/lottie-docs/) Lottie is a **vector** animation format, used to build marketing pages. See [Examples](https://lottiefiles.com/use-cases/website) - [Magic UI](https://magicui.design/) - **React**, **Typescript**, **Tailwind CSS**, and **Framer Motion**. Perfect companion for **shadcn/ui**. +- [NumberFlow](https://github.com/barvian/number-flow) - An animated number component for React, Vue, and Svelte. ## State Management @@ -166,7 +171,11 @@ Awesome **SvelteKit** Links - [climbing_noteboo](https://github.com/diericx/climbing_notebook) - Use skeleton, Superforms, sveltekit-flash-message - [Vercel Toolbar and Feature Flags SvelteKit Starter](https://github.com/vercel/examples/tree/main/toolbar/toolbar-feature-flags-sveltekit), [Demo](https://toolbar-feature-flags-sveltekit.vercel.app/), [Blog](https://vercel.com/blog/flags-as-code-in-next-js) - [JavaFlavors](https://github.com/Critteros/JavaFlavors/tree/main/web) - use `houdini` and `setClientSession()`, drizzle, superforms, shadcn-svelte +- [Churros](https://github.com/inp-net/churros) - use `houdini` Fragments, `@loading` and `kustomization` for deployment. [Demo](https://git.inpt.fr/churros/churros) - [Turborepo Svelte starter](https://github.com/kevingdc/turborepo-sveltekit-shadcn/tree/main) +- [JustShip](https://www.justship.today/) - Skip the boring parts, Ship **svelte 5** apps in days not weeks. Components: Stripe, Auth, tailwind +- [next-forge](https://www.next-forge.com/) - Production-grade `Turborepo` template for` Next.js` apps. Components: + ## Deployment diff --git a/docs/database.md b/docs/database.md index c983d8f08..94b01d217 100644 --- a/docs/database.md +++ b/docs/database.md @@ -156,5 +156,7 @@ cat /var/lib/pgsql/14/data/pg_hba.conf ## Reference - [Automatic Data Classification using OpenAI, PostgreSQL, pgai, and pgvector](https://github.com/quamernasim/automatic-data-classification-using-openai-postgreSQL-pgai-and-pgvector) -- [Use pgai with OpenAI](https://github.com/timescale/pgai/blob/main/docs/openai.md) +- [Use pgai with OpenAI](https://github.com/timescale/pgai/blob/main/docs/openai.md) - [Use pgai with Ollama](https://github.com/timescale/pgai/blob/main/docs/ollama.md) +- [supavisor](https://github.com/supabase/supavisor) - PostgreSQL connection pooler _extention_. Multi-tenant alternative for **PgBouncer**. +- [pgmq](https://github.com/tembo-io/pgmq) - PostgreSQL _extention_ for _LISTEN/NOTIFY_. [usecases](https://supabase.com/blog/supabase-queues) diff --git a/docs/hasura-auth.md b/docs/hasura-auth.md index f0aab823a..7173afe2c 100644 --- a/docs/hasura-auth.md +++ b/docs/hasura-auth.md @@ -14,7 +14,7 @@ JWT token issued during `SignIn` step is used as `Session` token to access backe Users can `SugnUp` via **WebApp** to a specific `organization` with an email in `allowed email domains` or `allowed emails` defined in `public.organizations` for that `organization`. They will automatically get _allowed roles_ defined in `AUTH_USER_DEFAULT_ALLOWED_ROLES` i.e., `user,me` and _default role_ defined in `AUTH_USER_DEFAULT_ROLE` i.e., `user` -Optionally, additional higher roles can be added to user's _allowed roles_ by administrator (manager) by [Deligation](#deligation) UI. +Optionally, additional higher roles can be added to user's _allowed roles_ by administrator (org:owner) by [Deligation](#deligation) UI. ### Service Accounts @@ -105,6 +105,12 @@ await nhost.auth.signUp({ }) ``` +Current user's `allowed-roles` and `default-role` once they switch to an `Org` in multi-tenancy setup : + +> allowed roles = user roles (auth.user_roles) + org role (public.user_org_roles) + +> default role = org role (public.user_org_roles) = user default role (auth.user) + ### Set Role for GraphQL Requests When no role is specified, the user’s default role will be used: @@ -131,10 +137,14 @@ await nhost.graphql.request( | Role | Action | Permissions | | ---------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------- | -| org:member | select | {"_and":[{"deleted_at":{"_is_null":true}},{"organization":{"_eq":"x-hasura-default-org"}},{"created_by":{"_eq":"x-hasura-user-id"}}]} | +| user | select | {"_and":[{"deleted_at":{"_is_null":true}},{"organization":{"_eq":"x-hasura-default-org"}},{"created_by":{"_eq":"x-hasura-user-id"}}]} | | org:admin | select | {"_and":[{"deleted_at":{"_is_null":true}},{"organization":{"_eq":"x-hasura-default-org"}}]} | -| org:member | update | {"_and":[{"deleted_at":{"_is_null":true}},{"organization":{"_eq":"x-hasura-default-org"}},{"created_by":{"_eq":"x-hasura-user-id"}}]} | +| org:owner | select | {"_and":[{"deleted_at":{"_is_null":true}},{"organization":{"_eq":"x-hasura-default-org"}}]} | +| sys:admin | select | {"_and":[{"deleted_at":{"_is_null":true}},{"organization":{"_eq":"x-hasura-default-org"}}]} | +| user | update | {"_and":[{"deleted_at":{"_is_null":true}},{"organization":{"_eq":"x-hasura-default-org"}},{"created_by":{"_eq":"x-hasura-user-id"}}]} | | org:admin | update | {"_and":[{"deleted_at":{"_is_null":true}},{"organization":{"_eq":"x-hasura-default-org"}}]} | +| org:owner | update | {"_and":[{"deleted_at":{"_is_null":true}},{"organization":{"_eq":"x-hasura-default-org"}}]} | +| sys:admin | update | {"_and":[{"deleted_at":{"_is_null":true}},{"organization":{"_eq":"x-hasura-default-org"}}]} | > `delete` action is desable for most cases, as we do `soft-delete` @@ -208,17 +218,17 @@ From this diagram, here are some info you need to know: ### Deligation -**Deligation** is the process where higher role users can assign elevated roles (supervisor, manager) to other users via custom UI with in his/her default `Organization` or diffrent `Organization` with in multi-tenant deployment. +**Deligation** is the process where higher role users can assign elevated roles (org:admin, org:owner) to other users via custom UI with in his/her default `Organization` or diffrent `Organization` with in multi-tenant deployment. > **Assumptions:** there will be `public.user_roles_orgs` table that manage `user-role` assignment for a give `Organization` #### Types of Deligation -1. An administrator (with `manager` role) can add additional higher roles to existing user's `allowed_roles` in the same user's `default_org` and set it as user's `default_role`. - e.g., Administrator can promote a regular `user` role up to `supervisor` role with in the user's **default_org**, 1. by setting user's `default_role` as `supervisor` in `auth.users` table and 2. by adding `supervisor` role to `auth.user_roles` table. A databse trigger should also insert corresponding rows in `public.user_roles_orgs` with user's `default_org`. -2. An administrator (with `manager` role) can also assign a role (up to `supervisor`) to existing user to **other** `Organizations` in `public.user_roles_orgs` table and set user's `allowed_roles` and `default_role` flag with that new `Organization` in `public.user_roles_orgs` table. -3. To assign `manager` role to an user, set `default_role` as `manager` in `auth.users` and add `manager` role for that user in `auth.user_roles` table. - > Admin users will have exactly one `manager` role defined as `default_role` in their `default_org` in `auth.users` table. +1. An administrator (with `org:owner` role) can add additional higher roles to existing user's `allowed_roles` in the same user's `default_org` and set it as user's `default_role`. + e.g., Administrator can promote a regular `user` role up to `org:admin` role with in the user's **default_org**, 1. by setting user's `default_role` as `org:admin` in `auth.users` table and 2. by adding `org:admin` role to `auth.user_roles` table. A databse trigger should also insert corresponding rows in `public.user_roles_orgs` with user's `default_org`. +2. An administrator (with `org:owner` role) can also assign a role (up to `org:admin`) to existing user to **other** `Organizations` in `public.user_roles_orgs` table and set user's `allowed_roles` and `default_role` flag with that new `Organization` in `public.user_roles_orgs` table. +3. To assign `org:owner` role to an user, set `default_role` as `org:owner` in `auth.users` and add `org:owner` role for that user in `auth.user_roles` table. + > Admin users will have exactly one `org:owner` role defined as `default_role` in their `default_org` in `auth.users` table. ## FAQ @@ -227,9 +237,17 @@ From this diagram, here are some info you need to know: In some cases it is necessary to act **on behalf of** a user. While the **Auth** service doesn’t allow that it is not difficult to implement such functionality as a serverless function. You can find an example of a function that can generate a valid access token for your application with customized values here: [Custom JWTs](https://docs.nhost.io/guides/auth/custom-jwts) +## TODO + +- [FedCM](https://developer.mozilla.org/en-US/docs/Web/API/Credential_Management_API/Credential_types) + ## Reference - [Authentication and authorization in multi-tenancy B2B scenarios](https://zitadel.com/docs/guides/solution-scenarios/b2b) - [user management in nhost](https://docs.nhost.io/guides/auth/users) - [Hasura Authentication Using JWTs](https://hasura.io/docs/latest/auth/authentication/jwt/) - [logto: Understand how organizations work](https://docs.logto.io/docs/recipes/organizations/understand-how-it-works/) +- [FedCA](https://developer.mozilla.org/en-US/docs/Web/API/Credential_Management_API/Credential_types) +- [Best Practices for Storing Access Tokens in the Browser](https://curity.medium.com/best-practices-for-storing-access-tokens-in-the-browser-6b3d515d9814) +- [The Ultimate Guide to handling JWTs on frontend clients (GraphQL)](https://hasura.io/blog/best-practices-of-using-jwt-with-graphql) +- [Permissions - Permissions with unrelated tables or views](https://hasura.io/docs/2.0/auth/authorization/permissions/row-level-permissions/#unrelated-tables-in-permissions) diff --git a/docs/hasura.md b/docs/hasura.md index f4bda6df4..06ca0994e 100644 --- a/docs/hasura.md +++ b/docs/hasura.md @@ -40,24 +40,35 @@ hasura console # Create a new seed by exporting data from tables already present in the database: # use `--insecure-skip-tls-verify` if needed -hasura seed create organizations --database-name default --from-table organizations --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret hasura seed create users --database-name default --from-table auth.users --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret -hasura seed create devices --database-name default --from-table devices --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed create user_roles --database-name default --from-table auth.user_roles --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed create organizations --database-name default --from-table public.organizations --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed create user_org_roles --database-name default --from-table public.user_org_roles --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed create groups --database-name default --from-table public.groups --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed create user_groups --database-name default --from-table public.user_groups --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret hasura seed create rules --database-name default --from-table rules --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret -hasura seed create pools --database-name default --from-table pools --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret hasura seed create policies --database-name default --from-table policies --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed create devices --database-name default --from-table devices --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed create pools --database-name default --from-table pools --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed create org_settings --database-name default --from-table org_settings --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret # Export data from multiple tables: # hasura seed create policies_organization --database-name default --from-table policies --from-table organization # Apply all seed file: hasura seed apply --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret # (Or) Apply only a particular files: -hasura seed apply --file 001_organizations.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret -hasura seed apply --file 002_users.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret -hasura seed apply --file 011_devices.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret -hasura seed apply --file 012_rules.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret -hasura seed apply --file 013_pools.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret -hasura seed apply --file 014_policies.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed apply --file 001_users.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed apply --file 002_user_roles.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed apply --file 003_organizations.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed apply --file 004_memberships.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed apply --file 005_groups.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed apply --file 006_user_groups.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed apply --file 007_org_settings.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret + +hasura seed apply --file 011_rules.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed apply --file 012_policies.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed apply --file 013_devices.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret +hasura seed apply --file 014_pools.sql --database-name default --endpoint https://local.hasura.local.nhost.run --admin-secret hasura-admin-secret # To apply all the Migrations present in the `migrations/` directory and the Metadata present in the `metadata/` directory on a new, "fresh", # instance of the Hasura Server at http://another-server-instance.hasura.app: @@ -142,12 +153,18 @@ hasura deploy --endpoint https://local.hasura.local.nhost.run --admin-secret To set custom CA certs for all _nhost_ containers, set: `export NHOST_CA_CERTIFICATES=./nhost/ca-certificates.crt` ```shell +# Initialize a new nhost project +nhost init # start nhost services nhost up # or start with applying seed data diff --git a/docs/playbook.md b/docs/playbook.md index 57bf304b0..7dd144dc7 100644 --- a/docs/playbook.md +++ b/docs/playbook.md @@ -6,6 +6,25 @@ Show how this repo is setup via step-by-step guild ### Prerequisite +Install **node** and **pnpm** + +> [!NOTE] +> Since v16.13, Node.js is shipping Corepack for managing package managers. + +```shell +brew install node +# This will automatically install pnpm on your system. +corepack enable pnpm +``` + +> [!NOTE] +> You can pin the version of pnpm used on your project using the following command + +```shell +cd ~/Developer/Work/SPA/spectacular +corepack use pnpm@latest-10 +``` + Install following CLI tools globally - [svelte CLI](https://github.com/sveltejs/cli) @@ -254,6 +273,14 @@ pnpm add -D mode-watcher --filter "./apps/web" pnpm add -D svelte-persisted-store --filter "./apps/console" ``` +#### Bot Protection + +Bot Protection for nhost-auth with Cloudflare Turnstile + +```shell +pnpm add -D svelte-turnstile --filter "./apps/console" +``` + ### UI Blocks - [Kometa UI Kit](https://kitwind.io/products/kometa) (Free) [Blocks](https://kitwind.io/products/kometa/components) @@ -413,8 +440,8 @@ pnpm add -D svelte-select We switched to inlang's [Paraglide JS](https://inlang.com/m/dxnzrydw/library-inlang-paraglideJsAdapterSvelteKit) for i18n ```shell -npx @inlang/paraglide-js init -npm i -D @inlang/paraglide-js-adapter-sveltekit +npx @inlang/paraglide-sveltekit init +npm install ``` #### Progressive Web Apps (PWA) diff --git a/docs/turborepo.md b/docs/turborepo.md index 4d2de4540..35fe3d547 100644 --- a/docs/turborepo.md +++ b/docs/turborepo.md @@ -69,11 +69,13 @@ pnpx create-turbo@latest -e with-svelte ### Setup Remote Caching for Turborepo on Vercel ```shell -npx turbo login -npx turbo link +pnpx turbo login +pnpx turbo link # bunx turbo login ``` +To disable Remote Caching, run `pnpx turbo unlink` + ### Environment Variables > Turbo is working on [first-class solution](https://turbo.build/repo/docs/handbook/dev#using-environment-variables) to load **dotEnv** files. diff --git a/llms.txt b/llms.txt new file mode 100644 index 000000000..003d1c331 --- /dev/null +++ b/llms.txt @@ -0,0 +1,27489 @@ +This is the full developer documentation for Svelte and SvelteKit. + +# Start of Svelte documentation + + +# Overview + +Svelte is a framework for building user interfaces on the web. It uses a compiler to turn declarative components written in HTML, CSS and JavaScript... + +```svelte + + + + + + +``` + +...into lean, tightly optimized JavaScript. + +You can use it to build anything on the web, from standalone components to ambitious full stack apps (using Svelte's companion application framework, [SvelteKit](../kit)) and everything in between. + +These pages serve as reference documentation. If you're new to Svelte, we recommend starting with the [interactive tutorial](/tutorial) and coming back here when you have questions. + +You can also try Svelte online in the [playground](/playground) or, if you need a more fully-featured environment, on [StackBlitz](https://sveltekit.new). + +# Getting started + +We recommend using [SvelteKit](../kit), the official application framework from the Svelte team powered by [Vite](https://vite.dev/): + +```bash +npx sv create myapp +cd myapp +npm install +npm run dev +``` + +Don't worry if you don't know Svelte yet! You can ignore all the nice features SvelteKit brings on top for now and dive into it later. + +## Alternatives to SvelteKit + +You can also use Svelte directly with Vite by running `npm create vite@latest` and selecting the `svelte` option. With this, `npm run build` will generate HTML, JS and CSS files inside the `dist` directory using [vite-plugin-svelte](https://github.com/sveltejs/vite-plugin-svelte). In most cases, you will probably need to [choose a routing library](faq#Is-there-a-router) as well. + +There are also plugins for [Rollup](https://github.com/sveltejs/rollup-plugin-svelte), [Webpack](https://github.com/sveltejs/svelte-loader) [and a few others](https://sveltesociety.dev/packages?category=build-plugins), but we recommend Vite. + +## Editor tooling + +The Svelte team maintains a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode), and there are integrations with various other [editors](https://sveltesociety.dev/resources#editor-support) and tools as well. + +You can also check your code from the command line using [sv check](https://github.com/sveltejs/cli). + +## Getting help + +Don't be shy about asking for help in the [Discord chatroom](/chat)! You can also find answers on [Stack Overflow](https://stackoverflow.com/questions/tagged/svelte). + +# .svelte files + +Components are the building blocks of Svelte applications. They are written into `.svelte` files, using a superset of HTML. + +All three sections — script, styles and markup — are optional. + + +```svelte +/// file: MyComponent.svelte + + + + + + + +``` + +## ` + + +``` + +You can `export` bindings from this block, and they will become exports of the compiled module. You cannot `export default`, since the default export is the component itself. + +> [!NOTE] If you are using TypeScript and import such exports from a `module` block into a `.ts` file, make sure to have your editor setup so that TypeScript knows about them. This is the case for our VS Code extension and the IntelliJ plugin, but in other cases you might need to setup our [TypeScript editor plugin](https://www.npmjs.com/package/typescript-svelte-plugin). + +> [!LEGACY] +> In Svelte 4, this script tag was created using ` +``` + +You can specify a fallback value for a prop. It will be used if the component's consumer doesn't specify the prop on the component when instantiating the component, or if the passed value is `undefined` at some point. + +```svelte + +``` + +To get all properties, use rest syntax: + +```svelte + +``` + +You can use reserved words as prop names. + +```svelte + +``` + +If you're using TypeScript, you can declare the prop types: + +```svelte + +``` + +If you're using JavaScript, you can declare the prop types using JSDoc: + +```svelte + +``` + +If you export a `const`, `class` or `function`, it is readonly from outside the component. + +```svelte + +``` + +Readonly props can be accessed as properties on the element, tied to the component using [`bind:this` syntax](bindings#bind:this). + +### Reactive variables + +To change component state and trigger a re-render, just assign to a locally declared variable that was declared using the `$state` rune. + +Update expressions (`count += 1`) and property assignments (`obj.x = y`) have the same effect. + +```svelte + +``` + +Svelte's ` +``` + +If you'd like to react to changes to a prop, use the `$derived` or `$effect` runes instead. + +```svelte + +``` + +For more information on reactivity, read the documentation around runes. + +# Reactivity fundamentals + +Reactivity is at the heart of interactive UIs. When you click a button, you expect some kind of response. It's your job as a developer to make this happen. It's Svelte's job to make your job as intuitive as possible, by providing a good API to express reactive systems. + +## Runes + +Svelte 5 uses _runes_, a powerful set of primitives for controlling reactivity inside your Svelte components and inside `.svelte.js` and `.svelte.ts` modules. + +Runes are function-like symbols that provide instructions to the Svelte compiler. You don't need to import them from anywhere — when you use Svelte, they're part of the language. + +The following sections introduce the most important runes for declare state, derived state and side effects at a high level. For more details refer to the later sections on [state](state) and [side effects](side-effects). + +## `$state` + +Reactive state is declared with the `$state` rune: + +```svelte + + + +``` + +You can also use `$state` in class fields (whether public or private): + +```js +// @errors: 7006 2554 +class Todo { + done = $state(false); + text = $state(); + + constructor(text) { + this.text = text; + } +} +``` + +> [!LEGACY] +> In Svelte 4, state was implicitly reactive if the variable was declared at the top level +> +> ```svelte +> +> +> +> ``` + +## `$derived` + +Derived state is declared with the `$derived` rune: + +```svelte + + + + +

    {count} doubled is {doubled}

    +``` + +The expression inside `$derived(...)` should be free of side-effects. Svelte will disallow state changes (e.g. `count++`) inside derived expressions. + +As with `$state`, you can mark class fields as `$derived`. + +> [!LEGACY] +> In Svelte 4, you could use reactive statements for this. +> +> ```svelte +> +> +> +> +>

    {count} doubled is {doubled}

    +> ``` +> +> This only worked at the top level of a component. + +## `$effect` + +To run _side-effects_ when the component is mounted to the DOM, and when values change, we can use the `$effect` rune ([demo](/playground/untitled#H4sIAAAAAAAAE31T24rbMBD9lUG7kAQ2sbdlX7xOYNk_aB_rQhRpbAsU2UiTW0P-vbrYubSlYGzmzMzROTPymdVKo2PFjzMzfIusYB99z14YnfoQuD1qQh-7bmdFQEonrOppVZmKNBI49QthCc-OOOH0LZ-9jxnR6c7eUpOnuv6KeT5JFdcqbvbcBcgDz1jXKGg6ncFyBedYR6IzLrAZwiN5vtSxaJA-EzadfJEjKw11C6GR22-BLH8B_wxdByWpvUYtqqal2XB6RVkG1CoHB6U1WJzbnYFDiwb3aGEdDa3Bm1oH12sQLTcNPp7r56m_00mHocSG97_zd7ICUXonA5fwKbPbkE2ZtMJGGVkEdctzQi4QzSwr9prnFYNk5hpmqVuqPQjNnfOJoMF22lUsrq_UfIN6lfSVyvQ7grB3X2mjMZYO3XO9w-U5iLx42qg29md3BP_ni5P4gy9ikTBlHxjLzAtPDlyYZmRdjAbGq7HprEQ7p64v4LU_guu0kvAkhBim3nMplWl8FreQD-CW20aZR0wq12t-KqDWeBywhvexKC3memmDwlHAv9q4Vo2ZK8KtK0CgX7u9J8wXbzdKv-nRnfF_2baTqlYoWUF2h5efl9-n0O6koAMAAA==)): + +```svelte + + + +``` + +The function passed to `$effect` will run when the component mounts, and will re-run after any changes to the values it reads that were declared with `$state` or `$derived` (including those passed in with `$props`). Re-runs are batched (i.e. changing `color` and `size` in the same moment won't cause two separate runs), and happen after any DOM updates have been applied. + +> [!LEGACY] +> In Svelte 4, you could use reactive statements for this. +> +> ```svelte +> +> +> +> ``` +> +> This only worked at the top level of a component. + +# What are runes? + +> [!NOTE] **rune** /ro͞on/ _noun_ +> +> A letter or mark used as a mystical or magic symbol. + +Runes are symbols that you use in `.svelte` and `.svelte.js`/`.svelte.ts` files to control the Svelte compiler. If you think of Svelte as a language, runes are part of the syntax — they are _keywords_. + +Runes have a `$` prefix and look like functions: + +```js +let message = $state('hello'); +``` + +They differ from normal JavaScript functions in important ways, however: + +- You don't need to import them — they are part of the language +- They're not values — you can't assign them to a variable or pass them as arguments to a function +- Just like JavaScript keywords, they are only valid in certain positions (the compiler will help you if you put them in the wrong place) + +> [!LEGACY] +> Runes didn't exist prior to Svelte 5. + +# $state + +The `$state` rune allows you to create _reactive state_, which means that your UI _reacts_ when it changes. + +```svelte + + + +``` + +Unlike other frameworks you may have encountered, there is no API for interacting with state — `count` is just a number, rather than an object or a function, and you can update it like you would update any other variable. + +### Deep state + +If `$state` is used with an array or a simple object, the result is a deeply reactive _state proxy_. [Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) allow Svelte to run code when you read or write properties, including via methods like `array.push(...)`, triggering granular updates. + +> [!NOTE] Classes like `Set` and `Map` will not be proxied, but Svelte provides reactive implementations for various built-ins like these that can be imported from [`svelte/reactivity`](./svelte-reactivity). + +State is proxified recursively until Svelte finds something other than an array or simple object. In a case like this... + +```js +let todos = $state([ + { + done: false, + text: 'add more todos' + } +]); +``` + +...modifying an individual todo's property will trigger updates to anything in your UI that depends on that specific property: + +```js +let todos = [{ done: false, text: 'add more todos' }]; +// ---cut--- +todos[0].done = !todos[0].done; +``` + +If you push a new object to the array, it will also be proxified: + +```js +// @filename: ambient.d.ts +declare global { + const todos: Array<{ done: boolean, text: string }> +} + +// @filename: index.js +// ---cut--- +todos.push({ + done: false, + text: 'eat lunch' +}); +``` + +> [!NOTE] When you update properties of proxies, the original object is _not_ mutated. + +Note that if you destructure a reactive value, the references are not reactive — as in normal JavaScript, they are evaluated at the point of destructuring: + +```js +let todos = [{ done: false, text: 'add more todos' }]; +// ---cut--- +let { done, text } = todos[0]; + +// this will not affect the value of `done` +todos[0].done = !todos[0].done; +``` + +### Classes + +You can also use `$state` in class fields (whether public or private): + +```js +// @errors: 7006 2554 +class Todo { + done = $state(false); + text = $state(); + + constructor(text) { + this.text = text; + } + + reset() { + this.text = ''; + this.done = false; + } +} +``` + +> [!NOTE] The compiler transforms `done` and `text` into `get`/`set` methods on the class prototype referencing private fields. This means the properties are not enumerable. + +When calling methods in JavaScript, the value of [`this`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) matters. This won't work, because `this` inside the `reset` method will be the ` +``` + +You can either use an inline function... + +```svelte + +``` + +...or use an arrow function in the class definition: + +```js +// @errors: 7006 2554 +class Todo { + done = $state(false); + text = $state(); + + constructor(text) { + this.text = text; + } + + +++reset = () => {+++ + this.text = ''; + this.done = false; + } +} +``` + +## `$state.raw` + +In cases where you don't want objects and arrays to be deeply reactive you can use `$state.raw`. + +State declared with `$state.raw` cannot be mutated; it can only be _reassigned_. In other words, rather than assigning to a property of an object, or using an array method like `push`, replace the object or array altogether if you'd like to update it: + +```js +let person = $state.raw({ + name: 'Heraclitus', + age: 49 +}); + +// this will have no effect +person.age += 1; + +// this will work, because we're creating a new person +person = { + name: 'Heraclitus', + age: 50 +}; +``` + +This can improve performance with large arrays and objects that you weren't planning to mutate anyway, since it avoids the cost of making them reactive. Note that raw state can _contain_ reactive state (for example, a raw array of reactive objects). + +## `$state.snapshot` + +To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snapshot`: + +```svelte + +``` + +This is handy when you want to pass some state to an external library or API that doesn't expect a proxy, such as `structuredClone`. + +## Passing state into functions + +JavaScript is a _pass-by-value_ language — when you call a function, the arguments are the _values_ rather than the _variables_. In other words: + +```js +/// file: index.js +// @filename: index.js +// ---cut--- +/** + * @param {number} a + * @param {number} b + */ +function add(a, b) { + return a + b; +} + +let a = 1; +let b = 2; +let total = add(a, b); +console.log(total); // 3 + +a = 3; +b = 4; +console.log(total); // still 3! +``` + +If `add` wanted to have access to the _current_ values of `a` and `b`, and to return the current `total` value, you would need to use functions instead: + +```js +/// file: index.js +// @filename: index.js +// ---cut--- +/** + * @param {() => number} getA + * @param {() => number} getB + */ +function add(+++getA, getB+++) { + return +++() => getA() + getB()+++; +} + +let a = 1; +let b = 2; +let total = add+++(() => a, () => b)+++; +console.log(+++total()+++); // 3 + +a = 3; +b = 4; +console.log(+++total()+++); // 7 +``` + +State in Svelte is no different — when you reference something declared with the `$state` rune... + +```js +let a = +++$state(1)+++; +let b = +++$state(2)+++; +``` + +...you're accessing its _current value_. + +Note that 'functions' is broad — it encompasses properties of proxies and [`get`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)/[`set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set) properties... + +```js +/// file: index.js +// @filename: index.js +// ---cut--- +/** + * @param {{ a: number, b: number }} input + */ +function add(input) { + return { + get value() { + return input.a + input.b; + } + }; +} + +let input = $state({ a: 1, b: 2 }); +let total = add(input); +console.log(total.value); // 3 + +input.a = 3; +input.b = 4; +console.log(total.value); // 7 +``` + +...though if you find yourself writing code like that, consider using [classes](#Classes) instead. + +# $derived + +Derived state is declared with the `$derived` rune: + +```svelte + + + + +

    {count} doubled is {doubled}

    +``` + +The expression inside `$derived(...)` should be free of side-effects. Svelte will disallow state changes (e.g. `count++`) inside derived expressions. + +As with `$state`, you can mark class fields as `$derived`. + +> [!NOTE] Code in Svelte components is only executed once at creation. Without the `$derived` rune, `doubled` would maintain its original value even when `count` changes. + +## `$derived.by` + +Sometimes you need to create complex derivations that don't fit inside a short expression. In these cases, you can use `$derived.by` which accepts a function as its argument. + +```svelte + + + +``` + +In essence, `$derived(expression)` is equivalent to `$derived.by(() => expression)`. + +## Understanding dependencies + +Anything read synchronously inside the `$derived` expression (or `$derived.by` function body) is considered a _dependency_ of the derived state. When the state changes, the derived will be marked as _dirty_ and recalculated when it is next read. + +To exempt a piece of state from being treated as a dependency, use [`untrack`](svelte#untrack). + +# $effect + +Effects are what make your application _do things_. When Svelte runs an effect function, it tracks which pieces of state (and derived state) are accessed (unless accessed inside [`untrack`](svelte#untrack)), and re-runs the function when that state later changes. + +Most of the effects in a Svelte app are created by Svelte itself — they're the bits that update the text in `

    hello {name}!

    ` when `name` changes, for example. + +But you can also create your own effects with the `$effect` rune, which is useful when you need to synchronize an external system (whether that's a library, or a `` element, or something across a network) with state inside your Svelte app. + +> [!NOTE] Avoid overusing `$effect`! When you do too much work in effects, code often becomes difficult to understand and maintain. See [when not to use `$effect`](#When-not-to-use-$effect) to learn about alternative approaches. + +Your effects run after the component has been mounted to the DOM, and in a [microtask](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide) after state changes ([demo](/playground/untitled#H4sIAAAAAAAAE31S246bMBD9lZF3pSRSAqTVvrCAVPUP2sdSKY4ZwJJjkD0hSVH-vbINuWxXfQH5zMyZc2ZmZLVUaFn6a2R06ZGlHmBrpvnBvb71fWQHVOSwPbf4GS46TajJspRlVhjZU1HqkhQSWPkHIYdXS5xw-Zas3ueI6FRn7qHFS11_xSRZhIxbFtcDtw7SJb1iXaOg5XIFeQGjzyPRaevYNOGZIJ8qogbpe8CWiy_VzEpTXiQUcvPDkSVrSNZz1UlW1N5eLcqmpdXUvaQ4BmqlhZNUCgxuzFHDqUWNAxrYeUM76AzsnOsdiJbrBp_71lKpn3RRbii-4P3f-IMsRxS-wcDV_bL4PmSdBa2wl7pKnbp8DMgVvJm8ZNskKRkEM_OzyOKQFkgqOYBQ3Nq89Ns0nbIl81vMFN-jKoLMTOr-SOBOJS-Z8f5Y6D1wdcR8dFqvEBdetK-PHwj-z-cH8oHPY54wRJ8Ys7iSQ3Bg3VA9azQbmC9k35kKzYa6PoVtfwbbKVnBixBiGn7Pq0rqJoUtHiCZwAM3jdTPWCVtr_glhVrhecIa3vuksJ_b7TqFs4DPyriSjd5IwoNNQaAmNI-ESfR2p8zimzvN1swdCkvJHPH6-_oX8o1SgcIDAAA=)): + +```svelte + + + +``` + +Re-runs are batched (i.e. changing `color` and `size` in the same moment won't cause two separate runs), and happen after any DOM updates have been applied. + +You can place `$effect` anywhere, not just at the top level of a component, as long as it is called during component initialization (or while a parent effect is active). It is then tied to the lifecycle of the component (or parent effect) and will therefore destroy itself when the component unmounts (or the parent effect is destroyed). + +You can return a function from `$effect`, which will run immediately before the effect re-runs, and before it is destroyed ([demo](/playground/untitled#H4sIAAAAAAAAE42RQY-bMBCF_8rI2kPopiXpMQtIPfbeW6m0xjyKtWaM7CFphPjvFVB2k2oPe7LmzXzyezOjaqxDVKefo5JrD3VaBLVXrLu5-tb3X-IZTmat0hHv6cazgCWqk8qiCbaXouRSHISMH1gop4coWrA7JE9bp7PO2QjjuY5vA8fDYZ3hUh7QNDCy2yWUFzTOUilpSj9aG-linaMKFGACtKCmSwvGGYGeLQvCWbtnMq3m34grajxHoa1JOUXI93_V_Sfz7Oz7Mafj0ypN-zvHm8dSAmQITP_xaUq2IU1GO1dp80I2Uh_82dao92Rl9R8GvgF0QrbrUFstcFeq0PgAkha0LoICPoeB4w1SJUvsZcj4rvcMlvmvGlGCv6J-DeSgw2vabQnJlm55p7nM0rcTctYei3HZxZSl7XHVqkHEM3k2zpqXfFyj393zU05fpyI6f0HI0hUoPoamC9roKDeo2ivBH1EnCQOmX9NfYw2GHrgCAAA=)). + +```svelte + + +

    {count}

    + + + +``` + +### Understanding dependencies + +`$effect` automatically picks up any reactive values (`$state`, `$derived`, `$props`) that are _synchronously_ read inside its function body and registers them as dependencies. When those dependencies change, the `$effect` schedules a rerun. + +Values that are read _asynchronously_ — after an `await` or inside a `setTimeout`, for example — will not be tracked. Here, the canvas will be repainted when `color` changes, but not when `size` changes ([demo](/playground/untitled#H4sIAAAAAAAAE31T246bMBD9lZF3pWSlBEirfaEQqdo_2PatVIpjBrDkGGQPJGnEv1e2IZfVal-wfHzmzJyZ4cIqqdCy9M-F0blDlnqArZjmB3f72XWRHVCRw_bc4me4aDWhJstSlllhZEfbQhekkMDKfwg5PFvihMvX5OXH_CJa1Zrb0-Kpqr5jkiwC48rieuDWQbqgZ6wqFLRcvkC-hYvnkWi1dWqa8ESQTxFRjfQWsOXiWzmr0sSLhEJu3p1YsoJkNUcdZUnN9dagrBu6FVRQHAM10sJRKgUG16bXcGxQ44AGdt7SDkTDdY02iqLHnJVU6hedlWuIp94JW6Tf8oBt_8GdTxlF0b4n0C35ZLBzXb3mmYn3ae6cOW74zj0YVzDNYXRHFt9mprNgHfZSl6mzml8CMoLvTV6wTZIUDEJv5us2iwMtiJRyAKG4tXnhl8O0yhbML0Wm-B7VNlSSSd31BG7z8oIZZ6dgIffAVY_5xdU9Qrz1Bnx8fCfwtZ7v8Qc9j3nB8PqgmMWlHIID6-bkVaPZwDySfWtKNGtquxQ23Qlsq2QJT0KIqb8dL0up6xQ2eIBkAg_c1FI_YqW0neLnFCqFpwmreedJYT7XX8FVOBfwWRhXstZrSXiwKQjUhOZeMIleb5JZfHWn2Yq5pWEpmR7Hv-N_wEqT8hEEAAA=)): + +```ts +// @filename: index.ts +declare let canvas: { + width: number; + height: number; + getContext(type: '2d', options?: CanvasRenderingContext2DSettings): CanvasRenderingContext2D; +}; +declare let color: string; +declare let size: number; + +// ---cut--- +$effect(() => { + const context = canvas.getContext('2d'); + context.clearRect(0, 0, canvas.width, canvas.height); + + // this will re-run whenever `color` changes... + context.fillStyle = color; + + setTimeout(() => { + // ...but not when `size` changes + context.fillRect(0, 0, size, size); + }, 0); +}); +``` + +An effect only reruns when the object it reads changes, not when a property inside it changes. (If you want to observe changes _inside_ an object at dev time, you can use [`$inspect`]($inspect).) + +```svelte + + + + +

    {state.value} doubled is {derived.value}

    +``` + +An effect only depends on the values that it read the last time it ran. If `a` is true, changes to `b` will [not cause this effect to rerun](/playground/untitled#H4sIAAAAAAAAE3WQ0WrDMAxFf0U1hTow1vcsMfQ7lj3YjlxEXTvEymC4_vfFC6Ewtidxde8RkrJw5DGJ9j2LoO8oWnGZJvEi-GuqIn2iZ1x1istsa6dLdqaJ1RAG9sigoYdjYs0onfYJm7fdMX85q3dE59CylA30CnJtDWxjSNHjq49XeZqXEChcT9usLUAOpIbHA0yzM78oColGhDVofLS3neZSS6mqOz-XD51ZmGOAGKwne-vztk-956CL0kAJsi7decupf4l658EUZX4I8yTWt93jSI5wFC3PC5aP8g0Aje5DcQEAAA==): + +```ts +let a = false; +let b = false; +// ---cut--- +$effect(() => { + console.log('running'); + + if (a || b) { + console.log('inside if block'); + } +}); +``` + +## `$effect.pre` + +In rare cases, you may need to run code _before_ the DOM updates. For this we can use the `$effect.pre` rune: + +```svelte + + +
    + {#each messages as message} +

    {message}

    + {/each} +
    +``` + +Apart from the timing, `$effect.pre` works exactly like `$effect`. + +## `$effect.tracking` + +The `$effect.tracking` rune is an advanced feature that tells you whether or not the code is running inside a tracking context, such as an effect or inside your template ([demo](/playground/untitled#H4sIAAAAAAAACn3PwYrCMBDG8VeZDYIt2PYeY8Dn2HrIhqkU08nQjItS-u6buAt7UDzmz8ePyaKGMWBS-nNRcmdU-hHUTpGbyuvI3KZvDFLal0v4qvtIgiSZUSb5eWSxPfWSc4oB2xDP1XYk8HHiSHkICeXKeruDDQ4Demlldv4y0rmq6z10HQwuJMxGVv4mVVXDwcJS0jP9u3knynwtoKz1vifT_Z9Jhm0WBCcOTlDD8kyspmML5qNpHg40jc3fFryJ0iWsp_UHgz3180oBAAA=)): + +```svelte + + +

    in template: {$effect.tracking()}

    +``` + +This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects. Here's a `readable` function that listens to changes from a callback function as long as it's inside a tracking context: + +```ts +import { tick } from 'svelte'; + +export default function readable( + initial_value: T, + start: (callback: (update: (v: T) => T) => T) => () => void +) { + let value = $state(initial_value); + + let subscribers = 0; + let stop: null | (() => void) = null; + + return { + get value() { + // If in a tracking context ... + if ($effect.tracking()) { + $effect(() => { + // ...and there's no subscribers yet... + if (subscribers === 0) { + // ...invoke the function and listen to changes to update state + stop = start((fn) => (value = fn(value))); + } + + subscribers++; + + // The return callback is called once a listener unlistens + return () => { + tick().then(() => { + subscribers--; + // If it was the last subscriber... + if (subscribers === 0) { + // ...stop listening to changes + stop?.(); + stop = null; + } + }); + }; + }); + } + + return value; + } + }; +} +``` + +## `$effect.root` + +The `$effect.root` rune is an advanced feature that creates a non-tracked scope that doesn't auto-cleanup. This is useful for nested effects that you want to manually control. This rune also allows for the creation of effects outside of the component initialisation phase. + +```svelte + +``` + +## When not to use `$effect` + +In general, `$effect` is best considered something of an escape hatch — useful for things like analytics and direct DOM manipulation — rather than a tool you should use frequently. In particular, avoid using it to synchronise state. Instead of this... + +```svelte + +``` + +...do this: + +```svelte + +``` + +> [!NOTE] For things that are more complicated than a simple expression like `count * 2`, you can also use `$derived.by`. + +You might be tempted to do something convoluted with effects to link one value to another. The following example shows two inputs for "money spent" and "money left" that are connected to each other. If you update one, the other should update accordingly. Don't use effects for this ([demo](/playground/untitled#H4sIAAAAAAAACpVRy26DMBD8FcvKgUhtoIdeHBwp31F6MGSJkBbHwksEQvx77aWQqooq9bgzOzP7mGTdIHipPiZJowOpGJAv0po2VmfnDv4OSBErjYdneHWzBJaCjcx91TWOToUtCIEE3cig0OIty44r5l1oDtjOkyFIsv3GINQ_CNYyGegd1DVUlCR7oU9iilDUcP8S8roYs9n8p2wdYNVFm4csTx872BxNCcjr5I11fdgonEkXsjP2CoUUZWMv6m6wBz2x7yxaM-iJvWeRsvSbSVeUy5i0uf8vKA78NIeJLSZWv1I8jQjLdyK4XuTSeIdmVKJGGI4LdjVOiezwDu1yG74My8PLCQaSiroe5s_5C2PHrkVGAgAA)): + +```svelte + + + + + +``` + +Instead, use callbacks where possible ([demo](/playground/untitled#H4sIAAAAAAAACo1SMW6EMBD8imWluFMSIEUaDiKlvy5lSOHjlhOSMRZeTiDkv8deMEEJRcqdmZ1ZjzzxqpZgePo5cRw18JQA_sSVaPz0rnVk7iDRYxdhYA8vW4Wg0NnwzJRdrfGtUAVKQIYtCsly9pIkp4AZ7cQOezAoEA7JcWUkVBuCdol0dNWrEutWsV5fHfnhPQ5wZJMnCwyejxCh6G6A0V3IHk4zu_jOxzzPBxBld83PTr7xXrb3rUNw8PbiYJ3FP22oTIoLSComq5XuXTeu8LzgnVA3KDgj13wiQ8taRaJ82rzXskYM-URRlsXktejjgNLoo9e4fyf70_8EnwncySX1GuunX6kGRwnzR_BgaPNaGy3FmLJKwrCUeBM6ZUn0Cs2mOlp3vwthQJ5i14P9st9vZqQlsQIAAA==)): + +```svelte + + + + + +``` + +If you need to use bindings, for whatever reason (for example when you want some kind of "writable `$derived`"), consider using getters and setters to synchronise state ([demo](/playground/untitled#H4sIAAAAAAAACpWRwW6DMBBEf8WyekikFOihFwcq9TvqHkyyQUjGsfCCQMj_XnvBNKpy6Qn2DTOD1wu_tRocF18Lx9kCFwT4iRvVxenT2syNoDGyWjl4xi93g2AwxPDSXfrW4oc0EjUgwzsqzSr2VhTnxJwNHwf24lAhHIpjVDZNwy1KS5wlNoGMSg9wOCYksQccerMlv65p51X0p_Xpdt_4YEy9yTkmV3z4MJT579-bUqsaNB2kbI0dwlnCgirJe2UakJzVrbkKaqkWivasU1O1ULxnOVk3JU-Uxti0p_-vKO4no_enbQ_yXhnZn0aHs4b1jiJMK7q2zmo1C3bTMG3LaZQVrMjeoSPgaUtkDxePMCEX2Ie6b_8D4WyJJEwCAAA=)): + +```svelte + + + + + +``` + +If you absolutely have to update `$state` within an effect and run into an infinite loop because you read and write to the same `$state`, use [untrack](svelte#untrack). + +# $props + +The inputs to a component are referred to as _props_, which is short for _properties_. You pass props to components just like you pass attributes to elements: + +```svelte + + + + +``` + +On the other side, inside `MyComponent.svelte`, we can receive props with the `$props` rune... + +```svelte + + + +

    this component is {props.adjective}

    +``` + +...though more commonly, you'll [_destructure_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) your props: + +```svelte + + + +

    this component is {+++adjective+++}

    +``` + +## Fallback values + +Destructuring allows us to declare fallback values, which are used if the parent component does not set a given prop: + +```js +let { adjective = 'happy' } = $props(); +``` + +> [!NOTE] Fallback values are not turned into reactive state proxies (see [Updating props](#Updating-props) for more info) + +## Renaming props + +We can also use the destructuring assignment to rename props, which is necessary if they're invalid identifiers, or a JavaScript keyword like `super`: + +```js +let { super: trouper = 'lights are gonna find me' } = $props(); +``` + +## Rest props + +Finally, we can use a _rest property_ to get, well, the rest of the props: + +```js +let { a, b, c, ...others } = $props(); +``` + +## Updating props + +References to a prop inside a component update when the prop itself updates — when `count` changes in `App.svelte`, it will also change inside `Child.svelte`. But the child component is able to temporarily override the prop value, which can be useful for unsaved ephemeral state ([demo](/playground/untitled#H4sIAAAAAAAAE6WQ0WrDMAxFf0WIQR0Wmu3VTQJln7HsIfVcZubIxlbGRvC_DzuBraN92qPula50tODZWB1RPi_IX16jLALWSOOUq6P3-_ihLWftNEZ9TVeOWBNHlNhGFYznfqCBzeRdYHh6M_YVzsFNsNs3pdpGd4eBcqPVDMrNxNDBXeSRtXioDgO1zU8ataeZ2RE4Utao924RFXQ9iHXwvoPHKpW1xY4g_Bg0cSVhKS0p560Za95612ZC02ONrD8ZJYdZp_rGQ37ff_mSP86Np2TWZaNNmdcH56P4P67K66_SXoK9pG-5dF5Z9QEAAA==)): + +```svelte + + + + + + +``` + +```svelte + + + + +``` + +While you can temporarily _reassign_ props, you should not _mutate_ props unless they are [bindable]($bindable). + +If the prop is a regular object, the mutation will have no effect ([demo](/playground/untitled#H4sIAAAAAAAAE3WQwU7DMBBEf2W1QmorQgJXk0RC3PkBwiExG9WQrC17U4Es_ztKUkQp9OjxzM7bjcjtSKjwyfKNp1aLORA4b13ADHszUED1HFE-3eyaBcy-Mw_O5eFAg8xa1wb6T9eWhVgCKiyD9sZJ3XAjZnTWCzzuzfAKvbcjbPJieR2jm_uGy-InweXqtd0baaliBG0nFgW3kBIUNWYo9CGoxE-UsgvIpw2_oc9-LmAPJBCPDJCggqvlVtvdH9puErEMlvVg9HsVtzuoaojzkKKAfRuALVDfk5ZZW0fmy05wXcFdwyktlUs-KIinljTXrRVnm7-kL9dYLVbUAQAA)): + +```svelte + + + + +``` + +```svelte + + + + +``` + +If the prop is a reactive state proxy, however, then mutations _will_ have an effect but you will see an [`ownership_invalid_mutation`](runtime-warnings#Client-warnings-ownership_invalid_mutation) warning, because the component is mutating state that does not 'belong' to it ([demo](/playground/untitled#H4sIAAAAAAAAE3WR0U7DMAxFf8VESBuiauG1WycheOEbKA9p67FA6kSNszJV-XeUZhMw2GN8r-1znUmQ7FGU4pn2UqsOes-SlSGRia3S6ET5Mgk-2OiJBZGdOh6szd0eNcdaIx3-V28NMRI7UYq1awdleVNTzaq3ZmB43CndwXYwPSzyYn4dWxermqJRI4Np3rFlqODasWRcTtAaT1zCHYSbVU3r4nsyrdPMKTUFKDYiE4yfLEoePIbsQpqfy3_nOVMuJIqg0wk1RFg7GOuWfwEbz2wIDLVatR_VtLyBagNTHFIUMCqtoZXeIfAOU1JoUJsR2IC3nWTMjt7GM4yKdyBhlAMpesvhydCC0y_i0ZagHByMh26WzUhXUUxKnpbcVnBfUwhznJnNlac7JkuIURL-2VVfwxflyrWcSQIAAA==)): + +```svelte + + + + +``` + +```svelte + + + + +``` + +The fallback value of a prop not declared with `$bindable` is left untouched — it is not turned into a reactive state proxy — meaning mutations will not cause updates ([demo](/playground/untitled#H4sIAAAAAAAAE3WQwU7DMBBEf2VkIbUVoYFraCIh7vwA4eC4G9Wta1vxpgJZ_nfkBEQp9OjxzOzTRGHlkUQlXpy9G0gq1idCL43ppDrAD84HUYheGwqieo2CP3y2Z0EU3-En79fhRIaz1slA_-nKWSbLQVRiE9SgPTetbVkfvRsYzztttugHd8RiXU6vr-jisbWb8idhN7O3bEQhmN5ZVDyMlIorcOddv_Eufq4AGmJEuG5PilEjQrnRcoV7JCTUuJlGWq7-YHYjs7NwVhmtDnVcrlA3iLmzLLGTAdaB-j736h68Oxv-JM1I0AFjoG1OzPfX023c1nhobUoT39QeKsRzS8owM8DFTG_pE6dcVl70AQAA)) + +```svelte + + + + +``` + +In summary: don't mutate props. Either use callback props to communicate changes, or — if parent and child should share the same object — use the [`$bindable`]($bindable) rune. + +## Type safety + +You can add type safety to your components by annotating your props, as you would with any other variable declaration. In TypeScript that might look like this... + +```svelte + +``` + +...while in JSDoc you can do this: + +```svelte + +``` + +You can, of course, separate the type declaration from the annotation: + +```svelte + +``` + +Adding types is recommended, as it ensures that people using your component can easily discover which props they should provide. + +# $bindable + +Ordinarily, props go one way, from parent to child. This makes it easy to understand how data flows around your app. + +In Svelte, component props can be _bound_, which means that data can also flow _up_ from child to parent. This isn't something you should do often, but it can simplify your code if used sparingly and carefully. + +It also means that a state proxy can be _mutated_ in the child. + +> [!NOTE] Mutation is also possible with normal props, but is strongly discouraged — Svelte will warn you if it detects that a component is mutating state it does not 'own'. + +To mark a prop as bindable, we use the `$bindable` rune: + + +```svelte +/// file: FancyInput.svelte + + + + + +``` + +Now, a component that uses `` can add the [`bind:`](bind) directive ([demo](/playground/untitled#H4sIAAAAAAAAE3WQwWrDMBBEf2URBSfg2nfFMZRCoYeecqx6UJx1IyqvhLUONcb_XqSkTUOSk1az7DBvJtEai0HI90nw6FHIJIhckO7i78n7IhzQctS2OuAtvXHESByEFFVoeuO5VqTYdN71DC-amvGV_MDQ9q6DrCjP0skkWymKJxYZOgxBfyKs4SGwZlxke7TWZcuVoqo8-1P1z3lraCcP2g64nk4GM5S1osrXf0JV-lrkgvGbheR-wDm_g30V8JL-1vpOCZFogpQsEsWcemtxscyhKArfOx9gjps0Lq4hzRVfemaYfu-PoIqqwKPFY_XpaIqj4tYRP7a6M3aUkD27zjSw0RTgbZN6Z8WNs66XsEP03tBXUueUJFlelvYx_wCuI3leNwIAAA==)): + + +```svelte +/// App.svelte + + + +

    {message}

    +``` + +The parent component doesn't _have_ to use `bind:` — it can just pass a normal prop. Some parents don't want to listen to what their children have to say. + +In this case, you can specify a fallback value for when no prop is passed at all: + +```js +/// file: FancyInput.svelte +let { value = $bindable('fallback'), ...props } = $props(); +``` + +# $inspect + +> [!NOTE] `$inspect` only works during development. In a production build it becomes a noop. + +The `$inspect` rune is roughly equivalent to `console.log`, with the exception that it will re-run whenever its argument changes. `$inspect` tracks reactive state deeply, meaning that updating something inside an object or array using fine-grained reactivity will cause it to re-fire ([demo](/playground/untitled#H4sIAAAAAAAACkWQ0YqDQAxFfyUMhSotdZ-tCvu431AXtGOqQ2NmmMm0LOK_r7Utfby5JzeXTOpiCIPKT5PidkSVq2_n1F7Jn3uIcEMSXHSw0evHpAjaGydVzbUQCmgbWaCETZBWMPlKj29nxBDaHj_edkAiu12JhdkYDg61JGvE_s2nR8gyuBuiJZuDJTyQ7eE-IEOzog1YD80Lb0APLfdYc5F9qnFxjiKWwbImo6_llKRQVs-2u91c_bD2OCJLkT3JZasw7KLA2XCX31qKWE6vIzNk1fKE0XbmYrBTufiI8-_8D2cUWBA_AQAA)): + +```svelte + + + + +``` + +## $inspect(...).with + +`$inspect` returns a property `with`, which you can invoke with a callback, which will then be invoked instead of `console.log`. The first argument to the callback is either `"init"` or `"update"`; subsequent arguments are the values passed to `$inspect` ([demo](/playground/untitled#H4sIAAAAAAAACkVQ24qDMBD9lSEUqlTqPlsj7ON-w7pQG8c2VCchmVSK-O-bKMs-DefKYRYx6BG9qL4XQd2EohKf1opC8Nsm4F84MkbsTXAqMbVXTltuWmp5RAZlAjFIOHjuGLOP_BKVqB00eYuKs82Qn2fNjyxLtcWeyUE2sCRry3qATQIpJRyD7WPVMf9TW-7xFu53dBcoSzAOrsqQNyOe2XUKr0Xi5kcMvdDB2wSYO-I9vKazplV1-T-d6ltgNgSG1KjVUy7ZtmdbdjqtzRcphxMS1-XubOITJtPrQWMvKnYB15_1F7KKadA_AQAA)): + +```svelte + + + +``` + +A convenient way to find the origin of some change is to pass `console.trace` to `with`: + +```js +// @errors: 2304 +$inspect(stuff).with(console.trace); +``` + +## $inspect.trace(...) + +This rune, added in 5.14, causes the surrounding function to be _traced_ in development. Any time the function re-runs as part of an [effect]($effect) or a [derived]($derived), information will be printed to the console about which pieces of reactive state caused the effect to fire. + +```svelte + +``` + +`$inspect.trace` takes an optional first argument which will be used as the label. + +# $host + +When compiling a component as a custom element, the `$host` rune provides access to the host element, allowing you to (for example) dispatch custom events ([demo](/playground/untitled#H4sIAAAAAAAAE41Ry2rDMBD8FSECtqkTt1fHFpSSL-ix7sFRNkTEXglrnTYY_3uRlDgxTaEHIfYxs7szA9-rBizPPwZOZwM89wmecqxbF70as7InaMjltrWFR3mpkQDJ8pwXVnbKkKiwItUa3RGLVtk7gTHQXRDR2lXda4CY1D0SK9nCUk0QPyfrCovsRoNFe17aQOAwGncgO2gBqRzihJXiQrEs2csYOhQ-7HgKHaLIbpRhhBG-I2eD_8ciM4KnnOCbeE5dD2P6h0Dz0-Yi_arNhPLJXBtSGi2TvSXdbpqwdsXvjuYsC1veabvvUTog2ylrapKH2G2XsMFLS4uDthQnq2t1cwKkGOGLvYU5PvaQxLsxOkPmsm97Io1Mo2yUPF6VnOZFkw1RMoopKLKAE_9gmGxyDFMwMcwN-Bx_ABXQWmOtAgAA)): + + +```svelte +/// file: Stepper.svelte + + + + + + +``` + + +```svelte +/// file: App.svelte + + + count -= 1} + onincrement={() => count += 1} +> + +

    count: {count}

    +``` + +# Basic markup + +Markup inside a Svelte component can be thought of as HTML++. + +## Tags + +A lowercase tag, like `
    `, denotes a regular HTML element. A capitalised tag or a tag that uses dot notation, such as `` or ``, indicates a _component_. + +```svelte + + +
    + +
    +``` + +## Element attributes + +By default, attributes work exactly like their HTML counterparts. + +```svelte +
    + +
    +``` + +As in HTML, values may be unquoted. + + +```svelte + +``` + +Attribute values can contain JavaScript expressions. + +```svelte +page {p} +``` + +Or they can _be_ JavaScript expressions. + +```svelte + +``` + +Boolean attributes are included on the element if their value is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) and excluded if it's [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy). + +All other attributes are included unless their value is [nullish](https://developer.mozilla.org/en-US/docs/Glossary/Nullish) (`null` or `undefined`). + +```svelte + +
    This div has no title attribute
    +``` + +> [!NOTE] Quoting a singular expression does not affect how the value is parsed, but in Svelte 6 it will cause the value to be coerced to a string: +> +> +> ```svelte +> +> ``` + +When the attribute name and value match (`name={name}`), they can be replaced with `{name}`. + +```svelte + + +``` + +## Component props + +By convention, values passed to components are referred to as _properties_ or _props_ rather than _attributes_, which are a feature of the DOM. + +As with elements, `name={name}` can be replaced with the `{name}` shorthand. + +```svelte + +``` + +_Spread attributes_ allow many attributes or properties to be passed to an element or component at once. + +An element or component can have multiple spread attributes, interspersed with regular ones. + +```svelte + +``` + +## Events + +Listening to DOM events is possible by adding attributes to the element that start with `on`. For example, to listen to the `click` event, add the `onclick` attribute to a button: + +```svelte + +``` + +Event attributes are case sensitive. `onclick` listens to the `click` event, `onClick` listens to the `Click` event, which is different. This ensures you can listen to custom events that have uppercase characters in them. + +Because events are just attributes, the same rules as for attributes apply: + +- you can use the shorthand form: `` +- you can spread them: `` + +Timing-wise, event attributes always fire after events from bindings (e.g. `oninput` always fires after an update to `bind:value`). Under the hood, some event handlers are attached directly with `addEventListener`, while others are _delegated_. + +When using `ontouchstart` and `ontouchmove` event attributes, the handlers are [passive](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#using_passive_listeners) for better performance. This greatly improves responsiveness by allowing the browser to scroll the document immediately, rather than waiting to see if the event handler calls `event.preventDefault()`. + +In the very rare cases that you need to prevent these event defaults, you should use [`on`](svelte-events#on) instead (for example inside an action). + +### Event delegation + +To reduce memory footprint and increase performance, Svelte uses a technique called event delegation. This means that for certain events — see the list below — a single event listener at the application root takes responsibility for running any handlers on the event's path. + +There are a few gotchas to be aware of: + +- when you manually dispatch an event with a delegated listener, make sure to set the `{ bubbles: true }` option or it won't reach the application root +- when using `addEventListener` directly, avoid calling `stopPropagation` or the event won't reach the application root and handlers won't be invoked. Similarly, handlers added manually inside the application root will run _before_ handlers added declaratively deeper in the DOM (with e.g. `onclick={...}`), in both capturing and bubbling phases. For these reasons it's better to use the `on` function imported from `svelte/events` rather than `addEventListener`, as it will ensure that order is preserved and `stopPropagation` is handled correctly. + +The following event handlers are delegated: + +- `beforeinput` +- `click` +- `change` +- `dblclick` +- `contextmenu` +- `focusin` +- `focusout` +- `input` +- `keydown` +- `keyup` +- `mousedown` +- `mousemove` +- `mouseout` +- `mouseover` +- `mouseup` +- `pointerdown` +- `pointermove` +- `pointerout` +- `pointerover` +- `pointerup` +- `touchend` +- `touchmove` +- `touchstart` + +## Text expressions + +A JavaScript expression can be included as text by surrounding it with curly braces. + +```svelte +{expression} +``` + +Curly braces can be included in a Svelte template by using their [HTML entity](https://developer.mozilla.org/docs/Glossary/Entity) strings: `{`, `{`, or `{` for `{` and `}`, `}`, or `}` for `}`. + +If you're using a regular expression (`RegExp`) [literal notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#literal_notation_and_constructor), you'll need to wrap it in parentheses. + + +```svelte +

    Hello {name}!

    +

    {a} + {b} = {a + b}.

    + +
    {(/^[A-Za-z ]+$/).test(value) ? x : y}
    +``` + +The expression will be stringified and escaped to prevent code injections. If you want to render HTML, use the `{@html}` tag instead. + +```svelte +{@html potentiallyUnsafeHtmlString} +``` + +> [!NOTE] Make sure that you either escape the passed string or only populate it with values that are under your control in order to prevent [XSS attacks](https://owasp.org/www-community/attacks/xss/) + +## Comments + +You can use HTML comments inside components. + +```svelte +

    Hello world

    +``` + +Comments beginning with `svelte-ignore` disable warnings for the next block of markup. Usually, these are accessibility warnings; make sure that you're disabling them for a good reason. + +```svelte + + +``` + +You can add a special comment starting with `@component` that will show up when hovering over the component name in other files. + +````svelte + + + +
    +

    + Hello, {name} +

    +
    +```` + +# {#if ...} + +```svelte + +{#if expression}...{/if} +``` + +```svelte + +{#if expression}...{:else if expression}...{/if} +``` + +```svelte + +{#if expression}...{:else}...{/if} +``` + +Content that is conditionally rendered can be wrapped in an if block. + +```svelte +{#if answer === 42} +

    what was the question?

    +{/if} +``` + +Additional conditions can be added with `{:else if expression}`, optionally ending in an `{:else}` clause. + +```svelte +{#if porridge.temperature > 100} +

    too hot!

    +{:else if 80 > porridge.temperature} +

    too cold!

    +{:else} +

    just right!

    +{/if} +``` + +(Blocks don't have to wrap elements, they can also wrap text within elements.) + +# {#each ...} + +```svelte + +{#each expression as name}...{/each} +``` + +```svelte + +{#each expression as name, index}...{/each} +``` + +Iterating over values can be done with an each block. The values in question can be arrays, array-like objects (i.e. anything with a `length` property), or iterables like `Map` and `Set` — in other words, anything that can be used with `Array.from`. + +```svelte +

    Shopping list

    +
      + {#each items as item} +
    • {item.name} x {item.qty}
    • + {/each} +
    +``` + +An each block can also specify an _index_, equivalent to the second argument in an `array.map(...)` callback: + +```svelte +{#each items as item, i} +
  • {i + 1}: {item.name} x {item.qty}
  • +{/each} +``` + +## Keyed each blocks + +```svelte + +{#each expression as name (key)}...{/each} +``` + +```svelte + +{#each expression as name, index (key)}...{/each} +``` + +If a _key_ expression is provided — which must uniquely identify each list item — Svelte will use it to diff the list when data changes, rather than adding or removing items at the end. The key can be any object, but strings and numbers are recommended since they allow identity to persist when the objects themselves change. + +```svelte +{#each items as item (item.id)} +
  • {item.name} x {item.qty}
  • +{/each} + + +{#each items as item, i (item.id)} +
  • {i + 1}: {item.name} x {item.qty}
  • +{/each} +``` + +You can freely use destructuring and rest patterns in each blocks. + +```svelte +{#each items as { id, name, qty }, i (id)} +
  • {i + 1}: {name} x {qty}
  • +{/each} + +{#each objects as { id, ...rest }} +
  • {id}
  • +{/each} + +{#each items as [id, ...rest]} +
  • {id}
  • +{/each} +``` + +## Each blocks without an item + +```svelte + +{#each expression}...{/each} +``` + +```svelte + +{#each expression, index}...{/each} +``` + +In case you just want to render something `n` times, you can omit the `as` part ([demo](/playground/untitled#H4sIAAAAAAAAE3WR0W7CMAxFf8XKNAk0WsSeUEaRpn3Guoc0MbQiJFHiMlDVf18SOrZJ48259_jaVgZmxBEZZ28thgCNFV6xBdt1GgPj7wOji0t2EqI-wa_OleGEmpLWiID_6dIaQkMxhm1UdwKpRQhVzWSaVORJNdvWpqbhAYVsYQCNZk8thzWMC_DCHMZk3wPSThNQ088I3mghD9UwSwHwlLE5PMIzVFUFq3G7WUZ2OyUvU3JOuZU332wCXTRmtPy1NgzXZtUFp8WFw9536uWqpbIgPEaDsJBW90cTOHh0KGi2XsBq5-cT6-3nPauxXqHnsHJnCFZ3CvJVkyuCQ0mFF9TZyCQ162WGvteLKfG197Y3iv_pz_fmS68Hxt8iPBPj5HscP8YvCNX7uhYCAAA=)): + +```svelte +
    + {#each { length: 8 }, rank} + {#each { length: 8 }, file} +
    + {/each} + {/each} +
    +``` + +## Else blocks + +```svelte + +{#each expression as name}...{:else}...{/each} +``` + +An each block can also have an `{:else}` clause, which is rendered if the list is empty. + +```svelte +{#each todos as todo} +

    {todo.text}

    +{:else} +

    No tasks today!

    +{/each} +``` + +# {#key ...} + +```svelte + +{#key expression}...{/key} +``` + +Key blocks destroy and recreate their contents when the value of an expression changes. When used around components, this will cause them to be reinstantiated and reinitialised: + +```svelte +{#key value} + +{/key} +``` + +It's also useful if you want a transition to play whenever a value changes: + +```svelte +{#key value} +
    {value}
    +{/key} +``` + +# {#await ...} + +```svelte + +{#await expression}...{:then name}...{:catch name}...{/await} +``` + +```svelte + +{#await expression}...{:then name}...{/await} +``` + +```svelte + +{#await expression then name}...{/await} +``` + +```svelte + +{#await expression catch name}...{/await} +``` + +Await blocks allow you to branch on the three possible states of a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — pending, fulfilled or rejected. + +```svelte +{#await promise} + +

    waiting for the promise to resolve...

    +{:then value} + +

    The value is {value}

    +{:catch error} + +

    Something went wrong: {error.message}

    +{/await} +``` + +> [!NOTE] During server-side rendering, only the pending branch will be rendered. +> +> If the provided expression is not a `Promise`, only the `:then` branch will be rendered, including during server-side rendering. + +The `catch` block can be omitted if you don't need to render anything when the promise rejects (or no error is possible). + +```svelte +{#await promise} + +

    waiting for the promise to resolve...

    +{:then value} + +

    The value is {value}

    +{/await} +``` + +If you don't care about the pending state, you can also omit the initial block. + +```svelte +{#await promise then value} +

    The value is {value}

    +{/await} +``` + +Similarly, if you only want to show the error state, you can omit the `then` block. + +```svelte +{#await promise catch error} +

    The error is {error}

    +{/await} +``` + +> [!NOTE] You can use `#await` with [`import(...)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import) to render components lazily: +> +> ```svelte +> {#await import('./Component.svelte') then { default: Component }} +> +> {/await} +> ``` + +# {#snippet ...} + +```svelte + +{#snippet name()}...{/snippet} +``` + +```svelte + +{#snippet name(param1, param2, paramN)}...{/snippet} +``` + +Snippets, and [render tags](@render), are a way to create reusable chunks of markup inside your components. Instead of writing duplicative code like [this](/playground/untitled#H4sIAAAAAAAAE5VUYW-kIBD9K8Tmsm2yXXRzvQ-s3eR-R-0HqqOQKhAZb9sz_vdDkV1t000vRmHewMx7w2AflbIGG7GnPlK8gYhFv42JthG-m9Gwf6BGcLbVXZuPSGrzVho8ZirDGpDIhldgySN5GpEMez9kaNuckY1ANJZRamRuu2ZnhEZt6a84pvs43mzD4pMsUDDi8DMkQFYCGdkvsJwblFq5uCik9bmJ4JZwUkv1eoknWigX2eGNN6aGXa6bjV8ybP-X7sM36T58SVcrIIV2xVIaA41xeD5kKqWXuqpUJEefOqVuOkL9DfBchGrzWfu0vb-RpTd3o-zBR045Ga3HfuE5BmJpKauuhbPtENlUF2sqR9jqpsPSxWsMrlngyj3VJiyYjJXb1-lMa7IWC-iSk2M5Zzh-SJjShe-siq5kpZRPs55BbSGU5YPyte4vVV_VfFXxVb10dSLf17pS2lM5HnpPxw4Zpv6x-F57p0jI3OKlVnhv5V9wPQrNYQQ9D_f6aGHlC89fq1Z3qmDkJCTCweOGF4VUFSPJvD_DhreVdA0eu8ehJJ5x91dBaBkpWm3ureCFPt3uzRv56d4kdp-2euG38XZ6dsnd3ZmPG9yRBCrzRUvi-MccOdwz3qE-fOZ7AwAhlrtTUx3c76vRhSwlFBHDtoPhefgHX3dM0PkEAAA=)... + +```svelte +{#each images as image} + {#if image.href} + +
    + {image.caption} +
    {image.caption}
    +
    +
    + {:else} +
    + {image.caption} +
    {image.caption}
    +
    + {/if} +{/each} +``` + +...you can write [this](/playground/untitled#H4sIAAAAAAAAE5VUYW-bMBD9KxbRlERKY4jWfSA02n5H6QcXDmwVbMs-lnaI_z6D7TTt1moTAnPvzvfenQ_GpBEd2CS_HxPJekjy5IfWyS7BFz0b9id0CM62ajDVjBS2MkLjqZQldoBE9KwFS-7I_YyUOPqlRGuqnKw5orY5pVpUduj3mitUln5LU3pI0_UuBp9FjTwnDr9AHETLMSeHK6xiGoWSLi9yYT034cwSRjohn17zcQPNFTs8s153sK9Uv_Yh0-5_5d7-o9zbD-UqCaRWrllSYZQxLw_HUhb0ta-y4NnJUxfUvc7QuLJSaO0a3oh2MLBZat8u-wsPnXzKQvTtVVF34xK5d69ThFmHEQ4SpzeVRediTG8rjD5vBSeN3E5JyHh6R1DQK9-iml5kjzQUN_lSgVU8DhYLx7wwjSvRkMDvTjiwF4zM1kXZ7DlF1eN3A7IG85e-zRrYEjjm0FkI4Cc7Ripm0pHOChexhcWXzreeZyRMU6Mk3ljxC9w4QH-cQZ_b3T5pjHxk1VNr1CDrnJy5QDh6XLO6FrLNSRb2l9gz0wo3S6m7HErSgLsPGMHkpDZK31jOanXeHPQz-eruLHUP0z6yTbpbrn223V70uMXNSpQSZjpL0y8hcxxpNqA6_ql3BQAxlxvfpQ_uT9GrWjQC6iRHM8D0MP0GQsIi92QEAAA=): + +```svelte +{#snippet figure(image)} +
    + {image.caption} +
    {image.caption}
    +
    +{/snippet} + +{#each images as image} + {#if image.href} + + {@render figure(image)} + + {:else} + {@render figure(image)} + {/if} +{/each} +``` + +Like function declarations, snippets can have an arbitrary number of parameters, which can have default values, and you can destructure each parameter. You cannot use rest parameters, however. + +## Snippet scope + +Snippets can be declared anywhere inside your component. They can reference values declared outside themselves, for example in the ` + +{#snippet hello(name)} +

    hello {name}! {message}!

    +{/snippet} + +{@render hello('alice')} +{@render hello('bob')} +``` + +...and they are 'visible' to everything in the same lexical scope (i.e. siblings, and children of those siblings): + +```svelte +
    + {#snippet x()} + {#snippet y()}...{/snippet} + + + {@render y()} + {/snippet} + + + {@render y()} +
    + + +{@render x()} +``` + +Snippets can reference themselves and each other ([demo](/playground/untitled#H4sIAAAAAAAAE2WPTQqDMBCFrxLiRqH1Zysi7TlqF1YnENBJSGJLCYGeo5tesUeosfYH3c2bee_jjaWMd6BpfrAU6x5oTvdS0g01V-mFPkNnYNRaDKrxGxto5FKCIaeu1kYwFkauwsoUWtZYPh_3W5FMY4U2mb3egL9kIwY0rbhgiO-sDTgjSEqSTvIDs-jiOP7i_MHuFGAL6p9BtiSbOTl0GtzCuihqE87cqtyam6WRGz_vRcsZh5bmRg3gju4Fptq_kzQBAAA=)): + +```svelte +{#snippet blastoff()} + 🚀 +{/snippet} + +{#snippet countdown(n)} + {#if n > 0} + {n}... + {@render countdown(n - 1)} + {:else} + {@render blastoff()} + {/if} +{/snippet} + +{@render countdown(10)} +``` + +## Passing snippets to components + +Within the template, snippets are values just like any other. As such, they can be passed to components as props ([demo](/playground/untitled#H4sIAAAAAAAAE3VS247aMBD9lZGpBGwDASRegonaPvQL2qdlH5zYEKvBNvbQLbL875VzAcKyj3PmzJnLGU8UOwqSkd8KJdaCk4TsZS0cyV49wYuJuQiQpGd-N2bu_ooaI1YwJ57hpVYoFDqSEepKKw3mO7VDeTTaIvxiRS1gb_URxvO0ibrS8WanIrHUyiHs7Vmigy28RmyHHmKvDMbMmFq4cQInvGSwTsBYWYoMVhCSB2rBFFPsyl0uruTlR3JZCWvlTXl1Yy_mawiR_rbZKZrellJ-5JQ0RiBUgnFhJ9OGR7HKmwVoilXeIye8DOJGfYCgRlZ3iE876TBsZPX7hPdteO75PC4QaIo8vwNPePmANQ2fMeEFHrLD7rR1jTNkW986E8C3KwfwVr8HSHOSEBT_kGRozyIkn_zQveXDL3rIfPJHtUDwzShJd_Qk3gQCbOGLsdq4yfTRJopRuin3I7nv6kL7ARRjmLdBDG3uv1mhuLA3V2mKtqNEf_oCn8p9aN-WYqH5peP4kWBl1UwJzAEPT9U7K--0fRrrWnPTXpCm1_EVdXjpNmlA8G1hPPyM1fKgMqjFHjctXGjLhZ05w0qpDhksGrybuNEHtJnCalZWsuaTlfq6nPaaBSv_HKw-K57BjzOiVj9ZKQYKzQjZodYFqydYTRN4gPhVzTDO2xnma3HsVWjaLjT8nbfwHy7Q5f2dBAAA)): + +```svelte + + +{#snippet header()} + fruit + qty + price + total +{/snippet} + +{#snippet row(d)} + {d.name} + {d.qty} + {d.price} + {d.qty * d.price} +{/snippet} + + +``` + +Think about it like passing content instead of data to a component. The concept is similar to slots in web components. + +As an authoring convenience, snippets declared directly _inside_ a component implicitly become props _on_ the component ([demo](/playground/untitled#H4sIAAAAAAAAE3VSTa_aMBD8Kyu_SkAbCA-JSzBR20N_QXt6vIMTO8SqsY29tI2s_PcqTiB8vaPHs7MzuxuIZgdBMvJLo0QlOElIJZXwJHsLBBvb_XUASc7Mb9Yu_B-hsMMK5sUzvDQahUZPMkJ96aTFfKd3KA_WOISfrFACKmcOMFmk8TWUTjY73RFLoz1C5U4SPWzhrcN2GKDrlcGEWauEnyRwxCaDdQLWyVJksII2uaMWTDPNLtzX5YX8-kgua-GcHJVXI3u5WEPb0d83O03TMZSmfRzOkG1Db7mNacOL19JagVALxoWbztq-H8U6j0SaYp2P2BGbOyQ2v8PQIFMXLKRDk177pq0zf6d8bMrzwBdd0pamyPMb-IjNEzS2f86Gz_Dwf-2F9nvNSUJQ_EOSoTuJNvngqK5v4Pas7n4-OCwlEEJcQTIMO-nSQwtb-GSdsX46e9gbRoP9yGQ11I0rEuycunu6PHx1QnPhxm3SFN15MOlYEFJZtf0dUywMbwZOeBGsrKNLYB54-1R9WNqVdki7usim6VmQphf7mnpshiQRhNAXdoOfMyX3OgMlKtz0cGEcF27uLSul3mewjPjgOOoDukxjPS9rqfh0pb-8zs6aBSt_7505aZ7B9xOi0T9YKW4UooVsr0zB1BTrWQJ3EL-oWcZ572GxFoezCk37QLe3897-B2i2U62uBAAA)): + +```svelte + +
    + {#snippet header()} + + + + + {/snippet} + + {#snippet row(d)} + + + + + {/snippet} +
    fruitqtypricetotal{d.name}{d.qty}{d.price}{d.qty * d.price}
    +``` + +Any content inside the component tags that is _not_ a snippet declaration implicitly becomes part of the `children` snippet ([demo](/playground/untitled#H4sIAAAAAAAAE3WOQQrCMBBFrzIMggql3ddY1Du4si5sOmIwnYRkFKX07lKqglqX8_7_w2uRDw1hjlsWI5ZqTPBoLEXMdy3K3fdZDzB5Ndfep_FKVnpWHSKNce1YiCVijirqYLwUJQOYxrsgsLmIOIZjcA1M02w4n-PpomSVvTclqyEutDX6DA2pZ7_ABIVugrmEC3XJH92P55_G39GodCmWBFrQJ2PrQAwdLGHig_NxNv9xrQa1dhWIawrv1Wzeqawa8953D-8QOmaEAQAA)): + +```svelte + + +``` + +```svelte + + + + + +``` + +> [!NOTE] Note that you cannot have a prop called `children` if you also have content inside the component — for this reason, you should avoid having props with that name + +You can declare snippet props as being optional. You can either use optional chaining to not render anything if the snippet isn't set... + +```svelte + + +{@render children?.()} +``` + +...or use an `#if` block to render fallback content: + +```svelte + + +{#if children} + {@render children()} +{:else} + fallback content +{/if} +``` + +## Typing snippets + +Snippets implement the `Snippet` interface imported from `'svelte'`: + +```svelte + +``` + +With this change, red squigglies will appear if you try and use the component without providing a `data` prop and a `row` snippet. Notice that the type argument provided to `Snippet` is a tuple, since snippets can have multiple parameters. + +We can tighten things up further by declaring a generic, so that `data` and `row` refer to the same type: + +```svelte + +``` + +## Exporting snippets + +Snippets declared at the top level of a `.svelte` file can be exported from a ` + +{#snippet add(a, b)} + {a} + {b} = {a + b} +{/snippet} +``` + +> [!NOTE] +> This requires Svelte 5.5.0 or newer + +## Programmatic snippets + +Snippets can be created programmatically with the [`createRawSnippet`](svelte#createRawSnippet) API. This is intended for advanced use cases. + +## Snippets and slots + +In Svelte 4, content can be passed to components using [slots](legacy-slots). Snippets are more powerful and flexible, and as such slots are deprecated in Svelte 5. + +# {@render ...} + +To render a [snippet](snippet), use a `{@render ...}` tag. + +```svelte +{#snippet sum(a, b)} +

    {a} + {b} = {a + b}

    +{/snippet} + +{@render sum(1, 2)} +{@render sum(3, 4)} +{@render sum(5, 6)} +``` + +The expression can be an identifier like `sum`, or an arbitrary JavaScript expression: + +```svelte +{@render (cool ? coolSnippet : lameSnippet)()} +``` + +## Optional snippets + +If the snippet is potentially undefined — for example, because it's an incoming prop — then you can use optional chaining to only render it when it _is_ defined: + +```svelte +{@render children?.()} +``` + +Alternatively, use an [`{#if ...}`](if) block with an `:else` clause to render fallback content: + +```svelte +{#if children} + {@render children()} +{:else} +

    fallback content

    +{/if} +``` + +# {@html ...} + +To inject raw HTML into your component, use the `{@html ...}` tag: + +```svelte +
    + {@html content} +
    +``` + +> [!NOTE] Make sure that you either escape the passed string or only populate it with values that are under your control in order to prevent [XSS attacks](https://owasp.org/www-community/attacks/xss/). Never render unsanitized content. + +The expression should be valid standalone HTML — this will not work, because `
    ` is not valid HTML: + +```svelte +{@html '
    '}content{@html '
    '} +``` + +It also will not compile Svelte code. + +## Styling + +Content rendered this way is 'invisible' to Svelte and as such will not receive [scoped styles](scoped-styles) — in other words, this will not work, and the `a` and `img` styles will be regarded as unused: + + +```svelte +
    + {@html content} +
    + + +``` + +Instead, use the `:global` modifier to target everything inside the `
    `: + + +```svelte + +``` + +# {@const ...} + +The `{@const ...}` tag defines a local constant. + +```svelte +{#each boxes as box} + {@const area = box.width * box.height} + {box.width} * {box.height} = {area} +{/each} +``` + +`{@const}` is only allowed as an immediate child of a block — `{#if ...}`, `{#each ...}`, `{#snippet ...}` and so on — or a ``. + +# {@debug ...} + +The `{@debug ...}` tag offers an alternative to `console.log(...)`. It logs the values of specific variables whenever they change, and pauses code execution if you have devtools open. + +```svelte + + +{@debug user} + +

    Hello {user.firstname}!

    +``` + +`{@debug ...}` accepts a comma-separated list of variable names (not arbitrary expressions). + +```svelte + +{@debug user} +{@debug user1, user2, user3} + + +{@debug user.firstname} +{@debug myArray[0]} +{@debug !isReady} +{@debug typeof user === 'object'} +``` + +The `{@debug}` tag without any arguments will insert a `debugger` statement that gets triggered when _any_ state changes, as opposed to the specified variables. + +# bind: + +Data ordinarily flows down, from parent to child. The `bind:` directive allows data to flow the other way, from child to parent. + +The general syntax is `bind:property={expression}`, where `expression` is an _lvalue_ (i.e. a variable or an object property). When the expression is an identifier with the same name as the property, we can omit the expression — in other words these are equivalent: + + +```svelte + + +``` + + +Svelte creates an event listener that updates the bound value. If an element already has a listener for the same event, that listener will be fired before the bound value is updated. + +Most bindings are _two-way_, meaning that changes to the value will affect the element and vice versa. A few bindings are _readonly_, meaning that changing their value will have no effect on the element. + +## Function bindings + +You can also use `bind:property={get, set}`, where `get` and `set` are functions, allowing you to perform validation and transformation: + +```svelte + value, + (v) => value = v.toLowerCase()} +/> +``` + +In the case of readonly bindings like [dimension bindings](#Dimensions), the `get` value should be `null`: + +```svelte +
    ...
    +``` + +> [!NOTE] +> Function bindings are available in Svelte 5.9.0 and newer. + +## `` + +A `bind:value` directive on an `` element binds the input's `value` property: + + +```svelte + + + +

    {message}

    +``` + +In the case of a numeric input (`type="number"` or `type="range"`), the value will be coerced to a number ([demo](/playground/untitled#H4sIAAAAAAAAE6WPwYoCMQxAfyWEPeyiOOqx2w74Hds9pBql0IllmhGXYf5dKqwiyILsLXnwwsuI-5i4oPkaUX8yo7kCnKNQV7dNzoty4qSVBSr8jG-Poixa0KAt2z5mbb14TaxA4OCtKCm_rz4-f2m403WltrlrYhMFTtcLNkoeFGqZ8yhDF7j3CCHKzpwoDexGmqCL4jwuPUJHZ-dxVcfmyYGe5MAv-La5pbxYFf5Z9Zf_UJXb-sEMquFgJJhBmGyTW5yj8lnRaD_w9D1dAKSSj7zqAQAA)): + +```svelte + + + + + + +

    {a} + {b} = {a + b}

    +``` + +If the input is empty or invalid (in the case of `type="number"`), the value is `undefined`. + +Since 5.6.0, if an `` has a `defaultValue` and is part of a form, it will revert to that value instead of the empty string when the form is reset. Note that for the initial render the value of the binding takes precedence unless it is `null` or `undefined`. + +```svelte + + +
    + + +
    +``` + +> [!NOTE] +> Use reset buttons sparingly, and ensure that users won't accidentally click them while trying to submit the form. + +## `` + +Checkbox and radio inputs can be bound with `bind:checked`: + +```svelte + +``` + +Since 5.6.0, if an `` has a `defaultChecked` attribute and is part of a form, it will revert to that value instead of `false` when the form is reset. Note that for the initial render the value of the binding takes precedence unless it is `null` or `undefined`. + +```svelte + + +
    + + +
    +``` + +## `` + +Inputs that work together can use `bind:group`. + +```svelte + + + + + + + + + + + + +``` + +> [!NOTE] `bind:group` only works if the inputs are in the same Svelte component. + +## `` + +On `` elements with `type="file"`, you can use `bind:files` to get the [`FileList` of selected files](https://developer.mozilla.org/en-US/docs/Web/API/FileList). When you want to update the files programmatically, you always need to use a `FileList` object. Currently `FileList` objects cannot be constructed directly, so you need to create a new [`DataTransfer`](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer) object and get `files` from there. + +```svelte + + + + + +``` + +`FileList` objects also cannot be modified, so if you want to e.g. delete a single file from the list, you need to create a new `DataTransfer` object and add the files you want to keep. + +> [!NOTE] `DataTransfer` may not be available in server-side JS runtimes. Leaving the state that is bound to `files` uninitialized prevents potential errors if components are server-side rendered. + +## `` value binding corresponds to the `value` property on the selected ` + + + + +``` + +When the value of an ` + + + +``` + +## `