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/.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/.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/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..2c3be6a --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,8 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +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/.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/Makefile b/Makefile index 6dfd427..451221c 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,23 @@ -.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 + if pgrep --older 1 --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 - # Kill daemons without losing test exit code for CI + + npm run deployComposites + # 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 dca8744..f01c14d 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,47 @@ -# 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. +# 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. -## Getting Started -1. Install your dependencies: +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: ```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 -## Reset -To clean everything up, delete `local-data`. This is necessary when changing networks, for example. +Now you can open [http://localhost:5001](http://localhost:5001) for the GraphiQL interface and explore the data models. -## 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. +## Test suite + +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 -``` \ No newline at end of file +``` + +## Reset + +To reset to a clean state, deleting everything except generated seed and user config: + +```bash +make clean +``` 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/composites/02-organization.graphql b/composites/02-organization.graphql deleted file mode 100644 index 3d76b81..0000000 --- a/composites/02-organization.graphql +++ /dev/null @@ -1,9 +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 59% rename from composites/05-claim.graphql rename to composites/1-claim.graphql index b3b8531..ff90c3a 100644 --- a/composites/05-claim.graphql +++ b/composites/1-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/00-profile.graphql b/composites/1-profile.graphql similarity index 89% rename from composites/00-profile.graphql rename to composites/1-profile.graphql index 3e29242..5361a22 100644 --- a/composites/00-profile.graphql +++ b/composites/1-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/1-researchField.graphql similarity index 57% rename from composites/001-researchField.graphql rename to composites/1-researchField.graphql index fcab995..1fa9424 100644 --- a/composites/001-researchField.graphql +++ b/composites/1-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/1-researchObject.graphql similarity index 80% rename from composites/01-researchObject.graphql rename to composites/1-researchObject.graphql index 614261d..054465c 100644 --- a/composites/01-researchObject.graphql +++ b/composites/1-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/11-annotation.graphql b/composites/2-annotation.graphql similarity index 90% rename from composites/11-annotation.graphql rename to composites/2-annotation.graphql index 63964d8..16abb84 100644 --- a/composites/11-annotation.graphql +++ b/composites/2-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/06-attestation.graphql b/composites/2-attestation.graphql similarity index 94% rename from composites/06-attestation.graphql rename to composites/2-attestation.graphql index 97259da..3bb8a28 100644 --- a/composites/06-attestation.graphql +++ b/composites/2-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/09-contributorRelation.graphql b/composites/2-contributorRelation.graphql similarity index 80% rename from composites/09-contributorRelation.graphql rename to composites/2-contributorRelation.graphql index c42a8ad..eb5bb05 100644 --- a/composites/09-contributorRelation.graphql +++ b/composites/2-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/08-referenceRelation.graphql b/composites/2-referenceRelation.graphql similarity index 76% rename from composites/08-referenceRelation.graphql rename to composites/2-referenceRelation.graphql index 792bba5..13207cd 100644 --- a/composites/08-referenceRelation.graphql +++ b/composites/2-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/07-researchComponent.graphql b/composites/2-researchComponent.graphql similarity index 83% rename from composites/07-researchComponent.graphql rename to composites/2-researchComponent.graphql index c51e85a..7bf4e8c 100644 --- a/composites/07-researchComponent.graphql +++ b/composites/2-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/10-researchFieldRelation.graphql b/composites/2-researchFieldRelation.graphql similarity index 73% rename from composites/10-researchFieldRelation.graphql rename to composites/2-researchFieldRelation.graphql index a4afabd..dff4762 100644 --- a/composites/10-researchFieldRelation.graphql +++ b/composites/2-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/3-additionalRelations.graphql b/composites/3-additionalRelations.graphql new file mode 100644 index 0000000..7d9dff0 --- /dev/null +++ b/composites/3-additionalRelations.graphql @@ -0,0 +1,101 @@ +# This composite holds additional relations that cause circular dependencies when deploying +type Attestation @loadModel(id: "$ATTESTATION_ID") { + id: ID! +} + +type ReferenceRelation @loadModel(id: "$REFERENCE_RELATION_ID") { + id: ID! +} + +type ContributorRelation @loadModel(id: "$CONTRIBUTOR_RELATION_ID") { + id: ID! +} + +type ResearchFieldRelation @loadModel(id: "$RESEARCH_FIELD_RELATION_ID") { + id: ID! +} + +type Annotation @loadModel(id: "$ANNOTATION_ID") { + replies: [Annotation] @relationFrom(model: "Annotation", property: "targetID") + replyCount: Int! @relationCountFrom(model: "Annotation", property: "targetID") +} + +type ResearchComponent @loadModel(id: "$RESEARCH_COMPONENT_ID") { + 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") +} + +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") +} + +# 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") + + 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") +} diff --git a/composites/additional-relations.graphql b/composites/additional-relations.graphql deleted file mode 100644 index 5429ffc..0000000 --- a/composites/additional-relations.graphql +++ /dev/null @@ -1,74 +0,0 @@ -# This composite holds additional relations that cause circular dependencies when deploying -type Attestation @loadModel(id: "$ATTESTATION_ID") { - id: ID! -} - -type ReferenceRelation @loadModel(id: "$REFERENCE_RELATION_ID") { - id: ID! -} - -type ContributorRelation @loadModel(id: "$CONTRIBUTOR_RELATION_ID") { - id: ID! -} - -type ResearchFieldRelation @loadModel(id: "$RESEARCH_FIELD_RELATION_ID") { - id: ID! -} - -type Annotation @loadModel(id: "$ANNOTATION_ID") { - replies: [Annotation] @relationFrom(model: "Annotation", property: "targetID") - replyCount: Int! @relationCountFrom(model: "Annotation", property: "targetID") -} - -type ResearchComponent @loadModel(id: "$RESEARCH_COMPONENT_ID") { - 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") -} - -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") -} - -# 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") - - 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") -} 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..52ba996 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,23 +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", - "next": "^13.4.19", - "react-icons": "^4.10.1", - "sass": "^1.66.1" + "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", @@ -25,14 +24,20 @@ "@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", - "@types/react": "18.2.21", - "eslint": "8.48.0", - "eslint-config-next": "13.4.19", + "@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", + "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" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -44,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", @@ -879,17 +913,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 +987,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 +2181,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", @@ -3306,155 +3196,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 +3377,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" } @@ -3848,6 +3589,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", @@ -4088,12 +3849,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", @@ -4209,11 +3964,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", @@ -4233,42 +3983,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", @@ -4291,23 +4010,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", @@ -4331,6 +4033,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", @@ -4353,38 +4056,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", @@ -4478,14 +4149,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,10 +4373,10 @@ "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==", + "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": { @@ -4747,12 +4410,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 +4424,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,10 +4433,10 @@ "@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==", + "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": { @@ -4816,16 +4462,51 @@ "@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.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.0.tgz", - "integrity": "sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==", + "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.0", - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/typescript-estree": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@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": { @@ -4845,13 +4526,32 @@ } }, "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==", + "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/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0" + "@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" @@ -4859,12 +4559,20 @@ "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.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", - "integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", + "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" @@ -4875,13 +4583,13 @@ } }, "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==", + "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.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@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", @@ -4901,13 +4609,38 @@ } } }, + "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.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", - "integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", + "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.0", + "@typescript-eslint/types": "6.9.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -5398,6 +5131,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" @@ -5406,11 +5142,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", @@ -5445,53 +5176,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,95 +5191,6 @@ "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==", - "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_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==", - "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.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", @@ -5599,12 +5200,6 @@ "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", @@ -5620,15 +5215,6 @@ "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", @@ -5685,15 +5271,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 +5280,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", @@ -5781,6 +5349,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", @@ -5791,6 +5368,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" } @@ -5821,6 +5399,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" } @@ -5880,7 +5461,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", @@ -5975,6 +5555,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", @@ -5989,6 +5581,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" }, @@ -6147,10 +5740,26 @@ "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", "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, "dependencies": { "streamsearch": "^1.1.0" }, @@ -6391,25 +6000,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 +6187,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 +6216,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" }, @@ -6692,7 +6288,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" }, @@ -6784,11 +6379,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 +6600,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 +6654,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", @@ -7157,6 +6735,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", @@ -7222,21 +6890,16 @@ "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==", + "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, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/delay": { @@ -7266,15 +6929,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", @@ -7323,24 +6977,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", @@ -7485,8 +7121,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", @@ -7567,12 +7202,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 +7308,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 +7443,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", @@ -8060,283 +7561,47 @@ "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==", + "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, - "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" + "bin": { + "eslint-config-prettier": "bin/cli.js" }, "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0", - "typescript": ">=3.3.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": ">=7.0.0" } }, - "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==", + "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": { - "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" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.5" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + "url": "https://opencollective.com/prettier" }, "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" + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "prettier": ">=3.0.0" }, "peerDependenciesMeta": { - "eslint": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { "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" - } - }, - "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==", - "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_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==", - "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" - } - }, - "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==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "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" - } - }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -8665,6 +7930,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", @@ -8848,6 +8119,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 +8301,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 +8320,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 +8406,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 +8444,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 +8471,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 +8557,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 +8641,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 +8662,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", @@ -9715,6 +8896,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", @@ -9760,7 +8956,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", @@ -9833,21 +9032,7 @@ "version": "5.1.4", "resolved": "https://registry.npmjs.org/interface-store/-/interface-store-5.1.4.tgz", "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" - } + "dev": true }, "node_modules/interpret": { "version": "2.2.0", @@ -10180,57 +9365,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 +9385,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 +9432,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 +9463,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 +9496,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" }, @@ -10407,11 +9513,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" }, @@ -10426,48 +9564,13 @@ "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" - } - }, "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 +9609,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 +9621,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", @@ -10610,7 +9646,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" }, @@ -10618,40 +9653,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 +9665,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 +9783,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 +9857,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", @@ -10934,15 +9911,15 @@ "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==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, "bin": { "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" } }, "node_modules/jsonc-parser": { @@ -10973,21 +9950,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", @@ -11008,6 +9970,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", @@ -11172,21 +10135,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 +11121,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", @@ -12839,53 +11776,8 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, - "engines": { - "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 - } + "engines": { + "node": ">= 0.6" } }, "node_modules/nft-did-resolver": { @@ -12909,6 +11801,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" @@ -12917,12 +11810,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" } @@ -13086,6 +11981,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 +12084,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 +12101,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", @@ -13348,6 +12146,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", @@ -13378,7 +12194,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", @@ -13401,7 +12216,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" }, @@ -13413,7 +12227,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" }, @@ -13425,7 +12238,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" }, @@ -13439,14 +12251,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" @@ -13462,7 +12272,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" } @@ -13471,7 +12280,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" }, @@ -13486,7 +12294,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" @@ -13502,7 +12309,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", @@ -13519,7 +12325,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" }, @@ -14001,12 +12806,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 +12928,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 +12956,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", @@ -14209,6 +13018,32 @@ "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/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", @@ -14275,17 +13110,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", @@ -14495,45 +13319,6 @@ "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/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", @@ -14556,7 +13341,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", @@ -14570,6 +13354,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 +13400,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 +13446,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", @@ -14843,27 +13584,131 @@ "resolved": "https://registry.npmjs.org/rpc-utils/-/rpc-utils-0.6.2.tgz", "integrity": "sha512-kzk1OflbBckfDBAo8JwsmtQSHzj+6hxRt5G+u8A8ZSmunBw1nhWvRkSq8j1+EvWBqBRLy1aiGLUW5644CZqQtA==", "dependencies": { - "nanoid": "^3.3.1" + "nanoid": "^3.3.1" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/rpc-utils/node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "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": ">=14.14" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/rpc-utils/node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, + "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": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=6" } }, "node_modules/run-parallel": { @@ -14969,24 +13814,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 +13846,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 +13856,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 +13877,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 +14060,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", @@ -15330,8 +14123,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", @@ -15414,6 +14206,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" } @@ -15519,7 +14312,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" }, @@ -15571,6 +14363,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" } @@ -15587,7 +14380,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" } @@ -15612,71 +14404,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 +14461,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,13 +14522,20 @@ "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==", + "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": ">=6" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" } }, "node_modules/tar": { @@ -16106,6 +14818,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", @@ -16137,6 +14861,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" }, @@ -16243,15 +14968,17 @@ } }, "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==", + "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": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", + "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, "node_modules/tslib": { @@ -16259,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", @@ -16311,71 +15047,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", @@ -16416,7 +15087,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" @@ -16477,21 +15147,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", @@ -16547,6 +15202,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", @@ -16641,8 +15305,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", @@ -16877,16 +15540,19 @@ } } }, - "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==", + "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": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" + "@actions/core": "^1.10.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=14.16.0" + }, + "peerDependencies": { + "vitest": ">=0.28.5" } }, "node_modules/webidl-conversions": { @@ -16931,63 +15597,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..6f9ed1a 100644 --- a/package.json +++ b/package.json @@ -1,45 +1,51 @@ { - "name": "desci-composites", + "name": "desci-composedb", "version": "1.0.0", - "description": "", - "main": "index.js", + "description": "A reference protocol implementation on Ceramic and ComposeDB", + "license": "MIT", + "author": "Edvard Hübinette", + "type": "module", "scripts": { - "generate": "node scripts/commands.mjs", - "dev": "node scripts/run.mjs", - "nextDev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint", + "generate": "node scripts/generate.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" + "test": "vitest --run --config vitest.config.ts", + "lint:fix": "eslint . --fix", + "lint:check": "eslint .", + "prepare": "husky install" }, - "author": "Edvard Hubinette", "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", - "@types/react": "18.2.21", - "eslint": "8.48.0", - "eslint-config-next": "13.4.19", + "@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", + "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", "@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", - "next": "^13.4.19", - "react-icons": "^4.10.1", - "sass": "^1.66.1" + "key-did-provider-ed25519": "^3.0.2", + "ora": "^7.0.1", + "prettier": "^3.0.3", + "uint8arrays": "^4.0.6" } } 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 bb15a70..0000000 Binary files a/public/ceramic.png and /dev/null differ diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index 718d6fe..0000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/nodes.png b/public/nodes.png deleted file mode 100644 index 7642249..0000000 Binary files a/public/nodes.png and /dev/null differ diff --git a/public/vercel.svg b/public/vercel.svg deleted file mode 100644 index fbf0e25..0000000 --- a/public/vercel.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - \ No newline at end of file diff --git a/scripts/composites.mjs b/scripts/composites.mjs index 51769c8..a1d6640 100644 --- a/scripts/composites.mjs +++ b/scripts/composites.mjs @@ -22,140 +22,150 @@ 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", - { encoding: "utf-8"} - ).replace("$CLAIM_ID", claimComposite.modelIDs[0]); + "./composites/2-attestation.graphql", + { encoding: "utf-8" }, + ).replace("$CLAIM_ID", modelIDs.claim); const attestationComposite = await Composite.create({ ceramic, - schema: attestationSchema + schema: attestationSchema, }); + modelIDs.attestation = attestationComposite.modelIDs[1]; - const componentSchema = readFileSync( - "./composites/07-researchComponent.graphql", - { encoding: "utf-8"} - ).replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]); + const researchComponentSchema = readFileSync( + "./composites/2-researchComponent.graphql", + { encoding: "utf-8" }, + ).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", - { encoding: "utf-8"} - ).replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]); + "./composites/2-referenceRelation.graphql", + { encoding: "utf-8" }, + ).replace("$RESEARCH_OBJECT_ID", modelIDs.researchObject); const referenceRelationComposite = await Composite.create({ ceramic, - schema: referenceRelationSchema + schema: referenceRelationSchema, }); + modelIDs.referenceRelation = referenceRelationComposite.modelIDs[1]; const contributorRelationSchema = readFileSync( - "./composites/09-contributorRelation.graphql", - { encoding: "utf-8"} - ).replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]) - .replace("$PROFILE_ID", profileComposite.modelIDs[0]) + "./composites/2-contributorRelation.graphql", + { encoding: "utf-8" }, + ) + .replace("$RESEARCH_OBJECT_ID", modelIDs.researchObject) + .replace("$PROFILE_ID", modelIDs.profile); const contributorRelationComposite = await Composite.create({ ceramic, - schema: contributorRelationSchema + schema: contributorRelationSchema, }); + modelIDs.contributorRelation = contributorRelationComposite.modelIDs[2]; const researchFieldRelationSchema = readFileSync( - "./composites/10-researchFieldRelation.graphql", - { encoding: "utf-8"} - ).replace("$RESEARCH_OBJECT_ID", researchObjComposite.modelIDs[0]) - .replace("$RESEARCH_FIELD_ID", researchFieldComposite.modelIDs[0]); + "./composites/2-researchFieldRelation.graphql", + { encoding: "utf-8" }, + ) + .replace("$RESEARCH_OBJECT_ID", modelIDs.researchObject) + .replace("$RESEARCH_FIELD_ID", modelIDs.researchField); const researchFieldRelationComposite = await Composite.create({ ceramic, - schema: researchFieldRelationSchema + schema: researchFieldRelationSchema, }); + modelIDs.researchFieldRelation = researchFieldRelationComposite.modelIDs[2]; - 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/2-annotation.graphql", { + encoding: "utf-8", + }) + .replace("$CLAIM_ID", modelIDs.claim) + .replace("$RESEARCH_OBJECT_ID", modelIDs.researchObject); const annotationComposite = await Composite.create({ ceramic, - schema: annotationSchema + schema: annotationSchema, }); + modelIDs.annotation = annotationComposite.modelIDs[2]; const additionalRelationsSchema = readFileSync( - "./composites/additional-relations.graphql", - { encoding: "utf-8" } + "./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, - schema: additionalRelationsSchema + schema: additionalRelationsSchema, }); const composite = Composite.from([ profileComposite, - researchObjComposite, - orgComposite, + researchObjectComposite, claimComposite, attestationComposite, - componentComposite, + researchComponentComposite, additionalRelationsComposite, contributorRelationComposite, 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 +188,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/commands.mjs b/scripts/generate.mjs similarity index 78% rename from scripts/commands.mjs rename to scripts/generate.mjs index 8eb7be9..ef96a24 100644 --- a/scripts/commands.mjs +++ b/scripts/generate.mjs @@ -10,15 +10,15 @@ 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') - } + 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(); +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 742b330..391b3b3 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,60 +26,45 @@ 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']) - spinner.succeed("[GraphiQL] graphiql started"); - graphiql.stdout.on('data', (buffer) => { - console.log('[GraphiqQL]',buffer.toString()) - }) -} - -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()) - }) -} + spinner.info("[GraphiQL] Starting server"); + const graphiql = spawn("node", ["./scripts/graphiql.mjs"]); + spinner.succeed("[GraphiQL] Server started"); + 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 next() + 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() +for (const signal in ["SIGTERM", "SIGINT", "beforeExit"]) { + process.on(signal, () => ceramic.kill()); +}; -process.on("SIGTERM", () => { - ceramic.kill(); -}); -process.on("SIGINT", () => { - ceramic.kill(); -}); -process.on("beforeExit", () => { - ceramic.kill(); -}); +start(); diff --git a/src/populate.ts b/src/populate.ts new file mode 100644 index 0000000..64616b7 --- /dev/null +++ b/src/populate.ts @@ -0,0 +1,347 @@ +import KeyDIDResolver from "key-did-resolver"; +import { Ed25519Provider } from "key-did-provider-ed25519"; +import { DID } from "dids"; +import { fromString } from "uint8arrays/from-string"; +import { ComposeClient } from "@composedb/client"; +import { + mutationCreateAnnotation, + mutationCreateAttestation, + mutationCreateClaim, + mutationCreateContributorRelation, + mutationCreateProfile, + mutationCreateReferenceRelation, + mutationCreateResearchComponent, + mutationCreateResearchField, + mutationCreateResearchFieldRelation, + mutationCreateResearchObject, +} from "./queries.js"; +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 { + AnnotationTemplate, + AttestationTemplate, + ContributorRelationTemplate, + DataTemplate, + ObjectPath, + ReferenceRelationTemplate, + ResearchComponentTemplate, + ResearchFieldRelationTemplate, + ResearchObjectTemplate, +} from "../template-data/templateData.js"; + +import untypedTemplateData from "../template-data/template_data.json" assert { type: "json" }; + +const templateData: DataTemplate = untypedTemplateData; + +const didFromSeed = async (seed: string) => { + const keyResolver = KeyDIDResolver.getResolver(); + const key = fromString(seed, "base16"); + const did = new DID({ + provider: new Ed25519Provider(key), + resolver: { + ...keyResolver, + }, + }); + await did.authenticate(); + return did; +}; + +type ProfileIndexResult = { profileIndex: { edges: [] } }; +export const loadIfUninitialised = async (ceramic: CeramicClient) => { + const composeClient = new ComposeClient({ + ceramic, + definition: definition as RuntimeCompositeDefinition, + }); + const firstProfile = await composeClient.executeQuery(` + query { + profileIndex(first: 1) { + edges { + node { + id + } + } + } + } + `); + + 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) { + console.log("Profile index empty, loading template data..."); + await loadTemplateData(composeClient); + } else { + 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; + researchObjects: NodeIDs[]; + researchComponents: NodeIDs[]; + claims: NodeIDs[]; + researchFields: NodeIDs[]; + attestations: NodeIDs[]; + contributorRelations: NodeIDs[]; + referenceRelations: NodeIDs[]; + researchFieldRelations: NodeIDs[]; + annotations: NodeIDs[]; +}; + +const freshActorRecord = (profile: NodeIDs): ActorDataNodeIDs => ({ + profile, + researchObjects: [], + researchComponents: [], + claims: [], + attestations: [], + researchFields: [], + contributorRelations: [], + referenceRelations: [], + researchFieldRelations: [], + annotations: [], +}); + +type StreamIndex = Record; + +/** + * Iterates over template data file, and with a DID generated from each root entry + * 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)); + + const profileIDs = await mutationCreateProfile( + composeClient, + template.profile, + ); + streamIndex[seed] = freshActorRecord(profileIDs); + + streamIndex[seed].researchFields = await Promise.all( + template.researchFields.map((rfTemplate) => + mutationCreateResearchField(composeClient, rfTemplate), + ), + ); + + streamIndex[seed].researchObjects = await Promise.all( + template.researchObjects.map((roTemplate) => + loadResearchObject(roTemplate, 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), + ), + ); + + streamIndex[seed].referenceRelations = await Promise.all( + template.referenceRelations.map((refTemplate) => + loadReferenceRelation(refTemplate, streamIndex, composeClient), + ), + ); + + streamIndex[seed].researchFieldRelations = await Promise.all( + template.researchFieldRelations.map((fieldRelTemplate) => + loadResearchFieldRelation(fieldRelTemplate, streamIndex, composeClient), + ), + ); + + streamIndex[seed].claims = await Promise.all( + template.claims.map((c) => mutationCreateClaim(composeClient, c)), + ); + + streamIndex[seed].attestations = await Promise.all( + template.attestations.map((attTemplate) => + loadAttestation(attTemplate, streamIndex, composeClient), + ), + ); + + streamIndex[seed].annotations = await Promise.all( + template.annotations.map((annTemplate) => + loadAnnotation(annTemplate, streamIndex, composeClient), + ), + ); + } + console.log("Loading template data done!"); +}; + +const loadResearchObject = async ( + roTemplate: ResearchObjectTemplate, + composeClient: ComposeClient, +): Promise => { + const roProps: ResearchObject = { + title: roTemplate.title, + manifest: roTemplate.manifest, + }; + const researchObject = await mutationCreateResearchObject( + composeClient, + roProps, + ); + + 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, + }; + + // Handle optionals + if (metadata) component.metadata = metadata; + return await mutationCreateResearchComponent(composeClient, component); +}; + +const loadContributorRelation = async ( + contTemplate: ContributorRelationTemplate, + streamIndex: StreamIndex, + 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, + }); +}; + +const loadReferenceRelation = async ( + refTemplate: ReferenceRelationTemplate, + streamIndex: StreamIndex, + 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, + }); +}; + +const loadResearchFieldRelation = async ( + fieldRelTemplate: ResearchFieldRelationTemplate, + streamIndex: StreamIndex, + 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, + }); +}; + +const loadAttestation = async ( + attestationTemplate: AttestationTemplate, + streamIndex: StreamIndex, + composeClient: ComposeClient, +): Promise => { + const { targetPath, claimPath } = attestationTemplate; + const target = recursePathToID(streamIndex, targetPath); + const claim = recursePathToID(streamIndex, claimPath); + const attestation: Attestation = { + targetID: target.streamID, + targetVersion: target.commitID, + claimID: claim.streamID, + claimVersion: claim.commitID, + revoked: false, + }; + return mutationCreateAttestation(composeClient, attestation); +}; + +const loadAnnotation = async ( + annotationTemplate: AnnotationTemplate, + streamIndex: StreamIndex, + composeClient: ComposeClient, +): Promise => { + const { + comment, + researchObjectPath, + targetPath, + dagNode, + pathToNode, + locationOnFile, + claimPath, + metadataPayload, + } = annotationTemplate; + + const researchObject = recursePathToID(streamIndex, researchObjectPath); + const annotation: Annotation = { + 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; + } + + // 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); +}; + +// 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; + +loadIfUninitialised(new CeramicClient("http://localhost:7007")); diff --git a/src/queries.ts b/src/queries.ts new file mode 100644 index 0000000..c23bdfd --- /dev/null +++ b/src/queries.ts @@ -0,0 +1,731 @@ +import { ComposeClient } from "@composedb/client"; +import { + Attestation, + Claim, + ResearchComponent, + Profile, + ResearchObject, + ContributorRelation, + ReferenceRelation, + ResearchFieldRelation, + ProtocolEntity, + Annotation, + NodeIDs, + ResearchField, +} from "./types.js"; +import { ExecutionResult } from "graphql"; + +export const queryViewerId = async ( + composeClient: ComposeClient, +): Promise => { + const response = await composeClient.executeQuery<{ + viewer: { id: string }; + }>(` + query { + 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, +): Promise => { + const response = await composeClient.executeQuery<{ + viewer: { profile: Profile | null }; + }>(` + query { + viewer { + profile { + id + displayName + orcid + } + } + }`); + assertQueryErrors(response, "viewer profile"); + return response.data!.viewer.profile; +}; + +export const queryViewerResearchObjects = async ( + composeClient: ComposeClient, +): Promise => { + const response = await composeClient.executeQuery<{ + viewer: { researchObjectList: { edges: { node: ResearchObject }[] } }; + }>(` + query { + viewer { + researchObjectList(first: 100) { + edges { + node { + id + title + manifest + } + } + } + } + } + `); + assertQueryErrors(response, "viewer research objects"); + return response.data!.viewer.researchObjectList.edges.map((e) => e.node); +}; + +export const queryViewerClaims = async ( + composeClient: ComposeClient, +): Promise => { + const response = await composeClient.executeQuery<{ + viewer: { claimList: { edges: { node: Claim }[] } }; + }>(` + query { + viewer { + claimList(first: 100) { + edges { + node { + id + title + description + badge + } + } + } + } + } + `); + assertQueryErrors(response, "viewer claims"); + return response.data!.viewer.claimList.edges.map((e) => e.node); +}; + +export const queryResearchObjects = async ( + composeClient: ComposeClient, +): Promise => { + const response = await composeClient.executeQuery<{ + researchObjectIndex: { edges: { node: ResearchObject }[] }; + }>(` + query { + researchObjectIndex(first: 100) { + edges { + node { + id + title + manifest + owner { + profile { + displayName + orcid + } + } + } + } + } + } + `); + assertQueryErrors(response, "research objects"); + return response.data!.researchObjectIndex.edges.map((e) => e.node); +}; + +export const queryResearchObjectAttestations = async ( + composeClient: ComposeClient, + researchObjectID: string, +) => { + const response = await composeClient.executeQuery<{ + node: { attestations: { edges: { node: Attestation }[] } }; + }>( + ` + query ($id: ID!) { + node(id: $id) { + ... on ResearchObject { + attestations(first: 10) { + edges { + node { + claim { + title + } + source { + profile { + displayName + } + } + } + } + } + } + } + } + `, + { 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", +}; + +export const mutationCreateResearchObject = async ( + composeClient: ComposeClient, + 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", + ); + +const COMPONENT_TYPE_MAP = { + name: "String!", + mimeType: "String!", + metadata: "InterPlanetaryCID", + dagNode: "InterPlanetaryCID!", + pathToNode: "String!", + researchObjectID: "CeramicStreamID!", + researchObjectVersion: "CeramicCommitID!", +}; + +export const mutationCreateResearchComponent = async ( + composeClient: ComposeClient, + 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", + ); + +export const mutationCreateProfile = async ( + composeClient: ComposeClient, + 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", + ); + +const ATTESTATION_TYPE_MAP = { + targetID: "CeramicStreamID!", + targetVersion: "CeramicCommitID!", + claimID: "CeramicStreamID!", + claimVersion: "CeramicCommitID!", + revoked: "Boolean", +}; + +export const mutationCreateAttestation = async ( + composeClient: ComposeClient, + 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", + ); + +const ANNOTATION_TYPE_MAP = { + comment: "String!", + researchObjectID: "CeramicStreamID!", + researchObjectVersion: "CeramicCommitID!", + targetID: "CeramicStreamID!", + targetVersion: "CeramicCommitID!", + dagNode: "InterPlanetaryCID", + pathToNode: "String", + locationOnFile: "String", + claimID: "CeramicStreamID", + claimVersion: "CeramicCommitID", + metadataPayload: "InterPlanetaryCID", +}; + +export const mutationCreateAnnotation = async ( + composeClient: ComposeClient, + 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", + ); + +const CONTRIBUTOR_TYPE_MAP = { + role: "String!", + contributorID: "CeramicStreamID!", + researchObjectID: "CeramicStreamID!", + researchObjectVersion: "CeramicCommitID!", + revoked: "Boolean!", +}; +export const mutationCreateContributorRelation = async ( + composeClient: ComposeClient, + 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", + ); + +const REFERENCE_TYPE_MAP = { + toID: "CeramicStreamID!", + toVersion: "CeramicCommitID!", + fromID: "CeramicStreamID!", + fromVersion: "CeramicCommitID!", + revoked: "Boolean!", +}; + +export const mutationCreateReferenceRelation = async ( + composeClient: ComposeClient, + 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", + ); + +export const mutationCreateResearchFieldRelation = async ( + composeClient: ComposeClient, + 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", + ); + +export const queryResearchObject = async ( + composeClient: ComposeClient, + id: string, + 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 ?? + ` + displayName + orcid + `, + ); + +export const queryClaim = async ( + composeClient: ComposeClient, + id: string, + 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 ?? + ` + targetID + targetVersion + claimID + claimVersion + revoked + `, + ); + +export const queryResearchComponent = async ( + composeClient: ComposeClient, + id: string, + selection?: string, +): Promise => + genericEntityQuery( + composeClient, + id, + "ResearchComponent", + selection ?? + ` + name + mimeType + metadata + dagNode + pathToNode + researchObjectID + researchObjectVersion + `, + ); + +export const queryAnnotation = async ( + composeClient: ComposeClient, + id: string, + selection?: string, +): Promise => + genericEntityQuery( + composeClient, + id, + "Annotation", + selection ?? + ` + comment + researchObjectID + researchObjectVersion + targetID + targetVersion + dagNode + pathToNode + locationOnFile + claimID + claimVersion + metadataPayload + `, + ); + +export const queryContributorRelation = async ( + composeClient: ComposeClient, + id: string, + 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 ?? + ` + fromID + fromVersion + toID + toVersion + revoked + `, + ); + +export const queryResearchFields = async ( + composeClient: ComposeClient, + id: string, + 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 ?? + ` + fieldID + researchObjectID + researchObjectVersion + `, + ); + +export async function genericEntityQuery( + composeClient: ComposeClient, + id: string, + entityName: string, + // Specify the field structure to query for + selection: string, +): Promise { + const query = ` + query($id: ID!) { + node(id: $id) { + ...on ${entityName} { + ${selection} + } + } + } + `; + 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 spec it fully because some props are not allowed in the mutation. + */ + gqlTypes: Partial>, + mutationName: string, + /** Skip timeout for accountRelation SINGLE entities */ + noTimeout?: boolean, +): Promise { + const [params, content] = getQueryFields( + gqlTypes as Record, + inputs, + ); + const response = (await composeClient.executeQuery( + ` + mutation( ${params} ) { + ${mutationName}(input: { + content: { ${content} } + ${noTimeout ? "options: { syncTimeout: 0 }" : ""} + }) + { + document { + id + version + } + } + }`, + inputs, + /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ + )) as any; + assertMutationErrors(response, mutationName); + const nodeIDs: NodeIDs = { + streamID: response.data[mutationName].document.id, + commitID: response.data[mutationName].document.version, + }; + return nodeIDs; +} + +async function genericUpdate( + composeClient: ComposeClient, + inputs: Partial & { id: string }, + // See note in genericCreate + gqlTypes: Partial>, + mutationName: string, +): Promise { + const [params, content] = getQueryFields( + gqlTypes as Record, + inputs, + ); + const response = (await composeClient.executeQuery( + ` + mutation($id: ID!, ${params} ) { + ${mutationName}( + input: { + id: $id + content: { ${content} } + } + ) + { + document { + id + version + } + } + }`, + inputs, + /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ + )) as any; + assertMutationErrors(response, mutationName); + const nodeIDs: NodeIDs = { + streamID: response.data[mutationName].document.id, + commitID: response.data[mutationName].document.version, + }; + return nodeIDs; +} + +type SimpleExecutionResult = Pick; + +const assertMutationErrors = ( + result: SimpleExecutionResult, + queryDescription: string, +) => { + if (result.errors) { + console.error("Error:", result.errors.toString()); + throw new Error(`Mutation failed: ${queryDescription}`); + } +}; + +const assertQueryErrors = ( + result: SimpleExecutionResult, + 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. + */ +const getQueryFields = ( + graphQLParamTypes: Record, + inputs: Record, +) => + Object.keys(inputs) + .filter((p) => p !== "id") + .reduce<[string[], string[]]>( + (acc, next) => [ + [...acc[0], `$${next}: ${graphQLParamTypes[next]}`], + [...acc[1], `${next}: $${next}`], + ], + [[], []], + ) + .map((stringArr) => stringArr.join(", ")); + +const makeAllOptional = (typeMap: Record) => + Object.fromEntries( + Object.entries(typeMap).map(([k, v]) => [k, v.replace("!", "")]), + ); diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..de8e68e --- /dev/null +++ b/src/types.ts @@ -0,0 +1,149 @@ +export type Profile = { + id?: string; + version?: string; + displayName?: string; + orcid?: string; +}; + +export type DID = { + profile?: Profile; +}; + +export type ResearchObject = { + id?: string; + version?: string; + owner?: DID; + + title: string; + manifest: string; + + components?: ResearchComponent[]; + + metadata?: string; // CID +}; + +export type ResearchComponent = { + owner?: DID; + version?: string; + + name: string; + mimeType: string; + + dagNode: string; + pathToNode: string; + + researchObjectID: string; + researchObjectVersion: string; + + metadata?: string; // CID +}; + +export type Claim = { + id?: string; + version?: string; + + title: string; + description: string; + badge?: string; +}; + +export type Attestation = { + id?: string; + version?: string; + source?: DID; + + targetID: string; + targetVersion: string; + + claimID: string; + claimVersion: string; + claim?: Claim; + + revoked: boolean; +}; + +export type Annotation = { + id?: string; + version?: string; + comment: string; + + researchObjectID: string; + researchObject?: ResearchObject; + researchObjectVersion: string; + + targetID?: string; + targetVersion?: string; + + dagNode?: string; // CID + pathToNode?: string; + + locationOnFile?: string; + + claimID?: string; + claim?: Claim; + claimVersion?: string; + + metadataPayload?: string; +}; + +export type ContributorRelation = { + id?: string; + role: string; + + contributorID: string; + + researchObjectID: string; + researchObjectVersion: string; + + revoked: boolean; +}; + +export type ReferenceRelation = { + id?: string; + + toID: string; + toVersion: string; + + fromID: string; + fromVersion: string; + + revoked: boolean; +}; + +export type ResearchField = { + title: string; +}; + +export type ResearchFieldRelation = { + id?: string; + fieldID: string; + + researchObjectID: string; + researchObjectVersion: string; +}; + +export type ProtocolEntity = + | Profile + | ResearchObject + | ResearchComponent + | Claim + | Attestation + | Annotation + | ContributorRelation + | ReferenceRelation + | ResearchField + | ResearchFieldRelation; + +export type NodeIDs = { + streamID: string; + commitID: string; +}; + +export type SidebarProps = { + displayName?: string; + id?: string; +}; + +export type RequiredKeys = { + [K in keyof T as undefined extends T[K] ? never : K]: T[K]; +}; 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/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/template-data/templateData.d.ts b/template-data/templateData.d.ts new file mode 100644 index 0000000..8a9bcd9 --- /dev/null +++ b/template-data/templateData.d.ts @@ -0,0 +1,75 @@ +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 = Profile; + +export type ResearchComponentTemplate = Omit< + ResearchComponent, + "owner" | "version" | "researchObjectID" | "researchObjectVersion" +> & { researchObjectPath: ObjectPath }; + +export type ResearchObjectTemplate = { + title: string; + manifest: string; + metadata?: string; +}; + +export type ClaimTemplate = { + title: string; + description: string; +}; + +export type ResearchFieldTemplate = { + title: string; +}; + +export type ContributorRelationTemplate = { + role: string; + researchObjectPath: ObjectPath; + contributorPath: ObjectPath; +}; + +export type ReferenceRelationTemplate = { + fromPath: ObjectPath; + toPath: ObjectPath; +}; + +export type ResearchFieldRelationTemplate = { + researchObjectPath: ObjectPath; + fieldPath: ObjectPath; +}; + +export type AttestationTemplate = { + targetPath: ObjectPath; + claimPath: ObjectPath; +}; + +export type AnnotationTemplate = { + comment: string; + 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[]; + referenceRelations: ReferenceRelationTemplate[]; + researchFieldRelations: ResearchFieldRelationTemplate[]; + attestations: AttestationTemplate[]; + annotations: AnnotationTemplate[]; +}; + +export type DataTemplate = Record; diff --git a/template_data.json b/template-data/template_data.json similarity index 80% rename from template_data.json rename to template-data/template_data.json index bbac70a..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", @@ -14,10 +15,7 @@ "description": "This research object has a dataset attached" } ], - "researchFields": [ - { "title": "Cosmology" }, - { "title": "Psychology"} - ], + "researchFields": [{ "title": "Cosmology" }, { "title": "Psychology" }], "contributorRelations": [], "referenceRelations": [], "researchFieldRelations": [], @@ -33,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": [], @@ -54,14 +57,12 @@ "fromPath": [ "dc0b1125d15f276c5e6fdaf2465ae9f25d5e9984a7cb062640345c941d3ed1e0", "researchObjects", - 1, - "IDs" + 1 ], "toPath": [ "dc0b1125d15f276c5e6fdaf2465ae9f25d5e9984a7cb062640345c941d3ed1e0", "researchObjects", - 0, - "IDs" + 0 ] } ], @@ -70,8 +71,7 @@ "researchObjectPath": [ "dc0b1125d15f276c5e6fdaf2465ae9f25d5e9984a7cb062640345c941d3ed1e0", "researchObjects", - 0, - "IDs" + 0 ], "fieldPath": [ "1a40e10dc4830864781716eab4f88c60d74d8718cc5ed9af268d338a2096833f", @@ -83,8 +83,7 @@ "researchObjectPath": [ "dc0b1125d15f276c5e6fdaf2465ae9f25d5e9984a7cb062640345c941d3ed1e0", "researchObjects", - 1, - "IDs" + 1 ], "fieldPath": [ "1a40e10dc4830864781716eab4f88c60d74d8718cc5ed9af268d338a2096833f", @@ -106,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 ] } ], @@ -122,8 +127,7 @@ "researchObjectPath": [ "17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015", "researchObjects", - 0, - "IDs" + 0 ], "contributorPath": [ "dc0b1125d15f276c5e6fdaf2465ae9f25d5e9984a7cb062640345c941d3ed1e0", @@ -137,8 +141,7 @@ "researchObjectPath": [ "17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015", "researchObjects", - 0, - "IDs" + 0 ], "fieldPath": [ "1a40e10dc4830864781716eab4f88c60d74d8718cc5ed9af268d338a2096833f", @@ -153,8 +156,7 @@ "targetPath": [ "17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015", "researchObjects", - 0, - "IDs" + 0 ], "claimPath": [ "1a40e10dc4830864781716eab4f88c60d74d8718cc5ed9af268d338a2096833f", @@ -174,10 +176,10 @@ "researchObjects": [ { "title": "Solar Mind Control", - "manifest": "bafkreifixmk6tierh6qompfouk63r6clg5jbeuvwherrxacq4uoedk4o5q", - "components": [] + "manifest": "bafkreifixmk6tierh6qompfouk63r6clg5jbeuvwherrxacq4uoedk4o5q" } ], + "researchComponents": [], "contributorRelations": [], "referenceRelations": [], "researchFieldRelations": [], @@ -187,8 +189,7 @@ "targetPath": [ "17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015", "researchObjects", - 0, - "IDs" + 0 ], "claimPath": [ "1a40e10dc4830864781716eab4f88c60d74d8718cc5ed9af268d338a2096833f", @@ -201,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": [ @@ -216,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 01acb44..ac5d885 100644 --- a/test/root.spec.ts +++ b/test/root.spec.ts @@ -1,7 +1,8 @@ -import { ComposeClient } from '@composedb/client' -import { definition } from '../src/__generated__/definition' -import { RuntimeCompositeDefinition } from '@composedb/types' -import { test, describe, beforeAll, expect } from 'vitest' +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { ComposeClient } from "@composedb/client"; +import { definition } from "../src/__generated__/definition.js"; +import { RuntimeCompositeDefinition } from "@composedb/types"; +import { test, describe, beforeAll, expect } from "vitest"; import { mutationCreateAnnotation, mutationCreateAttestation, @@ -27,72 +28,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 "../src/queries.js"; +import { randomDID } from "./util.js"; +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 "../src/types.js"; +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 +111,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 +186,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 +335,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 +363,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 +382,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 +407,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 +432,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 +458,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 +491,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 +514,7 @@ describe('ComposeDB nodes', () => { targetVersion: researchComponent.commitID, claimID: claim.streamID, - claimVersion: claim.commitID + claimVersion: claim.commitID, }; const annotation = await mutationCreateAnnotation(composeClient, data); @@ -518,22 +532,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 +556,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 +574,7 @@ describe('ComposeDB nodes', () => { targetVersion: question.commitID, claimID: claim.streamID, - claimVersion: claim.commitID + claimVersion: claim.commitID, }; const reply = await mutationCreateAnnotation(composeClient, replyData); @@ -573,63 +590,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 +672,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 +696,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 +713,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 +731,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 +778,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 +802,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,135 +877,136 @@ 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( + // Create version 0 + const { streamID } = await mutationCreateResearchObject( composeClient, - { - id: streamID, - title: 'Title 1' - } + data, ); + await waitAndSync(streamID); + // Create version 1 + await mutationUpdateResearchObject(composeClient, { + id: streamID, + title: "Title 1", + }); await waitAndSync(streamID); - const V2 = await mutationUpdateResearchObject( - composeClient, - { - id: streamID, - title: 'Title 2' - } - ); + // Create version 2 + await mutationUpdateResearchObject(composeClient, { + id: streamID, + title: "Title 2", + }); await waitAndSync(streamID); + const versionToResolve = 1; const stream = await ceramic.loadStream(streamID); // 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,26 +1014,29 @@ 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); 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)); - 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 8ea10b8..ed51cf3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,37 +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": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - "template_data.json" - ], - "exclude": [ - "node_modules" - ] + "resolveJsonModule": true + } } diff --git a/types/index.ts b/types/index.ts deleted file mode 100644 index 6b5e795..0000000 --- a/types/index.ts +++ /dev/null @@ -1,149 +0,0 @@ -export type Profile = { - id?: string - version?: string - displayName?: string - orcid?: string -}; - -export type DID = { - profile?: Profile -}; - -export type ResearchObject = { - id?: string - version?: string - owner?: DID - - title: string - manifest: string - - components?: ResearchComponent[] - - metadata?: string // CID -}; - -export type ResearchComponent = { - owner?: DID - version?: string - - name: string - mimeType: string - - dagNode: string - pathToNode: string - - researchObjectID: string - researchObjectVersion: string - - metadata?: string // CID -}; - -export type Claim = { - id?: string - version?: string - - title: string - description: string - badge?: string -}; - -export type Attestation = { - id?: string - version?: string - source?: DID - - targetID: string - targetVersion: string - - claimID: string - claimVersion: string - claim?: Claim - - revoked: boolean -}; - -export type Annotation = { - id?: string - version?: string - comment: string - - researchObjectID: string - researchObject?: ResearchObject - researchObjectVersion: string - - targetID?: string - targetVersion?: string - - dagNode?: string // CID - pathToNode?: string - - locationOnFile?: string - - claimID?: string - claim?: Claim - claimVersion?: string - - metadataPayload?: string -}; - -export type ContributorRelation = { - id?: string - role: string - - contributorID: string - - researchObjectID: string - researchObjectVersion: string - - revoked: Boolean -}; - -export type ReferenceRelation = { - id?: string - - toID: string - toVersion: string - - fromID: string - fromVersion: string - - revoked: Boolean -}; - -export type ResearchField = { - title: string -}; - -export type ResearchFieldRelation = { - id?: string - fieldID: string - - researchObjectID: string - researchObjectVersion: string -}; - -export type ProtocolEntity = - Profile | - ResearchObject | - ResearchComponent | - Claim | - Attestation | - Annotation | - ContributorRelation | - ReferenceRelation | - ResearchField | - ResearchFieldRelation; - -export type NodeIDs = { - streamID: string, - commitID: string -}; - -export type SidebarProps = { - displayName?: string - id?: string -}; - -export type RequiredKeys = { - [K in keyof T as (undefined extends T[K] ? never : K)]: T[K] -}; diff --git a/utils/index.ts b/utils/index.ts deleted file mode 100644 index 025a558..0000000 --- a/utils/index.ts +++ /dev/null @@ -1,54 +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 deleted file mode 100644 index b903ed5..0000000 --- a/utils/populate.tsx +++ /dev/null @@ -1,301 +0,0 @@ -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, - mutationCreateClaim, - mutationCreateContributorRelation, - mutationCreateProfile, - mutationCreateReferenceRelation, - 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" -import { - AnnotationTemplate, - AttestationTemplate, - ContributorRelationTemplate, - DataTemplate, - ObjectPath, - ReferenceRelationTemplate, - ResearchFieldRelationTemplate, - ResearchObjectTemplate -} from "./templateData" - -const templateData: DataTemplate = untypedTemplateData; - -const didFromSeed = async (seed: string) => { - const keyResolver = KeyDIDResolver.getResolver(); - const key = fromString(seed, "base16") - const did = new DID({ - provider: new Ed25519Provider(key), - resolver: { - ...keyResolver, - }, - }); - await did.authenticate(); - return did; -}; - -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(` - query { - profileIndex(first: 1) { - edges { - node { - id - } - } - } - } - `) as ProfileIndexResults; - - if (firstProfile.data.profileIndex.edges.length === 0) { - console.log("Profile index empty, loading template data...") - await loadTemplateData(composeClient) - } else { - 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 - researchObjects: { - 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: [] - } -); - -type StreamIndex = Record; - -/** - * Iterates over template data file, and with a DID generated from each root entry - * 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)) - - const profileIDs = await mutationCreateProfile(composeClient, template.profile); - streamIndex[seed] = freshActorRecord(profileIDs); - - streamIndex[seed].researchFields = await Promise.all( - template.researchFields.map( - rfTemplate => mutationCreateResearchField(composeClient, rfTemplate) - ) - ); - - streamIndex[seed].researchObjects = await Promise.all( - template.researchObjects.map( - roTemplate => loadResearchObject(roTemplate, composeClient) - ) - ); - - streamIndex[seed].contributorRelations = await Promise.all( - template.contributorRelations.map((contTemplate: any) => - loadContributorRelation(contTemplate, streamIndex, composeClient) - ) - ); - - streamIndex[seed].referenceRelations = await Promise.all( - template.referenceRelations.map((refTemplate: any) => - loadReferenceRelation(refTemplate, streamIndex, composeClient) - ) - ); - - streamIndex[seed].researchFieldRelations = await Promise.all( - template.researchFieldRelations.map((fieldRelTemplate: any) => - loadResearchFieldRelation(fieldRelTemplate, streamIndex, composeClient) - ) - ); - - streamIndex[seed].claims = await Promise.all( - template.claims.map(c => mutationCreateClaim(composeClient, c)) - ); - - streamIndex[seed].attestations = await Promise.all( - template.attestations.map(attTemplate => loadAttestation( - attTemplate, streamIndex, composeClient - )) - ); - - streamIndex[seed].annotations = await Promise.all( - template.annotations.map(annTemplate => loadAnnotation( - annTemplate, streamIndex, composeClient - )) - ); - }; - console.log("Loading template data done!"); -} - -const loadResearchObject = async ( - roTemplate: ResearchObjectTemplate, - composeClient: ComposeClient -): Promise => { - const roProps: ResearchObject = { - title: roTemplate.title, - 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: "." - } - ) - ) - ); - - return { IDs: researchObject, components }; -}; - -const loadContributorRelation = async ( - contTemplate: ContributorRelationTemplate, - streamIndex: StreamIndex, - 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 - } - ); -}; - -const loadReferenceRelation = async ( - refTemplate: ReferenceRelationTemplate, - streamIndex: StreamIndex, - 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 - } - ); -}; - -const loadResearchFieldRelation = async ( - fieldRelTemplate: ResearchFieldRelationTemplate, - streamIndex: StreamIndex, - 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 - } - ); -}; - -const loadAttestation = async ( - attestationTemplate: AttestationTemplate, - streamIndex: StreamIndex, - composeClient: ComposeClient -): Promise => { - const { targetPath, claimPath } = attestationTemplate; - const target = recursePathToID(streamIndex, targetPath); - const claim = recursePathToID(streamIndex, claimPath); - const attestation: Attestation = { - targetID: target.streamID, - targetVersion: target.commitID, - claimID: claim.streamID, - claimVersion: claim.commitID, - revoked: false - }; - return mutationCreateAttestation(composeClient, attestation); -}; - -const loadAnnotation = async ( - annotationTemplate: AnnotationTemplate, - streamIndex: StreamIndex, - composeClient: ComposeClient -): Promise => { - const { comment, path, targetPath, claimPath } = annotationTemplate; - const target = recursePathToID(streamIndex, targetPath); - const annotation: Annotation = { - targetID: target.streamID, - targetVersion: target.commitID, - 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); -}; - -// Oblivious to human faults, enjoy the footgun -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 deleted file mode 100644 index 6725e09..0000000 --- a/utils/queries.ts +++ /dev/null @@ -1,689 +0,0 @@ -import { ComposeClient } from "@composedb/client"; -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 -): Promise => { - const response = await composeClient.executeQuery<{ viewer: { id: string } }>(` - query { - 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 -): Promise => { - const response = await composeClient.executeQuery<{ viewer: { profile: Profile | null } }>(` - query { - viewer { - profile { - id - displayName - orcid - } - } - }` - ) - assertQueryErrors(response, 'viewer profile') - return response.data!.viewer.profile -} - -export const queryViewerResearchObjects = async ( - composeClient: ComposeClient -): Promise => { - const response = await composeClient.executeQuery< - { viewer: { researchObjectList: { edges: { node: ResearchObject }[] } } } - >(` - query { - viewer { - researchObjectList(first: 100) { - edges { - node { - id - title - manifest - } - } - } - } - } - `) - assertQueryErrors(response, 'viewer research objects') - return response.data!.viewer.researchObjectList.edges.map(e => e.node) -} - -export const queryViewerClaims = async ( - composeClient: ComposeClient -): Promise => { - const response = await composeClient.executeQuery< - { viewer: { claimList: { edges: { node: Claim }[] } } } - >(` - query { - viewer { - claimList(first: 100) { - edges { - node { - id - title - description - badge - } - } - } - } - } - `) - assertQueryErrors(response, 'viewer claims') - return response.data!.viewer.claimList.edges.map(e => e.node) -} - -export const queryResearchObjects = async ( - composeClient: ComposeClient -): Promise => { - const response = await composeClient.executeQuery< - { researchObjectIndex: { edges: { node: ResearchObject }[] } } - >(` - query { - researchObjectIndex(first: 100) { - edges { - node { - id - title - manifest - owner { - profile { - displayName - orcid - } - } - } - } - } - } - `) - assertQueryErrors(response, 'research objects') - return response.data!.researchObjectIndex.edges.map(e => e.node) -} - -export const queryResearchObjectAttestations = async ( - composeClient: ComposeClient, - researchObjectID: string -) => { - const response = await composeClient.executeQuery< - { node: { attestations: { edges: { node: Attestation }[] } } } - >(` - query ($id: ID!) { - node(id: $id) { - ... on ResearchObject { - attestations(first: 10) { - edges { - node { - claim { - title - } - source { - profile { - displayName - } - } - } - } - } - } - } - } - `, { 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" -}; - -export const mutationCreateResearchObject = async ( - composeClient: ComposeClient, - 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' -); - -const COMPONENT_TYPE_MAP = { - name: "String!", - mimeType: "String!", - metadata: "InterPlanetaryCID", - dagNode: "InterPlanetaryCID!", - pathToNode: "String!", - researchObjectID: "CeramicStreamID!", - researchObjectVersion: "CeramicCommitID!" -}; - -export const mutationCreateResearchComponent = async ( - composeClient: ComposeClient, - 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' -); - -export const mutationCreateProfile = async ( - composeClient: ComposeClient, - 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' -); - -const ATTESTATION_TYPE_MAP = { - targetID: "CeramicStreamID!", - targetVersion: "CeramicCommitID!", - claimID: "CeramicStreamID!", - claimVersion: "CeramicCommitID!", - revoked: "Boolean" -}; - -export const mutationCreateAttestation = async ( - composeClient: ComposeClient, - 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' -); - -const ANNOTATION_TYPE_MAP = { - comment: "String!", - researchObjectID: "CeramicStreamID!", - researchObjectVersion: "CeramicCommitID!", - targetID: "CeramicStreamID!", - targetVersion: "CeramicCommitID!", - dagNode: "InterPlanetaryCID", - pathToNode: "String", - locationOnFile: "String", - claimID: "CeramicStreamID", - claimVersion: "CeramicCommitID", - metadataPayload: "InterPlanetaryCID" -}; - -export const mutationCreateAnnotation = async ( - composeClient: ComposeClient, - 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' -); - -const CONTRIBUTOR_TYPE_MAP = { - role: "String!", - contributorID: "CeramicStreamID!", - researchObjectID: "CeramicStreamID!", - researchObjectVersion: "CeramicCommitID!", - revoked: "Boolean!" -}; -export const mutationCreateContributorRelation = async ( - composeClient: ComposeClient, - 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' -); - -const REFERENCE_TYPE_MAP = { - toID: "CeramicStreamID!", - toVersion: "CeramicCommitID!", - fromID: "CeramicStreamID!", - fromVersion: "CeramicCommitID!", - revoked: "Boolean!" -}; - -export const mutationCreateReferenceRelation = async ( - composeClient: ComposeClient, - 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' -); - -export const mutationCreateResearchFieldRelation = async ( - composeClient: ComposeClient, - 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' -); - -export const queryResearchObject = async ( - composeClient: ComposeClient, - id: string, - 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 ?? - ` - displayName - orcid - ` -); - -export const queryClaim = async ( - composeClient: ComposeClient, - id: string, - 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 ?? - ` - targetID - targetVersion - claimID - claimVersion - revoked - ` -); - -export const queryResearchComponent = async ( - composeClient: ComposeClient, - id: string, - selection?: string -): Promise => genericEntityQuery( - composeClient, - id, - 'ResearchComponent', - selection ?? - ` - name - mimeType - metadata - dagNode - pathToNode - researchObjectID - researchObjectVersion - ` -); - -export const queryAnnotation = async ( - composeClient: ComposeClient, - id: string, - selection?: string -): Promise => genericEntityQuery( - composeClient, - id, - 'Annotation', - selection ?? - ` - comment - researchObjectID - researchObjectVersion - targetID - targetVersion - dagNode - pathToNode - locationOnFile - claimID - claimVersion - metadataPayload - ` -); - -export const queryContributorRelation = async ( - composeClient: ComposeClient, - id: string, - 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 ?? - ` - fromID - fromVersion - toID - toVersion - revoked - ` -); - -export const queryResearchFields = async ( - composeClient: ComposeClient, - id: string, - 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 ?? - ` - fieldID - researchObjectID - researchObjectVersion - ` -); - -export async function genericEntityQuery( - composeClient: ComposeClient, - id: string, - entityName: string, - // Specify the field structure to query for - selection: string -): Promise { - const query = ` - query($id: ID!) { - node(id: $id) { - ...on ${entityName} { - ${selection} - } - } - } - `; - 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. - */ - gqlTypes: Partial>, - mutationName: string, - /** Skip timeout for single accountRelation entities */ - noTimeout?: boolean -): Promise { - const [params, content] = getQueryFields(gqlTypes as Record, inputs); - const response = await composeClient.executeQuery(` - mutation( ${params} ) { - ${mutationName}(input: { - content: { ${content} } - ${noTimeout ? "options: { syncTimeout: 0 }" : ""} - }) - { - document { - id - version - } - } - }`, inputs - ) as any; - assertMutationErrors(response, mutationName); - const nodeIDs: NodeIDs = { - streamID: response.data[mutationName].document.id, - commitID: response.data[mutationName].document.version - }; - return nodeIDs; -}; - -async function genericUpdate( - composeClient: ComposeClient, - inputs: Partial & { id: string }, - // See note in genericCreate - gqlTypes: Partial>, - mutationName: string, -): Promise { - const [params, content] = getQueryFields(gqlTypes as Record, inputs); - const response = await composeClient.executeQuery(` - mutation($id: ID!, ${params} ) { - ${mutationName}( - input: { - id: $id - content: { ${content} } - } - ) - { - document { - id - version - } - } - }`, inputs - ) as any; - assertMutationErrors(response, mutationName); - const nodeIDs: NodeIDs = { - streamID: response.data[mutationName].document.id, - commitID: response.data[mutationName].document.version - }; - return nodeIDs; -} - -type SimpleMutationResult = Pick -type SimpleQueryResult = Pick - -const assertMutationErrors = ( - result: SimpleMutationResult, - queryDescription: string -) => { - if (result.errors) { - console.error('Error:', result.errors.toString()); - throw new Error(`Mutation failed: ${queryDescription}`) - }; -} - -const assertQueryErrors = ( - result: SimpleQueryResult, - 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. -*/ -const getQueryFields = ( - graphQLParamTypes: Record, - inputs: Record -) => - Object.keys(inputs) - .filter(p => p !== 'id') - .reduce<[string[], string[]]>( - (acc, next) => [ - [...acc[0], `$${next}: ${graphQLParamTypes[next]}`], - [...acc[1], `${next}: $${next}`] - ], - [[], []] - ).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 diff --git a/utils/templateData.d.ts b/utils/templateData.d.ts deleted file mode 100644 index a39d6f2..0000000 --- a/utils/templateData.d.ts +++ /dev/null @@ -1,72 +0,0 @@ -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 ComponentTemplate = { - name: string, - dagNode: string, - mimeType: string -}; - -export type ResearchObjectTemplate = { - title: string, - manifest: string, - components: ComponentTemplate[] -}; - -export type ClaimTemplate = { - title: string, - description: string -} - -export type ResearchFieldTemplate = { - title: string -}; - -export type ContributorRelationTemplate = { - role: string, - researchObjectPath: ObjectPath, - contributorPath: ObjectPath -}; - -export type ReferenceRelationTemplate = { - fromPath: ObjectPath, - toPath: ObjectPath -}; - -export type ResearchFieldRelationTemplate = { - researchObjectPath: ObjectPath, - fieldPath: ObjectPath -}; - -export type AttestationTemplate = { - targetPath: ObjectPath, - claimPath: ObjectPath -}; - -export type AnnotationTemplate = { - 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[] -}; - -export type DataTemplate = Record diff --git a/vitest.config.ts b/vitest.config.ts index a8e550e..fc13e8a 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 { defineConfig } from "vitest/config"; +import GithubActionsReporter from "vitest-github-actions-reporter"; export default defineConfig({ test: { - include: ["test/**/*.spec.ts"] + include: ["test/**/*.spec.ts"], + reporters: process.env.GITHUB_ACTIONS + ? ["verbose", new GithubActionsReporter()] + : "verbose", }, - plugins: [tsconfigPaths()] -}) \ No newline at end of file +});