From 082ef8675f4cffa71be64713897feab42234b1bd Mon Sep 17 00:00:00 2001 From: samuel Date: Wed, 27 Mar 2024 18:58:12 +0100 Subject: [PATCH] WIP --- .npmrc | 2 + apps/devtool/public/narval-wordmark-white.png | Bin 0 -> 26236 bytes apps/devtool/src/app/api/data-store/init.json | 2 +- .../devtool/src/app/components/CodeEditor.tsx | 320 ++++++++++ .../src/app/components/EditorComponent.tsx | 179 ------ apps/devtool/src/app/components/Home.tsx | 6 +- .../src/app/design-system/NarButton.tsx | 107 ++++ .../src/app/design-system/NarDialog.tsx | 78 +++ .../src/app/design-system/NarInput.tsx | 74 +++ apps/devtool/src/app/global.css | 31 + .../src/app/{components => lib}/config.ts | 0 apps/devtool/src/app/lib/utils.ts | 6 + apps/devtool/src/app/page.tsx | 2 +- apps/devtool/tailwind.config.js | 220 ++++++- .../engine/core/service/bootstrap.service.ts | 23 - .../engine/http/rest/dto/create-tenant.dto.ts | 3 +- apps/policy-engine/src/main.ts | 3 + package-lock.json | 571 +++++++++++++++++- package.json | 9 +- 19 files changed, 1405 insertions(+), 231 deletions(-) create mode 100644 .npmrc create mode 100644 apps/devtool/public/narval-wordmark-white.png create mode 100644 apps/devtool/src/app/components/CodeEditor.tsx delete mode 100644 apps/devtool/src/app/components/EditorComponent.tsx create mode 100644 apps/devtool/src/app/design-system/NarButton.tsx create mode 100644 apps/devtool/src/app/design-system/NarDialog.tsx create mode 100644 apps/devtool/src/app/design-system/NarInput.tsx rename apps/devtool/src/app/{components => lib}/config.ts (100%) create mode 100644 apps/devtool/src/app/lib/utils.ts diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..fa045f3cd --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +@fortawesome:registry=https://npm.fontawesome.com/ +//npm.fontawesome.com/:_authToken=BB192AC2-6663-4FB6-8C01-F1156629CD1F diff --git a/apps/devtool/public/narval-wordmark-white.png b/apps/devtool/public/narval-wordmark-white.png new file mode 100644 index 0000000000000000000000000000000000000000..8b907e3d436158e2330825d20bc96ab9a4b4270a GIT binary patch literal 26236 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 literal 0 HcmV?d00001 diff --git a/apps/devtool/src/app/api/data-store/init.json b/apps/devtool/src/app/api/data-store/init.json index 84d9afd12..cd9f5e00d 100644 --- a/apps/devtool/src/app/api/data-store/init.json +++ b/apps/devtool/src/app/api/data-store/init.json @@ -5,7 +5,7 @@ "addressBook": [], "credentials": [], "tokens": [], - "userGroupMembers": [], + "userGroupMembers": [{ "userId": "user-id", "groupId": "user-group-id" }], "userGroups": [], "userWallets": [], "users": [], diff --git a/apps/devtool/src/app/components/CodeEditor.tsx b/apps/devtool/src/app/components/CodeEditor.tsx new file mode 100644 index 000000000..53485d59d --- /dev/null +++ b/apps/devtool/src/app/components/CodeEditor.tsx @@ -0,0 +1,320 @@ +'use client' + +import Editor from '@monaco-editor/react' +import { EntityUtil, entityDataSchema, policyDataSchema } from '@narval/policy-engine-shared' +import { Jwk, Payload, SigningAlg, hash, hexToBase64Url, signJwt } from '@narval/signature' +import { signMessage } from '@wagmi/core' +import axios from 'axios' +import Image from 'next/image' +import { useEffect, useRef, useState } from 'react' +import { useLocalStorage } from 'usehooks-ts' +import { useAccount, useConnect, useDisconnect } from 'wagmi' +import NarButton from '../design-system/NarButton' +import NarDialog from '../design-system/NarDialog' +import NarInput from '../design-system/NarInput' +import { config } from '../lib/config' + +const DATA_STORE_URL = 'http://127.0.0.1:4200/api/data-store' +const ENGINE_URL = 'http://127.0.0.1:3010' + +const LOCAL_STORAGE_KEYS = { + engineApiKey: 'narvalEngineApiKey', + engineClientId: 'narvalEngineClientId', + engineClientSecret: 'narvalEngineClientSecret', + engineUrl: 'narvalEngineUrl', + entityDataStoreUrl: 'narvalEntityDataStoreUrl', + policyDataStoreUrl: 'narvalPolicyDataStoreUrl', + entitySignatureUrl: 'narvalEntitySignatureUrl', + policySignatureUrl: 'narvalPolicySignatureUrl' +} + +const CodeEditor = () => { + const account = useAccount() + const { connectors, connect } = useConnect() + const { disconnect } = useDisconnect() + + const [engineApiKey, setEngineApiKey] = useLocalStorage(LOCAL_STORAGE_KEYS.engineApiKey, '') + const [engineClientId, setEngineClientId] = useLocalStorage(LOCAL_STORAGE_KEYS.engineClientId, '') + const [engineClientSecret, setEngineClientSecret] = useLocalStorage(LOCAL_STORAGE_KEYS.engineClientSecret, '') + const [engineUrl, setEngineUrl] = useLocalStorage(LOCAL_STORAGE_KEYS.engineUrl, ENGINE_URL) + const [entityDataStoreUrl, setEntityDataStoreUrl] = useLocalStorage( + LOCAL_STORAGE_KEYS.entityDataStoreUrl, + DATA_STORE_URL + ) + const [entitySignatureUrl, setEntitySignatureUrl] = useLocalStorage( + LOCAL_STORAGE_KEYS.entitySignatureUrl, + DATA_STORE_URL + ) + const [policyDataStoreUrl, setPolicyDataStoreUrl] = useLocalStorage( + LOCAL_STORAGE_KEYS.policyDataStoreUrl, + DATA_STORE_URL + ) + const [policySignatureUrl, setPolicySignatureUrl] = useLocalStorage( + LOCAL_STORAGE_KEYS.policySignatureUrl, + DATA_STORE_URL + ) + + const [data, setData] = useState() + const [jwk, setJwk] = useState() + const [isDialogOpen, setIsDialogOpen] = useState(false) + const [validationErrors, setValidationErrors] = useState([]) + + const editorRef = useRef(null) + const monacoRef = useRef(null) + + useEffect(() => { + if (data) return + + const getData = async () => { + const dataStore = await axios.get('/api/data-store') + const { entity, policy } = dataStore.data + setData(JSON.stringify({ entity: entity.data, policy: policy.data }, null, 2)) + } + + getData() + }, [data]) + + useEffect(() => { + if (!account.address) return + if (jwk) return + + setJwk({ + kty: 'EC', + crv: 'secp256k1', + alg: SigningAlg.ES256K, + kid: account.address + }) + }, [account]) + + const sign = async () => { + if (!data || !jwk) return + + const { entity, policy } = JSON.parse(data) + + const entityValidationResult = entityDataSchema.safeParse({ entity: { data: entity } }) + + if (!entityValidationResult.success) { + setValidationErrors( + entityValidationResult.error.errors.map((error) => `${error.path.join('.')}:${error.message}`) + ) + setIsDialogOpen(true) + return + } + + const policyValidationResult = policyDataSchema.safeParse({ policy: { data: policy } }) + + if (!policyValidationResult.success) { + setValidationErrors( + policyValidationResult.error.errors.map((error) => `${error.path.join('.')}:${error.message}`) + ) + setIsDialogOpen(true) + return + } + + const validation = EntityUtil.validate(entity) + + if (!validation.success) { + setValidationErrors(validation.issues.map((issue) => issue.message)) + setIsDialogOpen(true) + return + } + + const jwtSigner = async (message: string) => { + const jwtSig = await signMessage(config, { message }) + + return hexToBase64Url(jwtSig) + } + + if (!account.address) { + throw new Error('No address connected') + } + + const now = Math.floor(Date.now() / 1000) + + const entityPayload: Payload = { + data: hash(entity), + sub: account.address, + iss: 'https://devtool.narval.xyz', + iat: now + } + + const policyPayload: Payload = { + data: hash(policy), + sub: account.address, + iss: 'https://devtool.narval.xyz', + iat: now + } + const entitySig = await signJwt(entityPayload, jwk, { alg: SigningAlg.EIP191 }, jwtSigner) + const policySig = await signJwt(policyPayload, jwk, { alg: SigningAlg.EIP191 }, jwtSigner) + + await axios.post('/api/data-store', { + entity: { + signature: entitySig, + data: entity + }, + policy: { + signature: policySig, + data: policy + } + }) + + console.log('Data signed and stored!') + + await axios.post(`${engineUrl}/tenants/sync`, null, { + headers: { + 'x-client-id': engineClientId, + 'x-client-secret': engineClientSecret + } + }) + + console.log('Data store synced with engine!') + } + + const onboard = async () => { + const { data: tenant } = await axios.post( + `${engineUrl}/tenants`, + { + ...(engineClientId && { clientId: engineClientId }), + entityDataStore: { + dataUrl: entityDataStoreUrl, + signatureUrl: entitySignatureUrl + }, + policyDataStore: { + dataUrl: policyDataStoreUrl, + signatureUrl: policySignatureUrl + } + }, + { + headers: { + 'x-api-key': engineApiKey + } + } + ) + + setEngineClientId(tenant.clientId) + setEngineClientSecret(tenant.clientSecret) + } + + return ( + <> +
+
+ Narval Logo +
+ {!account.isConnected && ( +
+ {connectors.map((connector) => ( + connect({ connector })} + /> + ))} +
+ )} + {account.isConnected && ( + <> + disconnect()} /> + sign()} /> + + )} +
+
+
+
+
+
Entity Data store config:
+
+
Data URL:
+ +
+
+
Signature URL:
+ +
+
+
+
Policy Data store config:
+
+
Data URL:
+ +
+
+
Signature URL:
+ +
+
+
+
+
Policy Engine config:
+
+
Engine URL:
+ +
+
+
Engine API Key:
+ +
+ {engineClientId && ( +
+
Engine Client ID:
+
{engineClientId}
+
+ )} + {engineClientSecret && ( +
+
Engine Client Secret:
+
{engineClientSecret}
+
+ )} + {engineUrl && engineApiKey && !engineClientId && } +
+
+
+ setData(value)} + onMount={(editor, monaco) => { + editorRef.current = editor + monacoRef.current = monaco + }} + /> +
+
+ {isDialogOpen && ( + } + title="Data validation failed" + primaryButtonLabel="OK" + isOpen={isDialogOpen} + onOpenChange={setIsDialogOpen} + onDismiss={() => setIsDialogOpen(false)} + isConfirm + > +
+
    + {validationErrors.map((error, index) => ( +
  • {error}
  • + ))} +
+
+
+ )} + + ) +} + +export default CodeEditor diff --git a/apps/devtool/src/app/components/EditorComponent.tsx b/apps/devtool/src/app/components/EditorComponent.tsx deleted file mode 100644 index cb18d071e..000000000 --- a/apps/devtool/src/app/components/EditorComponent.tsx +++ /dev/null @@ -1,179 +0,0 @@ -'use client' - -import Editor from '@monaco-editor/react' -import { EntityUtil, entityDataSchema, policyDataSchema } from '@narval/policy-engine-shared' -import { Jwk, Payload, SigningAlg, hash, hexToBase64Url, signJwt } from '@narval/signature' -import { getAccount, signMessage } from '@wagmi/core' -import axios from 'axios' -import Image from 'next/image' -import { useEffect, useRef, useState } from 'react' -import { useAccount, useConnect, useDisconnect } from 'wagmi' -import { config } from './config' - -const EditorComponent = () => { - const account = useAccount() - const { connectors, connect } = useConnect() - const { disconnect } = useDisconnect() - - const [data, setData] = useState() - const [displayLink, setDisplayLink] = useState(false) - - const editorRef = useRef(null) - const monacoRef = useRef(null) - - useEffect(() => { - if (data) return - - const getData = async () => { - const dataStore = await axios.get('/api/data-store') - const { entity, policy } = dataStore.data - setData(JSON.stringify({ entity: entity.data, policy: policy.data }, null, 2)) - } - - getData() - }, [data]) - - const sign = async () => { - if (!data) return - - const { entity, policy } = JSON.parse(data) - - const validation = EntityUtil.validate(entity) - - if (!validation.success) { - console.log(validation.issues) - } - - const entityValidationResult = entityDataSchema.safeParse({ entity: { data: entity } }) - const policyValidationResult = policyDataSchema.safeParse({ policy: { data: policy } }) - - if (!entityValidationResult.success) { - console.log('Invalid entity', entityValidationResult.error.errors) - } - - if (!policyValidationResult.success) { - console.log('Invalid policy', policyValidationResult.error.errors) - } - - const jwtSigner = async (msg: string) => { - const jwtSig = await signMessage(config, { message: msg }) - - return hexToBase64Url(jwtSig) - } - - const address = getAccount(config).address - if (!address) throw new Error('No address connected') - - // Need real Jwk - const jwk: Jwk = { - kty: 'EC', - crv: 'secp256k1', - alg: SigningAlg.ES256K, - kid: address - } - - const now = Math.floor(Date.now() / 1000) - - const entityPayload: Payload = { - data: hash(entity), - sub: address, - iss: 'https://devtool.narval.xyz', - iat: now - } - - const policyPayload: Payload = { - data: hash(policy), - sub: address, - iss: 'https://devtool.narval.xyz', - iat: now - } - const entitySig = await signJwt(entityPayload, jwk, { alg: SigningAlg.EIP191 }, jwtSigner) - const policySig = await signJwt(policyPayload, jwk, { alg: SigningAlg.EIP191 }, jwtSigner) - - await axios.post('/api/data-store', { - entity: { - signature: entitySig, - data: entity - }, - policy: { - signature: policySig, - data: policy - } - }) - - setDisplayLink(true) - } - - return ( -
-
- Narval Logo -
- {!account.isConnected && ( -
- {connectors.map((connector) => ( - - ))} -
- )} - {account.isConnected && ( - <> - - - - )} -
-
-
- {displayLink && ( - - Data Store - - )} -
-
- setData(value)} - onMount={(editor, monaco) => { - editorRef.current = editor - monacoRef.current = monaco - }} - /> -
-
- ) -} - -export default EditorComponent diff --git a/apps/devtool/src/app/components/Home.tsx b/apps/devtool/src/app/components/Home.tsx index b94d99871..761e33457 100644 --- a/apps/devtool/src/app/components/Home.tsx +++ b/apps/devtool/src/app/components/Home.tsx @@ -2,15 +2,15 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { WagmiProvider } from 'wagmi' -import EditorComponent from './EditorComponent' -import { config } from './config' +import { config } from '../lib/config' +import CodeEditor from './CodeEditor' const queryClient = new QueryClient() const Home = () => ( - + ) diff --git a/apps/devtool/src/app/design-system/NarButton.tsx b/apps/devtool/src/app/design-system/NarButton.tsx new file mode 100644 index 000000000..30d521171 --- /dev/null +++ b/apps/devtool/src/app/design-system/NarButton.tsx @@ -0,0 +1,107 @@ +import { BaseSyntheticEvent, ForwardedRef, forwardRef, ReactElement, ReactNode } from 'react' +import { classNames } from '../lib/utils' + +interface ButtonProps { + label?: string + type?: 'button' | 'reset' | 'submit' + variant?: 'primary' | 'secondary' | 'tertiary' | 'quaternary' | 'danger' | 'danger-stroke' + size?: 'xs' | 'sm' | 'md' | 'lg' + className?: string + rounded?: boolean + disabled?: boolean + leftIcon?: ReactElement + rightIcon?: ReactElement + children?: ReactNode + onClick?: (e: BaseSyntheticEvent) => void +} + +const getVariantClass = (variant: ButtonProps['variant']) => { + const defaultVariant = 'text-nv-black bg-nv-white hover:bg-nv-neutrals-25' + + switch (variant) { + case 'primary': + return defaultVariant + case 'secondary': + return 'text-nv-white bg-nv-neutrals-800 border border-nv-white' + case 'tertiary': + return 'text-nv-white bg-nv-neutrals-600 border border-nv-neutrals-500 hover:bg-nv-neutrals-400 hover:border-nv-neutrals-400' + case 'quaternary': + return 'text-nv-white !p-0 hover:underline underline-offset-4 focus:!ring-0 focus-visible:!outline-none' + case 'danger': + return 'text-nv-white bg-nv-danger' + case 'danger-stroke': + return 'text-nv-danger bg-nv-neutrals-800 border border-nv-danger hover:border-nv-red-400' + default: + return defaultVariant + } +} + +const getSizeClass = (size: ButtonProps['size']) => { + const defaultSize = 'text-[14px] h-[40px] px-[20px] gap-[8px]' + + switch (size) { + case 'xs': + return 'text-[10px] h-[26px] px-[16px] gap-[2px]' + case 'sm': + return 'text-[12px] h-[32px] px-[16px] gap-[4px]' + case 'md': + return defaultSize + case 'lg': + return 'text-[16px] h-[40px] px-[20px] gap-[8px]' + default: + return defaultSize + } +} + +const btnStyles = 'relative flex items-center justify-center focus:ring focus:ring-nv-brand-500/20' + +const iconStyles = 'flex flex-col items-center justify-center h-[16px] w-[16px]' + +const NarButton = forwardRef( + ( + { + label, + type, + variant = 'primary', + size = 'md', + className, + rounded, + disabled, + leftIcon, + rightIcon, + children, + onClick, + ...props + }: ButtonProps, + forwardedRef: ForwardedRef + ) => { + const btnRounded = rounded ? 'rounded-full' : 'rounded-[12px]' + const btnDisabled = disabled + ? '!text-nv-neutrals-200 hover:!text-nv-neutrals-200 !bg-nv-neutrals-400 hover:!bg-nv-neutrals-400 !border-none cursor-not-allowed' + : '' + + return ( + + ) + } +) + +export default NarButton diff --git a/apps/devtool/src/app/design-system/NarDialog.tsx b/apps/devtool/src/app/design-system/NarDialog.tsx new file mode 100644 index 000000000..f6d784ac9 --- /dev/null +++ b/apps/devtool/src/app/design-system/NarDialog.tsx @@ -0,0 +1,78 @@ +import { faSpinner, faXmark } from '@fortawesome/pro-regular-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import * as Dialog from '@radix-ui/react-dialog' +import { FC, ReactNode } from 'react' +import { classNames } from '../lib/utils' +import NarButton from './NarButton' + +interface NarDialogProps { + title: string + triggerButton: ReactNode + children: ReactNode + isOpen: boolean + isSaving?: boolean + isSaveDisabled?: boolean + isConfirm?: boolean + primaryButtonLabel?: string + onDismiss?: () => void + onSave?: () => void + onOpenChange: (value: boolean) => void +} + +const NarDialog: FC = ({ + title, + triggerButton, + children, + isOpen, + isSaving, + isSaveDisabled, + isConfirm, + primaryButtonLabel, + onDismiss, + onSave, + onOpenChange +}) => ( + + {triggerButton} + + + + + {title} + + {children} + +
+ {!isConfirm && ( + <> + + : undefined} + onClick={onSave} + disabled={isSaving || isSaveDisabled} + /> + + )} + {isConfirm && } +
+ + +
+ +
+
+
+
+
+) + +export default NarDialog diff --git a/apps/devtool/src/app/design-system/NarInput.tsx b/apps/devtool/src/app/design-system/NarInput.tsx new file mode 100644 index 000000000..3e776207a --- /dev/null +++ b/apps/devtool/src/app/design-system/NarInput.tsx @@ -0,0 +1,74 @@ +import { IconDefinition } from '@fortawesome/pro-regular-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { FC, KeyboardEvent, useState } from 'react' +import { classNames } from '../lib/utils' + +interface NarInputProps { + id?: string + label?: string + value?: string + placeholder?: string + className?: string + errorMessage?: string + disabled?: boolean + leftIcon?: IconDefinition + validate?: (value: string | undefined) => boolean + onKeyDown?: (e: KeyboardEvent) => void + onChange: (value: string) => void +} + +const NarInput: FC = ({ + id, + value, + label, + placeholder, + className, + errorMessage, + disabled, + leftIcon, + validate, + onChange, + onKeyDown +}) => { + const [isDirty, setIsDirty] = useState(false) + const [isError, setIsError] = useState(false) + + return ( +
+ {label && ( + + )} +
+ {leftIcon && } + { + if (!isDirty) setIsDirty(true) + if (isError) setIsError(false) + onChange(e.target.value) + }} + onBlur={() => { + if (isDirty && validate && !validate(value)) setIsError(true) + else setIsError(false) + }} + onKeyDown={onKeyDown} + disabled={disabled} + /> +
+ {isError &&
{errorMessage}
} +
+ ) +} + +export default NarInput diff --git a/apps/devtool/src/app/global.css b/apps/devtool/src/app/global.css index b5c61c956..c828f1019 100644 --- a/apps/devtool/src/app/global.css +++ b/apps/devtool/src/app/global.css @@ -1,3 +1,34 @@ @tailwind base; @tailwind components; @tailwind utilities; +@tailwind forms; + +html, +body { + padding: 0; + margin: 0; + font-family: + -apple-system, + BlinkMacSystemFont, + Segoe UI, + Roboto, + Oxygen, + Ubuntu, + Cantarell, + Fira Sans, + Droid Sans, + Helvetica Neue, + sans-serif; + background-color: #08090a; + color: #ffffff; + height: 100%; +} + +a { + color: inherit; + text-decoration: none; +} + +* { + box-sizing: border-box; +} diff --git a/apps/devtool/src/app/components/config.ts b/apps/devtool/src/app/lib/config.ts similarity index 100% rename from apps/devtool/src/app/components/config.ts rename to apps/devtool/src/app/lib/config.ts diff --git a/apps/devtool/src/app/lib/utils.ts b/apps/devtool/src/app/lib/utils.ts new file mode 100644 index 000000000..d24130e97 --- /dev/null +++ b/apps/devtool/src/app/lib/utils.ts @@ -0,0 +1,6 @@ +import { extendTailwindMerge } from 'tailwind-merge' + +export const classNames = (...classes: Array) => { + const twMerge = extendTailwindMerge({ prefix: 'nv-' }) + return twMerge(...classes) +} diff --git a/apps/devtool/src/app/page.tsx b/apps/devtool/src/app/page.tsx index e10f58511..e002ebfbe 100644 --- a/apps/devtool/src/app/page.tsx +++ b/apps/devtool/src/app/page.tsx @@ -3,7 +3,7 @@ import './global.css' export default async function Index() { return ( -
+
) diff --git a/apps/devtool/tailwind.config.js b/apps/devtool/tailwind.config.js index 9a9408662..054c74041 100644 --- a/apps/devtool/tailwind.config.js +++ b/apps/devtool/tailwind.config.js @@ -2,7 +2,225 @@ module.exports = { content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'], theme: { - extend: {} + extend: { + boxShadow: { + nar: '4px 4px 4px rgba(0, 0, 0, 0.1)' + }, + colors: { + 'icon-gray-light': '#A8B0B9', + 'icon-gray-dark': '#71717a', + 'nar-blue': '#0A6BFF', + 'nar-blue-light': '#B9D5FF', + 'nar-blue-lighter': '#458FFF', + 'nar-blue-dark': '#0D063A', + 'nar-cyan': '#01CFFC', + 'nar-gray': '#585C63', + 'nar-gray-dark': '#07031B', + 'nar-gray-light': '#B8B9BD', + 'nar-guild-blue': '#0D0D54', + 'nar-blue-1': '#0C1523', + 'nar-gray-1': '#3F3F3F', + 'nar-gray-2': '#505050', + 'nar-gray-3': 'rgb(47, 48, 55)', + 'nar-blue-gray': '#24242C', + 'nar-bg-dark': '#121621', + 'nar-green': '#08B82F', + 'nar-red': '#B85208', + // New Theme Design + 'nv-black': '#08090A', + 'nv-white': '#FFFFFF', + 'nv-brand': { + 400: '#66B2FF', + 500: '#2E96FF' + }, + 'nv-accent': { + 400: '#5E41F7', + 500: '#582EFF' + }, + 'nv-danger': '#E8303D', + 'nv-warning': '#F9C50B', + 'nv-success': '#25C06D', + 'nv-neutrals': { + 25: '#DDE0E3', + 50: '#A4ABB2', + 100: '#858F98', + 200: '#656E76', + 300: '#434B54', + 400: '#2D3339 ', + 500: '#24292E', + 600: '#202428', + 700: '#1A1D21', + 800: '#14161A', + 900: '#101214' + }, + 'nv-red': { + 100: '#E8C5C7', + 200: '#F0989E', + 300: '#EF7079', + 400: '#F3545F', + 500: '#E8303D', + 600: '#C02833', + 700: '#881A22', + 800: '#5E1318', + 900: '#38090C' + }, + 'nv-orange': { + 100: '#FFEEDF', + 200: '#FFDFC2', + 300: '#FFC998', + 400: '#FFB26A', + 500: '#FF9430', + 600: '#DA802C', + 700: '#B06118', + 800: '#894608', + 900: '#341901' + }, + 'nv-yellow': { + 100: '#FEF9E6', + 200: '#FEF3CD', + 300: '#FDE79B', + 400: '#FBDB6A', + 500: '#F9C50B', + 600: '#CAA10C', + 700: '#9B7C0D', + 800: '#55460F', + 900: '#26210F' + }, + 'nv-green': { + 100: '#EAFBF2', + 200: '#D4F7E4', + 300: '#A9EEC9', + 400: '#7FE6AF', + 500: '#25C06D', + 600: '#219D5A', + 700: '#1C7948', + 800: '#16442C', + 900: '#112119' + }, + 'nv-blue': { + 100: '#E5F2FF', + 200: '#CCE5FF', + 300: '#99CCFF', + 400: '#66B2FF', + 500: '#2E96FF', + 600: '#3883CF', + 700: '#2E669F', + 800: '#093561', + 900: '#141E28' + }, + 'nv-purple': { + 100: '#E9E3FF', + 200: '#C7B9FF', + 300: '#9F87FF', + 400: '#6D49FF', + 500: '#582EFF', + 600: '#4122BC', + 700: '#321996', + 800: '#211162', + 900: '#120C28' + }, + 'nv-pink': { + 100: '#FFE7FF', + 200: '#FECEFF', + 300: '#FEACFF', + 400: '#FD82FF', + 500: '#FC5EFF', + 600: '#D951DB', + 700: '#A83EAA', + 800: '#5A205B', + 900: '#230D23' + } + }, + fontSize: { + xxxs: '.5rem', + xxs: '.65rem', + 'nv-3xs': ['10px', { lineHeight: '10px', letterSpacing: '0.02em' }], + 'nv-2xs': ['12px', { lineHeight: '16px', letterSpacing: '0.02em' }], + 'nv-xs': ['14px', { lineHeight: '20px', letterSpacing: '0.02em' }], + 'nv-sm': ['16px', { lineHeight: '24px', letterSpacing: '0.02em' }], + 'nv-md': ['18px', { lineHeight: '24px', letterSpacing: '0.02em' }], + 'nv-lg': ['20px', { lineHeight: '32px', letterSpacing: '0.02em' }], + 'nv-xl': ['24px', { lineHeight: '32px', letterSpacing: '0.02em' }], + 'nv-2xl': ['28px', { lineHeight: '36px', letterSpacing: '0.02em' }], + 'nv-3xl': ['32px', { lineHeight: '48px', letterSpacing: '0.02em' }], + 'nv-4xl': ['64px', { lineHeight: '80px', letterSpacing: '0.02em' }] + }, + screens: { + sm: '640px', + // => @media (min-width: 640px) { ... } + + md: '768px', + // => @media (min-width: 768px) { ... } + + lg: '1024px', + // => @media (min-width: 1024px) { ... } + + xl: '1280px', + // => @media (min-width: 1280px) { ... } + + '2xl': '1536px', + // => @media (min-width: 1536px) { ... } + + '16in': '1800px' // Bigger than a 16" macbook pro screen + // => @media (min-width: 1800px) { ... } + }, + animation: { + 'spin-slow': 'spin 3s linear infinite', + hide: 'hide 100ms ease-in', + slideIn: 'slideIn 150ms cubic-bezier(0.16, 1, 0.3, 1)', + swipeOut: 'swipeOut 100ms ease-out', + slideDownAndFade: 'slideDownAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)', + slideLeftAndFade: 'slideLeftAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)', + slideUpAndFade: 'slideUpAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)', + slideRightAndFade: 'slideRightAndFade 400ms cubic-bezier(0.16, 1, 0.3, 1)', + overlayShow: 'overlayShow 150ms cubic-bezier(0.16, 1, 0.3, 1)', + contentShow: 'contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1)', + bgBlueFlashing: 'bgBlueFlashing 1s infinite' + }, + keyframes: { + bgBlueFlashing: { + '0%': { backgroundColor: '#2E96FF' }, + '50%': { backgroundColor: '#2E669F' }, + '100%': { backgroundColor: '#2E96FF' } + }, + hide: { + from: { opacity: 1 }, + to: { opacity: 0 } + }, + slideIn: { + from: { transform: 'translateX(calc(100% + var(--viewport-padding)))' }, + to: { transform: 'translateX(0)' } + }, + swipeOut: { + from: { transform: 'translateX(var(--radix-toast-swipe-end-x))' }, + to: { transform: 'translateX(calc(100% + var(--viewport-padding)))' } + }, + slideDownAndFade: { + from: { opacity: 0, transform: 'translateY(-2px)' }, + to: { opacity: 1, transform: 'translateY(0)' } + }, + slideLeftAndFade: { + from: { opacity: 0, transform: 'translateX(2px)' }, + to: { opacity: 1, transform: 'translateX(0)' } + }, + slideUpAndFade: { + from: { opacity: 0, transform: 'translateY(2px)' }, + to: { opacity: 1, transform: 'translateY(0)' } + }, + slideRightAndFade: { + from: { opacity: 0, transform: 'translateX(-2px)' }, + to: { opacity: 1, transform: 'translateX(0)' } + }, + overlayShow: { + from: { opacity: 0 }, + to: { opacity: 1 } + }, + contentShow: { + from: { opacity: 0, transform: 'translate(-50%, -48%) scale(0.96)' }, + to: { opacity: 1, transform: 'translate(-50%, -50%) scale(1)' } + } + } + } }, plugins: [] } diff --git a/apps/policy-engine/src/engine/core/service/bootstrap.service.ts b/apps/policy-engine/src/engine/core/service/bootstrap.service.ts index d412aeb71..f390620b1 100644 --- a/apps/policy-engine/src/engine/core/service/bootstrap.service.ts +++ b/apps/policy-engine/src/engine/core/service/bootstrap.service.ts @@ -1,7 +1,5 @@ import { EncryptionService } from '@narval/encryption-module' -import { FIXTURE } from '@narval/policy-engine-shared' import { Injectable, Logger } from '@nestjs/common' -import { randomBytes } from 'crypto' import { TenantService } from './tenant.service' @Injectable() @@ -18,27 +16,6 @@ export class BootstrapService { await this.checkEncryptionConfiguration() - if (!(await this.tenantService.findByClientId(FIXTURE.ORGANIZATION.id))) { - await this.tenantService.onboard({ - clientId: FIXTURE.ORGANIZATION.id, - clientSecret: randomBytes(42).toString('hex'), - dataStore: { - entity: { - dataUrl: 'http://127.0.0.1:3001/storage/2/entity', - signatureUrl: 'http://127.0.0.1:3001/storage/2/entity', - keys: [] - }, - policy: { - dataUrl: 'http://127.0.0.1:3001/storage/2/policy', - signatureUrl: 'http://127.0.0.1:3001/storage/2/policy', - keys: [] - } - }, - createdAt: new Date(), - updatedAt: new Date() - }) - } - await this.syncTenants() } diff --git a/apps/policy-engine/src/engine/http/rest/dto/create-tenant.dto.ts b/apps/policy-engine/src/engine/http/rest/dto/create-tenant.dto.ts index e674b473c..034e79dfc 100644 --- a/apps/policy-engine/src/engine/http/rest/dto/create-tenant.dto.ts +++ b/apps/policy-engine/src/engine/http/rest/dto/create-tenant.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger' import { Type } from 'class-transformer' -import { IsDefined, IsString } from 'class-validator' +import { IsDefined, IsOptional, IsString } from 'class-validator' class DataStoreConfigurationDto { dataUrl: string @@ -9,6 +9,7 @@ class DataStoreConfigurationDto { export class CreateTenantDto { @IsString() + @IsOptional() @ApiPropertyOptional() clientId?: string diff --git a/apps/policy-engine/src/main.ts b/apps/policy-engine/src/main.ts index 0b2e8d420..f0c59feff 100644 --- a/apps/policy-engine/src/main.ts +++ b/apps/policy-engine/src/main.ts @@ -58,6 +58,9 @@ const withGlobalFilters = async function bootstrap() { const logger = new Logger('PolicyEngineBootstrap') const application = await NestFactory.create(PolicyEngineModule, { bodyParser: true }) + application.enableCors({ + origin: ['http://localhost:4200'] + }) const configService = application.get(ConfigService) const port = configService.get('port') diff --git a/package-lock.json b/package-lock.json index f53cc3cc0..ff2162b3a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,8 @@ "@bull-board/nestjs": "^5.11.0", "@docusaurus/core": "3.1.1", "@docusaurus/preset-classic": "3.1.0", + "@fortawesome/pro-regular-svg-icons": "^6.5.1", + "@fortawesome/react-fontawesome": "^0.2.0", "@mdx-js/react": "^3.0.0", "@monaco-editor/react": "^4.6.0", "@nestjs/axios": "^3.0.1", @@ -30,6 +32,7 @@ "@noble/curves": "1.3.0", "@open-policy-agent/opa-wasm": "^1.8.0", "@prisma/client": "^5.7.1", + "@radix-ui/react-dialog": "^1.0.5", "@tanstack/react-query": "^5.24.1", "axios": "^1.6.7", "bull": "^4.12.1", @@ -50,8 +53,10 @@ "reflect-metadata": "^0.1.13", "remeda": "^1.40.0", "rxjs": "^7.8.0", + "tailwind-merge": "^2.2.2", "tslib": "^2.3.0", "type-fest": "^4.10.1", + "usehooks-ts": "^3.0.2", "uuid": "^9.0.1", "viem": "^2.7.16", "wagmi": "^2.5.7", @@ -92,7 +97,7 @@ "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^6.18.0", "@typescript-eslint/parser": "^6.19.1", - "autoprefixer": "^10.4.18", + "autoprefixer": "^10.4.19", "babel-jest": "^29.4.1", "dotenv-cli": "^7.3.0", "eslint": "~8.56.0", @@ -112,7 +117,7 @@ "lint-staged": "15.2.0", "nock": "^13.5.3", "nx": "17.1.3", - "postcss": "^8.4.35", + "postcss": "^8.4.38", "prettier": "^3.2.5", "prettier-plugin-organize-imports": "^3.2.4", "prisma": "^5.8.1", @@ -3526,9 +3531,9 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.4.tgz", - "integrity": "sha512-2Yv65nlWnWlSpe3fXEyX5i7fx5kIKo4Qbcj+hMO0odwaneFjfXw5fdum+4yL20O0QiaHpia0cYQ9xpNMqrBwHg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", + "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -6783,6 +6788,51 @@ "npm": ">=6.14.13" } }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz", + "integrity": "sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz", + "integrity": "sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==", + "hasInstallScript": true, + "peer": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/pro-regular-svg-icons": { + "version": "6.5.1", + "resolved": "https://npm.fontawesome.com/@fortawesome/pro-regular-svg-icons/-/6.5.1/pro-regular-svg-icons-6.5.1.tgz", + "integrity": "sha512-Rd7Q7Vff68l/YtFKB4EJW/YJ5eXYk7TqejyDTapOI1sn3/AFMEc8CVCOsPfi4+6qGrJy16hlNvgpigIy5gkW7A==", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" + } + }, "node_modules/@golevelup/nestjs-discovery": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@golevelup/nestjs-discovery/-/nestjs-discovery-4.0.0.tgz", @@ -13090,6 +13140,329 @@ "@prisma/debug": "5.8.1" } }, + "node_modules/@radix-ui/primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", + "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", + "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz", + "integrity": "sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", + "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-escape-keydown": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", + "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", + "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", + "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", + "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", + "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", + "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", + "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", + "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", + "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", + "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@react-native-async-storage/async-storage": { "version": "1.22.3", "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.22.3.tgz", @@ -16056,7 +16429,7 @@ "version": "18.2.14", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz", "integrity": "sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==", - "dev": true, + "devOptional": true, "dependencies": { "@types/react": "*" } @@ -17873,6 +18246,17 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "node_modules/aria-hidden": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", + "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/aria-query": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", @@ -18182,9 +18566,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.18", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.18.tgz", - "integrity": "sha512-1DKbDfsr6KUElM6wg+0zRNkB/Q7WcKYAaK+pzXn+Xqmszm/5Xa9coeNdtP88Vi+dPzZnMjhge8GIV49ZQkDa+g==", + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", "funding": [ { "type": "opencollective", @@ -18201,7 +18585,7 @@ ], "dependencies": { "browserslist": "^4.23.0", - "caniuse-lite": "^1.0.30001591", + "caniuse-lite": "^1.0.30001599", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", @@ -19056,9 +19440,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001591", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz", - "integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==", + "version": "1.0.30001600", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", + "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", "funding": [ { "type": "opencollective", @@ -21662,6 +22046,11 @@ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" + }, "node_modules/detect-port": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", @@ -24643,6 +25032,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/get-own-enumerable-property-symbols": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", @@ -33618,9 +34015,9 @@ } }, "node_modules/postcss": { - "version": "8.4.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", - "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "funding": [ { "type": "opencollective", @@ -33638,7 +34035,7 @@ "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -35440,6 +35837,51 @@ "node": ">=0.10.0" } }, + "node_modules/react-remove-scroll": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", + "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.3", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz", + "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==", + "dependencies": { + "react-style-singleton": "^2.2.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-router": { "version": "5.3.4", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", @@ -35519,6 +35961,28 @@ "react": "^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-style-singleton": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", + "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", + "dependencies": { + "get-nonce": "^1.0.0", + "invariant": "^2.2.4", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -37092,9 +37556,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "engines": { "node": ">=0.10.0" } @@ -37950,6 +38414,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/tailwind-merge": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.2.2.tgz", + "integrity": "sha512-tWANXsnmJzgw6mQ07nE3aCDkCK4QdT3ThPMCzawoYA2Pws7vSTCvz3Vrjg61jVUGfFZPJzxEP+NimbcW+EdaDw==", + "dependencies": { + "@babel/runtime": "^7.24.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", @@ -39502,6 +39978,47 @@ "requires-port": "^1.0.0" } }, + "node_modules/use-callback-ref": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", + "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", + "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", @@ -39510,6 +40027,20 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/usehooks-ts": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-3.0.2.tgz", + "integrity": "sha512-qJScCj8YOxa8RV3Iz2T+2IsydLG0EID5FouTGE7aNFEpFlCXmRrnJiPCESDArKr1FLTaUQSfDQ43UDn7yMLExw==", + "dependencies": { + "lodash.debounce": "^4.0.8" + }, + "engines": { + "node": ">=16.15.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/utf-8-validate": { "version": "5.0.10", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", diff --git a/package.json b/package.json index bc98f450e..29b27e249 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^6.18.0", "@typescript-eslint/parser": "^6.19.1", - "autoprefixer": "^10.4.18", + "autoprefixer": "^10.4.19", "babel-jest": "^29.4.1", "dotenv-cli": "^7.3.0", "eslint": "~8.56.0", @@ -61,7 +61,7 @@ "lint-staged": "15.2.0", "nock": "^13.5.3", "nx": "17.1.3", - "postcss": "^8.4.35", + "postcss": "^8.4.38", "prettier": "^3.2.5", "prettier-plugin-organize-imports": "^3.2.4", "prisma": "^5.8.1", @@ -80,6 +80,8 @@ "@bull-board/nestjs": "^5.11.0", "@docusaurus/core": "3.1.1", "@docusaurus/preset-classic": "3.1.0", + "@fortawesome/pro-regular-svg-icons": "^6.5.1", + "@fortawesome/react-fontawesome": "^0.2.0", "@mdx-js/react": "^3.0.0", "@monaco-editor/react": "^4.6.0", "@nestjs/axios": "^3.0.1", @@ -92,6 +94,7 @@ "@noble/curves": "1.3.0", "@open-policy-agent/opa-wasm": "^1.8.0", "@prisma/client": "^5.7.1", + "@radix-ui/react-dialog": "^1.0.5", "@tanstack/react-query": "^5.24.1", "axios": "^1.6.7", "bull": "^4.12.1", @@ -112,8 +115,10 @@ "reflect-metadata": "^0.1.13", "remeda": "^1.40.0", "rxjs": "^7.8.0", + "tailwind-merge": "^2.2.2", "tslib": "^2.3.0", "type-fest": "^4.10.1", + "usehooks-ts": "^3.0.2", "uuid": "^9.0.1", "viem": "^2.7.16", "wagmi": "^2.5.7",