import { jsonLanguage } from '@codemirror/lang-json'; import { linter } from '@codemirror/lint'; import type { EditorView } from '@codemirror/view'; import type { GrpcRequest } from '@yaakapp-internal/models'; import classNames from 'classnames'; import { handleRefresh, jsonCompletion, jsonSchemaLinter, stateExtensions, updateSchema, } from 'codemirror-json-schema'; import { useCallback, useEffect, useMemo, useState } from 'react'; import type { ReflectResponseService } from '../hooks/useGrpc'; import { showAlert } from '../lib/alert'; import { showDialog } from '../lib/dialog'; import { pluralizeCount } from '../lib/pluralize'; import { Button } from './core/Button'; import type { EditorProps } from './core/Editor/Editor'; import { Editor } from './core/Editor/LazyEditor'; import { FormattedError } from './core/FormattedError'; import { InlineCode } from './core/InlineCode'; import { VStack } from './core/Stacks'; import { GrpcProtoSelectionDialog } from './GrpcProtoSelectionDialog'; type Props = Pick & { services: ReflectResponseService[] | null; reflectionError?: string; reflectionLoading?: boolean; request: GrpcRequest; protoFiles: string[]; }; export function GrpcEditor({ services, reflectionError, reflectionLoading, request, protoFiles, ...extraEditorProps }: Props) { const [editorView, setEditorView] = useState(null); const handleInitEditorViewRef = useCallback((h: EditorView | null) => { setEditorView(h); }, []); // Find the schema for the selected service and method and update the editor useEffect(() => { if ( editorView == null || services === null || request.service === null || request.method === null ) { return; } const s = services.find((s) => s.name === request.service); if (s == null) { console.log('Failed to find service', { service: request.service, services }); showAlert({ id: 'grpc-find-service-error', title: "Couldn't Find Service", body: ( <> Failed to find service {request.service} in schema ), }); return; } const schema = s.methods.find((m) => m.name === request.method)?.schema; if (request.method != null && schema == null) { console.log('Failed to find method', { method: request.method, methods: s?.methods }); showAlert({ id: 'grpc-find-schema-error', title: "Couldn't Find Method", body: ( <> Failed to find method {request.method} for{' '} {request.service} in schema ), }); return; } if (schema == null) { return; } try { updateSchema(editorView, JSON.parse(schema)); } catch (err) { showAlert({ id: 'grpc-parse-schema-error', title: 'Failed to Parse Schema', body: (

For service {request.service} and method{' '} {request.method}

{String(err)}
), }); } }, [editorView, services, request.method, request.service]); const extraExtensions = useMemo( () => [ linter(jsonSchemaLinter(), { delay: 200, needsRefresh: handleRefresh, }), jsonLanguage.data.of({ autocomplete: jsonCompletion(), }), stateExtensions({}), ], [], ); const reflectionUnavailable = reflectionError?.match(/unimplemented/i); reflectionError = reflectionUnavailable ? undefined : reflectionError; const actions = useMemo( () => [
, ], [protoFiles.length, reflectionError, reflectionLoading, reflectionUnavailable, services], ); return (
); }