diff --git a/.gitignore b/.gitignore index a9157706ae..ef8b36916c 100644 --- a/.gitignore +++ b/.gitignore @@ -64,4 +64,6 @@ apps/remixdesktop/release/ apps/remix-ide/src/assets/list.json apps/remix-ide/src/assets/esbuild.wasm apps/remixdesktop/build* -logs \ No newline at end of file +apps/remixdesktop/reports/ +apps/remixdesktop/logs/ +logs diff --git a/apps/remix-ide-e2e/src/tests/plugin_api.ts b/apps/remix-ide-e2e/src/tests/plugin_api.ts index 69bbc140ca..557b15db92 100644 --- a/apps/remix-ide-e2e/src/tests/plugin_api.ts +++ b/apps/remix-ide-e2e/src/tests/plugin_api.ts @@ -10,7 +10,7 @@ declare global { const localPluginData: Profile & LocationProfile & ExternalProfile = { name: 'localPlugin', displayName: 'Local Plugin', - canActivate: ['dGitProvider', 'flattener', 'solidityUnitTesting', 'udapp', 'hardhat-provider'], + canActivate: ['dgitApi', 'flattener', 'solidityUnitTesting', 'udapp', 'hardhat-provider'], url: 'http://localhost:9999', location: 'sidePanel' } diff --git a/apps/remix-ide-e2e/src/tests/workspace_git.test.ts b/apps/remix-ide-e2e/src/tests/workspace_git.test.ts index 16870069e3..758fa340a2 100644 --- a/apps/remix-ide-e2e/src/tests/workspace_git.test.ts +++ b/apps/remix-ide-e2e/src/tests/workspace_git.test.ts @@ -139,7 +139,7 @@ module.exports = { .click('[data-id="fileSystem-modal-footer-ok-react"]') .pause(5000) .waitForElementVisible('[data-id="cloneGitRepositoryModalDialogModalBody-react"]') - .waitForElementContainsText('[data-id="cloneGitRepositoryModalDialogModalBody-react"]', 'An error occurred: Please check that you have the correct URL for the repo. If the repo is private, you need to add your github credentials (with the valid token permissions) in Settings plugin') + .waitForElementContainsText('[data-id="cloneGitRepositoryModalDialogModalBody-react"]', 'An error occurred: Please check that you have the correct URL for the repo. If the repo is private, you need to add your github credentials (with the valid token permissions) in the Git plugin') .click('[data-id="cloneGitRepository-modal-footer-ok-react"]') }, diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js index 1fa9e2f8f7..ac53fa471b 100644 --- a/apps/remix-ide/src/app.js +++ b/apps/remix-ide/src/app.js @@ -54,6 +54,7 @@ import { electronTemplates } from './app/plugins/electron/templatesPlugin' import { xtermPlugin } from './app/plugins/electron/xtermPlugin' import { ripgrepPlugin } from './app/plugins/electron/ripgrepPlugin' import { compilerLoaderPlugin, compilerLoaderPluginDesktop } from './app/plugins/electron/compilerLoaderPlugin' +import { GitPlugin } from './app/plugins/git' import {OpenAIGpt} from './app/plugins/openaigpt' import {SolCoder} from './app/plugins/solcoderAI' @@ -219,6 +220,9 @@ class AppComponent { //---- templates const templates = new TemplatesPlugin() + //---- git + const git = new GitPlugin() + //---------------- Solidity UML Generator ------------------------- const solidityumlgen = new SolidityUmlGen(appManager) @@ -354,6 +358,7 @@ class AppComponent { templates, openaigpt, solcoder, + git, pluginStateLogger ]) @@ -494,7 +499,7 @@ class AppComponent { ]) await this.appManager.activatePlugin(['settings']) - await this.appManager.activatePlugin(['walkthrough', 'storage', 'search', 'compileAndRun', 'recorder']) + await this.appManager.activatePlugin(['walkthrough', 'storage', 'search', 'compileAndRun', 'recorder', 'dgit']) await this.appManager.activatePlugin(['solidity-script', 'remix-templates']) if (isElectron()){ diff --git a/apps/remix-ide/src/app/editor/editor.js b/apps/remix-ide/src/app/editor/editor.js index 9647c88ad4..92e0a637a9 100644 --- a/apps/remix-ide/src/app/editor/editor.js +++ b/apps/remix-ide/src/app/editor/editor.js @@ -5,6 +5,7 @@ import { EditorUI } from '@remix-ui/editor' // eslint-disable-line import { Plugin } from '@remixproject/engine' import * as packageJson from '../../../../../package.json' import { PluginViewWrapper } from '@remix-ui/helper' +import { commitChange } from '@remix-ui/git' const EventManager = require('../../lib/events') @@ -13,7 +14,7 @@ const profile = { name: 'editor', description: 'service - editor', version: packageJson.version, - methods: ['highlight', 'discardHighlight', 'clearAnnotations', 'addLineText', 'discardLineTexts', 'addAnnotation', 'gotoLine', 'revealRange', 'getCursorPosition', 'open', 'addModel','addErrorMarker', 'clearErrorMarkers', 'getText', 'getPositionAt'], + methods: ['highlight', 'discardHighlight', 'clearAnnotations', 'addLineText', 'discardLineTexts', 'addAnnotation', 'gotoLine', 'revealRange', 'getCursorPosition', 'open', 'addModel','addErrorMarker', 'clearErrorMarkers', 'getText', 'getPositionAt', 'openReadOnly'], } class Editor extends Plugin { @@ -63,7 +64,8 @@ class Editor extends Plugin { onBreakPointAdded: (file, line) => this.triggerEvent('breakpointAdded', [file, line]), onBreakPointCleared: (file, line) => this.triggerEvent('breakpointCleared', [file, line]), onDidChangeContent: (file) => this._onChange(file), - onEditorMounted: () => this.triggerEvent('editorMounted', []) + onEditorMounted: () => this.triggerEvent('editorMounted', []), + onDiffEditorMounted: () => this.triggerEvent('diffEditorMounted', []) } // to be implemented by the react component @@ -81,8 +83,10 @@ class Editor extends Plugin { editorAPI={state.api} themeType={state.currentThemeType} currentFile={state.currentFile} + currentDiffFile={state.currentDiffFile} events={state.events} plugin={state.plugin} + isDiff={state.isDiff} /> } @@ -111,6 +115,8 @@ class Editor extends Plugin { api: this.api, currentThemeType: this.currentThemeType, currentFile: this.currentFile, + currentDiffFile: this.currentDiffFile, + isDiff: this.isDiff, events: this.events, plugin: this }) @@ -183,9 +189,10 @@ class Editor extends Plugin { } _switchSession (path) { - if (path === this.currentFile) return - this.triggerEvent('sessionSwitched', []) - this.currentFile = path + if (path !== this.currentFile) { + this.triggerEvent('sessionSwitched', []) + this.currentFile = path + } this.renderComponent() } @@ -241,10 +248,10 @@ class Editor extends Plugin { * @param {string} content Content of the file to open * @param {string} mode Mode for this file [Default is `text`] */ - async _createSession (path, content, mode) { + async _createSession (path, content, mode, readOnly) { if (!this.activated) return - this.emit('addModel', content, mode, path, this.readOnlySessions[path]) + this.emit('addModel', content, mode, path, readOnly || this.readOnlySessions[path]) return { path, language: mode, @@ -314,6 +321,7 @@ class Editor extends Plugin { - URL prepended with "browser" - URL not prepended with the file explorer. We assume (as it is in the whole app, that this is a "browser" URL */ + this.isDiff = false if (!this.sessions[path]) { this.readOnlySessions[path] = false const session = await this._createSession(path, content, this._getMode(path)) @@ -335,9 +343,22 @@ class Editor extends Plugin { const session = await this._createSession(path, content, this._getMode(path)) this.sessions[path] = session } + this.isDiff = false this._switchSession(path) } + async openDiff(change) { + console.log('openDiff', change) + const hashedPathModified = change.readonly ? change.path + change.hashModified : change.path + const hashedPathOriginal = change.path + change.hashOriginal + const session = await this._createSession(hashedPathModified, change.modified, this._getMode(change.path), change.readonly) + await this._createSession(hashedPathOriginal, change.original, this._getMode(change.path), change.readonly) + this.sessions[hashedPathModified] = session + this.currentDiffFile = hashedPathOriginal + this.isDiff = true + this._switchSession(hashedPathModified) + } + /** * Content of the current session * @return {String} content of the file referenced by @arg path diff --git a/apps/remix-ide/src/app/files/dgitProvider.ts b/apps/remix-ide/src/app/files/dgitProvider.ts index 10d2c76c7a..dce9e72688 100644 --- a/apps/remix-ide/src/app/files/dgitProvider.ts +++ b/apps/remix-ide/src/app/files/dgitProvider.ts @@ -3,7 +3,7 @@ import { Plugin } from '@remixproject/engine' -import git from 'isomorphic-git' +import git, { ReadBlobResult, ReadCommitResult, StatusRow } from 'isomorphic-git' import IpfsHttpClient from 'ipfs-http-client' import { saveAs @@ -15,14 +15,26 @@ import path from 'path' import FormData from 'form-data' import axios from 'axios' import { Registry } from '@remix-project/remix-lib' +import { Octokit, App } from "octokit" +import { OctokitResponse } from '@octokit/types' +import { Endpoints } from "@octokit/types" +import { IndexedDBStorage } from './filesystems/indexedDB' +import { GitHubUser, RateLimit, branch, commitChange, remote, pagedCommits, remoteCommitsInputType, cloneInputType, fetchInputType, pullInputType, pushInputType, currentBranchInput, branchInputType, addInput, rmInput, resolveRefInput, readBlobInput, repositoriesInput, commitInput, branchDifference, compareBranchesInput, initInput, userEmails } from '@remix-ui/git' +import { LibraryProfile, StatusEvents } from '@remixproject/plugin-utils' +import { ITerminal } from '@remixproject/plugin-api/src/lib/terminal' + +declare global { + interface Window { remixFileSystemCallback: IndexedDBStorage; remixFileSystem: any; } +} -const profile = { - name: 'dGitProvider', +const profile: LibraryProfile = { + name: 'dgitApi', displayName: 'Decentralized git', description: 'Decentralized git provider', icon: 'assets/img/fileManager.webp', version: '0.0.1', - methods: ['init', 'localStorageUsed', 'addremote', 'delremote', 'remotes', 'fetch', 'clone', 'export', 'import', 'status', 'log', 'commit', 'add', 'remove', 'reset', 'rm', 'lsfiles', 'readblob', 'resolveref', 'branches', 'branch', 'checkout', 'currentbranch', 'push', 'pin', 'pull', 'pinList', 'unPin', 'setIpfsConfig', 'zip', 'setItem', 'getItem', 'version', 'updateSubmodules'], + methods: ['init', 'localStorageUsed', 'addremote', 'delremote', 'remotes', 'fetch', 'clone', 'export', 'import', 'status', 'log', 'commit', 'add', 'remove', 'reset', 'rm', 'lsfiles', 'readblob', 'resolveref', 'branches', 'branch', 'checkout', 'currentbranch', 'push', 'pull', 'setIpfsConfig', 'zip', 'setItem', 'getItem', 'version', 'updateSubmodules' + , 'getGitHubUser', 'remotebranches', 'remotecommits', 'repositories', 'getCommitChanges', 'compareBranches'], kind: 'file-system' } class DGitProvider extends Plugin { @@ -55,7 +67,7 @@ class DGitProvider extends Plugin { this.ipfsSources = [this.remixIPFS, this.globalIPFSConfig, this.ipfsconfig] } - async getGitConfig(dir = '') { + async addIsomorphicGitConfigFS(dir = '') { if ((Registry.getInstance().get('platform').api.isDesktop())) { return { @@ -73,14 +85,15 @@ class DGitProvider extends Plugin { } } - async parseInput(input) { + async addIsomorphicGitConfig(input) { + const token = await this.call('config' as any, 'getAppParameter', 'settings/gist-access-token') return { corsProxy: 'https://corsproxy.remixproject.org/', http, onAuth: url => { url const auth = { - username: input.token, + username: input.token || token, password: '' } return auth @@ -88,18 +101,45 @@ class DGitProvider extends Plugin { } } - async init(input?) { + async getCommandUser(input) { + const author = { + name: '', + email: '' + } + if (input && input.name && input.email) { + author.name = input.name + author.email = input.email + } else { + const username = await this.call('config' as any, 'getAppParameter', 'settings/github-user-name') + const email = await this.call('config' as any, 'getAppParameter', 'settings/github-email') + const token = await this.call('config' as any, 'getAppParameter', 'settings/gist-access-token') + if (username && email) { + author.name = username + author.email = email + } else if (token) { + console.log('token', token) + const gitHubUser = await this.getGitHubUser({ token }) + console.log('gitHubUser', gitHubUser) + if (gitHubUser) { + author.name = gitHubUser.user.login + } + } + } + return author + } + + async init(input?: initInput): Promise { if ((Registry.getInstance().get('platform').api.isDesktop())) { await this.call('isogit', 'init', { - defaultBranch: (input && input.branch) || 'main' + defaultBranch: (input && input.defaultBranch) || 'main' }) this.emit('init') return } await git.init({ - ...await this.getGitConfig(), - defaultBranch: (input && input.branch) || 'main' + ...await this.addIsomorphicGitConfigFS(), + defaultBranch: (input && input.defaultBranch) || 'main' }) this.emit('init') } @@ -113,7 +153,7 @@ class DGitProvider extends Plugin { return version } - async status(cmd) { + async status(cmd): Promise> { if ((Registry.getInstance().get('platform').api.isDesktop())) { const status = await this.call('isogit', 'status', cmd) @@ -122,20 +162,20 @@ class DGitProvider extends Plugin { } const status = await git.statusMatrix({ - ...await this.getGitConfig(), + ...await this.addIsomorphicGitConfigFS(), ...cmd }) return status } - async add(cmd) { + async add(cmd: addInput): Promise { if ((Registry.getInstance().get('platform').api.isDesktop())) { await this.call('isogit', 'add', cmd) } else { await git.add({ - ...await this.getGitConfig(), + ...await this.addIsomorphicGitConfigFS(), ...cmd }) } @@ -143,13 +183,13 @@ class DGitProvider extends Plugin { this.emit('add') } - async rm(cmd) { + async rm(cmd: rmInput) { if ((Registry.getInstance().get('platform').api.isDesktop())) { await this.call('isogit', 'rm', cmd) } else { await git.remove({ - ...await this.getGitConfig(), + ...await this.addIsomorphicGitConfigFS(), ...cmd }) this.emit('rm') @@ -163,7 +203,7 @@ class DGitProvider extends Plugin { await this.call('isogit', 'reset', cmd) } else { await git.resetIndex({ - ...await this.getGitConfig(), + ...await this.addIsomorphicGitConfigFS(), ...cmd }) this.emit('rm') @@ -178,7 +218,7 @@ class DGitProvider extends Plugin { } else { const gitmodules = await this.parseGitmodules() || [] await git.checkout({ - ...await this.getGitConfig(), + ...await this.addIsomorphicGitConfigFS(), ...cmd }) const newgitmodules = await this.parseGitmodules() || [] @@ -190,12 +230,12 @@ class DGitProvider extends Plugin { }) for (const module of toRemove) { - const path = (await this.getGitConfig(module.path)).dir + const path = (await this.addIsomorphicGitConfigFS(module.path)).dir if (await window.remixFileSystem.exists(path)) { const stat = await window.remixFileSystem.stat(path) try { if (stat.isDirectory()) { - await window.remixFileSystem.unlink((await this.getGitConfig(module.path)).dir) + await window.remixFileSystem.unlink((await this.addIsomorphicGitConfigFS(module.path)).dir) } } catch (e) { // do nothing @@ -212,7 +252,7 @@ class DGitProvider extends Plugin { this.emit('checkout') } - async log(cmd) { + async log(cmd:{ref:string}):Promise { if ((Registry.getInstance().get('platform').api.isDesktop())) { const status = await this.call('isogit', 'log', { @@ -224,39 +264,125 @@ class DGitProvider extends Plugin { } const status = await git.log({ - ...await this.getGitConfig(), + ...await this.addIsomorphicGitConfigFS(), ...cmd, - depth: 10 }) return status } - async remotes(config) { + async compareBranches({ branch, remote }: compareBranchesInput): Promise { + // Get current branch commits + const headCommits = await git.log({ + ...await this.addIsomorphicGitConfigFS(), + ref: branch.name, + }); + + // Get remote branch commits + const remoteCommits = await git.log({ + ...await this.addIsomorphicGitConfigFS(), + ref: `${remote.name}/${branch.name}`, + }); + + // Convert arrays of commit objects to sets of commit SHAs + const headCommitSHAs = new Set(headCommits.map(commit => commit.oid)); + const remoteCommitSHAs = new Set(remoteCommits.map(commit => commit.oid)); + + // Filter out commits that are only in the remote branch + const uniqueRemoteCommits = remoteCommits.filter(commit => !headCommitSHAs.has(commit.oid)); + + // filter out commits that are only in the local branch + const uniqueHeadCommits = headCommits.filter(commit => !remoteCommitSHAs.has(commit.oid)); + + return { + uniqueHeadCommits, + uniqueRemoteCommits, + }; + } + + async getCommitChanges(commitHash1: string, commitHash2: string): Promise { + //console.log(commitHash1, commitHash2, [git.TREE({ ref: commitHash1 }), git.TREE({ ref: commitHash2 })]) + const result: commitChange[] = await git.walk({ + ...await this.addIsomorphicGitConfigFS(), + trees: [git.TREE({ ref: commitHash1 }), git.TREE({ ref: commitHash2 })], + map: async function (filepath, [A, B]) { + // ignore directories + + //console.log(filepath, A, B) + + if (filepath === '.') { + return + } + try { + if ((A && await A.type()) === 'tree' || B && (await B.type()) === 'tree') { + return + } + } catch (e) { + // ignore + } + + // generate ids + const Aoid = A && await A.oid() || undefined + const Boid = B && await B.oid() || undefined + + const commitChange: Partial = { + hashModified: commitHash1, + hashOriginal: commitHash2, + path: filepath, + } + + //console.log('Aoid', Aoid, 'Boid', Boid, commitChange) + + // determine modification type + if (Aoid !== Boid) { + commitChange.type = "modified" + } + if (Aoid === undefined) { + commitChange.type = "deleted" + } + if (Boid === undefined || !commitHash2) { + commitChange.type = "added" + } + if (Aoid === undefined && Boid === undefined) { + commitChange.type = "unknown" + } + if (commitChange.type) + return commitChange + else + return undefined + }, + }) + //console.log(result) + return result + } + + async remotes(config): Promise { if ((Registry.getInstance().get('platform').api.isDesktop())) { return await this.call('isogit', 'remotes', config) } - let remotes = [] + let remotes: remote[] = [] try { - remotes = await git.listRemotes({ ...config ? config : await this.getGitConfig() }) + remotes = (await git.listRemotes({ ...config ? config : await this.addIsomorphicGitConfigFS() })).map((remote) => + { return { name: remote.remote, url: remote.url } } + ) } catch (e) { // do nothing } return remotes } - async branch(cmd, refresh = true) { + async branch(cmd: branchInputType): Promise { let status if ((Registry.getInstance().get('platform').api.isDesktop())) { status = await this.call('isogit', 'branch', cmd) } else { status = await git.branch({ - ...await this.getGitConfig(), + ...await this.addIsomorphicGitConfigFS(), ...cmd }) } - if (refresh) { + if (cmd.refresh) { setTimeout(async () => { await this.call('fileManager', 'refresh') }, 1000) @@ -265,38 +391,59 @@ class DGitProvider extends Plugin { return status } - async currentbranch(config) { + async currentbranch(config: currentBranchInput): Promise { if ((Registry.getInstance().get('platform').api.isDesktop())) { return await this.call('isogit', 'currentbranch') } try { - const defaultConfig = await this.getGitConfig() + const defaultConfig = await this.addIsomorphicGitConfigFS() const cmd = config ? defaultConfig ? { ...defaultConfig, ...config } : config : defaultConfig const name = await git.currentBranch(cmd) + console.log('current branch', name) + let remote: remote = undefined + try { + const remoteName = await git.getConfig({ + ...defaultConfig, + path: `branch.${name}.remote` + }) + if (remoteName) { + const remoteUrl = await git.getConfig({ + ...defaultConfig, + path: `remote.${remoteName}.url` + }) + remote = { name: remoteName, url: remoteUrl } + } - return name + } catch (e) { + // do nothing + } + + return { + remote: remote, + name: name || '' + } } catch (e) { - return '' + return undefined } } - async branches(config) { + async branches(config): Promise { if ((Registry.getInstance().get('platform').api.isDesktop())) { return await this.call('isogit', 'branches') } try { - const defaultConfig = await this.getGitConfig() + const defaultConfig = await this.addIsomorphicGitConfigFS() const cmd = config ? defaultConfig ? { ...defaultConfig, ...config } : config : defaultConfig const remotes = await this.remotes(config) - let branches = [] + let branches: branch[] = [] branches = (await git.listBranches(cmd)).map((branch) => { return { remote: undefined, name: branch } }) for (const remote of remotes) { - cmd.remote = remote.remote - const remotebranches = (await git.listBranches(cmd)).map((branch) => { return { remote: remote.remote, name: branch } }) + cmd.remote = remote.name + const remotebranches = (await git.listBranches(cmd)).map((branch) => { return { remote: remote, name: branch } }) branches = [...branches, ...remotebranches] } return branches @@ -305,7 +452,7 @@ class DGitProvider extends Plugin { } } - async commit(cmd) { + async commit(cmd: commitInput): Promise { if ((Registry.getInstance().get('platform').api.isDesktop())) { try { @@ -321,7 +468,7 @@ class DGitProvider extends Plugin { await this.init() try { const sha = await git.commit({ - ...await this.getGitConfig(), + ...await this.addIsomorphicGitConfigFS(), ...cmd }) this.emit('commit') @@ -339,32 +486,32 @@ class DGitProvider extends Plugin { } const filesInStaging = await git.listFiles({ - ...await this.getGitConfig(), + ...await this.addIsomorphicGitConfigFS(), ...cmd }) return filesInStaging } - async resolveref(cmd) { + async resolveref(cmd: resolveRefInput): Promise { if ((Registry.getInstance().get('platform').api.isDesktop())) { return await this.call('isogit', 'resolveref', cmd) } const oid = await git.resolveRef({ - ...await this.getGitConfig(), + ...await this.addIsomorphicGitConfigFS(), ...cmd }) return oid } - async readblob(cmd) { + async readblob(cmd: readBlobInput): Promise { if ((Registry.getInstance().get('platform').api.isDesktop())) { const readBlobResult = await this.call('isogit', 'readblob', cmd) return readBlobResult } const readBlobResult = await git.readBlob({ - ...await this.getGitConfig(), + ...await this.addIsomorphicGitConfigFS(), ...cmd }) @@ -388,27 +535,27 @@ class DGitProvider extends Plugin { } } - async addremote(input) { + async addremote(input: remote): Promise { if ((Registry.getInstance().get('platform').api.isDesktop())) { - await this.call('isogit', 'addremote', { url: input.url, remote: input.remote }) + await this.call('isogit', 'addremote', { url: input.url, remote: input.name }) return } - await git.addRemote({ ...await this.getGitConfig(), url: input.url, remote: input.remote }) + await git.addRemote({ ...await this.addIsomorphicGitConfigFS(), url: input.url, remote: input.name }) } - async delremote(input) { + async delremote(input: remote) { if ((Registry.getInstance().get('platform').api.isDesktop())) { - await this.call('isogit', 'delremote', { remote: input.remote }) + await this.call('isogit', 'delremote', { remote: input.name }) return } - await git.deleteRemote({ ...await this.getGitConfig(), remote: input.remote }) + await git.deleteRemote({ ...await this.addIsomorphicGitConfigFS(), remote: input.name }) } async localStorageUsed() { return this.calculateLocalStorage() } - async clone(input, workspaceName, workspaceExists = false) { + async clone(input: cloneInputType) { if ((Registry.getInstance().get('platform').api.isDesktop())) { const folder = await this.call('fs', 'selectFolder', null, 'Select or create a folder to clone the repository in', 'Select as Repository Destination') @@ -436,18 +583,18 @@ class DGitProvider extends Plugin { const permission = await this.askUserPermission('clone', 'Import multiple files into your workspaces.') if (!permission) return false if (parseFloat(this.calculateLocalStorage()) > 10000) throw new Error('The local storage of the browser is full.') - if (!workspaceExists) await this.call('filePanel', 'createWorkspace', workspaceName || `workspace_${Date.now()}`, true) + if (!input.workspaceExists) await this.call('filePanel', 'createWorkspace', input.workspaceName || `workspace_${Date.now()}`, true) const cmd = { url: input.url, singleBranch: input.singleBranch, ref: input.branch, depth: input.depth || 10, - ...await this.parseInput(input), - ...await this.getGitConfig() + ...await this.addIsomorphicGitConfig(input), + ...await this.addIsomorphicGitConfigFS() } this.call('terminal', 'logHtml', `Cloning ${input.url}...`) const result = await git.clone(cmd) - if (!workspaceExists) { + if (!input.workspaceExists) { setTimeout(async () => { await this.call('fileManager', 'refresh') }, 1000) @@ -457,12 +604,12 @@ class DGitProvider extends Plugin { } } - async parseGitmodules (dir = '') { + async parseGitmodules(dir = '') { try { const gitmodules = await this.call('fileManager', 'readFile', path.join(dir, '.gitmodules')) if (gitmodules) { const lines = gitmodules.split('\n') - let currentModule:any = {} + let currentModule: any = {} const modules = [] for (let line of lines) { line = line.trim() @@ -497,7 +644,7 @@ class DGitProvider extends Plugin { if (gitmodules) { for (const module of gitmodules) { const dir = path.join(currentDir, module.path) - const targetPath = (await this.getGitConfig(dir)).dir + const targetPath = (await this.addIsomorphicGitConfigFS(dir)).dir if (await window.remixFileSystem.exists(targetPath)) { const stat = await window.remixFileSystem.stat(targetPath) try { @@ -520,20 +667,20 @@ class DGitProvider extends Plugin { url: module.url, singleBranch: true, depth: 1, - ...await this.parseInput(input), - ...await this.getGitConfig(dir) + ...await this.addIsomorphicGitConfig(input), + ...await this.addIsomorphicGitConfigFS(dir) } this.call('terminal', 'logHtml', `Cloning submodule ${dir}...`) await git.clone(cmd) this.call('terminal', 'logHtml', `Cloned successfully submodule ${dir}...`) const commitHash = await git.resolveRef({ - ...await this.getGitConfig(currentDir), + ...await this.addIsomorphicGitConfigFS(currentDir), ref: 'HEAD' }) const result = await git.walk({ - ...await this.getGitConfig(currentDir), + ...await this.addIsomorphicGitConfigFS(currentDir), trees: [git.TREE({ ref: commitHash })], map: async function (filepath, [A]) { if (filepath === module.path) { @@ -544,19 +691,19 @@ class DGitProvider extends Plugin { if (result && result.length) { this.call('terminal', 'logHtml', `Checking out submodule ${dir} to ${result[0]} in directory ${dir}`) await git.fetch({ - ...await this.parseInput(input), - ...await this.getGitConfig(dir), + ...await this.addIsomorphicGitConfig(input), + ...await this.addIsomorphicGitConfigFS(dir), singleBranch: true, ref: result[0] }) await git.checkout({ - ...await this.getGitConfig(dir), + ...await this.addIsomorphicGitConfigFS(dir), ref: result[0] }) const log = await git.log({ - ...await this.getGitConfig(dir), + ...await this.addIsomorphicGitConfigFS(dir), }) if (log[0].oid !== result[0]) { @@ -588,16 +735,14 @@ class DGitProvider extends Plugin { } } - async push(input) { + async push(input: pushInputType) { + console.log('push input', input) const cmd = { force: input.force, - ref: input.ref, - remoteRef: input.remoteRef, - remote: input.remote, - author: { - name: input.name, - email: input.email - }, + ref: input.ref.name, + remoteRef: input.remoteRef.name, + remote: input.remote.name, + author: await this.getCommandUser(input), input, } if ((Registry.getInstance().get('platform').api.isDesktop())) { @@ -606,25 +751,25 @@ class DGitProvider extends Plugin { const cmd2 = { ...cmd, - ...await this.parseInput(input), + ...await this.addIsomorphicGitConfig(input), } - return await git.push({ - ...await this.getGitConfig(), + console.log('push cmd', cmd2) + const result = await git.push({ + ...await this.addIsomorphicGitConfigFS(), ...cmd2 }) + console.log('push result', cmd2, result) + return result } } - async pull(input) { + async pull(input: pullInputType) { const cmd = { - ref: input.ref, - remoteRef: input.remoteRef, - author: { - name: input.name, - email: input.email - }, - remote: input.remote, + ref: input.ref.name, + remoteRef: input.remoteRef.name, + author: await this.getCommandUser(input), + remote: input.remote.name, input, } let result @@ -634,43 +779,47 @@ class DGitProvider extends Plugin { else { const cmd2 = { ...cmd, - ...await this.parseInput(input), + ...await this.addIsomorphicGitConfig(input), } result = await git.pull({ - ...await this.getGitConfig(), + ...await this.addIsomorphicGitConfigFS(), ...cmd2 }) } + console.log('pull result', result) setTimeout(async () => { await this.call('fileManager', 'refresh') }, 1000) return result } - async fetch(input) { + async fetch(input: fetchInputType) { const cmd = { - ref: input.ref, - remoteRef: input.remoteRef, - author: { - name: input.name, - email: input.email - }, - remote: input.remote, + ref: input.ref && input.ref.name, + remoteRef: input.remoteRef && input.remoteRef.name, + author: await this.getCommandUser(input), + remote: input.remote && input.remote.name, + depth: input.depth || 5, + singleBranch: input.singleBranch, + relative: input.relative, input } + console.log('fetch input', cmd) let result if ((Registry.getInstance().get('platform').api.isDesktop())) { result = await this.call('isogit', 'fetch', cmd) } else { const cmd2 = { ...cmd, - ...await this.parseInput(input), + ...await this.addIsomorphicGitConfig(input), } result = await git.fetch({ - ...await this.getGitConfig(), + ...await this.addIsomorphicGitConfigFS(), ...cmd2 }) + console.log('fetch result', cmd2, result) } + setTimeout(async () => { await this.call('fileManager', 'refresh') }, 1000) @@ -683,7 +832,7 @@ class DGitProvider extends Plugin { const files = await this.getDirectory('/') this.filesToSend = [] for (const file of files) { - const c = await window.remixFileSystem.readFile(`${workspace.absolutePath}/${file}`) + const c = await window.remixFileSystem.readFile(`${workspace.absolutePath}/${file}`, null) const ob = { path: file, content: c @@ -697,108 +846,6 @@ class DGitProvider extends Plugin { return r.cid.string } - async pin(pinataApiKey, pinataSecretApiKey) { - const workspace = await this.call('filePanel', 'getCurrentWorkspace') - const files = await this.getDirectory('/') - this.filesToSend = [] - - const data = new FormData() - for (const file of files) { - const c = await window.remixFileSystem.readFile(`${workspace.absolutePath}/${file}`) - data.append('file', new Blob([c]), `base/${file}`) - } - // get last commit data - let ob - try { - const commits = await this.log({ ref: 'HEAD' }) - ob = { - ref: commits[0].oid, - message: commits[0].commit.message, - commits: JSON.stringify(commits.map((commit) => { - return { - oid: commit.oid, - commit: { - parent: commit.commit?.parent, - tree: commit.commit?.tree, - message: commit.commit?.message, - committer: { - timestamp: commit.commit?.committer?.timestamp - } - } - } - })) - } - } catch (e) { - ob = { - ref: 'no commits', - message: 'no commits' - } - } - const today = new Date() - const metadata = JSON.stringify({ - name: `remix - ${workspace.name} - ${today.toLocaleString()}`, - keyvalues: ob - }) - const pinataOptions = JSON.stringify({ - wrapWithDirectory: false - }) - data.append('pinataOptions', pinataOptions) - data.append('pinataMetadata', metadata) - const url = 'https://api.pinata.cloud/pinning/pinFileToIPFS' - try { - const result = await axios - .post(url, data, { - maxBodyLength: 'Infinity', - headers: { - 'Content-Type': `multipart/form-data; boundary=${(data as any)._boundary}`, - pinata_api_key: pinataApiKey, - pinata_secret_api_key: pinataSecretApiKey - } - } as any).catch((e) => { - console.log(e) - }) - // also commit to remix IPFS for availability after pinning to Pinata - return await this.export(this.remixIPFS) || (result as any).data.IpfsHash - } catch (error) { - throw new Error(error) - } - } - - async pinList(pinataApiKey, pinataSecretApiKey) { - const url = 'https://api.pinata.cloud/data/pinList?status=pinned' - try { - const result = await axios - .get(url, { - maxBodyLength: 'Infinity', - headers: { - pinata_api_key: pinataApiKey, - pinata_secret_api_key: pinataSecretApiKey - } - } as any).catch((e) => { - console.log('Pinata unreachable') - }) - return (result as any).data - } catch (error) { - throw new Error(error) - } - } - - async unPin(pinataApiKey, pinataSecretApiKey, hashToUnpin) { - const url = `https://api.pinata.cloud/pinning/unpin/${hashToUnpin}` - try { - await axios - .delete(url, { - headers: { - pinata_api_key: pinataApiKey, - pinata_secret_api_key: pinataSecretApiKey - } - }) - return true - } catch (error) { - throw new Error(error) - } - } - async importIPFSFiles(config, cid, workspace) { const ipfs = IpfsHttpClient(config) let result = false @@ -819,7 +866,7 @@ class DGitProvider extends Plugin { await this.createDirectories(`${workspace.absolutePath}/${dir}`) } catch (e) { throw new Error(e) } try { - await window.remixFileSystem.writeFile(`${workspace.absolutePath}/${file.path}`, Buffer.concat(content) || new Uint8Array()) + await window.remixFileSystem.writeFile(`${workspace.absolutePath}/${file.path}`, Buffer.concat(content) || new Uint8Array(), null) } catch (e) { throw new Error(e) } } } catch (e) { @@ -885,7 +932,7 @@ class DGitProvider extends Plugin { const files = await this.getDirectory('/') this.filesToSend = [] for (const file of files) { - const c = await window.remixFileSystem.readFile(`${workspace.absolutePath}/${file}`) + const c = await window.remixFileSystem.readFile(`${workspace.absolutePath}/${file}`, null) zip.file(file, c) } await zip.generateAsync({ @@ -935,6 +982,149 @@ class DGitProvider extends Plugin { } return result } + + // OCTOKIT FEATURES + + async remotebranches(input: { owner: string, repo: string, token: string, page: number, per_page: number }) { + console.log(input) + + const octokit = new Octokit({ + auth: input.token + }) + + const data = await octokit.request('GET /repos/{owner}/{repo}/branches{?protected,per_page,page}', { + owner: input.owner, + repo: input.repo, + per_page: input.per_page || 100, + page: input.page || 1 + }) + + return data.data + } + + async getGitHubUser(input: { token: string }): Promise<{ + user: GitHubUser, + ratelimit: RateLimit, + emails: userEmails, + scopes: string[] + }> { + const octokit = new Octokit({ + auth: input.token + }) + + const ratelimit = await octokit.request('GET /rate_limit', { + headers: { + 'X-GitHub-Api-Version': '2022-11-28' + } + }) + // epoch timestamp to local date time + const localResetTime = ratelimit.data.rate.reset * 1000 + const localResetTimeString = new Date(localResetTime).toLocaleString() + + console.log('rate limit', localResetTimeString) + + const user = await octokit.request('GET /user') + const emails = await octokit.request('GET /user/emails') + + const scopes = user.headers['x-oauth-scopes']; + + console.log('scopes', scopes) + + return { + user: user.data, + emails: emails.data, + ratelimit: ratelimit.data, + scopes: scopes.split(',') + } + } + + async remotecommits(input: remoteCommitsInputType): Promise { + const octokit = new Octokit({ + auth: input.token + }) + input.length = input.length || 5 + input.page = input.page || 1 + const response = await octokit.request('GET /repos/{owner}/{repo}/commits', { + owner: input.owner, + repo: input.repo, + sha: input.branch, + per_page: input.length, + page: input.page + }) + const pages: pagedCommits[] = [] + const readCommitResults: ReadCommitResult[] = [] + for (const githubApiCommit of response.data) { + const readCommitResult = { + oid: githubApiCommit.sha, + commit: { + author: { + name: githubApiCommit.commit.author.name, + email: githubApiCommit.commit.author.email, + timestamp: new Date(githubApiCommit.commit.author.date).getTime() / 1000, + timezoneOffset: new Date(githubApiCommit.commit.author.date).getTimezoneOffset() + }, + committer: { + name: githubApiCommit.commit.committer.name, + email: githubApiCommit.commit.committer.email, + timestamp: new Date(githubApiCommit.commit.committer.date).getTime() / 1000, + timezoneOffset: new Date(githubApiCommit.commit.committer.date).getTimezoneOffset() + }, + message: githubApiCommit.commit.message, + tree: githubApiCommit.commit.tree.sha, + parent: githubApiCommit.parents.map(parent => parent.sha) + }, + payload: '' // You may need to reconstruct the commit object in Git's format if necessary + } + readCommitResults.push(readCommitResult) + } + + console.log(readCommitResults) + + // Check for the Link header to determine pagination + const linkHeader = response.headers.link; + + let hasNextPage = false; + if (linkHeader) { + // A simple check for the presence of a 'next' relation in the Link header + hasNextPage = linkHeader.includes('rel="next"'); + } + + console.log("Has next page:", hasNextPage); + pages.push({ + page: input.page, + perPage: input.length, + total: response.data.length, + hasNextPage: hasNextPage, + commits: readCommitResults + }) + return pages + } + + async repositories(input: repositoriesInput) { + + const accessToken = input.token; + + const page = input.page || 1 + const perPage = input.per_page || 10 + + const baseURL = 'https://api.github.com/user/repos' + const repositories = [] + const sort = 'updated' + const direction = 'desc' + + const headers = { + 'Authorization': `Bearer ${accessToken}`, // Include your GitHub access token + 'Accept': 'application/vnd.github.v3+json', // GitHub API v3 media type + }; + + const url = `${baseURL}?visibility=private,public&page=${page}&per_page=${perPage}&sort=${sort}&direction=${direction}`; + const response = await axios.get(url, { headers }); + + repositories.push(...response.data); + + return repositories + } + } const addSlash = (file) => { diff --git a/apps/remix-ide/src/app/files/fileManager.ts b/apps/remix-ide/src/app/files/fileManager.ts index b2d0117246..c9f1c1d93d 100644 --- a/apps/remix-ide/src/app/files/fileManager.ts +++ b/apps/remix-ide/src/app/files/fileManager.ts @@ -8,6 +8,7 @@ import { Registry } from '@remix-project/remix-lib' import { fileChangedToastMsg, recursivePasteToastMsg, storageFullMessage } from '@remix-ui/helper' import helper from '../../lib/helper.js' import { RemixAppManager } from '../../remixAppManager' +import { commitChange } from '@remix-ui/git' /* attach to files event (removed renamed) @@ -24,7 +25,7 @@ const profile = { methods: ['closeAllFiles', 'closeFile', 'file', 'exists', 'open', 'writeFile', 'writeMultipleFiles', 'writeFileNoRewrite', 'readFile', 'copyFile', 'copyDir', 'rename', 'mkdir', 'readdir', 'dirList', 'fileList', 'remove', 'getCurrentFile', 'getFile', 'getFolder', 'setFile', 'switchFile', 'refresh', 'getProviderOf', 'getProviderByName', 'getPathFromUrl', 'getUrlFromPath', - 'saveCurrentFile', 'setBatchFiles', 'isGitRepo', 'isFile', 'isDirectory', 'hasGitSubmodule', 'copyFolderToJson' + 'saveCurrentFile', 'setBatchFiles', 'isGitRepo', 'isFile', 'isDirectory', 'hasGitSubmodule', 'copyFolderToJson', 'diff' ], kind: 'file-system' } @@ -702,6 +703,37 @@ class FileManager extends Plugin { this.emit('noFileSelected') } + async diff(change: commitChange) { + await this.saveCurrentFile() + this._deps.config.set('currentFile', '') + // TODO: Only keep `this.emit` (issue#2210) + this.emit('noFileSelected') + + if (!change.readonly){ + let file = this.normalize(change.path) + const resolved = this.getPathFromUrl(file) + file = resolved.file + this._deps.config.set('currentFile', file) + this.openedFiles[file] = file + } + + await this.editor.openDiff(change) + this.emit('openDiff', change) + } + + async closeDiff(change: commitChange) { + if (!change.readonly){ + const file = this.normalize(change.path) + delete this.openedFiles[file] + if (!Object.keys(this.openedFiles).length) { + this._deps.config.set('currentFile', '') + // TODO: Only keep `this.emit` (issue#2210) + this.emit('noFileSelected') + } + } + this.emit('closeDiff', change) + } + async openFile(file?: string) { if (!file) { this.emit('noFileSelected') @@ -710,16 +742,17 @@ class FileManager extends Plugin { const resolved = this.getPathFromUrl(file) file = resolved.file await this.saveCurrentFile() - if (this.currentFile() === file) return + // we always open the file in the editor, even if it's the same as the current one if the editor is in diff mode + if (this.currentFile() === file && !this.editor.isDiff) return const provider = resolved.provider this._deps.config.set('currentFile', file) + this.openedFiles[file] = file let content = '' try { content = await provider.get(file) - } catch (error) { console.log(error) throw error @@ -736,6 +769,7 @@ class FileManager extends Plugin { } else { await this.editor.open(file, content) } + // TODO: Only keep `this.emit` (issue#2210) this.emit('currentFileChanged', file) return true } diff --git a/apps/remix-ide/src/app/panels/layout.ts b/apps/remix-ide/src/app/panels/layout.ts index fa564370f4..90896c2041 100644 --- a/apps/remix-ide/src/app/panels/layout.ts +++ b/apps/remix-ide/src/app/panels/layout.ts @@ -43,6 +43,11 @@ export class Layout extends Plugin { this.panels.main.active = false this.event.emit('change', null) }) + this.on('fileManager', 'openDiff', () => { + this.panels.editor.active = true + this.panels.main.active = false + this.event.emit('change', null) + }) this.on('tabs', 'openFile', () => { this.panels.editor.active = true this.panels.main.active = false @@ -59,6 +64,12 @@ export class Layout extends Plugin { this.panels.main.active = false this.event.emit('change', null) }) + this.on('tabs', 'openDiff', () => { + console.log('openDiff') + this.panels.editor.active = true + this.panels.main.active = false + this.event.emit('change', null) + }) this.on('manager', 'activate', (profile: Profile) => { switch (profile.name) { case 'filePanel': diff --git a/apps/remix-ide/src/app/panels/tab-proxy.js b/apps/remix-ide/src/app/panels/tab-proxy.js index fa6521023a..8eda6d6202 100644 --- a/apps/remix-ide/src/app/panels/tab-proxy.js +++ b/apps/remix-ide/src/app/panels/tab-proxy.js @@ -146,6 +146,23 @@ export class TabProxy extends Plugin { } }) + this.on('fileManager', 'openDiff', (commit) => { + const hash = commit.hashModified? commit.hashModified.substring(0,6): 'Working Tree' + const name = `${commit.path} (${hash})` + this.addTab(name, name, async () => { + await this.fileManager.diff(commit) + this.event.emit('openDiff', commit) + this.emit('openDiff', commit) + }, + async () => { + this.removeTab(name) + await this.fileManager.closeDiff(commit) + this.event.emit('closeDiff', commit) + this.emit('closeDiff', commit) + }) + this.tabsApi.activateTab(name) + }) + this.on('manager', 'pluginActivated', ({ name, location, displayName, icon, description }) => { if (location === 'mainPanel') { this.addTab( diff --git a/apps/remix-ide/src/app/plugins/git.tsx b/apps/remix-ide/src/app/plugins/git.tsx new file mode 100644 index 0000000000..586f3e1300 --- /dev/null +++ b/apps/remix-ide/src/app/plugins/git.tsx @@ -0,0 +1,36 @@ +'use strict' +import { ViewPlugin } from '@remixproject/engine-web'; +import React from 'react' // eslint-disable-line +import { gitState, GitUI } from '@remix-ui/git'; +import * as packageJson from '../../../../../package.json' + +const profile = { + name: 'dgit', + desciption: 'Git plugin for Remix', + methods: ['pull', 'track', 'diff', 'clone', 'open'], + events: [''], + version: packageJson.version, + maintainedBy: 'Remix', + permission: true, + description: 'Use this plugin to interact with your git repositories', + location: 'sidePanel', + icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTIxLjAwNyA4LjIyMTY4QzIxLjAxMDUgNy41Mjc5MiAyMC44MjA3IDYuODQ2ODkgMjAuNDU5MSA2LjI1NDg1QzIwLjA5NzQgNS42NjI4MSAxOS41NzggNS4xODMxNSAxOC45NTkyIDQuODY5NTdDMTguMzQwMyA0LjU1NiAxNy42NDYzIDQuNDIwOTEgMTYuOTU1MSA0LjQ3OTQxQzE2LjI2MzcgNC41Mzc5MyAxNS42MDI1IDQuNzg3NzMgMTUuMDQ1IDUuMjAwODVDMTQuNDg3NyA1LjYxMzk3IDE0LjA1NjMgNi4xNzQwOSAxMy43OTkzIDYuODE4NUMxMy41NDI0IDcuNDYyOSAxMy40Njk3IDguMTY2MTMgMTMuNTg5OCA4Ljg0OTQ0QzEzLjcwOTkgOS41MzI3NCAxNC4wMTc3IDEwLjE2OTIgMTQuNDc4OSAxMC42ODc0QzE0Ljk0MDIgMTEuMjA1NiAxNS41MzY3IDExLjU4NTIgMTYuMjAxNSAxMS43ODM2QzE1Ljk1NiAxMi4yODI0IDE1LjU3NjMgMTIuNzAzIDE1LjEwNDkgMTIuOTk3OUMxNC42MzM2IDEzLjI5MjkgMTQuMDg5NCAxMy40NTA1IDEzLjUzMzQgMTMuNDUzMkgxMC41NDRDOS40MzcyNiAxMy40NTcxIDguMzcxNjMgMTMuODcyNyA3LjU1NDUxIDE0LjYxOTFWNy4zOTgwOUM4LjQ2MTg0IDcuMjEyODggOS4yNjgwOCA2LjY5NzM3IDkuODE2OTIgNS45NTE1MUMxMC4zNjU4IDUuMjA1NjUgMTAuNjE4MSA0LjI4MjU2IDEwLjUyNSAzLjM2MTIxQzEwLjQzMTkgMi40Mzk4NyAxMC4wMDAxIDEuNTg1OSA5LjMxMzE2IDAuOTY0ODczQzguNjI2MjQgMC4zNDM4NDUgNy43MzMxOSAwIDYuODA3MTYgMEM1Ljg4MTEyIDAgNC45ODgwNyAwLjM0Mzg0NSA0LjMwMTE0IDAuOTY0ODczQzMuNjE0MjIgMS41ODU5IDMuMTgyMzYgMi40Mzk4NyAzLjA4OTI4IDMuMzYxMjFDMi45OTYyIDQuMjgyNTYgMy4yNDg1NSA1LjIwNTY1IDMuNzk3MzkgNS45NTE1MUM0LjM0NjIzIDYuNjk3MzcgNS4xNTI0NyA3LjIxMjg4IDYuMDU5OCA3LjM5ODA5VjE2LjUxNTlDNS4xNTQxOCAxNi42ODkxIDQuMzQzMjMgMTcuMTg3NyAzLjc3OTkzIDE3LjkxNzZDMy4yMTY2MyAxOC42NDc2IDIuOTM5OTIgMTkuNTU4NSAzLjAwMTk3IDIwLjQ3ODVDMy4wNjQwMyAyMS4zOTg0IDMuNDYwNTcgMjIuMjYzOSA0LjExNjggMjIuOTExNUM0Ljc3MzAzIDIzLjU1OTIgNS42NDM2IDIzLjk0NDQgNi41NjQyNyAyMy45OTQ0QzcuNDg0OTYgMjQuMDQ0NSA4LjM5MjExIDIzLjc1NTggOS4xMTQ2NCAyMy4xODNDOS44MzcxOCAyMi42MTAyIDEwLjMyNTEgMjEuNzkyOCAxMC40ODY1IDIwLjg4NUMxMC42NDc4IDE5Ljk3NzEgMTAuNDcxNCAxOS4wNDE3IDkuOTkwNDggMTguMjU1QzkuNTA5NTcgMTcuNDY4MyA4Ljc1NzQxIDE2Ljg4NDggNy44NzU4OCAxNi42MTQ1QzguMTIxNzYgMTYuMTE2MiA4LjUwMTY3IDE1LjY5NjMgOC45NzI5NiAxNS40MDE5QzkuNDQ0MjYgMTUuMTA3NCA5Ljk4ODI3IDE0Ljk1MDMgMTAuNTQ0IDE0Ljk0NzlIMTMuNTMzNEMxNC40NjYxIDE0Ljk0MzYgMTUuMzc0MiAxNC42NDg2IDE2LjEzMTMgMTQuMTAzOUMxNi44ODg0IDEzLjU1OTIgMTcuNDU2OCAxMi43OTIgMTcuNzU3NSAxMS45MDkxQzE4LjY1MzQgMTEuNzkxNCAxOS40NzYzIDExLjM1MjggMjAuMDczOCAxMC42NzQ4QzIwLjY3MTMgOS45OTY4IDIxLjAwMjggOS4xMjUzMyAyMS4wMDcgOC4yMjE2OFpNNC41NjUwOCAzLjczNzUyQzQuNTY1MDggMy4yOTQwOCA0LjY5NjU3IDIuODYwNiA0Ljk0MjkzIDIuNDkxOUM1LjE4OTMgMi4xMjMxOSA1LjUzOTQ3IDEuODM1ODEgNS45NDkxNSAxLjY2NjExQzYuMzU4ODQgMS40OTY0MiA2LjgwOTY1IDEuNDUyMDIgNy4yNDQ1NiAxLjUzODU0QzcuNjc5NDggMS42MjUwNCA4LjA3ODk4IDEuODM4NTcgOC4zOTI1NCAyLjE1MjE0QzguNzA2MTEgMi40NjU3IDguOTE5NjQgMi44NjUyIDkuMDA2MTUgMy4zMDAxMkM5LjA5MjY2IDMuNzM1MDQgOS4wNDgyNyA0LjE4NTg1IDguODc4NTcgNC41OTU1M0M4LjcwODg3IDUuMDA1MjEgOC40MjE0OSA1LjM1NTM5IDguMDUyNzggNS42MDE3NUM3LjY4NDA4IDUuODQ4MTEgNy4yNTA2IDUuOTc5NiA2LjgwNzE2IDUuOTc5NkM2LjIxMjUyIDUuOTc5NiA1LjY0MjI0IDUuNzQzMzkgNS4yMjE3NyA1LjMyMjkxQzQuODAxMjkgNC45MDI0NSA0LjU2NTA4IDQuMzMyMTYgNC41NjUwOCAzLjczNzUyWk05LjA0OTIzIDIwLjE3OTRDOS4wNDkyMyAyMC42MjI5IDguOTE3NzQgMjEuMDU2MyA4LjY3MTM4IDIxLjQyNUM4LjQyNTAxIDIxLjc5MzcgOC4wNzQ4NSAyMi4wODExIDcuNjY1MTYgMjIuMjUwOEM3LjI1NTQ3IDIyLjQyMDUgNi44MDQ2NiAyMi40NjQ5IDYuMzY5NzUgMjIuMzc4NEM1LjkzNDgzIDIyLjI5MiA1LjUzNTMzIDIyLjA3ODQgNS4yMjE3NyAyMS43NjQ4QzQuOTA4MjEgMjEuNDUxMiA0LjY5NDY3IDIxLjA1MTcgNC42MDgxNiAyMC42MTY5QzQuNTIxNjUgMjAuMTgxOSA0LjU2NjA1IDE5LjczMTEgNC43MzU3NSAxOS4zMjE0QzQuOTA1NDUgMTguOTExNyA1LjE5MjgyIDE4LjU2MTUgNS41NjE1MyAxOC4zMTUyQzUuOTMwMjMgMTguMDY4OSA2LjM2MzcxIDE3LjkzNzMgNi44MDcxNiAxNy45MzczQzcuNDAxNzkgMTcuOTM3MyA3Ljk3MjA3IDE4LjE3MzYgOC4zOTI1NCAxOC41OTRDOC44MTMwMiAxOS4wMTQ1IDkuMDQ5MjMgMTkuNTg0OCA5LjA0OTIzIDIwLjE3OTRaTTE3LjI3MDIgMTAuNDYzOEMxNi44MjY3IDEwLjQ2MzggMTYuMzkzMyAxMC4zMzIyIDE2LjAyNDYgMTAuMDg1OUMxNS42NTU5IDkuODM5NTQgMTUuMzY4NSA5LjQ4OTM3IDE1LjE5ODggOS4wNzk2OUMxNS4wMjkxIDguNjcgMTQuOTg0NyA4LjIxOTIgMTUuMDcxMiA3Ljc4NDI3QzE1LjE1NzYgNy4zNDkzNSAxNS4zNzEyIDYuOTQ5ODUgMTUuNjg0OCA2LjYzNjI5QzE1Ljk5ODQgNi4zMjI3MyAxNi4zOTc5IDYuMTA5MTkgMTYuODMyNyA2LjAyMjY4QzE3LjI2NzcgNS45MzYxNyAxNy43MTg1IDUuOTgwNTggMTguMTI4MSA2LjE1MDI3QzE4LjUzNzkgNi4zMTk5NyAxOC44ODgxIDYuNjA3MzQgMTkuMTM0NCA2Ljk3NjA1QzE5LjM4MDcgNy4zNDQ3NiAxOS41MTIzIDcuNzc4MjMgMTkuNTEyMyA4LjIyMTY4QzE5LjUxMjMgOC44MTYzMiAxOS4yNzYgOS4zODY2IDE4Ljg1NTYgOS44MDcwNkMxOC40MzUxIDEwLjIyNzUgMTcuODY0OCAxMC40NjM4IDE3LjI3MDIgMTAuNDYzOFoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==" +} + +export class GitPlugin extends ViewPlugin { + + constructor() { + + super(profile) + } + + onDeactivation(): void { + this.call('fileDecorator', 'clearFileDecorators') + this.call('manager', 'activatePlugin', 'dgitApi') + } + + render() { + return
+ } + +} diff --git a/apps/remix-ide/src/app/tabs/locales/en/filePanel.json b/apps/remix-ide/src/app/tabs/locales/en/filePanel.json index 5f033c3aad..9c189262e8 100644 --- a/apps/remix-ide/src/app/tabs/locales/en/filePanel.json +++ b/apps/remix-ide/src/app/tabs/locales/en/filePanel.json @@ -78,7 +78,7 @@ "filePanel.checkoutGitBranch": "Checkout Git Branch", "filePanel.findOrCreateABranch": "Find or create a branch.", "filePanel.initGitRepositoryLabel": "Initialize workspace as a new git repository", - "filePanel.initGitRepositoryWarning": "To use Git features, add username and email to the Github section of the Settings panel.", + "filePanel.initGitRepositoryWarning": "To use Git features, add username and email to the Github section of the Git plugin.", "filePanel.workspaceName": "Workspace name", "filePanel.customizeTemplate": "Customize template", "filePanel.features": "Features", diff --git a/apps/remix-ide/src/app/tabs/locales/en/git.json b/apps/remix-ide/src/app/tabs/locales/en/git.json new file mode 100644 index 0000000000..c5f4fa6a09 --- /dev/null +++ b/apps/remix-ide/src/app/tabs/locales/en/git.json @@ -0,0 +1,20 @@ +{ + "git.push": "push", + "git.pull": "pull", + "git.commit": "commit", + "git.sync": "sync", + "git.syncchanges": "sync changes", + "git.publish": "publish", + "git.ignore": "ignore", + "git.createBranch": "create branch", + "git.deleteBranch": "delete branch", + "git.mergeBranch": "merge branch", + "git.rebaseBranch": "rebase branch", + "git.checkout": "checkout", + "git.fetch": "fetch", + "git.refresh": "refresh", + "git.unstageall": "unstage all", + "git.stageall": "stage all", + "git.noremote": "this repo has no remotes", + "git.init": "Initialize repository" +} \ No newline at end of file diff --git a/apps/remix-ide/src/remixAppManager.js b/apps/remix-ide/src/remixAppManager.js index df13ce19c0..ef765acdbf 100644 --- a/apps/remix-ide/src/remixAppManager.js +++ b/apps/remix-ide/src/remixAppManager.js @@ -35,7 +35,7 @@ let requiredModules = [ // services + layout views + system views 'pluginManager', 'tabs', 'udapp', - 'dGitProvider', + 'dgitApi', 'solidity', 'solidity-logic', 'gistHandler', @@ -78,6 +78,7 @@ let requiredModules = [ // services + layout views + system views 'doc-gen', 'remix-templates', 'solhint', + 'dgit', 'pinnedPanel', 'pluginStateLogger' ] @@ -248,6 +249,7 @@ export class RemixAppManager extends PluginManager { const res = await fetch(this.pluginsDirectory) plugins = await res.json() plugins = plugins.filter((plugin) => { + if (plugin.name === 'dgit') return false if (plugin.targets && Array.isArray(plugin.targets) && plugin.targets.length > 0) { return plugin.targets.includes('remix') } diff --git a/apps/remix-ide/src/remixEngine.js b/apps/remix-ide/src/remixEngine.js index 948eca47bc..d45e58317a 100644 --- a/apps/remix-ide/src/remixEngine.js +++ b/apps/remix-ide/src/remixEngine.js @@ -10,7 +10,7 @@ export class RemixEngine extends Engine { setPluginOption ({ name, kind }) { if (kind === 'provider') return { queueTimeout: 60000 * 2 } if (name === 'LearnEth') return { queueTimeout: 60000 } - if (name === 'dGitProvider') return { queueTimeout: 60000 * 4 } + if (name === 'dgitApi') return { queueTimeout: 60000 * 4 } if (name === 'slither') return { queueTimeout: 60000 * 4 } // Requires when a solc version is installed if (name === 'hardhat') return { queueTimeout: 60000 * 4 } if (name === 'truffle') return { queueTimeout: 60000 * 4 } diff --git a/apps/remixdesktop/src/plugins/isoGitPlugin.ts b/apps/remixdesktop/src/plugins/isoGitPlugin.ts index 62a3451a63..fad68d02da 100644 --- a/apps/remixdesktop/src/plugins/isoGitPlugin.ts +++ b/apps/remixdesktop/src/plugins/isoGitPlugin.ts @@ -6,6 +6,7 @@ import git from 'isomorphic-git' import { dialog } from "electron"; import http from 'isomorphic-git/http/web' import { gitProxy } from "../tools/git"; +import { remote } from "../types"; const profile: Profile = { name: 'isogit', @@ -328,9 +329,9 @@ class IsoGitPluginClient extends ElectronBasePluginClient { async clone(cmd: any) { if (this.gitIsInstalled) { - try{ + try { await gitProxy.clone(cmd.url, cmd.dir) - }catch(e){ + } catch (e) { throw e } } else { @@ -376,8 +377,9 @@ class IsoGitPluginClient extends ElectronBasePluginClient { if (!this.workingDir || this.workingDir === '') { return [] } - let remotes = [] - remotes = await git.listRemotes({ ...await this.getGitConfig() }) + let remotes: remote[] = [] + remotes = (await git.listRemotes({ ...await this.getGitConfig() })).map((remote) => { return { name: remote.remote, url: remote.url } } + ) return remotes } @@ -408,10 +410,10 @@ class IsoGitPluginClient extends ElectronBasePluginClient { for (const remote of remotes) { cmd = { ...cmd, - remote: remote.remote + remote: remote.name } - const remotebranches = (await git.listBranches(cmd)).map((branch) => { return { remote: remote.remote, name: branch } }) + const remotebranches = (await git.listBranches(cmd)).map((branch) => { return { remote: remote.name, name: branch } }) branches = [...branches, ...remotebranches] } diff --git a/apps/remixdesktop/src/types/index.ts b/apps/remixdesktop/src/types/index.ts new file mode 100644 index 0000000000..8c0087b62e --- /dev/null +++ b/apps/remixdesktop/src/types/index.ts @@ -0,0 +1,9 @@ +export type branch = { + name: string + remote: remote +} + +export type remote = { + name: string + url: string +} \ No newline at end of file diff --git a/apps/vyper/src/app/utils/remix-client.tsx b/apps/vyper/src/app/utils/remix-client.tsx index 088aa6c36d..27c234092d 100644 --- a/apps/vyper/src/app/utils/remix-client.tsx +++ b/apps/vyper/src/app/utils/remix-client.tsx @@ -81,14 +81,17 @@ export class RemixClient extends PluginClient { try { // @ts-ignore this.call('notification', 'toast', 'cloning Snekmate Vyper repository...') - await this.call('manager', 'activatePlugin', 'dGitProvider') + + await this.call('manager', 'activatePlugin', 'dgitApi') + /* await this.call( - 'dGitProvider', + 'dgitApi', 'clone', {url: 'https://github.com/pcaversaccio/snekmate', token: null, branch: 'v0.0.5'}, // @ts-ignore 'snekmate' ) + */ this.call( // @ts-ignore 'notification', diff --git a/libs/remix-api/src/index.ts b/libs/remix-api/src/index.ts new file mode 100644 index 0000000000..71e343fc8a --- /dev/null +++ b/libs/remix-api/src/index.ts @@ -0,0 +1 @@ +export * from './lib/remix-api' \ No newline at end of file diff --git a/libs/remix-api/src/lib/plugins/config-api.ts b/libs/remix-api/src/lib/plugins/config-api.ts new file mode 100644 index 0000000000..e5f072712f --- /dev/null +++ b/libs/remix-api/src/lib/plugins/config-api.ts @@ -0,0 +1,11 @@ +import { StatusEvents } from "@remixproject/plugin-utils" + +export interface IConfigApi { + events: { + configChanged: () => void + } & StatusEvents, + methods: { + getAppParameter(key: string): Promise, + setAppParameter(key: string, value: any): Promise + } +} \ No newline at end of file diff --git a/libs/remix-api/src/lib/plugins/fileSystem-api.ts b/libs/remix-api/src/lib/plugins/fileSystem-api.ts new file mode 100644 index 0000000000..04d0a2a0af --- /dev/null +++ b/libs/remix-api/src/lib/plugins/fileSystem-api.ts @@ -0,0 +1,10 @@ +import { commitChange } from "@remix-ui/git"; +import { IFileSystem } from "@remixproject/plugin-api" + +// Extended interface with 'diff' method +export interface IExtendedFileSystem extends IFileSystem { + methods: IFileSystem['methods'] & { + /** Compare the differences between two files */ + diff(change: commitChange): Promise + }; +} \ No newline at end of file diff --git a/libs/remix-api/src/lib/plugins/filedecorator-api.ts b/libs/remix-api/src/lib/plugins/filedecorator-api.ts new file mode 100644 index 0000000000..a787489002 --- /dev/null +++ b/libs/remix-api/src/lib/plugins/filedecorator-api.ts @@ -0,0 +1,11 @@ +import { fileDecoration } from '@remix-ui/file-decorators' +import { StatusEvents } from '@remixproject/plugin-utils' + +export interface IFileDecoratorApi { + events: { + } & StatusEvents + methods: { + clearFileDecorators(path?: string): void + setFileDecorators(decorators: fileDecoration[]): void + } +} diff --git a/libs/remix-api/src/lib/plugins/notification-api.ts b/libs/remix-api/src/lib/plugins/notification-api.ts new file mode 100644 index 0000000000..e46b3d493f --- /dev/null +++ b/libs/remix-api/src/lib/plugins/notification-api.ts @@ -0,0 +1,29 @@ +import { ModalTypes } from "@remix-ui/app" +import { StatusEvents } from "@remixproject/plugin-utils" + +export interface INotificationApi { + events: { + + } & StatusEvents, + methods: { + toast(key: string): Promise, + alert({ + title, + message + }:{ + title: string, + message: string, + }): Promise, + modal({ + title, + message, + okLabel, + type + }:{ + title: string, + message: string, + okLabel: string, + type: ModalTypes + }): Promise, + } +} \ No newline at end of file diff --git a/libs/remix-api/src/lib/plugins/settings-api.ts b/libs/remix-api/src/lib/plugins/settings-api.ts new file mode 100644 index 0000000000..dd7323ac73 --- /dev/null +++ b/libs/remix-api/src/lib/plugins/settings-api.ts @@ -0,0 +1,11 @@ +import { StatusEvents } from '@remixproject/plugin-utils' + +export interface ISettings { + events: { + configChanged: () => void, + } & StatusEvents + methods: { + getGithubAccessToken(): string + get(key: string): Promise + } +} diff --git a/libs/remix-api/src/lib/remix-api.ts b/libs/remix-api/src/lib/remix-api.ts new file mode 100644 index 0000000000..8469d9e057 --- /dev/null +++ b/libs/remix-api/src/lib/remix-api.ts @@ -0,0 +1,19 @@ +import { IGitApi } from "@remix-ui/git" +import { IRemixApi } from "@remixproject/plugin-api" +import { StatusEvents } from "@remixproject/plugin-utils" +import { IConfigApi } from "./plugins/config-api" +import { IFileDecoratorApi } from "./plugins/filedecorator-api" +import { IExtendedFileSystem } from "./plugins/fileSystem-api" +import { INotificationApi } from "./plugins/notification-api" +import { ISettings } from "./plugins/settings-api" + +export interface ICustomRemixApi extends IRemixApi { + dgitApi: IGitApi + config: IConfigApi + notification: INotificationApi + settings: ISettings + fileDecorator: IFileDecoratorApi + fileManager: IExtendedFileSystem +} + +export declare type CustomRemixApi = Readonly \ No newline at end of file diff --git a/libs/remix-ui/editor/src/lib/actions/editor.ts b/libs/remix-ui/editor/src/lib/actions/editor.ts index d533823af1..45296b7efd 100644 --- a/libs/remix-ui/editor/src/lib/actions/editor.ts +++ b/libs/remix-ui/editor/src/lib/actions/editor.ts @@ -1,5 +1,6 @@ import { monacoTypes } from '@remix-ui/editor'; +import { commitChange } from '@remix-ui/git'; export interface Action { type: string; payload: Record @@ -38,6 +39,10 @@ export const reducerActions = (models = initialState, action: Action) => { delete models[uri] return models } + case 'ADD_DIFF': { + if (!editor) return models + return models + } case 'SET_VALUE': { if (!editor) return models const uri = action.payload.uri @@ -111,6 +116,15 @@ export const reducerListener = (plugin, dispatch, monaco, editor, events) => { }) }) + plugin.on('editor', 'addDiff', (value: commitChange) => { + dispatch({ + type: 'ADD_DIFF', + payload: { value }, + monaco, + editor + }) + }) + plugin.on('editor', 'disposeModel', (uri) => { dispatch({ type: 'DISPOSE_MODEL', diff --git a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx index a0ed7626aa..def6633d02 100644 --- a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx +++ b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx @@ -1,7 +1,7 @@ import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint-disable-line import { FormattedMessage, useIntl } from 'react-intl' import { isArray } from 'lodash' -import Editor, { loader, Monaco } from '@monaco-editor/react' +import Editor, { DiffEditor, loader, Monaco } from '@monaco-editor/react' import { AlertModal } from '@remix-ui/app' import { ConsoleLogs, QueryParams } from '@remix-project/remix-lib' import { reducerActions, reducerListener, initialState } from './actions/editor' @@ -135,6 +135,8 @@ export interface EditorUIProps { activated: boolean themeType: string currentFile: string + currentDiffFile: string + isDiff: boolean events: { onBreakPointAdded: (file: string, line: number) => void onBreakPointCleared: (file: string, line: number) => void @@ -147,6 +149,8 @@ export interface EditorUIProps { export const EditorUI = (props: EditorUIProps) => { const intl = useIntl() const [, setCurrentBreakpoints] = useState({}) + const [isDiff, setIsDiff] = useState(false) + const [isSplit, setIsSplit] = useState(true) const defaultEditorValue = ` \t\t\t\t\t\t\t ____ _____ __ __ ___ __ __ ___ ____ _____ \t\t\t\t\t\t\t| _ \\ | ____| | \\/ | |_ _| \\ \\/ / |_ _| | _ \\ | ____| @@ -171,6 +175,8 @@ export const EditorUI = (props: EditorUIProps) => { const pasteCodeRef = useRef(false) const editorRef = useRef(null) const monacoRef = useRef(null) + const diffEditorRef = useRef(null) + const currentFunction = useRef('') const currentFileRef = useRef('') const currentUrlRef = useRef('') @@ -326,11 +332,20 @@ export const EditorUI = (props: EditorUIProps) => { }) useEffect(() => { - if (!editorRef.current || !props.currentFile) return + console.log(props.isDiff, props.currentFile) + if (!(editorRef.current || diffEditorRef.current ) || !props.currentFile) return currentFileRef.current = props.currentFile props.plugin.call('fileManager', 'getUrlFromPath', currentFileRef.current).then((url) => (currentUrlRef.current = url.file)) const file = editorModelsState[props.currentFile] + + props.isDiff && diffEditorRef && diffEditorRef.current && diffEditorRef.current.setModel({ + original: editorModelsState[props.currentDiffFile].model, + modified: file.model + }) + + props.isDiff && diffEditorRef.current.getModifiedEditor().updateOptions({ readOnly: editorModelsState[props.currentFile].readOnly }) + editorRef.current.setModel(file.model) editorRef.current.updateOptions({ readOnly: editorModelsState[props.currentFile].readOnly, @@ -348,7 +363,7 @@ export const EditorUI = (props: EditorUIProps) => { } else if (file.language === 'toml') { monacoRef.current.editor.setModelLanguage(file.model, 'remix-toml') } - }, [props.currentFile]) + }, [props.currentFile, props.isDiff]) const convertToMonacoDecoration = (decoration: lineText | sourceAnnotation | sourceMarker, typeOfDecoration: string) => { if (typeOfDecoration === 'sourceAnnotationsPerFile') { @@ -614,6 +629,14 @@ export const EditorUI = (props: EditorUIProps) => { } } + function handleDiffEditorDidMount(editor: any) { + console.log('diff editor mounted') + diffEditorRef.current = editor + defineAndSetTheme(monacoRef.current) + reducerListener(props.plugin, dispatch, monacoRef.current, diffEditorRef.current.getModifiedEditor(), props.events) + props.events.onEditorMounted() + } + function handleEditorDidMount(editor) { editorRef.current = editor defineAndSetTheme(monacoRef.current) @@ -928,8 +951,22 @@ export const EditorUI = (props: EditorUIProps) => { return (
+ + { } }} defaultValue={defaultEditorValue} + className={props.isDiff ? "d-none" : "d-block"} /> {editorModelsState[props.currentFile]?.readOnly && ( diff --git a/libs/remix-ui/git/src/components/branchHeader.tsx b/libs/remix-ui/git/src/components/branchHeader.tsx new file mode 100644 index 0000000000..bfe88fbf3a --- /dev/null +++ b/libs/remix-ui/git/src/components/branchHeader.tsx @@ -0,0 +1,33 @@ +import React, { useEffect, useReducer, useState } from 'react' +import { gitActionsContext } from '../state/context' +import { gitPluginContext } from './gitui' +export const BranchHeader = () => { + + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + const [changed, setChanged] = useState(false) + + useEffect(() => { + if (context.currentBranch) { + console.log('GET BRANCH COMMITS', context.currentBranch) + actions.getBranchDifferences(context.currentBranch, null, context) + } + }, [context.currentBranch, context.commits, context.branches, context.remotes]) + + useEffect(() => { + if (context.fileStatusResult) { + const total = context.allchangesnotstaged.length + const badges = total + context.staged.length + setChanged((context.deleted.length > 0 || context.staged.length > 0 || context.untracked.length > 0 || context.modified.length > 0)) + } + }, [context.fileStatusResult, context.modified, context.allchangesnotstaged, context.untracked, context.deleted]) + + return (<> +
+
+ + {changed?'*':''}{context.currentBranch && context.currentBranch.name}
+
+
+ ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/buttons/commitmessage.tsx b/libs/remix-ui/git/src/components/buttons/commitmessage.tsx new file mode 100644 index 0000000000..0322308a32 --- /dev/null +++ b/libs/remix-ui/git/src/components/buttons/commitmessage.tsx @@ -0,0 +1,139 @@ +import React, { useEffect } from "react" +import { useState } from "react" +import { gitActionsContext } from "../../state/context" +import { gitPluginContext } from "../gitui" +import { faArrowDown, faArrowUp, faCheck, faCloudArrowUp, faSync } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { syncStateContext } from "./sourceControlBase"; + +enum buttonStateValues { + Commit , + Sync = 1, + PublishBranch = 2 +} + +export const CommitMessage = () => { + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + const syncState = React.useContext(syncStateContext) + const [buttonState, setButtonState] = useState(buttonStateValues.Commit) + + const [message, setMessage] = useState({ value: '' }) + + const handleChange = (e: React.ChangeEvent) => { + setMessage({ value: e.currentTarget.value }) + } + + useEffect(() => { + if (context.fileStatusResult) { + console.log(context.staged.length + ' staged') + } + }, [context.fileStatusResult]) + + const commit = async() => { + if (context.staged.length === 0 && context.allchangesnotstaged.length == 0) return + if (context.staged.length === 0) + await actions.addall(context.allchangesnotstaged) + await actions.commit(message.value) + setMessage({ value: '' }) + } + + const getRemote = () => { + return context.upstream ? context.upstream : context.defaultRemote ? context.defaultRemote : null + } + + const sync = async() => { + await actions.pull({ + remote: getRemote(), + ref: context.currentBranch + }) + await actions.push({ + remote: getRemote(), + ref: context.currentBranch + }) + } + + const commitNotAllowed = () => { + return context.canCommit === false || message.value === "" || ( context.staged.length === 0 && context.allchangesnotstaged.length == 0 ) + } + + const commitMessagePlaceholder = () => { + if (context.currentBranch === undefined || context.currentBranch.name === "") + return `message` + return `message ( commit on ${context.currentBranch.name} )` + } + + const syncEnabled = () => { + return syncState.commitsAhead.length > 0 || syncState.commitsBehind.length > 0 + } + + const upDownArrows = () => { + return ( + <> + {syncState.commitsBehind && syncState.commitsBehind.length ? <>{syncState.commitsBehind.length}: null} + {syncState.commitsAhead && syncState.commitsAhead.length ? <>{syncState.commitsAhead.length}: null} + + ) + } + + const publishEnabled = () => { + const remoteEquivalentBranch = context.branches.find((b) => b.name === context.currentBranch.name && b.remote) + return remoteEquivalentBranch === undefined && getRemote()!== null + } + + const publishBranch = async () => { + if (context.currentBranch === undefined || context.currentBranch.name === "") + return + //await actions.push(context.currentBranch.name) + } + + const messageEnabled = () => { + return context.canCommit && (context.allchangesnotstaged.length > 0 || context.staged.length > 0) + } + + const setButtonStateValues = () => { + console.log('setButtonStateValues', context) + if (!commitNotAllowed() || context.allchangesnotstaged.length > 0 || context.staged.length > 0){ + if (context.allchangesnotstaged.length == 0 && context.staged.length == 0 && message.value === "" && publishEnabled()){ + setButtonState(buttonStateValues.PublishBranch) + return + } + setButtonState(buttonStateValues.Commit) + return + } + if (syncEnabled()){ + setButtonState(buttonStateValues.Sync) + return + } + if (publishEnabled()){ + setButtonState(buttonStateValues.PublishBranch) + return + } + setButtonState(buttonStateValues.Commit) + } + + useEffect(() => { + setButtonStateValues() + },[context.canCommit, context.staged, context.allchangesnotstaged, context.currentBranch, syncState.commitsAhead, syncState.commitsBehind, message.value]) + + return ( + <> +
+ +
+ + + +
+ + ); +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/buttons/gituibutton.tsx b/libs/remix-ui/git/src/components/buttons/gituibutton.tsx new file mode 100644 index 0000000000..7556829c13 --- /dev/null +++ b/libs/remix-ui/git/src/components/buttons/gituibutton.tsx @@ -0,0 +1,24 @@ +import React, { useContext } from 'react' +import { gitPluginContext } from '../gitui' + +interface ButtonWithContextProps { + onClick: React.MouseEventHandler; + children: React.ReactNode; + disabledCondition?: boolean; // Optional additional disabling condition + // You can add other props if needed, like 'type', 'className', etc. + [key: string]: any; // Allow additional props to be passed +} + +// This component extends a button, disabling it when loading is true +const GitUIButton = ({ children, disabledCondition = false, ...rest }:ButtonWithContextProps) => { + const { loading } = React.useContext(gitPluginContext) + + const isDisabled = loading || disabledCondition + return ( + + ); +}; + +export default GitUIButton; \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/buttons/sourceControlBase.tsx b/libs/remix-ui/git/src/components/buttons/sourceControlBase.tsx new file mode 100644 index 0000000000..9757e1e0f5 --- /dev/null +++ b/libs/remix-ui/git/src/components/buttons/sourceControlBase.tsx @@ -0,0 +1,90 @@ +import { faArrowDown, faArrowUp, faArrowsUpDown, faArrowRotateRight } from "@fortawesome/free-solid-svg-icons" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" +import { CustomTooltip } from "@remix-ui/helper" +import { ReadCommitResult } from "isomorphic-git" +import React, { createContext, useEffect, useState } from "react" +import { FormattedMessage } from "react-intl" +import { gitActionsContext } from "../../state/context" +import { branch, remote } from "../../types" +import { gitPluginContext } from "../gitui" +import GitUIButton from "./gituibutton" + +interface SourceControlButtonsProps { + remote?: remote, + branch?: branch, + children: React.ReactNode +} + +export const syncStateContext = createContext<{ + commitsAhead: ReadCommitResult[], + commitsBehind: ReadCommitResult[] + branch: branch, + remote: remote +}> +({ commitsAhead: [], commitsBehind: [], branch: undefined, remote: undefined }) + +export const SourceControlBase = (props: SourceControlButtonsProps) => { + const [branch, setBranch] = useState(props.branch) + const [remote, setRemote] = useState(props.remote) + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + const [commitsAhead, setCommitsAhead] = useState([]) + const [commitsBehind, setCommitsBehind] = useState([]) + + useEffect(() => { + //console.log('BRANCH DIFF SourceControlButtons',branch, remote, context.branchDifferences, context.currentBranch) + setDefaultRemote() + if (remote && branch && context.branchDifferences && context.branchDifferences[`${remote.name}/${branch.name}`]) { + setCommitsAhead(context.branchDifferences[`${remote.name}/${branch.name}`]?.uniqueHeadCommits) + setCommitsBehind(context.branchDifferences[`${remote.name}/${branch.name}`]?.uniqueRemoteCommits) + } else { + setCommitsAhead([]) + setCommitsBehind([]) + } + }, [context.branchDifferences, context.currentBranch, branch, remote]) + + const setDefaultRemote = () => { + + if (context.remotes.length > 0) { + // find remote called origin + const origin = context.remotes.find(remote => remote.name === 'origin') + if (origin) { + setRemote(origin) + } else { + setRemote(context.remotes[0]) + } + return origin + } + return null + } + + useEffect(() => { + if (!props.branch) { + setBranch(context.currentBranch) + } + if (!props.remote) { + setRemote(context.defaultRemote) + } else { + setDefaultRemote() + } + }, []) + + useEffect(() => { + console.log('context', context.defaultRemote, context.currentBranch) + if (!props.branch) { + setBranch(context.currentBranch) + } + if (!props.remote) { + setRemote(context.defaultRemote) + } else { + setDefaultRemote() + } + }, [context.defaultRemote, context.currentBranch]) + + return (<> + + {props.children} + + ) + +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/buttons/sourcecontrolbuttons.tsx b/libs/remix-ui/git/src/components/buttons/sourcecontrolbuttons.tsx new file mode 100644 index 0000000000..9685ef0f7e --- /dev/null +++ b/libs/remix-ui/git/src/components/buttons/sourcecontrolbuttons.tsx @@ -0,0 +1,101 @@ +import { faArrowDown, faArrowUp, faArrowsUpDown, faArrowRotateRight } from "@fortawesome/free-solid-svg-icons" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" +import { CustomTooltip } from "@remix-ui/helper" +import React, { useEffect, useState } from "react" +import { FormattedMessage } from "react-intl" +import { gitActionsContext } from "../../state/context" +import { branch, remote } from "../../types" +import { gitPluginContext } from "../gitui" +import GitUIButton from "./gituibutton" +import { syncStateContext } from "./sourceControlBase" + +export const SourceControlButtons = () => { + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + const syncState = React.useContext(syncStateContext) + const [branch, setBranch] = useState(syncState.branch) + const [remote, setRemote] = useState(syncState.remote) + + useEffect(() => { + console.log('SC BUTTONS', branch, remote) + }, []) + + const getRemote = () => { + return remote ? remote : context.upstream ? context.upstream : context.defaultRemote ? context.defaultRemote : null + } + + const getRemoteName = () => { + return getRemote() ? getRemote().name : '' + } + + const pull = async () => { + await actions.pull({ + remote: getRemote(), + ref: branch ? branch : context.currentBranch + }) + } + + const push = async () => { + await actions.push({ + remote: getRemote(), + ref: branch ? branch : context.currentBranch + }) + await actions.fetch({ + remote: getRemote(), + ref: branch ? branch : context.currentBranch, + relative: false, + depth: 1, + singleBranch: true + }) + } + + const sync = async () => { + await pull() + await push() + } + + const refresh = async() => { + actions.getFileStatusMatrix(null) + } + + const buttonsDisabled = () => { + return (!context.upstream) || context.remotes.length === 0 + } + + const getTooltipText = (id: string) => { + if (buttonsDisabled()) return + return <> {getRemoteName()} + } + + return ( + + + +
+ {syncState.commitsBehind.length ?
+ {syncState.commitsBehind.length} +
: null} + +
+
+
+ + +
+ {syncState.commitsAhead.length ?
+ {syncState.commitsAhead.length} +
: null} + +
+
+
+ + + + }> + + +
+ + ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/github/branchselect.tsx b/libs/remix-ui/git/src/components/github/branchselect.tsx new file mode 100644 index 0000000000..c80a8e93ae --- /dev/null +++ b/libs/remix-ui/git/src/components/github/branchselect.tsx @@ -0,0 +1,49 @@ +import React, { useState, useCallback, useEffect } from 'react'; +import Select from 'react-select'; +import { gitActionsContext } from '../../state/context'; +import { selectStyles, selectTheme } from '../../types/styles'; +import { gitPluginContext } from '../gitui'; + +interface BranchySelectProps { + select: (branch:{ name: string }) => void; +} + +export const BranchSelect = (props: BranchySelectProps) => { + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + const [branchOptions, setBranchOptions] = useState([]); + + useEffect(() => { + if (context.remoteBranches && context.remoteBranches.length > 0) { + const options = context.remoteBranches && context.remoteBranches.length > 0 && context.remoteBranches.map(branch => { + return { value: branch.name, label: branch.name } + } + ) + setBranchOptions(options) + } else { + setBranchOptions(null) + } + }, [context.remoteBranches]) + + const selectRemoteBranch = async (e: any) => { + if (!e || !e.value) { + props.select(null) + return + } + const value = e && e.value + props.select({ name: value.toString() }) + } + + return (<>{branchOptions && branchOptions.length ? + +
+ +
+
+

+ Step 2: Authorize the app here +

{gitHubResponse.verification_uri} +


+ Step 3: When you are done, click on the button below: + + + } + { + (context.gitHubUser && context.gitHubUser.login) ? +
+ +
: null + } + { + (context.gitHubUser && context.gitHubUser.login) ? +
+ + + Connected as {context.gitHubUser.login} + + + {context.gitHubUser.html_url} + {context.userEmails && context.userEmails.filter((email: any) => email.primary).map((email: any) => { + return

{email.email}
+ })} +
+
+
+ +
: null + } + + ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/github/repositoryselect.tsx b/libs/remix-ui/git/src/components/github/repositoryselect.tsx new file mode 100644 index 0000000000..dd1264e0a8 --- /dev/null +++ b/libs/remix-ui/git/src/components/github/repositoryselect.tsx @@ -0,0 +1,86 @@ +import React, { useState, useEffect } from 'react'; +import { Button } from 'react-bootstrap'; +import Select from 'react-select'; +import { gitActionsContext } from '../../state/context'; +import { repository } from '../../types'; +import { selectStyles, selectTheme } from '../../types/styles'; +import { gitPluginContext } from '../gitui'; +import { TokenWarning } from '../panels/tokenWarning'; + +interface RepositorySelectProps { + select: (repo: repository) => void; +} + +const RepositorySelect = (props: RepositorySelectProps) => { + const [repoOtions, setRepoOptions] = useState([]); + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + const [loading, setLoading] = useState(false) + const [show, setShow] = useState(false) + + useEffect(() => { + if (context.repositories && context.repositories.length > 0) { + // map context.repositories to options + const options = context.repositories && context.repositories.length > 0 && context.repositories.map(repo => { + return { value: repo.id, label: repo.full_name } + }) + + setRepoOptions(options) + setShow(options.length > 0) + } else { + setRepoOptions(null) + setShow(false) + } + setLoading(false) + + }, [context.repositories]) + + const selectRepo = async (e: any) => { + if (!e || !e.value) { + props.select(null) + return + } + const value = e && e.value + + const repo = context.repositories.find(repo => { + return repo.id.toString() === value.toString() + }) + + if (repo) { + props.select(repo) + await actions.remoteBranches(repo.owner.login, repo.name) + } + } + + const fetchRepositories = async () => { + try { + setShow(true) + setLoading(true) + setRepoOptions([]) + console.log(await actions.repositories()) + } catch (e) { + // do nothing + } + }; + + return ( + <> + { + show ? + + + actions.createBranch(newBranch.value)} + className="btn w-md-25 w-100 btn-primary" + id="createbranch-btn" + > + create new branch + + :
No branches
} + + + ); +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/branches/branchdifferencedetails.tsx b/libs/remix-ui/git/src/components/panels/branches/branchdifferencedetails.tsx new file mode 100644 index 0000000000..b93a3c596e --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/branches/branchdifferencedetails.tsx @@ -0,0 +1,48 @@ +import { ReadCommitResult } from "isomorphic-git"; +import { Accordion } from "react-bootstrap"; +import React, { useEffect, useState } from "react"; +import { CommitDetails } from "../commits/commitdetails"; +import { CommitsNavigation } from "../../navigation/commits"; +import { branch, remote } from "../../../types"; +import { gitActionsContext } from "../../../state/context"; +import { gitPluginContext } from "../../gitui"; + +export interface BrancheDifferenceProps { + commits: ReadCommitResult[]; + title: string, + remote?: remote, + branch?: branch + ahead?: boolean, + behind?: boolean +} + +export const BranchDifferenceDetails = (props: BrancheDifferenceProps) => { + const { commits, title, branch, remote, ahead, behind } = props; + const [activePanel, setActivePanel] = useState(""); + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + + if (commits.length === 0) return null + + const getRemote = () => { + return remote ? remote : context.upstream ? context.upstream : context.defaultRemote ? context.defaultRemote : null + } + + const getCommitChanges = async (commit: ReadCommitResult) => { + await actions.getCommitChanges(commit.oid, commit.commit.parent[0], null, getRemote()) + } + + return ( + + + +
+ {commits && commits.map((commit, index) => { + return ( + {}} commit={commit}> + ); + })} +
+
+
) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/branches/branchdifferences.tsx b/libs/remix-ui/git/src/components/panels/branches/branchdifferences.tsx new file mode 100644 index 0000000000..7cdbc548e1 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/branches/branchdifferences.tsx @@ -0,0 +1,47 @@ +import { branch, remote } from "../../../types"; +import React, { useEffect, useState } from "react"; +import { gitPluginContext } from "../../gitui"; +import { CommitDetails } from "../commits/commitdetails"; +import { BranchDifferenceDetails } from "./branchdifferencedetails"; + +export interface BrancheDetailsProps { + branch: branch; + showSummary?: boolean; +} + +export const BranchDifferences = (props: BrancheDetailsProps) => { + const { branch, showSummary } = props; + const context = React.useContext(gitPluginContext) + + useEffect(() => { + console.log('GET BRANCH DIFF', branch) + }, []) + + const getRemote = (): remote | null => { + return context.upstream ? context.upstream : context.defaultRemote ? context.defaultRemote : null + } + + useEffect(() => { + console.log('BRANCH DIFF', context.branchDifferences) + }, [context.branchDifferences]) + + const commitsAhead = (remote: remote) => { + if (!remote) return []; + return context.branchDifferences[`${remote.name}/${branch.name}`]?.uniqueHeadCommits || []; + } + + const commitsBehind = (remote: remote) => { + if (!remote) return []; + return context.branchDifferences[`${remote.name}/${branch.name}`]?.uniqueRemoteCommits || []; + } + + if (!getRemote()) return null; + + return ( + +
+ + + {commitsAhead(getRemote()).length === 0 && commitsBehind(getRemote()).length === 0 ? null :
} +
) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/branches/localbranchdetails.tsx b/libs/remix-ui/git/src/components/panels/branches/localbranchdetails.tsx new file mode 100644 index 0000000000..ffb80332bb --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/branches/localbranchdetails.tsx @@ -0,0 +1,84 @@ +import { ReadCommitResult } from "isomorphic-git" +import React, { useEffect, useState } from "react"; +import { Accordion } from "react-bootstrap"; +import { CommitDetailsNavigation } from "../../navigation/commitdetails"; +import { gitActionsContext } from "../../../state/context"; +import { gitPluginContext } from "../../gitui"; +import { branch } from "../../../types"; +import { BrancheDetailsNavigation } from "../../navigation/branchedetails"; +import { CommitDetailsItems } from "../commits/commitdetailsitem"; +import { CommitDetails } from "../commits/commitdetails"; +import { BranchDifferences } from "./branchdifferences"; +import GitUIButton from "../../buttons/gituibutton"; + +export interface BrancheDetailsProps { + branch: branch; +} + +export const LocalBranchDetails = (props: BrancheDetailsProps) => { + const { branch } = props; + const actions = React.useContext(gitActionsContext) + const context = React.useContext(gitPluginContext) + const [activePanel, setActivePanel] = useState(""); + const [hasNextPage, setHasNextPage] = useState(false) + const [lastPageNumber, setLastPageNumber] = useState(0) + + useEffect(() => { + if (activePanel === "0") { + console.log('GET BRANCH COMMITS', branch) + if (lastPageNumber === 0) + actions.getBranchCommits(branch, 1) + actions.getBranchDifferences(branch, null, context) + } + }, [activePanel]) + + const checkout = (branch: branch) => { + actions.checkout({ + ref: branch.name, + remote: branch.remote && branch.remote.name || null + }); + } + + const loadNextPage = () => { + console.log('LOAD NEXT PAGE', lastPageNumber + 1) + actions.getBranchCommits(branch, lastPageNumber + 1) + } + + const checkoutCommit = async (oid: string) => { + try { + //await ModalRef.current?.show(); + actions.checkout({ ref: oid }) + //Utils.log("yes"); + } catch (e) { + //Utils.log("no"); + } + }; + + const getRemote = () => { + return context.upstream ? context.upstream : context.defaultRemote ? context.defaultRemote : null + } + + const getCommitChanges = async (commit: ReadCommitResult) => { + await actions.getCommitChanges(commit.oid, commit.commit.parent[0], null, getRemote()) + } + + return ( + + + <> +
+ + {context.localBranchCommits && Object.entries(context.localBranchCommits).map(([key, value]) => { + if (key == branch.name) { + return value.map((commit, index) => { + return () + }) + } + })} + +
+ {hasNextPage && Load more} + +
+
) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/branches/remotebranchedetails.tsx b/libs/remix-ui/git/src/components/panels/branches/remotebranchedetails.tsx new file mode 100644 index 0000000000..bdf1f4d9b4 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/branches/remotebranchedetails.tsx @@ -0,0 +1,109 @@ +import { ReadCommitResult } from "isomorphic-git" +import React, { useEffect, useState } from "react"; +import { Accordion } from "react-bootstrap"; +import { CommitDetailsNavigation } from "../../navigation/commitdetails"; +import { gitActionsContext } from "../../../state/context"; +import { gitPluginContext } from "../../gitui"; +import { branch } from "../../../types"; +import { BrancheDetailsNavigation } from "../../navigation/branchedetails"; +import { CommitDetailsItems } from "../commits/commitdetailsitem"; +import { CommitDetails } from "../commits/commitdetails"; +import GitUIButton from "../../buttons/gituibutton"; + +export interface BrancheDetailsProps { + branch: branch; +} + +export const RemoteBranchDetails = (props: BrancheDetailsProps) => { + const { branch } = props; + const actions = React.useContext(gitActionsContext) + const context = React.useContext(gitPluginContext) + const [activePanel, setActivePanel] = useState(""); + const [hasNextPage, setHasNextPage] = useState(false) + const [lastPageNumber, setLastPageNumber] = useState(0) + + useEffect(() => { + if (activePanel === "0") { + console.log('GET BRANCH COMMITS', branch) + if (lastPageNumber === 0) + actions.getBranchCommits(branch, 1) + } + }, [activePanel]) + + useEffect(() => { + let hasNextPage = false + let lastPageNumber = 0 + console.log('BRANCH COMMITS', context.remoteBranchCommits) + context.remoteBranchCommits && Object.entries(context.remoteBranchCommits).map(([key, value]) => { + if (key == branch.name) { + value.map((page, index) => { + hasNextPage = page.hasNextPage + lastPageNumber = page.page + }) + } + }) + setHasNextPage(hasNextPage) + setLastPageNumber(lastPageNumber) + }, [context.remoteBranchCommits]) + + const checkout = async (branch: branch) => { + await actions.checkout({ + ref: branch.name, + remote: branch.remote && branch.remote.name || null + }); + await actions.getBranches() + } + + const loadNextPage = () => { + console.log('LOAD NEXT PAGE', lastPageNumber + 1) + actions.getBranchCommits(branch, lastPageNumber + 1) + } + + const checkoutCommit = async (oid: string) => { + try { + //await ModalRef.current?.show(); + actions.checkout({ ref: oid }) + //Utils.log("yes"); + } catch (e) { + //Utils.log("no"); + } + }; + + const getCommitChanges = async (commit: ReadCommitResult) => { + const changes = await actions.getCommitChanges(commit.oid, commit.commit.parent[0], branch, branch.remote) + console.log('CHANGES', changes) + if (!changes) { + // try to fetch the data + //await actions.fetch(branch.remote.name, branch.name,null,20, true, false, true) + await actions.fetch({ + remote: branch.remote, + ref: branch, + depth: 20, + singleBranch: true, + relative: false, + quiet: true + }) + } + } + + return ( + + + <> +
+ {context.remoteBranchCommits && Object.entries(context.remoteBranchCommits).map(([key, value]) => { + if (key == branch.name) { + return value.map((page, index) => { + return page.commits.map((commit, index) => { + return () + }) + }) + } + })} + +
+ {hasNextPage && Load more} + +
+
) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/clone.tsx b/libs/remix-ui/git/src/components/panels/clone.tsx new file mode 100644 index 0000000000..b86b0fdf13 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/clone.tsx @@ -0,0 +1,100 @@ + +import React, { useState } from "react"; +import { Alert, Form, FormControl, InputGroup } from "react-bootstrap"; +import { useLocalStorage } from "../../hooks/useLocalStorage"; +import { gitActionsContext } from "../../state/context"; +import { gitPluginContext } from "../gitui"; +import { SelectAndCloneRepositories } from "../github/selectandclonerepositories"; +import { RemixUiCheckbox } from "@remix-ui/checkbox"; +import GitUIButton from "../buttons/gituibutton"; + +export const Clone = () => { + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + const [cloneUrl, setCloneUrl] = useLocalStorage( + "CLONE_URL", + '' + ); + + const [cloneDepth, setCloneDepth] = useLocalStorage( + "CLONE_DEPTH", + 1 + ); + + const [cloneBranch, setCloneBranch] = useLocalStorage( + "CLONE_BRANCH", + '' + ); + + const [url, setUrl] = useLocalStorage( + "GITHUB_URL", + '' + ); + + const clone = async () => { + await actions.clone({ + url: cloneUrl, + branch: cloneBranch, + depth: cloneDepth, + singleBranch: !cloneAllBranches + }) + //await actions.clone(cloneUrl, cloneBranch, cloneDepth, !cloneAllBranches) + } + + const onCloneBranchChange = (value: string) => { + setCloneBranch(value) + } + + const onGitHubCloneUrlChange = (value: string) => { + setCloneUrl(value) + } + + const onDepthChange = (value: number) => { + setCloneDepth(value) + } + + const [cloneAllBranches, setcloneAllBranches] = useLocalStorage( + "GITHUB_CLONE_ALL_BRANCES", + false + ); + + const onAllBranchChange = () => { + setcloneAllBranches((e: any) => !e) + } + + return ( + <> + + onGitHubCloneUrlChange(e.target.value)} aria-describedby="urlprepend" /> + + + onCloneBranchChange(e.target.value)} value={cloneBranch} className="form-control mb-1 mt-2" placeholder="branch" type="text" id="clonebranch" /> + { + clone() + }}>clone +
+ +
+ + + + + --depth + + + onDepthChange(parseInt(e.target.value))} aria-describedby="clonedepthprepend" /> + + + onAllBranchChange()} + checked={cloneAllBranches} + onChange={() => { }} + /> + +
+ ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/commands.tsx b/libs/remix-ui/git/src/components/panels/commands.tsx new file mode 100644 index 0000000000..bb1abc9991 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/commands.tsx @@ -0,0 +1,16 @@ +import React, { useEffect, useState } from "react"; +import { PushPull } from "./commands/pushpull"; +import { Fetch } from "./commands/fetch"; +import { Merge } from "./commands/merge"; + +export const Commands = () => { + + return ( + <> + +
+ +
+ + ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/commands/fetch.tsx b/libs/remix-ui/git/src/components/panels/commands/fetch.tsx new file mode 100644 index 0000000000..f3b4a0bbb4 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/commands/fetch.tsx @@ -0,0 +1,25 @@ +import React, { useEffect, useState } from "react"; +import { gitActionsContext } from "../../../state/context"; +import GitUIButton from "../../buttons/gituibutton"; +import { gitPluginContext } from "../../gitui"; + +export const Fetch = () => { + const actions = React.useContext(gitActionsContext) + const context = React.useContext(gitPluginContext) + + const fetchIsDisabled = () => { + return (!context.upstream) || context.remotes.length === 0 + } + return ( + <> +
+ actions.fetch({ + remote: context.upstream, + })} className="btn btn-primary mr-1 w-50">
Fetch {context.upstream && context.upstream.name}
+ actions.fetch({ + remote: context.upstream, + ref: context.currentBranch + })} className="btn btn-primary w-50 long-and-truncated">Fetch {context.currentBranch.name} +
+ ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/commands/merge.tsx b/libs/remix-ui/git/src/components/panels/commands/merge.tsx new file mode 100644 index 0000000000..1e7c41cad8 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/commands/merge.tsx @@ -0,0 +1,58 @@ +import React, { useEffect, useState } from "react"; +import { gitActionsContext } from "../../../state/context"; +import { gitPluginContext } from "../../gitui"; +import { selectStyles, selectTheme } from "../../../types/styles"; +import Select from 'react-select' +import GitUIButton from "../../buttons/gituibutton"; + +export const Merge = () => { + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + const [localBranch, setLocalBranch] = useState('') + const [localBranchOptions, setLocalBranchOptions] = useState([]); + + useEffect(() => { + setLocalBranch(context.currentBranch.name) + }, [context.currentBranch]) + + const onLocalBranchChange = (value: any) => { + console.log('onLocalBranchChange', value) + setLocalBranch(value) + } + + const merge = async () => { + //gitservice.push(currentRemote, branch || '', remoteBranch, force) + } + + useEffect(() => { + // map context.repositories to options + const localBranches = context.branches && context.branches.length > 0 && context.branches + .filter(branch => !branch.remote) + .map(repo => { + return { value: repo.name, label: repo.name } + }) + setLocalBranchOptions(localBranches) + + }, [context.branches]) + + return ( + <> + +
+ merge()} className="btn btn-primary mr-1">Merge +
+ + + e && onLocalBranchChange(e.value)} + theme={selectTheme} + styles={selectStyles} + isClearable={true} + value={{ value: localBranch, label: localBranch }} + placeholder="Type to search for a branch..." + /> + + + e && onRemoteChange(e.value)} + theme={selectTheme} + styles={selectStyles} + isClearable={true} + value={{ value: context.upstream && context.upstream.name, label: context.upstream && context.upstream.name }} + placeholder="Type to search for a branch..." + /> + +
+ onForceChange(e)} className="remixui_autocompile custom-control-input" type="checkbox" data-id="compilerContainerAutoCompile" id="forcepush" title="Force Push" /> + +
+ + ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/commits.tsx b/libs/remix-ui/git/src/components/panels/commits.tsx new file mode 100644 index 0000000000..f0893ab371 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/commits.tsx @@ -0,0 +1,68 @@ +import { checkout, ReadCommitResult } from "isomorphic-git"; +import React from "react"; +import { gitActionsContext } from "../../state/context"; +import GitUIButton from "../buttons/gituibutton"; +import { gitPluginContext } from "../gitui"; +import LoaderIndicator from "../navigation/loaderindicator"; +import { BranchDifferences } from "./branches/branchdifferences"; +import { CommitDetails } from "./commits/commitdetails"; +import { CommitSummary } from "./commits/commitsummary"; + +export const Commits = () => { + const [hasNextPage, setHasNextPage] = React.useState(true) + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + + const checkout = async (oid: string) => { + try { + //await ModalRef.current?.show(); + actions.checkout({ ref: oid }) + //Utils.log("yes"); + } catch (e) { + //Utils.log("no"); + } + }; + + const loadNextPage = () => { + console.log('LOAD NEXT PAGE', context.commits.length) + //actions.fetch(null, context.currentBranch.name, null, 5, true, true) + actions.fetch({ + remote: null, + ref: context.currentBranch, + relative: true, + depth: 5, + singleBranch: true + }) + //actions.getBranchCommits(branch, lastPageNumber+1) + } + + const getRemote = () => { + return context.upstream ? context.upstream : context.defaultRemote ? context.defaultRemote : null + } + + const getCommitChanges = async (commit: ReadCommitResult) => { + await actions.getCommitChanges(commit.oid, commit.commit.parent[0],null, getRemote()) + } + + const fetchIsDisabled = () => { + return (!context.upstream)|| context.remotes.length === 0 + } + + return ( + <> + {context.commits && context.commits.length ? + <>
+
+ {context.commits && context.commits.map((commit, index) => { + return ( + + ); + })} +
+
+ {hasNextPage && Load more} + + :
No commits
} + + ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/commits/commitdetails.tsx b/libs/remix-ui/git/src/components/panels/commits/commitdetails.tsx new file mode 100644 index 0000000000..2fecd45b05 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/commits/commitdetails.tsx @@ -0,0 +1,62 @@ +import { ReadCommitResult } from "isomorphic-git" +import React, { useEffect, useState } from "react"; +import { Accordion } from "react-bootstrap"; +import { CommitDetailsNavigation } from "../../navigation/commitdetails"; +import { gitActionsContext } from "../../../state/context"; +import { gitPluginContext } from "../../gitui"; +import { CommitDetailsItems } from "./commitdetailsitem"; +import { branch, remote } from "@remix-ui/git"; + +export interface CommitDetailsProps { + commit: ReadCommitResult; + checkout: (oid: string) => void; + getCommitChanges: (commit: ReadCommitResult) => void; + branch: branch +} + +export const CommitDetails = (props: CommitDetailsProps) => { + const { commit, checkout, getCommitChanges, branch } = props; + const actions = React.useContext(gitActionsContext) + const context = React.useContext(gitPluginContext) + const [activePanel, setActivePanel] = useState(""); + + useEffect(() => { + if (activePanel === "0") { + console.log(context) + getCommitChanges(commit) + } + }, [activePanel]) + + const getRemote = (): remote | null => { + return context.upstream ? context.upstream : context.defaultRemote ? context.defaultRemote : null + } + + const commitsAhead = (remote: remote) => { + if (!remote) return []; + return context.branchDifferences[`${remote.name}/${branch.name}`]?.uniqueHeadCommits || []; + } + + const isAheadOfRepo = () => { + return commitsAhead(getRemote()).findIndex((c) => c.oid === commit.oid) > -1 + } + + const openFileOnRemote = (file: string, hash: string) => { + console.log("open file on remote", file, hash, getRemote() ? `${getRemote().name}/${branch.name}/commit/${hash}/${file}` : "") + if (!getRemote()) return + window.open(`${getRemote() ? `${getRemote().url}/blob/${hash}/${file}` : ""}`, "_blank") + } + + return ( + + + <> + {context.commitChanges && context.commitChanges.filter( + (change) => change.hashModified === commit.oid && change.hashOriginal === commit.commit.parent[0] + ).map((change, index) => { + return () + })} + + + + ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/commits/commitdetailsitem.tsx b/libs/remix-ui/git/src/components/panels/commits/commitdetailsitem.tsx new file mode 100644 index 0000000000..00638efb43 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/commits/commitdetailsitem.tsx @@ -0,0 +1,53 @@ +import { branch, commitChange } from "../../../types"; +import React from "react"; +import path from "path"; +import { gitActionsContext, pluginActionsContext } from "../../../state/context"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faGlobe } from "@fortawesome/free-solid-svg-icons"; + +export interface CCommitDetailsItemsProps { + commitChange: commitChange; + isAheadOfRepo: boolean; + openFileOnRemote: (file: string, hash: string) => void; +} + +export const CommitDetailsItems = (props: CCommitDetailsItemsProps) => { + const { commitChange, isAheadOfRepo, openFileOnRemote } = props; + const actions = React.useContext(gitActionsContext) + const pluginActions = React.useContext(pluginActionsContext) + + const openChanges = async (change: commitChange) => { + console.log("open changes", change); + await actions.diff(change) + console.log("open changes", change); + await pluginActions.openDiff(change) + } + + const openRemote = () => { + openFileOnRemote(commitChange.path, commitChange.hashModified) + } + + function FunctionStatusIcons() { + const status = commitChange.type + return (<> + + {status && status.indexOf("modified") === -1 ? <> : M} + {status && status.indexOf("deleted") === -1 ? <> : D} + {status && status.indexOf("added") === -1 ? <> : A} + + ) + } + return (<> +
+
await openChanges(commitChange)}> + {path.basename(commitChange.path)} +
{commitChange.path}
+
+
+ {!isAheadOfRepo ? + openRemote()} className="pointer mr-1 align-self-center" /> : <>} + +
+
+ ) +} diff --git a/libs/remix-ui/git/src/components/panels/commits/commitsummary.tsx b/libs/remix-ui/git/src/components/panels/commits/commitsummary.tsx new file mode 100644 index 0000000000..79caa2de6a --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/commits/commitsummary.tsx @@ -0,0 +1,67 @@ +import { ReadCommitResult } from "isomorphic-git" +import { default as dateFormat } from "dateformat"; +import React from "react"; +import { faGlobe } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { remote } from "@remix-ui/git"; +import GitUIButton from "../../buttons/gituibutton"; +import { gitPluginContext } from "../../gitui"; + +export interface CommitSummaryProps { + commit: ReadCommitResult; + checkout: (oid: string) => void; + isAheadOfRepo: boolean +} + +export const CommitSummary = (props: CommitSummaryProps) => { + const { commit, checkout, isAheadOfRepo } = props; + const context = React.useContext(gitPluginContext) + + const getDate = (commit: ReadCommitResult) => { + const timestamp = commit.commit.author.timestamp; + + if (timestamp) { + // calculate the difference between the current time and the commit time in days or hours or minutes + const diff = Math.floor((Date.now() - timestamp * 1000) / 1000 / 60 / 60 / 24); + + if (diff == 0) { + return "today at " + dateFormat(timestamp * 1000, "HH:MM"); + } else + + if (diff < 1) { + // return how many hours ago + return `${Math.floor(diff * 24)} hour(s) ago`; + } + + if (diff < 7) { + // return how many days ago + return `${diff} day(s) ago`; + } + if (diff < 365) { + return dateFormat(timestamp * 1000, "mmm dd"); + } + return dateFormat(timestamp * 1000, "mmm dd yyyy"); + } + return ""; + }; + + const getRemote = (): remote | null => { + return context.upstream ? context.upstream : context.defaultRemote ? context.defaultRemote : null + } + + const openRemote = () => { + if (getRemote()) + window.open(`${getRemote().url}/commit/${commit.oid}`, '_blank'); + } + + return ( + <> +
+ {commit.commit.message} +
+ {commit.commit.author.name || ""} + {getDate(commit)} + {getRemote() && getRemote()?.url && !isAheadOfRepo && openRemote()}>} + + ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/githubcredentials.tsx b/libs/remix-ui/git/src/components/panels/githubcredentials.tsx new file mode 100644 index 0000000000..c51a299fb8 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/githubcredentials.tsx @@ -0,0 +1,83 @@ +import React, { useEffect } from "react"; +import { gitActionsContext, pluginActionsContext } from "../../state/context"; +import { gitPluginContext, loaderContext } from "../gitui"; +import { CustomTooltip } from "@remix-ui/helper"; + +import { useIntl, FormattedMessage } from "react-intl"; +import { CopyToClipboard } from "@remix-ui/clipboard"; + +export const GitHubCredentials = () => { + const context = React.useContext(gitPluginContext) + const pluginactions = React.useContext(pluginActionsContext) + const loader = React.useContext(loaderContext) + const actions = React.useContext(gitActionsContext) + const [githubToken, setGithubToken] = React.useState('') + const [githubUsername, setGithubUsername] = React.useState('') + const [githubEmail, setGithubEmail] = React.useState('') + const intl = useIntl() + + useEffect(() => { + refresh() + }, [loader.plugin, context.gitHubAccessToken, context.userEmails, context.gitHubUser]) + + function handleChangeTokenState(e: string): void { + setGithubToken(e) + } + + function handleChangeUserNameState(e: string): void { + setGithubUsername(e) + } + + function handleChangeEmailState(e: string): void { + setGithubEmail(e) + } + + async function saveGithubToken() { + await pluginactions.saveGitHubCredentials({ + username: githubUsername, + email: githubEmail, + token: githubToken + }) + } + + async function refresh() { + const credentials = await pluginactions.getGitHubCredentialsFromLocalStorage() + if (!credentials) return + console.log('credentials', credentials) + setGithubToken(credentials.token || '') + setGithubUsername(credentials.username || '') + setGithubEmail(credentials.email || '') + } + + function removeToken(): void { + setGithubToken('') + setGithubUsername('') + setGithubEmail('') + pluginactions.saveGitHubCredentials({ + username: '', + email: '', + token: '' + }) + } + + return ( + <> +
+ handleChangeTokenState(e.target.value)} /> +
+ +
+
+ handleChangeUserNameState(e.target.value)} value={githubUsername} className="form-control mb-1" placeholder="Git username" type="text" id="githubUsername" /> + handleChangeEmailState(e.target.value)} value={githubEmail} className="form-control mb-1" placeholder="Git email" type="text" id="githubEmail" /> +
+ + +
+
+ + ); +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/init.tsx b/libs/remix-ui/git/src/components/panels/init.tsx new file mode 100644 index 0000000000..070acc9669 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/init.tsx @@ -0,0 +1,29 @@ +import { CustomTooltip } from '@remix-ui/helper'; +import { pull } from 'lodash'; +import React, { useContext } from 'react'; +import { FormattedMessage } from 'react-intl'; +import { gitActionsContext } from '../../state/context'; +import GitUIButton from '../buttons/gituibutton'; + +export const Init = () => { + + const actions = React.useContext(gitActionsContext) + + const init = async () => { + actions.init() + } + + return ( + <> +
+
+ +
+
+ + ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/log.tsx b/libs/remix-ui/git/src/components/panels/log.tsx new file mode 100644 index 0000000000..4c1b627b5d --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/log.tsx @@ -0,0 +1,39 @@ +// src/LogViewer.tsx +import React, { useContext } from 'react'; +import { gitPluginContext } from '../gitui'; + +const LogViewer = () => { + const context = useContext(gitPluginContext); + + const typeToCssClass = (type: string) => { + switch (type) { + case 'error': + return 'text-danger'; + case 'warning': + return 'text-warning'; + case 'info': + return 'text-info'; + case 'debug': + return 'text-secondary'; + default: + return 'text-success'; + } + }; + + if (context.log && context.log.length > 0) { + + return ( +
+ {context.log && context.log.map((log, index) => ( +
+ [{log.type.toUpperCase()}] {log.message} +
+ ))} +
+ ); + } else { + return
No logs
+ } +}; + +export default LogViewer; diff --git a/libs/remix-ui/git/src/components/panels/remotes.tsx b/libs/remix-ui/git/src/components/panels/remotes.tsx new file mode 100644 index 0000000000..376dc33c70 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/remotes.tsx @@ -0,0 +1,57 @@ +import React, { useEffect } from "react"; +import { gitActionsContext } from "../../state/context"; +import { gitPluginContext } from "../gitui"; +import { Remoteselect } from "./remoteselect"; +import { RemotesImport } from "./remotesimport"; + +export const Remotes = () => { + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + const [remoteName, setRemoteName] = React.useState('') + const [url, setUrl] = React.useState('') + + const onRemoteNameChange = (value: string) => { + setRemoteName(value) + } + const onUrlChange = (value: string) => { + setUrl(value) + } + + const addRemote = async () => { + actions.addRemote({ + name: remoteName, + url: url + }) + } + + useEffect(() => { + console.log('SHOW REMOTES', context.remotes) + }, [context.remotes]) + + return ( + <> + + {context.remotes && context.remotes.length ? + <> + + {context.remotes && context.remotes.map((remote, index) => { + + return ( + + ); + })} + : <>No remotes} +
+ + onRemoteNameChange(e.target.value)} value={remoteName} className="form-control mb-2" type="text" id="remotename" /> + onUrlChange(e.target.value)} value={url} className="form-control" type="text" id="remoteurl" /> + + +
+ +
+ + ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/remoteselect.tsx b/libs/remix-ui/git/src/components/panels/remoteselect.tsx new file mode 100644 index 0000000000..e279320755 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/remoteselect.tsx @@ -0,0 +1,47 @@ +import { branch, checkout, ReadCommitResult } from "isomorphic-git"; +import React, { useEffect, useState } from "react"; +import { gitActionsContext } from "../../state/context"; +import { gitPluginContext } from "../gitui"; +import { default as dateFormat } from "dateformat"; +import { RemotesDetailsNavigation } from "../navigation/remotesdetails"; +import { Accordion } from "react-bootstrap"; +import { remote } from "../../types"; +import { RemoteBranchDetails } from "./branches/remotebranchedetails"; + +export interface RemoteSelectProps { + remote: remote +} + +export const Remoteselect = (props: RemoteSelectProps) => { + const { remote } = props; + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + const [activePanel, setActivePanel] = useState(""); + + useEffect(() => { + if (activePanel === "0") { + console.log('fetching', remote) + } + }, [activePanel]) + + useEffect(() => { + console.log('remote branches', context.branches) + }, [context.branches]) + + return ( + <> + + + + <> + {context.branches && context.branches.filter((branch, index) => branch.remote && branch.remote.name === remote.name ).map((branch, index) => { + return ( + + ); + })} + + + + + ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/remotesimport.tsx b/libs/remix-ui/git/src/components/panels/remotesimport.tsx new file mode 100644 index 0000000000..b79c40d230 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/remotesimport.tsx @@ -0,0 +1,86 @@ +import React, { useEffect, useState } from "react"; +import { Alert, Button } from "react-bootstrap"; +import { gitActionsContext } from "../../state/context"; +import { repository } from "../../types"; +import { gitPluginContext } from "../gitui"; +import Select from 'react-select' +import { selectStyles, selectTheme } from "../../types/styles"; +import { TokenWarning } from "./tokenWarning"; +import RepositorySelect from "../github/repositoryselect"; + +export const RemotesImport = () => { + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + const [repo, setRepo] = useState(null); + const [repoOtions, setRepoOptions] = useState([]); + const [loading, setLoading] = useState(false) + const [show, setShow] = useState(false) + const [remoteName, setRemoteName] = useState('') + + useEffect(() => { + if (context.repositories && context.repositories.length > 0) { + // map context.repositories to options + const options = context.repositories && context.repositories.length > 0 && context.repositories.map(repo => { + return { value: repo.id, label: repo.full_name } + }) + setRepoOptions(options) + } else { + setRepoOptions(null) + setShow(false) + } + setLoading(false) + + }, [context.repositories]) + + const fetchRepositories = async () => { + try { + setShow(true) + setLoading(true) + setRepoOptions([]) + console.log(await actions.repositories()) + } catch (e) { + // do nothing + } + }; + + const selectRepo = async (repo: repository) => { + setRepo(repo) + } + + useEffect(() => { + console.log('OTIONS', repoOtions) + },[repoOtions]) + + const addRemote = async () => { + try { + actions.addRemote({ + name: remoteName, + url: repo.html_url + }) + } catch (e) { + // do nothing + } + + }; + const onRemoteNameChange = (value: string) => { + setRemoteName(value) + } + + return ( + <> + + + + {repo ? + onRemoteNameChange(e.target.value)} value={remoteName} className="form-control mb-2" type="text" id="remotename" /> + : null} + + {repo && remoteName ? + : null} + + + ) +} + diff --git a/libs/remix-ui/git/src/components/panels/settings.tsx b/libs/remix-ui/git/src/components/panels/settings.tsx new file mode 100644 index 0000000000..5267a72e24 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/settings.tsx @@ -0,0 +1,48 @@ +import { checkout, clone, ReadCommitResult } from "isomorphic-git"; +import React from "react"; +import { gitActionsContext } from "../../state/context"; +import { gitPluginContext } from "../gitui"; +import { CustomTooltip } from "@remix-ui/helper"; + +import { useIntl, FormattedMessage } from "react-intl"; +import { CopyToClipboard } from "@remix-ui/clipboard"; +import { FormControl, InputGroup } from "react-bootstrap"; + +export const Settings = () => { + + const [githubToken, setGithubToken] = React.useState('') + const [githubUsername, setGithubUsername] = React.useState('') + const [githubEmail, setGithubEmail] = React.useState('') + const intl = useIntl() + + const gitAccessTokenLink = 'https://github.com/settings/tokens/new?scopes=gist,repo&description=Remix%20IDE%20Token' + + function handleChangeTokenState(e: string): void { + throw new Error("Function not implemented."); + } + + function handleChangeUserNameState(e: string): void { + throw new Error("Function not implemented."); + } + + function handleChangeEmailState(e: string): void { + throw new Error("Function not implemented."); + } + + function saveGithubToken(): void { + throw new Error("Function not implemented."); + } + + function removeToken(): void { + throw new Error("Function not implemented."); + } + + return ( + <> + handleChangeUserNameState(e.target.value)} value={githubToken} className="form-control mb-2" placeholder="GitHub token" type="text" id="githubToken" /> + handleChangeUserNameState(e.target.value)} value={githubUsername} className="form-control mb-2" placeholder="GitHub username" type="text" id="githubUsername" /> + handleChangeEmailState(e.target.value)} value={githubEmail} className="form-control mb-1" placeholder="GitHub email" type="text" id="githubEmail" /> +
+ + ); +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/setup.tsx b/libs/remix-ui/git/src/components/panels/setup.tsx new file mode 100644 index 0000000000..42a68014ae --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/setup.tsx @@ -0,0 +1,36 @@ +import React, { useEffect, useState } from 'react' +import { GetDeviceCode } from '../github/devicecode' +import { GitHubCredentials } from './githubcredentials' + +export const Setup = () => { + + const [screen, setScreen] = useState(0) + + if (screen === 0) { + return ( + <> +
SETUP
+
+
+ To ensure that your commits are properly attributed in Git, you need to configure a username and email address. + These will be used to identify the author of the commit. +
+ +
+ +
+ + ) + } else if (screen === 1) { + return ( + <> +
SETUP
+
Step 2
+
+ To ensure that your commits are properly attributed in Git, you need to configure your username and email address. + +
+ + ) + } +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcecontrolgroup.tsx b/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcecontrolgroup.tsx new file mode 100644 index 0000000000..1b17cb2b31 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcecontrolgroup.tsx @@ -0,0 +1,38 @@ +import { ReadCommitResult } from "isomorphic-git" +import React, { useEffect, useState } from "react"; +import { Accordion } from "react-bootstrap"; +import { gitActionsContext } from "../../../state/context"; +import { gitPluginContext } from "../../gitui"; +import { sourceControlGroup } from "../../../types"; +import { SourceControlGroupNavigation } from "../../navigation/sourcecontrolgroup"; +import { SourceControlItem } from "./sourcecontrolitem"; + +export interface SourceControGroupProps { + group: sourceControlGroup +} + +export const SourceControGroup = (props: SourceControGroupProps) => { + const { group } = props; + const actions = React.useContext(gitActionsContext) + const context = React.useContext(gitPluginContext) + const [activePanel, setActivePanel] = useState("0"); + + useEffect(() => { + if (activePanel === "0") { + } + }, [activePanel]) + + return (<> + {group.group.length > 0 ? + + + + <> + {group.group.map((file, index) => { + return () + })} + + + : <>} + ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcecontrolitem.tsx b/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcecontrolitem.tsx new file mode 100644 index 0000000000..f898897b54 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcecontrolitem.tsx @@ -0,0 +1,67 @@ +import { commitChange, fileStatusResult, sourceControlGroup } from "../../../types"; +import React from "react"; +import path from "path"; +import { gitActionsContext, pluginActionsContext } from "../../../state/context"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faGlobe } from "@fortawesome/free-solid-svg-icons"; +import { SourceControlItemButtons } from "./sourcontrolitembuttons"; +import { removeSlash } from "../../../utils"; + +export interface SourceControlItemProps { + file: fileStatusResult; + group: sourceControlGroup; +} + +export const SourceControlItem = (props: SourceControlItemProps) => { + const { file, group } = props; + const actions = React.useContext(gitActionsContext) + const pluginActions = React.useContext(pluginActionsContext) + + async function fileClick(file: fileStatusResult) { + console.log(file) + //let status = fileservice.getFileStatusForFile(file.filename || ""); + if (file.statusNames && file.statusNames.indexOf("modified") !== -1) { + const headHash = await actions.resolveRef("HEAD") + const change: commitChange = { + path: removeSlash(file.filename), + type: "modified", + hashOriginal: headHash, + hashModified: '', + readonly: false, + } + await actions.diff(change) + await pluginActions.openDiff(change) + console.log("diff", change) + + } else { + await pluginActions.openFile(file.filename) + //await client.call('fileManager', 'open', file.filename) + } + } + + function FunctionStatusIcons() { + + const status = file.statusNames + + return (<> + + {status && status.indexOf("modified") === -1 ? <> :
M
} + {status && status.indexOf("deleted") === -1 ? <> : D} + {status && status.indexOf("added") === -1 ? <> : A} + {status && status.indexOf("untracked") === -1 ? <> : U} + ) + + } + return (<> +
+
await fileClick(file)}> + {path.basename(file.filename)} +
{file.filename}
+
+
+ + +
+
+ ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcontrolitembuttons.tsx b/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcontrolitembuttons.tsx new file mode 100644 index 0000000000..e6492cb4e4 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/sourcecontrol/sourcontrolitembuttons.tsx @@ -0,0 +1,44 @@ +import { commitChange, fileStatusResult, sourceControlGroup } from "../../../types"; +import React from "react"; +import path from "path"; +import { gitActionsContext, pluginActionsContext } from "../../../state/context"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faGlobe, faMinus, faPlus, faUndo } from "@fortawesome/free-solid-svg-icons"; + +export interface SourceControlItemButtonsProps { + file: fileStatusResult, + group: sourceControlGroup +} + +export const SourceControlItemButtons = (props: SourceControlItemButtonsProps) => { + const { file, group } = props; + const actions = React.useContext(gitActionsContext) + const pluginActions = React.useContext(pluginActionsContext) + + function RenderButtons() { + const status = file.statusNames + + if (group.name === 'Staged') { + return <> + + {status && status.indexOf("modified") === -1 ? <> : } + {status && status.indexOf("deleted") === -1 ? <> : } + {status && status.indexOf("deleted") !== -1 ? <> : } + + + } + if (group.name === 'Changes') { + return <> + + {status && status.indexOf("deleted") === -1 ? <> : <>} + {status && status.indexOf("modified") === -1 ? <> : } + {(status && status.indexOf("unstaged") !== -1 || status && status.indexOf("deleted") !== -1) ? <> : } + {(status && status.indexOf("unstaged") !== -1 && status && status.indexOf("modified") !== -1) ? : <>} + + } + return <> + } + + return + +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/sourcontrol.tsx b/libs/remix-ui/git/src/components/panels/sourcontrol.tsx new file mode 100644 index 0000000000..4866c2cc2d --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/sourcontrol.tsx @@ -0,0 +1,57 @@ +import React, { useEffect, useState } from 'react' +import { gitActionsContext, pluginActionsContext } from '../../state/context' +import { gitPluginContext } from '../gitui' +import { sourceControlGroup } from '../../types' +import { SourceControGroup } from './sourcecontrol/sourcecontrolgroup' + +export const SourceControl = () => { + const context = React.useContext(gitPluginContext) + const actions = React.useContext(gitActionsContext) + const pluginactions = React.useContext(pluginActionsContext) + const [show, setShow] = useState(false) + + useEffect(() => { + if (context.fileStatusResult) { + console.log(context) + const total = context.allchangesnotstaged.length + const badges = total + context.staged.length + pluginactions.statusChanged(badges) + //console.log("allchangesnotstaged", context.allchangesnotstaged, context.fileStatusResult) + setShow((context.deleted.length > 0 || context.staged.length > 0 || context.untracked.length > 0 || context.modified.length > 0)) + } + }, [context.fileStatusResult, context.modified, context.allchangesnotstaged, context.untracked, context.deleted]) + + useEffect(() => { + if (context.commits) { + console.log("SC commits", context.localCommitCount, context.currentBranch) + } + }, [context.localCommitCount, context.currentBranch]) + + function RenderGroups() { + const groups: sourceControlGroup[] = [{ name: 'Staged', group: context.staged }, { name: 'Changes', group: context.allchangesnotstaged }] + return (<> + { + groups.map((ob: sourceControlGroup, index: number) => { + return ( + + ) + }) + } + + ) + } + + return ( + <> + {show ? + <> +
+ +
+ : <> + + } + + ); + +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/tokenWarning.tsx b/libs/remix-ui/git/src/components/panels/tokenWarning.tsx new file mode 100644 index 0000000000..4188c07c93 --- /dev/null +++ b/libs/remix-ui/git/src/components/panels/tokenWarning.tsx @@ -0,0 +1,12 @@ +import { gitPluginContext } from "../gitui" +import React, { useEffect, useState } from "react"; +export const TokenWarning = () => { + const context = React.useContext(gitPluginContext) + return (<> + {(context.gitHubUser && context.gitHubUser.login) ? null : +
  • + To use add a GitHub token to the settings.
  • + } + + ) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/hooks/useLocalStorage.tsx b/libs/remix-ui/git/src/hooks/useLocalStorage.tsx new file mode 100644 index 0000000000..dbef5378a8 --- /dev/null +++ b/libs/remix-ui/git/src/hooks/useLocalStorage.tsx @@ -0,0 +1,37 @@ +import { useState } from "react" + +export function useLocalStorage(key: string, initialValue: any) { + // State to store our value + // Pass initial state function to useState so logic is only executed once + const [storedValue, setStoredValue] = useState(() => { + try { + // Get from local storage by key + const item = window.localStorage.getItem(key) + // Parse stored json or if none return initialValue + return item ? JSON.parse(item) : initialValue + } catch (error) { + // If error also return initialValue + console.error(error) + return initialValue + } + }) + + // Return a wrapped version of useState's setter function that ... + // ... persists the new value to localStorage. + const setValue = (value: any) => { + try { + // Allow value to be a function so we have same API as useState + const valueToStore = + value instanceof Function ? value(storedValue) : value + // Save state + setStoredValue(valueToStore) + // Save to local storage + window.localStorage.setItem(key, JSON.stringify(valueToStore)) + } catch (error) { + // A more advanced implementation would handle the error case + console.error(error) + } + } + + return [storedValue, setValue] +} diff --git a/libs/remix-ui/git/src/index.ts b/libs/remix-ui/git/src/index.ts new file mode 100644 index 0000000000..677c174059 --- /dev/null +++ b/libs/remix-ui/git/src/index.ts @@ -0,0 +1,4 @@ +export * from './types' +export { GitUI } from './components/gitui' +export { commitChange, commitChangeType, remote, branch } from './types' +export * from './types/styles' \ No newline at end of file diff --git a/libs/remix-ui/git/src/lib/fileHelpers.ts b/libs/remix-ui/git/src/lib/fileHelpers.ts new file mode 100644 index 0000000000..6076cac43e --- /dev/null +++ b/libs/remix-ui/git/src/lib/fileHelpers.ts @@ -0,0 +1,56 @@ +import { fileStatusResult, gitState } from "../types"; + +export const getFilesCountByStatus = (status: string, files: fileStatusResult[]) => { + let count = 0; + + files.map((m) => { + if (m.statusNames !== undefined) { + if (m.statusNames && m.statusNames.indexOf(status) > -1) { + count++; + } + } + }); + return count; +} + +export const getFilesByStatus = (status: string, files: fileStatusResult[]): fileStatusResult[] => { + const result: fileStatusResult[] = [] + files.map((m) => { + if (m.statusNames !== undefined) { + if (m.statusNames && m.statusNames.indexOf(status) > -1) { + result.push(m) + } + } + }); + return result; +} + +export const getFilesWithNotModifiedStatus = (files: fileStatusResult[]): fileStatusResult[] => { + const result: fileStatusResult[] = [] + + files.map((m) => { + + if (m.statusNames !== undefined) { + if (m.statusNames && m.statusNames.indexOf("unmodified") === -1) { + result.push(m) + } + } + }); + return result; +} + +export const allChangedButNotStagedFiles = (files: fileStatusResult[]): fileStatusResult[] => { + let allfiles = getFilesWithNotModifiedStatus(files) + const staged = getFilesByStatus("staged", files) + allfiles = allfiles.filter((trackedFile) => { + return staged.findIndex((stagedFile) => stagedFile.filename === trackedFile.filename) === -1 + }) + return allfiles; +} + +export const getFileStatusForFile = (filename: string, files: fileStatusResult[]) => { + for (let i: number = 0; i < files.length; i++) { + if (files[i].filename === filename) + return files[i].statusNames; + } +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/lib/gitactions.ts b/libs/remix-ui/git/src/lib/gitactions.ts new file mode 100644 index 0000000000..d28348af74 --- /dev/null +++ b/libs/remix-ui/git/src/lib/gitactions.ts @@ -0,0 +1,802 @@ +import { ViewPlugin } from "@remixproject/engine-web"; +import { ReadBlobResult, ReadCommitResult } from "isomorphic-git"; +import React from "react"; +import { fileStatus, fileStatusMerge, setRemoteBranchCommits, resetRemoteBranchCommits, setBranches, setCanCommit, setCommitChanges, setCommits, setCurrentBranch, setGitHubUser, setLoading, setRateLimit, setRemoteBranches, setRemotes, setRepos, setUpstream, setLocalBranchCommits, setBranchDifferences, setRemoteAsDefault, setScopes, setLog, clearLog, setUserEmails } from "../state/gitpayload"; +import { GitHubUser, RateLimit, branch, commitChange, gitActionDispatch, statusMatrixType, gitState, branchDifference, remote, gitLog, fileStatusResult, customGitApi, IGitApi, cloneInputType, fetchInputType, pullInputType, pushInputType, checkoutInput, rmInput, addInput, repository, userEmails } from '../types'; +import { removeSlash } from "../utils"; +import { disableCallBacks, enableCallBacks } from "./listeners"; +import { AlertModal, ModalTypes } from "@remix-ui/app"; +import { gitActions, gitActionsContext } from "../state/context"; +import { gitPluginContext } from "../components/gitui"; +import { setFileDecorators } from "./pluginActions"; +import { IDgitSystem, IRemixApi, RemixApi } from "@remixproject/plugin-api"; +import { Plugin } from "@remixproject/engine"; +import { AnyMxRecord } from "dns"; +import { StatusEvents } from "@remixproject/plugin-utils"; +import { CustomRemixApi } from "@remix-api"; + +export const fileStatuses = [ + ["new,untracked", 0, 2, 0], // new, untracked + ["added,staged", 0, 2, 2], // + ["added,staged,with unstaged changes", 0, 2, 3], // added, staged, with unstaged changes + ["unmodified", 1, 1, 1], // unmodified + ["modified,unstaged", 1, 2, 1], // modified, unstaged + ["modified,staged", 1, 2, 2], // modified, staged + ["modified,staged,with unstaged changes", 1, 2, 3], // modified, staged, with unstaged changes + ["deleted,unstaged", 1, 0, 1], // deleted, unstaged + ["deleted,staged", 1, 0, 0], + ["unmodified", 1, 1, 3], + ["deleted,not in git", 0, 0, 3], + ["unstaged,modified", 1, 2, 0] +]; + +const statusmatrix: statusMatrixType[] = fileStatuses.map((x: any) => { + return { + matrix: x.shift().split(","), + status: x, + }; +}); + +let plugin: Plugin, dispatch: React.Dispatch + +export const setPlugin = (p: Plugin, dispatcher: React.Dispatch) => { + plugin = p + dispatch = dispatcher + console.log('setPlugin') +} + +export const init = async () => { + console.log('gitInit') + await plugin.call('dgitApi', "init"); + await gitlog(); + await getBranches(); +} + +export const getBranches = async () => { + console.log('getBranches') + const branches = await plugin.call('dgitApi', "branches") + console.log('branches :>>', branches) + dispatch(setBranches(branches)); +} +export const getRemotes = async () => { + console.log('getRemotes') + const remotes: remote[] = await plugin.call('dgitApi', "remotes"); + console.log('remotes :>>', remotes) + dispatch(setRemotes(remotes)); +} + +export const setUpstreamRemote = async (remote: remote) => { + dispatch(setUpstream(remote)); +} + +export const getFileStatusMatrix = async (filepaths: string[]) => { + const fileStatusResult = await statusMatrix(filepaths); + fileStatusResult.map((m) => { + statusmatrix.map((sm) => { + if (JSON.stringify(sm.status) === JSON.stringify(m.status)) { + //Utils.log(m, sm); + m.statusNames = sm.matrix; + } + }); + }); + //console.log(fileStatusResult); + if (!filepaths) { + dispatch(fileStatus(fileStatusResult)) + } else { + dispatch(fileStatusMerge(fileStatusResult)) + setFileDecorators(fileStatusResult) + } +} + +export const getCommits = async () => { + //Utils.log("get commits"); + console.log('getCommits') + try { + const commits: ReadCommitResult[] = await plugin.call( + 'dgitApi', + "log", + { ref: "HEAD" } + ); + console.log('commits :>>', commits) + return commits; + } catch (e) { + return []; + } +} + +export const gitlog = async () => { + let commits = [] + try { + commits = await getCommits() + } catch (e) { + } + dispatch(setCommits(commits)) + await showCurrentBranch() +} + +export const showCurrentBranch = async () => { + try { + const branch = await currentBranch(); + console.log('branch :>>', branch) + + dispatch(setCanCommit((branch && branch.name !== ""))); + dispatch(setCurrentBranch(branch)); + + } catch (e) { + // show empty branch + } +} + +export const currentBranch = async () => { + + const branch: branch = + (await plugin.call('dgitApi', "currentbranch")) || { + name: "", + remote: { + name: "", + url: "", + }, + }; + return branch; + +} + +export const createBranch = async (name: string = "") => { + dispatch(setLoading(true)) + if (name) { + await plugin.call('dgitApi', 'branch', { ref: name }); + await plugin.call('dgitApi', 'checkout', { ref: name }); + } + dispatch(setLoading(false)) +} + +export const getCommitFromRef = async (ref: string) => { + const commitOid = await plugin.call('dgitApi', "resolveref", { + ref: ref, + }); + return commitOid; +} + +const settingsWarning = async () => { + const username = await plugin.call('config', 'getAppParameter', 'settings/github-user-name') + const email = await plugin.call('config', 'getAppParameter', 'settings/github-email') + if (!username || !email) { + plugin.call('notification', 'toast', 'Please set your github username and email in the settings') + return false; + } else { + return { + username, + email + }; + } +} + +export const commit = async (message: string = "") => { + + try { + const credentials = await settingsWarning() + if (!credentials) { + dispatch(setLoading(false)) + return + } + + const sha = await plugin.call('dgitApi', 'commit', { + author: { + name: credentials.username, + email: credentials.email, + }, + message: message, + }); + + sendToGitLog({ + type: 'success', + message: `Commited: ${sha}` + }) + + } catch (err) { + plugin.call('notification', 'toast', `${err}`) + } + +} + +export const addall = async (files: fileStatusResult[]) => { + try { + console.log('addall', files.map(f => removeSlash(f.filename))) + const filesToAdd = files.map(f => removeSlash(f.filename)) + try { + add({ filepath: filesToAdd }) + } catch (e) { } + sendToGitLog({ + type: 'success', + message: `Added all files to git` + }) + + } catch (e) { + plugin.call('notification', 'toast', `${e}`) + } +} + +export const add = async (filepath: addInput) => { + try { + await plugin.call('dgitApi', 'add', filepath); + sendToGitLog({ + type: 'success', + message: `Added to git` + }) + } catch (e) { + plugin.call('notification', 'toast', `${e}`) + } + +} + +const getLastCommmit = async () => { + try { + let currentcommitoid = ""; + currentcommitoid = await getCommitFromRef("HEAD"); + return currentcommitoid; + } catch (e) { + return false; + } +} + +export const rm = async (args: rmInput) => { + await plugin.call('dgitApi', 'rm', { + filepath: removeSlash(args.filepath), + }); + sendToGitLog({ + type: 'success', + message: `Removed from git` + }) +} + +export const checkoutfile = async (filename: string) => { + const oid = await getLastCommmit(); + if (oid) + try { + const commitOid = await plugin.call('dgitApi', 'resolveref', { + ref: oid, + }); + const { blob } = await plugin.call('dgitApi', 'readblob', { + oid: commitOid, + filepath: removeSlash(filename), + }); + const original = Buffer.from(blob).toString("utf8"); + //(original, filename); + await disableCallBacks(); + await plugin.call( + "fileManager", + "setFile", + removeSlash(filename), + original + ); + await enableCallBacks(); + } catch (e) { + plugin.call('notification', 'toast', `No such file`) + } +} + +export const checkout = async (cmd: checkoutInput) => { + console.log(cmd) + await disableCallBacks(); + await plugin.call('fileManager', 'closeAllFiles') + try { + await plugin.call('dgitApi', 'checkout', cmd) + gitlog(); + } catch (e) { + plugin.call('notification', 'toast', `${e}`) + } + await enableCallBacks(); +} + +export const clone = async (input: cloneInputType) => { + + dispatch(setLoading(true)) + try { + await disableCallBacks() + // get last part of url + const urlParts = input.url.split("/"); + const lastPart = urlParts[urlParts.length - 1]; + const repoName = lastPart.split(".")[0]; + // add timestamp to repo name + const timestamp = new Date().getTime(); + const repoNameWithTimestamp = `${repoName}-${timestamp}`; + //const token = await tokenWarning(); + const token = await plugin.call('config' as any, 'getAppParameter' as any, 'settings/gist-access-token') + + await plugin.call('dgitApi', 'clone', { ...input, workspaceName: repoNameWithTimestamp }); + await enableCallBacks() + + sendToGitLog({ + type: 'success', + message: `Cloned ${input.url} to ${repoNameWithTimestamp}` + }) + //} + } catch (e: any) { + await parseError(e) + } + dispatch(setLoading(false)) +} + +export const fetch = async (input: fetchInputType) => { + dispatch(setLoading(true)) + await disableCallBacks() + try { + await plugin.call('dgitApi', 'fetch', input); + if (!input.quiet) { + await gitlog() + await getBranches() + } + } catch (e: any) { + console.log(e) + await parseError(e) + } + dispatch(setLoading(false)) + await enableCallBacks() +} + +export const pull = async (input: pullInputType) => { + dispatch(setLoading(true)) + await disableCallBacks() + try { + await plugin.call('dgitApi', 'pull', input) + await gitlog() + } catch (e: any) { + await parseError(e) + } + dispatch(setLoading(false)) + await enableCallBacks() +} + +export const push = async (input: pushInputType) => { + dispatch(setLoading(true)) + await disableCallBacks() + try { + await plugin.call('dgitApi', 'push', input) + } catch (e: any) { + await parseError(e) + } + dispatch(setLoading(false)) + await enableCallBacks() +} + +const tokenWarning = async () => { + const token = await plugin.call('config' as any, 'getAppParameter' as any, 'settings/gist-access-token') + if (!token) { + return false; + } else { + return token; + } +} + +const parseError = async (e: any) => { + console.trace(e) + // if message conttains 401 Unauthorized, show token warning + if (e.message.includes('401')) { + const result = await plugin.call('notification', 'modal' as any, { + title: 'The GitHub token may be missing or invalid', + message: 'Please check the GitHub token and try again. Error: 401 Unauthorized', + okLabel: 'Go to settings', + cancelLabel: 'Close', + type: ModalTypes.confirm + }) + console.log(result) + } + // if message contains 404 Not Found, show repo not found + else if (e.message.includes('404')) { + await plugin.call('notification', 'modal' as any, { + title: 'Repository not found', + message: 'Please check the URL and try again.', + okLabel: 'Go to settings', + cancelLabel: 'Close', + type: ModalTypes.confirm + }) + } + // if message contains 403 Forbidden + else if (e.message.includes('403')) { + await plugin.call('notification', 'modal' as any, { + title: 'The GitHub token may be missing or invalid', + message: 'Please check the GitHub token and try again. Error: 403 Forbidden', + okLabel: 'Go to settings', + cancelLabel: 'Close', + type: ModalTypes.confirm + }) + } else if (e.toString().includes('NotFoundError') && !e.toString().includes('fetch')) { + await plugin.call('notification', 'modal', { + title: 'Remote branch not found', + message: 'The branch you are trying to fetch does not exist on the remote. If you have forked this branch from another branch, you may need to fetch the original branch first or publish this branch on the remote.', + okLabel: 'OK', + type: ModalTypes.alert + }) + } else { + await plugin.call('notification', 'alert' as any, { + title: 'Error', + message: e.message + }) + } +} + +export const repositories = async () => { + try { + const token = await tokenWarning(); + if (token) { + let repos = await plugin.call('dgitApi', 'repositories', { token, per_page: 100 }) + dispatch(setRepos(repos)) + let page = 2 + let hasMoreData = true + const per_page = 100 + while (hasMoreData) { + const pagedResponse = await plugin.call('dgitApi', 'repositories', { token, page: page, per_page: per_page }) + if (pagedResponse.length < per_page) { + hasMoreData = false + } + repos = [...repos, ...pagedResponse] + dispatch(setRepos(repos)) + page++ + } + + } else { + plugin.call('notification', 'alert', { + title: 'Error getting repositories', + message: `Please check your GitHub token in the GitHub settings... cannot connect to GitHub` + }) + dispatch(setRepos([])) + } + } catch (e) { + console.log(e) + plugin.call('notification', 'alert', { + title: 'Error getting repositories', + message: `${e.message}: Please check your GitHub token in the GitHub settings.` + }) + dispatch(setRepos([])) + } +} + +export const remoteBranches = async (owner: string, repo: string) => { + try { + const token = await tokenWarning(); + if (token) { + let branches = await plugin.call('dgitApi' as any, 'remotebranches', { token, owner, repo, per_page: 100 }); + dispatch(setRemoteBranches(branches)) + let page = 2 + let hasMoreData = true + const per_page = 100 + while (hasMoreData) { + const pagedResponse = await plugin.call('dgitApi' as any, 'remotebranches', { token, owner, repo, page: page, per_page: per_page }) + if (pagedResponse.length < per_page) { + hasMoreData = false + } + branches = [...branches, ...pagedResponse] + dispatch(setRemoteBranches(branches)) + page++ + } + } else { + plugin.call('notification', 'alert', { + title: 'Error getting branches', + message: `Please check your GitHub token in the GitHub settings. It needs to have access to the branches.` + }) + dispatch(setRemoteBranches([])) + } + } catch (e) { + console.log(e) + plugin.call('notification', 'alert', { + title: 'Error', + message: e.message + }) + dispatch(setRemoteBranches([])) + } +} + +export const remoteCommits = async (url: string, branch: string, length: number) => { + const urlParts = url.split("/"); + + console.log(urlParts, 'urlParts') + // check if it's github + if (!urlParts[urlParts.length - 3].includes('github')) { + return + } + + const owner = urlParts[urlParts.length - 2]; + const repo = urlParts[urlParts.length - 1].split(".")[0]; + + try { + const token = await tokenWarning(); + if (token) { + console.log(token, owner, repo, branch, length) + const commits = await plugin.call('dgitApi' as any, 'remotecommits', { token, owner, repo, branch, length }); + console.log(commits, 'remote commits') + } else { + sendToGitLog({ + type: 'error', + message: `Please check your GitHub token in the GitHub settings.` + }) + } + } catch (e) { + console.log(e) + plugin.call('notification', 'alert', { + title: 'Error', + message: e.message + }) + } +} + +export const saveGitHubCredentials = async (credentials: { username: string, email: string, token: string }) => { + console.log('saveGitHubCredentials', credentials) + try { + const storedEmail = await plugin.call('config', 'getAppParameter', 'settings/github-email') + const storedUsername = await plugin.call('config', 'getAppParameter', 'settings/github-user-name') + const storedToken = await plugin.call('config', 'getAppParameter', 'settings/gist-access-token') + + if (storedUsername !== credentials.username) await plugin.call('config', 'setAppParameter', 'settings/github-user-name', credentials.username) + if (storedEmail !== credentials.email) await plugin.call('config', 'setAppParameter', 'settings/github-email', credentials.email) + if (storedToken !== credentials.token) await plugin.call('config', 'setAppParameter', 'settings/gist-access-token', credentials.token) + + } catch (e) { + console.log(e) + } +} + +export const getGitHubCredentialsFromLocalStorage = async () => { + if (!plugin) return + try { + const username = await plugin.call('config', 'getAppParameter', 'settings/github-user-name') + const email = await plugin.call('config', 'getAppParameter', 'settings/github-email') + const token = await plugin.call('config', 'getAppParameter', 'settings/gist-access-token') + return { + username, + email, + token + } + } catch (e) { + console.log(e) + } +} + +export const loadGitHubUserFromToken = async () => { + if (!plugin) return + try { + const token = await tokenWarning(); + if (token) { + const data: { + user: GitHubUser, + ratelimit: RateLimit + scopes: string[] + emails: userEmails + } = await plugin.call('dgitApi' as any, 'getGitHubUser', { token }); + + console.log('GET USER"', data) + if (data && data.emails && data.user && data.user.login) { + console.log('SET USER"', data) + const primaryEmail = data.emails.find(email => email.primary) + + const storedEmail = await plugin.call('config', 'getAppParameter', 'settings/github-email') + if (primaryEmail && storedEmail !== primaryEmail.email) await plugin.call('config', 'setAppParameter', 'settings/github-email', primaryEmail.email) + const storedUsername = await plugin.call('config', 'getAppParameter', 'settings/github-user-name') + if (data.user && data.user.login && (storedUsername !== data.user.login)) await plugin.call('config', 'setAppParameter', 'settings/github-user-name', data.user.login) + + dispatch(setGitHubUser(data.user)) + dispatch(setRateLimit(data.ratelimit)) + dispatch(setScopes(data.scopes)) + dispatch(setUserEmails(data.emails)) + + } + } else { + const credentials = await getGitHubCredentialsFromLocalStorage() + if (credentials) { + //dispatch(setGitHubUser({ login: credentials.username })) + //dispatch(setUserEmails([{ email: credentials.email, primary: true, visibility: 'public', verified: true }])) + } + dispatch(setGitHubUser(null)) + } + } catch (e) { + console.log(e) + } +} + +export const statusMatrix = async (filepaths: string[]) => { + const matrix = await plugin.call('dgitApi', 'status', { ref: "HEAD", filepaths: filepaths || ['.']}); + const result = (matrix || []).map((x) => { + return { + filename: `/${x.shift()}`, + status: x, + statusNames: [] + }; + }); + + return result; +} + +export const resolveRef = async (ref: string) => { + const oid = await plugin.call('dgitApi', "resolveref", { + ref, + }); + return oid; +} + +export const diff = async (commitChange: commitChange) => { + + if (!commitChange.hashModified) { + const newcontent = await plugin.call( + "fileManager", + "readFile",// + removeSlash(commitChange.path) + ); + commitChange.modified = newcontent; + commitChange.readonly = false; + + } else { + + try { + const modifiedContentReadBlobResult: ReadBlobResult = await plugin.call('dgitApi', "readblob", { + oid: commitChange.hashModified, + filepath: removeSlash(commitChange.path), + }); + + const modifiedContent = Buffer.from(modifiedContentReadBlobResult.blob).toString("utf8"); + console.log(modifiedContent) + commitChange.modified = modifiedContent; + commitChange.readonly = true; + } catch (e) { + commitChange.modified = ""; + } + } + + try { + const originalContentReadBlobResult: ReadBlobResult = await plugin.call('dgitApi', "readblob", { + oid: commitChange.hashOriginal, + filepath: removeSlash(commitChange.path), + }); + + const originalContent = Buffer.from(originalContentReadBlobResult.blob).toString("utf8"); + console.log(originalContent) + commitChange.original = originalContent; + } catch (e) { + commitChange.original = ""; + } + +} + +export const getCommitChanges = async (oid1: string, oid2: string, branch?: branch, remote?: remote) => { + console.log(oid1, oid2, branch, remote) + + try { + let log + try { + // check if oid2 exists + log = await plugin.call('dgitApi', 'log', { + ref: branch ? branch.name : 'HEAD', + }) + console.log(log, 'log') + } catch (e) { + console.log(e, 'log error') + } + if (log) { + const foundCommit = log.find((commit: ReadCommitResult) => commit.oid === oid2) + if (!foundCommit && remote) { + console.log('getCommitChanges fetching remote') + //await fetch(remote ? remote.name : null, branch ? branch.name : null, null, 5, true, true) + await fetch({ + remote: remote, + singleBranch: true, + quiet: true, + relative: true, + depth: 5, + ref: branch, + remoteRef: null + }) + } + } + const result: commitChange[] = await plugin.call('dgitApi', 'getCommitChanges', oid1, oid2) + dispatch(setCommitChanges(result)) + return result + } catch (e) { + console.log(e) + return false + } +} + +async function getRepoDetails(url: string) { + // Extract the owner and repo name from the URL + const pathParts = new URL(url).pathname.split('/').filter(part => part); + if (pathParts.length < 2) { + throw new Error("URL must be in the format 'https://github.com/[owner]/[repository]'"); + } + const owner = pathParts[0]; + const repo = pathParts[1]; + return { owner, repo }; +} + +export const fetchBranch = async (branch: branch, page: number) => { + if (!branch.remote || !branch.remote.url) return + const token = await tokenWarning(); + console.log('fetch', branch) + if (page == 1) { + dispatch(resetRemoteBranchCommits({ branch })) + } + const { owner, repo } = await getRepoDetails(branch.remote.url); + const rc = await plugin.call('dgitApi', 'remotecommits', { token, owner: owner, repo: repo, branch: branch.name, length, page }); + console.log(rc, 'remote commits from octokit') + dispatch(setRemoteBranchCommits({ branch, commits: rc })) + return +} + +export const getBranchDifferences = async (branch: branch, remote: remote, state: gitState) => { + if (!remote && state) { + if (state.defaultRemote) { + remote = state.defaultRemote + } else { + remote = state.remotes.find((remote: remote) => remote.name === 'origin') + } + if (!remote && state.remotes[0]) { + remote = state.remotes[0] + } + } + if (!remote) return + try { + console.log('compare', branch, remote) + const branchDifference: branchDifference = await plugin.call('dgitApi', 'compareBranches', { + branch, + remote + }) + + dispatch(setBranchDifferences( + { + branch, + remote, + branchDifference: branchDifference + })) + } catch (e) { + console.log(e) + } +} + +export const getBranchCommits = async (branch: branch, page: number) => { + dispatch(setLoading(true)) + await disableCallBacks() + try { + console.log(branch) + if (!branch.remote) { + const commits: ReadCommitResult[] = await plugin.call('dgitApi', 'log', { + ref: branch.name, + }) + console.log(commits) + dispatch(setLocalBranchCommits({ branch, commits })) + } else { + await fetchBranch(branch, page) + } + } catch (e) { + console.trace(e) + await fetchBranch(branch, page) + } + dispatch(setLoading(false)) + await enableCallBacks() +} + +export const setDefaultRemote = async (remote: remote) => { + dispatch(setRemoteAsDefault(remote)) +} + +export const addRemote = async (remote: remote) => { + try { + await plugin.call('dgitApi', 'addremote', remote) + await getRemotes() + } catch (e) { + console.log(e) + } +} + +export const removeRemote = async (remote: remote) => { + try { + await plugin.call('dgitApi', 'delremote', remote) + await getRemotes() + } catch (e) { + console.log(e) + } +} + +export const sendToGitLog = async (message: gitLog) => { + dispatch(setLog(message)) +} + +export const clearGitLog = async () => { + dispatch(clearLog()) +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/lib/listeners.ts b/libs/remix-ui/git/src/lib/listeners.ts new file mode 100644 index 0000000000..b8f07516d8 --- /dev/null +++ b/libs/remix-ui/git/src/lib/listeners.ts @@ -0,0 +1,195 @@ + +import React from "react"; +import { setCanUseApp, setLoading, setRepoName, setGItHubToken, setLog, setGitHubUser, setUserEmails } from "../state/gitpayload"; +import { gitActionDispatch } from "../types"; +import { Plugin } from "@remixproject/engine"; +import { getBranches, getFileStatusMatrix, loadGitHubUserFromToken, getRemotes, gitlog, setPlugin } from "./gitactions"; +import { Profile } from "@remixproject/plugin-utils"; +import { CustomRemixApi } from "@remix-api"; +import { statusChanged } from "./pluginActions"; + +let plugin: Plugin, gitDispatch: React.Dispatch, loaderDispatch: React.Dispatch, loadFileQueue: AsyncDebouncedQueue +let callBackEnabled: boolean = false + +type AsyncCallback = () => Promise; + +class AsyncDebouncedQueue { + private queues: Map; + + constructor(private delay: number = 300) { + this.queues = new Map(); + } + + enqueue(callback: AsyncCallback, customDelay?:number): void { + if (this.queues.has(callback)) { + clearTimeout(this.queues.get(callback)!.timer); + } + + const timer = setTimeout(async () => { + await callback(); + this.queues.delete(callback); + }, customDelay || this.delay); + + this.queues.set(callback, { timer, lastCall: Date.now() }); + } +} + +export const setCallBacks = (viewPlugin: Plugin, gitDispatcher: React.Dispatch, loaderDispatcher: React.Dispatch) => { + plugin = viewPlugin + gitDispatch = gitDispatcher + loaderDispatch = loaderDispatcher + loadFileQueue = new AsyncDebouncedQueue() + + setPlugin(viewPlugin, gitDispatcher) + + plugin.on("fileManager", "fileSaved", async (file: string) => { + console.log(file) + loadFileQueue.enqueue(async () => { + loadFiles() + }) + }); + + plugin.on('dgitApi', 'checkout', async () => { + //await synTimerStart(); + }) + plugin.on('dgitApi', 'branch', async () => { + //await synTimerStart(); + }) + + plugin.on("fileManager", "fileAdded", async (e) => { + loadFileQueue.enqueue(async () => { + loadFiles() + }) + }); + + plugin.on("fileManager", "fileRemoved", async (e) => { + //await synTimerStart(); + }); + + plugin.on("fileManager", "currentFileChanged", async (e) => { + console.log('current file change', e) + //await synTimerStart(); + }); + + plugin.on("fileManager", "fileRenamed", async (oldfile, newfile) => { + //await synTimerStart(); + }); + + plugin.on("filePanel", "setWorkspace", async (x: any) => { + loadFileQueue.enqueue(async () => { + loadFiles() + }) + loadFileQueue.enqueue(async () => { + gitlog() + }) + loadFileQueue.enqueue(async () => { + getBranches() + }) + loadFileQueue.enqueue(async () => { + getRemotes() + }) + }); + + plugin.on("filePanel", "deleteWorkspace" as any, async (x: any) => { + //await synTimerStart(); + }); + + plugin.on("filePanel", "renameWorkspace" as any, async (x: any) => { + //await synTimerStart(); + }); + + plugin.on('dgitApi', 'checkout', async () => { + + }) + plugin.on('dgitApi', 'init', async () => { + loadFileQueue.enqueue(async () => { + loadFiles() + }, 10) + }) + plugin.on('dgitApi', 'add', async () => { + loadFileQueue.enqueue(async () => { + loadFiles() + }, 10) + }) + plugin.on('dgitApi', 'rm', async () => { + loadFileQueue.enqueue(async () => { + loadFiles() + }, 10) + }) + plugin.on('dgitApi', 'commit', async () => { + loadFileQueue.enqueue(async () => { + gitlog() + }, 10) + gitDispatch(setLog({ + message: 'Committed changes...', + type: 'success' + })) + }) + plugin.on('dgitApi', 'branch', async () => { + gitDispatch(setLog({ + message: "Created Branch", + type: "success" + })) + }) + plugin.on('dgitApi', 'clone', async () => { + gitDispatch(setLog({ + message: "Cloned Repository", + type: "success" + })) + loadFileQueue.enqueue(async () => { + loadFiles() + }) + }) + plugin.on('manager', 'pluginActivated', async (p: Profile) => { + if (p.name === 'dgitApi') { + loadGitHubUserFromToken(); + plugin.off('manager', 'pluginActivated'); + } + }) + + plugin.on('config', 'configChanged', async () => { + console.log('config changed') + await getGitConfig() + }) + plugin.on('settings', 'configChanged', async () => { + console.log('settings changed') + await getGitConfig() + }) + + callBackEnabled = true; +} + +export const getGitConfig = async () => { + const username = await plugin.call('settings', 'get', 'settings/github-user-name') + const email = await plugin.call('settings', 'get', 'settings/github-email') + const token = await plugin.call('settings', 'get', 'settings/gist-access-token') + const config = { username, email, token } + + loadGitHubUserFromToken() + return + +} + +export const loadFiles = async (filepaths: string[] = null) => { + try { + const branch = await plugin.call('dgitApi', "currentbranch") + console.log('load files', branch) + if (branch) { + await getFileStatusMatrix(filepaths); + } else { + await plugin.call('fileDecorator', 'clearFileDecorators') + statusChanged(0) + } + } catch (e) { + // TODO: handle error + console.error(e); + } +} + +export const disableCallBacks = async () => { + callBackEnabled = false; +} +export const enableCallBacks = async () => { + callBackEnabled = true; +} + diff --git a/libs/remix-ui/git/src/lib/pluginActions.ts b/libs/remix-ui/git/src/lib/pluginActions.ts new file mode 100644 index 0000000000..a76194fbb5 --- /dev/null +++ b/libs/remix-ui/git/src/lib/pluginActions.ts @@ -0,0 +1,101 @@ + +import { commitChange, fileStatusResult, gitActionDispatch, gitState } from "../types" +import { fileDecoration, fileDecorationType } from "@remix-ui/file-decorators" +import { removeSlash } from "../utils" +import { getFilesByStatus } from "./fileHelpers" +import { CustomRemixApi } from "@remix-api"; +import { Plugin } from "@remixproject/engine"; + +let plugin: Plugin, gitDispatch: React.Dispatch, loaderDispatch: React.Dispatch + +export const setPlugin = (p: Plugin, gitDispatcher: React.Dispatch, loaderDispatcher: React.Dispatch) => { + plugin = p + gitDispatch = gitDispatcher + loaderDispatch = loaderDispatcher +} + +export const statusChanged = (badges: number) => { + if (!plugin) return + plugin.emit('statusChanged', { + key: badges === 0 ? 'none' : badges, + type: badges === 0 ? '' : 'success', + title: 'Git changes' + }) +} + +export const openFile = async (path: string) => { + if (!plugin) return + await plugin.call('fileManager', 'open', path) +} + +export const openDiff = async (change: commitChange) => { + console.log('openDiff', change) + if (!plugin) return + plugin.call('fileManager', 'diff', change) +} + +export const saveToken = async (token: string) => { + if (!plugin) return + await plugin.call('config', 'setAppParameter', 'settings/gist-access-token', token) +} + +export const setFileDecorators = async (files: fileStatusResult[]) => { + + if (!plugin) return + const modified = getFilesByStatus('modified', files) + const untracked = getFilesByStatus('untracked', files) + const unmodified = getFilesByStatus('unmodified', files) + + await setModifiedDecorator(modified) + await setUntrackedDecorator(untracked) + unmodified.forEach((file) => { + clearFileDecorator(removeSlash(file.filename)) + }) +} + +export const setModifiedDecorator = async (files: fileStatusResult[]) => { + const decorators: fileDecoration[] = [] + for (const file of files) { + const decorator: fileDecoration = { + path: removeSlash(file.filename), + isDirectory: false, + fileStateType: fileDecorationType.Custom, + fileStateLabelClass: 'text-warning', + fileStateIconClass: 'text-warning', + fileStateIcon: '', + text: 'M', + owner: 'git', + bubble: true, + comment: 'Modified' + } + decorators.push(decorator) + } + + await plugin.call('fileDecorator', 'setFileDecorators', decorators) +} + +export const setUntrackedDecorator = async (files: fileStatusResult[]) => { + const decorators: fileDecoration[] = [] + for (const file of files) { + const decorator: fileDecoration = { + path: removeSlash(file.filename), + isDirectory: false, + fileStateType: fileDecorationType.Custom, + fileStateLabelClass: 'text-success', + fileStateIconClass: 'text-success', + fileStateIcon: '', + text: 'U', + owner: 'git', + bubble: true, + comment: 'Untracked' + } + decorators.push(decorator) + } + + await plugin.call('fileDecorator', 'setFileDecorators', decorators) +} + +export const clearFileDecorator = async(path: string) => { + await plugin.call('fileDecorator', 'clearFileDecorators', path) +} + diff --git a/libs/remix-ui/git/src/state/actions.ts b/libs/remix-ui/git/src/state/actions.ts new file mode 100644 index 0000000000..99e7fed793 --- /dev/null +++ b/libs/remix-ui/git/src/state/actions.ts @@ -0,0 +1,51 @@ +import { ReadCommitResult } from "isomorphic-git" +import { branch, branchDifference, commitChange, fileStatusResult, GitHubUser, gitLog, pagedCommits, remote, remoteBranch, repository, userEmails } from "../types" + +export interface ActionPayloadTypes { + FILE_STATUS: fileStatusResult[], + FILE_STATUS_MERGE: fileStatusResult[] + SET_COMMITS: ReadCommitResult[] + SET_BRANCHES: branch[] + SET_CURRENT_BRANCH: branch + SET_CAN_USE_APP: boolean + SET_REPO_NAME: string + SET_LOADING: boolean + SET_REPOS: repository[] + SET_REMOTE_BRANCHES: remoteBranch[] + SET_CAN_COMMIT: boolean + SET_REMOTES: remote[] + SET_UPSTREAM: remote + SET_COMMIT_CHANGES: commitChange[] + RESET_REMOTE_BRANCH_COMMITS: { + branch: branch + pagedCommits: pagedCommits[] + } + SET_REMOTE_BRANCH_COMMITS: { + branch: branch + commits: pagedCommits[] + } + SET_LOCAL_BRANCH_COMMITS: { + branch: branch + commits: ReadCommitResult[] + } + SET_BRANCH_DIFFERENCES: { + branch: branch + remote: remote + branchDifference: branchDifference + } + SET_GITHUB_USER: GitHubUser + SET_RATE_LIMIT: any + SET_GITHUB_ACCESS_TOKEN: string + SET_SCOPES: string[] + SET_DEFAULT_REMOTE: remote + SET_LOG: gitLog + CLEAR_LOG: void + SET_USER_EMAILS: userEmails +} + +export interface Action { + type: T, + payload: ActionPayloadTypes[T] +} + +export type Actions = {[A in keyof ActionPayloadTypes]: Action}[keyof ActionPayloadTypes] \ No newline at end of file diff --git a/libs/remix-ui/git/src/state/context.tsx b/libs/remix-ui/git/src/state/context.tsx new file mode 100644 index 0000000000..a1629fb0c3 --- /dev/null +++ b/libs/remix-ui/git/src/state/context.tsx @@ -0,0 +1,57 @@ +import { ReadCommitResult } from "isomorphic-git" +import React from "react" +import { addInput, branch, checkoutInput, cloneInputType, commitChange, fetchInputType, fileStatusResult, gitLog, gitState, pullInputType, pushInputType, remote, rmInput } from "../types" + +export interface gitActions { + removeRemote(remote: remote): void + clone(input: cloneInputType): Promise + add(input: addInput): Promise + rm(input: rmInput): Promise + commit(message: string): Promise + addall(files: fileStatusResult[]): Promise + push(input: pushInputType): Promise + pull(input: pullInputType): Promise + fetch(input: fetchInputType): Promise + repositories(): Promise + checkoutfile(file: string): Promise + checkout(input: checkoutInput): Promise + createBranch(branch: string): Promise + remoteBranches(owner: string, repo: string): Promise + getCommitChanges(oid1: string, oid2: string, branch?: branch, remote?: remote): Promise + getBranchCommits(branch: branch, page: number): Promise + getBranchDifferences(branch: branch, remote?: remote, state?: gitState): Promise + loadGitHubUserFromToken(): Promise + diff(commitChange: commitChange): Promise + resolveRef(ref: string): Promise + setUpstreamRemote(upstream: remote): Promise + getBranches: () => Promise + getRemotes: () => Promise + setDefaultRemote: (remote: remote) => Promise + addRemote: (remote: remote) => Promise + sendToGitLog: (message: gitLog) => Promise + clearGitLog: () => Promise + getFileStatusMatrix(filespaths:[]): Promise + init(): Promise +} + +export const gitActionsContext = React.createContext(null) + +export interface pluginActions { + statusChanged(data: any): void + loadFiles(): void + openFile(path: string): Promise + openDiff(change: commitChange): Promise + saveToken(token: string): Promise + saveGitHubCredentials({ + username, + email, + token + }): Promise + getGitHubCredentialsFromLocalStorage(): Promise<{ + username: string + email: string + token: string + }> +} + +export const pluginActionsContext = React.createContext(null) \ No newline at end of file diff --git a/libs/remix-ui/git/src/state/gitpayload.ts b/libs/remix-ui/git/src/state/gitpayload.ts new file mode 100644 index 0000000000..d66264a19e --- /dev/null +++ b/libs/remix-ui/git/src/state/gitpayload.ts @@ -0,0 +1,220 @@ +import { ReadCommitResult } from "isomorphic-git" +import { GitHubUser, branch, commitChange, fileStatusResult, remote, pagedCommits, branchDifference, gitLog, repository, userEmails } from "../types" +import { Endpoints } from "@octokit/types" + +export const fileStatus = (files: fileStatusResult[]) => { + return { + type: 'FILE_STATUS', + payload: files + } +} + +export const fileStatusMerge = (files: fileStatusResult[]) => { + return { + type: 'FILE_STATUS_MERGE', + payload: files + } +} + +export const setCommits = (commits: ReadCommitResult[]) => { + return { + type: 'SET_COMMITS', + payload: commits + } +} + +export const setBranches = (branches: any[]) => { + return { + type: 'SET_BRANCHES', + payload: branches + } +} + +export const setRepos = (repos: repository[]) => { + return { + type: 'SET_REPOS', + payload: repos + } +} + +export const setRemoteBranches = (branches: any[]) => { + return { + type: 'SET_REMOTE_BRANCHES', + payload: branches + } +} + +export const setGitHubUser = (user: GitHubUser) => { + console.log('set user', user) + return { + type: 'SET_GITHUB_USER', + payload: user + } +} + +export const setUserEmails = (emails: userEmails) => { + return { + type: 'SET_USER_EMAILS', + payload: emails + } +} + +export const setRateLimit = (rateLimit: any) => { + return { + type: 'SET_RATE_LIMIT', + payload: rateLimit + } +} + +export const setScopes = (scopes: string[]) => { + return { + type: 'SET_SCOPES', + payload: scopes + } +} + +export const setGitHubAccessToken = (token: string) => { + return { + type: 'SET_GITHUB_ACCESS_TOKEN', + payload: token + } +} + +export const setLoading = (loading: boolean) => { + return { + type: 'SET_LOADING', + payload: loading + } +} + +export const setCanUseApp = (canUseApp: boolean) => { + return { + type: 'SET_CAN_USE_APP', + payload: canUseApp + } +} + +export const setRepoName = (reponame: string) => { + return { + type: 'SET_REPO_NAME', + payload: reponame + } +} + +export const setCurrentBranch = (currentBranch: branch) => { + return { + type: 'SET_CURRENT_BRANCH', + payload: currentBranch + } +} + +export const setCanCommit = (canCommit: boolean) => { + return { + type: 'SET_CAN_COMMIT', + payload: canCommit + } +} + +export const setRemotes = (remotes: remote[]) => { + return { + type: 'SET_REMOTES', + payload: remotes + } +} + +export const setUpstream = (upstream: remote) => { + return { + type: 'SET_UPSTREAM', + payload: upstream + } +} + +export const setCommitChanges = (commitChanges: commitChange[]) => { + return { + type: 'SET_COMMIT_CHANGES', + payload: commitChanges + } +} + +export const setRemoteBranchCommits = ({ branch, commits }:{ + branch: branch, + commits: pagedCommits[] +}):{ + type: string; + payload: { branch: branch; commits: pagedCommits[] }; +} => { + return { + type: 'SET_REMOTE_BRANCH_COMMITS', + payload: { branch, commits } + } +} + +export const resetRemoteBranchCommits = ({ branch }:{ + branch: branch, +}):{ + type: string; + payload: { branch: branch }; +} => { + return { + type: 'RESET_REMOTE_BRANCH_COMMITS', + payload: { branch } + } +} + +export const setLocalBranchCommits = ({ + branch, + commits +}: { + branch: branch; + commits: ReadCommitResult[]; +}): { + type: string; + payload: { branch: branch; commits: ReadCommitResult[] }; +} => { + return { + type: 'SET_LOCAL_BRANCH_COMMITS', + payload: { branch, commits } + }; +}; + +export const setBranchDifferences = ({ + branch, + remote, + branchDifference +}:{ + branch: branch; + remote: remote; + branchDifference: branchDifference; +}) => { + return { + type: 'SET_BRANCH_DIFFERENCES', + payload: { branch, remote, branchDifference } + } +} + +export const setGItHubToken = (token: string) => { + return { + type: 'SET_GITHUB_ACCESS_TOKEN', + payload: token + } +} + +export const setRemoteAsDefault = (remote: remote) => { + return { + type: 'SET_DEFAULT_REMOTE', + payload: remote + } +} + +export const setLog = (message: gitLog) => { + return { + type: 'SET_LOG', + payload: message + } +} + +export const clearLog = () => { + return { + type: 'CLEAR_LOG' + } +} diff --git a/libs/remix-ui/git/src/state/gitreducer.tsx b/libs/remix-ui/git/src/state/gitreducer.tsx new file mode 100644 index 0000000000..3d55d6818c --- /dev/null +++ b/libs/remix-ui/git/src/state/gitreducer.tsx @@ -0,0 +1,210 @@ +import { ReadCommitResult } from "isomorphic-git" +import { allChangedButNotStagedFiles, getFilesByStatus, getFilesWithNotModifiedStatus } from "../lib/fileHelpers" +import { branch, commitChange, defaultGitState, fileStatusResult, gitState, setRemoteBranchCommitsAction, setLocalBranchCommitsAction, setBranchDifferencesAction, setDefaultRemoteAction, setRemotesAction, setUpstreamAction } from "../types" +import { Actions } from "./actions" + +export const gitReducer = (state: gitState = defaultGitState, action: Actions): gitState => { + ///console.log(action, state) + switch (action.type) { + + case 'FILE_STATUS': + return { + ...state, + fileStatusResult: action.payload, + staged: getFilesByStatus("staged", action.payload), + modified: getFilesByStatus("modified", action.payload), + untracked: getFilesByStatus("untracked", action.payload), + deleted: getFilesByStatus("deleted", action.payload), + allchangesnotstaged: allChangedButNotStagedFiles(action.payload) + } + + case 'FILE_STATUS_MERGE': + action.payload.map((fileStatusResult: fileStatusResult) => { + const file = state.fileStatusResult.find(stateFile => { + return stateFile.filename === fileStatusResult.filename + }) + if (file) { + file.status = fileStatusResult.status + file.statusNames = fileStatusResult.statusNames + } + }) + + return { + ...state, + staged: getFilesByStatus("staged", state.fileStatusResult), + modified: getFilesByStatus("modified", state.fileStatusResult), + untracked: getFilesByStatus("untracked", state.fileStatusResult), + deleted: getFilesByStatus("deleted", state.fileStatusResult), + allchangesnotstaged: allChangedButNotStagedFiles(state.fileStatusResult) + } + + case 'SET_COMMITS': + return { + ...state, + commits: action.payload, + localCommitCount: action.payload.length + } + + case 'SET_BRANCHES': + return { + ...state, + branches: action.payload + } + + case 'SET_CURRENT_BRANCH': + return { + ...state, + currentBranch: action.payload + } + + case 'SET_CAN_USE_APP': + return { + ...state, + canUseApp: action.payload + } + case 'SET_REPO_NAME': + return { + ...state, + reponame: action.payload + } + case 'SET_LOADING': + return { + ...state, + loading: action.payload + } + + case 'SET_REPOS': + return { + ...state, + repositories: action.payload + } + + case 'SET_REMOTE_BRANCHES': + return { + ...state, + remoteBranches: action.payload + } + + case 'SET_CAN_COMMIT': + return { + ...state, + canCommit: action.payload + } + + case 'SET_REMOTES': + return { + ...state, + remotes: action.payload + } + + case 'SET_UPSTREAM': + return { + ...state, + upstream: action.payload + } + + case 'SET_COMMIT_CHANGES': + + action.payload.forEach((change: commitChange) => { + state.commitChanges.find((c) => c.hashModified === change.hashModified && c.hashOriginal === change.hashOriginal && c.path === change.path) ? null : state.commitChanges.push(change) + }) + + return { + ...state, + commitChanges: [...state.commitChanges] + } + + case 'RESET_REMOTE_BRANCH_COMMITS': + if (state.remoteBranchCommits[action.payload.branch.name]) { + delete state.remoteBranchCommits[action.payload.branch.name] + } + return { + ...state, + remoteBranchCommits: { ...state.remoteBranchCommits } + } + + case 'SET_REMOTE_BRANCH_COMMITS': + if (state.remoteBranchCommits[action.payload.branch.name]) { + state.remoteBranchCommits[action.payload.branch.name].push(...action.payload.commits) + } else { + state.remoteBranchCommits[action.payload.branch.name] = action.payload.commits + } + return { + ...state, + remoteBranchCommits: { ...state.remoteBranchCommits } + } + + case 'SET_LOCAL_BRANCH_COMMITS': + + state.localBranchCommits[action.payload.branch.name] = action.payload.commits + return { + ...state, + localBranchCommits: { ...state.localBranchCommits } + } + + case 'SET_BRANCH_DIFFERENCES': + + state.branchDifferences[`${action.payload.remote.name}/${action.payload.branch.name}`] = action.payload.branchDifference + + return { + ...state, + branchDifferences: { ...state.branchDifferences } + } + + case 'SET_GITHUB_USER': + return { + ...state, + gitHubUser: action.payload + } + + case 'SET_RATE_LIMIT': + console.log("rate limit", action.payload) + return { + ...state, + rateLimit: action.payload + } + + case 'SET_GITHUB_ACCESS_TOKEN': + return { + ...state, + gitHubAccessToken: action.payload + } + + case 'SET_SCOPES': + return { + ...state, + gitHubScopes: action.payload + } + + case 'SET_USER_EMAILS': + return { + ...state, + userEmails: action.payload + } + + case 'SET_DEFAULT_REMOTE': + return { + ...state, + defaultRemote: action.payload + } + + case 'SET_LOG': + if (state.log.length > 0 && state.log[[...state.log].length - 1].message === action.payload.message) { + return { + ...state, + log: [...state.log] + } + } + return { + ...state, + log: [...state.log, action.payload] + } + + case 'CLEAR_LOG': + return { + ...state, + log: [] + } + + } +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/state/loaderReducer.ts b/libs/remix-ui/git/src/state/loaderReducer.ts new file mode 100644 index 0000000000..dccd7439de --- /dev/null +++ b/libs/remix-ui/git/src/state/loaderReducer.ts @@ -0,0 +1,11 @@ +import { defaultLoaderState, loaderState } from "../types"; + +interface Action { + type: string + payload: any +} + +export const loaderReducer = (state: loaderState = defaultLoaderState, action: Action): loaderState => { + state[action.type] = action.payload + return state +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/style/index.css b/libs/remix-ui/git/src/style/index.css new file mode 100644 index 0000000000..973889c15c --- /dev/null +++ b/libs/remix-ui/git/src/style/index.css @@ -0,0 +1,36 @@ +.nav { + cursor: pointer; +} + +.pointer { + cursor: pointer; +} + +.long-and-truncated { + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + +.commit-navigation{ + align-items: center; +} + +.commit-navigation:hover { + background-color: var(--custom-select); +} + +.commitdetailsitem { + align-items: baseline; +} + +.gitfile:hover { + background-color : var(--custom-select); +} + +hr { + background-color: var(--custom-select); +} + + diff --git a/libs/remix-ui/git/src/types/index.ts b/libs/remix-ui/git/src/types/index.ts new file mode 100644 index 0000000000..cea92b30f2 --- /dev/null +++ b/libs/remix-ui/git/src/types/index.ts @@ -0,0 +1,430 @@ +import { Endpoints } from "@octokit/types" +import { IRemixApi } from "@remixproject/plugin-api" +import { LibraryProfile, StatusEvents } from "@remixproject/plugin-utils" +import { CommitObject, ReadBlobResult, ReadCommitResult, StatusRow } from "isomorphic-git" +export type GitHubUser = Partial +export type RateLimit = Endpoints["GET /rate_limit"]["response"]["data"] +export type userEmails = Endpoints["GET /user/emails"]["response"]["data"] + +export interface IGitApi { + events: { + "checkout": () => void + "clone": () => void + "add": () => void + "rm": () => void + "commit": () => void + "branch": () => void + "init": () => void + } & StatusEvents, + methods: { + getCommitChanges(oid1: string, oid2: string): Promise + repositories(input: repositoriesInput): Promise + clone(input: cloneInputType): Promise + branches(input?: branchesInput): Promise, + remotes(): Promise, + log(cmd: { ref: string }): Promise, + remotecommits(input: remoteCommitsInputType): Promise + fetch(input: fetchInputType): Promise + pull(input: pullInputType): Promise + push(input: pushInputType): Promise + currentbranch(input?: currentBranchInput): Promise + branch(input: branchInputType): Promise + checkout(input: checkoutInput): Promise + add(input: addInput): Promise + rm(input: rmInput): Promise + resolveref(input: resolveRefInput): Promise + readblob(input: readBlobInput): Promise + commit(input: commitInput): Promise + addremote(input: remote): Promise + delremote(input: remote): Promise + status(input?: statusInput): Promise> + compareBranches(input: compareBranchesInput): Promise + init(input?: initInput): Promise + updateSubmodules: (input: updateSubmodulesInput) => Promise + } +} + +export type initInput = { + defaultBranch: string +} + +export type updateSubmodulesInput = { + dir?: string + token?: string +} + +export type remoteCommitsInputType = { + owner: string, repo: string, token: string, branch: string, length: number, page: number +} + +export type compareBranchesInput = { + branch: branch, remote: remote +} + +export type fetchInputType = { + remote: remote, + ref?: branch, + remoteRef?: branch, + depth?: number, + singleBranch?: boolean, + relative?: boolean, + quiet?: boolean +} + +export type pullInputType = { + remote: remote, ref: branch, remoteRef?: branch +} + +export type pushInputType = { + remote: remote, ref: branch, remoteRef?: branch, force?: boolean +} + +export type branchInputType = { + ref: string, + checkout?: boolean + refresh?: boolean +} + +export type currentBranchInput = { + fs: any, + dir: string +} + +export type checkoutInput = { + ref: string, + force?: boolean, + remote?: string + refresh?: boolean +} + +export type addInput = { + filepath: string | string[] +} + +export type rmInput = { + filepath: string +} + +export type resolveRefInput = { + ref: string +} + +export type readBlobInput = { + oid: string, + filepath: string +} + +export type commitInput = { + author: { + name: string, + email: string, + }, + message: string, +} + +export type branchesInput = { + fs?: any + dir?: string +} + +export interface cloneInputType { + url: string, + branch?: string, + depth?: number, + singleBranch?: boolean + workspaceName?: string + workspaceExists?: boolean + token?: string +} + +export interface repositoriesInput { token: string, page?: number, per_page?: number } + +export interface statusInput { ref: string, filepaths?: string[] } + +export const dGitProfile: LibraryProfile = { + name: 'dgitApi', + methods: ['clone', 'branches', 'remotes', 'getCommitChanges', 'log', 'remotecommits'], +} + +export interface customGitApi extends IRemixApi { + dgit: IGitApi +} + +export type gitState = { + currentBranch: branch + commits: ReadCommitResult[] + branch: string + canCommit: boolean + branches: branch[] + remotes: remote[] + defaultRemote: remote + fileStatusResult: fileStatusResult[] + canUseApp: boolean + loading: boolean + storageUsed: any + reponame: string + staged: fileStatusResult[] + untracked: fileStatusResult[] + deleted: fileStatusResult[] + modified: fileStatusResult[] + allchangesnotstaged: fileStatusResult[], + repositories: repository[] + remoteBranches: remoteBranch[] + commitChanges: commitChange[] + remoteBranchCommits: Record + localBranchCommits: Record + branchDifferences: Record + syncStatus: syncStatus, + localCommitCount: number + remoteCommitCount: number + upstream: remote + gitHubUser: GitHubUser + rateLimit: RateLimit + userEmails: userEmails + gitHubScopes: string[] + gitHubAccessToken: string + log: gitLog[] +} +export type gitLog = { + type: 'error' | 'warning' | 'info' | 'success', + message: string +} + +export type remoteBranchIdentifier = `${string}/${string}` + +export type branchDifference = { + uniqueHeadCommits: ReadCommitResult[], + uniqueRemoteCommits: ReadCommitResult[], +} + +export type pagedCommits = { + page: number, + perPage: number, + total: number, + hasNextPage: boolean, + commits: ReadCommitResult[] +} + +export type loaderState = { + branches: boolean + remotes: boolean + commits: boolean + sourcecontrol: boolean + plugin: boolean +} + +export type commitChangeTypes = { + "deleted": "D" + "modified": "M" + "added": "A", + "unknown": "?" +} + +export enum syncStatus { + "sync" = "sync", + "publishBranch" = "publishBranch", + "none" = "none", +} + +export type commitChangeType = keyof commitChangeTypes + +export type commitChange = { + type: commitChangeType + path: string, + hashModified: string, + hashOriginal: string, + original?: string, + modified?: string, + readonly?: boolean +} + +export type repository = { + name: string + html_url: string + owner: { + login: string + }, + full_name: string + default_branch: string + id: number + url: string +} + +export type branch = { + name: string + remote: remote +} + +export type remote = { + name: string + url: string +} + +export type remoteBranch = { + name: string +} + +export const defaultGitState: gitState = { + currentBranch: { name: "", remote: { name: "", url: "" } }, + commits: [], + branch: "", + canCommit: true, + branches: [], + remotes: [], + defaultRemote: null, + fileStatusResult: [], + staged: [], + untracked: [], + deleted: [], + modified: [], + allchangesnotstaged: [], + canUseApp: false, + loading: false, + storageUsed: {}, + reponame: "", + repositories: [], + remoteBranches: [], + commitChanges: [], + remoteBranchCommits: {}, + localBranchCommits: {}, + branchDifferences: {}, + syncStatus: syncStatus.none, + localCommitCount: 0, + remoteCommitCount: 0, + upstream: null, + gitHubUser: {} as GitHubUser, + rateLimit: {} as RateLimit, + userEmails: [] as userEmails, + gitHubScopes: [], + gitHubAccessToken: "", + log: [] +} + +export const defaultLoaderState: loaderState = { + branches: false, + commits: false, + sourcecontrol: false, + remotes: false, + plugin: false +} + +export type fileStatusResult = { + filename: string, + status?: fileStatus + statusNames?: string[] +} + +export type fileStatus = [string, 0 | 1, 0 | 1 | 2, 0 | 1 | 2 | 3] + +export type statusMatrixType = { matrix: string[] | undefined; status: string[] } + +export type sourceControlGroup = { + group: fileStatusResult[], + name: string +} + +export interface fileStatusAction { + type: string, + payload: fileStatusResult[] +} + +export interface setCommitsAction { + type: string, + payload: ReadCommitResult[] +} + +export interface setBranchesAction { + type: string, + payload: any[] +} + +export interface setReposAction { + type: string, + payload: any[] +} + +export interface setRemoteBranchesAction { + type: string, + payload: any[] +} + +export interface setGitHubUserAction { + type: string, + payload: any +} + +export interface setLoadingAction { + type: string, + payload: boolean +} + +export interface setCanUseAppAction { + type: string, + payload: boolean +} + +export interface setRepoNameAction { + type: string, + payload: string +} + +export interface setCurrentBranchAction { + type: string, + payload: branch +} + +export interface setRemotesAction { + type: string, + payload: remote[] +} + +export interface setUpstreamAction { + type: string, + payload: remote +} + +export interface setRemoteBranchCommitsAction { + type: string, + payload: { + branch: branch, + commits: pagedCommits[] + } +} + +export interface setLocalBranchCommitsAction { + type: string, + payload: { + branch: branch, + commits: ReadCommitResult[] + } +} + +export interface setBranchDifferencesAction { + type: string, + payload: { + branch: branch, + remote: remote, + branchDifference: branchDifference + } +} + +export interface setTokenAction { + type: string, + payload: string +} + +export interface setDefaultRemoteAction { + type: string, + payload: remote +} + +export interface setLogAction { + type: string, + payload: gitLog +} + +export interface clearLogAction { + type: string +} + +export type gitActionDispatch = clearLogAction | setLogAction | setDefaultRemoteAction | setTokenAction | setUpstreamAction | setRemoteBranchCommitsAction | setLocalBranchCommitsAction | setBranchDifferencesAction | setRemotesAction | setCurrentBranchAction | fileStatusAction | setLoadingAction | setCanUseAppAction | setRepoNameAction | setCommitsAction | setBranchesAction | setReposAction | setRemoteBranchesAction \ No newline at end of file diff --git a/libs/remix-ui/git/src/types/styles.ts b/libs/remix-ui/git/src/types/styles.ts new file mode 100644 index 0000000000..928a981dff --- /dev/null +++ b/libs/remix-ui/git/src/types/styles.ts @@ -0,0 +1,53 @@ +import { StylesConfig } from 'react-select' +export const selectStyles: StylesConfig = { + option: (baseStyles, state) => { + return { + ...baseStyles, + color: 'var(--text)', + } + }, + input(base, props) { + return { + ...base, + color: 'var(--text)', + } + }, + singleValue: (baseStyles, state) => { + return { + ...baseStyles, + color: 'var(--text)', + } + }, + control: (baseStyles, state) => ({ + ...baseStyles, + color: 'var(--text)', + backgroundColor: 'var(--custom-select)', + border: 'none', + }), + menu: (baseStyles, state) => { + return { + ...baseStyles, + backgroundColor: 'var(--custom-select)', + color: 'var(--text)', + } + }, + menuList: (baseStyles, props) => { + return { + ...baseStyles, + backgroundColor: 'var(--custom-select)', + color: 'var(--text)', + } + }, +} + +export const selectTheme = (theme) => ({ + ...theme, + borderRadius: 0, + colors: { + ...theme.colors, + primary25: 'var(--primary)', + primary: 'var(--primary)', + primary50: 'var(--primary)', + primary75: 'var(--primary)', + }, +}) \ No newline at end of file diff --git a/libs/remix-ui/git/src/utils/index.ts b/libs/remix-ui/git/src/utils/index.ts new file mode 100644 index 0000000000..8aab076424 --- /dev/null +++ b/libs/remix-ui/git/src/utils/index.ts @@ -0,0 +1,3 @@ +export const removeSlash = (s: string) => { + return s.replace(/^\/+/, ""); +}; diff --git a/libs/remix-ui/home-tab/src/lib/components/homeTabGetStarted.tsx b/libs/remix-ui/home-tab/src/lib/components/homeTabGetStarted.tsx index e7629edea1..2f85725d1b 100644 --- a/libs/remix-ui/home-tab/src/lib/components/homeTabGetStarted.tsx +++ b/libs/remix-ui/home-tab/src/lib/components/homeTabGetStarted.tsx @@ -71,7 +71,7 @@ function HomeTabGetStarted({ plugin }: HomeTabGetStartedProps) { const metadata = TEMPLATE_METADATA[templateName] if (metadata) { if (metadata.type === 'git') { - await plugin.call('dGitProvider', 'clone', { url: metadata.url, branch: metadata.branch }, templateDisplayName) + await plugin.call('dgitApi', 'clone', { url: metadata.url, branch: metadata.branch }, templateDisplayName) } else if (metadata && metadata.type === 'plugin') { await plugin.appManager.activatePlugin('filePanel') templateDisplayName = await plugin.call('filePanel', 'getAvailableWorkspaceName', templateDisplayName) diff --git a/libs/remix-ui/workspace/src/lib/actions/payload.ts b/libs/remix-ui/workspace/src/lib/actions/payload.ts index c19e93f4c5..59d0bc276d 100644 --- a/libs/remix-ui/workspace/src/lib/actions/payload.ts +++ b/libs/remix-ui/workspace/src/lib/actions/payload.ts @@ -1,4 +1,5 @@ import { fileDecoration } from '@remix-ui/file-decorators' +import { branch } from '@remix-ui/git'; import { Action, ActionPayloadTypes, FileTree, WorkspaceElement, action } from '../types' export const setCurrentWorkspace = (workspace: { name: string; isGitRepo: boolean; }): Action<'SET_CURRENT_WORKSPACE'> => { @@ -280,7 +281,7 @@ export const setCurrentWorkspaceBranches = (branches?: { remote: any, name: stri } } -export const setCurrentWorkspaceCurrentBranch = (currentBranch?: string): Action<'SET_CURRENT_WORKSPACE_CURRENT_BRANCH'> => { +export const setCurrentWorkspaceCurrentBranch = (currentBranch?: branch): Action<'SET_CURRENT_WORKSPACE_CURRENT_BRANCH'> => { return { type: 'SET_CURRENT_WORKSPACE_CURRENT_BRANCH', payload: currentBranch diff --git a/libs/remix-ui/workspace/src/lib/actions/workspace.ts b/libs/remix-ui/workspace/src/lib/actions/workspace.ts index fd79dd961c..4c05f836f9 100644 --- a/libs/remix-ui/workspace/src/lib/actions/workspace.ts +++ b/libs/remix-ui/workspace/src/lib/actions/workspace.ts @@ -42,7 +42,10 @@ import { ROOT_PATH, slitherYml, solTestYml, tsSolTestYml } from '../utils/consta import { IndexedDBStorage } from '../../../../../../apps/remix-ide/src/app/files/filesystems/indexedDB' import { getUncommittedFiles } from '../utils/gitStatusFilter' import { AppModal, ModalTypes } from '@remix-ui/app' +import { branch, cloneInputType, IGitApi } from '@remix-ui/git' import * as templates from '@remix-project/remix-ws-templates' +import { Plugin } from "@remixproject/engine"; +import { CustomRemixApi } from '@remix-api' declare global { interface Window { @@ -55,27 +58,28 @@ const NO_WORKSPACE = ' - none - ' const ELECTRON = 'electron' const queryParams = new QueryParams() const _paq = (window._paq = window._paq || []) //eslint-disable-line -let plugin, dispatch: React.Dispatch +let plugin: any, dgitPlugin: Plugin,dispatch: React.Dispatch export const setPlugin = (filePanelPlugin, reducerDispatch) => { plugin = filePanelPlugin + dgitPlugin = filePanelPlugin dispatch = reducerDispatch - plugin.on('dGitProvider', 'checkout', async () => { + dgitPlugin.on('dgitApi', 'checkout', async () => { await checkGit() }) - plugin.on('dGitProvider', 'init', async () => { + dgitPlugin.on('dgitApi', 'init', async () => { await checkGit() }) - plugin.on('dGitProvider', 'add', async () => { + dgitPlugin.on('dgitApi', 'add', async () => { await checkGit() }) - plugin.on('dGitProvider', 'commit', async () => { + dgitPlugin.on('dgitApi', 'commit', async () => { await checkGit() }) - plugin.on('dGitProvider', 'branch', async () => { + dgitPlugin.on('dgitApi', 'branch', async () => { await checkGit() }) - plugin.on('dGitProvider', 'clone', async () => { + dgitPlugin.on('dgitApi', 'clone', async () => { await checkGit() }) plugin.on('config', 'configChanged', async () => { @@ -152,31 +156,31 @@ export const createWorkspace = async ( if (isGitRepo && createCommit) { const name = await plugin.call('settings', 'get', 'settings/github-user-name') const email = await plugin.call('settings', 'get', 'settings/github-email') - const currentBranch = await plugin.call('dGitProvider', 'currentbranch') + const currentBranch: branch = await dgitPlugin.call('dgitApi', 'currentbranch') if (!currentBranch) { if (!name || !email) { - await plugin.call('notification', 'toast', 'To use Git features, add username and email to the Github section of the Settings panel.') + await plugin.call('notification', 'toast', 'To use Git features, add username and email to the Github section of the Git plugin.') } else { // commit the template as first commit plugin.call('notification', 'toast', 'Creating initial git commit ...') - await plugin.call('dGitProvider', 'init') + await dgitPlugin.call('dgitApi', 'init') if (!isEmpty) await loadWorkspacePreset(workspaceTemplateName, opts) - const status = await plugin.call('dGitProvider', 'status', { ref: 'HEAD' }) + const status = await dgitPlugin.call('dgitApi', 'status', { ref: 'HEAD' }) Promise.all( status.map(([filepath, , worktreeStatus]) => worktreeStatus - ? plugin.call('dGitProvider', 'add', { + ? dgitPlugin.call('dgitApi', 'add', { filepath: removeSlash(filepath), }) - : plugin.call('dGitProvider', 'rm', { + : dgitPlugin.call('dgitApi', 'rm', { filepath: removeSlash(filepath), }) ) ).then(async () => { - await plugin.call('dGitProvider', 'commit', { + await dgitPlugin.call('dgitApi', 'commit', { author: { name, email, @@ -200,11 +204,7 @@ export const createWorkspace = async ( }, 5000) } else if (!isEmpty && !(isGitRepo && createCommit)) await loadWorkspacePreset(workspaceTemplateName, opts) cb && cb(null, workspaceName) - if (isGitRepo) { - await checkGit() - const isActive = await plugin.call('manager', 'isActive', 'dgit') - if (!isActive) await plugin.call('manager', 'activatePlugin', 'dgit') - } + if (workspaceTemplateName === 'semaphore' || workspaceTemplateName === 'hashchecker' || workspaceTemplateName === 'rln') { const isCircomActive = await plugin.call('manager', 'isActive', 'circuit-compiler') if (!isCircomActive) await plugin.call('manager', 'activatePlugin', 'circuit-compiler') @@ -224,7 +224,7 @@ export const createWorkspaceTemplate = async (workspaceName: string, template: W if ((await workspaceExists(workspaceName)) && template === 'remixDefault') throw new Error('workspace already exists') else if (metadata && metadata.type === 'git') { dispatch(cloneRepositoryRequest()) - await plugin.call('dGitProvider', 'clone', { url: metadata.url, branch: metadata.branch }, workspaceName) + await dgitPlugin.call('dgitApi', 'clone', { url: metadata.url, branch: metadata.branch, workspaceName: workspaceName }) dispatch(cloneRepositorySuccess()) } else { const workspaceProvider = plugin.fileProviders.workspace @@ -509,10 +509,7 @@ export const switchToWorkspace = async (name: string) => { await plugin.fileProviders.workspace.setWorkspace(name) await plugin.setWorkspace({ name, isLocalhost: false }) const isGitRepo = await plugin.fileManager.isGitRepo() - if (isGitRepo) { - const isActive = await plugin.call('manager', 'isActive', 'dgit') - if (!isActive) await plugin.call('manager', 'activatePlugin', 'dgit') - } + dispatch(setMode('browser')) dispatch(setCurrentWorkspace({ name, isGitRepo })) dispatch(setReadOnlyMode(false)) @@ -648,11 +645,11 @@ export const getWorkspaces = async (): Promise<{ name: string; isGitRepo: boolea export const cloneRepository = async (url: string) => { const config = plugin.registry.get('config').api const token = config.get('settings/gist-access-token') - const repoConfig = { url, token } + const repoConfig: cloneInputType = { url, token } if (plugin.registry.get('platform').api.isDesktop()) { try { - await plugin.call('dGitProvider', 'clone', repoConfig) + await dgitPlugin.call('dgitApi', 'clone', repoConfig) } catch (e) { console.log(e) plugin.call('notification', 'alert', { @@ -665,7 +662,7 @@ export const cloneRepository = async (url: string) => { const repoName = await getRepositoryTitle(url) await createWorkspace(repoName, 'blank', null, true, null, true, false) - const promise = plugin.call('dGitProvider', 'clone', repoConfig, repoName, true) + const promise = dgitPlugin.call('dgitApi', 'clone', { ...repoConfig, workspaceExists: true, workspaceName: repoName }) dispatch(cloneRepositoryRequest()) promise @@ -687,7 +684,7 @@ export const cloneRepository = async (url: string) => { id: 'cloneGitRepository', title: 'Clone Git Repository', message: - 'An error occurred: Please check that you have the correct URL for the repo. If the repo is private, you need to add your github credentials (with the valid token permissions) in Settings plugin', + 'An error occurred: Please check that you have the correct URL for the repo. If the repo is private, you need to add your github credentials (with the valid token permissions) in the Git plugin', modalType: 'modal', okLabel: plugin.registry.get('platform').api.isDesktop() ? 'Select or create folder':'OK', okFn: async () => { @@ -714,7 +711,7 @@ export const checkGit = async () => { dispatch(setCurrentWorkspaceIsGitRepo(isGitRepo)) dispatch(setCurrentWorkspaceHasGitSubmodules(hasGitSubmodule)) await refreshBranches() - const currentBranch = await plugin.call('dGitProvider', 'currentbranch') + const currentBranch: branch = await dgitPlugin.call('dgitApi', 'currentbranch') dispatch(setCurrentWorkspaceCurrentBranch(currentBranch)) } catch (e) {} } @@ -743,7 +740,7 @@ export const getGitRepoBranches = async (workspacePath: string) => { fs: window.remixFileSystemCallback, dir: addSlash(workspacePath), } - const branches: { remote: any; name: string }[] = await plugin.call('dGitProvider', 'branches', { ...gitConfig }) + const branches: branch[] = await dgitPlugin.call('dgitApi', 'branches', { ...gitConfig }) return branches } @@ -752,7 +749,7 @@ export const getGitRepoCurrentBranch = async (workspaceName: string) => { fs: window.remixFileSystemCallback, dir: addSlash(workspaceName), } - const currentBranch: string = await plugin.call('dGitProvider', 'currentbranch', { ...gitConfig }) + const currentBranch: branch = await dgitPlugin.call('dgitApi', 'currentbranch', { ...gitConfig }) return currentBranch } @@ -781,7 +778,7 @@ const refreshBranches = async () => { dispatch(setCurrentWorkspaceBranches(branches)) } -export const switchBranch = async (branch: string) => { +export const switchBranch = async (branch: branch) => { await plugin.call('fileManager', 'closeAllFiles') const localChanges = await hasLocalChanges() @@ -797,7 +794,7 @@ export const switchBranch = async (branch: string) => { okFn: async () => { dispatch(cloneRepositoryRequest()) plugin - .call('dGitProvider', 'checkout', { ref: branch, force: true }, false) + .call('dgitApi', 'checkout', { ref: branch, force: true }, false) .then(async () => { await fetchWorkspaceDirectory(ROOT_PATH) dispatch(setCurrentWorkspaceCurrentBranch(branch)) @@ -815,7 +812,7 @@ export const switchBranch = async (branch: string) => { } else { dispatch(cloneRepositoryRequest()) plugin - .call('dGitProvider', 'checkout', { ref: branch, force: true }, false) + .call('dgitApi', 'checkout', { ref: branch, force: true }, false) .then(async () => { await fetchWorkspaceDirectory(ROOT_PATH) dispatch(setCurrentWorkspaceCurrentBranch(branch)) @@ -828,13 +825,16 @@ export const switchBranch = async (branch: string) => { } export const createNewBranch = async (branch: string) => { - const promise = plugin.call('dGitProvider', 'branch', { ref: branch, checkout: true }, false) + const promise = dgitPlugin.call('dgitApi', 'branch', { ref: branch, checkout: true, refresh: false }) dispatch(cloneRepositoryRequest()) promise .then(async () => { await fetchWorkspaceDirectory(ROOT_PATH) - dispatch(setCurrentWorkspaceCurrentBranch(branch)) + dispatch(setCurrentWorkspaceCurrentBranch({ + remote: null, + name: branch, + })) const workspacesPath = plugin.fileProviders.workspace.workspacesPath const workspaceName = plugin.fileProviders.workspace.workspace const branches = await getGitRepoBranches(workspacesPath + '/' + workspaceName) @@ -880,11 +880,11 @@ export const updateGitSubmodules = async () => { const config = plugin.registry.get('config').api const token = config.get('settings/gist-access-token') const repoConfig = { token } - await plugin.call('dGitProvider', 'updateSubmodules', repoConfig) + await dgitPlugin.call('dgitApi', 'updateSubmodules', repoConfig) dispatch(cloneRepositorySuccess()) } -export const checkoutRemoteBranch = async (branch: string, remote: string) => { +export const checkoutRemoteBranch = async (branch: branch) => { const localChanges = await hasLocalChanges() if (Array.isArray(localChanges) && localChanges.length > 0) { @@ -899,7 +899,10 @@ export const checkoutRemoteBranch = async (branch: string, remote: string) => { okFn: async () => { dispatch(cloneRepositoryRequest()) plugin - .call('dGitProvider', 'checkout', { ref: branch, remote, force: true }, false) + .call('dgitApi', 'checkout', { + ref: branch, + force: true, + }) .then(async () => { await fetchWorkspaceDirectory(ROOT_PATH) dispatch(setCurrentWorkspaceCurrentBranch(branch)) @@ -922,7 +925,10 @@ export const checkoutRemoteBranch = async (branch: string, remote: string) => { } else { dispatch(cloneRepositoryRequest()) plugin - .call('dGitProvider', 'checkout', { ref: branch, remote, force: true }, false) + .call('dgitApi', 'checkout',{ + ref: branch, + force: true, + }, false) .then(async () => { await fetchWorkspaceDirectory(ROOT_PATH) dispatch(setCurrentWorkspaceCurrentBranch(branch)) @@ -955,7 +961,7 @@ export const removeRecentElectronFolder = async (path: string) => { } export const hasLocalChanges = async () => { - const filesStatus = await plugin.call('dGitProvider', 'status') + const filesStatus = await dgitPlugin.call('dgitApi', 'status') const uncommittedFiles = getUncommittedFiles(filesStatus) return uncommittedFiles diff --git a/libs/remix-ui/workspace/src/lib/contexts/index.ts b/libs/remix-ui/workspace/src/lib/contexts/index.ts index 7e297ffb0d..4269b8b647 100644 --- a/libs/remix-ui/workspace/src/lib/contexts/index.ts +++ b/libs/remix-ui/workspace/src/lib/contexts/index.ts @@ -1,3 +1,4 @@ +import { branch } from '@remix-ui/git' import { customAction } from '@remixproject/plugin-api' import { createContext, SyntheticEvent } from 'react' import { BrowserState } from '../reducers/workspace' @@ -40,9 +41,9 @@ export const FileSystemContext = createContext<{ dispatchMoveFile: (src: string, dest: string) => Promise, dispatchMoveFolder: (src: string, dest: string) => Promise, dispatchShowAllBranches: () => Promise, - dispatchSwitchToBranch: (branch: string) => Promise, - dispatchCreateNewBranch: (branch: string) => Promise, - dispatchCheckoutRemoteBranch: (branch: string, remote: string) => Promise, + dispatchSwitchToBranch: (branch: branch) => Promise, + dispatchCreateNewBranch: (name: string) => Promise, + dispatchCheckoutRemoteBranch: (branch: branch) => Promise, dispatchCreateSolidityGithubAction: () => Promise, dispatchCreateTsSolGithubAction: () => Promise, dispatchCreateSlitherGithubAction: () => Promise diff --git a/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx b/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx index 481991dd12..af2caab30f 100644 --- a/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx +++ b/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx @@ -5,6 +5,7 @@ import {Toaster} from '@remix-ui/toaster' // eslint-disable-line // eslint-disable-next-line @typescript-eslint/no-unused-vars import { FileSystemContext } from '../contexts' import { browserReducer, browserInitialState } from '../reducers/workspace' +import { branch } from '@remix-ui/git' import { initWorkspace, fetchDirectory, @@ -209,7 +210,7 @@ export const FileSystemProvider = (props: WorkspaceProps) => { await showAllBranches() } - const dispatchSwitchToBranch = async (branch: string) => { + const dispatchSwitchToBranch = async (branch: branch) => { await switchBranch(branch) } @@ -217,8 +218,8 @@ export const FileSystemProvider = (props: WorkspaceProps) => { await createNewBranch(branch) } - const dispatchCheckoutRemoteBranch = async (branch: string, remote: string) => { - await checkoutRemoteBranch(branch, remote) + const dispatchCheckoutRemoteBranch = async (branch: branch) => { + await checkoutRemoteBranch(branch) } const dispatchCreateSolidityGithubAction = async () => { diff --git a/libs/remix-ui/workspace/src/lib/reducers/workspace.ts b/libs/remix-ui/workspace/src/lib/reducers/workspace.ts index f86929ca23..b2febcc602 100644 --- a/libs/remix-ui/workspace/src/lib/reducers/workspace.ts +++ b/libs/remix-ui/workspace/src/lib/reducers/workspace.ts @@ -5,6 +5,7 @@ import { fileDecoration } from '@remix-ui/file-decorators' import { ROOT_PATH } from '../utils/constants' import isElectron from 'is-electron' import { fileKeySort } from '../utils' +import { branch } from '@remix-ui/git' export interface BrowserState { browser: { currentWorkspace: string @@ -12,11 +13,8 @@ export interface BrowserState { name: string isGitRepo: boolean hasGitSubmodules?: boolean - branches?: { - remote: any - name: string - }[] - currentBranch?: string + branches?: branch[] + currentBranch?: branch isGist: string }[] files: {[x: string]: Record} diff --git a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx index 2368fc6a83..b35f750a8d 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -16,6 +16,7 @@ import { customAction } from '@remixproject/plugin-api' import { appPlatformTypes, platformContext } from '@remix-ui/app' import { ElectronMenu } from './components/electron-menu' import { ElectronWorkspaceName } from './components/electron-workspace-name' +import { branch } from '@remix-ui/git' const _paq = (window._paq = window._paq || []) @@ -693,13 +694,14 @@ export function Workspace() { global.dispatchShowAllBranches() } - const switchToBranch = async (branch: {remote: string; name: string}) => { + const switchToBranch = async (branch: branch) => { + console.log('switchToBranch', branch) try { if (branch.remote) { - await global.dispatchCheckoutRemoteBranch(branch.name, branch.remote) + await global.dispatchCheckoutRemoteBranch(branch) _paq.push(['trackEvent', 'Workspace', 'GIT', 'checkout_remote_branch']) } else { - await global.dispatchSwitchToBranch(branch.name) + await global.dispatchSwitchToBranch(branch) _paq.push(['trackEvent', 'Workspace', 'GIT', 'switch_to_exisiting_branch']) } } catch (e) { @@ -1219,7 +1221,7 @@ export function Workspace() { className="btn btn-light btn-block w-100 d-inline-block border border-dark form-control h-100 p-0 pl-2 pr-2 text-dark" icon={null} > - {global.fs.browser.isRequestingCloning ? : currentBranch || '-none-'} + {global.fs.browser.isRequestingCloning ? : (currentBranch && currentBranch.name) || '-none-'} @@ -1259,8 +1261,8 @@ export function Workspace() { }} title={intl.formatMessage({ id: `filePanel.switchToBranch${branch.remote ? 'Title1' : 'Title2'}` })} > -
    - {currentBranch === branch.name && !branch.remote ? ( +
    + {currentBranch && currentBranch.name === branch.name && !branch.remote ? ( {branch.name} @@ -1268,7 +1270,7 @@ export function Workspace() { ) : ( - {branch.remote ? `${branch.remote}/${branch.name}` : branch.name} + {branch.remote ? `${branch.remote.name}/${branch.name}` : branch.name} )}
    @@ -1280,7 +1282,7 @@ export function Workspace() {
    - : {branchFilter} from '{currentBranch}' + : {branchFilter} from '{currentBranch && currentBranch.name}'
    diff --git a/libs/remix-ui/workspace/src/lib/types/index.ts b/libs/remix-ui/workspace/src/lib/types/index.ts index 7d812c75ec..4c7cd5b1b0 100644 --- a/libs/remix-ui/workspace/src/lib/types/index.ts +++ b/libs/remix-ui/workspace/src/lib/types/index.ts @@ -6,6 +6,7 @@ import { RemixAppManager } from 'libs/remix-ui/plugin-manager/src/types' import { ViewPlugin } from '@remixproject/engine-web' import { appPlatformTypes } from '@remix-ui/app' import { Placement } from 'react-bootstrap/esm/Overlay' +import { branch } from '@remix-ui/git' export type action = { name: string, type?: Array, path?: string[], extension?: string[], pattern?: string[], id: string, multiselect: boolean, label: string, sticky?: boolean, group: number, platform?: appPlatformTypes } export interface JSONStandardInput { @@ -51,8 +52,8 @@ export type WorkspaceMetadata = { name: string isGitRepo: boolean hasGitSubmodules?: boolean - branches?: {remote: any; name: string}[] - currentBranch?: string + branches?: branch[] + currentBranch?: branch isGist: string } @@ -244,14 +245,14 @@ export interface ActionPayloadTypes { SET_CURRENT_WORKSPACE: { name: string isGitRepo: boolean - branches?: {remote: string | undefined; name: string}[] - currentBranch?: string + branches?: branch[] + currentBranch?: branch }, SET_WORKSPACES: { name: string isGitRepo: boolean - branches?: {remote: string | undefined; name: string}[] - currentBranch?: string + branches?: branch[] + currentBranch?: branch }[], SET_MODE: 'browser' | 'localhost', FETCH_DIRECTORY_REQUEST: undefined | null, @@ -293,8 +294,8 @@ export interface ActionPayloadTypes { CREATE_WORKSPACE_SUCCESS: { name: string isGitRepo: boolean - branches?: { remote: string | undefined; name: string }[] - currentBranch?: string + branches?: branch[] + currentBranch?: branch }, CREATE_WORKSPACE_ERROR: string, RENAME_WORKSPACE: { oldName: string; workspaceName: string }, @@ -317,8 +318,8 @@ export interface ActionPayloadTypes { CLONE_REPOSITORY_FAILED: undefined | null, FS_INITIALIZATION_COMPLETED: undefined | null, SET_FILE_DECORATION_SUCCESS: fileDecoration[], - SET_CURRENT_WORKSPACE_BRANCHES: { remote: string | undefined; name: string }[], - SET_CURRENT_WORKSPACE_CURRENT_BRANCH: string, + SET_CURRENT_WORKSPACE_BRANCHES: branch[], + SET_CURRENT_WORKSPACE_CURRENT_BRANCH: branch, SET_CURRENT_WORKSPACE_IS_GITREPO: boolean, SET_CURRENT_WORKSPACE_HAS_GIT_SUBMODULES: boolean, SET_GIT_CONFIG: { diff --git a/lintpr.sh b/lintpr.sh new file mode 100644 index 0000000000..38f60e3338 --- /dev/null +++ b/lintpr.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# Find all project.json files in subdirectories +find . -type d -name 'node_modules' -prune -o -name '.eslintrc' -print | while read -r file; do + # Extract the directory path of the file + dir=$(dirname "$file") + + + + echo $file + + git checkout master -- $file + +done diff --git a/package.json b/package.json index ade5becb79..34ab8222c1 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "build-contracts": "find ./node_modules/@openzeppelin/contracts | grep -i '.sol' > libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt && find ./node_modules/@uniswap/v3-core/contracts | grep -i '.sol' >> libs/remix-ui/editor/src/lib/providers/completion/contracts/contracts.txt" }, "dependencies": { + "@apollo/client": "^3.9.5", "@babel/plugin-proposal-class-properties": "^7.16.0", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", "@erebos/bzz-node": "^0.13.0", @@ -97,6 +98,9 @@ "@ethereumjs/util": "9.0.3", "@ethereumjs/vm": "8.0.0", "@ethersphere/bee-js": "^3.2.0", + "@fortawesome/fontawesome-svg-core": "^6.5.1", + "@fortawesome/free-solid-svg-icons": "^6.5.1", + "@fortawesome/react-fontawesome": "^0.2.0", "@gradio/client": "^0.10.1", "@isomorphic-git/lightning-fs": "^4.4.1", "@microlink/react-json-view": "^1.23.0", @@ -149,11 +153,12 @@ "from-exponential": "1.1.1", "fs-extra": "^3.0.1", "ganache": "^7.9.1", + "graphql": "^16.8.1", "html-react-parser": "^3.0.4", "http-server": "^14.1.1", "intro.js": "^4.1.0", "isbinaryfile": "^3.0.2", - "isomorphic-git": "^1.25.0", + "isomorphic-git": "^1.25.7", "jquery": "^3.3.1", "js-yaml": "^4.1.0", "jspdf": "^2.5.1", @@ -167,6 +172,7 @@ "path-browserify": "^1.0.1", "prettier": "^2.8.4", "prettier-plugin-solidity": "^1.0.0-beta.24", + "ra-data-graphql": "^4.16.11", "raw-loader": "^4.0.2", "react": "^18.2.0", "react-beautiful-dnd": "^13.1.0", @@ -177,6 +183,7 @@ "react-markdown": "^8.0.5", "react-multi-carousel": "^2.8.2", "react-router-dom": "^6.16.0", + "react-select": "^5.8.0", "react-spinners": "^0.13.8", "react-tabs": "^6.0.2", "react-toastify": "^10.0.3", @@ -224,6 +231,9 @@ "@babel/register": "^7.4.4", "@electron-forge/cli": "^6.1.1", "@fortawesome/fontawesome-free": "^5.8.1", + "@graphql-codegen/cli": "^5.0.2", + "@graphql-codegen/client-preset": "^4.2.4", + "@graphql-typed-document-node/core": "^3.2.0", "@monaco-editor/react": "4.6.0", "@nrwl/cli": "15.7.1", "@nrwl/eslint-plugin-nx": "15.7.1", @@ -235,6 +245,7 @@ "@nrwl/web": "15.7.1", "@nrwl/webpack": "15.7.1", "@nrwl/workspace": "15.7.1", + "@octokit/types": "^12.4.0", "@openzeppelin/contracts-upgradeable": "^5.0.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.10", "@svgr/webpack": "^6.5.1", diff --git a/tsconfig.paths.json b/tsconfig.paths.json index 479658b4a9..27b4cf0fbf 100644 --- a/tsconfig.paths.json +++ b/tsconfig.paths.json @@ -172,7 +172,12 @@ "@remix-ui/xterm": [ "libs/remix-ui/xterm/src/index.ts" ], - + "@remix-ui/git": [ + "libs/remix-ui/git/src/index.ts" + ], + "@remix-api": [ + "libs/remix-api/src/index.ts" + ] } } } diff --git a/yarn.lock b/yarn.lock index 34d352ac8e..e0b092a4cb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,6 +25,56 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" +"@apollo/client@^3.3.19", "@apollo/client@^3.9.5": + version "3.9.5" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.9.5.tgz#502ec191756a7f44788b5f08cbe7b8de594a7656" + integrity sha512-7y+c8MTPU+hhTwvcGVtMMGIgWduzrvG1mz5yJMRyqYbheBkkky3Lki6ADWVSBXG1lZoOtPYvB2zDgVfKb2HSsw== + dependencies: + "@graphql-typed-document-node/core" "^3.1.1" + "@wry/caches" "^1.0.0" + "@wry/equality" "^0.5.6" + "@wry/trie" "^0.5.0" + graphql-tag "^2.12.6" + hoist-non-react-statics "^3.3.2" + optimism "^0.18.0" + prop-types "^15.7.2" + rehackt "0.0.5" + response-iterator "^0.2.6" + symbol-observable "^4.0.0" + ts-invariant "^0.10.3" + tslib "^2.3.0" + zen-observable-ts "^1.2.5" + +"@ardatan/relay-compiler@12.0.0": + version "12.0.0" + resolved "https://registry.yarnpkg.com/@ardatan/relay-compiler/-/relay-compiler-12.0.0.tgz#2e4cca43088e807adc63450e8cab037020e91106" + integrity sha512-9anThAaj1dQr6IGmzBMcfzOQKTa5artjuPmw8NYK/fiGEMjADbSguBY2FMDykt+QhilR3wc9VA/3yVju7JHg7Q== + dependencies: + "@babel/core" "^7.14.0" + "@babel/generator" "^7.14.0" + "@babel/parser" "^7.14.0" + "@babel/runtime" "^7.0.0" + "@babel/traverse" "^7.14.0" + "@babel/types" "^7.0.0" + babel-preset-fbjs "^3.4.0" + chalk "^4.0.0" + fb-watchman "^2.0.0" + fbjs "^3.0.0" + glob "^7.1.1" + immutable "~3.7.6" + invariant "^2.2.4" + nullthrows "^1.1.1" + relay-runtime "12.0.0" + signedsource "^1.0.0" + yargs "^15.3.1" + +"@ardatan/sync-fetch@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@ardatan/sync-fetch/-/sync-fetch-0.0.1.tgz#3385d3feedceb60a896518a1db857ec1e945348f" + integrity sha512-xhlTqH0m31mnsG0tIP4ETgfSB6gXDaYYsUWTrlUV93fFQPI9dd8hE0Ot6MHLCtqgB32hwJAC3YZMWlXZw7AleA== + dependencies: + node-fetch "^2.6.1" + "@babel/cli@^7.19.3": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.21.0.tgz#1868eb70e9824b427fc607610cce8e9e7889e7e1" @@ -70,6 +120,14 @@ "@babel/highlight" "^7.22.13" chalk "^2.4.2" +"@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== + dependencies: + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" + "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8", "@babel/compat-data@^7.19.1": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.1.tgz#72d647b4ff6a4f82878d184613353af1dd0290f9" @@ -90,6 +148,11 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.0.tgz#c241dc454e5b5917e40d37e525e2f4530c399298" integrity sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g== +"@babel/compat-data@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" + integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== + "@babel/core@^7.11.6": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.0.tgz#1341aefdcc14ccc7553fcc688dd8986a2daffc13" @@ -132,6 +195,27 @@ semver "^6.3.0" source-map "^0.5.0" +"@babel/core@^7.14.0", "@babel/core@^7.22.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.9.tgz#b028820718000f267870822fec434820e9b1e4d1" + integrity sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.23.9" + "@babel/parser" "^7.23.9" + "@babel/template" "^7.23.9" + "@babel/traverse" "^7.23.9" + "@babel/types" "^7.23.9" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + "@babel/core@^7.15.0": version "7.19.3" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.3.tgz#2519f62a51458f43b682d61583c3810e7dcee64c" @@ -183,6 +267,16 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.14.0", "@babel/generator@^7.18.13", "@babel/generator@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== + dependencies: + "@babel/types" "^7.23.6" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/generator@^7.15.8", "@babel/generator@^7.21.0", "@babel/generator@^7.4.0", "@babel/generator@^7.7.2": version "7.21.1" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd" @@ -235,6 +329,13 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" @@ -274,6 +375,17 @@ browserslist "^4.21.3" semver "^6.3.0" +"@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== + dependencies: + "@babel/compat-data" "^7.23.5" + "@babel/helper-validator-option" "^7.23.5" + browserslist "^4.22.2" + lru-cache "^5.1.1" + semver "^6.3.1" + "@babel/helper-create-class-features-plugin@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.0.tgz#090d4d166b342a03a9fec37ef4fd5aeb9c7c6a4b" @@ -404,6 +516,13 @@ dependencies: "@babel/types" "^7.18.9" +"@babel/helper-member-expression-to-functions@^7.22.15": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" + integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== + dependencies: + "@babel/types" "^7.23.0" + "@babel/helper-module-imports@^7.0.0-beta.44": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz#90538e60b672ecf1b448f5f4f5433d37e79a3ec3" @@ -418,6 +537,13 @@ dependencies: "@babel/types" "^7.21.4" +"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== + dependencies: + "@babel/types" "^7.22.15" + "@babel/helper-module-imports@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" @@ -481,6 +607,17 @@ "@babel/traverse" "^7.21.0" "@babel/types" "^7.21.0" +"@babel/helper-module-transforms@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" + integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + "@babel/helper-optimise-call-expression@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz#cecdb145d70c54096b1564f8e9f10cd7d193b338" @@ -495,6 +632,13 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-optimise-call-expression@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" + integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" @@ -510,6 +654,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== +"@babel/helper-plugin-utils@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + "@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" @@ -541,6 +690,15 @@ "@babel/traverse" "^7.19.1" "@babel/types" "^7.19.0" +"@babel/helper-replace-supers@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793" + integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-simple-access@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" @@ -562,6 +720,13 @@ dependencies: "@babel/types" "^7.20.2" +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz#778d87b3a758d90b471e7b9918f34a9a02eb5818" @@ -569,6 +734,13 @@ dependencies: "@babel/types" "^7.18.9" +"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" + integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-split-export-declaration@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz#29672f43663e936df370aaeb22beddb3baec7438" @@ -610,6 +782,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== + "@babel/helper-validator-identifier@^7.15.7": version "7.15.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" @@ -630,6 +807,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== +"@babel/helper-validator-option@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" + integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== + "@babel/helper-wrap-function@^7.18.9": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1" @@ -667,6 +849,15 @@ "@babel/traverse" "^7.19.4" "@babel/types" "^7.19.4" +"@babel/helpers@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.9.tgz#c3e20bbe7f7a7e10cb9b178384b4affdf5995c7d" + integrity sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ== + dependencies: + "@babel/template" "^7.23.9" + "@babel/traverse" "^7.23.9" + "@babel/types" "^7.23.9" + "@babel/highlight@^7.14.5", "@babel/highlight@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" @@ -694,11 +885,25 @@ chalk "^2.4.2" js-tokens "^4.0.0" +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.0", "@babel/parser@^7.7.0": version "7.21.1" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.1.tgz#a8f81ee2fe872af23faea4b17a08fcc869de7bcc" integrity sha512-JzhBFpkuhBNYUY7qs+wTzNmyCWUHEaAFpQQD2YfU1rPL38/L43Wvid0fFkiOCnHvsGncRZgEPyGnltABLcVDTg== +"@babel/parser@^7.14.0", "@babel/parser@^7.16.8", "@babel/parser@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" + integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== + "@babel/parser@^7.15.8", "@babel/parser@^7.4.3": version "7.21.2" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3" @@ -760,6 +965,14 @@ "@babel/helper-remap-async-to-generator" "^7.18.9" "@babel/plugin-syntax-async-generators" "^7.8.4" +"@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.16.0", "@babel/plugin-proposal-class-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-proposal-class-properties@^7.14.5": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.0.tgz#c029618267ddebc7280fa286e0f8ca2a278a2d1a" @@ -768,14 +981,6 @@ "@babel/helper-create-class-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-proposal-class-properties@^7.16.0", "@babel/plugin-proposal-class-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" - integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-proposal-class-static-block@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" @@ -844,6 +1049,17 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-numeric-separator" "^7.10.4" +"@babel/plugin-proposal-object-rest-spread@^7.0.0": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" + integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== + dependencies: + "@babel/compat-data" "^7.20.5" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.20.7" + "@babel/plugin-proposal-object-rest-spread@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz#f9434f6beb2c8cae9dfcf97d2a5941bbbf9ad4e7" @@ -931,7 +1147,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": +"@babel/plugin-syntax-class-properties@^7.0.0", "@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== @@ -966,6 +1182,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.23.3.tgz#084564e0f3cc21ea6c70c44cff984a1c0509729a" + integrity sha512-YZiAIpkJAwQXBJLIQbRFayR5c+gJ35Vcz3bg954k7cd73zqjvhacJuL9RbrzPz8qPmZdgqP6EUKwy0PCNhaaPA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-import-assertions@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz#cd6190500a4fa2fe31990a963ffab4b63e4505e4" @@ -973,6 +1196,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-syntax-import-assertions@^7.20.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz#9c05a7f592982aff1a2768260ad84bcd3f0c77fc" + integrity sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" @@ -987,6 +1217,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" + integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-jsx@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" @@ -1015,7 +1252,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-object-rest-spread@^7.8.3": +"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== @@ -1071,6 +1308,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.19.0" +"@babel/plugin-transform-arrow-functions@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz#94c6dcfd731af90f27a79509f9ab7fb2120fc38b" + integrity sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-arrow-functions@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" @@ -1087,6 +1331,13 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/helper-remap-async-to-generator" "^7.18.6" +"@babel/plugin-transform-block-scoped-functions@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz#fe1177d715fb569663095e04f3598525d98e8c77" + integrity sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-block-scoped-functions@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" @@ -1094,6 +1345,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-block-scoping@^7.0.0": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz#b2d38589531c6c80fbe25e6b58e763622d2d3cf5" + integrity sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-block-scoping@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz#f9b7e018ac3f373c81452d6ada8bd5a18928926d" @@ -1108,6 +1366,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.19.0" +"@babel/plugin-transform-classes@^7.0.0": + version "7.23.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz#d08ae096c240347badd68cdf1b6d1624a6435d92" + integrity sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.20" + "@babel/helper-split-export-declaration" "^7.22.6" + globals "^11.1.0" + "@babel/plugin-transform-classes@^7.19.0": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz#0e61ec257fba409c41372175e7c1e606dc79bb20" @@ -1123,6 +1395,14 @@ "@babel/helper-split-export-declaration" "^7.18.6" globals "^11.1.0" +"@babel/plugin-transform-computed-properties@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz#652e69561fcc9d2b50ba4f7ac7f60dcf65e86474" + integrity sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/template" "^7.22.15" + "@babel/plugin-transform-computed-properties@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" @@ -1130,6 +1410,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.9" +"@babel/plugin-transform-destructuring@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz#8c9ee68228b12ae3dff986e56ed1ba4f3c446311" + integrity sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-destructuring@^7.18.13": version "7.18.13" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz#9e03bc4a94475d62b7f4114938e6c5c33372cbf5" @@ -1175,6 +1462,22 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-flow-strip-types@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.23.3.tgz#cfa7ca159cc3306fab526fc67091556b51af26ff" + integrity sha512-26/pQTf9nQSNVJCrLB1IkHUKyPxR+lMrH2QDPG89+Znu9rAMbtrybdbWeE9bb7gzjmE5iXHEY+e0HUwM6Co93Q== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-flow" "^7.23.3" + +"@babel/plugin-transform-for-of@^7.0.0": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz#81c37e24171b37b370ba6aaffa7ac86bcb46f94e" + integrity sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-transform-for-of@^7.18.8": version "7.18.8" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" @@ -1182,6 +1485,15 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-function-name@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz#8f424fcd862bf84cb9a1a6b42bc2f47ed630f8dc" + integrity sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw== + dependencies: + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-function-name@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" @@ -1191,6 +1503,13 @@ "@babel/helper-function-name" "^7.18.9" "@babel/helper-plugin-utils" "^7.18.9" +"@babel/plugin-transform-literals@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz#8214665f00506ead73de157eba233e7381f3beb4" + integrity sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-literals@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" @@ -1198,6 +1517,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.9" +"@babel/plugin-transform-member-expression-literals@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz#e37b3f0502289f477ac0e776b05a833d853cabcc" + integrity sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-member-expression-literals@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" @@ -1214,6 +1540,15 @@ "@babel/helper-plugin-utils" "^7.18.6" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-commonjs@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz#661ae831b9577e52be57dd8356b734f9700b53b4" + integrity sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA== + dependencies: + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" + "@babel/plugin-transform-modules-commonjs@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz#afd243afba166cca69892e24a8fd8c9f2ca87883" @@ -1274,6 +1609,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-object-super@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz#81fdb636dcb306dd2e4e8fd80db5b2362ed2ebcd" + integrity sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.20" + "@babel/plugin-transform-object-super@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" @@ -1282,6 +1625,13 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/helper-replace-supers" "^7.18.6" +"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.20.7": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz#83ef5d1baf4b1072fa6e54b2b0999a7b2527e2af" + integrity sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-parameters@^7.18.8": version "7.18.8" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz#ee9f1a0ce6d78af58d0956a9378ea3427cccb48a" @@ -1289,6 +1639,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-property-literals@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz#54518f14ac4755d22b92162e4a852d308a560875" + integrity sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-property-literals@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" @@ -1303,6 +1660,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.20.2" +"@babel/plugin-transform-react-display-name@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.23.3.tgz#70529f034dd1e561045ad3c8152a267f0d7b6200" + integrity sha512-GnvhtVfA2OAtzdX58FJxU19rhoGeQzyVndw3GgtdECQvQFXPEZIOVULHVZGAYmOgmqjXpVpfocAbSjh99V/Fqw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-react-display-name@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" @@ -1317,6 +1681,17 @@ dependencies: "@babel/plugin-transform-react-jsx" "^7.18.6" +"@babel/plugin-transform-react-jsx@^7.0.0": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz#393f99185110cea87184ea47bcb4a7b0c2e39312" + integrity sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-jsx" "^7.23.3" + "@babel/types" "^7.23.4" + "@babel/plugin-transform-react-jsx@^7.18.6": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9" @@ -1363,6 +1738,13 @@ babel-plugin-polyfill-regenerator "^0.4.1" semver "^6.3.0" +"@babel/plugin-transform-shorthand-properties@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz#97d82a39b0e0c24f8a981568a8ed851745f59210" + integrity sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-shorthand-properties@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" @@ -1370,6 +1752,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-spread@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz#41d17aacb12bde55168403c6f2d6bdca563d362c" + integrity sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-transform-spread@^7.19.0": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" @@ -1385,6 +1775,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-template-literals@^7.0.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz#5f0f028eb14e50b5d0f76be57f90045757539d07" + integrity sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-template-literals@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" @@ -1663,6 +2060,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.12.0", "@babel/runtime@^7.18.3": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7" + integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/runtime@^7.14.8": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" @@ -1713,6 +2117,31 @@ "@babel/parser" "^7.22.15" "@babel/types" "^7.22.15" +"@babel/template@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a" + integrity sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + +"@babel/traverse@^7.14.0", "@babel/traverse@^7.16.8", "@babel/traverse@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" + integrity sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + debug "^4.3.1" + globals "^11.1.0" + "@babel/traverse@^7.15.4", "@babel/traverse@^7.16.0", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.19.3", "@babel/traverse@^7.19.4", "@babel/traverse@^7.19.6", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.3.tgz#26ee5f252e725aa7aca3474aa5b324eaf7908b5b" @@ -1746,6 +2175,15 @@ "@babel/helper-validator-identifier" "^7.15.7" to-fast-properties "^2.0.0" +"@babel/types@^7.16.8", "@babel/types@^7.18.13", "@babel/types@^7.23.4", "@babel/types@^7.23.6", "@babel/types@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" + integrity sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.0.tgz#75f21d73d73dc0351f3368d28db73465f4814600" @@ -2103,6 +2541,94 @@ minimatch "^3.0.4" plist "^3.0.4" +"@emotion/babel-plugin@^11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c" + integrity sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ== + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/runtime" "^7.18.3" + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/serialize" "^1.1.2" + babel-plugin-macros "^3.1.0" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "4.2.0" + +"@emotion/cache@^11.11.0", "@emotion/cache@^11.4.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff" + integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ== + dependencies: + "@emotion/memoize" "^0.8.1" + "@emotion/sheet" "^1.2.2" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + stylis "4.2.0" + +"@emotion/hash@^0.9.1": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43" + integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== + +"@emotion/memoize@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" + integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== + +"@emotion/react@^11.8.1": + version "11.11.3" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.3.tgz#96b855dc40a2a55f52a72f518a41db4f69c31a25" + integrity sha512-Cnn0kuq4DoONOMcnoVsTOR8E+AdnKFf//6kUWc4LCdnxj31pZWn7rIULd6Y7/Js1PiPHzn7SKCM9vB/jBni8eA== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/cache" "^11.11.0" + "@emotion/serialize" "^1.1.3" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@^1.1.2", "@emotion/serialize@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.3.tgz#84b77bfcfe3b7bb47d326602f640ccfcacd5ffb0" + integrity sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA== + dependencies: + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/unitless" "^0.8.1" + "@emotion/utils" "^1.2.1" + csstype "^3.0.2" + +"@emotion/sheet@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec" + integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA== + +"@emotion/unitless@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3" + integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ== + +"@emotion/use-insertion-effect-with-fallbacks@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz#08de79f54eb3406f9daaf77c76e35313da963963" + integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw== + +"@emotion/utils@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4" + integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg== + +"@emotion/weak-memoize@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" + integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== + "@erebos/bzz-node@^0.13.0": version "0.13.0" resolved "https://registry.yarnpkg.com/@erebos/bzz-node/-/bzz-node-0.13.0.tgz#495240c8b4fa67fa920c52a2d8db2cf82e673e1a" @@ -2846,6 +3372,26 @@ resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.0.0.tgz#f22824caff3ae506b18207bad4126dbc6ccdb6b8" integrity sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ== +"@floating-ui/core@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.0.tgz#fa41b87812a16bf123122bf945946bae3fdf7fc1" + integrity sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g== + dependencies: + "@floating-ui/utils" "^0.2.1" + +"@floating-ui/dom@^1.0.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.1.tgz#d552e8444f77f2d88534372369b3771dc3a2fa5d" + integrity sha512-iA8qE43/H5iGozC3W0YSnVSW42Vh522yyM1gj+BqRwVsTNOyr231PsXDaV04yT39PsO0QL2QpbI/M0ZaLUQgRQ== + dependencies: + "@floating-ui/core" "^1.6.0" + "@floating-ui/utils" "^0.2.1" + +"@floating-ui/utils@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.1.tgz#16308cea045f0fc777b6ff20a9f25474dd8293d2" + integrity sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q== + "@formatjs/ecma402-abstract@1.11.7": version "1.11.7" resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.7.tgz#47f1a854f679f813d9baa1ee55adae94880ec706" @@ -2916,11 +3462,37 @@ intl-messageformat "10.1.0" tslib "2.4.0" +"@fortawesome/fontawesome-common-types@6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz#fdb1ec4952b689f5f7aa0bffe46180bb35490032" + integrity sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A== + "@fortawesome/fontawesome-free@^5.8.1": version "5.15.4" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz#ecda5712b61ac852c760d8b3c79c96adca5554e5" integrity sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg== +"@fortawesome/fontawesome-svg-core@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz#9d56d46bddad78a7ebb2043a97957039fcebcf0a" + integrity sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ== + dependencies: + "@fortawesome/fontawesome-common-types" "6.5.1" + +"@fortawesome/free-solid-svg-icons@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.1.tgz#737b8d787debe88b400ab7528f47be333031274a" + integrity sha512-S1PPfU3mIJa59biTtXJz1oI0+KAXW6bkAb31XKhxdxtuXDiUIFsih4JR1v5BbxY7hVHsD1RKq+jRkVRaf773NQ== + dependencies: + "@fortawesome/fontawesome-common-types" "6.5.1" + +"@fortawesome/react-fontawesome@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz#d90dd8a9211830b4e3c08e94b63a0ba7291ddcf4" + integrity sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw== + dependencies: + prop-types "^15.8.1" + "@gar/promisify@^1.1.3": version "1.1.3" resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" @@ -2935,6 +3507,444 @@ semiver "^1.1.0" ws "^8.13.0" +"@graphql-codegen/add@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/add/-/add-5.0.2.tgz#71b3ae0465a4537172dddb84531b6967ca5545f2" + integrity sha512-ouBkSvMFUhda5VoKumo/ZvsZM9P5ZTyDsI8LW18VxSNWOjrTeLXBWHG8Gfaai0HwhflPtCYVABbriEcOmrRShQ== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.3" + tslib "~2.6.0" + +"@graphql-codegen/cli@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/cli/-/cli-5.0.2.tgz#07ff691c16da4c3dcc0e1995d3231530379ab317" + integrity sha512-MBIaFqDiLKuO4ojN6xxG9/xL9wmfD3ZjZ7RsPjwQnSHBCUXnEkdKvX+JVpx87Pq29Ycn8wTJUguXnTZ7Di0Mlw== + dependencies: + "@babel/generator" "^7.18.13" + "@babel/template" "^7.18.10" + "@babel/types" "^7.18.13" + "@graphql-codegen/client-preset" "^4.2.2" + "@graphql-codegen/core" "^4.0.2" + "@graphql-codegen/plugin-helpers" "^5.0.3" + "@graphql-tools/apollo-engine-loader" "^8.0.0" + "@graphql-tools/code-file-loader" "^8.0.0" + "@graphql-tools/git-loader" "^8.0.0" + "@graphql-tools/github-loader" "^8.0.0" + "@graphql-tools/graphql-file-loader" "^8.0.0" + "@graphql-tools/json-file-loader" "^8.0.0" + "@graphql-tools/load" "^8.0.0" + "@graphql-tools/prisma-loader" "^8.0.0" + "@graphql-tools/url-loader" "^8.0.0" + "@graphql-tools/utils" "^10.0.0" + "@whatwg-node/fetch" "^0.8.0" + chalk "^4.1.0" + cosmiconfig "^8.1.3" + debounce "^1.2.0" + detect-indent "^6.0.0" + graphql-config "^5.0.2" + inquirer "^8.0.0" + is-glob "^4.0.1" + jiti "^1.17.1" + json-to-pretty-yaml "^1.2.2" + listr2 "^4.0.5" + log-symbols "^4.0.0" + micromatch "^4.0.5" + shell-quote "^1.7.3" + string-env-interpolation "^1.0.1" + ts-log "^2.2.3" + tslib "^2.4.0" + yaml "^2.3.1" + yargs "^17.0.0" + +"@graphql-codegen/client-preset@^4.2.2", "@graphql-codegen/client-preset@^4.2.4": + version "4.2.4" + resolved "https://registry.yarnpkg.com/@graphql-codegen/client-preset/-/client-preset-4.2.4.tgz#a20e85b07b77282bb27b2e8e014bed5d491443e7" + integrity sha512-k1c8v2YxJhhITGQGxViG9asLAoop9m7X9duU7Zztqjc98ooxsUzXICfvAWsH3mLAUibXAx4Ax6BPzKsTtQmBPg== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/template" "^7.20.7" + "@graphql-codegen/add" "^5.0.2" + "@graphql-codegen/gql-tag-operations" "4.0.6" + "@graphql-codegen/plugin-helpers" "^5.0.3" + "@graphql-codegen/typed-document-node" "^5.0.6" + "@graphql-codegen/typescript" "^4.0.6" + "@graphql-codegen/typescript-operations" "^4.2.0" + "@graphql-codegen/visitor-plugin-common" "^5.1.0" + "@graphql-tools/documents" "^1.0.0" + "@graphql-tools/utils" "^10.0.0" + "@graphql-typed-document-node/core" "3.2.0" + tslib "~2.6.0" + +"@graphql-codegen/core@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/core/-/core-4.0.2.tgz#7e6ec266276f54bbf02f60599d9e518f4a59d85e" + integrity sha512-IZbpkhwVqgizcjNiaVzNAzm/xbWT6YnGgeOLwVjm4KbJn3V2jchVtuzHH09G5/WkkLSk2wgbXNdwjM41JxO6Eg== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.3" + "@graphql-tools/schema" "^10.0.0" + "@graphql-tools/utils" "^10.0.0" + tslib "~2.6.0" + +"@graphql-codegen/gql-tag-operations@4.0.6": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@graphql-codegen/gql-tag-operations/-/gql-tag-operations-4.0.6.tgz#d16ee0306cfdea60217c025a1bc21649452d7da3" + integrity sha512-y6iXEDpDNjwNxJw3WZqX1/Znj0QHW7+y8O+t2V8qvbTT+3kb2lr9ntc8By7vCr6ctw9tXI4XKaJgpTstJDOwFA== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.3" + "@graphql-codegen/visitor-plugin-common" "5.1.0" + "@graphql-tools/utils" "^10.0.0" + auto-bind "~4.0.0" + tslib "~2.6.0" + +"@graphql-codegen/plugin-helpers@^5.0.3": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.0.3.tgz#7027b9d911d7cb594663590fcf5d63e9cf7ec2ff" + integrity sha512-yZ1rpULIWKBZqCDlvGIJRSyj1B2utkEdGmXZTBT/GVayP4hyRYlkd36AJV/LfEsVD8dnsKL5rLz2VTYmRNlJ5Q== + dependencies: + "@graphql-tools/utils" "^10.0.0" + change-case-all "1.0.15" + common-tags "1.8.2" + import-from "4.0.0" + lodash "~4.17.0" + tslib "~2.6.0" + +"@graphql-codegen/schema-ast@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@graphql-codegen/schema-ast/-/schema-ast-4.0.2.tgz#aeaa104e4555cca73a058f0a9350b4b0e290b377" + integrity sha512-5mVAOQQK3Oz7EtMl/l3vOQdc2aYClUzVDHHkMvZlunc+KlGgl81j8TLa+X7ANIllqU4fUEsQU3lJmk4hXP6K7Q== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.3" + "@graphql-tools/utils" "^10.0.0" + tslib "~2.6.0" + +"@graphql-codegen/typed-document-node@^5.0.6": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typed-document-node/-/typed-document-node-5.0.6.tgz#54750f4a7c6e963defeb6c27a9ea280a2a8bc2a3" + integrity sha512-US0J95hOE2/W/h42w4oiY+DFKG7IetEN1mQMgXXeat1w6FAR5PlIz4JrRrEkiVfVetZ1g7K78SOwBD8/IJnDiA== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.3" + "@graphql-codegen/visitor-plugin-common" "5.1.0" + auto-bind "~4.0.0" + change-case-all "1.0.15" + tslib "~2.6.0" + +"@graphql-codegen/typescript-operations@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-operations/-/typescript-operations-4.2.0.tgz#0c6bbaf41cb325809b7e9e2b9d85ab01f11d142f" + integrity sha512-lmuwYb03XC7LNRS8oo9M4/vlOrq/wOKmTLBHlltK2YJ1BO/4K/Q9Jdv/jDmJpNydHVR1fmeF4wAfsIp1f9JibA== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.3" + "@graphql-codegen/typescript" "^4.0.6" + "@graphql-codegen/visitor-plugin-common" "5.1.0" + auto-bind "~4.0.0" + tslib "~2.6.0" + +"@graphql-codegen/typescript@^4.0.6": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript/-/typescript-4.0.6.tgz#2c9b70dc1eafda912de5e31c119c757b1aa5fca1" + integrity sha512-IBG4N+Blv7KAL27bseruIoLTjORFCT3r+QYyMC3g11uY3/9TPpaUyjSdF70yBe5GIQ6dAgDU+ENUC1v7EPi0rw== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.3" + "@graphql-codegen/schema-ast" "^4.0.2" + "@graphql-codegen/visitor-plugin-common" "5.1.0" + auto-bind "~4.0.0" + tslib "~2.6.0" + +"@graphql-codegen/visitor-plugin-common@5.1.0", "@graphql-codegen/visitor-plugin-common@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-5.1.0.tgz#4edf7edb53460e71762a5fd8bbf5269bc3d9200b" + integrity sha512-eamQxtA9bjJqI2lU5eYoA1GbdMIRT2X8m8vhWYsVQVWD3qM7sx/IqJU0kx0J3Vd4/CSd36BzL6RKwksibytDIg== + dependencies: + "@graphql-codegen/plugin-helpers" "^5.0.3" + "@graphql-tools/optimize" "^2.0.0" + "@graphql-tools/relay-operation-optimizer" "^7.0.0" + "@graphql-tools/utils" "^10.0.0" + auto-bind "~4.0.0" + change-case-all "1.0.15" + dependency-graph "^0.11.0" + graphql-tag "^2.11.0" + parse-filepath "^1.0.2" + tslib "~2.6.0" + +"@graphql-tools/apollo-engine-loader@^8.0.0": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-8.0.1.tgz#1ec8718af6130ff8039cd653991412472cdd7e55" + integrity sha512-NaPeVjtrfbPXcl+MLQCJLWtqe2/E4bbAqcauEOQ+3sizw1Fc2CNmhHRF8a6W4D0ekvTRRXAMptXYgA2uConbrA== + dependencies: + "@ardatan/sync-fetch" "^0.0.1" + "@graphql-tools/utils" "^10.0.13" + "@whatwg-node/fetch" "^0.9.0" + tslib "^2.4.0" + +"@graphql-tools/batch-execute@^9.0.4": + version "9.0.4" + resolved "https://registry.yarnpkg.com/@graphql-tools/batch-execute/-/batch-execute-9.0.4.tgz#11601409c0c33491971fc82592de12390ec58be2" + integrity sha512-kkebDLXgDrep5Y0gK1RN3DMUlLqNhg60OAz0lTCqrYeja6DshxLtLkj+zV4mVbBA4mQOEoBmw6g1LZs3dA84/w== + dependencies: + "@graphql-tools/utils" "^10.0.13" + dataloader "^2.2.2" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/code-file-loader@^8.0.0": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/code-file-loader/-/code-file-loader-8.1.1.tgz#517c37d4f8a20b2c6558b10cbe9a6f9bcfe98918" + integrity sha512-q4KN25EPSUztc8rA8YUU3ufh721Yk12xXDbtUA+YstczWS7a1RJlghYMFEfR1HsHSYbF7cUqkbnTKSGM3o52bQ== + dependencies: + "@graphql-tools/graphql-tag-pluck" "8.3.0" + "@graphql-tools/utils" "^10.0.13" + globby "^11.0.3" + tslib "^2.4.0" + unixify "^1.0.0" + +"@graphql-tools/delegate@^10.0.4": + version "10.0.4" + resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-10.0.4.tgz#7c38240f11e42ec2dd45d0a569ca6433ce4cb8dc" + integrity sha512-WswZRbQZMh/ebhc8zSomK9DIh6Pd5KbuiMsyiKkKz37TWTrlCOe+4C/fyrBFez30ksq6oFyCeSKMwfrCbeGo0Q== + dependencies: + "@graphql-tools/batch-execute" "^9.0.4" + "@graphql-tools/executor" "^1.2.1" + "@graphql-tools/schema" "^10.0.3" + "@graphql-tools/utils" "^10.0.13" + dataloader "^2.2.2" + tslib "^2.5.0" + +"@graphql-tools/documents@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/documents/-/documents-1.0.0.tgz#e3ed97197cc22ec830ca227fd7d17e86d8424bdf" + integrity sha512-rHGjX1vg/nZ2DKqRGfDPNC55CWZBMldEVcH+91BThRa6JeT80NqXknffLLEZLRUxyikCfkwMsk6xR3UNMqG0Rg== + dependencies: + lodash.sortby "^4.7.0" + tslib "^2.4.0" + +"@graphql-tools/executor-graphql-ws@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/executor-graphql-ws/-/executor-graphql-ws-1.1.2.tgz#2bf959d2319692460b39400c0fe1515dfbb9f034" + integrity sha512-+9ZK0rychTH1LUv4iZqJ4ESbmULJMTsv3XlFooPUngpxZkk00q6LqHKJRrsLErmQrVaC7cwQCaRBJa0teK17Lg== + dependencies: + "@graphql-tools/utils" "^10.0.13" + "@types/ws" "^8.0.0" + graphql-ws "^5.14.0" + isomorphic-ws "^5.0.0" + tslib "^2.4.0" + ws "^8.13.0" + +"@graphql-tools/executor-http@^1.0.9": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@graphql-tools/executor-http/-/executor-http-1.0.9.tgz#87ca8b99a32241eb0cc30a9c500d2672e92d58b7" + integrity sha512-+NXaZd2MWbbrWHqU4EhXcrDbogeiCDmEbrAN+rMn4Nu2okDjn2MTFDbTIab87oEubQCH4Te1wDkWPKrzXup7+Q== + dependencies: + "@graphql-tools/utils" "^10.0.13" + "@repeaterjs/repeater" "^3.0.4" + "@whatwg-node/fetch" "^0.9.0" + extract-files "^11.0.0" + meros "^1.2.1" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/executor-legacy-ws@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@graphql-tools/executor-legacy-ws/-/executor-legacy-ws-1.0.6.tgz#4ed311b731db8fd5c99e66a66361afbf9c2109fc" + integrity sha512-lDSxz9VyyquOrvSuCCnld3256Hmd+QI2lkmkEv7d4mdzkxkK4ddAWW1geQiWrQvWmdsmcnGGlZ7gDGbhEExwqg== + dependencies: + "@graphql-tools/utils" "^10.0.13" + "@types/ws" "^8.0.0" + isomorphic-ws "^5.0.0" + tslib "^2.4.0" + ws "^8.15.0" + +"@graphql-tools/executor@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/executor/-/executor-1.2.1.tgz#9aa132ac1839679fbd14810f7ad8a65e82c0db44" + integrity sha512-BP5UI1etbNOXmTSt7q4NL1+zsURFgh2pG+Hyt9K/xO0LlsfbSx59L5dHLerqZP7Js0xI6GYqrUQ4m29rUwUHJg== + dependencies: + "@graphql-tools/utils" "^10.0.13" + "@graphql-typed-document-node/core" "3.2.0" + "@repeaterjs/repeater" "^3.0.4" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/git-loader@^8.0.0": + version "8.0.5" + resolved "https://registry.yarnpkg.com/@graphql-tools/git-loader/-/git-loader-8.0.5.tgz#77f9c2a35fdb3a403d33660ed11702720d4b016e" + integrity sha512-P97/1mhruDiA6D5WUmx3n/aeGPLWj2+4dpzDOxFGGU+z9NcI/JdygMkeFpGZNHeJfw+kHfxgPcMPnxHcyhAoVA== + dependencies: + "@graphql-tools/graphql-tag-pluck" "8.3.0" + "@graphql-tools/utils" "^10.0.13" + is-glob "4.0.3" + micromatch "^4.0.4" + tslib "^2.4.0" + unixify "^1.0.0" + +"@graphql-tools/github-loader@^8.0.0": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/github-loader/-/github-loader-8.0.1.tgz#011e1f9495d42a55139a12f576cc6bb04943ecf4" + integrity sha512-W4dFLQJ5GtKGltvh/u1apWRFKBQOsDzFxO9cJkOYZj1VzHCpRF43uLST4VbCfWve+AwBqOuKr7YgkHoxpRMkcg== + dependencies: + "@ardatan/sync-fetch" "^0.0.1" + "@graphql-tools/executor-http" "^1.0.9" + "@graphql-tools/graphql-tag-pluck" "^8.0.0" + "@graphql-tools/utils" "^10.0.13" + "@whatwg-node/fetch" "^0.9.0" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/graphql-file-loader@^8.0.0": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-file-loader/-/graphql-file-loader-8.0.1.tgz#03869b14cb91d0ef539df8195101279bb2df9c9e" + integrity sha512-7gswMqWBabTSmqbaNyWSmRRpStWlcCkBc73E6NZNlh4YNuiyKOwbvSkOUYFOqFMfEL+cFsXgAvr87Vz4XrYSbA== + dependencies: + "@graphql-tools/import" "7.0.1" + "@graphql-tools/utils" "^10.0.13" + globby "^11.0.3" + tslib "^2.4.0" + unixify "^1.0.0" + +"@graphql-tools/graphql-tag-pluck@8.3.0", "@graphql-tools/graphql-tag-pluck@^8.0.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-8.3.0.tgz#11bb8c627253137b39b34fb765cd6ebe506388b9" + integrity sha512-gNqukC+s7iHC7vQZmx1SEJQmLnOguBq+aqE2zV2+o1hxkExvKqyFli1SY/9gmukFIKpKutCIj+8yLOM+jARutw== + dependencies: + "@babel/core" "^7.22.9" + "@babel/parser" "^7.16.8" + "@babel/plugin-syntax-import-assertions" "^7.20.0" + "@babel/traverse" "^7.16.8" + "@babel/types" "^7.16.8" + "@graphql-tools/utils" "^10.0.13" + tslib "^2.4.0" + +"@graphql-tools/import@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/import/-/import-7.0.1.tgz#4e0d181c63350b1c926ae91b84a4cbaf03713c2c" + integrity sha512-935uAjAS8UAeXThqHfYVr4HEAp6nHJ2sximZKO1RzUTq5WoALMAhhGARl0+ecm6X+cqNUwIChJbjtaa6P/ML0w== + dependencies: + "@graphql-tools/utils" "^10.0.13" + resolve-from "5.0.0" + tslib "^2.4.0" + +"@graphql-tools/json-file-loader@^8.0.0": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/json-file-loader/-/json-file-loader-8.0.1.tgz#3fcfe869f22d8129a74369da69bf491c0bff7c2d" + integrity sha512-lAy2VqxDAHjVyqeJonCP6TUemrpYdDuKt25a10X6zY2Yn3iFYGnuIDQ64cv3ytyGY6KPyPB+Kp+ZfOkNDG3FQA== + dependencies: + "@graphql-tools/utils" "^10.0.13" + globby "^11.0.3" + tslib "^2.4.0" + unixify "^1.0.0" + +"@graphql-tools/load@^8.0.0": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/load/-/load-8.0.2.tgz#47d9916bf96dea05df27f11b53812f4327d9b6d2" + integrity sha512-S+E/cmyVmJ3CuCNfDuNF2EyovTwdWfQScXv/2gmvJOti2rGD8jTt9GYVzXaxhblLivQR9sBUCNZu/w7j7aXUCA== + dependencies: + "@graphql-tools/schema" "^10.0.3" + "@graphql-tools/utils" "^10.0.13" + p-limit "3.1.0" + tslib "^2.4.0" + +"@graphql-tools/merge@^9.0.0", "@graphql-tools/merge@^9.0.3": + version "9.0.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-9.0.3.tgz#4d0b467132e6f788b69fab803d31480b8ce4b61a" + integrity sha512-FeKv9lKLMwqDu0pQjPpF59GY3HReUkWXKsMIuMuJQOKh9BETu7zPEFUELvcw8w+lwZkl4ileJsHXC9+AnsT2Lw== + dependencies: + "@graphql-tools/utils" "^10.0.13" + tslib "^2.4.0" + +"@graphql-tools/optimize@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/optimize/-/optimize-2.0.0.tgz#7a9779d180824511248a50c5a241eff6e7a2d906" + integrity sha512-nhdT+CRGDZ+bk68ic+Jw1OZ99YCDIKYA5AlVAnBHJvMawSx9YQqQAIj4refNc1/LRieGiuWvhbG3jvPVYho0Dg== + dependencies: + tslib "^2.4.0" + +"@graphql-tools/prisma-loader@^8.0.0": + version "8.0.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/prisma-loader/-/prisma-loader-8.0.3.tgz#a41acb41629cf5327834bedd259939024cf774ba" + integrity sha512-oZhxnMr3Jw2WAW1h9FIhF27xWzIB7bXWM8olz4W12oII4NiZl7VRkFw9IT50zME2Bqi9LGh9pkmMWkjvbOpl+Q== + dependencies: + "@graphql-tools/url-loader" "^8.0.2" + "@graphql-tools/utils" "^10.0.13" + "@types/js-yaml" "^4.0.0" + "@types/json-stable-stringify" "^1.0.32" + "@whatwg-node/fetch" "^0.9.0" + chalk "^4.1.0" + debug "^4.3.1" + dotenv "^16.0.0" + graphql-request "^6.0.0" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.0" + jose "^5.0.0" + js-yaml "^4.0.0" + json-stable-stringify "^1.0.1" + lodash "^4.17.20" + scuid "^1.1.0" + tslib "^2.4.0" + yaml-ast-parser "^0.0.43" + +"@graphql-tools/relay-operation-optimizer@^7.0.0": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-7.0.1.tgz#8ac33e1d2626b6816d9283769c4a05c062b8065a" + integrity sha512-y0ZrQ/iyqWZlsS/xrJfSir3TbVYJTYmMOu4TaSz6F4FRDTQ3ie43BlKkhf04rC28pnUOS4BO9pDcAo1D30l5+A== + dependencies: + "@ardatan/relay-compiler" "12.0.0" + "@graphql-tools/utils" "^10.0.13" + tslib "^2.4.0" + +"@graphql-tools/schema@^10.0.0", "@graphql-tools/schema@^10.0.3": + version "10.0.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-10.0.3.tgz#48c14be84cc617c19c4c929258672b6ab01768de" + integrity sha512-p28Oh9EcOna6i0yLaCFOnkcBDQECVf3SCexT6ktb86QNj9idnkhI+tCxnwZDh58Qvjd2nURdkbevvoZkvxzCog== + dependencies: + "@graphql-tools/merge" "^9.0.3" + "@graphql-tools/utils" "^10.0.13" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/url-loader@^8.0.0", "@graphql-tools/url-loader@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/url-loader/-/url-loader-8.0.2.tgz#ee8e10a85d82c72662f6bc6bbc7b408510a36ebd" + integrity sha512-1dKp2K8UuFn7DFo1qX5c1cyazQv2h2ICwA9esHblEqCYrgf69Nk8N7SODmsfWg94OEaI74IqMoM12t7eIGwFzQ== + dependencies: + "@ardatan/sync-fetch" "^0.0.1" + "@graphql-tools/delegate" "^10.0.4" + "@graphql-tools/executor-graphql-ws" "^1.1.2" + "@graphql-tools/executor-http" "^1.0.9" + "@graphql-tools/executor-legacy-ws" "^1.0.6" + "@graphql-tools/utils" "^10.0.13" + "@graphql-tools/wrap" "^10.0.2" + "@types/ws" "^8.0.0" + "@whatwg-node/fetch" "^0.9.0" + isomorphic-ws "^5.0.0" + tslib "^2.4.0" + value-or-promise "^1.0.11" + ws "^8.12.0" + +"@graphql-tools/utils@^10.0.0", "@graphql-tools/utils@^10.0.13": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-10.1.0.tgz#d8c23a8b8636a5df59b14991bf25eae5ac15d314" + integrity sha512-wLPqhgeZ9BZJPRoaQbsDN/CtJDPd/L4qmmtPkjI3NuYJ39x+Eqz1Sh34EAGMuDh+xlOHqBwHczkZUpoK9tvzjw== + dependencies: + "@graphql-typed-document-node/core" "^3.1.1" + cross-inspect "1.0.0" + dset "^3.1.2" + tslib "^2.4.0" + +"@graphql-tools/wrap@^10.0.2": + version "10.0.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/wrap/-/wrap-10.0.2.tgz#87f510b5f35db2771e7743bc3d71059ee4adaf09" + integrity sha512-nb/YjBcyF02KBCy3hiyw0nBKIC+qkiDY/tGMCcIe4pM6BPEcnreaPhXA28Rdge7lKtySF4Mhbc86XafFH5bIkQ== + dependencies: + "@graphql-tools/delegate" "^10.0.4" + "@graphql-tools/schema" "^10.0.3" + "@graphql-tools/utils" "^10.0.13" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-typed-document-node/core@3.2.0", "@graphql-typed-document-node/core@^3.1.1", "@graphql-typed-document-node/core@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" + integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== + "@humanwhocodes/config-array@^0.11.10": version "0.11.10" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" @@ -3266,6 +4276,11 @@ dependencies: glob-to-regexp "^0.4.1" +"@kamilkisiela/fast-url-parser@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@kamilkisiela/fast-url-parser/-/fast-url-parser-1.1.4.tgz#9d68877a489107411b953c54ea65d0658b515809" + integrity sha512-gbkePEBupNydxCelHCESvFSFM8XPh1Zs/OAVRW/rKpEqPAl5PbOM90Si8mv9bvnR53uPD2s/FiRxdvSejpRJew== + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" @@ -5222,6 +6237,33 @@ "@parcel/watcher-win32-ia32" "2.4.0" "@parcel/watcher-win32-x64" "2.4.0" +"@peculiar/asn1-schema@^2.3.8": + version "2.3.8" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.3.8.tgz#04b38832a814e25731232dd5be883460a156da3b" + integrity sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA== + dependencies: + asn1js "^3.0.5" + pvtsutils "^1.3.5" + tslib "^2.6.2" + +"@peculiar/json-schema@^1.1.12": + version "1.1.12" + resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.12.tgz#fe61e85259e3b5ba5ad566cb62ca75b3d3cd5339" + integrity sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w== + dependencies: + tslib "^2.0.0" + +"@peculiar/webcrypto@^1.4.0": + version "1.4.5" + resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.4.5.tgz#424bed6b0d133b772f5cbffd143d0468a90f40a0" + integrity sha512-oDk93QCDGdxFRM8382Zdminzs44dg3M2+E5Np+JWkpqLDyJC9DviMh8F8mEJkYuUcUOGA5jHO5AJJ10MFWdbZw== + dependencies: + "@peculiar/asn1-schema" "^2.3.8" + "@peculiar/json-schema" "^1.1.12" + pvtsutils "^1.3.5" + tslib "^2.6.2" + webcrypto-core "^1.7.8" + "@phenomnomnominal/tsquery@4.1.1": version "4.1.1" resolved "https://registry.yarnpkg.com/@phenomnomnominal/tsquery/-/tsquery-4.1.1.tgz#42971b83590e9d853d024ddb04a18085a36518df" @@ -5443,6 +6485,11 @@ "@remixproject/plugin-utils" "0.3.42" events "3.2.0" +"@repeaterjs/repeater@^3.0.4": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.5.tgz#b77571685410217a548a9c753aa3cdfc215bfc78" + integrity sha512-l3YHBLAol6d/IKnB9LhpD0cEZWAoe3eFKUyTYWmFmCO2Q/WOckxLQAUyMZWwZV2M/m3+4vgRoaolFqaII82/TA== + "@restart/context@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@restart/context/-/context-2.1.4.tgz#a99d87c299a34c28bd85bb489cb07bfd23149c02" @@ -6324,6 +7371,11 @@ dependencies: "@types/istanbul-lib-report" "*" +"@types/js-yaml@^4.0.0": + version "4.0.9" + resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.9.tgz#cd82382c4f902fed9691a2ed79ec68c5898af4c2" + integrity sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg== + "@types/json-schema@*", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" @@ -6334,6 +7386,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== +"@types/json-stable-stringify@^1.0.32": + version "1.0.36" + resolved "https://registry.yarnpkg.com/@types/json-stable-stringify/-/json-stable-stringify-1.0.36.tgz#fe6c6001a69ff8160a772da08779448a333c7ddd" + integrity sha512-b7bq23s4fgBB76n34m2b3RBf6M369B0Z9uRR8aHTMd8kZISRkmDEpPD8hhpYvDFzr3bJCPES96cm3Q6qRNDbQw== + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" @@ -6550,7 +7607,7 @@ "@types/history" "*" "@types/react" "*" -"@types/react-transition-group@^4.4.1": +"@types/react-transition-group@^4.4.0", "@types/react-transition-group@^4.4.1": version "4.4.10" resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.10.tgz#6ee71127bdab1f18f11ad8fb3322c6da27c327ac" integrity sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q== @@ -6720,6 +7777,13 @@ dependencies: "@types/node" "*" +"@types/ws@^8.0.0": + version "8.5.10" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" + integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== + dependencies: + "@types/node" "*" + "@types/yargs-parser@*": version "20.2.1" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" @@ -7424,6 +8488,92 @@ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== +"@whatwg-node/events@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@whatwg-node/events/-/events-0.0.3.tgz#13a65dd4f5893f55280f766e29ae48074927acad" + integrity sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA== + +"@whatwg-node/events@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@whatwg-node/events/-/events-0.1.1.tgz#0ca718508249419587e130da26d40e29d99b5356" + integrity sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w== + +"@whatwg-node/fetch@^0.8.0": + version "0.8.8" + resolved "https://registry.yarnpkg.com/@whatwg-node/fetch/-/fetch-0.8.8.tgz#48c6ad0c6b7951a73e812f09dd22d75e9fa18cae" + integrity sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg== + dependencies: + "@peculiar/webcrypto" "^1.4.0" + "@whatwg-node/node-fetch" "^0.3.6" + busboy "^1.6.0" + urlpattern-polyfill "^8.0.0" + web-streams-polyfill "^3.2.1" + +"@whatwg-node/fetch@^0.9.0": + version "0.9.16" + resolved "https://registry.yarnpkg.com/@whatwg-node/fetch/-/fetch-0.9.16.tgz#c833eb714f41f5d2caf1a345bed7a05f56db7b16" + integrity sha512-mqasZiUNquRe3ea9+aCAuo81BR6vq5opUKprPilIHTnrg8a21Z1T1OrI+KiMFX8OmwO5HUJe/vro47lpj2JPWQ== + dependencies: + "@whatwg-node/node-fetch" "^0.5.5" + urlpattern-polyfill "^10.0.0" + +"@whatwg-node/node-fetch@^0.3.6": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@whatwg-node/node-fetch/-/node-fetch-0.3.6.tgz#e28816955f359916e2d830b68a64493124faa6d0" + integrity sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA== + dependencies: + "@whatwg-node/events" "^0.0.3" + busboy "^1.6.0" + fast-querystring "^1.1.1" + fast-url-parser "^1.1.3" + tslib "^2.3.1" + +"@whatwg-node/node-fetch@^0.5.5": + version "0.5.6" + resolved "https://registry.yarnpkg.com/@whatwg-node/node-fetch/-/node-fetch-0.5.6.tgz#3ec2044ff66dd78134492b5f2f841bedf1cc73c9" + integrity sha512-cmAsGMHoI0S3AHi3CmD3ma1Q234ZI2JNmXyDyM9rLtbXejBKxU3ZWdhS+mzRIAyUxZCMGlFW1tHmROv0MDdxpw== + dependencies: + "@kamilkisiela/fast-url-parser" "^1.1.4" + "@whatwg-node/events" "^0.1.0" + busboy "^1.6.0" + fast-querystring "^1.1.1" + tslib "^2.3.1" + +"@wry/caches@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@wry/caches/-/caches-1.0.1.tgz#8641fd3b6e09230b86ce8b93558d44cf1ece7e52" + integrity sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA== + dependencies: + tslib "^2.3.0" + +"@wry/context@^0.7.0": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.7.4.tgz#e32d750fa075955c4ab2cfb8c48095e1d42d5990" + integrity sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ== + dependencies: + tslib "^2.3.0" + +"@wry/equality@^0.5.6": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.5.7.tgz#72ec1a73760943d439d56b7b1e9985aec5d497bb" + integrity sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw== + dependencies: + tslib "^2.3.0" + +"@wry/trie@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.4.3.tgz#077d52c22365871bf3ffcbab8e95cb8bc5689af4" + integrity sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w== + dependencies: + tslib "^2.3.0" + +"@wry/trie@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.5.0.tgz#11e783f3a53f6e4cd1d42d2d1323f5bc3fa99c94" + integrity sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA== + dependencies: + tslib "^2.3.0" + "@xenova/transformers@^2.7.0": version "2.7.0" resolved "https://registry.yarnpkg.com/@xenova/transformers/-/transformers-2.7.0.tgz#0aabc8700d32ed8e28f6aa61abf8653f62fb1678" @@ -7657,6 +8807,13 @@ agent-base@6, agent-base@^6.0.2: dependencies: debug "4" +agent-base@^7.0.2, agent-base@^7.1.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" + integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== + dependencies: + debug "^4.3.4" + agent-base@~4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" @@ -8241,6 +9398,15 @@ asn1@~0.2.3: resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" integrity sha512-6i37w/+EhlWlGUJff3T/Q8u1RGmP5wgbiwYnOnbOqvtrPxT63/sYFyP9RcpxtxGymtfA075IvmOnL7ycNOWl3w== +asn1js@^3.0.1, asn1js@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.5.tgz#5ea36820443dbefb51cc7f88a2ebb5b462114f38" + integrity sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ== + dependencies: + pvtsutils "^1.3.2" + pvutils "^1.1.3" + tslib "^2.4.0" + assert-plus@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" @@ -8373,6 +9539,11 @@ author-regex@^1.0.0: resolved "https://registry.yarnpkg.com/author-regex/-/author-regex-1.0.0.tgz#d08885be6b9bbf9439fe087c76287245f0a81450" integrity sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g== +auto-bind@~4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb" + integrity sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ== + autoprefixer@^10.4.9: version "10.4.12" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.12.tgz#183f30bf0b0722af54ee5ef257f7d4320bb33129" @@ -8693,6 +9864,15 @@ babel-plugin-macros@^2.8.0: cosmiconfig "^6.0.0" resolve "^1.12.0" +babel-plugin-macros@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" + integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== + dependencies: + "@babel/runtime" "^7.12.5" + cosmiconfig "^7.0.0" + resolve "^1.19.0" + babel-plugin-module-resolver@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz#22a4f32f7441727ec1fbf4967b863e1e3e9f33e2" @@ -8758,6 +9938,11 @@ babel-plugin-syntax-trailing-function-commas@^6.22.0: resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" integrity sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ== +babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: + version "7.0.0-beta.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" + integrity sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ== + babel-plugin-syntax-typescript@7.0.0-alpha.19: version "7.0.0-alpha.19" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-typescript/-/babel-plugin-syntax-typescript-7.0.0-alpha.19.tgz#fc5876863db297549f5d840d248eac3310241f84" @@ -9067,6 +10252,39 @@ babel-preset-env@^1.7.0: invariant "^2.2.2" semver "^5.3.0" +babel-preset-fbjs@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz#38a14e5a7a3b285a3f3a86552d650dca5cf6111c" + integrity sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow== + dependencies: + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/plugin-syntax-class-properties" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-block-scoped-functions" "^7.0.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-for-of" "^7.0.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-member-expression-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-object-super" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-property-literals" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-template-literals" "^7.0.0" + babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" + babel-preset-jest@^28.1.3: version "28.1.3" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-28.1.3.tgz#5dfc20b99abed5db994406c2b9ab94c73aaa419d" @@ -9774,6 +10992,16 @@ browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4 node-releases "^2.0.6" update-browserslist-db "^1.0.9" +browserslist@^4.22.2: + version "4.23.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" + integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== + dependencies: + caniuse-lite "^1.0.30001587" + electron-to-chromium "^1.4.668" + node-releases "^2.0.14" + update-browserslist-db "^1.0.13" + bs58@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" @@ -9920,6 +11148,13 @@ builtins@^1.0.3: resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ== +busboy@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + byline@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" @@ -10190,6 +11425,11 @@ caniuse-lite@^1.0.30001400: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001412.tgz#30f67d55a865da43e0aeec003f073ea8764d5d7c" integrity sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA== +caniuse-lite@^1.0.30001587: + version "1.0.30001589" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001589.tgz#7ad6dba4c9bf6561aec8291976402339dc157dfb" + integrity sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg== + canvg@^3.0.6: version "3.0.10" resolved "https://registry.yarnpkg.com/canvg/-/canvg-3.0.10.tgz#8e52a2d088b6ffa23ac78970b2a9eebfae0ef4b3" @@ -10306,7 +11546,7 @@ chalk@^2.0.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4 escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2: +chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -10314,7 +11554,23 @@ chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -change-case@^4.1.1: +change-case-all@1.0.15: + version "1.0.15" + resolved "https://registry.yarnpkg.com/change-case-all/-/change-case-all-1.0.15.tgz#de29393167fc101d646cd76b0ef23e27d09756ad" + integrity sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ== + dependencies: + change-case "^4.1.2" + is-lower-case "^2.0.2" + is-upper-case "^2.0.2" + lower-case "^2.0.2" + lower-case-first "^2.0.2" + sponge-case "^1.0.1" + swap-case "^2.0.2" + title-case "^3.0.3" + upper-case "^2.0.2" + upper-case-first "^2.0.2" + +change-case@^4.1.1, change-case@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" integrity sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A== @@ -10670,6 +11926,11 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + clipboardy@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-4.0.0.tgz#e73ced93a76d19dd379ebf1f297565426dffdca1" @@ -10928,7 +12189,7 @@ colorette@^2.0.10, colorette@^2.0.14: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== -colorette@^2.0.19: +colorette@^2.0.16, colorette@^2.0.19: version "2.0.20" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== @@ -11045,6 +12306,11 @@ common-path-prefix@^3.0.0: resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w== +common-tags@1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" + integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -11312,6 +12578,11 @@ convert-source-map@^1.4.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + convert-source-map@~1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" @@ -11499,6 +12770,16 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" +cosmiconfig@^8.1.0, cosmiconfig@^8.1.3: + version "8.3.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== + dependencies: + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + path-type "^4.0.0" + crc-32@^1.2.0, crc-32@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" @@ -11576,6 +12857,13 @@ cross-fetch@^4.0.0: dependencies: node-fetch "^2.6.12" +cross-inspect@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cross-inspect/-/cross-inspect-1.0.0.tgz#5fda1af759a148594d2d58394a9e21364f6849af" + integrity sha512-4PFfn4b5ZN6FMNGSZlyb7wUhuN8wvj8t/VQHZdM4JsDcruGJ8L2kf9zao98QIrBPFCpdk27qst/AGTl7pL3ypQ== + dependencies: + tslib "^2.4.0" + cross-spawn-async@^2.1.1: version "2.2.5" resolved "https://registry.yarnpkg.com/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz#845ff0c0834a3ded9d160daca6d390906bb288cc" @@ -11999,6 +13287,11 @@ data-uri-to-buffer@^3.0.1: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== +dataloader@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.2.2.tgz#216dc509b5abe39d43a9b9d97e6e5e473dfbe3e0" + integrity sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g== + dateformat@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" @@ -12017,6 +13310,11 @@ deasync@^0.1.9: bindings "^1.5.0" node-addon-api "^1.7.1" +debounce@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" + integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -12333,6 +13631,11 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= +dependency-graph@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27" + integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg== + deprecation@^2.0.0, deprecation@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" @@ -12386,6 +13689,11 @@ detect-indent@^5.0.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= +detect-indent@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" + integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== + detect-libc@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" @@ -12678,6 +13986,11 @@ dotenv@10.0.0, dotenv@~10.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== +dotenv@^16.0.0: + version "16.4.5" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" + integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== + dotenv@^8.2.0: version "8.6.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" @@ -12690,6 +14003,11 @@ dotignore@~0.1.2: dependencies: minimatch "^3.0.4" +dset@^3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.3.tgz#c194147f159841148e8e34ca41f638556d9542d2" + integrity sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ== + duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" @@ -12834,6 +14152,11 @@ electron-to-chromium@^1.4.251: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.264.tgz#2f68a062c38b7a04bf57f3e6954b868672fbdcd3" integrity sha512-AZ6ZRkucHOQT8wke50MktxtmcWZr67kE17X/nAXFf62NIdMdgY6xfsaJD5Szoy84lnkuPWH+4tTNE3s2+bPCiw== +electron-to-chromium@^1.4.668: + version "1.4.681" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.681.tgz#5f23fad8aa7e1f64cbb7dd9d15c7e39a1cd7e6e3" + integrity sha512-1PpuqJUFWoXZ1E54m8bsLPVYwIVCRzvaL+n5cjigGga4z854abDnFRc+cTa2th4S79kyGqya/1xoR7h+Y5G5lg== + electron@^24.4.0: version "24.4.0" resolved "https://registry.yarnpkg.com/electron/-/electron-24.4.0.tgz#48d05561dab6a5835ec1a3a96852797f69824eea" @@ -14114,6 +15437,11 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +extract-files@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-11.0.0.tgz#b72d428712f787eef1f5193aff8ab5351ca8469a" + integrity sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ== + extract-zip@2.0.1, extract-zip@^2.0.0, extract-zip@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" @@ -14151,6 +15479,11 @@ fast-async@^7.0.6: nodent-runtime "^3.2.1" nodent-transform "^3.2.4" +fast-decode-uri-component@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" + integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -14215,6 +15548,13 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-querystring@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fast-querystring/-/fast-querystring-1.1.2.tgz#a6d24937b4fc6f791b4ee31dcb6f53aeafb89f53" + integrity sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg== + dependencies: + fast-decode-uri-component "^1.0.1" + fast-redact@^3.0.0: version "3.3.0" resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.3.0.tgz#7c83ce3a7be4898241a46560d51de10f653f7634" @@ -14230,6 +15570,13 @@ fast-text-encoding@^1.0.0: resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#ec02ac8e01ab8a319af182dae2681213cfe9ce53" integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig== +fast-url-parser@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" + integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== + dependencies: + punycode "^1.3.2" + fastest-levenshtein@^1.0.12: version "1.0.16" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" @@ -14340,7 +15687,7 @@ figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== -figures@3.2.0: +figures@3.2.0, figures@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== @@ -14497,6 +15844,11 @@ find-cache-dir@^3.3.2: make-dir "^3.0.2" pkg-dir "^4.1.0" +find-root@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -15608,7 +16960,7 @@ globby@10.0.1: merge2 "^1.2.3" slash "^3.0.0" -globby@^11.1.0: +globby@^11.0.3, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -15737,6 +17089,48 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +graphql-config@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/graphql-config/-/graphql-config-5.0.3.tgz#d9aa2954cf47a927f9cb83cdc4e42ae55d0b321e" + integrity sha512-BNGZaoxIBkv9yy6Y7omvsaBUHOzfFcII3UN++tpH8MGOKFPFkCPZuwx09ggANMt8FgyWP1Od8SWPmrUEZca4NQ== + dependencies: + "@graphql-tools/graphql-file-loader" "^8.0.0" + "@graphql-tools/json-file-loader" "^8.0.0" + "@graphql-tools/load" "^8.0.0" + "@graphql-tools/merge" "^9.0.0" + "@graphql-tools/url-loader" "^8.0.0" + "@graphql-tools/utils" "^10.0.0" + cosmiconfig "^8.1.0" + jiti "^1.18.2" + minimatch "^4.2.3" + string-env-interpolation "^1.0.1" + tslib "^2.4.0" + +graphql-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-6.1.0.tgz#f4eb2107967af3c7a5907eb3131c671eac89be4f" + integrity sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw== + dependencies: + "@graphql-typed-document-node/core" "^3.2.0" + cross-fetch "^3.1.5" + +graphql-tag@^2.11.0, graphql-tag@^2.12.6: + version "2.12.6" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" + integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg== + dependencies: + tslib "^2.1.0" + +graphql-ws@^5.14.0: + version "5.15.0" + resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.15.0.tgz#2db79e1b42468a8363bf5ca6168d076e2f8fdebc" + integrity sha512-xWGAtm3fig9TIhSaNsg0FaDZ8Pyn/3re3RFlP4rhQcmjRDIPpk1EhRuNB+YSJtLzttyuToaDiNhwT1OMoGnJnw== + +graphql@^16.8.1: + version "16.8.1" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" + integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw== + growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" @@ -16158,7 +17552,7 @@ hoek@2.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0= -hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -16330,6 +17724,14 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" +http-proxy-agent@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + http-proxy-middleware@^2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" @@ -16429,6 +17831,14 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +https-proxy-agent@^7.0.0: + version "7.0.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz#8e97b841a029ad8ddc8731f26595bad868cb4168" + integrity sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg== + dependencies: + agent-base "^7.0.2" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -16566,6 +17976,11 @@ immutable@^4.0.0-rc.12: resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.4.tgz#83260d50889526b4b531a5e293709a77f7c55a2a" integrity sha512-WDxL3Hheb1JkRN3sQkyujNlL/xRjAo3rJtaU5xeufUauG66JdMr32bLj4gF+vWl84DIA3Zxw7tiAjneYzRRw+w== +immutable@~3.7.6: + version "3.7.6" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b" + integrity sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw== + import-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-3.0.0.tgz#20845547718015126ea9b3676b7592fb8bd4cf92" @@ -16581,7 +17996,7 @@ import-fresh@^2.0.0: caller-path "^2.0.0" resolve-from "^3.0.0" -import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: +import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -16589,6 +18004,11 @@ import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-from@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-4.0.0.tgz#2710b8d66817d232e16f4166e319248d3d5492e2" + integrity sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ== + import-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/import-from/-/import-from-3.0.0.tgz#055cfec38cd5a27d8057ca51376d7d3bf0891966" @@ -16731,6 +18151,27 @@ inquirer@^6.2.0: strip-ansi "^5.1.0" through "^2.3.6" +inquirer@^8.0.0: + version "8.2.6" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.6.tgz#733b74888195d8d400a67ac332011b5fae5ea562" + integrity sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg== + dependencies: + ansi-escapes "^4.2.1" + chalk "^4.1.1" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.21" + mute-stream "0.0.8" + ora "^5.4.1" + run-async "^2.4.0" + rxjs "^7.5.5" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + wrap-ansi "^6.0.1" + insert-css@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/insert-css/-/insert-css-0.2.0.tgz#d15789971662d9899c28977fb6220d5381d2451a" @@ -17277,6 +18718,13 @@ is-generator-function@^1.0.7: dependencies: has-tostringtag "^1.0.0" +is-glob@4.0.3, is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" @@ -17291,13 +18739,6 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - is-hex-prefixed@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" @@ -17327,6 +18768,13 @@ is-lambda@^1.0.1: resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== +is-lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-2.0.2.tgz#1c0884d3012c841556243483aa5d522f47396d2a" + integrity sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ== + dependencies: + tslib "^2.0.3" + is-map@^2.0.1, is-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" @@ -17590,6 +19038,13 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-upper-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-2.0.2.tgz#f1105ced1fe4de906a5f39553e7d3803fd804649" + integrity sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ== + dependencies: + tslib "^2.0.3" + is-utf8@^0.2.0, is-utf8@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" @@ -17707,10 +19162,10 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= -isomorphic-git@^1.25.0: - version "1.25.0" - resolved "https://registry.yarnpkg.com/isomorphic-git/-/isomorphic-git-1.25.0.tgz#3a04d7e70f75ebdbb991f9fa87cfec90e3742c9f" - integrity sha512-F8X7z74gL+jN4bd6qB6a3Z0QQzonWPkiQ3nK/oFWlrc2pIwVM9Uksl3YMFh99ltswsqoCoOthgasybX08/fiGg== +isomorphic-git@^1.25.7: + version "1.25.7" + resolved "https://registry.yarnpkg.com/isomorphic-git/-/isomorphic-git-1.25.7.tgz#f6f6fae81ee67d3982edad8c90ca0f096e39267c" + integrity sha512-KE10ejaIsEpQ+I/apS33qqTjyzCXgOniEaL32DwNbXtboKG8H3cu+RiBcdp3G9w4MpOOTQfGPsWp4i8UxRfDLg== dependencies: async-lock "^1.1.0" clean-git-ref "^2.0.1" @@ -18318,7 +19773,7 @@ jest-worker@^29.1.2: merge-stream "^2.0.0" supports-color "^8.0.0" -jiti@^1.21.0: +jiti@^1.17.1, jiti@^1.18.2, jiti@^1.21.0: version "1.21.0" resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== @@ -18335,6 +19790,11 @@ jodid25519@^1.0.0: dependencies: jsbn "~0.1.0" +jose@^5.0.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/jose/-/jose-5.2.2.tgz#b91170e9ba6dbe609b0c0a86568f9a1fbe4335c0" + integrity sha512-/WByRr4jDcsKlvMd1dRJnPfS1GVO3WuKyaurJ/vvXcOaUQO8rnNObCQMlv/5uCceVQIq5Q4WLF44ohsdiTohdg== + jquery@^3.3.1: version "3.6.0" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470" @@ -18387,7 +19847,7 @@ js-yaml@4.0.0: dependencies: argparse "^2.0.1" -js-yaml@4.1.0, js-yaml@^4.1.0: +js-yaml@4.1.0, js-yaml@^4.0.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -18503,6 +19963,14 @@ json-text-sequence@~0.1.0: dependencies: delimit-stream "0.1.0" +json-to-pretty-yaml@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz#f4cd0bd0a5e8fe1df25aaf5ba118b099fd992d5b" + integrity sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A== + dependencies: + remedial "^1.0.7" + remove-trailing-spaces "^1.0.6" + json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -18515,7 +19983,7 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -json5@^2.1.2, json5@^2.2.1, json5@^2.2.2: +json5@^2.1.2, json5@^2.2.1, json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -19096,6 +20564,20 @@ listhen@^1.5.5: untun "^0.1.3" uqr "^0.1.2" +listr2@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-4.0.5.tgz#9dcc50221583e8b4c71c43f9c7dfd0ef546b75d5" + integrity sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA== + dependencies: + cli-truncate "^2.1.0" + colorette "^2.0.16" + log-update "^4.0.0" + p-map "^4.0.0" + rfdc "^1.3.0" + rxjs "^7.5.5" + through "^2.3.8" + wrap-ansi "^7.0.0" + listr2@^5.0.3, listr2@^5.0.7: version "5.0.8" resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.8.tgz#a9379ffeb4bd83a68931a65fb223a11510d6ba23" @@ -19535,7 +21017,7 @@ lodash.without@~4.4.0: resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw= -lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.2.1: +lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.2.1, lodash@~4.17.0, lodash@~4.17.5: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -19625,6 +21107,13 @@ loupe@^2.3.1: dependencies: get-func-name "^2.0.0" +lower-case-first@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-2.0.2.tgz#64c2324a2250bf7c37c5901e76a5b5309301160b" + integrity sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg== + dependencies: + tslib "^2.0.3" + lower-case@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" @@ -20077,6 +21566,11 @@ memfs@^3.4.1, memfs@^3.4.3: resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== +memoize-one@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" + integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== + memoizee@^0.4.15: version "0.4.15" resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72" @@ -20194,6 +21688,11 @@ merge@^2.1.1: resolved "https://registry.yarnpkg.com/merge/-/merge-2.1.1.tgz#59ef4bf7e0b3e879186436e8481c06a6c162ca98" integrity sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w== +meros@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/meros/-/meros-1.3.0.tgz#c617d2092739d55286bf618129280f362e6242f2" + integrity sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -20657,6 +22156,13 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +minimatch@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.3.tgz#b4dcece1d674dee104bb0fb833ebb85a78cbbca6" + integrity sha512-lIUdtK5hdofgCTu3aT0sOaHsYR37viUuIc0rwnnDXImbwFRcumyLMeZaM0t0I/fgxS6s6JMfu0rLD1Wz9pv1ng== + dependencies: + brace-expansion "^1.1.7" + minimatch@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7" @@ -21198,6 +22704,11 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + mute-stream@~0.0.4: version "0.0.5" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" @@ -21609,6 +23120,11 @@ node-notifier@^4.2.3: shellwords "^0.1.0" which "^1.0.5" +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== + node-releases@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" @@ -22083,6 +23599,11 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" +nullthrows@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" + integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== + number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -22501,6 +24022,16 @@ opener@~1.4.3: resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8" integrity sha1-XG2ixdflgx6P+jlklQ+NZnSskLg= +optimism@^0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.18.0.tgz#e7bb38b24715f3fdad8a9a7fc18e999144bbfa63" + integrity sha512-tGn8+REwLRNFnb9WmcY5IfpOqeX2kpaYJ1s6Ae3mn12AeydLkR3j+jSCmVQFoXqU8D41PAJ1RG1rCRNWmNZVmQ== + dependencies: + "@wry/caches" "^1.0.0" + "@wry/context" "^0.7.0" + "@wry/trie" "^0.4.3" + tslib "^2.3.0" + optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -22538,7 +24069,7 @@ options@>=0.0.5: resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" integrity sha512-bOj3L1ypm++N+n7CEbbe473A414AB7z+amKYshRb//iuL3MpdDCLhPnw6aVTdKB9g5ZRVHIEp8eUln6L2NUStg== -ora@5.4.1, ora@^5.1.0: +ora@5.4.1, ora@^5.1.0, ora@^5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== @@ -22669,6 +24200,13 @@ p-is-promise@^2.0.0: resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== +p-limit@3.1.0, p-limit@^3.0.2, p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -22690,13 +24228,6 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -22890,7 +24421,7 @@ parse-duration@^0.4.4: resolved "https://registry.yarnpkg.com/parse-duration/-/parse-duration-0.4.4.tgz#11c0f51a689e97d06c57bd772f7fda7dc013243c" integrity sha512-KbAJuYGUhZkB9gotDiKLnZ7Z3VTacK3fgwmDdB6ZVDtJbMBT6MfLga0WJaYpPDu0mzqT0NgHtHDt5PY4l0nidg== -parse-filepath@^1.0.1: +parse-filepath@^1.0.1, parse-filepath@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE= @@ -23338,6 +24869,11 @@ plur@^1.0.0: resolved "https://registry.yarnpkg.com/plur/-/plur-1.0.0.tgz#db85c6814f5e5e5a3b49efc28d604fec62975156" integrity sha1-24XGgU9eXlo7Se/CjWBP7GKXUVY= +pluralize@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== + pngjs@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" @@ -23936,7 +25472,7 @@ prop-types-extra@^1.1.0: react-is "^16.3.2" warning "^4.0.0" -prop-types@^15.0.0, prop-types@^15.8.1: +prop-types@^15.0.0, prop-types@^15.6.0, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -24145,6 +25681,18 @@ pure-color@^1.2.0: resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e" integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA== +pvtsutils@^1.3.2, pvtsutils@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.5.tgz#b8705b437b7b134cd7fd858f025a23456f1ce910" + integrity sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA== + dependencies: + tslib "^2.6.1" + +pvutils@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3" + integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ== + q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -24247,6 +25795,15 @@ r1csfile@0.0.45: fastfile "0.0.20" ffjavascript "0.2.57" +ra-data-graphql@^4.16.11: + version "4.16.11" + resolved "https://registry.yarnpkg.com/ra-data-graphql/-/ra-data-graphql-4.16.11.tgz#974e87ea178aec547407372c2c32018333c2ac52" + integrity sha512-mJ1xWYjdgJu8mKwMRZfU/0+ZdLC3y6QES0hpc2kLuVvB2t3OtecYMB0WwfQnyekt+qZ1Chj6sMLtEvUCAZcpkA== + dependencies: + "@apollo/client" "^3.3.19" + lodash "~4.17.5" + pluralize "~7.0.0" + radix3@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/radix3/-/radix3-1.1.0.tgz#9745df67a49c522e94a33d0a93cf743f104b6e0d" @@ -24540,6 +26097,21 @@ react-router@6.21.0: dependencies: "@remix-run/router" "1.14.0" +react-select@^5.8.0: + version "5.8.0" + resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.8.0.tgz#bd5c467a4df223f079dd720be9498076a3f085b5" + integrity sha512-TfjLDo58XrhP6VG5M/Mi56Us0Yt8X7xD6cDybC7yoRMUNm7BGO7qk8J0TLQOua/prb8vUOtsfnXZwfm30HGsAA== + dependencies: + "@babel/runtime" "^7.12.0" + "@emotion/cache" "^11.4.0" + "@emotion/react" "^11.8.1" + "@floating-ui/dom" "^1.0.1" + "@types/react-transition-group" "^4.4.0" + memoize-one "^6.0.0" + prop-types "^15.6.0" + react-transition-group "^4.3.0" + use-isomorphic-layout-effect "^1.1.2" + react-spinners@^0.13.8: version "0.13.8" resolved "https://registry.yarnpkg.com/react-spinners/-/react-spinners-0.13.8.tgz#5262571be0f745d86bbd49a1e6b49f9f9cb19acc" @@ -24569,7 +26141,7 @@ react-toastify@^10.0.3: dependencies: clsx "^2.1.0" -react-transition-group@^4.4.1: +react-transition-group@^4.3.0, react-transition-group@^4.4.1: version "4.4.5" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== @@ -25177,6 +26749,11 @@ regjsparser@^0.9.1: dependencies: jsesc "~0.5.0" +rehackt@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/rehackt/-/rehackt-0.0.5.tgz#184c82ea369d5b0b989ede0593ebea8b2bcfb1d6" + integrity sha512-BI1rV+miEkaHj8zd2n+gaMgzu/fKz7BGlb4zZ6HAiY9adDmJMkaDcmuXlJFv0eyKUob+oszs3/2gdnXUrzx2Tg== + rehype-raw@^6.0.0: version "6.1.1" resolved "https://registry.yarnpkg.com/rehype-raw/-/rehype-raw-6.1.1.tgz#81bbef3793bd7abacc6bf8335879d1b6c868c9d4" @@ -25186,6 +26763,15 @@ rehype-raw@^6.0.0: hast-util-raw "^7.2.0" unified "^10.0.0" +relay-runtime@12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/relay-runtime/-/relay-runtime-12.0.0.tgz#1e039282bdb5e0c1b9a7dc7f6b9a09d4f4ff8237" + integrity sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug== + dependencies: + "@babel/runtime" "^7.0.0" + fbjs "^3.0.0" + invariant "^2.2.4" + release-zalgo@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" @@ -25222,6 +26808,11 @@ remark-rehype@^10.0.0: mdast-util-to-hast "^12.1.0" unified "^10.0.0" +remedial@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/remedial/-/remedial-1.0.8.tgz#a5e4fd52a0e4956adbaf62da63a5a46a78c578a0" + integrity sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg== + remove-bom-buffer@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" @@ -25244,6 +26835,11 @@ remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0: resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= +remove-trailing-spaces@^1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz#4354d22f3236374702f58ee373168f6d6887ada7" + integrity sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA== + repeat-element@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" @@ -25396,6 +26992,11 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1: expand-tilde "^2.0.0" global-modules "^1.0.0" +resolve-from@5.0.0, resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" @@ -25406,11 +27007,6 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - resolve-options@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" @@ -25481,6 +27077,11 @@ resolve@^2.0.0-next.3: is-core-module "^2.2.0" path-parse "^1.0.6" +response-iterator@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/response-iterator/-/response-iterator-0.2.6.tgz#249005fb14d2e4eeb478a3f735a28fd8b4c9f3da" + integrity sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw== + responselike@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" @@ -25695,7 +27296,7 @@ rss-parser@^3.12.0: entities "^2.0.3" xml2js "^0.4.19" -run-async@^2.2.0: +run-async@^2.2.0, run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== @@ -25752,7 +27353,7 @@ rxjs@^6.4.0, rxjs@^6.5.4: dependencies: tslib "^1.9.0" -rxjs@^7.8.0: +rxjs@^7.5.5, rxjs@^7.8.0: version "7.8.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== @@ -25882,6 +27483,11 @@ scrypt-js@3.0.1, scrypt-js@^3.0.0: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== +scuid@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/scuid/-/scuid-1.1.0.tgz#d3f9f920956e737a60f72d0e4ad280bf324d5dab" + integrity sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg== + secp256k1@4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" @@ -25974,6 +27580,11 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semve resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + semver@^7.1.3, semver@^7.2.1, semver@^7.3.2: version "7.5.1" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.1.tgz#c90c4d631cf74720e46b21c1d37ea07edfab91ec" @@ -26207,6 +27818,11 @@ shell-quote@^1.6.1: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== +shell-quote@^1.7.3: + version "1.8.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== + shelljs@^0.7.5: version "0.7.8" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" @@ -26266,6 +27882,11 @@ signed-varint@^2.0.1: dependencies: varint "~5.0.0" +signedsource@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/signedsource/-/signedsource-1.0.0.tgz#1ddace4981798f93bd833973803d80d52e93ad6a" + integrity sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww== + simple-concat@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" @@ -26764,6 +28385,13 @@ split@^1.0.0: dependencies: through "2" +sponge-case@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sponge-case/-/sponge-case-1.0.1.tgz#260833b86453883d974f84854cdb63aecc5aef4c" + integrity sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA== + dependencies: + tslib "^2.0.3" + sprintf-js@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" @@ -26950,6 +28578,11 @@ stream-to-it@^0.2.0, stream-to-it@^0.2.1: dependencies: get-iterator "^1.0.2" +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + streamx@^2.15.0: version "2.15.1" resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.15.1.tgz#396ad286d8bc3eeef8f5cea3f029e81237c024c6" @@ -26968,6 +28601,11 @@ string-argv@^0.3.1: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== +string-env-interpolation@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz#ad4397ae4ac53fe6c91d1402ad6f6a52862c7152" + integrity sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg== + string-hash@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" @@ -27347,6 +28985,11 @@ stylehacks@^5.1.1: browserslist "^4.21.4" postcss-selector-parser "^6.0.4" +stylis@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" + integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== + stylus-loader@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/stylus-loader/-/stylus-loader-7.1.0.tgz#19e09a98b19075c246e6e3f65e38b8cb89d2d6fb" @@ -27494,6 +29137,18 @@ svgpath@^2.3.0: resolved "https://registry.yarnpkg.com/svgpath/-/svgpath-2.6.0.tgz#5b160ef3d742b7dfd2d721bf90588d3450d7a90d" integrity sha512-OIWR6bKzXvdXYyO4DK/UWa1VA1JeKq8E+0ug2DG98Y/vOmMpfZNj+TIG988HjfYSqtcy/hFOtZq/n/j5GSESNg== +swap-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-2.0.2.tgz#671aedb3c9c137e2985ef51c51f9e98445bf70d9" + integrity sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw== + dependencies: + tslib "^2.0.3" + +symbol-observable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205" + integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ== + syntax-error@^1.1.1: version "1.4.0" resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.4.0.tgz#2d9d4ff5c064acb711594a3e3b95054ad51d907c" @@ -27847,6 +29502,13 @@ tiny-warning@^1.0.2: resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== +title-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/title-case/-/title-case-3.0.3.tgz#bc689b46f02e411f1d1e1d081f7c3deca0489982" + integrity sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA== + dependencies: + tslib "^2.0.3" + tmp@0.0.33, tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -28054,6 +29716,13 @@ tryer@^1.0.1: resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== +ts-invariant@^0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.10.3.tgz#3e048ff96e91459ffca01304dbc7f61c1f642f6c" + integrity sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ== + dependencies: + tslib "^2.1.0" + ts-loader@^9.2.6: version "9.2.6" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74" @@ -28074,6 +29743,11 @@ ts-loader@^9.3.1: micromatch "^4.0.0" semver "^7.3.4" +ts-log@^2.2.3: + version "2.2.5" + resolved "https://registry.yarnpkg.com/ts-log/-/ts-log-2.2.5.tgz#aef3252f1143d11047e2cb6f7cfaac7408d96623" + integrity sha512-PGcnJoTBnVGy6yYNFxWVNkdcAuAMstvutN9MgDJIV6L0oG8fB+ZNNy1T+wJzah8RPGor1mZuPQkVfXNDpy9eHA== + ts-node@10.9.1: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" @@ -28151,7 +29825,7 @@ tslib@^2.1.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.2.tgz#1b6f07185c881557b0ffa84b111a0106989e8338" integrity sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA== -tslib@^2.3.1: +tslib@^2.3.1, tslib@^2.5.0, tslib@^2.6.1, tslib@^2.6.2, tslib@~2.6.0: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== @@ -28749,6 +30423,13 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== +unixify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unixify/-/unixify-1.0.0.tgz#3a641c8c2ffbce4da683a5c70f03a462940c2090" + integrity sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg== + dependencies: + normalize-path "^2.1.1" + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -28798,6 +30479,14 @@ upath@^1.1.1, upath@^1.2.0: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + update-browserslist-db@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz#2924d3927367a38d5c555413a7ce138fc95fcb18" @@ -28883,12 +30572,22 @@ url@^0.11.0, url@~0.11.0: punycode "1.3.2" querystring "0.2.0" +urlpattern-polyfill@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz#f0a03a97bfb03cdf33553e5e79a2aadd22cac8ec" + integrity sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg== + +urlpattern-polyfill@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz#99f096e35eff8bf4b5a2aa7d58a1523d6ebc7ce5" + integrity sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ== + use-composed-ref@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.3.0.tgz#3d8104db34b7b264030a9d916c5e94fbe280dbda" integrity sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ== -use-isomorphic-layout-effect@^1.1.1: +use-isomorphic-layout-effect@^1.1.1, use-isomorphic-layout-effect@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== @@ -29099,6 +30798,11 @@ value-or-function@^3.0.0: resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= +value-or-promise@^1.0.11, value-or-promise@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.12.tgz#0e5abfeec70148c78460a849f6b003ea7986f15c" + integrity sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q== + varint@^5.0.0, varint@^5.0.2, varint@~5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" @@ -29322,6 +31026,11 @@ web-streams-polyfill@^3.1.0: resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965" integrity sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA== +web-streams-polyfill@^3.2.1: + version "3.3.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== + web-worker@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.2.0.tgz#5d85a04a7fbc1e7db58f66595d7a3ac7c9c180da" @@ -29562,6 +31271,17 @@ web3@^4.1.0: web3-utils "^4.0.7" web3-validator "^2.0.3" +webcrypto-core@^1.7.8: + version "1.7.8" + resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.7.8.tgz#056918036e846c72cfebbb04052e283f57f1114a" + integrity sha512-eBR98r9nQXTqXt/yDRtInszPMjTaSAMJAFDg2AHsgrnczawT1asx9YNBX6k5p+MekbPF4+s/UJJrr88zsTqkSg== + dependencies: + "@peculiar/asn1-schema" "^2.3.8" + "@peculiar/json-schema" "^1.1.12" + asn1js "^3.0.1" + pvtsutils "^1.3.5" + tslib "^2.6.2" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -29960,7 +31680,7 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" -wrap-ansi@^6.2.0: +wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== @@ -30079,7 +31799,7 @@ ws@^7.3.1, ws@^7.4.6, ws@^7.5.1: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -ws@^8.13.0: +ws@^8.12.0, ws@^8.13.0, ws@^8.15.0: version "8.16.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== @@ -30162,6 +31882,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml-ast-parser@^0.0.43: + version "0.0.43" + resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb" + integrity sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A== + yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" @@ -30172,6 +31897,11 @@ yaml@^2.2.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== +yaml@^2.3.1: + version "2.4.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.0.tgz#2376db1083d157f4b3a452995803dbcf43b08140" + integrity sha512-j9iR8g+/t0lArF4V6NE/QCfT+CO7iLqrXAHZbJdo+LfjqP1vR8Fg5bSiaq6Q2lOD1AUEVrEVIgABvBFYojJVYQ== + yargs-parser@20.2.4, yargs-parser@^20.2.2: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" @@ -30319,7 +32049,7 @@ yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^17.0.1: +yargs@^17.0.0, yargs@^17.0.1: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== @@ -30400,6 +32130,18 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +zen-observable-ts@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz#6c6d9ea3d3a842812c6e9519209365a122ba8b58" + integrity sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg== + dependencies: + zen-observable "0.8.15" + +zen-observable@0.8.15: + version "0.8.15" + resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" + integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== + zod@3.22.4, zod@^3.21.4: version "3.22.4" resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff"