From 6aeb86cc162a3022ee0b478f5eeb14f8a081347a Mon Sep 17 00:00:00 2001 From: m0ar Date: Wed, 1 Nov 2023 14:46:49 +0100 Subject: [PATCH 1/9] Remove webapp entirely as it is out of date and incomplete --- .eslintrc.json | 3 - components/AttestButton.tsx | 34 - components/AttestList.tsx | 40 - components/AuthPrompt.tsx | 33 - components/ResearchObject.tsx | 25 - components/ResearchObjectForm.tsx | 73 - components/Sidebar.tsx | 27 - components/UserForm.tsx | 93 -- context/index.tsx | 38 - next-env.d.ts | 5 - next.config.js | 6 - package-lock.json | 2160 ++--------------------------- package.json | 15 +- pages/_app.tsx | 56 - pages/explore.tsx | 56 - pages/index.tsx | 60 - pages/profile.tsx | 20 - public/ceramic.png | Bin 57047 -> 0 bytes public/favicon.ico | Bin 25931 -> 0 bytes public/nodes.png | Bin 4284 -> 0 bytes public/vercel.svg | 4 - scripts/run.mjs | 9 - styles/Home.module.css | 94 -- styles/Home.module.scss | 80 -- styles/colors.module.scss | 3 - styles/globals.css | 33 - styles/globals.scss | 89 -- styles/layout.module.scss | 126 -- styles/mixins.scss | 14 - styles/profile.module.scss | 18 - styles/user.module.scss | 23 - tsconfig.json | 1 - 32 files changed, 152 insertions(+), 3086 deletions(-) delete mode 100644 .eslintrc.json delete mode 100644 components/AttestButton.tsx delete mode 100644 components/AttestList.tsx delete mode 100644 components/AuthPrompt.tsx delete mode 100644 components/ResearchObject.tsx delete mode 100644 components/ResearchObjectForm.tsx delete mode 100755 components/Sidebar.tsx delete mode 100644 components/UserForm.tsx delete mode 100644 context/index.tsx delete mode 100644 next-env.d.ts delete mode 100644 next.config.js delete mode 100644 pages/_app.tsx delete mode 100644 pages/explore.tsx delete mode 100644 pages/index.tsx delete mode 100644 pages/profile.tsx delete mode 100644 public/ceramic.png delete mode 100644 public/favicon.ico delete mode 100644 public/nodes.png delete mode 100644 public/vercel.svg delete mode 100644 styles/Home.module.css delete mode 100755 styles/Home.module.scss delete mode 100755 styles/colors.module.scss delete mode 100644 styles/globals.css delete mode 100755 styles/globals.scss delete mode 100755 styles/layout.module.scss delete mode 100644 styles/mixins.scss delete mode 100644 styles/profile.module.scss delete mode 100644 styles/user.module.scss diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index bffb357..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/components/AttestButton.tsx b/components/AttestButton.tsx deleted file mode 100644 index 9d4ebf2..0000000 --- a/components/AttestButton.tsx +++ /dev/null @@ -1,34 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { useCeramicContext } from "@/context"; -import { mutationCreateAttestation } from "@/utils/queries"; - -type AttestButtonProps = { - targetID: string; -}; - -export const AttestButton = ({ targetID }: AttestButtonProps) => { - const { composeClient } = useCeramicContext(); - const [loading, setLoading] = useState(false); - - const createAttestation = async () => { - setLoading(true); - const inputs = { - targetID, - claimID: - "kjzl6kcym7w8y9hnsan2s4tzxa96gyb59zf3ozu60f79o7na6i2yuafjatjy8rc", - revoked: false, - }; - await mutationCreateAttestation(composeClient, inputs); - setLoading(false); - }; - - return ( -
- -
- ); -}; diff --git a/components/AttestList.tsx b/components/AttestList.tsx deleted file mode 100644 index aff97fe..0000000 --- a/components/AttestList.tsx +++ /dev/null @@ -1,40 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; -import { useCeramicContext } from "@/context"; -import { queryResearchObjectAttestations } from "@/utils/queries"; -import { Attestation } from "@/types"; - -type AttestListProps = { - targetID: string; -}; - -export const AttestList = ({ targetID }: AttestListProps) => { - const { composeClient } = useCeramicContext(); - const [loading, setLoading] = useState(false); - const [attestations, setAttestations] = useState([]); - - useEffect(() => { - const getAttestations = async () => { - setLoading(true); - const attestations = await queryResearchObjectAttestations( - composeClient, - targetID - ); - setAttestations(attestations); - setLoading(false); - }; - getAttestations(); - }, [composeClient, targetID]); - - return ( -
- {loading - ? "..." - : attestations.map( - (a) => - `[ ${a.claim?.title} (from ${a.source?.profile?.displayName})] ` - )} -
- ); -}; diff --git a/components/AuthPrompt.tsx b/components/AuthPrompt.tsx deleted file mode 100644 index ff79571..0000000 --- a/components/AuthPrompt.tsx +++ /dev/null @@ -1,33 +0,0 @@ -"use client"; -import React, { useState } from "react"; -import { authenticateCeramic } from "@/utils"; -import { useCeramicContext } from "@/context"; - -const AuthPrompt = () => { - const [isVisible, setIsVisible] = useState(true); - const clients = useCeramicContext(); - const { ceramic, composeClient } = clients; - - const handleEthPkh = () => { - localStorage.setItem("ceramic:auth_type", "eth"); - setIsVisible(false); - authenticateCeramic(ceramic, composeClient); - }; - - return ( -
- {isVisible && ( -
-
-

Authenticate

- - - -
-
- )} -
- ); -}; - -export default AuthPrompt; diff --git a/components/ResearchObject.tsx b/components/ResearchObject.tsx deleted file mode 100644 index f8c1eb8..0000000 --- a/components/ResearchObject.tsx +++ /dev/null @@ -1,25 +0,0 @@ -"use client"; -import Link from "next/link"; -import styles from "@/styles/Home.module.scss"; - -import { ResearchObject } from "@/types"; -import { PropsWithChildren } from "react"; - -const ResearchObjectComponent = ({ - owner, - title, - manifest, - children, -}: PropsWithChildren) => { - return ( -
-
{title}
- { owner?.profile ? (Author: {owner.profile.displayName}) : <> } -
- {manifest} - {children} -
- ); -}; - -export default ResearchObjectComponent; diff --git a/components/ResearchObjectForm.tsx b/components/ResearchObjectForm.tsx deleted file mode 100644 index a0a8467..0000000 --- a/components/ResearchObjectForm.tsx +++ /dev/null @@ -1,73 +0,0 @@ -"use client"; -import { useCeramicContext } from "@/context"; -import { ResearchObject } from "@/types"; -import styles from "@/styles/profile.module.scss"; -import { useState } from "react"; -import { mutationCreateResearchObject } from "@/utils/queries"; - -export const ResearchObjectForm = (updateParent: () => void) => { - const { ceramic, composeClient } = useCeramicContext(); - const [object, setObject] = useState({ - title: "", - manifest: "" - }); - const [loading, setLoading] = useState(false); - - const createResearchObject = async () => { - setLoading(true); - if (ceramic.did !== undefined) { - const inputs = { - title: object.title, - manifest: object.manifest, - }; - try { - await mutationCreateResearchObject(composeClient, inputs); - } catch (e) { - alert((e as Error).message); - } - updateParent(); - } - setLoading(false); - }; - - return ( - <> - {ceramic.did === undefined ? ( -
- ) : ( -
-
-
- - { - setObject({ ...object, title: e.target.value }); - }} - /> -
-
- - { - setObject({ ...object, manifest: e.target.value }); - }} - /> -
-
- -
-
-
- )} - - ); -}; diff --git a/components/Sidebar.tsx b/components/Sidebar.tsx deleted file mode 100755 index 45b428f..0000000 --- a/components/Sidebar.tsx +++ /dev/null @@ -1,27 +0,0 @@ -"use client"; -import Image from "next/image"; -import Link from "next/link"; -import nodesLogo from "@/public/nodes.png"; - -import { FaHome, FaUser, FaHashtag } from "react-icons/fa"; - -export const Sidebar = () => { - return ( -
-
-
- {"Nodes -
- - Home - - - Profile - - - Explore - -
-
- ); -}; diff --git a/components/UserForm.tsx b/components/UserForm.tsx deleted file mode 100644 index 5fb59ce..0000000 --- a/components/UserForm.tsx +++ /dev/null @@ -1,93 +0,0 @@ -"use client"; -import { useState, useEffect, useCallback } from "react"; -import { useCeramicContext } from "@/context"; -import { Profile } from "@/types"; -import styles from "@/styles/profile.module.scss"; -import { mutationCreateProfile, queryViewerProfile } from "@/utils/queries"; - -export const UserForm = () => { - const clients = useCeramicContext(); - const { ceramic, composeClient } = clients; - - const [profile, setProfile] = useState(); - const [loading, setLoading] = useState(false); - - const getProfile = useCallback(async () => { - setLoading(true); - if (ceramic.did !== undefined) { - const profile = await queryViewerProfile(composeClient); - if (profile === null) { - console.log( - "Failed to fetch profile, maybe user haven't created one yet" - ); - } else { - setProfile(profile); - } - setLoading(false); - } - }, [setLoading, setProfile, composeClient, ceramic.did]); - - const updateProfile = async () => { - setLoading(true); - if (ceramic.did !== undefined && profile !== undefined) { - let success = true; - try { - await mutationCreateProfile(composeClient, profile); - } catch (e) { - alert((e as Error).message); - success = false; - } - if (success) { - await getProfile(); - } - setLoading(false); - } - }; - - useEffect(() => { - getProfile(); - }, [getProfile]); - - return ( - <> - {profile === undefined && ceramic.did === undefined ? ( -
- ) : ( -
-
-
- - { - setProfile({ ...profile, displayName: e.target.value }); - }} - /> -
-
- - { - setProfile({ ...profile, orcid: e.target.value }); - }} - /> -
-
- -
-
-
- )} - - ); -}; diff --git a/context/index.tsx b/context/index.tsx deleted file mode 100644 index 5567af3..0000000 --- a/context/index.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { createContext, useContext } from "react"; -import { CeramicClient } from "@ceramicnetwork/http-client"; -import { ComposeClient } from "@composedb/client"; - -import { definition } from "@/src/__generated__/definition.js"; -import { RuntimeCompositeDefinition } from "@composedb/types"; - -/** - * Configure ceramic Client & create context. - */ -const ceramic = new CeramicClient("http://localhost:7007"); - -const composeClient = new ComposeClient({ - ceramic: "http://localhost:7007", - // cast our definition as a RuntimeCompositeDefinition - definition: definition as RuntimeCompositeDefinition, -}); - -const CeramicContext = createContext({ - ceramic: ceramic, - composeClient: composeClient, -}); - -export const CeramicWrapper = ({ children }: any) => { - return ( - - {children} - - ); -}; - -/** - * Provide access to the Ceramic & Compose clients. - * @example const { ceramic, compose } = useCeramicContext() - * @returns CeramicClient - */ - -export const useCeramicContext = () => useContext(CeramicContext); diff --git a/next-env.d.ts b/next-env.d.ts deleted file mode 100644 index 4f11a03..0000000 --- a/next-env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/// -/// - -// NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/next.config.js b/next.config.js deleted file mode 100644 index a843cbe..0000000 --- a/next.config.js +++ /dev/null @@ -1,6 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { - reactStrictMode: true, -} - -module.exports = nextConfig diff --git a/package-lock.json b/package-lock.json index 35bb97e..729261c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "desci-composites", "version": "1.0.0", + "license": "MIT", "dependencies": { "@ceramicnetwork/http-client": "^2.31.0", "@composedb/client": "^0.5.0", @@ -14,10 +15,7 @@ "@didtools/pkh-ethereum": "^0.4.1", "did-session": "^2.0.1", "dids": "^4.0.4", - "graphql": "^16.8.0", - "next": "^13.4.19", - "react-icons": "^4.10.1", - "sass": "^1.66.1" + "graphql": "^16.8.0" }, "devDependencies": { "@ceramicnetwork/cli": "^2.35.0", @@ -27,9 +25,7 @@ "@composedb/devtools-node": "^0.5.0", "@composedb/graphql-scalars": "^0.5.0", "@composedb/types": "^0.5.0", - "@types/react": "18.2.21", "eslint": "8.48.0", - "eslint-config-next": "13.4.19", "key-did-resolver": "^3.0.0", "vite-tsconfig-paths": "^4.2.1", "vitest": "^0.34.5" @@ -3306,155 +3302,6 @@ "npm": ">=7.0.0" } }, - "node_modules/@next/env": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.6.tgz", - "integrity": "sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "13.4.19", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.4.19.tgz", - "integrity": "sha512-N/O+zGb6wZQdwu6atMZHbR7T9Np5SUFUjZqCbj0sXm+MwQO35M8TazVB4otm87GkXYs2l6OPwARd3/PUWhZBVQ==", - "dev": true, - "dependencies": { - "glob": "7.1.7" - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.6.tgz", - "integrity": "sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.6.tgz", - "integrity": "sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.6.tgz", - "integrity": "sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.6.tgz", - "integrity": "sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.6.tgz", - "integrity": "sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.6.tgz", - "integrity": "sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.6.tgz", - "integrity": "sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.6.tgz", - "integrity": "sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.6.tgz", - "integrity": "sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@noble/ciphers": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.4.0.tgz", @@ -3636,7 +3483,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.4.1.tgz", "integrity": "sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA==", - "devOptional": true, + "dev": true, "engines": { "node": ">=8.0.0" } @@ -4088,12 +3935,6 @@ "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz", "integrity": "sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA==" }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz", - "integrity": "sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==", - "dev": true - }, "node_modules/@samverschueren/stream-to-observable": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", @@ -4478,14 +4319,6 @@ } ] }, - "node_modules/@swc/helpers": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz", - "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==", - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -4710,12 +4543,6 @@ "dev": true, "peer": true }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", @@ -4747,12 +4574,6 @@ "undici-types": "~5.26.4" } }, - "node_modules/@types/prop-types": { - "version": "15.7.9", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", - "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==", - "dev": true - }, "node_modules/@types/qs": { "version": "6.9.9", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", @@ -4767,17 +4588,6 @@ "dev": true, "peer": true }, - "node_modules/@types/react": { - "version": "18.2.21", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.21.tgz", - "integrity": "sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, "node_modules/@types/responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.2.tgz", @@ -4787,12 +4597,6 @@ "@types/node": "*" } }, - "node_modules/@types/scheduler": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.5.tgz", - "integrity": "sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==", - "dev": true - }, "node_modules/@types/send": { "version": "0.17.3", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", @@ -4816,108 +4620,6 @@ "@types/node": "*" } }, - "node_modules/@typescript-eslint/parser": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.0.tgz", - "integrity": "sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/typescript-estree": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz", - "integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", - "integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz", - "integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", - "integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.9.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@vitest/expect": { "version": "0.34.6", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", @@ -5398,6 +5100,9 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "optional": true, + "peer": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -5445,53 +5150,12 @@ "sprintf-js": "~1.0.2" } }, - "node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "dev": true }, - "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -5501,138 +5165,34 @@ "node": ">=8" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "*" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", - "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", - "dev": true - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, - "node_modules/asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "dev": true, "engines": { "node": ">= 0.4" @@ -5685,15 +5245,6 @@ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true }, - "node_modules/axe-core": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.8.2.tgz", - "integrity": "sha512-/dlp0fxyM3R8YW7MFzaHWXrf4zzbr0vaYb23VBFCl83R7nWNPg/yaQw2Dc8jzCMmDVLhSdzH8MjrsuIUuvX+6g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/axios": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", @@ -5703,15 +5254,6 @@ "follow-redirects": "^1.14.4" } }, - "node_modules/axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", - "dev": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -5821,6 +5363,9 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -5989,6 +5534,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -6151,6 +5697,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, "dependencies": { "streamsearch": "^1.1.0" }, @@ -6391,25 +5938,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001558", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001558.tgz", - "integrity": "sha512-/Et7DwLqpjS47JPEcz6VnxU9PwcIdVi0ciLXRWBQdj1XFye68pSQYpV0QtPTfUKWuOaEig+/Vez2l74eDc1tPQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, "node_modules/canonicalize": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-2.0.0.tgz", @@ -6597,12 +6125,15 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, "funding": [ { "type": "individual", "url": "https://paulmillr.com/funding/" } ], + "optional": true, + "peer": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -6623,6 +6154,9 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "optional": true, + "peer": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -6784,11 +6318,6 @@ "node": ">=0.10.0" } }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" - }, "node_modules/clone-response": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", @@ -7010,12 +6539,6 @@ "node": ">= 8" } }, - "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", - "dev": true - }, "node_modules/cuint": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", @@ -7070,12 +6593,6 @@ "cborg": "lib/bin.js" } }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true - }, "node_modules/dataloader": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", @@ -7222,23 +6739,6 @@ "node": ">= 0.4" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/delay": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", @@ -7266,15 +6766,6 @@ "node": ">= 0.8" } }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -7567,12 +7058,6 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -7679,19 +7164,6 @@ "once": "^1.4.0" } }, - "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/env-paths": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", @@ -7827,121 +7299,6 @@ "u3": "^0.1.1" } }, - "node_modules/es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", - "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==", - "dev": true, - "dependencies": { - "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.1", - "es-set-tostringtag": "^2.0.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.2.1", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.0.1" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/esbuild": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", @@ -7976,365 +7333,88 @@ "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", - "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.48.0", - "@humanwhocodes/config-array": "^0.11.10", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-next": { - "version": "13.4.19", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.4.19.tgz", - "integrity": "sha512-WE8367sqMnjhWHvR5OivmfwENRQ1ixfNE9hZwQqNCsd+iM3KnuMc1V8Pt6ytgjxjf23D+xbesADv9x3xaKfT3g==", - "dev": true, - "dependencies": { - "@next/eslint-plugin-next": "13.4.19", - "@rushstack/eslint-patch": "^1.1.3", - "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.31.7", - "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" - }, - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0", - "typescript": ">=3.3.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", - "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", - "dev": true, - "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "fast-glob": "^3.3.1", - "get-tsconfig": "^4.5.0", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz", - "integrity": "sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", - "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.20.7", - "aria-query": "^5.1.3", - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.6.2", - "axobject-query": "^3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.3", - "language-tags": "=1.0.5", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "@esbuild/win32-x64": "0.18.20" } }, - "node_modules/eslint-plugin-react": { - "version": "7.33.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", - "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.12", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.8" - }, "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "node": ">=6" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "engines": { "node": ">=10" }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "node_modules/eslint": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", + "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", "dev": true, "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.48.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" }, "bin": { - "resolve": "bin/resolve" + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-scope": { @@ -8848,6 +7928,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -9029,6 +8110,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -9047,33 +8129,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/gauge": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", @@ -9160,34 +8215,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", - "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", - "dev": true, - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, "node_modules/getopts": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", @@ -9226,11 +8253,6 @@ "node": ">=10.13.0" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" - }, "node_modules/globals": { "version": "13.23.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", @@ -9258,21 +8280,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -9359,7 +8366,8 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/graphemer": { "version": "1.4.0", @@ -9442,15 +8450,6 @@ "gunzip-maybe": "bin.js" } }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -9472,15 +8471,6 @@ "node": ">=0.10.0" } }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -9760,7 +8750,10 @@ "node_modules/immutable": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", - "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==" + "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", + "dev": true, + "optional": true, + "peer": true }, "node_modules/import-fresh": { "version": "3.3.0", @@ -9835,20 +8828,6 @@ "integrity": "sha512-SI2co5IAxAybBc9egRM2bXvHOa1RPh5SQQkO6di6t/aX92RbtzP4t8raB0l3GTzQmJADaBbzz8Tfa1QLgfMdGQ==", "dev": true }, - "node_modules/internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/interpret": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", @@ -10180,57 +9159,19 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "peer": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -10238,22 +9179,6 @@ "node": ">=8" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-buffer": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", @@ -10301,21 +9226,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-deflate": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", @@ -10347,22 +9257,11 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -10391,6 +9290,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -10421,53 +9321,18 @@ }, "node_modules/is-lambda": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true, - "optional": true - }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true, + "optional": true }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.12.0" } }, "node_modules/is-observable": { @@ -10506,43 +9371,6 @@ "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", "dev": true }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -10555,36 +9383,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-typed-array": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", @@ -10618,40 +9416,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -10664,12 +9428,6 @@ "node": ">=8" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -10788,19 +9546,6 @@ "node": ">=8" } }, - "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - } - }, "node_modules/jake": { "version": "10.8.7", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", @@ -10875,11 +9620,6 @@ "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, "node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", @@ -10933,18 +9673,6 @@ "integrity": "sha512-5Nom9inkIMrtY992LMBBG1Zaekrc10JaRhyZgprwHBVMDtRgllTvzl0oBbg13wJsVZoSoFNNMaeIVQs0P04vsA==", "dev": true }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, "node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", @@ -10973,21 +9701,6 @@ "base64-js": "^1.5.1" } }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, "node_modules/key-did-provider-ed25519": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/key-did-provider-ed25519/-/key-did-provider-ed25519-3.0.2.tgz", @@ -11172,21 +9885,6 @@ "npm": ">=7.0.0" } }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", - "dev": true - }, - "node_modules/language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", - "dev": true, - "dependencies": { - "language-subtag-registry": "~0.3.2" - } - }, "node_modules/least-recent": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/least-recent/-/least-recent-1.0.3.tgz", @@ -12173,17 +10871,6 @@ "node": ">=0.6" } }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, "node_modules/loupe": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", @@ -12843,51 +11530,6 @@ "node": ">= 0.6" } }, - "node_modules/next": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/next/-/next-13.5.6.tgz", - "integrity": "sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==", - "dependencies": { - "@next/env": "13.5.6", - "@swc/helpers": "0.5.2", - "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001406", - "postcss": "8.4.31", - "styled-jsx": "5.1.1", - "watchpack": "2.4.0" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=16.14.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "13.5.6", - "@next/swc-darwin-x64": "13.5.6", - "@next/swc-linux-arm64-gnu": "13.5.6", - "@next/swc-linux-arm64-musl": "13.5.6", - "@next/swc-linux-x64-gnu": "13.5.6", - "@next/swc-linux-x64-musl": "13.5.6", - "@next/swc-win32-arm64-msvc": "13.5.6", - "@next/swc-win32-ia32-msvc": "13.5.6", - "@next/swc-win32-x64-msvc": "13.5.6" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, "node_modules/nft-did-resolver": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/nft-did-resolver/-/nft-did-resolver-3.0.0.tgz", @@ -13086,6 +11728,9 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -13186,15 +11831,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/object-sizeof": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/object-sizeof/-/object-sizeof-2.6.3.tgz", @@ -13212,97 +11848,6 @@ "node": ">= 10" } }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" - } - }, - "node_modules/object.hasown": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", - "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -14001,12 +12546,14 @@ "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "engines": { "node": ">=8.6" }, @@ -14121,6 +12668,7 @@ "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -14148,6 +12696,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, "funding": [ { "type": "github", @@ -14275,17 +12824,6 @@ "dev": true, "optional": true }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, "node_modules/protobufjs": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", @@ -14480,60 +13018,21 @@ "node": ">= 0.6" } }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" - }, - "peerDependencies": { - "react": "^18.2.0" - } - }, - "node_modules/react-icons": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.11.0.tgz", - "integrity": "sha512-V+4khzYcE5EBk/BvcuYRq6V/osf11ODUM2J8hg2FDSswRrGvqiYUYPRy4OdrWaQOBj4NcpJfmHZLNaD+VH0TyA==", - "peerDependencies": { - "react": "*" + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, "node_modules/react-native-fetch-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/react-native-fetch-api/-/react-native-fetch-api-3.0.0.tgz", @@ -14570,6 +13069,9 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "optional": true, + "peer": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -14613,49 +13115,12 @@ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", "dev": true }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", - "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/regenerator-runtime": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", "dev": true }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -14696,15 +13161,6 @@ "node": ">=4" } }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, "node_modules/responselike": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", @@ -14969,24 +13425,6 @@ "node": ">=6" } }, - "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -15019,20 +13457,6 @@ "merge-options": "^3.0.4" } }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -15043,6 +13467,9 @@ "version": "1.69.5", "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.5.tgz", "integrity": "sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==", + "dev": true, + "optional": true, + "peer": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -15061,15 +13488,6 @@ "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==", "dev": true }, - "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - } - }, "node_modules/scrypt-js": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", @@ -15253,20 +13671,6 @@ "node": ">= 0.4" } }, - "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -15414,6 +13818,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -15571,6 +13976,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true, "engines": { "node": ">=10.0.0" } @@ -15612,71 +14018,6 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/string.prototype.matchall": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", - "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "regexp.prototype.flags": "^1.5.0", - "set-function-name": "^2.0.0", - "side-channel": "^1.0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -15734,28 +14075,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, "node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -15817,15 +14136,6 @@ "node": ">=0.10.0" } }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/tar": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", @@ -16137,6 +14447,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -16167,18 +14478,6 @@ "node": "*" } }, - "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", - "dev": true, - "engines": { - "node": ">=16.13.0" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, "node_modules/ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", @@ -16242,18 +14541,6 @@ } } }, - "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -16311,71 +14598,6 @@ "node": ">= 0.6" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/typedarray-to-buffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-4.0.0.tgz", @@ -16477,21 +14699,6 @@ "npm": ">=7.0.0" } }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/undici": { "version": "5.27.0", "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.0.tgz", @@ -16877,18 +15084,6 @@ } } }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -16931,63 +15126,6 @@ "node": ">= 8" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dev": true, - "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/which-typed-array": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", diff --git a/package.json b/package.json index df5d786..a22e0dd 100644 --- a/package.json +++ b/package.json @@ -2,19 +2,15 @@ "name": "desci-composites", "version": "1.0.0", "description": "", - "main": "index.js", "scripts": { "generate": "node scripts/commands.mjs", "dev": "node scripts/run.mjs", - "nextDev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint", "ceramic": "ceramic daemon --config composedb.config.json", "kill": "pkill --full \"ceramic daemon|ipfs daemon\"", "test": "vitest --run --config vitest.config.ts" }, - "author": "Edvard Hubinette", + "license": "MIT", + "author": "Edvard Hübinette", "devDependencies": { "@ceramicnetwork/cli": "^2.35.0", "@ceramicnetwork/streamid": "^2.17.0", @@ -23,9 +19,7 @@ "@composedb/devtools-node": "^0.5.0", "@composedb/graphql-scalars": "^0.5.0", "@composedb/types": "^0.5.0", - "@types/react": "18.2.21", "eslint": "8.48.0", - "eslint-config-next": "13.4.19", "key-did-resolver": "^3.0.0", "vite-tsconfig-paths": "^4.2.1", "vitest": "^0.34.5" @@ -37,9 +31,6 @@ "@didtools/pkh-ethereum": "^0.4.1", "did-session": "^2.0.1", "dids": "^4.0.4", - "graphql": "^16.8.0", - "next": "^13.4.19", - "react-icons": "^4.10.1", - "sass": "^1.66.1" + "graphql": "^16.8.0" } } diff --git a/pages/_app.tsx b/pages/_app.tsx deleted file mode 100644 index bb8350f..0000000 --- a/pages/_app.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import "@/styles/globals.scss"; - -import { CeramicWrapper, useCeramicContext } from "@/context"; -import type { AppProps } from "next/app"; -import { authenticateCeramic } from "@/utils"; -import { useCallback, useEffect } from "react"; -import AuthPrompt from "@/components/AuthPrompt"; -import { Sidebar } from "@/components/Sidebar"; -import { loadIfUninitialised } from "@/utils/populate"; -import { queryViewerId } from "@/utils/queries"; - -let doInitCheck = true; - -const MyApp = ({ Component, pageProps }: AppProps) => { - const { ceramic, composeClient } = useCeramicContext(); - - const setViewerId = useCallback(async () => { - if (ceramic.did !== undefined) { - const viewerId = await queryViewerId(composeClient); - localStorage.setItem("viewer", viewerId); - } - }, [ceramic.did, composeClient]); - - const handleLogin = useCallback(async () => { - await authenticateCeramic(ceramic, composeClient); - await setViewerId(); - }, [ceramic, composeClient, setViewerId]); - - // Update to include refresh on auth - useEffect(() => { - if (doInitCheck) { - loadIfUninitialised(ceramic); - doInitCheck = false; - } - if (localStorage.getItem("logged_in")) { - handleLogin(); - setViewerId(); - } - }, [composeClient, handleLogin, setViewerId]); - - return ( -
- -
- - -
- -
-
-
-
- ); -}; - -export default MyApp; diff --git a/pages/explore.tsx b/pages/explore.tsx deleted file mode 100644 index bfded2b..0000000 --- a/pages/explore.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import type { NextPage } from "next"; -import { useCallback, useEffect, useState } from "react"; -import { useCeramicContext } from "@/context"; -import { ResearchObject } from "@/types"; -import Head from "next/head"; -import styles from "@/styles/Home.module.scss"; -import React from "react"; -import ResearchObjectComponent from "@/components/ResearchObject"; -import { queryResearchObjects } from "@/utils/queries"; -import { AttestButton } from "@/components/AttestButton"; -import { AttestList } from "@/components/AttestList"; - -const ExplorePage: NextPage = () => { - const clients = useCeramicContext(); - const { composeClient } = clients; - const [objects, setObjects] = useState([]); - - const getResearchObjects = useCallback(async () => { - const researchObjects = await queryResearchObjects(composeClient); - setObjects(researchObjects); - }, [composeClient]); - - useEffect(() => { - getResearchObjects(); - }, [getResearchObjects]); - - return ( - <> - - Nodes Home - - -
-
- - {objects.map((ro) => ( - - - - - ))} -
-
- - ); -}; - -export default ExplorePage; diff --git a/pages/index.tsx b/pages/index.tsx deleted file mode 100644 index 26b332d..0000000 --- a/pages/index.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import type { NextPage } from "next"; -import { useCallback, useEffect, useState } from "react"; -import { useCeramicContext } from "@/context"; -import { ResearchObject } from "@/types"; -import Head from "next/head"; -import styles from "@/styles/Home.module.scss"; -import React from "react"; -import ResearchObjectComponent from "@/components/ResearchObject"; -import { ResearchObjectForm } from "@/components/ResearchObjectForm"; -import { queryViewerId, queryViewerResearchObjects } from "@/utils/queries"; - -const Home: NextPage = () => { - const clients = useCeramicContext(); - const { ceramic, composeClient } = clients; - const [objects, setObjects] = useState([]); - - const getResearchObjects = useCallback(async () => { - if (ceramic.did !== undefined) { - const viewerId = await queryViewerId(composeClient); - localStorage.setItem("viewer", viewerId); - - const ownResearchObjects = await queryViewerResearchObjects( - composeClient - ); - setObjects(ownResearchObjects); - } - }, [ceramic.did, composeClient]); - - useEffect(() => { - getResearchObjects(); - }, [getResearchObjects]); - - return ( - <> - - Nodes Home - - -
- {ResearchObjectForm(getResearchObjects)} -
- - {objects.map((ro) => ( - - ))} -
-
- - ); -}; - -export default Home; diff --git a/pages/profile.tsx b/pages/profile.tsx deleted file mode 100644 index a807ea5..0000000 --- a/pages/profile.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import type { NextPage } from "next"; -import Head from "next/head"; -import { UserForm } from "@/components/UserForm"; - -const ProfilePage: NextPage = () => { - return ( - <> - - Profile - -
-
- -
-
- - ); -}; - -export default ProfilePage; diff --git a/public/ceramic.png b/public/ceramic.png deleted file mode 100644 index bb15a70172f99be00879c11fed9f46b76af4120e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57047 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

BM=s=D@btDGuBhgm4+l>Vdm>J18%x@vf~iXHZQ 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 lC$zIKxSc|~lcVd;b@u0O{vU&5k*NRx diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index 718d6fea4835ec2d246af9800eddb7ffb276240c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25931 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 LrJugUA?W`A8`#=m diff --git a/public/nodes.png b/public/nodes.png deleted file mode 100644 index 76422495c5268008fe5f83a686a86e769e035193..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4284 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 - - \ No newline at end of file diff --git a/scripts/run.mjs b/scripts/run.mjs index 742b330..ba451ef 100644 --- a/scripts/run.mjs +++ b/scripts/run.mjs @@ -44,14 +44,6 @@ const graphiql = async () => { }) } -const next = async () => { - const next = spawn('npm', ['run', 'nextDev']) - spinner.info("[NextJS] starting nextjs app"); - next.stdout.on('data', (buffer) => { - console.log('[NextJS]', buffer.toString()) - }) -} - const start = async () => { try { spinner.start('[Ceramic] Starting Ceramic node\n') @@ -59,7 +51,6 @@ const start = async () => { if (isRunning) { await bootstrap() await graphiql() - await next() } if(isRunning === false) { ceramic.kill() diff --git a/styles/Home.module.css b/styles/Home.module.css deleted file mode 100644 index f89da21..0000000 --- a/styles/Home.module.css +++ /dev/null @@ -1,94 +0,0 @@ -.main { - height: 80rem; - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - text-align: center; -} -.title { - font-weight: regular; -} - -.logo { - top: 30px; -} - -.formGroup { - margin-top: 15px; - margin-bottom: 10px; - - font-size: 18px; -} -.formGroup label { - display: block; - padding-bottom: 2px; -} -.formGroup input { - border: 2px solid black; - color: #333; - /* background-color: #efefef; */ - border-radius: 5px; - font-size: 16px; - padding: 5px 15px; -} -.formGroup2 label { - display: block; - padding-bottom: 2px; -} -.formGroup2 input { - border: 2px solid black; - color: #333; - /* background-color: #efefef; */ - border-radius: 5px; - font-size: 16px; - height: 2rem; - padding: 5px 15px; -} -.buttonContainer { - width: 100%; - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; -} -.buttonContainer button { - width: 100%; -} - -.footer { - height: 62px; - position: sticky; - bottom: 0px; - right:0px; - - min-width: 100vh; - padding: 20px; - - display: flex; - flex-direction: row; - flex-wrap: wrap; - align-items: center; - justify-content: center; - font-size: 18px; -} -.footer::before { - content: ""; - position: absolute; - top: 0; - left: 37.5%; - width: 25%; - text-align: center; - height: 2px; - background-color: #eb4a27; -} -.footer div { - display: inline-block; - width: 100%; - text-align: center; -} -.footer a { - display: block; - -} diff --git a/styles/Home.module.scss b/styles/Home.module.scss deleted file mode 100755 index 6e7cfb7..0000000 --- a/styles/Home.module.scss +++ /dev/null @@ -1,80 +0,0 @@ -@import "./colors.module.scss"; -@import "./mixins.scss"; -.title { - font-weight: regular; -} - -.formGroup { - margin-bottom: 10px; - font-size: 18px; - label { - display: block; - padding-bottom: 3px; - } - input { - border: 2px solid black; - color: #333; - border-radius: 5px; - font-size: 16px; - padding: 5px 15px; - } -} - -.buttonContainer { - width: 240px; - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; -} -.buttonContainer button { - width: 100%; -} - -.postContainer { - flex-grow: 1; - padding: 0; - // width: calc(100% + 5px); - @include scrollbar; - .post { - border-bottom: 1px solid $borders; - padding: 15px 20px; - - white-space:pre; - } -} - -.postInput { - border: none; - border-bottom: 1px solid $borders; - color: white; - - height: 120px; - - padding: 10px 15px; - background-color: $bgColor; -} - -.share { - min-width:100%; - - max-height: 100px; - - display: flex; - flex-direction: row; - flex-wrap: nowrap; - flex-grow:1; - - align-items: center; - textarea { - resize: none; - height: 100px; - width: calc(100% - 36px); - font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif - } - button { - height:100%; - margin: 0; - border-radius: 0; - } -} \ No newline at end of file diff --git a/styles/colors.module.scss b/styles/colors.module.scss deleted file mode 100755 index a0823c3..0000000 --- a/styles/colors.module.scss +++ /dev/null @@ -1,3 +0,0 @@ -$borders: #696969; -$bgColor: #292828; -$accent: #eb4a27; \ No newline at end of file diff --git a/styles/globals.css b/styles/globals.css deleted file mode 100644 index d0fbcfd..0000000 --- a/styles/globals.css +++ /dev/null @@ -1,33 +0,0 @@ -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: #292828; - color: #f5f5f5; -} - -a { - color: inherit; - text-decoration: none; -} - -button { - border: none; - border-radius: 5px; - margin-top: 15px; - padding: 10px 15px; - color: #f5f5f5; - background: #eb4a27; - cursor: pointer; -} - -input { - background: #f5f5f5; - color: #292828; -} - -* { - box-sizing: border-box; -} diff --git a/styles/globals.scss b/styles/globals.scss deleted file mode 100755 index 216126d..0000000 --- a/styles/globals.scss +++ /dev/null @@ -1,89 +0,0 @@ -@import "./layout.module.scss"; -@import "./colors.module.scss"; -@import "./mixins.scss"; -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: #292828; - color: #f5f5f5; -} - -a { - color: inherit; - text-decoration: none; -} - -button { - border: none; - border-radius: 5px; - margin-top: 15px; - padding: 10px 15px; - color: #f5f5f5; - background: #eb4a27; - cursor: pointer; -} - -input { - background: #f5f5f5; - color: #292828; -} - -* { - box-sizing: border-box; -} - -.content { - height: calc(100vh - 80px); - display: flex; - flex-direction: column; - justify-content: center; - width: 100%; - padding: 0; -} - -.composite { - white-space: pre; -} - -.popup { - position: fixed; - top: 0; - left: 0; - bottom: 0; - right: 0; - z-index: 9999; - // background-color: rgba(0, 0, 0, 0.5); - display: hidden; - &::before { - content: " "; - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - z-index: 0; - background-color: rgba(0, 0, 0, 0.5); - backdrop-filter: blur(2px); - } - - h2 { - text-align: center; - } - .popup-content { - border-radius: 10px; - padding: 10px; - box-shadow: 0 0 10px rgba(127, 127, 127, 0.9); - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background-color: rgba(0, 0, 0, 1); - - span { - padding: 4px; - } - } -} diff --git a/styles/layout.module.scss b/styles/layout.module.scss deleted file mode 100755 index 240bc77..0000000 --- a/styles/layout.module.scss +++ /dev/null @@ -1,126 +0,0 @@ -@import "colors.module.scss"; - -.container { - width: 70%; - @media screen and (max-width: 540px) { - width: 100% - } - margin: 0 auto; - - /* Flex positioning */ - display: flex; - flex-direction: row; - justify-content: space-between; - flex: 1; - .sidebar, - .ctas { - margin: auto 0; - height: 100vh; - position: sticky; - - max-width: 250px; - } - @media screen and (max-width: 540px) { - .sidebar { - max-width: 120px!important; - .logoContainer{ - width:100px!important; - } - a { - font-size: 18px!important; - } - } - } - .sidebar { - display: flex; - flex-direction: column; - justify-content: space-between; - - padding: 0 5px; - - .top { - .logoContainer { - margin: 30px 0 30px 5px; - width: 180px; - } - a { - font-size: 24px; - font-weight: bold; - letter-spacing: 1px; - cursor: pointer; - padding: 5px 10px; - margin-bottom: 10px; - width:100%; - - display: inline-flex; - align-items: center; - - transition: ease all .1s; - svg { - margin-right: 10px; - } - &:hover { - background-color: $accent; - transition: ease all .25s; - } - } - } - .bottom { - margin-bottom: 30px; - } - } - .body { - $border: 1.5px solid $borders; - - margin: 0 15px; - border-left: $border; - border-right: $border; - - display: flex; - flex-grow: 1; - flex-direction: column; - align-items: center; - justify-content: center; - } - .footer { - background-color: $bgColor; - - height: 62px; - position: relative; - bottom: 0px; - right:0px; - width: 100%; - - padding: 20px; - - display: flex; - flex-grow: 1; - flex-wrap: wrap; - align-items: center; - - font-size: 18px; - &:before { - content: ""; - position: absolute; - top: 0; - left: calc((100% - 240px) / 2); - width: 240px; - @media screen and (max-width: 540px) { - width: 100px; - left:calc((100% - 100px) / 2); - } - text-align: center; - height: 2px; - background-color: #eb4a27; - } - div { - display: inline-block; - width: 100%; - text-align: center; - } - a { - display: block; - } - } -} - diff --git a/styles/mixins.scss b/styles/mixins.scss deleted file mode 100644 index ab9d9ce..0000000 --- a/styles/mixins.scss +++ /dev/null @@ -1,14 +0,0 @@ -@mixin scrollbar { - // This is causing weird padding issues - overflow-y: scroll; - &::-webkit-scrollbar { - background-color: transparent; - - width:5px; - } - &::-webkit-scrollbar-thumb { - border: 1px solid $borders; - background: $accent; - border-radius: 10px; - } -} \ No newline at end of file diff --git a/styles/profile.module.scss b/styles/profile.module.scss deleted file mode 100644 index 46daff8..0000000 --- a/styles/profile.module.scss +++ /dev/null @@ -1,18 +0,0 @@ -.formGroup { - margin-bottom: 10px; - font-size: 18px; - display: flex; - flex-direction: column; - align-items: center; - label { - display: block; - padding-bottom: 3px; - } - input { - border: 2px solid black; - color: #333; - border-radius: 5px; - font-size: 16px; - padding: 5px 15px; - } -} \ No newline at end of file diff --git a/styles/user.module.scss b/styles/user.module.scss deleted file mode 100644 index fcbdfe0..0000000 --- a/styles/user.module.scss +++ /dev/null @@ -1,23 +0,0 @@ -@import "./colors.module.scss"; -.details { - border-bottom: 1px solid $borders; - display: flex; - justify-content: space-between; - align-items: center; - min-height:120px; - .user { - display: flex; - flex-direction: row; - align-items: center; - .emoji { - font-size: 40px; - display: inline-block; - } - .names { - - } - .follow { - align-self: flex-end; - } - } -} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 8ea10b8..c794de1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,7 +26,6 @@ } }, "include": [ - "next-env.d.ts", "**/*.ts", "**/*.tsx", "template_data.json" From 05c7d536547d6fed1cd8d60b1a4c55cc01ba178f Mon Sep 17 00:00:00 2001 From: m0ar Date: Wed, 1 Nov 2023 14:52:43 +0100 Subject: [PATCH 2/9] Linting pass --- .github/workflows/pr.yml | 2 +- .vscode/settings.json | 68 +- README.md | 7 +- composites/00-profile.graphql | 5 +- composites/001-researchField.graphql | 6 +- composites/01-researchObject.graphql | 5 +- composites/02-organization.graphql | 5 +- composites/05-claim.graphql | 8 +- composites/06-attestation.graphql | 3 +- composites/07-researchComponent.graphql | 8 +- composites/08-referenceRelation.graphql | 10 +- composites/09-contributorRelation.graphql | 11 +- composites/10-researchFieldRelation.graphql | 11 +- composites/11-annotation.graphql | 10 +- composites/additional-relations.graphql | 89 ++- package-lock.json | 236 +++++- package.json | 8 +- scripts/commands.mjs | 24 +- scripts/composites.mjs | 96 +-- scripts/run.mjs | 64 +- stream-to-cid.mjs | 8 +- template_data.json | 5 +- test/root.spec.ts | 808 +++++++++++--------- test/util.ts | 22 +- tsconfig.json | 20 +- types/index.ts | 166 ++-- utils/index.ts | 40 +- utils/populate.tsx | 258 +++---- utils/queries.ts | 675 ++++++++-------- utils/templateData.d.ts | 74 +- vitest.config.ts | 10 +- 31 files changed, 1571 insertions(+), 1191 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 693080e..9cd8dcb 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -1,6 +1,6 @@ on: pull_request: - branches: + branches: - main jobs: test: diff --git a/.vscode/settings.json b/.vscode/settings.json index 5215238..7c63cde 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,39 +1,39 @@ { + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/Thumbs.db": true + }, + "hide-files.files": [], + "editor.formatOnSave": true, // Tell VSCode to format files on save + "editor.defaultFormatter": "esbenp.prettier-vscode", + "typescript.format.enable": false, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true - }, - "files.exclude": { - "**/.git": true, - "**/.svn": true, - "**/.hg": true, - "**/CVS": true, - "**/.DS_Store": true, - "**/Thumbs.db": true - }, - "hide-files.files": [], - "editor.formatOnSave": true, // Tell VSCode to format files on save + /// TSX auto format on save ESLint + "source.fixAll.eslint": true + } + }, + "[typescriptreact]": { "editor.defaultFormatter": "esbenp.prettier-vscode", - "typescript.format.enable": false, - "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true, - "editor.codeActionsOnSave": { - /// TSX auto format on save ESLint - "source.fixAll.eslint": true - } - }, - "[typescriptreact]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true, - "editor.codeActionsOnSave": { - /// TSX auto format on save ESLint - "source.fixAll.eslint": true - } - }, - "[xml]": { - "editor.defaultFormatter": "redhat.vscode-xml" - }, - "[properties]": { - "editor.defaultFormatter": "foxundermoon.shell-format" + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + /// TSX auto format on save ESLint + "source.fixAll.eslint": true } + }, + "[xml]": { + "editor.defaultFormatter": "redhat.vscode-xml" + }, + "[properties]": { + "editor.defaultFormatter": "foxundermoon.shell-format" + } } diff --git a/README.md b/README.md index dca8744..4664b32 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # ComposeDB configuration + This is a rough take on model definitions for DeSci Nodes on Ceramic and ComposeDB, based on a Ceramic demo at ETHDenver and snippets from Mark Krasner. ## Getting Started + 1. Install your dependencies: ```bash @@ -21,17 +23,20 @@ npm run generate ```bash npm run dev ``` + - Open [http://localhost:3000](http://localhost:3000) to get to Nodes Home - Open [http://localhost:5001](http://localhost:5001) for the GraphiQL interface ## Reset + To clean everything up, delete `local-data`. This is necessary when changing networks, for example. ## Tests + There is a test suite running through API operations demonstrating the functional protocol requirements in an isolated ceramic instance not to dirty down the state, but can also be run against the dev process. Not both at the same time though, because the ports overlap. ```bash make test -``` \ No newline at end of file +``` diff --git a/composites/00-profile.graphql b/composites/00-profile.graphql index 3e29242..5361a22 100644 --- a/composites/00-profile.graphql +++ b/composites/00-profile.graphql @@ -1,9 +1,8 @@ -type Profile +type Profile @createModel(accountRelation: SINGLE, description: "An author profile") @createIndex(fields: [{ path: "orcid" }]) @createIndex(fields: [{ path: "googleScholar" }]) - @createIndex(fields: [{ path: "publicKey" }]) -{ + @createIndex(fields: [{ path: "publicKey" }]) { owner: DID! @documentAccount version: CommitID! @documentVersion displayName: String! @string(maxLength: 256) diff --git a/composites/001-researchField.graphql b/composites/001-researchField.graphql index fcab995..1fa9424 100644 --- a/composites/001-researchField.graphql +++ b/composites/001-researchField.graphql @@ -1,6 +1,8 @@ type ResearchField - @createModel(accountRelation: LIST, description: "A particular field of research") -{ + @createModel( + accountRelation: LIST + description: "A particular field of research" + ) { owner: DID! @documentAccount version: CommitID! @documentVersion title: String! @string(maxLength: 256) diff --git a/composites/01-researchObject.graphql b/composites/01-researchObject.graphql index 614261d..054465c 100644 --- a/composites/01-researchObject.graphql +++ b/composites/01-researchObject.graphql @@ -1,7 +1,6 @@ type ResearchObject - @createModel(accountRelation: LIST, description: "A research object") - @createIndex(fields: [{ path: "title" }]) -{ + @createModel(accountRelation: LIST, description: "A research object") + @createIndex(fields: [{ path: "title" }]) { owner: DID! @documentAccount version: CommitID! @documentVersion title: String! @string(maxLength: 250) diff --git a/composites/02-organization.graphql b/composites/02-organization.graphql index 3d76b81..b1f3505 100644 --- a/composites/02-organization.graphql +++ b/composites/02-organization.graphql @@ -1,7 +1,6 @@ -type Organization +type Organization @createModel(accountRelation: LIST, description: "An organization") - @createIndex(fields: [{ path: "name" }]) -{ + @createIndex(fields: [{ path: "name" }]) { owner: DID! @documentAccount version: CommitID! @documentVersion name: String! @string(maxLength: 250) diff --git a/composites/05-claim.graphql b/composites/05-claim.graphql index b3b8531..ff90c3a 100644 --- a/composites/05-claim.graphql +++ b/composites/05-claim.graphql @@ -1,8 +1,10 @@ type Claim - @createModel(accountRelation: LIST, description: "A reusable claim to be granted via attestation") + @createModel( + accountRelation: LIST + description: "A reusable claim to be granted via attestation" + ) @createIndex(fields: [{ path: "title" }]) - @createIndex(fields: [{ path: "badge" }]) -{ + @createIndex(fields: [{ path: "badge" }]) { maintainer: DID! @documentAccount version: CommitID! @documentVersion title: String! @string(maxLength: 100) diff --git a/composites/06-attestation.graphql b/composites/06-attestation.graphql index 97259da..3bb8a28 100644 --- a/composites/06-attestation.graphql +++ b/composites/06-attestation.graphql @@ -7,8 +7,7 @@ type Attestation @createIndex(fields: [{ path: "revoked" }]) @createIndex(fields: [{ path: "targetID" }]) @createIndex(fields: [{ path: "targetVersion" }]) - @createIndex(fields: [{ path: "claimVersion" }]) -{ + @createIndex(fields: [{ path: "claimVersion" }]) { source: DID! @documentAccount version: CommitID! @documentVersion # 1. Any type of document, shown with relation on reciever end but cannot use diff --git a/composites/07-researchComponent.graphql b/composites/07-researchComponent.graphql index c51e85a..7bf4e8c 100644 --- a/composites/07-researchComponent.graphql +++ b/composites/07-researchComponent.graphql @@ -4,14 +4,13 @@ type ResearchObject @loadModel(id: "$RESEARCH_OBJECT_ID") { type ResearchComponent @createModel( - accountRelation: LIST, + accountRelation: LIST description: "A contextualized DAG pointer for a research object" ) @createIndex(fields: [{ path: "mimeType" }]) @createIndex(fields: [{ path: "researchObjectVersion" }]) # Don't join index with path as it prevents efficient reverse CID lookups - @createIndex(fields: [{ path: "dagNode" }]) -{ + @createIndex(fields: [{ path: "dagNode" }]) { owner: DID! @documentAccount version: CommitID! @documentVersion name: String! @string(maxLength: 512) @@ -24,6 +23,7 @@ type ResearchComponent # The associated research object researchObjectID: StreamID! @documentReference(model: "ResearchObject") - researchObject: ResearchObject! @relationDocument(property: "researchObjectID") + researchObject: ResearchObject! + @relationDocument(property: "researchObjectID") researchObjectVersion: CommitID! } diff --git a/composites/08-referenceRelation.graphql b/composites/08-referenceRelation.graphql index 792bba5..13207cd 100644 --- a/composites/08-referenceRelation.graphql +++ b/composites/08-referenceRelation.graphql @@ -2,12 +2,14 @@ type ResearchObject @loadModel(id: "$RESEARCH_OBJECT_ID") { id: ID! } -type ReferenceRelation - @createModel(accountRelation: LIST, description: "Indicate a reference between research objects") +type ReferenceRelation + @createModel( + accountRelation: LIST + description: "Indicate a reference between research objects" + ) @createIndex(fields: [{ path: "fromVersion" }]) @createIndex(fields: [{ path: "toVersion" }]) - @createIndex(fields: [{ path: "revoked" }]) -{ + @createIndex(fields: [{ path: "revoked" }]) { owner: DID! @documentAccount version: CommitID! @documentVersion diff --git a/composites/09-contributorRelation.graphql b/composites/09-contributorRelation.graphql index c42a8ad..eb5bb05 100644 --- a/composites/09-contributorRelation.graphql +++ b/composites/09-contributorRelation.graphql @@ -7,11 +7,13 @@ type Profile @loadModel(id: "$PROFILE_ID") { } type ContributorRelation - @createModel(accountRelation: LIST, description: "List a contributor on a research object") + @createModel( + accountRelation: LIST + description: "List a contributor on a research object" + ) @createIndex(fields: [{ path: "role" }]) @createIndex(fields: [{ path: "revoked" }]) - @createIndex(fields: [{ path: "researchObjectVersion" }]) -{ + @createIndex(fields: [{ path: "researchObjectVersion" }]) { owner: DID! @documentAccount version: CommitID! @documentVersion @@ -19,7 +21,8 @@ type ContributorRelation role: String! @string(maxLength: 256) researchObjectID: StreamID! @documentReference(model: "ResearchObject") - researchObject: ResearchObject! @relationDocument(property: "researchObjectID") + researchObject: ResearchObject! + @relationDocument(property: "researchObjectID") researchObjectVersion: CommitID! # Skipping stream versioning on profile reference diff --git a/composites/10-researchFieldRelation.graphql b/composites/10-researchFieldRelation.graphql index a4afabd..dff4762 100644 --- a/composites/10-researchFieldRelation.graphql +++ b/composites/10-researchFieldRelation.graphql @@ -7,13 +7,16 @@ type ResearchField @loadModel(id: "$RESEARCH_FIELD_ID") { } type ResearchFieldRelation - @createModel(accountRelation: LIST, description: "Association between a research object and a field") -{ + @createModel( + accountRelation: LIST + description: "Association between a research object and a field" + ) { owner: DID! @documentAccount version: CommitID! @documentVersion researchObjectID: StreamID! @documentReference(model: "ResearchObject") - researchObject: ResearchObject! @relationDocument(property: "researchObjectID") + researchObject: ResearchObject! + @relationDocument(property: "researchObjectID") researchObjectVersion: CommitID! # Skipping stream versioning on field refs @@ -22,4 +25,4 @@ type ResearchFieldRelation # Revoke this relation revoked: Boolean -} \ No newline at end of file +} diff --git a/composites/11-annotation.graphql b/composites/11-annotation.graphql index 63964d8..16abb84 100644 --- a/composites/11-annotation.graphql +++ b/composites/11-annotation.graphql @@ -11,8 +11,7 @@ type Annotation @createIndex(fields: [{ path: "targetID" }]) @createIndex(fields: [{ path: "claimID" }]) @createIndex(fields: [{ path: "researchObjectID" }]) - @createIndex(fields: [{ path: "dagNode" }]) -{ + @createIndex(fields: [{ path: "dagNode" }]) { owner: DID! @documentAccount version: CommitID! @documentVersion @@ -21,9 +20,10 @@ type Annotation # Research object context researchObjectID: StreamID! @documentReference(model: "ResearchObject") - researchObject: ResearchObject! @relationDocument(property: "researchObjectID") + researchObject: ResearchObject! + @relationDocument(property: "researchObjectID") researchObjectVersion: CommitID! - + # Research component or annotation as reply # TODO: interface targetID: StreamID @@ -34,7 +34,7 @@ type Annotation dagNode: CID pathToNode: String @string(maxLength: 512) - # Localization of the annotation payload, depending on file type. + # Localization of the annotation payload, depending on file type. # For example a JSON path, line number, or coordinates. locationOnFile: String @string(maxLength: 512) diff --git a/composites/additional-relations.graphql b/composites/additional-relations.graphql index 5429ffc..7d9dff0 100644 --- a/composites/additional-relations.graphql +++ b/composites/additional-relations.graphql @@ -21,54 +21,81 @@ type Annotation @loadModel(id: "$ANNOTATION_ID") { } type ResearchComponent @loadModel(id: "$RESEARCH_COMPONENT_ID") { - annotations: [Annotation] @relationFrom(model: "Annotation", property: "targetID") - annotationCount: Int! @relationCountFrom(model: "Annotation", property: "targetID") + annotations: [Annotation] + @relationFrom(model: "Annotation", property: "targetID") + annotationCount: Int! + @relationCountFrom(model: "Annotation", property: "targetID") } type Claim @loadModel(id: "$CLAIM_ID") { - attestations: [Attestation] @relationFrom(model: "Attestation", property: "claimID") - attestationCount: Int! @relationCountFrom(model: "Attestation", property: "claimID") - - annotations: [Annotation] @relationFrom(model: "Annotation", property: "claimID") - annotationCount: Int! @relationCountFrom(model: "Annotation", property: "claimID") + attestations: [Attestation] + @relationFrom(model: "Attestation", property: "claimID") + attestationCount: Int! + @relationCountFrom(model: "Attestation", property: "claimID") + + annotations: [Annotation] + @relationFrom(model: "Annotation", property: "claimID") + annotationCount: Int! + @relationCountFrom(model: "Annotation", property: "claimID") } type ResearchObject @loadModel(id: "$RESEARCH_OBJECT_ID") { - attestations: [Attestation] @relationFrom(model: "Attestation", property: "targetID") - attestationCount: Int! @relationCountFrom(model: "Attestation", property: "targetID") - - components: [ResearchComponent] @relationFrom(model: "ResearchComponent", property: "researchObjectID") - componentCount: Int! @relationCountFrom(model: "ResearchComponent", property: "researchObjectID") - - incomingReferences: [ReferenceRelation] @relationFrom(model: "ReferenceRelation", property: "toID") - outgoingReferences: [ReferenceRelation] @relationFrom(model: "ReferenceRelation", property: "fromID") - incomingReferenceCount: Int! @relationCountFrom(model: "ReferenceRelation", property: "toID") - outgoingReferenceCount: Int! @relationCountFrom(model: "ReferenceRelation", property: "fromID") - - contributors: [ContributorRelation] @relationFrom(model: "ContributorRelation", property: "researchObjectID") - contributorCount: Int! @relationCountFrom(model: "ContributorRelation", property: "researchObjectID") - - researchFields: [ResearchFieldRelation] @relationFrom(model: "ResearchFieldRelation", property: "researchObjectID") - - annotations: [Annotation] @relationFrom(model: "Annotation", property: "researchObjectID") - annotationCount: Int! @relationCountFrom(model: "Annotation", property: "researchObjectID") + attestations: [Attestation] + @relationFrom(model: "Attestation", property: "targetID") + attestationCount: Int! + @relationCountFrom(model: "Attestation", property: "targetID") + + components: [ResearchComponent] + @relationFrom(model: "ResearchComponent", property: "researchObjectID") + componentCount: Int! + @relationCountFrom(model: "ResearchComponent", property: "researchObjectID") + + incomingReferences: [ReferenceRelation] + @relationFrom(model: "ReferenceRelation", property: "toID") + outgoingReferences: [ReferenceRelation] + @relationFrom(model: "ReferenceRelation", property: "fromID") + incomingReferenceCount: Int! + @relationCountFrom(model: "ReferenceRelation", property: "toID") + outgoingReferenceCount: Int! + @relationCountFrom(model: "ReferenceRelation", property: "fromID") + + contributors: [ContributorRelation] + @relationFrom(model: "ContributorRelation", property: "researchObjectID") + contributorCount: Int! + @relationCountFrom( + model: "ContributorRelation" + property: "researchObjectID" + ) + + researchFields: [ResearchFieldRelation] + @relationFrom(model: "ResearchFieldRelation", property: "researchObjectID") + + annotations: [Annotation] + @relationFrom(model: "Annotation", property: "researchObjectID") + annotationCount: Int! + @relationCountFrom(model: "Annotation", property: "researchObjectID") } -# Support for incoming relations on CeramicAccounts is coming, but we'd need a separate +# Support for incoming relations on CeramicAccounts is coming, but we'd need a separate # account attestation because DID !== streamID. Main tradeoff that you can attest to an # yet inactive DID if known, even if they haven't created a profile. Does it make sense # though? type Profile @loadModel(id: "$PROFILE_ID") { - contributions: [ContributorRelation] @relationFrom(model: "ContributorRelation", property: "contributorID") - contributionCount: Int! @relationCountFrom(model: "ContributorRelation", property: "contributorID") + contributions: [ContributorRelation] + @relationFrom(model: "ContributorRelation", property: "contributorID") + contributionCount: Int! + @relationCountFrom(model: "ContributorRelation", property: "contributorID") - recievedAttestations: [Attestation] @relationFrom(model: "Attestation", property: "targetID") + recievedAttestations: [Attestation] + @relationFrom(model: "Attestation", property: "targetID") # bork bork bork because the attestation is associated with the DID, not the profile streamID # fix: can be accessed through owner -> attestationList # givenAttestations: [Attestation] @relationFrom(model: "Attestation", property: "source") } type ResearchField @loadModel(id: "$RESEARCH_FIELD_ID") { - researchObjects: [ResearchFieldRelation] @relationFrom(model: "ResearchFieldRelation", property: "fieldID") - researchObjectCount: Int! @relationCountFrom(model: "ResearchFieldRelation", property: "fieldID") + researchObjects: [ResearchFieldRelation] + @relationFrom(model: "ResearchFieldRelation", property: "fieldID") + researchObjectCount: Int! + @relationCountFrom(model: "ResearchFieldRelation", property: "fieldID") } diff --git a/package-lock.json b/package-lock.json index 729261c..7c57135 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,8 @@ "@didtools/pkh-ethereum": "^0.4.1", "did-session": "^2.0.1", "dids": "^4.0.4", - "graphql": "^16.8.0" + "graphql": "^16.8.0", + "prettier": "^3.0.3" }, "devDependencies": { "@ceramicnetwork/cli": "^2.35.0", @@ -25,8 +26,11 @@ "@composedb/devtools-node": "^0.5.0", "@composedb/graphql-scalars": "^0.5.0", "@composedb/types": "^0.5.0", - "eslint": "8.48.0", + "@typescript-eslint/eslint-plugin": "^6.9.1", + "@typescript-eslint/parser": "^6.9.1", + "eslint": "^8.48.0", "key-did-resolver": "^3.0.0", + "typescript": "^5.2.2", "vite-tsconfig-paths": "^4.2.1", "vitest": "^0.34.5" } @@ -4543,6 +4547,12 @@ "dev": true, "peer": true }, + "node_modules/@types/json-schema": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", + "dev": true + }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", @@ -4597,6 +4607,12 @@ "@types/node": "*" } }, + "node_modules/@types/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", + "dev": true + }, "node_modules/@types/send": { "version": "0.17.3", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", @@ -4620,6 +4636,195 @@ "@types/node": "*" } }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.1.tgz", + "integrity": "sha512-w0tiiRc9I4S5XSXXrMHOWgHgxbrBn1Ro+PmiYhSg2ZVdxrAJtQgzU5o2m1BfP6UOn7Vxcc6152vFjQfmZR4xEg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/type-utils": "6.9.1", + "@typescript-eslint/utils": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.1.tgz", + "integrity": "sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", + "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.1.tgz", + "integrity": "sha512-eh2oHaUKCK58qIeYp19F5V5TbpM52680sB4zNSz29VBQPTWIlE/hCj5P5B1AChxECe/fmZlspAWFuRniep1Skg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/utils": "6.9.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", + "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", + "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", + "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", + "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.9.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@vitest/expect": { "version": "0.34.6", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", @@ -12758,6 +12963,20 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -14478,6 +14697,18 @@ "node": "*" } }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", @@ -14638,7 +14869,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "dev": true, - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index a22e0dd..0920eb4 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,11 @@ "@composedb/devtools-node": "^0.5.0", "@composedb/graphql-scalars": "^0.5.0", "@composedb/types": "^0.5.0", - "eslint": "8.48.0", + "@typescript-eslint/eslint-plugin": "^6.9.1", + "@typescript-eslint/parser": "^6.9.1", + "eslint": "^8.48.0", "key-did-resolver": "^3.0.0", + "typescript": "^5.2.2", "vite-tsconfig-paths": "^4.2.1", "vitest": "^0.34.5" }, @@ -31,6 +34,7 @@ "@didtools/pkh-ethereum": "^0.4.1", "did-session": "^2.0.1", "dids": "^4.0.4", - "graphql": "^16.8.0" + "graphql": "^16.8.0", + "prettier": "^3.0.3" } } diff --git a/scripts/commands.mjs b/scripts/commands.mjs index 8eb7be9..2375890 100644 --- a/scripts/commands.mjs +++ b/scripts/commands.mjs @@ -13,12 +13,12 @@ const SEED_PATH = `${PWD}/admin_seed.txt`; export const RunCommands = async () => { const newSeed = () => { const raw = new Uint8Array(randomBytes(32)); - return toString(raw, 'base16') - } + return toString(raw, "base16"); + }; const generateAdminKeyDid = async () => { const seed = readFileSync(SEED_PATH); - const key = fromString(seed, 'base16'); + const key = fromString(seed, "base16"); const did = new DID({ provider: new Ed25519Provider(key), resolver: getResolver(), @@ -40,7 +40,7 @@ export const RunCommands = async () => { logger: { "log-level": 2, "log-to-files": true, - "log-directory": "local-data/ceramic/logs" + "log-directory": "local-data/ceramic/logs", }, metrics: { "metrics-exporter-enabled": false, @@ -65,21 +65,21 @@ export const RunCommands = async () => { writeFileSync(CONFIG_PATH, JSON.stringify(configData, undefined, 2)); }; - if (!existsSync(SEED_PATH)){ - console.log('Creating new admin seed...'); + if (!existsSync(SEED_PATH)) { + console.log("Creating new admin seed..."); writeFileSync(SEED_PATH, newSeed()); - console.log('Generating new config...'); + console.log("Generating new config..."); const did = await generateAdminKeyDid(); - console.log('Saving new DID:', JSON.stringify(did, undefined, 2)) - await generateLocalConfig(did); + console.log("Saving new DID:", JSON.stringify(did, undefined, 2)); + await generateLocalConfig(did); } else if (!existsSync(CONFIG_PATH)) { - console.log('Found seed but no config, generating...'); + console.log("Found seed but no config, generating..."); const did = await generateAdminKeyDid(); await generateLocalConfig(did); } else { - console.log('Seed and config present, skipping generation.') - }; + console.log("Seed and config present, skipping generation."); + } }; RunCommands(); diff --git a/scripts/composites.mjs b/scripts/composites.mjs index 51769c8..4df81c4 100644 --- a/scripts/composites.mjs +++ b/scripts/composites.mjs @@ -24,110 +24,118 @@ export const writeComposite = async (spinner) => { const profileComposite = await createComposite( ceramic, - "./composites/00-profile.graphql" + "./composites/00-profile.graphql", ); const researchFieldComposite = await createComposite( ceramic, - "./composites/001-researchField.graphql" + "./composites/001-researchField.graphql", ); const researchObjComposite = await createComposite( ceramic, - "./composites/01-researchObject.graphql" + "./composites/01-researchObject.graphql", ); const orgComposite = await createComposite( ceramic, - "./composites/02-organization.graphql" + "./composites/02-organization.graphql", ); const claimComposite = await createComposite( ceramic, - "./composites/05-claim.graphql" + "./composites/05-claim.graphql", ); const attestationSchema = readFileSync( "./composites/06-attestation.graphql", - { encoding: "utf-8"} + { encoding: "utf-8" }, ).replace("$CLAIM_ID", claimComposite.modelIDs[0]); const attestationComposite = await Composite.create({ ceramic, - schema: attestationSchema + schema: attestationSchema, }); const componentSchema = readFileSync( "./composites/07-researchComponent.graphql", - { encoding: "utf-8"} + { encoding: "utf-8" }, ).replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]); const componentComposite = await Composite.create({ ceramic, - schema: componentSchema + schema: componentSchema, }); const referenceRelationSchema = readFileSync( "./composites/08-referenceRelation.graphql", - { encoding: "utf-8"} + { encoding: "utf-8" }, ).replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]); const referenceRelationComposite = await Composite.create({ ceramic, - schema: referenceRelationSchema + schema: referenceRelationSchema, }); const contributorRelationSchema = readFileSync( "./composites/09-contributorRelation.graphql", - { encoding: "utf-8"} - ).replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]) - .replace("$PROFILE_ID", profileComposite.modelIDs[0]) + { encoding: "utf-8" }, + ) + .replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]) + .replace("$PROFILE_ID", profileComposite.modelIDs[0]); const contributorRelationComposite = await Composite.create({ ceramic, - schema: contributorRelationSchema + schema: contributorRelationSchema, }); const researchFieldRelationSchema = readFileSync( "./composites/10-researchFieldRelation.graphql", - { encoding: "utf-8"} - ).replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]) - .replace("$RESEARCH_FIELD_ID", researchFieldComposite.modelIDs[0]); + { encoding: "utf-8" }, + ) + .replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]) + .replace("$RESEARCH_FIELD_ID", researchFieldComposite.modelIDs[0]); const researchFieldRelationComposite = await Composite.create({ ceramic, - schema: researchFieldRelationSchema + schema: researchFieldRelationSchema, }); - const annotationSchema = readFileSync( - "./composites/11-annotation.graphql", - { encoding: "utf-8"} - ).replace("$CLAIM_ID", claimComposite.modelIDs[0]) - .replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]); + const annotationSchema = readFileSync("./composites/11-annotation.graphql", { + encoding: "utf-8", + }) + .replace("$CLAIM_ID", claimComposite.modelIDs[0]) + .replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]); const annotationComposite = await Composite.create({ ceramic, - schema: annotationSchema + schema: annotationSchema, }); const additionalRelationsSchema = readFileSync( "./composites/additional-relations.graphql", - { encoding: "utf-8" } + { encoding: "utf-8" }, ) - .replace("$ATTESTATION_ID", attestationComposite.modelIDs[1]) - .replace("$CLAIM_ID", claimComposite.modelIDs[0]) - .replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]) - .replace("$PROFILE_ID", profileComposite.modelIDs[0]) - .replace("$RESEARCH_COMPONENT_ID", componentComposite.modelIDs[1]) - .replace("$CONTRIBUTOR_RELATION_ID", contributorRelationComposite.modelIDs[2]) - .replace("$REFERENCE_RELATION_ID", referenceRelationComposite.modelIDs[1]) - .replace("$RESEARCH_FIELD_ID", researchFieldComposite.modelIDs[0]) - .replace("$RESEARCH_FIELD_RELATION_ID", researchFieldRelationComposite.modelIDs[2]) - .replace("$ANNOTATION_ID", annotationComposite.modelIDs[2]); + .replace("$ATTESTATION_ID", attestationComposite.modelIDs[1]) + .replace("$CLAIM_ID", claimComposite.modelIDs[0]) + .replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]) + .replace("$PROFILE_ID", profileComposite.modelIDs[0]) + .replace("$RESEARCH_COMPONENT_ID", componentComposite.modelIDs[1]) + .replace( + "$CONTRIBUTOR_RELATION_ID", + contributorRelationComposite.modelIDs[2], + ) + .replace("$REFERENCE_RELATION_ID", referenceRelationComposite.modelIDs[1]) + .replace("$RESEARCH_FIELD_ID", researchFieldComposite.modelIDs[0]) + .replace( + "$RESEARCH_FIELD_RELATION_ID", + researchFieldRelationComposite.modelIDs[2], + ) + .replace("$ANNOTATION_ID", annotationComposite.modelIDs[2]); const additionalRelationsComposite = await Composite.create({ ceramic, - schema: additionalRelationsSchema + schema: additionalRelationsSchema, }); const composite = Composite.from([ @@ -142,20 +150,20 @@ export const writeComposite = async (spinner) => { referenceRelationComposite, researchFieldComposite, researchFieldRelationComposite, - annotationComposite - ]); + annotationComposite, + ]); await writeEncodedComposite(composite, "./src/__generated__/definition.json"); spinner.info("creating composite for runtime usage"); await writeEncodedCompositeRuntime( ceramic, "./src/__generated__/definition.json", - "./src/__generated__/definition.js" + "./src/__generated__/definition.js", ); spinner.info("deploying composite"); const deployComposite = await readEncodedComposite( ceramic, - "./src/__generated__/definition.json" + "./src/__generated__/definition.json", ); await deployComposite.startIndexingOn(ceramic); @@ -178,10 +186,10 @@ const authenticateAdmin = async () => { }; const runAsScript = - process.argv[0].includes('/bin/node') && - process.argv[1].includes('scripts/composites.mjs'); + process.argv[0].includes("/bin/node") && + process.argv[1].includes("scripts/composites.mjs"); if (runAsScript) { const logSpinner = { info: console.log, succeed: console.log }; await writeComposite(logSpinner); -}; \ No newline at end of file +} diff --git a/scripts/run.mjs b/scripts/run.mjs index ba451ef..ca33536 100644 --- a/scripts/run.mjs +++ b/scripts/run.mjs @@ -1,24 +1,24 @@ -import ora from 'ora' +import ora from "ora"; -import { spawn } from "child_process" -import { EventEmitter } from 'events' -import { writeComposite } from './composites.mjs'; +import { spawn } from "child_process"; +import { EventEmitter } from "events"; +import { writeComposite } from "./composites.mjs"; -const events = new EventEmitter() +const events = new EventEmitter(); const spinner = ora(); const ceramic = spawn("npm", ["run", "ceramic"]); ceramic.stdout.on("data", async (buffer) => { - console.log('[Ceramic]', buffer.toString()) + console.log("[Ceramic]", buffer.toString()); if (buffer.toString().includes("0.0.0.0:7007")) { events.emit("ceramic", true); spinner.succeed("ceramic node started"); } -}) +}); -ceramic.stderr.on('data', (err) => { - console.log(err.toString()) -}) +ceramic.stderr.on("data", (err) => { + console.log(err.toString()); +}); const bootstrap = async () => { // TODO: convert to event driven to ensure functions run in correct orders after releasing the bytestream. @@ -26,44 +26,44 @@ const bootstrap = async () => { // & do not create the model if it already exists & has not been updated try { spinner.info("[Composites] bootstrapping composites"); - await writeComposite(spinner) + await writeComposite(spinner); spinner.succeed("Composites] composites bootstrapped"); } catch (err) { - spinner.fail(err.message) - ceramic.kill() - throw err + spinner.fail(err.message); + ceramic.kill(); + throw err; } -} +}; const graphiql = async () => { spinner.info("[GraphiQL] starting graphiql"); - const graphiql = spawn('node', ['./scripts/graphiql.mjs']) + const graphiql = spawn("node", ["./scripts/graphiql.mjs"]); spinner.succeed("[GraphiQL] graphiql started"); - graphiql.stdout.on('data', (buffer) => { - console.log('[GraphiqQL]',buffer.toString()) - }) -} + graphiql.stdout.on("data", (buffer) => { + console.log("[GraphiqQL]", buffer.toString()); + }); +}; const start = async () => { try { - spinner.start('[Ceramic] Starting Ceramic node\n') - events.on('ceramic', async (isRunning) => { + spinner.start("[Ceramic] Starting Ceramic node\n"); + events.on("ceramic", async (isRunning) => { if (isRunning) { - await bootstrap() - await graphiql() + await bootstrap(); + await graphiql(); } - if(isRunning === false) { - ceramic.kill() - process.exit() + if (isRunning === false) { + ceramic.kill(); + process.exit(); } - }) + }); } catch (err) { - ceramic.kill() - spinner.fail(err) + ceramic.kill(); + spinner.fail(err); } -} +}; -start() +start(); process.on("SIGTERM", () => { ceramic.kill(); diff --git a/stream-to-cid.mjs b/stream-to-cid.mjs index 023f4de..051fb29 100644 --- a/stream-to-cid.mjs +++ b/stream-to-cid.mjs @@ -1,6 +1,6 @@ -import { CommitID, StreamID } from "@ceramicnetwork/streamid" +import { CommitID, StreamID } from "@ceramicnetwork/streamid"; -console.log('Recieved args:', process.argv) -const commitID = CommitID.fromString(process.argv[2]) +console.log("Recieved args:", process.argv); +const commitID = CommitID.fromString(process.argv[2]); -console.log('stream CID:', commitID.cid) +console.log("stream CID:", commitID.cid); diff --git a/template_data.json b/template_data.json index bbac70a..d625a87 100644 --- a/template_data.json +++ b/template_data.json @@ -14,10 +14,7 @@ "description": "This research object has a dataset attached" } ], - "researchFields": [ - { "title": "Cosmology" }, - { "title": "Psychology"} - ], + "researchFields": [{ "title": "Cosmology" }, { "title": "Psychology" }], "contributorRelations": [], "referenceRelations": [], "researchFieldRelations": [], diff --git a/test/root.spec.ts b/test/root.spec.ts index 01acb44..1e15999 100644 --- a/test/root.spec.ts +++ b/test/root.spec.ts @@ -1,7 +1,7 @@ -import { ComposeClient } from '@composedb/client' -import { definition } from '../src/__generated__/definition' -import { RuntimeCompositeDefinition } from '@composedb/types' -import { test, describe, beforeAll, expect } from 'vitest' +import { ComposeClient } from "@composedb/client"; +import { definition } from "../src/__generated__/definition"; +import { RuntimeCompositeDefinition } from "@composedb/types"; +import { test, describe, beforeAll, expect } from "vitest"; import { mutationCreateAnnotation, mutationCreateAttestation, @@ -27,72 +27,82 @@ import { queryResearchComponent, queryResearchFieldRelation, queryResearchFields, - queryResearchObject -} from '../utils/queries' -import { randomDID } from './util' -import { CeramicClient } from '@ceramicnetwork/http-client' -import { writeComposite } from 'scripts/composites.mjs' + queryResearchObject, +} from "../utils/queries"; +import { randomDID } from "./util"; +import { CeramicClient } from "@ceramicnetwork/http-client"; +import { writeComposite } from "scripts/composites.mjs"; import { setTimeout } from "timers/promises"; -import { Annotation, Attestation, Claim, ContributorRelation, Profile, ReferenceRelation, ResearchObject } from '@/types' -import { CommitID } from '@ceramicnetwork/streamid' - -const CERAMIC_API = 'http:/localhost:7007' -const A_CID = 'bafybeibeaampol2yz5xuoxex7dxri6ztqveqrybzfh5obz6jrul5gb4cf4' - -const ceramic = new CeramicClient(CERAMIC_API) - -describe('ComposeDB nodes', () => { +import { + Annotation, + Attestation, + Claim, + ContributorRelation, + Profile, + ReferenceRelation, + ResearchObject, +} from "@/types"; +import { CommitID } from "@ceramicnetwork/streamid"; + +const CERAMIC_API = "http:/localhost:7007"; +const A_CID = "bafybeibeaampol2yz5xuoxex7dxri6ztqveqrybzfh5obz6jrul5gb4cf4"; + +const ceramic = new CeramicClient(CERAMIC_API); + +describe("ComposeDB nodes", () => { beforeAll(async () => { try { - await fetch(`${CERAMIC_API}/api/v0`) + await fetch(`${CERAMIC_API}/api/v0`); } catch (e) { - console.error('Failed connection to Ceramic. Run with "make test" or against live devserver!') - process.exit(1) - }; + console.error( + 'Failed connection to Ceramic. Run with "make test" or against live devserver!', + ); + process.exit(1); + } // Takes a spinner param which just screws with our test output - await writeComposite({ info: () => { }, succeed: () => { } }); + await writeComposite({ info: () => {}, succeed: () => {} }); }); - describe('User can create', async () => { + describe("User can create", async () => { const composeClient = freshClient(); const user = await randomDID(); composeClient.setDID(user); // Create mutations error on failure and are otherwise successful - test('research object', async () => { + test("research object", async () => { const data: ResearchObject = { - title: 'Test', + title: "Test", manifest: A_CID, - metadata: A_CID - } + metadata: A_CID, + }; const researchObject = await mutationCreateResearchObject( - composeClient, data + composeClient, + data, ); const result = await queryResearchObject( - composeClient, researchObject.streamID, + composeClient, + researchObject.streamID, ); expect(result).toEqual(data); }); - test('profile', async () => { + test("profile", async () => { const data: Profile = { - displayName: 'First Lastname', - orcid: 'orcidHandle' + displayName: "First Lastname", + orcid: "orcidHandle", }; const profile = await mutationCreateProfile(composeClient, data); - const result = await queryProfile( - composeClient, profile.streamID, - ); + const result = await queryProfile(composeClient, profile.streamID); expect(result).toEqual(data); }); - test('claim', async () => { + test("claim", async () => { const data: Claim = { - title: 'My Claim', - description: 'The point of the claim', - badge: A_CID + title: "My Claim", + description: "The point of the claim", + badge: A_CID, }; const claim = await mutationCreateClaim(composeClient, data); @@ -100,71 +110,71 @@ describe('ComposeDB nodes', () => { expect(result).toEqual(data); }); - test('attestation to own research object', async () => { + test("attestation to own research object", async () => { const myResearchObject = await mutationCreateResearchObject( composeClient, { - title: 'Test', - manifest: A_CID - } - ); - const myClaim = await mutationCreateClaim( - composeClient, - { - title: 'My Claim', - description: 'The point of the claim', - badge: A_CID - } + title: "Test", + manifest: A_CID, + }, ); + const myClaim = await mutationCreateClaim(composeClient, { + title: "My Claim", + description: "The point of the claim", + badge: A_CID, + }); const data: Attestation = { targetID: myResearchObject.streamID, targetVersion: myResearchObject.commitID, claimID: myClaim.streamID, claimVersion: myClaim.commitID, - revoked: false + revoked: false, }; const attestation = await mutationCreateAttestation(composeClient, data); - const result = await queryAttestation(composeClient, attestation.streamID); + const result = await queryAttestation( + composeClient, + attestation.streamID, + ); expect(result).toEqual(data); }); }); - describe('User can update', async () => { + describe("User can update", async () => { const composeClient = freshClient(); const user = await randomDID(); composeClient.setDID(user); - test('research object', async () => { + test("research object", async () => { const data: ResearchObject = { - title: 'Test', - manifest: A_CID + title: "Test", + manifest: A_CID, }; - const researchObject = await mutationCreateResearchObject(composeClient, data); + const researchObject = await mutationCreateResearchObject( + composeClient, + data, + ); await waitAndSync(researchObject.streamID); - await mutationUpdateResearchObject( + await mutationUpdateResearchObject(composeClient, { + id: researchObject.streamID, + metadata: A_CID, // Add some new metadata + }); + const result = await queryResearchObject( composeClient, - { - id: researchObject.streamID, - metadata: A_CID // Add some new metadata - } + researchObject.streamID, ); - const result = await queryResearchObject(composeClient, researchObject.streamID); expect(result).toEqual({ ...data, metadata: A_CID }); }); - test('profile', async () => { - const profile = await mutationCreateProfile( - composeClient, - { - displayName: "My Name", - orcid: "@handle" - } - ); + test("profile", async () => { + const profile = await mutationCreateProfile(composeClient, { + displayName: "My Name", + orcid: "@handle", + }); const newProfile: Profile = { displayName: "New Name", - orcid: "@handle" + orcid: "@handle", }; await waitAndSync(profile.streamID); // Apparently create acts as an upsert on SINGLE accountRelation models @@ -175,162 +185,147 @@ describe('ComposeDB nodes', () => { }); }); - describe('Attestations', async () => { - const composeClient = freshClient() - composeClient.setDID(await randomDID()) - const testClaim = await mutationCreateClaim( - composeClient, - { - title: 'Test', - description: 'A nice explanation' - } - ); + describe("Attestations", async () => { + const composeClient = freshClient(); + composeClient.setDID(await randomDID()); + const testClaim = await mutationCreateClaim(composeClient, { + title: "Test", + description: "A nice explanation", + }); - test('can be made to own profile', async () => { + test("can be made to own profile", async () => { const user = await randomDID(); composeClient.setDID(user); - const ownProfile = await mutationCreateProfile( - composeClient, - { - displayName: 'First Lastname', - orcid: 'orcidHandle' - } - ); + const ownProfile = await mutationCreateProfile(composeClient, { + displayName: "First Lastname", + orcid: "orcidHandle", + }); - const attestation = await mutationCreateAttestation( + const attestation = await mutationCreateAttestation(composeClient, { + targetID: ownProfile.streamID, + targetVersion: ownProfile.commitID, + claimID: testClaim.streamID, + claimVersion: testClaim.commitID, + revoked: false, + }); + const result = await queryAttestation( composeClient, - { - targetID: ownProfile.streamID, - targetVersion: ownProfile.commitID, - claimID: testClaim.streamID, - claimVersion: testClaim.commitID, - revoked: false - } - ); - const result = await queryAttestation(composeClient, attestation.streamID); + attestation.streamID, + ); expect(result?.targetID).toEqual(ownProfile.streamID); expect(result?.targetVersion).toEqual(ownProfile.commitID); - }) + }); - test('can be made to other users research object', async () => { + test("can be made to other users research object", async () => { const user1 = await randomDID(); composeClient.setDID(user1); const user1ResearchObject = await mutationCreateResearchObject( composeClient, { - title: 'Paper', - manifest: A_CID - } + title: "Paper", + manifest: A_CID, + }, ); const user2 = await randomDID(); composeClient.setDID(user2); - const attestation = await mutationCreateAttestation( + const attestation = await mutationCreateAttestation(composeClient, { + targetID: user1ResearchObject.streamID, + targetVersion: user1ResearchObject.commitID, + claimID: testClaim.streamID, + claimVersion: testClaim.commitID, + revoked: false, + }); + const result = await queryAttestation( composeClient, - { - targetID: user1ResearchObject.streamID, - targetVersion: user1ResearchObject.commitID, - claimID: testClaim.streamID, - claimVersion: testClaim.commitID, - revoked: false - } - ); - const result = await queryAttestation(composeClient, attestation.streamID); + attestation.streamID, + ); expect(result?.targetID).toEqual(user1ResearchObject.streamID); expect(result?.targetVersion).toEqual(user1ResearchObject.commitID); - }) + }); - test('can be updated with revokation', async () => { + test("can be updated with revokation", async () => { const user = await randomDID(); composeClient.setDID(user); - const researchObject = await mutationCreateResearchObject( - composeClient, - { - title: 'Paper', - manifest: A_CID - } - ); + const researchObject = await mutationCreateResearchObject(composeClient, { + title: "Paper", + manifest: A_CID, + }); - const attestation = await mutationCreateAttestation( - composeClient, - { - targetID: researchObject.streamID, - targetVersion: researchObject.commitID, - claimID: testClaim.streamID, - claimVersion: testClaim.commitID, - revoked: false - } - ); + const attestation = await mutationCreateAttestation(composeClient, { + targetID: researchObject.streamID, + targetVersion: researchObject.commitID, + claimID: testClaim.streamID, + claimVersion: testClaim.commitID, + revoked: false, + }); await waitAndSync(attestation.streamID); - await mutationUpdateAttestation( + await mutationUpdateAttestation(composeClient, { + id: attestation.streamID, + revoked: true, + }); + + const result = await queryAttestation( composeClient, - { - id: attestation.streamID, - revoked: true - } + attestation.streamID, ); + expect(result?.revoked).toEqual(true); + }); + }); - const result = await queryAttestation(composeClient, attestation.streamID); - expect(result?.revoked).toEqual(true) - }) - }) - - describe('Annotations', async () => { + describe("Annotations", async () => { const composeClient = freshClient(); const user = await randomDID(); composeClient.setDID(user); - const researchObject = await mutationCreateResearchObject( - composeClient, - { - title: 'Title', - manifest: A_CID - } - ); + const researchObject = await mutationCreateResearchObject(composeClient, { + title: "Title", + manifest: A_CID, + }); - const claim = await mutationCreateClaim( - composeClient, - { - title: 'Title', - description: 'Description' - } - ); + const claim = await mutationCreateClaim(composeClient, { + title: "Title", + description: "Description", + }); const researchComponent = await mutationCreateResearchComponent( composeClient, { - name: 'Name', - mimeType: 'text/csv', + name: "Name", + mimeType: "text/csv", dagNode: A_CID, pathToNode: "", researchObjectID: researchObject.streamID, - researchObjectVersion: researchObject.commitID - } + researchObjectVersion: researchObject.commitID, + }, ); - describe('can be created on', async () => { - test('research object', async () => { + describe("can be created on", async () => { + test("research object", async () => { const data: Annotation = { - comment: 'This is a cool object!', + comment: "This is a cool object!", researchObjectID: researchObject.streamID, researchObjectVersion: researchObject.commitID, claimID: claim.streamID, - claimVersion: claim.commitID + claimVersion: claim.commitID, }; const annotation = await mutationCreateAnnotation(composeClient, data); - const response = await queryAnnotation(composeClient, annotation.streamID); + const response = await queryAnnotation( + composeClient, + annotation.streamID, + ); expect(response).toMatchObject(data); }); - test('research component', async () => { + test("research component", async () => { const data: Annotation = { - comment: 'What a component!', + comment: "What a component!", researchObjectID: researchObject.streamID, researchObjectVersion: researchObject.commitID, @@ -339,18 +334,21 @@ describe('ComposeDB nodes', () => { targetVersion: researchComponent.commitID, claimID: claim.streamID, - claimVersion: claim.commitID + claimVersion: claim.commitID, }; const annotation = await mutationCreateAnnotation(composeClient, data); - const response = await queryAnnotation(composeClient, annotation.streamID); + const response = await queryAnnotation( + composeClient, + annotation.streamID, + ); expect(response).toMatchObject(data); }); - test('raw dagNode', async () => { + test("raw dagNode", async () => { const data: Annotation = { - comment: 'What a file!', + comment: "What a file!", researchObjectID: researchObject.streamID, researchObjectVersion: researchObject.commitID, @@ -364,15 +362,18 @@ describe('ComposeDB nodes', () => { const annotation = await mutationCreateAnnotation(composeClient, data); - const response = await queryAnnotation(composeClient, annotation.streamID); + const response = await queryAnnotation( + composeClient, + annotation.streamID, + ); expect(response).toMatchObject(data); }); }); - describe('can suggest metadata on', async () => { - test('research object', async () => { + describe("can suggest metadata on", async () => { + test("research object", async () => { const data: Annotation = { - comment: 'Adding some metadata to research object', + comment: "Adding some metadata to research object", researchObjectID: researchObject.streamID, researchObjectVersion: researchObject.commitID, @@ -380,18 +381,21 @@ describe('ComposeDB nodes', () => { claimID: claim.streamID, claimVersion: claim.commitID, - metadataPayload: A_CID + metadataPayload: A_CID, }; const annotation = await mutationCreateAnnotation(composeClient, data); - const response = await queryAnnotation(composeClient, annotation.streamID); + const response = await queryAnnotation( + composeClient, + annotation.streamID, + ); expect(response?.metadataPayload).toEqual(A_CID); }); - test('component', async () => { + test("component", async () => { const data: Annotation = { - comment: 'Adding some metadata to component', + comment: "Adding some metadata to component", researchObjectID: researchObject.streamID, researchObjectVersion: researchObject.commitID, @@ -402,18 +406,21 @@ describe('ComposeDB nodes', () => { claimID: claim.streamID, claimVersion: claim.commitID, - metadataPayload: A_CID + metadataPayload: A_CID, }; const annotation = await mutationCreateAnnotation(composeClient, data); - const response = await queryAnnotation(composeClient, annotation.streamID); + const response = await queryAnnotation( + composeClient, + annotation.streamID, + ); expect(response?.metadataPayload).toEqual(A_CID); }); - test('raw dagNode', async () => { + test("raw dagNode", async () => { const data: Annotation = { - comment: 'Adding some metadata to DAG', + comment: "Adding some metadata to DAG", researchObjectID: researchObject.streamID, researchObjectVersion: researchObject.commitID, @@ -424,22 +431,25 @@ describe('ComposeDB nodes', () => { claimID: claim.streamID, claimVersion: claim.commitID, - metadataPayload: A_CID + metadataPayload: A_CID, }; const annotation = await mutationCreateAnnotation(composeClient, data); - const response = await queryAnnotation(composeClient, annotation.streamID); + const response = await queryAnnotation( + composeClient, + annotation.streamID, + ); expect(response?.metadataPayload).toEqual(A_CID); }); }); - test.skip('can be made without claim', async () => { + test.skip("can be made without claim", async () => { // API error on @relationDocument when claimID omitted even if optional, // under review by ceramic devs. // When fixed, remove unnecessary claims and make this a separate case const data: Annotation = { - comment: 'This is a cool object!', + comment: "This is a cool object!", researchObjectID: researchObject.streamID, researchObjectVersion: researchObject.commitID, @@ -447,20 +457,23 @@ describe('ComposeDB nodes', () => { const annotation = await mutationCreateAnnotation(composeClient, data); - const response = await queryAnnotation(composeClient, annotation.streamID); + const response = await queryAnnotation( + composeClient, + annotation.streamID, + ); expect(response).toEqual(data); }); - describe('can be found from', async () => { - test('research object', async () => { + describe("can be found from", async () => { + test("research object", async () => { const data: Annotation = { - comment: 'This is a cool object!', + comment: "This is a cool object!", researchObjectID: researchObject.streamID, researchObjectVersion: researchObject.commitID, claimID: claim.streamID, - claimVersion: claim.commitID + claimVersion: claim.commitID, }; const annotation = await mutationCreateAnnotation(composeClient, data); @@ -477,21 +490,21 @@ describe('ComposeDB nodes', () => { } } } - ` + `, ); const expected = { node: { researchObjectID: researchObject.streamID, researchObjectVersion: researchObject.commitID, - id: annotation.streamID - } + id: annotation.streamID, + }, }; expect((response as any).annotations.edges).toContainEqual(expected); }); - test('research component', async () => { + test("research component", async () => { const data: Annotation = { - comment: 'This is a cool component!', + comment: "This is a cool component!", researchObjectID: researchObject.streamID, researchObjectVersion: researchObject.commitID, @@ -500,7 +513,7 @@ describe('ComposeDB nodes', () => { targetVersion: researchComponent.commitID, claimID: claim.streamID, - claimVersion: claim.commitID + claimVersion: claim.commitID, }; const annotation = await mutationCreateAnnotation(composeClient, data); @@ -518,22 +531,22 @@ describe('ComposeDB nodes', () => { } } } - ` + `, ); const expected = { node: { targetID: researchComponent.streamID, targetVersion: researchComponent.commitID, - id: annotation.streamID - } + id: annotation.streamID, + }, }; expect((response as any).annotations.edges).toContainEqual(expected); }); }); - test('can reply to another annotation', async () => { + test("can reply to another annotation", async () => { const questionData: Annotation = { - comment: 'What do you tink about this?', + comment: "What do you tink about this?", researchObjectID: researchObject.streamID, researchObjectVersion: researchObject.commitID, @@ -542,13 +555,16 @@ describe('ComposeDB nodes', () => { targetVersion: researchComponent.commitID, claimID: claim.streamID, - claimVersion: claim.commitID + claimVersion: claim.commitID, }; - const question = await mutationCreateAnnotation(composeClient, questionData); + const question = await mutationCreateAnnotation( + composeClient, + questionData, + ); const replyData: Annotation = { - comment: 'Looks good!', + comment: "Looks good!", researchObjectID: researchObject.streamID, researchObjectVersion: researchObject.commitID, @@ -557,7 +573,7 @@ describe('ComposeDB nodes', () => { targetVersion: question.commitID, claimID: claim.streamID, - claimVersion: claim.commitID + claimVersion: claim.commitID, }; const reply = await mutationCreateAnnotation(composeClient, replyData); @@ -573,63 +589,77 @@ describe('ComposeDB nodes', () => { } } } - ` + `, ); // Verify that we can get the replies from the question const expectedReply = { node: { id: reply.streamID } }; - expect((replyFromQuestion as any).replies.edges).toContainEqual(expectedReply); + expect((replyFromQuestion as any).replies.edges).toContainEqual( + expectedReply, + ); }); }); - describe('Contributor relations', async () => { + describe("Contributor relations", async () => { const composeClient = freshClient(); const user1 = await randomDID(); composeClient.setDID(user1); const user1Profile = await mutationCreateProfile(composeClient, { - displayName: 'Name', - orcid: '000-111' + displayName: "Name", + orcid: "000-111", }); const user2 = await randomDID(); composeClient.setDID(user2); - const researchObject = await mutationCreateResearchObject( - composeClient, - { - title: 'Title', - manifest: A_CID - } - ); + const researchObject = await mutationCreateResearchObject(composeClient, { + title: "Title", + manifest: A_CID, + }); const contributionData: ContributorRelation = { - role: 'Author', + role: "Author", contributorID: user1Profile.streamID, researchObjectID: researchObject.streamID, researchObjectVersion: researchObject.commitID, - revoked: false + revoked: false, }; - test('created', async () => { - const contribution = await mutationCreateContributorRelation(composeClient, contributionData); - const response = await queryContributorRelation(composeClient, contribution.streamID); + test("created", async () => { + const contribution = await mutationCreateContributorRelation( + composeClient, + contributionData, + ); + const response = await queryContributorRelation( + composeClient, + contribution.streamID, + ); expect(response).toEqual(contributionData); }); - test('updated with revokation', async () => { - const contribution = await mutationCreateContributorRelation(composeClient, contributionData); - await mutationUpdateContributorRelation( + test("updated with revokation", async () => { + const contribution = await mutationCreateContributorRelation( composeClient, - { id: contribution.streamID, revoked: true }, - ) + contributionData, + ); + await mutationUpdateContributorRelation(composeClient, { + id: contribution.streamID, + revoked: true, + }); - const response = await queryContributorRelation(composeClient, contribution.streamID); + const response = await queryContributorRelation( + composeClient, + contribution.streamID, + ); expect(response).toEqual({ ...contributionData, revoked: true }); }); - test('found from research objects', async () => { - const contribution = await mutationCreateContributorRelation(composeClient, contributionData); + test("found from research objects", async () => { + const contribution = await mutationCreateContributorRelation( + composeClient, + contributionData, + ); const response = await queryResearchObject( composeClient, researchObject.streamID, @@ -641,14 +671,19 @@ describe('ComposeDB nodes', () => { } } } - ` + `, ); const expectedContribution = { node: { id: contribution.streamID } }; - expect((response as any).contributors.edges).toContainEqual(expectedContribution); + expect((response as any).contributors.edges).toContainEqual( + expectedContribution, + ); }); - test('found from profiles', async () => { - const contribution = await mutationCreateContributorRelation(composeClient, contributionData); + test("found from profiles", async () => { + const contribution = await mutationCreateContributorRelation( + composeClient, + contributionData, + ); const response = await queryProfile( composeClient, user1Profile.streamID, @@ -660,14 +695,16 @@ describe('ComposeDB nodes', () => { } } } - ` + `, ); const expectedContribution = { node: { id: contribution.streamID } }; - expect((response as any).contributions.edges).toContainEqual(expectedContribution); + expect((response as any).contributions.edges).toContainEqual( + expectedContribution, + ); }); }); - describe('Reference relations can be', async () => { + describe("Reference relations can be", async () => { const composeClient = freshClient(); const user1 = await randomDID(); composeClient.setDID(user1); @@ -675,17 +712,17 @@ describe('ComposeDB nodes', () => { const researchObjectSource = await mutationCreateResearchObject( composeClient, { - title: 'Title', - manifest: A_CID - } + title: "Title", + manifest: A_CID, + }, ); const researchObjectTarget = await mutationCreateResearchObject( composeClient, { - title: 'Title', - manifest: A_CID - } + title: "Title", + manifest: A_CID, + }, ); const referenceData: ReferenceRelation = { @@ -693,24 +730,42 @@ describe('ComposeDB nodes', () => { fromVersion: researchObjectSource.commitID, toID: researchObjectTarget.streamID, toVersion: researchObjectTarget.commitID, - revoked: false + revoked: false, }; - test('created', async () => { - const reference = await mutationCreateReferenceRelation(composeClient, referenceData); - const response = await queryReferenceRelation(composeClient, reference.streamID); + test("created", async () => { + const reference = await mutationCreateReferenceRelation( + composeClient, + referenceData, + ); + const response = await queryReferenceRelation( + composeClient, + reference.streamID, + ); expect(response).toEqual(referenceData); }); - test('updated with revokation', async () => { - const reference = await mutationCreateReferenceRelation(composeClient, referenceData); - await mutationUpdateReferenceRelation(composeClient, { id: reference.streamID, revoked: true }); - const response = await queryReferenceRelation(composeClient, reference.streamID); + test("updated with revokation", async () => { + const reference = await mutationCreateReferenceRelation( + composeClient, + referenceData, + ); + await mutationUpdateReferenceRelation(composeClient, { + id: reference.streamID, + revoked: true, + }); + const response = await queryReferenceRelation( + composeClient, + reference.streamID, + ); expect(response).toEqual({ ...referenceData, revoked: true }); }); - test('found from source research objects', async () => { - const reference = await mutationCreateReferenceRelation(composeClient, referenceData); + test("found from source research objects", async () => { + const reference = await mutationCreateReferenceRelation( + composeClient, + referenceData, + ); const response = await queryResearchObject( composeClient, researchObjectSource.streamID, @@ -722,14 +777,19 @@ describe('ComposeDB nodes', () => { } } } - ` + `, ); const expectedReference = { node: { id: reference.streamID } }; - expect((response as any).outgoingReferences.edges).toContainEqual(expectedReference); + expect((response as any).outgoingReferences.edges).toContainEqual( + expectedReference, + ); }); - test('found from target research objects', async () => { - const reference = await mutationCreateReferenceRelation(composeClient, referenceData); + test("found from target research objects", async () => { + const reference = await mutationCreateReferenceRelation( + composeClient, + referenceData, + ); const response = await queryResearchObject( composeClient, researchObjectTarget.streamID, @@ -741,57 +801,69 @@ describe('ComposeDB nodes', () => { } } } - ` + `, ); const expectedReference = { node: { id: reference.streamID } }; - expect((response as any).incomingReferences.edges).toContainEqual(expectedReference); + expect((response as any).incomingReferences.edges).toContainEqual( + expectedReference, + ); }); }); - describe('Research field', async () => { + describe("Research field", async () => { const composeClient = freshClient(); const user1 = await randomDID(); composeClient.setDID(user1); - const researchObject = await mutationCreateResearchObject( - composeClient, - { - title: 'Title', - manifest: A_CID - } - ); + const researchObject = await mutationCreateResearchObject(composeClient, { + title: "Title", + manifest: A_CID, + }); - test('can be created', async () => { - const field = await mutationCreateResearchField(composeClient, { title: "DeSci" }); - const response = await queryResearchFields(composeClient, field.streamID, 'id title'); - expect(response).toMatchObject({ title: 'DeSci', id: field.streamID }) + test("can be created", async () => { + const field = await mutationCreateResearchField(composeClient, { + title: "DeSci", + }); + const response = await queryResearchFields( + composeClient, + field.streamID, + "id title", + ); + expect(response).toMatchObject({ title: "DeSci", id: field.streamID }); }); - describe('relations', async () => { - test('can be created', async () => { - const field = await mutationCreateResearchField(composeClient, { title: "DeSci" }); + describe("relations", async () => { + test("can be created", async () => { + const field = await mutationCreateResearchField(composeClient, { + title: "DeSci", + }); const relationData = { fieldID: field.streamID, researchObjectID: researchObject.streamID, - researchObjectVersion: researchObject.commitID + researchObjectVersion: researchObject.commitID, }; const relation = await mutationCreateResearchFieldRelation( composeClient, - relationData + relationData, + ); + const response = await queryResearchFieldRelation( + composeClient, + relation.streamID, ); - const response = await queryResearchFieldRelation(composeClient, relation.streamID); expect(response).toMatchObject(relationData); }); - test('can be found from research object', async () => { - const field = await mutationCreateResearchField(composeClient, { title: "DeSci" }); + test("can be found from research object", async () => { + const field = await mutationCreateResearchField(composeClient, { + title: "DeSci", + }); const relation = await mutationCreateResearchFieldRelation( composeClient, { fieldID: field.streamID, researchObjectID: researchObject.streamID, - researchObjectVersion: researchObject.commitID - } + researchObjectVersion: researchObject.commitID, + }, ); const response = await queryResearchObject( composeClient, @@ -804,126 +876,123 @@ describe('ComposeDB nodes', () => { } } } - ` + `, + ); + const expectedRelation = { node: { id: relation.streamID } }; + expect((response as any).researchFields.edges).toContainEqual( + expectedRelation, ); - const expectedRelation = { node: { id: relation.streamID }}; - expect((response as any).researchFields.edges).toContainEqual(expectedRelation); }); }); }); - describe.todo('Queries can find', async () => { + describe.todo("Queries can find", async () => { // Additional queries required to work }); - describe('System', async () => { + describe("System", async () => { const composeClient = freshClient(); const user = await randomDID(); composeClient.setDID(user); - test('can get commits anchored before a certain time', async () => { + test("can get commits anchored before a certain time", async () => { // This assumes anchors have been made, which is very fast running locally // but are made in longer time periods with on-chain anchoring - const { streamID } = await mutationCreateResearchObject( - composeClient, - { - title: 'Old', - manifest: A_CID - } - ); + const { streamID } = await mutationCreateResearchObject(composeClient, { + title: "Old", + manifest: A_CID, + }); const timeBetween = Math.floor(Date.now() / 1000); // Encourage an anchor in between commits await waitAndSync(streamID, 200); - await mutationUpdateResearchObject( - composeClient, - { - id: streamID, - title: 'New' - } - ); + await mutationUpdateResearchObject(composeClient, { + id: streamID, + title: "New", + }); const stream = await ceramic.loadStream(streamID); - expect(stream.state.content.title).toEqual('New'); + expect(stream.state.content.title).toEqual("New"); - const streamBetween = await ceramic.loadStream(streamID, { atTime: timeBetween }); - expect(streamBetween.state.content.title).toEqual('Old'); + const streamBetween = await ceramic.loadStream(streamID, { + atTime: timeBetween, + }); + expect(streamBetween.state.content.title).toEqual("Old"); }); - test('can resolve stream refs in old versions', async () => { + test("can resolve stream refs in old versions", async () => { const researchObjectV0 = await mutationCreateResearchObject( composeClient, { - title: 'Title', - manifest: A_CID - } + title: "Title", + manifest: A_CID, + }, ); - const componentV0 = await mutationCreateResearchComponent( - composeClient, - { - name: 'Filename', - mimeType: 'text/plain', - dagNode: A_CID, - pathToNode: "files/data.csv", - researchObjectID: researchObjectV0.streamID, - researchObjectVersion: researchObjectV0.commitID - } - ); - const newManifest = 'bafybeibeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; + const componentV0 = await mutationCreateResearchComponent(composeClient, { + name: "Filename", + mimeType: "text/plain", + dagNode: A_CID, + pathToNode: "files/data.csv", + researchObjectID: researchObjectV0.streamID, + researchObjectVersion: researchObjectV0.commitID, + }); + const newManifest = + "bafybeibeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; const researchObjectV1 = await mutationUpdateResearchObject( composeClient, { id: researchObjectV0.streamID, - manifest: newManifest - } + manifest: newManifest, + }, ); await waitAndSync(componentV0.streamID); - await mutationUpdateResearchComponent( - composeClient, - { - id: componentV0.streamID, - dagNode: newManifest, - // Set a new version indicator - researchObjectVersion: researchObjectV1.commitID - } - ); + await mutationUpdateResearchComponent(composeClient, { + id: componentV0.streamID, + dagNode: newManifest, + // Set a new version indicator + researchObjectVersion: researchObjectV1.commitID, + }); // Verify that queries return the fresh data - const roResult = await queryResearchObject(composeClient, researchObjectV0.streamID); - const rcResult = await queryResearchComponent(composeClient, componentV0.streamID); + const roResult = await queryResearchObject( + composeClient, + researchObjectV0.streamID, + ); + const rcResult = await queryResearchComponent( + composeClient, + componentV0.streamID, + ); expect(roResult?.manifest).toEqual(newManifest); expect(rcResult?.researchObjectID).toEqual(researchObjectV0.streamID); // Verify that we can still get the data of a specific version const oldComponentState = await ceramic.loadStream(componentV0.commitID); - expect(oldComponentState.content.researchObjectVersion) - .toEqual(researchObjectV0.commitID); + expect(oldComponentState.content.researchObjectVersion).toEqual( + researchObjectV0.commitID, + ); }); - test('can resolve a specific version index', async () => { + test("can resolve a specific version index", async () => { const data: ResearchObject = { - title: 'Title 0', - manifest: A_CID + title: "Title 0", + manifest: A_CID, }; - const { streamID } = await mutationCreateResearchObject(composeClient, data); - - await waitAndSync(streamID); - const V1 = await mutationUpdateResearchObject( + const { streamID } = await mutationCreateResearchObject( composeClient, - { - id: streamID, - title: 'Title 1' - } + data, ); await waitAndSync(streamID); - const V2 = await mutationUpdateResearchObject( - composeClient, - { - id: streamID, - title: 'Title 2' - } - ); + const V1 = await mutationUpdateResearchObject(composeClient, { + id: streamID, + title: "Title 1", + }); + + await waitAndSync(streamID); + const V2 = await mutationUpdateResearchObject(composeClient, { + id: streamID, + title: "Title 2", + }); await waitAndSync(streamID); const versionToResolve = 1; @@ -931,8 +1000,8 @@ describe('ComposeDB nodes', () => { // Find n:th commit, excluding anchor commits const commitCID = stream.state.log - .filter(c => c.type !== 2) - .map(c => c.cid) + .filter((c) => c.type !== 2) + .map((c) => c.cid) .at(versionToResolve); expect(commitCID).not.toBeUndefined(); @@ -940,17 +1009,20 @@ describe('ComposeDB nodes', () => { // Load state as of the n:th data commit in the stream const streamAtV0 = await ceramic.loadStream(commit); - expect(streamAtV0.content.title).toEqual('Title 1'); // yay + expect(streamAtV0.content.title).toEqual("Title 1"); // yay }); }); }); const freshClient = () => - new ComposeClient({ ceramic, definition: definition as RuntimeCompositeDefinition }); + new ComposeClient({ + ceramic, + definition: definition as RuntimeCompositeDefinition, + }); /** Sync between fast updates to same streams to make tests less flaky, -* also allowing for an anchor commit to pop in between -*/ + * also allowing for an anchor commit to pop in between + */ const waitAndSync = async (streamID: string, timeout?: number) => { await setTimeout(timeout || 150); const stream = await ceramic.loadStream(streamID); @@ -961,5 +1033,5 @@ const debugStream = async (streamID: string, message: string) => { const stream = await ceramic.loadStream(streamID); console.log(`*********** [START] ${message} ***********`); console.log(`LOG:`, JSON.stringify(stream.state.log, undefined, 2)); - console.log(`*********** [END] ${message} ***********`) -} \ No newline at end of file + console.log(`*********** [END] ${message} ***********`); +}; diff --git a/test/util.ts b/test/util.ts index ac98aa6..ba6228b 100644 --- a/test/util.ts +++ b/test/util.ts @@ -1,9 +1,9 @@ -import KeyDIDResolver from 'key-did-resolver' -import { webcrypto } from 'crypto' -import { DID } from 'dids'; -import { Ed25519Provider } from "key-did-provider-ed25519" +import KeyDIDResolver from "key-did-resolver"; +import { webcrypto } from "crypto"; +import { DID } from "dids"; +import { Ed25519Provider } from "key-did-provider-ed25519"; -const keyResolver = KeyDIDResolver.getResolver() +const keyResolver = KeyDIDResolver.getResolver(); export const randomDID = async () => { const privateKey = new Uint8Array(32); @@ -11,9 +11,9 @@ export const randomDID = async () => { const did = new DID({ provider: new Ed25519Provider(privateKey), resolver: { - ...keyResolver - } - }) - await did.authenticate() - return did -} + ...keyResolver, + }, + }); + await did.authenticate(); + return did; +}; diff --git a/tsconfig.json b/tsconfig.json index c794de1..1830192 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,11 +1,7 @@ { "compilerOptions": { "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -20,17 +16,9 @@ "incremental": true, "baseUrl": ".", "paths": { - "@/*": [ - "./*" - ] + "@/*": ["./*"] } }, - "include": [ - "**/*.ts", - "**/*.tsx", - "template_data.json" - ], - "exclude": [ - "node_modules" - ] + "include": ["**/*.ts", "**/*.tsx", "template_data.json"], + "exclude": ["node_modules"] } diff --git a/types/index.ts b/types/index.ts index 6b5e795..097ae2c 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1,149 +1,149 @@ export type Profile = { - id?: string - version?: string - displayName?: string - orcid?: string + id?: string; + version?: string; + displayName?: string; + orcid?: string; }; export type DID = { - profile?: Profile + profile?: Profile; }; export type ResearchObject = { - id?: string - version?: string - owner?: DID + id?: string; + version?: string; + owner?: DID; - title: string - manifest: string + title: string; + manifest: string; - components?: ResearchComponent[] + components?: ResearchComponent[]; - metadata?: string // CID + metadata?: string; // CID }; export type ResearchComponent = { - owner?: DID - version?: string + owner?: DID; + version?: string; - name: string - mimeType: string + name: string; + mimeType: string; - dagNode: string - pathToNode: string + dagNode: string; + pathToNode: string; - researchObjectID: string - researchObjectVersion: string + researchObjectID: string; + researchObjectVersion: string; - metadata?: string // CID + metadata?: string; // CID }; export type Claim = { - id?: string - version?: string + id?: string; + version?: string; - title: string - description: string - badge?: string + title: string; + description: string; + badge?: string; }; export type Attestation = { - id?: string - version?: string - source?: DID + id?: string; + version?: string; + source?: DID; - targetID: string - targetVersion: string + targetID: string; + targetVersion: string; - claimID: string - claimVersion: string - claim?: Claim + claimID: string; + claimVersion: string; + claim?: Claim; - revoked: boolean + revoked: boolean; }; export type Annotation = { - id?: string - version?: string - comment: string + id?: string; + version?: string; + comment: string; - researchObjectID: string - researchObject?: ResearchObject - researchObjectVersion: string + researchObjectID: string; + researchObject?: ResearchObject; + researchObjectVersion: string; - targetID?: string - targetVersion?: string + targetID?: string; + targetVersion?: string; - dagNode?: string // CID - pathToNode?: string + dagNode?: string; // CID + pathToNode?: string; - locationOnFile?: string + locationOnFile?: string; - claimID?: string - claim?: Claim - claimVersion?: string + claimID?: string; + claim?: Claim; + claimVersion?: string; - metadataPayload?: string + metadataPayload?: string; }; export type ContributorRelation = { - id?: string - role: string + id?: string; + role: string; - contributorID: string + contributorID: string; - researchObjectID: string - researchObjectVersion: string + researchObjectID: string; + researchObjectVersion: string; - revoked: Boolean + revoked: Boolean; }; export type ReferenceRelation = { - id?: string + id?: string; - toID: string - toVersion: string + toID: string; + toVersion: string; - fromID: string - fromVersion: string + fromID: string; + fromVersion: string; - revoked: Boolean + revoked: Boolean; }; export type ResearchField = { - title: string + title: string; }; export type ResearchFieldRelation = { - id?: string - fieldID: string + id?: string; + fieldID: string; - researchObjectID: string - researchObjectVersion: string + researchObjectID: string; + researchObjectVersion: string; }; -export type ProtocolEntity = - Profile | - ResearchObject | - ResearchComponent | - Claim | - Attestation | - Annotation | - ContributorRelation | - ReferenceRelation | - ResearchField | - ResearchFieldRelation; +export type ProtocolEntity = + | Profile + | ResearchObject + | ResearchComponent + | Claim + | Attestation + | Annotation + | ContributorRelation + | ReferenceRelation + | ResearchField + | ResearchFieldRelation; export type NodeIDs = { - streamID: string, - commitID: string + streamID: string; + commitID: string; }; export type SidebarProps = { - displayName?: string - id?: string + displayName?: string; + id?: string; }; export type RequiredKeys = { - [K in keyof T as (undefined extends T[K] ? never : K)]: T[K] + [K in keyof T as undefined extends T[K] ? never : K]: T[K]; }; diff --git a/utils/index.ts b/utils/index.ts index 025a558..5f67e3a 100644 --- a/utils/index.ts +++ b/utils/index.ts @@ -1,9 +1,9 @@ import { DIDSession } from "did-session"; import { EthereumWebAuth, getAccountId } from "@didtools/pkh-ethereum"; -import type { CeramicApi } from "@ceramicnetwork/common" +import type { CeramicApi } from "@ceramicnetwork/common"; import type { ComposeClient } from "@composedb/client"; -// If you are relying on an injected provider this must be here otherwise you will have a type error. +// If you are relying on an injected provider this must be here otherwise you will have a type error. declare global { interface Window { ethereum: any; @@ -14,15 +14,18 @@ declare global { * Checks localStorage for a stored DID Session. If one is found we authenticate it, otherwise we create a new one. * @returns Promise - The User's authenticated sesion. */ -export const authenticateCeramic = async (ceramic: CeramicApi, compose: ComposeClient) => { - const sessionStr = localStorage.getItem('did') // for production you will want a better place than localStorage for your sessions. - let session +export const authenticateCeramic = async ( + ceramic: CeramicApi, + compose: ComposeClient, +) => { + const sessionStr = localStorage.getItem("did"); // for production you will want a better place than localStorage for your sessions. + let session; - if(sessionStr) { - session = await DIDSession.fromSession(sessionStr) + if (sessionStr) { + session = await DIDSession.fromSession(sessionStr); } - if(!session || (session.hasSession && session.isExpired)) { + if (!session || (session.hasSession && session.isExpired)) { if (window.ethereum === null || window.ethereum === undefined) { throw new Error("No injected Ethereum provider found."); } @@ -33,8 +36,11 @@ export const authenticateCeramic = async (ceramic: CeramicApi, compose: ComposeC const addresses = await ethProvider.enable({ method: "eth_requestAccounts", }); - const accountId = await getAccountId(ethProvider, addresses[0]) - const authMethod = await EthereumWebAuth.getAuthMethod(ethProvider, accountId) + const accountId = await getAccountId(ethProvider, addresses[0]); + const authMethod = await EthereumWebAuth.getAuthMethod( + ethProvider, + accountId, + ); /** * Create DIDSession & provide capabilities that we want to access. @@ -42,13 +48,15 @@ export const authenticateCeramic = async (ceramic: CeramicApi, compose: ComposeC * This is not done here to allow you to add more datamodels to your application. */ // TODO: update resources to only provide access to our composities - session = await DIDSession.authorize(authMethod, {resources: ["ceramic://*"]}) + session = await DIDSession.authorize(authMethod, { + resources: ["ceramic://*"], + }); // Set the session in localStorage. - localStorage.setItem('did', session.serialize()); + localStorage.setItem("did", session.serialize()); } // Set our Ceramic DID to be our session DID. - compose.setDID(session.did) - ceramic.did = session.did - return session -} + compose.setDID(session.did); + ceramic.did = session.did; + return session; +}; diff --git a/utils/populate.tsx b/utils/populate.tsx index b903ed5..d3b12cc 100644 --- a/utils/populate.tsx +++ b/utils/populate.tsx @@ -1,9 +1,9 @@ -import KeyDIDResolver from "key-did-resolver" -import { Ed25519Provider } from "key-did-provider-ed25519" -import { DID } from "dids" -import { fromString } from "uint8arrays/from-string" -import untypedTemplateData from "../template_data.json" -import { ComposeClient } from "@composedb/client" +import KeyDIDResolver from "key-did-resolver"; +import { Ed25519Provider } from "key-did-provider-ed25519"; +import { DID } from "dids"; +import { fromString } from "uint8arrays/from-string"; +import untypedTemplateData from "../template_data.json"; +import { ComposeClient } from "@composedb/client"; import { mutationCreateAnnotation, mutationCreateAttestation, @@ -14,12 +14,12 @@ import { mutationCreateResearchComponent, mutationCreateResearchField, mutationCreateResearchFieldRelation, - mutationCreateResearchObject -} from "./queries" -import { CeramicClient } from "@ceramicnetwork/http-client" -import { definition } from '@/src/__generated__/definition' -import { RuntimeCompositeDefinition } from "@composedb/types" -import { Annotation, Attestation, NodeIDs, ResearchObject } from "@/types" + mutationCreateResearchObject, +} from "./queries"; +import { CeramicClient } from "@ceramicnetwork/http-client"; +import { definition } from "@/src/__generated__/definition"; +import { RuntimeCompositeDefinition } from "@composedb/types"; +import { Annotation, Attestation, NodeIDs, ResearchObject } from "@/types"; import { AnnotationTemplate, AttestationTemplate, @@ -28,14 +28,14 @@ import { ObjectPath, ReferenceRelationTemplate, ResearchFieldRelationTemplate, - ResearchObjectTemplate -} from "./templateData" + ResearchObjectTemplate, +} from "./templateData"; const templateData: DataTemplate = untypedTemplateData; const didFromSeed = async (seed: string) => { const keyResolver = KeyDIDResolver.getResolver(); - const key = fromString(seed, "base16") + const key = fromString(seed, "base16"); const did = new DID({ provider: new Ed25519Provider(key), resolver: { @@ -46,15 +46,13 @@ const didFromSeed = async (seed: string) => { return did; }; -type ProfileIndexResults = { data: { profileIndex: { edges: [] } } } +type ProfileIndexResults = { data: { profileIndex: { edges: [] } } }; export const loadIfUninitialised = async (ceramic: CeramicClient) => { - const composeClient = new ComposeClient( - { - ceramic, - definition: definition as RuntimeCompositeDefinition - } - ); - const firstProfile = await composeClient.executeQuery(` + const composeClient = new ComposeClient({ + ceramic, + definition: definition as RuntimeCompositeDefinition, + }); + const firstProfile = (await composeClient.executeQuery(` query { profileIndex(first: 1) { edges { @@ -64,45 +62,45 @@ export const loadIfUninitialised = async (ceramic: CeramicClient) => { } } } - `) as ProfileIndexResults; + `)) as ProfileIndexResults; if (firstProfile.data.profileIndex.edges.length === 0) { - console.log("Profile index empty, loading template data...") - await loadTemplateData(composeClient) + console.log("Profile index empty, loading template data..."); + await loadTemplateData(composeClient); } else { - console.log("Found profiles in index, skipping template data initialisation.") - }; + console.log( + "Found profiles in index, skipping template data initialisation.", + ); + } }; // Same shape as the template data, but with NodeIDs for each leaf type ActorDataNodeIDs = { - profile?: NodeIDs + profile?: NodeIDs; researchObjects: { - IDs: NodeIDs - components: NodeIDs[] - }[], - claims: NodeIDs[], - researchFields: NodeIDs[], - attestations: NodeIDs[], - contributorRelations: NodeIDs[], - referenceRelations: NodeIDs[], - researchFieldRelations: NodeIDs[], - annotations: NodeIDs[] + IDs: NodeIDs; + components: NodeIDs[]; + }[]; + claims: NodeIDs[]; + researchFields: NodeIDs[]; + attestations: NodeIDs[]; + contributorRelations: NodeIDs[]; + referenceRelations: NodeIDs[]; + researchFieldRelations: NodeIDs[]; + annotations: NodeIDs[]; }; -const freshActorRecord = (profile: NodeIDs): ActorDataNodeIDs => ( - { - profile, - researchObjects: [], - claims: [], - attestations: [], - researchFields: [], - contributorRelations: [], - referenceRelations: [], - researchFieldRelations: [], - annotations: [] - } -); +const freshActorRecord = (profile: NodeIDs): ActorDataNodeIDs => ({ + profile, + researchObjects: [], + claims: [], + attestations: [], + researchFields: [], + contributorRelations: [], + referenceRelations: [], + researchFieldRelations: [], + annotations: [], +}); type StreamIndex = Record; @@ -111,87 +109,90 @@ type StreamIndex = Record; * seed runs mutations to create instances of the data. Builds up the corresponding * record but with the streamIDs of the nodes so they can be found and used as targets * for more complex instances made by later actors. -**/ + **/ const loadTemplateData = async (composeClient: ComposeClient) => { const streamIndex: StreamIndex = {}; for (const [seed, template] of Object.entries(templateData)) { - composeClient.setDID(await didFromSeed(seed)) + composeClient.setDID(await didFromSeed(seed)); - const profileIDs = await mutationCreateProfile(composeClient, template.profile); + const profileIDs = await mutationCreateProfile( + composeClient, + template.profile, + ); streamIndex[seed] = freshActorRecord(profileIDs); streamIndex[seed].researchFields = await Promise.all( - template.researchFields.map( - rfTemplate => mutationCreateResearchField(composeClient, rfTemplate) - ) + template.researchFields.map((rfTemplate) => + mutationCreateResearchField(composeClient, rfTemplate), + ), ); streamIndex[seed].researchObjects = await Promise.all( - template.researchObjects.map( - roTemplate => loadResearchObject(roTemplate, composeClient) - ) + template.researchObjects.map((roTemplate) => + loadResearchObject(roTemplate, composeClient), + ), ); streamIndex[seed].contributorRelations = await Promise.all( template.contributorRelations.map((contTemplate: any) => - loadContributorRelation(contTemplate, streamIndex, composeClient) - ) + loadContributorRelation(contTemplate, streamIndex, composeClient), + ), ); streamIndex[seed].referenceRelations = await Promise.all( template.referenceRelations.map((refTemplate: any) => - loadReferenceRelation(refTemplate, streamIndex, composeClient) - ) + loadReferenceRelation(refTemplate, streamIndex, composeClient), + ), ); streamIndex[seed].researchFieldRelations = await Promise.all( template.researchFieldRelations.map((fieldRelTemplate: any) => - loadResearchFieldRelation(fieldRelTemplate, streamIndex, composeClient) - ) + loadResearchFieldRelation(fieldRelTemplate, streamIndex, composeClient), + ), ); streamIndex[seed].claims = await Promise.all( - template.claims.map(c => mutationCreateClaim(composeClient, c)) + template.claims.map((c) => mutationCreateClaim(composeClient, c)), ); streamIndex[seed].attestations = await Promise.all( - template.attestations.map(attTemplate => loadAttestation( - attTemplate, streamIndex, composeClient - )) + template.attestations.map((attTemplate) => + loadAttestation(attTemplate, streamIndex, composeClient), + ), ); streamIndex[seed].annotations = await Promise.all( - template.annotations.map(annTemplate => loadAnnotation( - annTemplate, streamIndex, composeClient - )) + template.annotations.map((annTemplate) => + loadAnnotation(annTemplate, streamIndex, composeClient), + ), ); - }; + } console.log("Loading template data done!"); -} +}; const loadResearchObject = async ( roTemplate: ResearchObjectTemplate, - composeClient: ComposeClient -): Promise => { + composeClient: ComposeClient, +): Promise => { const roProps: ResearchObject = { title: roTemplate.title, - manifest: roTemplate.manifest - } - const researchObject = await mutationCreateResearchObject(composeClient, roProps); + manifest: roTemplate.manifest, + }; + const researchObject = await mutationCreateResearchObject( + composeClient, + roProps, + ); // Possibly create manifest components if such exist const components = await Promise.all( roTemplate.components.map((c: any) => - mutationCreateResearchComponent( - composeClient, - { - ...c, - researchObjectID: researchObject.streamID, - researchObjectVersion: researchObject.commitID, - pathToNode: "." - } - ) - ) + mutationCreateResearchComponent(composeClient, { + ...c, + researchObjectID: researchObject.streamID, + researchObjectVersion: researchObject.commitID, + pathToNode: ".", + }), + ), ); return { IDs: researchObject, components }; @@ -200,66 +201,57 @@ const loadResearchObject = async ( const loadContributorRelation = async ( contTemplate: ContributorRelationTemplate, streamIndex: StreamIndex, - composeClient: ComposeClient -): Promise => { + composeClient: ComposeClient, +): Promise => { const { role, researchObjectPath, contributorPath } = contTemplate; const researchObject = recursePathToID(streamIndex, researchObjectPath); const contributor = recursePathToID(streamIndex, contributorPath); - return await mutationCreateContributorRelation( - composeClient, - { - role, - contributorID: contributor.streamID, - researchObjectID: researchObject.streamID, - researchObjectVersion: researchObject.commitID, - revoked: false - } - ); + return await mutationCreateContributorRelation(composeClient, { + role, + contributorID: contributor.streamID, + researchObjectID: researchObject.streamID, + researchObjectVersion: researchObject.commitID, + revoked: false, + }); }; const loadReferenceRelation = async ( refTemplate: ReferenceRelationTemplate, streamIndex: StreamIndex, - composeClient: ComposeClient -): Promise => { + composeClient: ComposeClient, +): Promise => { const { toPath, fromPath } = refTemplate; const to = recursePathToID(streamIndex, toPath); const from = recursePathToID(streamIndex, fromPath); - return await mutationCreateReferenceRelation( - composeClient, - { - toID: to.streamID, - toVersion: to.commitID, - fromID: from.streamID, - fromVersion: from.commitID, - revoked: false - } - ); + return await mutationCreateReferenceRelation(composeClient, { + toID: to.streamID, + toVersion: to.commitID, + fromID: from.streamID, + fromVersion: from.commitID, + revoked: false, + }); }; const loadResearchFieldRelation = async ( fieldRelTemplate: ResearchFieldRelationTemplate, streamIndex: StreamIndex, - composeClient: ComposeClient -): Promise => { + composeClient: ComposeClient, +): Promise => { const { researchObjectPath, fieldPath } = fieldRelTemplate; const researchObject = recursePathToID(streamIndex, researchObjectPath); const field = recursePathToID(streamIndex, fieldPath); - return await mutationCreateResearchFieldRelation( - composeClient, - { - researchObjectID: researchObject.streamID, - researchObjectVersion: researchObject.commitID, - fieldID: field.streamID - } - ); + return await mutationCreateResearchFieldRelation(composeClient, { + researchObjectID: researchObject.streamID, + researchObjectVersion: researchObject.commitID, + fieldID: field.streamID, + }); }; const loadAttestation = async ( attestationTemplate: AttestationTemplate, streamIndex: StreamIndex, - composeClient: ComposeClient -): Promise => { + composeClient: ComposeClient, +): Promise => { const { targetPath, claimPath } = attestationTemplate; const target = recursePathToID(streamIndex, targetPath); const claim = recursePathToID(streamIndex, claimPath); @@ -268,7 +260,7 @@ const loadAttestation = async ( targetVersion: target.commitID, claimID: claim.streamID, claimVersion: claim.commitID, - revoked: false + revoked: false, }; return mutationCreateAttestation(composeClient, attestation); }; @@ -276,23 +268,23 @@ const loadAttestation = async ( const loadAnnotation = async ( annotationTemplate: AnnotationTemplate, streamIndex: StreamIndex, - composeClient: ComposeClient -): Promise => { + composeClient: ComposeClient, +): Promise => { const { comment, path, targetPath, claimPath } = annotationTemplate; const target = recursePathToID(streamIndex, targetPath); const annotation: Annotation = { targetID: target.streamID, targetVersion: target.commitID, - comment + comment, }; if (claimPath) { const claim = recursePathToID(streamIndex, claimPath); annotation.claimID = claim.streamID; annotation.claimVersion = claim.commitID; - }; + } if (path) { annotation.path = path; - }; + } return mutationCreateAnnotation(composeClient, annotation); }; diff --git a/utils/queries.ts b/utils/queries.ts index 6725e09..145e6fa 100644 --- a/utils/queries.ts +++ b/utils/queries.ts @@ -1,28 +1,44 @@ import { ComposeClient } from "@composedb/client"; -import { Attestation, Claim, ResearchComponent, Profile, ResearchObject, ContributorRelation, ReferenceRelation, ResearchFieldRelation, ProtocolEntity, Annotation, NodeIDs, ResearchField } from "../types"; +import { + Attestation, + Claim, + ResearchComponent, + Profile, + ResearchObject, + ContributorRelation, + ReferenceRelation, + ResearchFieldRelation, + ProtocolEntity, + Annotation, + NodeIDs, + ResearchField, +} from "../types"; import { ExecutionResult } from "graphql"; export const queryViewerId = async ( - composeClient: ComposeClient + composeClient: ComposeClient, ): Promise => { - const response = await composeClient.executeQuery<{ viewer: { id: string } }>(` + const response = await composeClient.executeQuery<{ + viewer: { id: string }; + }>(` query { viewer { id } - }` - ) - assertQueryErrors(response, 'viewer id'); - return response.data!.viewer.id -} + }`); + assertQueryErrors(response, "viewer id"); + return response.data!.viewer.id; +}; /** * Queries for the viewer profile, which could be null if authentication isn't done yet -*/ + */ export const queryViewerProfile = async ( - composeClient: ComposeClient + composeClient: ComposeClient, ): Promise => { - const response = await composeClient.executeQuery<{ viewer: { profile: Profile | null } }>(` + const response = await composeClient.executeQuery<{ + viewer: { profile: Profile | null }; + }>(` query { viewer { profile { @@ -31,18 +47,17 @@ export const queryViewerProfile = async ( orcid } } - }` - ) - assertQueryErrors(response, 'viewer profile') - return response.data!.viewer.profile -} + }`); + assertQueryErrors(response, "viewer profile"); + return response.data!.viewer.profile; +}; export const queryViewerResearchObjects = async ( - composeClient: ComposeClient + composeClient: ComposeClient, ): Promise => { - const response = await composeClient.executeQuery< - { viewer: { researchObjectList: { edges: { node: ResearchObject }[] } } } - >(` + const response = await composeClient.executeQuery<{ + viewer: { researchObjectList: { edges: { node: ResearchObject }[] } }; + }>(` query { viewer { researchObjectList(first: 100) { @@ -56,17 +71,17 @@ export const queryViewerResearchObjects = async ( } } } - `) - assertQueryErrors(response, 'viewer research objects') - return response.data!.viewer.researchObjectList.edges.map(e => e.node) -} + `); + assertQueryErrors(response, "viewer research objects"); + return response.data!.viewer.researchObjectList.edges.map((e) => e.node); +}; export const queryViewerClaims = async ( - composeClient: ComposeClient + composeClient: ComposeClient, ): Promise => { - const response = await composeClient.executeQuery< - { viewer: { claimList: { edges: { node: Claim }[] } } } - >(` + const response = await composeClient.executeQuery<{ + viewer: { claimList: { edges: { node: Claim }[] } }; + }>(` query { viewer { claimList(first: 100) { @@ -81,17 +96,17 @@ export const queryViewerClaims = async ( } } } - `) - assertQueryErrors(response, 'viewer claims') - return response.data!.viewer.claimList.edges.map(e => e.node) -} + `); + assertQueryErrors(response, "viewer claims"); + return response.data!.viewer.claimList.edges.map((e) => e.node); +}; export const queryResearchObjects = async ( - composeClient: ComposeClient + composeClient: ComposeClient, ): Promise => { - const response = await composeClient.executeQuery< - { researchObjectIndex: { edges: { node: ResearchObject }[] } } - >(` + const response = await composeClient.executeQuery<{ + researchObjectIndex: { edges: { node: ResearchObject }[] }; + }>(` query { researchObjectIndex(first: 100) { edges { @@ -109,18 +124,19 @@ export const queryResearchObjects = async ( } } } - `) - assertQueryErrors(response, 'research objects') - return response.data!.researchObjectIndex.edges.map(e => e.node) -} + `); + assertQueryErrors(response, "research objects"); + return response.data!.researchObjectIndex.edges.map((e) => e.node); +}; export const queryResearchObjectAttestations = async ( composeClient: ComposeClient, - researchObjectID: string + researchObjectID: string, ) => { - const response = await composeClient.executeQuery< - { node: { attestations: { edges: { node: Attestation }[] } } } - >(` + const response = await composeClient.executeQuery<{ + node: { attestations: { edges: { node: Attestation }[] } }; + }>( + ` query ($id: ID!) { node(id: $id) { ... on ResearchObject { @@ -141,36 +157,38 @@ export const queryResearchObjectAttestations = async ( } } } - `, { id: researchObjectID }) - assertQueryErrors(response, `attestations on research object ${researchObjectID}`) - return response.data!.node.attestations.edges.map(e => e.node) -} + `, + { id: researchObjectID }, + ); + assertQueryErrors( + response, + `attestations on research object ${researchObjectID}`, + ); + return response.data!.node.attestations.edges.map((e) => e.node); +}; const RO_TYPE_MAP = { title: "String!", manifest: "InterPlanetaryCID!", - metadata: "InterPlanetaryCID" + metadata: "InterPlanetaryCID", }; export const mutationCreateResearchObject = async ( composeClient: ComposeClient, - inputs: ResearchObject -): Promise => genericCreate( - composeClient, - inputs, - RO_TYPE_MAP, - 'createResearchObject' -); + inputs: ResearchObject, +): Promise => + genericCreate(composeClient, inputs, RO_TYPE_MAP, "createResearchObject"); export const mutationUpdateResearchObject = async ( composeClient: ComposeClient, - inputs: Partial & { id: string } -): Promise => genericUpdate( - composeClient, - inputs, - makeAllOptional(RO_TYPE_MAP), - 'updateResearchObject' -); + inputs: Partial & { id: string }, +): Promise => + genericUpdate( + composeClient, + inputs, + makeAllOptional(RO_TYPE_MAP), + "updateResearchObject", + ); const COMPONENT_TYPE_MAP = { name: "String!", @@ -179,84 +197,90 @@ const COMPONENT_TYPE_MAP = { dagNode: "InterPlanetaryCID!", pathToNode: "String!", researchObjectID: "CeramicStreamID!", - researchObjectVersion: "CeramicCommitID!" + researchObjectVersion: "CeramicCommitID!", }; export const mutationCreateResearchComponent = async ( composeClient: ComposeClient, - inputs: ResearchComponent -): Promise => genericCreate( - composeClient, - inputs, - COMPONENT_TYPE_MAP, - 'createResearchComponent' -); + inputs: ResearchComponent, +): Promise => + genericCreate( + composeClient, + inputs, + COMPONENT_TYPE_MAP, + "createResearchComponent", + ); export const mutationUpdateResearchComponent = async ( composeClient: ComposeClient, - inputs: Partial & { id: string } -): Promise => genericUpdate( - composeClient, - inputs, - makeAllOptional(COMPONENT_TYPE_MAP), - 'updateResearchComponent' -); + inputs: Partial & { id: string }, +): Promise => + genericUpdate( + composeClient, + inputs, + makeAllOptional(COMPONENT_TYPE_MAP), + "updateResearchComponent", + ); export const mutationCreateProfile = async ( composeClient: ComposeClient, - inputs: Profile -): Promise => genericCreate( - composeClient, - inputs, - { - displayName: "String!", - orcid: "String" - }, - 'createProfile', - true -); + inputs: Profile, +): Promise => + genericCreate( + composeClient, + inputs, + { + displayName: "String!", + orcid: "String", + }, + "createProfile", + true, + ); export const mutationCreateClaim = async ( composeClient: ComposeClient, - inputs: Claim -): Promise => genericCreate( - composeClient, - inputs, - { - title: "String!", - description: "String!", - badge: "InterPlanetaryCID!", - }, - 'createClaim' -); + inputs: Claim, +): Promise => + genericCreate( + composeClient, + inputs, + { + title: "String!", + description: "String!", + badge: "InterPlanetaryCID!", + }, + "createClaim", + ); const ATTESTATION_TYPE_MAP = { targetID: "CeramicStreamID!", targetVersion: "CeramicCommitID!", claimID: "CeramicStreamID!", claimVersion: "CeramicCommitID!", - revoked: "Boolean" + revoked: "Boolean", }; export const mutationCreateAttestation = async ( composeClient: ComposeClient, - inputs: Attestation -): Promise => genericCreate( - composeClient, - inputs, - ATTESTATION_TYPE_MAP, - 'createAttestation' -); + inputs: Attestation, +): Promise => + genericCreate( + composeClient, + inputs, + ATTESTATION_TYPE_MAP, + "createAttestation", + ); export const mutationUpdateAttestation = async ( composeClient: ComposeClient, - inputs: Partial & { id: string } -): Promise => genericUpdate( - composeClient, - inputs, - makeAllOptional(ATTESTATION_TYPE_MAP), - 'updateAttestation' -); + inputs: Partial & { id: string }, +): Promise => + genericUpdate( + composeClient, + inputs, + makeAllOptional(ATTESTATION_TYPE_MAP), + "updateAttestation", + ); const ANNOTATION_TYPE_MAP = { comment: "String!", @@ -269,185 +293,193 @@ const ANNOTATION_TYPE_MAP = { locationOnFile: "String", claimID: "CeramicStreamID", claimVersion: "CeramicCommitID", - metadataPayload: "InterPlanetaryCID" + metadataPayload: "InterPlanetaryCID", }; export const mutationCreateAnnotation = async ( composeClient: ComposeClient, - inputs: Annotation -): Promise => genericCreate( - composeClient, - inputs, - ANNOTATION_TYPE_MAP, - 'createAnnotation' -); + inputs: Annotation, +): Promise => + genericCreate(composeClient, inputs, ANNOTATION_TYPE_MAP, "createAnnotation"); export const mutationUpdateAnnotation = async ( composeClient: ComposeClient, - inputs: Partial & { id: string } -): Promise => genericCreate( - composeClient, - inputs, - makeAllOptional(ANNOTATION_TYPE_MAP), - 'createAnnotation' -); + inputs: Partial & { id: string }, +): Promise => + genericCreate( + composeClient, + inputs, + makeAllOptional(ANNOTATION_TYPE_MAP), + "createAnnotation", + ); const CONTRIBUTOR_TYPE_MAP = { role: "String!", contributorID: "CeramicStreamID!", researchObjectID: "CeramicStreamID!", researchObjectVersion: "CeramicCommitID!", - revoked: "Boolean!" + revoked: "Boolean!", }; export const mutationCreateContributorRelation = async ( composeClient: ComposeClient, - inputs: ContributorRelation -): Promise => genericCreate( - composeClient, - inputs, - CONTRIBUTOR_TYPE_MAP, - 'createContributorRelation' -); + inputs: ContributorRelation, +): Promise => + genericCreate( + composeClient, + inputs, + CONTRIBUTOR_TYPE_MAP, + "createContributorRelation", + ); export const mutationUpdateContributorRelation = async ( composeClient: ComposeClient, - inputs: Partial & { id: string } -): Promise => genericUpdate( - composeClient, - inputs, - makeAllOptional(CONTRIBUTOR_TYPE_MAP), - 'updateContributorRelation' -); + inputs: Partial & { id: string }, +): Promise => + genericUpdate( + composeClient, + inputs, + makeAllOptional(CONTRIBUTOR_TYPE_MAP), + "updateContributorRelation", + ); const REFERENCE_TYPE_MAP = { toID: "CeramicStreamID!", toVersion: "CeramicCommitID!", fromID: "CeramicStreamID!", fromVersion: "CeramicCommitID!", - revoked: "Boolean!" + revoked: "Boolean!", }; export const mutationCreateReferenceRelation = async ( composeClient: ComposeClient, - inputs: ReferenceRelation -): Promise => genericCreate( - composeClient, - inputs, - REFERENCE_TYPE_MAP, - 'createReferenceRelation' -); + inputs: ReferenceRelation, +): Promise => + genericCreate( + composeClient, + inputs, + REFERENCE_TYPE_MAP, + "createReferenceRelation", + ); export const mutationUpdateReferenceRelation = async ( composeClient: ComposeClient, - inputs: Partial & { id: string } -): Promise => genericUpdate( - composeClient, - inputs, - makeAllOptional(REFERENCE_TYPE_MAP), - 'updateReferenceRelation' -); + inputs: Partial & { id: string }, +): Promise => + genericUpdate( + composeClient, + inputs, + makeAllOptional(REFERENCE_TYPE_MAP), + "updateReferenceRelation", + ); export const mutationCreateResearchFieldRelation = async ( composeClient: ComposeClient, - inputs: ResearchFieldRelation -): Promise => genericCreate( - composeClient, - inputs, - { - fieldID: "CeramicStreamID!", - researchObjectID: "CeramicStreamID!", - researchObjectVersion: "CeramicCommitID!" - }, - 'createResearchFieldRelation' -); + inputs: ResearchFieldRelation, +): Promise => + genericCreate( + composeClient, + inputs, + { + fieldID: "CeramicStreamID!", + researchObjectID: "CeramicStreamID!", + researchObjectVersion: "CeramicCommitID!", + }, + "createResearchFieldRelation", + ); export const mutationCreateResearchField = async ( composeClient: ComposeClient, - inputs: ResearchField -): Promise => genericCreate( - composeClient, - inputs, - { - title: "String!", - }, - 'createResearchField' -); + inputs: ResearchField, +): Promise => + genericCreate( + composeClient, + inputs, + { + title: "String!", + }, + "createResearchField", + ); export const queryResearchObject = async ( composeClient: ComposeClient, id: string, - selection?: string -): Promise => genericEntityQuery( - composeClient, - id, - 'ResearchObject', - selection ?? - ` + selection?: string, +): Promise => + genericEntityQuery( + composeClient, + id, + "ResearchObject", + selection ?? + ` title manifest metadata - ` -); + `, + ); export const queryProfile = async ( composeClient: ComposeClient, id: string, - selection?: string -): Promise => genericEntityQuery( - composeClient, - id, - 'Profile', - selection ?? - ` + selection?: string, +): Promise => + genericEntityQuery( + composeClient, + id, + "Profile", + selection ?? + ` displayName orcid - ` -); + `, + ); export const queryClaim = async ( composeClient: ComposeClient, id: string, - selection?: string -): Promise => genericEntityQuery( - composeClient, - id, - 'Claim', - selection ?? - ` + selection?: string, +): Promise => + genericEntityQuery( + composeClient, + id, + "Claim", + selection ?? + ` title description badge - ` -); + `, + ); export const queryAttestation = async ( composeClient: ComposeClient, id: string, - selection?: string -): Promise => genericEntityQuery( - composeClient, - id, - 'Attestation', - selection ?? - ` + selection?: string, +): Promise => + genericEntityQuery( + composeClient, + id, + "Attestation", + selection ?? + ` targetID targetVersion claimID claimVersion revoked - ` -); + `, + ); export const queryResearchComponent = async ( composeClient: ComposeClient, id: string, - selection?: string -): Promise => genericEntityQuery( - composeClient, - id, - 'ResearchComponent', - selection ?? - ` + selection?: string, +): Promise => + genericEntityQuery( + composeClient, + id, + "ResearchComponent", + selection ?? + ` name mimeType metadata @@ -455,19 +487,20 @@ export const queryResearchComponent = async ( pathToNode researchObjectID researchObjectVersion - ` -); + `, + ); export const queryAnnotation = async ( composeClient: ComposeClient, id: string, - selection?: string -): Promise => genericEntityQuery( - composeClient, - id, - 'Annotation', - selection ?? - ` + selection?: string, +): Promise => + genericEntityQuery( + composeClient, + id, + "Annotation", + selection ?? + ` comment researchObjectID researchObjectVersion @@ -479,78 +512,77 @@ export const queryAnnotation = async ( claimID claimVersion metadataPayload - ` -); + `, + ); export const queryContributorRelation = async ( composeClient: ComposeClient, id: string, - selection?: string -): Promise => genericEntityQuery( - composeClient, - id, - 'ContributorRelation', - selection ?? - ` + selection?: string, +): Promise => + genericEntityQuery( + composeClient, + id, + "ContributorRelation", + selection ?? + ` role contributorID researchObjectID researchObjectVersion revoked - ` -); + `, + ); export const queryReferenceRelation = async ( composeClient: ComposeClient, id: string, - selection?: string -): Promise => genericEntityQuery( - composeClient, - id, - 'ReferenceRelation', - selection ?? - ` + selection?: string, +): Promise => + genericEntityQuery( + composeClient, + id, + "ReferenceRelation", + selection ?? + ` fromID fromVersion toID toVersion revoked - ` -); + `, + ); export const queryResearchFields = async ( composeClient: ComposeClient, id: string, - selection?: string -): Promise => genericEntityQuery( - composeClient, - id, - 'ResearchField', - selection ?? 'title' -); + selection?: string, +): Promise => + genericEntityQuery(composeClient, id, "ResearchField", selection ?? "title"); export const queryResearchFieldRelation = async ( composeClient: ComposeClient, id: string, - selection?: string -): Promise => genericEntityQuery( - composeClient, - id, - 'ResearchFieldRelation', - selection ?? - ` + selection?: string, +): Promise => + genericEntityQuery( + composeClient, + id, + "ResearchFieldRelation", + selection ?? + ` fieldID researchObjectID researchObjectVersion - ` -); + `, + ); export async function genericEntityQuery( composeClient: ComposeClient, id: string, entityName: string, // Specify the field structure to query for - selection: string + selection: string, ): Promise { const query = ` query($id: ID!) { @@ -561,26 +593,28 @@ export async function genericEntityQuery( } } `; - const result = await composeClient.executeQuery(query, { id }) - assertQueryErrors(result, `${entityName} node`) - return result.data - ? result.data.node as T - : undefined // query can return null too, downscope type -}; + const result = await composeClient.executeQuery(query, { id }); + assertQueryErrors(result, `${entityName} node`); + return result.data ? (result.data.node as T) : undefined; // query can return null too, downscope type +} async function genericCreate( composeClient: ComposeClient, inputs: T, /** At least verify all keys exist in T, can still forget one though. - * Can't require it fully because some props are not allowed in the mutation. - */ + * Can't require it fully because some props are not allowed in the mutation. + */ gqlTypes: Partial>, mutationName: string, /** Skip timeout for single accountRelation entities */ - noTimeout?: boolean + noTimeout?: boolean, ): Promise { - const [params, content] = getQueryFields(gqlTypes as Record, inputs); - const response = await composeClient.executeQuery(` + const [params, content] = getQueryFields( + gqlTypes as Record, + inputs, + ); + const response = (await composeClient.executeQuery( + ` mutation( ${params} ) { ${mutationName}(input: { content: { ${content} } @@ -592,15 +626,16 @@ async function genericCreate( version } } - }`, inputs - ) as any; + }`, + inputs, + )) as any; assertMutationErrors(response, mutationName); const nodeIDs: NodeIDs = { streamID: response.data[mutationName].document.id, - commitID: response.data[mutationName].document.version + commitID: response.data[mutationName].document.version, }; return nodeIDs; -}; +} async function genericUpdate( composeClient: ComposeClient, @@ -609,8 +644,12 @@ async function genericUpdate( gqlTypes: Partial>, mutationName: string, ): Promise { - const [params, content] = getQueryFields(gqlTypes as Record, inputs); - const response = await composeClient.executeQuery(` + const [params, content] = getQueryFields( + gqlTypes as Record, + inputs, + ); + const response = (await composeClient.executeQuery( + ` mutation($id: ID!, ${params} ) { ${mutationName}( input: { @@ -624,66 +663,68 @@ async function genericUpdate( version } } - }`, inputs - ) as any; + }`, + inputs, + )) as any; assertMutationErrors(response, mutationName); const nodeIDs: NodeIDs = { streamID: response.data[mutationName].document.id, - commitID: response.data[mutationName].document.version + commitID: response.data[mutationName].document.version, }; return nodeIDs; } -type SimpleMutationResult = Pick -type SimpleQueryResult = Pick +type SimpleMutationResult = Pick; +type SimpleQueryResult = Pick; const assertMutationErrors = ( result: SimpleMutationResult, - queryDescription: string + queryDescription: string, ) => { if (result.errors) { - console.error('Error:', result.errors.toString()); - throw new Error(`Mutation failed: ${queryDescription}`) - }; -} + console.error("Error:", result.errors.toString()); + throw new Error(`Mutation failed: ${queryDescription}`); + } +}; const assertQueryErrors = ( result: SimpleQueryResult, - queryDescription: string + queryDescription: string, ) => { if (result.errors || !result.data) { console.error("Error:", result.errors?.toString()); throw new Error(`Query failed: ${queryDescription}!`); - }; -} + } +}; /** Get query parameters and doc content string depending on which -* input parameters are supplied. E.g. this input: -* graphQLParamTypes = { field: "String!" } -* inputs = { field: "hello"} -* would yield: -* ["$field: String!", "field: $field"] -* which is what the GraphQL needs to put in the query/mutation parameters -* and the 'content' field, respectively. -* -* This function ignore any the id property because it need to be supplied -* in a special spot and for mutations only. -*/ + * input parameters are supplied. E.g. this input: + * graphQLParamTypes = { field: "String!" } + * inputs = { field: "hello"} + * would yield: + * ["$field: String!", "field: $field"] + * which is what the GraphQL needs to put in the query/mutation parameters + * and the 'content' field, respectively. + * + * This function ignore any the id property because it need to be supplied + * in a special spot and for mutations only. + */ const getQueryFields = ( graphQLParamTypes: Record, - inputs: Record + inputs: Record, ) => Object.keys(inputs) - .filter(p => p !== 'id') + .filter((p) => p !== "id") .reduce<[string[], string[]]>( (acc, next) => [ [...acc[0], `$${next}: ${graphQLParamTypes[next]}`], - [...acc[1], `${next}: $${next}`] + [...acc[1], `${next}: $${next}`], ], - [[], []] - ).map(stringArr => stringArr.join(', ')); + [[], []], + ) + .map((stringArr) => stringArr.join(", ")); const makeAllOptional = (typeMap: Record) => Object.fromEntries( - Object.entries(typeMap).map(([k, v]) => ([k, v.replace('!', '')])) - ); \ No newline at end of file + Object.entries(typeMap).map(([k, v]) => [k, v.replace("!", "")]), + ); diff --git a/utils/templateData.d.ts b/utils/templateData.d.ts index a39d6f2..1a19949 100644 --- a/utils/templateData.d.ts +++ b/utils/templateData.d.ts @@ -1,72 +1,72 @@ export type Seed = string; // Address properties and array indices for indicating the future StreamID, // will be resolved to the actual stream when the template is instantiated -export type ObjectPath = (string | number)[] +export type ObjectPath = (string | number)[]; export type ProfileTemplate = { - displayName: string, - orcid?: string -} + displayName: string; + orcid?: string; +}; export type ComponentTemplate = { - name: string, - dagNode: string, - mimeType: string + name: string; + dagNode: string; + mimeType: string; }; export type ResearchObjectTemplate = { - title: string, - manifest: string, - components: ComponentTemplate[] + title: string; + manifest: string; + components: ComponentTemplate[]; }; export type ClaimTemplate = { - title: string, - description: string -} + title: string; + description: string; +}; export type ResearchFieldTemplate = { - title: string + title: string; }; export type ContributorRelationTemplate = { - role: string, - researchObjectPath: ObjectPath, - contributorPath: ObjectPath + role: string; + researchObjectPath: ObjectPath; + contributorPath: ObjectPath; }; export type ReferenceRelationTemplate = { - fromPath: ObjectPath, - toPath: ObjectPath + fromPath: ObjectPath; + toPath: ObjectPath; }; export type ResearchFieldRelationTemplate = { - researchObjectPath: ObjectPath, - fieldPath: ObjectPath + researchObjectPath: ObjectPath; + fieldPath: ObjectPath; }; export type AttestationTemplate = { - targetPath: ObjectPath, - claimPath: ObjectPath + targetPath: ObjectPath; + claimPath: ObjectPath; }; export type AnnotationTemplate = { - comment: string, - path?: string, - targetPath: ObjectPath, - claimPath?: ObjectPath + comment: string; + path?: string; + targetPath: ObjectPath; + claimPath?: ObjectPath; }; export type ActorTemplate = { - profile: ProfileTemplate, - researchObjects: ResearchObjectTemplate[], - claims: ClaimTemplate[], - researchFields: ResearchFieldTemplate[], - contributorRelations: ContributorRelationTemplate[], - referenceRelations: ReferenceRelationTemplate[], - researchFieldRelations: ResearchFieldRelationTemplate[], - attestations: AttestationTemplate[], - annotations: AnnotationTemplate[] + profile: ProfileTemplate; + researchObjects: ResearchObjectTemplate[]; + claims: ClaimTemplate[]; + researchFields: ResearchFieldTemplate[]; + contributorRelations: ContributorRelationTemplate[]; + referenceRelations: ReferenceRelationTemplate[]; + researchFieldRelations: ResearchFieldRelationTemplate[]; + attestations: AttestationTemplate[]; + annotations: AnnotationTemplate[]; }; -export type DataTemplate = Record +export type DataTemplate = Record; diff --git a/vitest.config.ts b/vitest.config.ts index a8e550e..91ce788 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,9 +1,9 @@ -import { defineConfig } from 'vitest/config' -import tsconfigPaths from 'vite-tsconfig-paths' +import { defineConfig } from "vitest/config"; +import tsconfigPaths from "vite-tsconfig-paths"; export default defineConfig({ test: { - include: ["test/**/*.spec.ts"] + include: ["test/**/*.spec.ts"], }, - plugins: [tsconfigPaths()] -}) \ No newline at end of file + plugins: [tsconfigPaths()], +}); From e5c59b2d70acb94988b36d3100886924b5b7180f Mon Sep 17 00:00:00 2001 From: m0ar Date: Wed, 1 Nov 2023 16:14:43 +0100 Subject: [PATCH 3/9] Add husky lint hook, cleanup scripts, delete some leftovers --- .eslintignore | 1 + .eslintrc.cjs | 18 + .husky/pre-commit | 4 + Makefile | 10 +- README.md | 38 +- package-lock.json | 731 +++++++++++++++---------- package.json | 26 +- scripts/{commands.mjs => generate.mjs} | 4 +- scripts/graphiql.mjs | 15 +- scripts/run.mjs | 16 +- test/root.spec.ts | 17 +- types/index.ts | 4 +- utils/index.ts | 62 --- utils/populate.tsx | 9 +- utils/queries.ts | 13 +- 15 files changed, 548 insertions(+), 420 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.cjs create mode 100755 .husky/pre-commit rename scripts/{commands.mjs => generate.mjs} (97%) delete mode 100644 utils/index.ts diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..9afc44d --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +src/__generated__/* diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..f0d4837 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,18 @@ +module.exports = { + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended' + ], + parser: '@typescript-eslint/parser', + plugins: [ + '@typescript-eslint', + 'prettier', + ], + root: true, + rules: { + "prettier/prettier": "error", + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": ["error", { "varsIgnorePattern": "^_" }] + } +}; diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..75fac8e --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npm run lint diff --git a/Makefile b/Makefile index 6dfd427..f877a8c 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,18 @@ -.PHONY: clean-test test +.PHONY: clean clean-test test + +clean: + rm -rf node_modules local-data clean-test: rm -rf local-data/ceramic-test test: clean-test - sed 's|local-data/ceramic|local-data/ceramic-test|' composedb.config.json > test.config.json + sed 's|local-data/ceramic|local-data/ceramic-test|' composedb.config.json \ + > test.config.json npx ceramic daemon --config test.config.json &>/dev/null & sleep 5 node scripts/composites.mjs - # Kill daemons without losing test exit code for CI + # Ensure daemons dead, without losing test exit code for CI if npm test; then \ npm run kill; true; \ else \ diff --git a/README.md b/README.md index 4664b32..c80a36a 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,44 @@ -# ComposeDB configuration +# Protocol V2 reference implementation +This repo contains a reference implementation for the next generation of the protocol, built on [Ceramic](https://ceramic.network/) and [ComposeDB](https://composedb.js.org/docs/0.5.x/introduction). It includes data models and an extensive test suite to ensure correct functionality, but also example data population and a GraphiQL interface to explore the protocol structure. -This is a rough take on model definitions for DeSci Nodes on Ceramic and ComposeDB, -based on a Ceramic demo at ETHDenver and snippets from Mark Krasner. +By default, the application runs a local Ceramic/ComposeDB node with the bundled IPFS server, uses the `inmemory` network for anchoring, and writes all data and logs to `local-data`. -## Getting Started +## Getting started -1. Install your dependencies: +1. Install dependencies: ```bash -nvm use # ensure node 20 is selected according to .nvmrc -npm install +nvm use # or otherwise ensure the use of node v20 +npm ci # install deps ``` -2. Generate your admin seed, admin did, and ComposeDB configuration file: +2. Generate your own seed, admin DID, and ComposeDB configuration file: ```bash npm run generate ``` -3. Finally, run your application in a new terminal: +3. Finally, start the services: ```bash npm run dev ``` -- Open [http://localhost:3000](http://localhost:3000) to get to Nodes Home -- Open [http://localhost:5001](http://localhost:5001) for the GraphiQL interface +Now you can open [http://localhost:5001](http://localhost:5001) for the GraphiQL interface and explore the data models. -## Reset - -To clean everything up, delete `local-data`. This is necessary when changing networks, for example. - -## Tests +## Test suite There is a test suite running through API operations demonstrating the functional protocol -requirements in an isolated ceramic instance not to dirty down the state, but can also be -run against the dev process. Not both at the same time though, because the ports overlap. +requirements. This clones your user configuration, but changes storage to `local-data/ceramic-test` not to interfere with prepopulated data. Do make sure to stop `npm run dev` before executing tests. ```bash make test ``` + +## Reset + +To reset to a clean state, deleting everything except generated seed and user config: + +```bash +make clean +``` diff --git a/package-lock.json b/package-lock.json index 7c57135..e785009 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,22 +1,22 @@ { - "name": "desci-composites", + "name": "desci-composedb", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "desci-composites", + "name": "desci-composedb", "version": "1.0.0", "license": "MIT", "dependencies": { "@ceramicnetwork/http-client": "^2.31.0", "@composedb/client": "^0.5.0", - "@datamodels/identity-profile-basic": "^0.2.0", - "@didtools/pkh-ethereum": "^0.4.1", - "did-session": "^2.0.1", "dids": "^4.0.4", "graphql": "^16.8.0", - "prettier": "^3.0.3" + "key-did-provider-ed25519": "^3.0.2", + "ora": "^7.0.1", + "prettier": "^3.0.3", + "uint8arrays": "^4.0.6" }, "devDependencies": { "@ceramicnetwork/cli": "^2.35.0", @@ -24,11 +24,13 @@ "@composedb/cli": "^0.5.0", "@composedb/devtools": "^0.5.0", "@composedb/devtools-node": "^0.5.0", - "@composedb/graphql-scalars": "^0.5.0", "@composedb/types": "^0.5.0", "@typescript-eslint/eslint-plugin": "^6.9.1", "@typescript-eslint/parser": "^6.9.1", "eslint": "^8.48.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.1", + "husky": "^8.0.3", "key-did-resolver": "^3.0.0", "typescript": "^5.2.2", "vite-tsconfig-paths": "^4.2.1", @@ -879,17 +881,6 @@ "node": ">=12" } }, - "node_modules/@datamodels/identity-profile-basic": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@datamodels/identity-profile-basic/-/identity-profile-basic-0.2.0.tgz", - "integrity": "sha512-Xk+Az0a74GoQDP7HbTJc7bsf3S92IQaRpMkCokrVM1C04zjO7jN76Cs3KSKzHPtFsdO6QsVH5mSQBCrF2kesKw==", - "dependencies": { - "@glazed/types": "^0.2.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/@datastructures-js/heap": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/@datastructures-js/heap/-/heap-4.3.2.tgz", @@ -964,20 +955,6 @@ "node": ">=14.14" } }, - "node_modules/@didtools/key-webcrypto": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@didtools/key-webcrypto/-/key-webcrypto-0.1.1.tgz", - "integrity": "sha512-xoyOOv8WHJOa28fjNtubyBubMrCna1oLFR0Ony91XgbkeUH4Vs4Ju/Fi2g8RUaX4oPCulNMzcjRTW+Naa4fvfg==", - "dependencies": { - "fast-json-stable-stringify": "^2.1.0", - "rpc-utils": "^0.6.2", - "uint8arrays": "^4.0.3", - "varint": "^6.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/@didtools/pkh-ethereum": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@didtools/pkh-ethereum/-/pkh-ethereum-0.4.1.tgz", @@ -2172,125 +2149,6 @@ "dev": true, "optional": true }, - "node_modules/@glazed/types": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@glazed/types/-/types-0.2.0.tgz", - "integrity": "sha512-NPZRNoF9u1RhwvZzAGFgByYrwED45mIqTa8712/mmJ6scEZU2HfuH74kS3bhwgFAu8efnpoFp8TVIX4AwGfSiA==", - "dependencies": { - "ajv": "^8.10.0", - "dids": "^3.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@glazed/types/node_modules/@didtools/cacao": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@didtools/cacao/-/cacao-1.2.0.tgz", - "integrity": "sha512-y0nMgV8DL0jgHUq0uhjMqrW9p79PopQnugLWx02tss+iR0ahON2cfal20+eFx2p3kXtvaL8U+iByrjmyuokj+A==", - "dependencies": { - "@ipld/dag-cbor": "^7.0.1", - "apg-js": "^4.1.1", - "caip": "^1.1.0", - "multiformats": "^9.5.1", - "uint8arrays": "^4.0.2" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@glazed/types/node_modules/@didtools/pkh-ethereum": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@didtools/pkh-ethereum/-/pkh-ethereum-0.0.1.tgz", - "integrity": "sha512-2hDt1f60WXUNWMVS9S9b0pmXl78ivkVxZJHeyBUkbz7O7To1rHvlgvJ0gFJ3sKVemI1llpClzwd3PEjZfGwiUw==", - "dependencies": { - "@didtools/cacao": "^1.0.0", - "@ethersproject/wallet": "^5.7.0", - "@stablelib/random": "^1.0.2", - "caip": "^1.1.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@glazed/types/node_modules/bech32": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" - }, - "node_modules/@glazed/types/node_modules/dag-jose-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dag-jose-utils/-/dag-jose-utils-2.0.0.tgz", - "integrity": "sha512-vE6EyhjSh+dfr8hbs/gLk0v98h2ekjy6r6pXvmB4SvO6awalt95LEetG0QDh5rmMYE3FO8ynp3xrCYsAHHZOlg==", - "dependencies": { - "@ipld/dag-cbor": "^7.0.1", - "multiformats": "^9.5.1" - } - }, - "node_modules/@glazed/types/node_modules/did-jwt": { - "version": "6.11.6", - "resolved": "https://registry.npmjs.org/did-jwt/-/did-jwt-6.11.6.tgz", - "integrity": "sha512-OfbWknRxJuUqH6Lk0x+H1FsuelGugLbBDEwsoJnicFOntIG/A4y19fn0a8RLxaQbWQ5gXg0yDq5E2huSBiiXzw==", - "dependencies": { - "@stablelib/ed25519": "^1.0.2", - "@stablelib/random": "^1.0.1", - "@stablelib/sha256": "^1.0.1", - "@stablelib/x25519": "^1.0.2", - "@stablelib/xchacha20poly1305": "^1.0.1", - "bech32": "^2.0.0", - "canonicalize": "^2.0.0", - "did-resolver": "^4.0.0", - "elliptic": "^6.5.4", - "js-sha3": "^0.8.0", - "multiformats": "^9.6.5", - "uint8arrays": "^3.0.0" - } - }, - "node_modules/@glazed/types/node_modules/did-jwt/node_modules/uint8arrays": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz", - "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/@glazed/types/node_modules/dids": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/dids/-/dids-3.4.0.tgz", - "integrity": "sha512-hXHkOTL9E5R4rbQwDVOktiiEq57Y6yWOEYjev1ojOpMr2Rkx9g8bw0v6BQIsbPB94aaYxUCtaejNl2FrublfiA==", - "dependencies": { - "@didtools/cacao": "^1.0.0", - "@didtools/pkh-ethereum": "^0.0.1", - "@stablelib/random": "^1.0.1", - "dag-jose-utils": "^2.0.0", - "did-jwt": "^6.0.0", - "did-resolver": "^3.1.5", - "multiformats": "^9.4.10", - "rpc-utils": "^0.6.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@glazed/types/node_modules/dids/node_modules/did-resolver": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/did-resolver/-/did-resolver-3.2.2.tgz", - "integrity": "sha512-Eeo2F524VM5N3W4GwglZrnul2y6TLTwMQP3In62JdG34NZoqihYyOZLk+5wUW8sSgvIYIcJM8Dlt3xsdKZZ3tg==" - }, - "node_modules/@glazed/types/node_modules/dids/node_modules/uint8arrays": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz", - "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/@glazed/types/node_modules/multiformats": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==" - }, "node_modules/@graphql-tools/batch-delegate": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@graphql-tools/batch-delegate/-/batch-delegate-9.0.0.tgz", @@ -3699,6 +3557,26 @@ "node": ">=14" } }, + "node_modules/@pkgr/utils": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", + "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "fast-glob": "^3.3.0", + "is-glob": "^4.0.3", + "open": "^9.1.0", + "picocolors": "^1.0.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@polkadot/networks": { "version": "7.9.2", "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-7.9.2.tgz", @@ -4054,11 +3932,6 @@ "node-fetch": "^2.6.1" } }, - "node_modules/@stablelib/aead": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/aead/-/aead-1.0.1.tgz", - "integrity": "sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg==" - }, "node_modules/@stablelib/binary": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@stablelib/binary/-/binary-1.0.1.tgz", @@ -4078,42 +3951,11 @@ "@stablelib/wipe": "^1.0.1" } }, - "node_modules/@stablelib/bytes": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/bytes/-/bytes-1.0.1.tgz", - "integrity": "sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ==" - }, - "node_modules/@stablelib/chacha": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/chacha/-/chacha-1.0.1.tgz", - "integrity": "sha512-Pmlrswzr0pBzDofdFuVe1q7KdsHKhhU24e8gkEwnTGOmlC7PADzLVxGdn2PoNVBBabdg0l/IfLKg6sHAbTQugg==", - "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/chacha20poly1305": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/chacha20poly1305/-/chacha20poly1305-1.0.1.tgz", - "integrity": "sha512-MmViqnqHd1ymwjOQfghRKw2R/jMIGT3wySN7cthjXCBdO+qErNPUBnRzqNpnvIwg7JBCg3LdeCZZO4de/yEhVA==", - "dependencies": { - "@stablelib/aead": "^1.0.1", - "@stablelib/binary": "^1.0.1", - "@stablelib/chacha": "^1.0.1", - "@stablelib/constant-time": "^1.0.1", - "@stablelib/poly1305": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/constant-time/-/constant-time-1.0.1.tgz", - "integrity": "sha512-tNOs3uD0vSJcK6z1fvef4Y+buN7DXhzHDPqRLSXUel1UfqMB1PWNsnnAezrKfEwTLpN0cGH2p9NNjs6IqeD0eg==" - }, "node_modules/@stablelib/ed25519": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@stablelib/ed25519/-/ed25519-1.0.3.tgz", "integrity": "sha512-puIMWaX9QlRsbhxfDc5i+mNPMY+0TmQEskunY1rZEBPi1acBCVQAhnsk/1Hk50DGPtVsZtAWQg4NHGlVaO9Hqg==", + "dev": true, "dependencies": { "@stablelib/random": "^1.0.2", "@stablelib/sha512": "^1.0.1", @@ -4136,23 +3978,6 @@ "resolved": "https://registry.npmjs.org/@stablelib/int/-/int-1.0.1.tgz", "integrity": "sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==" }, - "node_modules/@stablelib/keyagreement": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/keyagreement/-/keyagreement-1.0.1.tgz", - "integrity": "sha512-VKL6xBwgJnI6l1jKrBAfn265cspaWBPAPEc62VBQrWHLqVgNRE09gQ/AnOEyKUWrrqfD+xSQ3u42gJjLDdMDQg==", - "dependencies": { - "@stablelib/bytes": "^1.0.1" - } - }, - "node_modules/@stablelib/poly1305": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/poly1305/-/poly1305-1.0.1.tgz", - "integrity": "sha512-1HlG3oTSuQDOhSnLwJRKeTRSAdFNVB/1djy2ZbS35rBSJ/PFqx9cf9qatinWghC2UbfOYD8AcrtbUQl8WoxabA==", - "dependencies": { - "@stablelib/constant-time": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, "node_modules/@stablelib/random": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@stablelib/random/-/random-1.0.2.tgz", @@ -4176,6 +4001,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@stablelib/sha512/-/sha512-1.0.1.tgz", "integrity": "sha512-13gl/iawHV9zvDKciLo1fQ8Bgn2Pvf7OV6amaRVKiq3pjQ3UmEpXxWiAfV8tYjUpeZroBxtyrwtdooQT/i3hzw==", + "dev": true, "dependencies": { "@stablelib/binary": "^1.0.1", "@stablelib/hash": "^1.0.1", @@ -4198,38 +4024,6 @@ "resolved": "https://registry.npmjs.org/@stablelib/wipe/-/wipe-1.0.1.tgz", "integrity": "sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==" }, - "node_modules/@stablelib/x25519": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@stablelib/x25519/-/x25519-1.0.3.tgz", - "integrity": "sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw==", - "dependencies": { - "@stablelib/keyagreement": "^1.0.1", - "@stablelib/random": "^1.0.2", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/xchacha20": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/xchacha20/-/xchacha20-1.0.1.tgz", - "integrity": "sha512-1YkiZnFF4veUwBVhDnDYwo6EHeKzQK4FnLiO7ezCl/zu64uG0bCCAUROJaBkaLH+5BEsO3W7BTXTguMbSLlWSw==", - "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/chacha": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/xchacha20poly1305": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/xchacha20poly1305/-/xchacha20poly1305-1.0.1.tgz", - "integrity": "sha512-B1Abj0sMJ8h3HNmGnJ7vHBrAvxuNka6cJJoZ1ILN7iuacXp7sUYcgOVEOTLWj+rtQMpspY9tXSCRLPmN1mQNWg==", - "dependencies": { - "@stablelib/aead": "^1.0.1", - "@stablelib/chacha20poly1305": "^1.0.1", - "@stablelib/constant-time": "^1.0.1", - "@stablelib/wipe": "^1.0.1", - "@stablelib/xchacha20": "^1.0.1" - } - }, "node_modules/@stacks/common": { "version": "6.8.1", "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", @@ -5316,11 +5110,6 @@ "node": ">= 8" } }, - "node_modules/apg-js": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/apg-js/-/apg-js-4.2.1.tgz", - "integrity": "sha512-S3unf9jb9XrhmZYC27L5yits1p/+HqN6lksrkqKEv1U0Ytu+ENkIkOMV5+iutFjBaY9JTUCDQFS1svHsy3uNZA==" - }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -5528,6 +5317,15 @@ "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", "dev": true }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, "node_modules/bigi": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/bigi/-/bigi-1.4.2.tgz", @@ -5538,6 +5336,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/bigint-mod-arith/-/bigint-mod-arith-3.3.1.tgz", "integrity": "sha512-pX/cYW3dCa87Jrzv6DAr8ivbbJRzEX5yGhdt8IutnX/PCIXfpx+mabWNK/M8qqh+zQ0J3thftUBHW0ByuUlG0w==", + "dev": true, "engines": { "node": ">=10.4.0" } @@ -5630,7 +5429,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", - "dev": true, "dependencies": { "buffer": "^6.0.3", "inherits": "^2.0.4", @@ -5725,6 +5523,18 @@ "base-x": "^3.0.2" } }, + "node_modules/bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.44" + }, + "engines": { + "node": ">= 5.10.0" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -5898,6 +5708,21 @@ "node": ">=0.2.0" } }, + "node_modules/bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "dependencies": { + "run-applescript": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -6431,7 +6256,6 @@ "version": "2.9.1", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", - "dev": true, "engines": { "node": ">=6" }, @@ -6879,6 +6703,96 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "dev": true, + "dependencies": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "dependencies": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/default-browser/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/default-browser/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/defer-to-connect": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", @@ -6944,6 +6858,18 @@ "node": ">= 0.4" } }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/delay": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", @@ -7019,24 +6945,6 @@ "resolved": "https://registry.npmjs.org/did-resolver/-/did-resolver-4.1.0.tgz", "integrity": "sha512-S6fWHvCXkZg2IhS4RcVHxwuyVejPR7c+a4Go0xbQ9ps5kILa8viiYQgrM4gfTyeTjJ0ekgJH9gk/BawTpmkbZA==" }, - "node_modules/did-session": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/did-session/-/did-session-2.1.1.tgz", - "integrity": "sha512-HWpMKE3iAFp3JcAauQIh4fT7KkwVEiGk6N3wHJQ/ThqDyBlq65acXQzIYiwVMd8lAJmXo9EsAQRTmyuzbIUtLw==", - "dependencies": { - "@ceramicnetwork/stream-tile": "^2.21.0", - "@didtools/key-webcrypto": "^0.1.1", - "@stablelib/random": "^1.0.1", - "caip": "^1.1.0", - "dids": "^4.0.3", - "key-did-provider-ed25519": "^3.0.1", - "key-did-resolver": "^3.0.0", - "uint8arrays": "^4.0.3" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/dids": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/dids/-/dids-4.0.4.tgz", @@ -7181,8 +7089,7 @@ "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/ecurve": { "version": "1.0.5", @@ -7622,6 +7529,47 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-prettier": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", + "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz", + "integrity": "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.5" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -7950,6 +7898,12 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", @@ -8910,6 +8864,21 @@ "ms": "^2.0.0" } }, + "node_modules/husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/hyperlinker": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hyperlinker/-/hyperlinker-1.0.0.tgz", @@ -9512,11 +9481,43 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-interactive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -9613,7 +9614,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -9926,6 +9926,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/key-did-resolver/-/key-did-resolver-3.0.0.tgz", "integrity": "sha512-IyEq64AdS6lUwtn3YSvGpu7KAGA2x5+fjRCUIa8+ccSLmWrODV/ICM5aa6hHV/19EPWef8/e322r9sQJJ6/3qA==", + "dev": true, "dependencies": { "@stablelib/ed25519": "^1.0.2", "bigint-mod-arith": "^3.1.0", @@ -11756,6 +11757,7 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/nist-weierstrauss/-/nist-weierstrauss-1.6.1.tgz", "integrity": "sha512-FpjCOnPV/s3ZVIkeldCVSml2K4lruabPbBgoEitpCK1JL0KTVoWb56CFTU6rZn5i6VqAjdwcOp0FDwJACPmeFA==", + "dev": true, "dependencies": { "multiformats": "^9.6.5", "uint8arrays": "^2.1.4" @@ -11764,12 +11766,14 @@ "node_modules/nist-weierstrauss/node_modules/multiformats": { "version": "9.9.0", "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==" + "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", + "dev": true }, "node_modules/nist-weierstrauss/node_modules/uint8arrays": { "version": "2.1.10", "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.10.tgz", "integrity": "sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A==", + "dev": true, "dependencies": { "multiformats": "^9.4.2" } @@ -12098,6 +12102,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dev": true, + "dependencies": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/opencollective-postinstall": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", @@ -12128,7 +12150,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/ora/-/ora-7.0.1.tgz", "integrity": "sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==", - "dev": true, "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^4.0.0", @@ -12151,7 +12172,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "engines": { "node": ">=12" }, @@ -12163,7 +12183,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -12175,7 +12194,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dev": true, "dependencies": { "restore-cursor": "^4.0.0" }, @@ -12189,14 +12207,12 @@ "node_modules/ora/node_modules/emoji-regex": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" }, "node_modules/ora/node_modules/log-symbols": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", - "dev": true, "dependencies": { "chalk": "^5.0.0", "is-unicode-supported": "^1.1.0" @@ -12212,7 +12228,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { "node": ">=6" } @@ -12221,7 +12236,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -12236,7 +12250,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "dev": true, "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -12252,7 +12265,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-6.1.0.tgz", "integrity": "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==", - "dev": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^10.2.1", @@ -12269,7 +12281,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -12977,6 +12988,18 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -13274,7 +13297,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -13541,6 +13563,110 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-applescript/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/run-applescript/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-applescript/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/run-applescript/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/run-applescript/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/run-applescript/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-applescript/node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -13953,8 +14079,7 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/slash": { "version": "3.0.0", @@ -14143,7 +14268,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", - "dev": true, "dependencies": { "bl": "^5.0.0" }, @@ -14212,7 +14336,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -14355,6 +14478,22 @@ "node": ">=0.10.0" } }, + "node_modules/synckit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dev": true, + "dependencies": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/tar": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", @@ -14635,6 +14774,18 @@ "node": ">=14.0.0" } }, + "node_modules/titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", @@ -14984,6 +15135,15 @@ "node": ">= 0.8" } }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/unzip-stream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/unzip-stream/-/unzip-stream-0.3.1.tgz", @@ -15078,8 +15238,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utils-merge": { "version": "1.0.1", diff --git a/package.json b/package.json index 0920eb4..24bf3bd 100644 --- a/package.json +++ b/package.json @@ -1,27 +1,31 @@ { - "name": "desci-composites", + "name": "desci-composedb", "version": "1.0.0", - "description": "", + "description": "A reference protocol implementation on Ceramic and ComposeDB", + "license": "MIT", + "author": "Edvard Hübinette", "scripts": { - "generate": "node scripts/commands.mjs", + "generate": "node scripts/generate.mjs", "dev": "node scripts/run.mjs", "ceramic": "ceramic daemon --config composedb.config.json", "kill": "pkill --full \"ceramic daemon|ipfs daemon\"", - "test": "vitest --run --config vitest.config.ts" + "test": "vitest --run --config vitest.config.ts", + "lint": "eslint . --fix", + "prepare": "husky install" }, - "license": "MIT", - "author": "Edvard Hübinette", "devDependencies": { "@ceramicnetwork/cli": "^2.35.0", "@ceramicnetwork/streamid": "^2.17.0", "@composedb/cli": "^0.5.0", "@composedb/devtools": "^0.5.0", "@composedb/devtools-node": "^0.5.0", - "@composedb/graphql-scalars": "^0.5.0", "@composedb/types": "^0.5.0", "@typescript-eslint/eslint-plugin": "^6.9.1", "@typescript-eslint/parser": "^6.9.1", "eslint": "^8.48.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.1", + "husky": "^8.0.3", "key-did-resolver": "^3.0.0", "typescript": "^5.2.2", "vite-tsconfig-paths": "^4.2.1", @@ -30,11 +34,11 @@ "dependencies": { "@ceramicnetwork/http-client": "^2.31.0", "@composedb/client": "^0.5.0", - "@datamodels/identity-profile-basic": "^0.2.0", - "@didtools/pkh-ethereum": "^0.4.1", - "did-session": "^2.0.1", "dids": "^4.0.4", "graphql": "^16.8.0", - "prettier": "^3.0.3" + "key-did-provider-ed25519": "^3.0.2", + "ora": "^7.0.1", + "prettier": "^3.0.3", + "uint8arrays": "^4.0.6" } } diff --git a/scripts/commands.mjs b/scripts/generate.mjs similarity index 97% rename from scripts/commands.mjs rename to scripts/generate.mjs index 2375890..ef96a24 100644 --- a/scripts/commands.mjs +++ b/scripts/generate.mjs @@ -10,7 +10,7 @@ const PWD = process.cwd(); const CONFIG_PATH = `${PWD}/composedb.config.json`; const SEED_PATH = `${PWD}/admin_seed.txt`; -export const RunCommands = async () => { +export const Generate = async () => { const newSeed = () => { const raw = new Uint8Array(randomBytes(32)); return toString(raw, "base16"); @@ -82,4 +82,4 @@ export const RunCommands = async () => { } }; -RunCommands(); +Generate(); diff --git a/scripts/graphiql.mjs b/scripts/graphiql.mjs index d2c1c27..2b01f16 100644 --- a/scripts/graphiql.mjs +++ b/scripts/graphiql.mjs @@ -12,13 +12,10 @@ const server = await serveEncodedDefinition({ console.log(`Server started on port ${server.port}`); -process.on("SIGTERM", () => { - server.close(() => { - console.log("Server stopped"); +for (const signal in ["SIGTERM", "SIGINT"]) { + process.on(signal, () => { + server.close(() => { + console.log("Server stopped"); + }); }); -}); -process.on("SIGINT", () => { - server.close(() => { - console.log("Server stopped"); - }); -}); +}; diff --git a/scripts/run.mjs b/scripts/run.mjs index ca33536..94ace56 100644 --- a/scripts/run.mjs +++ b/scripts/run.mjs @@ -36,9 +36,9 @@ const bootstrap = async () => { }; const graphiql = async () => { - spinner.info("[GraphiQL] starting graphiql"); + spinner.info("[GraphiQL] Starting server"); const graphiql = spawn("node", ["./scripts/graphiql.mjs"]); - spinner.succeed("[GraphiQL] graphiql started"); + spinner.succeed("[GraphiQL] Server started"); graphiql.stdout.on("data", (buffer) => { console.log("[GraphiqQL]", buffer.toString()); }); @@ -65,12 +65,6 @@ const start = async () => { start(); -process.on("SIGTERM", () => { - ceramic.kill(); -}); -process.on("SIGINT", () => { - ceramic.kill(); -}); -process.on("beforeExit", () => { - ceramic.kill(); -}); +for (const signal in ["SIGTERM", "SIGINT", "beforeExit"]) { + process.on(signal, () => ceramic.kill()); +}; diff --git a/test/root.spec.ts b/test/root.spec.ts index 1e15999..6231875 100644 --- a/test/root.spec.ts +++ b/test/root.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { ComposeClient } from "@composedb/client"; import { definition } from "../src/__generated__/definition"; import { RuntimeCompositeDefinition } from "@composedb/types"; @@ -977,24 +978,28 @@ describe("ComposeDB nodes", () => { title: "Title 0", manifest: A_CID, }; + + // Create version 0 const { streamID } = await mutationCreateResearchObject( composeClient, data, ); - await waitAndSync(streamID); - const V1 = await mutationUpdateResearchObject(composeClient, { + + // Create version 1 + await mutationUpdateResearchObject(composeClient, { id: streamID, title: "Title 1", }); - await waitAndSync(streamID); - const V2 = await mutationUpdateResearchObject(composeClient, { + + // Create version 2 + await mutationUpdateResearchObject(composeClient, { id: streamID, title: "Title 2", }); - await waitAndSync(streamID); + const versionToResolve = 1; const stream = await ceramic.loadStream(streamID); @@ -1029,7 +1034,7 @@ const waitAndSync = async (streamID: string, timeout?: number) => { await stream.sync(); }; -const debugStream = async (streamID: string, message: string) => { +const _debugStream = async (streamID: string, message: string) => { const stream = await ceramic.loadStream(streamID); console.log(`*********** [START] ${message} ***********`); console.log(`LOG:`, JSON.stringify(stream.state.log, undefined, 2)); diff --git a/types/index.ts b/types/index.ts index 097ae2c..de8e68e 100644 --- a/types/index.ts +++ b/types/index.ts @@ -95,7 +95,7 @@ export type ContributorRelation = { researchObjectID: string; researchObjectVersion: string; - revoked: Boolean; + revoked: boolean; }; export type ReferenceRelation = { @@ -107,7 +107,7 @@ export type ReferenceRelation = { fromID: string; fromVersion: string; - revoked: Boolean; + revoked: boolean; }; export type ResearchField = { diff --git a/utils/index.ts b/utils/index.ts deleted file mode 100644 index 5f67e3a..0000000 --- a/utils/index.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { DIDSession } from "did-session"; -import { EthereumWebAuth, getAccountId } from "@didtools/pkh-ethereum"; -import type { CeramicApi } from "@ceramicnetwork/common"; -import type { ComposeClient } from "@composedb/client"; - -// If you are relying on an injected provider this must be here otherwise you will have a type error. -declare global { - interface Window { - ethereum: any; - } -} - -/** - * Checks localStorage for a stored DID Session. If one is found we authenticate it, otherwise we create a new one. - * @returns Promise - The User's authenticated sesion. - */ -export const authenticateCeramic = async ( - ceramic: CeramicApi, - compose: ComposeClient, -) => { - const sessionStr = localStorage.getItem("did"); // for production you will want a better place than localStorage for your sessions. - let session; - - if (sessionStr) { - session = await DIDSession.fromSession(sessionStr); - } - - if (!session || (session.hasSession && session.isExpired)) { - if (window.ethereum === null || window.ethereum === undefined) { - throw new Error("No injected Ethereum provider found."); - } - - // We enable the ethereum provider to get the user's addresses. - const ethProvider = window.ethereum; - // request ethereum accounts. - const addresses = await ethProvider.enable({ - method: "eth_requestAccounts", - }); - const accountId = await getAccountId(ethProvider, addresses[0]); - const authMethod = await EthereumWebAuth.getAuthMethod( - ethProvider, - accountId, - ); - - /** - * Create DIDSession & provide capabilities that we want to access. - * @NOTE: Any production applications will want to provide a more complete list of capabilities. - * This is not done here to allow you to add more datamodels to your application. - */ - // TODO: update resources to only provide access to our composities - session = await DIDSession.authorize(authMethod, { - resources: ["ceramic://*"], - }); - // Set the session in localStorage. - localStorage.setItem("did", session.serialize()); - } - - // Set our Ceramic DID to be our session DID. - compose.setDID(session.did); - ceramic.did = session.did; - return session; -}; diff --git a/utils/populate.tsx b/utils/populate.tsx index d3b12cc..883d9d4 100644 --- a/utils/populate.tsx +++ b/utils/populate.tsx @@ -134,19 +134,19 @@ const loadTemplateData = async (composeClient: ComposeClient) => { ); streamIndex[seed].contributorRelations = await Promise.all( - template.contributorRelations.map((contTemplate: any) => + template.contributorRelations.map((contTemplate) => loadContributorRelation(contTemplate, streamIndex, composeClient), ), ); streamIndex[seed].referenceRelations = await Promise.all( - template.referenceRelations.map((refTemplate: any) => + template.referenceRelations.map((refTemplate) => loadReferenceRelation(refTemplate, streamIndex, composeClient), ), ); streamIndex[seed].researchFieldRelations = await Promise.all( - template.researchFieldRelations.map((fieldRelTemplate: any) => + template.researchFieldRelations.map((fieldRelTemplate) => loadResearchFieldRelation(fieldRelTemplate, streamIndex, composeClient), ), ); @@ -185,7 +185,7 @@ const loadResearchObject = async ( // Possibly create manifest components if such exist const components = await Promise.all( - roTemplate.components.map((c: any) => + roTemplate.components.map((c) => mutationCreateResearchComponent(composeClient, { ...c, researchObjectID: researchObject.streamID, @@ -289,5 +289,6 @@ const loadAnnotation = async ( }; // Oblivious to human faults, enjoy the footgun +/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ const recursePathToID = (object: any, path: ObjectPath): NodeIDs => path.length ? recursePathToID(object[path[0]], path.slice(1)) : object; diff --git a/utils/queries.ts b/utils/queries.ts index 145e6fa..af3d7b5 100644 --- a/utils/queries.ts +++ b/utils/queries.ts @@ -602,11 +602,11 @@ async function genericCreate( composeClient: ComposeClient, inputs: T, /** At least verify all keys exist in T, can still forget one though. - * Can't require it fully because some props are not allowed in the mutation. + * Can't spec it fully because some props are not allowed in the mutation. */ gqlTypes: Partial>, mutationName: string, - /** Skip timeout for single accountRelation entities */ + /** Skip timeout for accountRelation SINGLE entities */ noTimeout?: boolean, ): Promise { const [params, content] = getQueryFields( @@ -628,6 +628,7 @@ async function genericCreate( } }`, inputs, + /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ )) as any; assertMutationErrors(response, mutationName); const nodeIDs: NodeIDs = { @@ -665,6 +666,7 @@ async function genericUpdate( } }`, inputs, + /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ )) as any; assertMutationErrors(response, mutationName); const nodeIDs: NodeIDs = { @@ -674,11 +676,10 @@ async function genericUpdate( return nodeIDs; } -type SimpleMutationResult = Pick; -type SimpleQueryResult = Pick; +type SimpleExecutionResult = Pick; const assertMutationErrors = ( - result: SimpleMutationResult, + result: SimpleExecutionResult, queryDescription: string, ) => { if (result.errors) { @@ -688,7 +689,7 @@ const assertMutationErrors = ( }; const assertQueryErrors = ( - result: SimpleQueryResult, + result: SimpleExecutionResult, queryDescription: string, ) => { if (result.errors || !result.data) { From dfe9edb3834bad294144133c3446f58200b6fe9d Mon Sep 17 00:00:00 2001 From: m0ar Date: Thu, 2 Nov 2023 10:15:14 +0100 Subject: [PATCH 4/9] Switch to node modules, fix file structure --- Makefile | 7 +- composites/02-organization.graphql | 8 -- .../{05-claim.graphql => 1-claim.graphql} | 0 .../{00-profile.graphql => 1-profile.graphql} | 0 ...hField.graphql => 1-researchField.graphql} | 0 ...bject.graphql => 1-researchObject.graphql} | 0 ...nnotation.graphql => 2-annotation.graphql} | 0 ...estation.graphql => 2-attestation.graphql} | 0 ....graphql => 2-contributorRelation.graphql} | 0 ...on.graphql => 2-referenceRelation.graphql} | 0 ...nt.graphql => 2-researchComponent.graphql} | 0 ...raphql => 2-researchFieldRelation.graphql} | 0 ....graphql => 3-additionalRelations.graphql} | 0 package-lock.json | 28 +++++ package.json | 7 +- scripts/composites.mjs | 100 ++++++++-------- scripts/run.mjs | 4 +- utils/populate.tsx => src/populate.ts | 108 ++++++++++++------ {utils => src}/queries.ts | 4 +- types/index.ts => src/types.ts | 0 {utils => template-data}/templateData.d.ts | 27 +++-- .../template_data.json | 89 ++++++++------- test/root.spec.ts | 10 +- tsconfig.json | 33 +++--- 24 files changed, 254 insertions(+), 171 deletions(-) delete mode 100644 composites/02-organization.graphql rename composites/{05-claim.graphql => 1-claim.graphql} (100%) rename composites/{00-profile.graphql => 1-profile.graphql} (100%) rename composites/{001-researchField.graphql => 1-researchField.graphql} (100%) rename composites/{01-researchObject.graphql => 1-researchObject.graphql} (100%) rename composites/{11-annotation.graphql => 2-annotation.graphql} (100%) rename composites/{06-attestation.graphql => 2-attestation.graphql} (100%) rename composites/{09-contributorRelation.graphql => 2-contributorRelation.graphql} (100%) rename composites/{08-referenceRelation.graphql => 2-referenceRelation.graphql} (100%) rename composites/{07-researchComponent.graphql => 2-researchComponent.graphql} (100%) rename composites/{10-researchFieldRelation.graphql => 2-researchFieldRelation.graphql} (100%) rename composites/{additional-relations.graphql => 3-additionalRelations.graphql} (100%) rename utils/populate.tsx => src/populate.ts (75%) rename {utils => src}/queries.ts (99%) rename types/index.ts => src/types.ts (100%) rename {utils => template-data}/templateData.d.ts (73%) rename template_data.json => template-data/template_data.json (81%) diff --git a/Makefile b/Makefile index f877a8c..5d89732 100644 --- a/Makefile +++ b/Makefile @@ -7,11 +7,16 @@ clean-test: rm -rf local-data/ceramic-test test: clean-test + if pgrep --ignore-ancestors --count --full "ceramic daemon|ipfs daemon"; then \ + echo "Refusing to clobber running daemons"; exit 1; \ + fi + sed 's|local-data/ceramic|local-data/ceramic-test|' composedb.config.json \ > test.config.json npx ceramic daemon --config test.config.json &>/dev/null & sleep 5 - node scripts/composites.mjs + + npm run deployComposites # Ensure daemons dead, without losing test exit code for CI if npm test; then \ npm run kill; true; \ diff --git a/composites/02-organization.graphql b/composites/02-organization.graphql deleted file mode 100644 index b1f3505..0000000 --- a/composites/02-organization.graphql +++ /dev/null @@ -1,8 +0,0 @@ -type Organization - @createModel(accountRelation: LIST, description: "An organization") - @createIndex(fields: [{ path: "name" }]) { - owner: DID! @documentAccount - version: CommitID! @documentVersion - name: String! @string(maxLength: 250) - members: [DID] @list(maxLength: 100000) -} diff --git a/composites/05-claim.graphql b/composites/1-claim.graphql similarity index 100% rename from composites/05-claim.graphql rename to composites/1-claim.graphql diff --git a/composites/00-profile.graphql b/composites/1-profile.graphql similarity index 100% rename from composites/00-profile.graphql rename to composites/1-profile.graphql diff --git a/composites/001-researchField.graphql b/composites/1-researchField.graphql similarity index 100% rename from composites/001-researchField.graphql rename to composites/1-researchField.graphql diff --git a/composites/01-researchObject.graphql b/composites/1-researchObject.graphql similarity index 100% rename from composites/01-researchObject.graphql rename to composites/1-researchObject.graphql diff --git a/composites/11-annotation.graphql b/composites/2-annotation.graphql similarity index 100% rename from composites/11-annotation.graphql rename to composites/2-annotation.graphql diff --git a/composites/06-attestation.graphql b/composites/2-attestation.graphql similarity index 100% rename from composites/06-attestation.graphql rename to composites/2-attestation.graphql diff --git a/composites/09-contributorRelation.graphql b/composites/2-contributorRelation.graphql similarity index 100% rename from composites/09-contributorRelation.graphql rename to composites/2-contributorRelation.graphql diff --git a/composites/08-referenceRelation.graphql b/composites/2-referenceRelation.graphql similarity index 100% rename from composites/08-referenceRelation.graphql rename to composites/2-referenceRelation.graphql diff --git a/composites/07-researchComponent.graphql b/composites/2-researchComponent.graphql similarity index 100% rename from composites/07-researchComponent.graphql rename to composites/2-researchComponent.graphql diff --git a/composites/10-researchFieldRelation.graphql b/composites/2-researchFieldRelation.graphql similarity index 100% rename from composites/10-researchFieldRelation.graphql rename to composites/2-researchFieldRelation.graphql diff --git a/composites/additional-relations.graphql b/composites/3-additionalRelations.graphql similarity index 100% rename from composites/additional-relations.graphql rename to composites/3-additionalRelations.graphql diff --git a/package-lock.json b/package-lock.json index e785009..bbdf43c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,8 @@ "eslint-plugin-prettier": "^5.0.1", "husky": "^8.0.3", "key-did-resolver": "^3.0.0", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", "typescript": "^5.2.2", "vite-tsconfig-paths": "^4.2.1", "vitest": "^0.34.5" @@ -9878,6 +9880,18 @@ "integrity": "sha512-5Nom9inkIMrtY992LMBBG1Zaekrc10JaRhyZgprwHBVMDtRgllTvzl0oBbg13wJsVZoSoFNNMaeIVQs0P04vsA==", "dev": true }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", @@ -14923,6 +14937,20 @@ } } }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", diff --git a/package.json b/package.json index 24bf3bd..8a061cc 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,12 @@ "description": "A reference protocol implementation on Ceramic and ComposeDB", "license": "MIT", "author": "Edvard Hübinette", + "type": "module", "scripts": { "generate": "node scripts/generate.mjs", - "dev": "node scripts/run.mjs", + "dev": "node --no-warnings=ExperimentalWarning scripts/run.mjs", + "deployComposites": "node scripts/composites.mjs", + "populate": "node --no-warnings=ExperimentalWarning --loader ts-node/esm src/populate.ts", "ceramic": "ceramic daemon --config composedb.config.json", "kill": "pkill --full \"ceramic daemon|ipfs daemon\"", "test": "vitest --run --config vitest.config.ts", @@ -27,6 +30,8 @@ "eslint-plugin-prettier": "^5.0.1", "husky": "^8.0.3", "key-did-resolver": "^3.0.0", + "tsconfig-paths": "^4.2.0", + "ts-node": "^10.9.1", "typescript": "^5.2.2", "vite-tsconfig-paths": "^4.2.1", "vitest": "^0.34.5" diff --git a/scripts/composites.mjs b/scripts/composites.mjs index 4df81c4..a1d6640 100644 --- a/scripts/composites.mjs +++ b/scripts/composites.mjs @@ -22,116 +22,119 @@ export const writeComposite = async (spinner) => { await authenticateAdmin(); spinner.info("writing composite to Ceramic"); - const profileComposite = await createComposite( - ceramic, - "./composites/00-profile.graphql", - ); + /** Collect streamID of each composite as it is created */ + const modelIDs = {}; - const researchFieldComposite = await createComposite( + const profileComposite = await createComposite( ceramic, - "./composites/001-researchField.graphql", + "./composites/1-profile.graphql", ); + modelIDs.profile = profileComposite.modelIDs[0]; - const researchObjComposite = await createComposite( + const researchObjectComposite = await createComposite( ceramic, - "./composites/01-researchObject.graphql", + "./composites/1-researchObject.graphql", ); + modelIDs.researchObject = researchObjectComposite.modelIDs[0]; - const orgComposite = await createComposite( + const researchFieldComposite = await createComposite( ceramic, - "./composites/02-organization.graphql", + "./composites/1-researchField.graphql", ); + modelIDs.researchField = researchFieldComposite.modelIDs[0]; const claimComposite = await createComposite( ceramic, - "./composites/05-claim.graphql", + "./composites/1-claim.graphql", ); + modelIDs.claim = claimComposite.modelIDs[0]; const attestationSchema = readFileSync( - "./composites/06-attestation.graphql", + "./composites/2-attestation.graphql", { encoding: "utf-8" }, - ).replace("$CLAIM_ID", claimComposite.modelIDs[0]); + ).replace("$CLAIM_ID", modelIDs.claim); const attestationComposite = await Composite.create({ ceramic, schema: attestationSchema, }); + modelIDs.attestation = attestationComposite.modelIDs[1]; - const componentSchema = readFileSync( - "./composites/07-researchComponent.graphql", + const researchComponentSchema = readFileSync( + "./composites/2-researchComponent.graphql", { encoding: "utf-8" }, - ).replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]); + ).replace("$RESEARCH_OBJECT_ID", modelIDs.researchObject); - const componentComposite = await Composite.create({ + const researchComponentComposite = await Composite.create({ ceramic, - schema: componentSchema, + schema: researchComponentSchema, }); + modelIDs.researchComponent = researchComponentComposite.modelIDs[1]; + const referenceRelationSchema = readFileSync( - "./composites/08-referenceRelation.graphql", + "./composites/2-referenceRelation.graphql", { encoding: "utf-8" }, - ).replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]); + ).replace("$RESEARCH_OBJECT_ID", modelIDs.researchObject); const referenceRelationComposite = await Composite.create({ ceramic, schema: referenceRelationSchema, }); + modelIDs.referenceRelation = referenceRelationComposite.modelIDs[1]; const contributorRelationSchema = readFileSync( - "./composites/09-contributorRelation.graphql", + "./composites/2-contributorRelation.graphql", { encoding: "utf-8" }, ) - .replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]) - .replace("$PROFILE_ID", profileComposite.modelIDs[0]); + .replace("$RESEARCH_OBJECT_ID", modelIDs.researchObject) + .replace("$PROFILE_ID", modelIDs.profile); const contributorRelationComposite = await Composite.create({ ceramic, schema: contributorRelationSchema, }); + modelIDs.contributorRelation = contributorRelationComposite.modelIDs[2]; const researchFieldRelationSchema = readFileSync( - "./composites/10-researchFieldRelation.graphql", + "./composites/2-researchFieldRelation.graphql", { encoding: "utf-8" }, ) - .replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]) - .replace("$RESEARCH_FIELD_ID", researchFieldComposite.modelIDs[0]); + .replace("$RESEARCH_OBJECT_ID", modelIDs.researchObject) + .replace("$RESEARCH_FIELD_ID", modelIDs.researchField); const researchFieldRelationComposite = await Composite.create({ ceramic, schema: researchFieldRelationSchema, }); + modelIDs.researchFieldRelation = researchFieldRelationComposite.modelIDs[2]; - const annotationSchema = readFileSync("./composites/11-annotation.graphql", { + const annotationSchema = readFileSync("./composites/2-annotation.graphql", { encoding: "utf-8", }) - .replace("$CLAIM_ID", claimComposite.modelIDs[0]) - .replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]); + .replace("$CLAIM_ID", modelIDs.claim) + .replace("$RESEARCH_OBJECT_ID", modelIDs.researchObject); const annotationComposite = await Composite.create({ ceramic, schema: annotationSchema, }); + modelIDs.annotation = annotationComposite.modelIDs[2]; const additionalRelationsSchema = readFileSync( - "./composites/additional-relations.graphql", + "./composites/3-additionalRelations.graphql", { encoding: "utf-8" }, ) - .replace("$ATTESTATION_ID", attestationComposite.modelIDs[1]) - .replace("$CLAIM_ID", claimComposite.modelIDs[0]) - .replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]) - .replace("$PROFILE_ID", profileComposite.modelIDs[0]) - .replace("$RESEARCH_COMPONENT_ID", componentComposite.modelIDs[1]) - .replace( - "$CONTRIBUTOR_RELATION_ID", - contributorRelationComposite.modelIDs[2], - ) - .replace("$REFERENCE_RELATION_ID", referenceRelationComposite.modelIDs[1]) - .replace("$RESEARCH_FIELD_ID", researchFieldComposite.modelIDs[0]) - .replace( - "$RESEARCH_FIELD_RELATION_ID", - researchFieldRelationComposite.modelIDs[2], - ) - .replace("$ANNOTATION_ID", annotationComposite.modelIDs[2]); + .replace("$ATTESTATION_ID", modelIDs.attestation) + .replace("$CLAIM_ID", modelIDs.claim) + .replace("$RESEARCH_OBJECT_ID", modelIDs.researchObject) + .replace("$PROFILE_ID", modelIDs.profile) + .replace("$RESEARCH_COMPONENT_ID", modelIDs.researchComponent) + .replace("$CONTRIBUTOR_RELATION_ID", modelIDs.contributorRelation) + .replace("$REFERENCE_RELATION_ID", modelIDs.referenceRelation) + .replace("$RESEARCH_FIELD_ID", modelIDs.researchField) + .replace("$RESEARCH_FIELD_RELATION_ID", modelIDs.researchFieldRelation) + .replace("$ANNOTATION_ID", modelIDs.annotation); const additionalRelationsComposite = await Composite.create({ ceramic, @@ -140,11 +143,10 @@ export const writeComposite = async (spinner) => { const composite = Composite.from([ profileComposite, - researchObjComposite, - orgComposite, + researchObjectComposite, claimComposite, attestationComposite, - componentComposite, + researchComponentComposite, additionalRelationsComposite, contributorRelationComposite, referenceRelationComposite, diff --git a/scripts/run.mjs b/scripts/run.mjs index 94ace56..391b3b3 100644 --- a/scripts/run.mjs +++ b/scripts/run.mjs @@ -63,8 +63,8 @@ const start = async () => { } }; -start(); - for (const signal in ["SIGTERM", "SIGINT", "beforeExit"]) { process.on(signal, () => ceramic.kill()); }; + +start(); diff --git a/utils/populate.tsx b/src/populate.ts similarity index 75% rename from utils/populate.tsx rename to src/populate.ts index 883d9d4..190258b 100644 --- a/utils/populate.tsx +++ b/src/populate.ts @@ -2,7 +2,6 @@ import KeyDIDResolver from "key-did-resolver"; import { Ed25519Provider } from "key-did-provider-ed25519"; import { DID } from "dids"; import { fromString } from "uint8arrays/from-string"; -import untypedTemplateData from "../template_data.json"; import { ComposeClient } from "@composedb/client"; import { mutationCreateAnnotation, @@ -15,11 +14,11 @@ import { mutationCreateResearchField, mutationCreateResearchFieldRelation, mutationCreateResearchObject, -} from "./queries"; +} from "./queries.js"; import { CeramicClient } from "@ceramicnetwork/http-client"; -import { definition } from "@/src/__generated__/definition"; +import { definition } from "./__generated__/definition.js"; import { RuntimeCompositeDefinition } from "@composedb/types"; -import { Annotation, Attestation, NodeIDs, ResearchObject } from "@/types"; +import { Annotation, Attestation, NodeIDs, ResearchComponent, ResearchObject } from "./types.js"; import { AnnotationTemplate, AttestationTemplate, @@ -27,9 +26,12 @@ import { DataTemplate, ObjectPath, ReferenceRelationTemplate, + ResearchComponentTemplate, ResearchFieldRelationTemplate, ResearchObjectTemplate, -} from "./templateData"; +} from "../template-data/templateData.js"; + +import untypedTemplateData from "../template-data/template_data.json" assert { type: "json" }; const templateData: DataTemplate = untypedTemplateData; @@ -46,13 +48,13 @@ const didFromSeed = async (seed: string) => { return did; }; -type ProfileIndexResults = { data: { profileIndex: { edges: [] } } }; +type ProfileIndexResult = { profileIndex: { edges: [] } }; export const loadIfUninitialised = async (ceramic: CeramicClient) => { const composeClient = new ComposeClient({ ceramic, definition: definition as RuntimeCompositeDefinition, }); - const firstProfile = (await composeClient.executeQuery(` + const firstProfile = await composeClient.executeQuery(` query { profileIndex(first: 1) { edges { @@ -62,9 +64,15 @@ export const loadIfUninitialised = async (ceramic: CeramicClient) => { } } } - `)) as ProfileIndexResults; + `); + + if (firstProfile.errors) { + console.error("Failed to query Ceramic:", JSON.stringify(firstProfile.errors, undefined, 2)); + console.error("Is the Ceramic node running?") + process.exit(1); + }; - if (firstProfile.data.profileIndex.edges.length === 0) { + if (firstProfile.data!.profileIndex.edges.length === 0) { console.log("Profile index empty, loading template data..."); await loadTemplateData(composeClient); } else { @@ -77,10 +85,8 @@ export const loadIfUninitialised = async (ceramic: CeramicClient) => { // Same shape as the template data, but with NodeIDs for each leaf type ActorDataNodeIDs = { profile?: NodeIDs; - researchObjects: { - IDs: NodeIDs; - components: NodeIDs[]; - }[]; + researchObjects: NodeIDs[]; + researchComponents: NodeIDs[]; claims: NodeIDs[]; researchFields: NodeIDs[]; attestations: NodeIDs[]; @@ -93,6 +99,7 @@ type ActorDataNodeIDs = { const freshActorRecord = (profile: NodeIDs): ActorDataNodeIDs => ({ profile, researchObjects: [], + researchComponents: [], claims: [], attestations: [], researchFields: [], @@ -133,6 +140,12 @@ const loadTemplateData = async (composeClient: ComposeClient) => { ), ); + streamIndex[seed].researchComponents = await Promise.all( + template.researchComponents.map((component) => + loadResearchComponent(component, streamIndex, composeClient), + ), + ); + streamIndex[seed].contributorRelations = await Promise.all( template.contributorRelations.map((contTemplate) => loadContributorRelation(contTemplate, streamIndex, composeClient), @@ -183,19 +196,29 @@ const loadResearchObject = async ( roProps, ); - // Possibly create manifest components if such exist - const components = await Promise.all( - roTemplate.components.map((c) => - mutationCreateResearchComponent(composeClient, { - ...c, - researchObjectID: researchObject.streamID, - researchObjectVersion: researchObject.commitID, - pathToNode: ".", - }), - ), - ); + return researchObject; +}; + +const loadResearchComponent = async ( + rcTemplate: ResearchComponentTemplate, + streamIndex: StreamIndex, + composeClient: ComposeClient, +): Promise => { + const { name, mimeType, dagNode, pathToNode, researchObjectPath, metadata } = + rcTemplate; + const researchObject = recursePathToID(streamIndex, researchObjectPath); + const component: ResearchComponent = { + name, + mimeType, + dagNode, + pathToNode, + researchObjectID: researchObject.streamID, + researchObjectVersion: researchObject.commitID + }; - return { IDs: researchObject, components }; + // Handle optionals + if (metadata) component.metadata = metadata; + return await mutationCreateResearchComponent(composeClient, component); }; const loadContributorRelation = async ( @@ -270,21 +293,40 @@ const loadAnnotation = async ( streamIndex: StreamIndex, composeClient: ComposeClient, ): Promise => { - const { comment, path, targetPath, claimPath } = annotationTemplate; - const target = recursePathToID(streamIndex, targetPath); + const { + comment, + researchObjectPath, + targetPath, + dagNode, + pathToNode, + locationOnFile, + claimPath, + metadataPayload, + } = annotationTemplate; + + const researchObject = recursePathToID(streamIndex, researchObjectPath); const annotation: Annotation = { - targetID: target.streamID, - targetVersion: target.commitID, comment, + researchObjectID: researchObject.streamID, + researchObjectVersion: researchObject.commitID, }; + if (targetPath) { + const target = recursePathToID(streamIndex, targetPath); + annotation.targetID = target.streamID; + annotation.targetVersion = target.commitID; + } if (claimPath) { const claim = recursePathToID(streamIndex, claimPath); annotation.claimID = claim.streamID; annotation.claimVersion = claim.commitID; } - if (path) { - annotation.path = path; - } + + // GraphQL queries dislike undefined + if (dagNode) annotation.dagNode = dagNode; + if (pathToNode) annotation.pathToNode = dagNode; + if (locationOnFile) annotation.locationOnFile = dagNode; + if (metadataPayload) annotation.metadataPayload = dagNode; + return mutationCreateAnnotation(composeClient, annotation); }; @@ -292,3 +334,5 @@ const loadAnnotation = async ( /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ const recursePathToID = (object: any, path: ObjectPath): NodeIDs => path.length ? recursePathToID(object[path[0]], path.slice(1)) : object; + +loadIfUninitialised(new CeramicClient("http://localhost:7007")); diff --git a/utils/queries.ts b/src/queries.ts similarity index 99% rename from utils/queries.ts rename to src/queries.ts index af3d7b5..4f63ee6 100644 --- a/utils/queries.ts +++ b/src/queries.ts @@ -12,7 +12,7 @@ import { Annotation, NodeIDs, ResearchField, -} from "../types"; +} from "./types.js"; import { ExecutionResult } from "graphql"; export const queryViewerId = async ( @@ -715,7 +715,7 @@ const getQueryFields = ( inputs: Record, ) => Object.keys(inputs) - .filter((p) => p !== "id") + .filter(p => p !== "id") .reduce<[string[], string[]]>( (acc, next) => [ [...acc[0], `$${next}: ${graphQLParamTypes[next]}`], diff --git a/types/index.ts b/src/types.ts similarity index 100% rename from types/index.ts rename to src/types.ts diff --git a/utils/templateData.d.ts b/template-data/templateData.d.ts similarity index 73% rename from utils/templateData.d.ts rename to template-data/templateData.d.ts index 1a19949..8a9bcd9 100644 --- a/utils/templateData.d.ts +++ b/template-data/templateData.d.ts @@ -1,23 +1,21 @@ +import { Profile, ResearchComponent } from "../src/types.js"; + export type Seed = string; // Address properties and array indices for indicating the future StreamID, // will be resolved to the actual stream when the template is instantiated export type ObjectPath = (string | number)[]; -export type ProfileTemplate = { - displayName: string; - orcid?: string; -}; +export type ProfileTemplate = Profile; -export type ComponentTemplate = { - name: string; - dagNode: string; - mimeType: string; -}; +export type ResearchComponentTemplate = Omit< + ResearchComponent, + "owner" | "version" | "researchObjectID" | "researchObjectVersion" +> & { researchObjectPath: ObjectPath }; export type ResearchObjectTemplate = { title: string; manifest: string; - components: ComponentTemplate[]; + metadata?: string; }; export type ClaimTemplate = { @@ -52,14 +50,19 @@ export type AttestationTemplate = { export type AnnotationTemplate = { comment: string; - path?: string; - targetPath: ObjectPath; + researchObjectPath: ObjectPath; + targetPath?: ObjectPath; + dagNode?: string; + pathToNode?: string; + locationOnFile?: string; claimPath?: ObjectPath; + metadataPayload?: string; }; export type ActorTemplate = { profile: ProfileTemplate; researchObjects: ResearchObjectTemplate[]; + researchComponents: ResearchComponentTemplate[]; claims: ClaimTemplate[]; researchFields: ResearchFieldTemplate[]; contributorRelations: ContributorRelationTemplate[]; diff --git a/template_data.json b/template-data/template_data.json similarity index 81% rename from template_data.json rename to template-data/template_data.json index d625a87..28edd96 100644 --- a/template_data.json +++ b/template-data/template_data.json @@ -4,6 +4,7 @@ "displayName": "DeSci Labs" }, "researchObjects": [], + "researchComponents": [], "claims": [ { "title": "Quality Stuff", @@ -30,19 +31,24 @@ "researchObjects": [ { "title": "Sunrises in Teletubbyland", - "manifest": "bafkreiepot62powegf7tt73gyiz24facsdloywggattt2asz5y4eaqhkyi", - "components": [ - { - "name": "A fancy dataset", - "dagNode": "bafkreibtsll3aq2bynvlxnqh6nxafzdm4cpiovr3bcncbkzjcy32xaaaaa", - "mimeType": "text/csv" - } - ] + "manifest": "bafkreiepot62powegf7tt73gyiz24facsdloywggattt2asz5y4eaqhkyi" }, { "title": "TeletubbyPlanet Orbital Behaviour", - "manifest": "bafkreibtsll3aq2bynvlxnqh6nxafzdm4cpiovr3bcncbkzjcy32xalp7i", - "components": [] + "manifest": "bafkreibtsll3aq2bynvlxnqh6nxafzdm4cpiovr3bcncbkzjcy32xalp7i" + } + ], + "researchComponents": [ + { + "name": "A fancy dataset", + "mimeType": "text/csv", + "dagNode": "bafkreibtsll3aq2bynvlxnqh6nxafzdm4cpiovr3bcncbkzjcy32xaaaaa", + "pathToNode": ".", + "researchObjectPath": [ + "dc0b1125d15f276c5e6fdaf2465ae9f25d5e9984a7cb062640345c941d3ed1e0", + "researchObjects", + 0 + ] } ], "contributorRelations": [], @@ -51,14 +57,12 @@ "fromPath": [ "dc0b1125d15f276c5e6fdaf2465ae9f25d5e9984a7cb062640345c941d3ed1e0", "researchObjects", - 1, - "IDs" + 1 ], "toPath": [ "dc0b1125d15f276c5e6fdaf2465ae9f25d5e9984a7cb062640345c941d3ed1e0", "researchObjects", - 0, - "IDs" + 0 ] } ], @@ -67,8 +71,7 @@ "researchObjectPath": [ "dc0b1125d15f276c5e6fdaf2465ae9f25d5e9984a7cb062640345c941d3ed1e0", "researchObjects", - 0, - "IDs" + 0 ], "fieldPath": [ "1a40e10dc4830864781716eab4f88c60d74d8718cc5ed9af268d338a2096833f", @@ -80,8 +83,7 @@ "researchObjectPath": [ "dc0b1125d15f276c5e6fdaf2465ae9f25d5e9984a7cb062640345c941d3ed1e0", "researchObjects", - 1, - "IDs" + 1 ], "fieldPath": [ "1a40e10dc4830864781716eab4f88c60d74d8718cc5ed9af268d338a2096833f", @@ -103,13 +105,19 @@ "researchObjects": [ { "title": "Teletubby Folklore", - "manifest": "bafkreieodz3e4kzbnlg4nka5pwrgafwuuemfuejxqa5dpdaqlgt6bjs7fm", - "components": [ - { - "name": "Some cool data I found", - "dagNode": "bafkreibtsll3aq2bynvlxnqh6nxafzdm4cpiovr3bcncbkzjcy32xaaaaa", - "mimeType": "text/csv" - } + "manifest": "bafkreieodz3e4kzbnlg4nka5pwrgafwuuemfuejxqa5dpdaqlgt6bjs7fm" + } + ], + "researchComponents": [ + { + "name": "Some cool data I found", + "mimeType": "text/csv", + "dagNode": "bafkreibtsll3aq2bynvlxnqh6nxafzdm4cpiovr3bcncbkzjcy32xaaaaa", + "pathToNode": ".", + "researchObjectPath": [ + "17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015", + "researchObjects", + 0 ] } ], @@ -119,8 +127,7 @@ "researchObjectPath": [ "17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015", "researchObjects", - 0, - "IDs" + 0 ], "contributorPath": [ "dc0b1125d15f276c5e6fdaf2465ae9f25d5e9984a7cb062640345c941d3ed1e0", @@ -134,8 +141,7 @@ "researchObjectPath": [ "17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015", "researchObjects", - 0, - "IDs" + 0 ], "fieldPath": [ "1a40e10dc4830864781716eab4f88c60d74d8718cc5ed9af268d338a2096833f", @@ -150,8 +156,7 @@ "targetPath": [ "17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015", "researchObjects", - 0, - "IDs" + 0 ], "claimPath": [ "1a40e10dc4830864781716eab4f88c60d74d8718cc5ed9af268d338a2096833f", @@ -171,10 +176,10 @@ "researchObjects": [ { "title": "Solar Mind Control", - "manifest": "bafkreifixmk6tierh6qompfouk63r6clg5jbeuvwherrxacq4uoedk4o5q", - "components": [] + "manifest": "bafkreifixmk6tierh6qompfouk63r6clg5jbeuvwherrxacq4uoedk4o5q" } ], + "researchComponents": [], "contributorRelations": [], "referenceRelations": [], "researchFieldRelations": [], @@ -184,8 +189,7 @@ "targetPath": [ "17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015", "researchObjects", - 0, - "IDs" + 0 ], "claimPath": [ "1a40e10dc4830864781716eab4f88c60d74d8718cc5ed9af268d338a2096833f", @@ -198,11 +202,15 @@ { "comment": "I viewed this dataset and it seems to check out!", "path": ".", - "targetPath": [ + "researchObjectPath": [ "17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015", "researchObjects", - 0, - "components", + 0 + ], + + "targetPath": [ + "17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015", + "researchComponents", 0 ], "claimPath": [ @@ -213,11 +221,10 @@ }, { "comment": "I recommend this RO gets stamped as quality content", - "targetPath": [ + "researchObjectPath": [ "17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015", "researchObjects", - 0, - "IDs" + 0 ], "claimPath": [ "1a40e10dc4830864781716eab4f88c60d74d8718cc5ed9af268d338a2096833f", diff --git a/test/root.spec.ts b/test/root.spec.ts index 6231875..ac5d885 100644 --- a/test/root.spec.ts +++ b/test/root.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { ComposeClient } from "@composedb/client"; -import { definition } from "../src/__generated__/definition"; +import { definition } from "../src/__generated__/definition.js"; import { RuntimeCompositeDefinition } from "@composedb/types"; import { test, describe, beforeAll, expect } from "vitest"; import { @@ -29,10 +29,10 @@ import { queryResearchFieldRelation, queryResearchFields, queryResearchObject, -} from "../utils/queries"; -import { randomDID } from "./util"; +} from "../src/queries.js"; +import { randomDID } from "./util.js"; import { CeramicClient } from "@ceramicnetwork/http-client"; -import { writeComposite } from "scripts/composites.mjs"; +import { writeComposite } from "../scripts/composites.mjs"; import { setTimeout } from "timers/promises"; import { Annotation, @@ -42,7 +42,7 @@ import { Profile, ReferenceRelation, ResearchObject, -} from "@/types"; +} from "../src/types.js"; import { CommitID } from "@ceramicnetwork/streamid"; const CERAMIC_API = "http:/localhost:7007"; diff --git a/tsconfig.json b/tsconfig.json index 1830192..ed51cf3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,24 +1,21 @@ { + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Node 20", + "_version": "20.1.0", + "compilerOptions": { - "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, + "lib": ["es2023"], + "module": "nodenext", + "target": "es2022", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, "forceConsistentCasingInFileNames": true, + "moduleResolution": "node16", + + "allowJs": true, "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "baseUrl": ".", - "paths": { - "@/*": ["./*"] - } - }, - "include": ["**/*.ts", "**/*.tsx", "template_data.json"], - "exclude": ["node_modules"] + "resolveJsonModule": true + } } From ea4bef4a430913a57244fae22c6579a400e5320e Mon Sep 17 00:00:00 2001 From: m0ar Date: Thu, 2 Nov 2023 11:54:50 +0100 Subject: [PATCH 5/9] Fix lint commit hook --- .husky/pre-commit | 6 +++++- package.json | 3 ++- src/populate.ts | 19 ++++++++++++++----- src/queries.ts | 2 +- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index 75fac8e..2c3be6a 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,8 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" -npm run lint +if ! npm run lint:check; then + echo "⚠️ Linting failed, trying to fix. Solve any remaining issues and try again." + npm run lint:fix + exit 1 +fi diff --git a/package.json b/package.json index 8a061cc..8d7d3a8 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "ceramic": "ceramic daemon --config composedb.config.json", "kill": "pkill --full \"ceramic daemon|ipfs daemon\"", "test": "vitest --run --config vitest.config.ts", - "lint": "eslint . --fix", + "lint:fix": "eslint . --fix", + "lint:check": "eslint .", "prepare": "husky install" }, "devDependencies": { diff --git a/src/populate.ts b/src/populate.ts index 190258b..64616b7 100644 --- a/src/populate.ts +++ b/src/populate.ts @@ -18,7 +18,13 @@ import { import { CeramicClient } from "@ceramicnetwork/http-client"; import { definition } from "./__generated__/definition.js"; import { RuntimeCompositeDefinition } from "@composedb/types"; -import { Annotation, Attestation, NodeIDs, ResearchComponent, ResearchObject } from "./types.js"; +import { + Annotation, + Attestation, + NodeIDs, + ResearchComponent, + ResearchObject, +} from "./types.js"; import { AnnotationTemplate, AttestationTemplate, @@ -67,10 +73,13 @@ export const loadIfUninitialised = async (ceramic: CeramicClient) => { `); if (firstProfile.errors) { - console.error("Failed to query Ceramic:", JSON.stringify(firstProfile.errors, undefined, 2)); - console.error("Is the Ceramic node running?") + console.error( + "Failed to query Ceramic:", + JSON.stringify(firstProfile.errors, undefined, 2), + ); + console.error("Is the Ceramic node running?"); process.exit(1); - }; + } if (firstProfile.data!.profileIndex.edges.length === 0) { console.log("Profile index empty, loading template data..."); @@ -213,7 +222,7 @@ const loadResearchComponent = async ( dagNode, pathToNode, researchObjectID: researchObject.streamID, - researchObjectVersion: researchObject.commitID + researchObjectVersion: researchObject.commitID, }; // Handle optionals diff --git a/src/queries.ts b/src/queries.ts index 4f63ee6..c23bdfd 100644 --- a/src/queries.ts +++ b/src/queries.ts @@ -715,7 +715,7 @@ const getQueryFields = ( inputs: Record, ) => Object.keys(inputs) - .filter(p => p !== "id") + .filter((p) => p !== "id") .reduce<[string[], string[]]>( (acc, next) => [ [...acc[0], `$${next}: ${graphQLParamTypes[next]}`], From ead6fc575838b8104290199d189cea933934026d Mon Sep 17 00:00:00 2001 From: m0ar Date: Thu, 2 Nov 2023 11:58:10 +0100 Subject: [PATCH 6/9] Tidy README --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c80a36a..f01c14d 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ This repo contains a reference implementation for the next generation of the pro By default, the application runs a local Ceramic/ComposeDB node with the bundled IPFS server, uses the `inmemory` network for anchoring, and writes all data and logs to `local-data`. +The protocol documentation can be found [here](pls-replace-me)! + ## Getting started 1. Install dependencies: @@ -28,8 +30,9 @@ Now you can open [http://localhost:5001](http://localhost:5001) for the GraphiQL ## Test suite -There is a test suite running through API operations demonstrating the functional protocol -requirements. This clones your user configuration, but changes storage to `local-data/ceramic-test` not to interfere with prepopulated data. Do make sure to stop `npm run dev` before executing tests. +There is a test suite running through API operations demonstrating the functional protocol requirements, by generating random DID's and performing create and mutation operations. Before each run, it will remove the remains of the last test execution. + +The test setup clones your user configuration, but changes storage to `local-data/ceramic-test` not to interfere with prepopulated data. It will refuse to run if `npm run dev` is already active. ```bash make test From fb27f595fc826ce8152b33eb224b1e170e9ed2d6 Mon Sep 17 00:00:00 2001 From: m0ar Date: Thu, 2 Nov 2023 12:32:48 +0100 Subject: [PATCH 7/9] Change flags to pgrep for yanky old ubuntu version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5d89732..451221c 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ clean-test: rm -rf local-data/ceramic-test test: clean-test - if pgrep --ignore-ancestors --count --full "ceramic daemon|ipfs daemon"; then \ + if pgrep --older 1 --count --full "ceramic daemon|ipfs daemon"; then \ echo "Refusing to clobber running daemons"; exit 1; \ fi From 0ae1932093eb1cdab6386ecf3eb16582363b5e73 Mon Sep 17 00:00:00 2001 From: m0ar Date: Thu, 2 Nov 2023 12:40:13 +0100 Subject: [PATCH 8/9] Add GHA reporter for vitest --- package-lock.json | 56 ++++++++++++++++++++++++++++++++++++++++++++++- package.json | 5 +++-- vitest.config.ts | 6 +++-- 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index bbdf43c..52ba996 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,8 @@ "tsconfig-paths": "^4.2.0", "typescript": "^5.2.2", "vite-tsconfig-paths": "^4.2.1", - "vitest": "^0.34.5" + "vitest": "^0.34.5", + "vitest-github-actions-reporter": "^0.10.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -48,6 +49,35 @@ "node": ">=0.10.0" } }, + "node_modules/@actions/core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", + "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", + "dev": true, + "dependencies": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "node_modules/@actions/core/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@actions/http-client": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.0.tgz", + "integrity": "sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==", + "dev": true, + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, "node_modules/@awaitjs/express": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@awaitjs/express/-/express-0.9.0.tgz", @@ -14956,6 +14986,15 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, "node_modules/tweetnacl": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", @@ -15501,6 +15540,21 @@ } } }, + "node_modules/vitest-github-actions-reporter": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/vitest-github-actions-reporter/-/vitest-github-actions-reporter-0.10.0.tgz", + "integrity": "sha512-ctFM1xlOVsXCNp5+LkaBZBhN1Iq5y9vVMZ9+Czls2CimOUKt0lH24MV1S0EzKysNUT7efs2OOSdmc6lgR8hqXg==", + "dev": true, + "dependencies": { + "@actions/core": "^1.10.0" + }, + "engines": { + "node": ">=14.16.0" + }, + "peerDependencies": { + "vitest": ">=0.28.5" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", diff --git a/package.json b/package.json index 8d7d3a8..6f9ed1a 100644 --- a/package.json +++ b/package.json @@ -31,11 +31,12 @@ "eslint-plugin-prettier": "^5.0.1", "husky": "^8.0.3", "key-did-resolver": "^3.0.0", - "tsconfig-paths": "^4.2.0", "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", "typescript": "^5.2.2", "vite-tsconfig-paths": "^4.2.1", - "vitest": "^0.34.5" + "vitest": "^0.34.5", + "vitest-github-actions-reporter": "^0.10.0" }, "dependencies": { "@ceramicnetwork/http-client": "^2.31.0", diff --git a/vitest.config.ts b/vitest.config.ts index 91ce788..5cb536d 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,9 +1,11 @@ import { defineConfig } from "vitest/config"; -import tsconfigPaths from "vite-tsconfig-paths"; +import GithubActionsReporter from "vitest-github-actions-reporter"; export default defineConfig({ test: { include: ["test/**/*.spec.ts"], + reporters: process.env.GITHUB_ACTIONS + ? ["default", new GithubActionsReporter()] + : "default", }, - plugins: [tsconfigPaths()], }); From 21191c07886e8e90f39fdeb1a849721ce9231823 Mon Sep 17 00:00:00 2001 From: m0ar Date: Thu, 2 Nov 2023 12:46:45 +0100 Subject: [PATCH 9/9] Switch vitest to verbose output --- vitest.config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vitest.config.ts b/vitest.config.ts index 5cb536d..fc13e8a 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -5,7 +5,7 @@ export default defineConfig({ test: { include: ["test/**/*.spec.ts"], reporters: process.env.GITHUB_ACTIONS - ? ["default", new GithubActionsReporter()] - : "default", + ? ["verbose", new GithubActionsReporter()] + : "verbose", }, });