Skip to content

Commit

Permalink
Merge pull request #480 from near/feat/editor-error-logging
Browse files Browse the repository at this point in the history
Feat/editor error logging
  • Loading branch information
jl-santana committed Jan 3, 2024
2 parents dfcd365 + a829917 commit 314dc2c
Show file tree
Hide file tree
Showing 8 changed files with 1,181 additions and 1,284 deletions.
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"react-switch": "^7.0.0",
"regenerator-runtime": "^0.13.11",
"styled-components": "^5.3.6",
"typescript": "4.9.5"
"typescript": "4.9.5",
"use-debounce": "^10.0.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { ForkIndexerModal } from "../Modals/ForkIndexerModal";
import { getLatestBlockHeight } from "../../utils/getLatestBlockHeight";
import { IndexerDetailsContext } from '../../contexts/IndexerDetailsContext';
import { PgSchemaTypeGen } from "../../utils/pgSchemaTypeGen";
import { validateSQLSchema } from "@/utils/validators";

const BLOCKHEIGHT_LIMIT = 3600;

Expand Down Expand Up @@ -49,9 +50,7 @@ const Editor = ({
}`;

const [blockHeightError, setBlockHeightError] = useState(undefined);
const [codeFormattingError, setCodeFormattingError] = useState(undefined);
const [schemaFormattingError, setSchemaFormattingError] = useState(undefined);
const [typesGenerationError, setTypesGenerationError] = useState(undefined);
const [error, setError] = useState();

const [fileName, setFileName] = useState("indexingLogic.js");

Expand Down Expand Up @@ -121,10 +120,10 @@ const Editor = ({
if (fileName === "indexingLogic.js") {
try {
setSchemaTypes(pgSchemaTypeGen.generateTypes(schema));
setTypesGenerationError(undefined);
} catch (typesError) {
console.log("typesGenerationError generating types for saved schema.\n", typesError);
setTypesGenerationError("There was an error generating types from your schema. Please fix your schema or file a support ticket.");
setError(undefined);
} catch (error) {
console.error("Error generating types for saved schema.\n", error.message);
setError("There was an error with your schema. Check the console for more details.");
}
}
}, [fileName]);
Expand All @@ -150,47 +149,34 @@ const Editor = ({
}
}

const checkSQLSchemaFormatting = () => {
try {
let formatted_sql = formatSQL(schema);
let formatted_schema = formatted_sql;
try {
pgSchemaTypeGen.generateTypes(formatted_sql); // Sanity check
} catch (typesError) {
console.log("Error generating types from schema", typesError);
setTypesGenerationError("There was an error generating types from your schema. Please fix your schema or file a support ticket." );
}
setSchemaFormattingError(undefined);
return formatted_schema;
} catch (formattingError) {
console.log("formattingError", formattingError);
setSchemaFormattingError("Please check your SQL schema formatting and specify an Indexer Name");
return undefined;
}
};


const forkIndexer = async(indexerName) => {
let code = indexingCode;
setAccountId(currentUserAccountId)
let prevAccountId = indexerDetails.accountId.replaceAll(".", "_");
let newAccountId = currentUserAccountId.replaceAll(".", "_");
let prevIndexerName = indexerDetails.indexerName.replaceAll("-", "_").trim().toLowerCase();
let newIndexerName = indexerName.replaceAll("-", "_").trim().toLowerCase();
code = code.replaceAll(prevAccountId, newAccountId);
code = code.replaceAll(prevIndexerName, newIndexerName);
setIndexingCode(formatIndexingCode(code))
const forkIndexer = async (indexerName) => {
let code = indexingCode;
setAccountId(currentUserAccountId)
let prevAccountId = indexerDetails.accountId.replaceAll(".", "_");
let newAccountId = currentUserAccountId.replaceAll(".", "_");
let prevIndexerName = indexerDetails.indexerName.replaceAll("-", "_").trim().toLowerCase();
let newIndexerName = indexerName.replaceAll("-", "_").trim().toLowerCase();
code = code.replaceAll(prevAccountId, newAccountId);
code = code.replaceAll(prevIndexerName, newIndexerName);
setIndexingCode(formatIndexingCode(code))
}

const registerFunction = async (indexerName, indexerConfig) => {
let formatted_schema = checkSQLSchemaFormatting();
const { data: formattedSchema, error } = await validateSQLSchema(schema);

if (error) {
setError("There was an error in your schema, please check the console for more details");
return;
}

let innerCode = indexingCode.match(/getBlock\s*\([^)]*\)\s*{([\s\S]*)}/)[1];
indexerName = indexerName.replaceAll(" ", "_");

request("register-function", {
indexerName: indexerName,
code: innerCode,
schema: formatted_schema,
schema: formattedSchema,
blockHeight: indexerConfig.startBlockHeight,
contractFilter: indexerConfig.filter,
});
Expand Down Expand Up @@ -250,16 +236,17 @@ const Editor = ({
let formattedSql = schema;
try {
formattedCode = formatIndexingCode(indexingCode);
setCodeFormattingError(undefined);
setError(undefined);
} catch (error) {
console.log("error", error)
setCodeFormattingError("Oh snap! We could not format your code. Make sure it is proper Javascript code.");
console.error("error", error)
setError("Oh snap! We could not format your code. Make sure it is proper Javascript code.");
}
try {
formattedSql = formatSQL(schema);
setSchemaFormattingError(undefined);
setError(undefined);
} catch (error) {
setSchemaFormattingError("Could not format your SQL schema. Make sure it is proper SQL DDL");
console.error(error);
setError("Could not format your SQL schema. Make sure it is proper SQL DDL");
}
setIndexingCode(formattedCode);
setSchema(formattedSql);
Expand All @@ -270,10 +257,10 @@ const Editor = ({
try {
setSchemaTypes(pgSchemaTypeGen.generateTypes(schema));
attachTypesToMonaco(); // Just in case schema types have been updated but weren't added to monaco
setTypesGenerationError(undefined);
} catch (typesError) {
console.log("typesGenerationError generating types for saved schema.\n", typesError);
setTypesGenerationError("Oh snap! We could not generate types for your SQL schema. Make sure it is proper SQL DDL.");
setError(undefined);
} catch (error) {
console.error("Error generating types for saved schema.\n", error);
setError("Oh snap! We could not generate types for your SQL schema. Make sure it is proper SQL DDL.");
}
}

Expand Down Expand Up @@ -339,91 +326,81 @@ const Editor = ({
Indexer Function could not be found. Are you sure this indexer exists?
</Alert>
)}
{(indexerDetails.code || isCreateNewIndexer) && <>
<EditorButtons
handleFormating={handleFormating}
handleCodeGen={handleCodeGen}
executeIndexerFunction={executeIndexerFunction}
currentUserAccountId={currentUserAccountId}
getActionButtonText={getActionButtonText}
heights={heights}
setHeights={setHeights}
isCreateNewIndexer={isCreateNewIndexer}
isExecuting={isExecutingIndexerFunction}
stopExecution={() => indexerRunner.stop()}
latestHeight={height}
isUserIndexer={indexerDetails.accountId === currentUserAccountId}
handleDeleteIndexer={handleDeleteIndexer}
/>
<ResetChangesModal
handleReload={handleReload}
/>
<PublishModal
registerFunction={registerFunction}
actionButtonText={getActionButtonText()}
blockHeightError={blockHeightError}
/>
<ForkIndexerModal
forkIndexer={forkIndexer}
/>

<div
className="px-3 pt-3"
style={{
flex: "display",
justifyContent: "space-around",
width: "100%",
height: "100%",
}}
>
{codeFormattingError && (
<Alert className="px-3 pt-3" variant="danger">
{codeFormattingError}
</Alert>
)}
{schemaFormattingError && (
<Alert className="px-3 pt-3" variant="danger">
{schemaFormattingError}
</Alert>
)}
{typesGenerationError && (
<Alert className="px-3 pt-3" variant="danger">
{typesGenerationError}
</Alert>
)}
{debugMode && !debugModeInfoDisabled && (
<Alert
className="px-3 pt-3"
dismissible="true"
onClose={() => setDebugModeInfoDisabled(true)}
variant="info"
>
To debug, you will need to open your browser console window in
order to see the logs.
</Alert>
)}
<FileSwitcher
fileName={fileName}
setFileName={setFileName}
diffView={diffView}
setDiffView={setDiffView}
/>
<ResizableLayoutEditor
fileName={fileName}
indexingCode={indexingCode}
blockView={blockView}
diffView={diffView}
setIndexingCode={setIndexingCode}
setSchema={setSchema}
block_details={block_details}
originalSQLCode={originalSQLCode}
originalIndexingCode={originalIndexingCode}
schema={schema}
{(indexerDetails.code || isCreateNewIndexer) && <>
<EditorButtons
handleFormating={handleFormating}
handleCodeGen={handleCodeGen}
executeIndexerFunction={executeIndexerFunction}
currentUserAccountId={currentUserAccountId}
getActionButtonText={getActionButtonText}
heights={heights}
setHeights={setHeights}
isCreateNewIndexer={isCreateNewIndexer}
handleEditorWillMount={handleEditorWillMount}
handleEditorMount={handleEditorMount}
isExecuting={isExecutingIndexerFunction}
stopExecution={() => indexerRunner.stop()}
latestHeight={height}
isUserIndexer={indexerDetails.accountId === currentUserAccountId}
handleDeleteIndexer={handleDeleteIndexer}
/>
<ResetChangesModal
handleReload={handleReload}
/>
<PublishModal
registerFunction={registerFunction}
actionButtonText={getActionButtonText()}
blockHeightError={blockHeightError}
/>
<ForkIndexerModal
forkIndexer={forkIndexer}
/>
</div>

<div
className="px-3 pt-3"
style={{
flex: "display",
justifyContent: "space-around",
width: "100%",
height: "100%",
}}
>
{error && (
<Alert dismissible="true" onClose={() => setError(undefined)} className="px-3 pt-3" variant="danger">
{error}
</Alert>
)}
{debugMode && !debugModeInfoDisabled && (
<Alert
className="px-3 pt-3"
dismissible="true"
onClose={() => setDebugModeInfoDisabled(true)}
variant="info"
>
To debug, you will need to open your browser console window in
order to see the logs.
</Alert>
)}
<FileSwitcher
fileName={fileName}
setFileName={setFileName}
diffView={diffView}
setDiffView={setDiffView}
/>
<ResizableLayoutEditor
fileName={fileName}
indexingCode={indexingCode}
blockView={blockView}
diffView={diffView}
setIndexingCode={setIndexingCode}
setSchema={setSchema}
block_details={block_details}
originalSQLCode={originalSQLCode}
originalIndexingCode={originalIndexingCode}
schema={schema}
isCreateNewIndexer={isCreateNewIndexer}
handleEditorWillMount={handleEditorWillMount}
handleEditorMount={handleEditorMount}
/>
</div>
</>}
</div>
);
Expand Down
13 changes: 12 additions & 1 deletion frontend/src/components/Editor/ResizableLayoutEditor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { MonacoEditorComponent } from "./MonacoEditorComponent";
import { defaultCode, defaultSchema } from "../../utils/formatters";
import { useDragResize } from "../../utils/resize";
import GraphqlPlayground from "./../Playground";
import { validateSQLSchema } from "@/utils/validators";
import { useDebouncedCallback } from "use-debounce";

// Define styles as separate objects
const containerStyle = {
Expand Down Expand Up @@ -57,6 +59,15 @@ const ResizableEditor = ({
sizeThresholdSecond: 60,
});

const debouncedValidateSQLSchema = useDebouncedCallback((_schema) => {
validateSQLSchema(_schema)
}, 1000);

const handleOnChangeSchema = (_schema) => {
setSchema(_schema);
debouncedValidateSQLSchema(_schema);
}

// Render logic based on fileName
const editorComponents = {
GraphiQL: () => <GraphqlPlayground />,
Expand Down Expand Up @@ -98,7 +109,7 @@ const ResizableEditor = ({
defaultValue={defaultSchema}
defaultLanguage="sql"
readOnly={isCreateNewIndexer === true ? false : false}
onChange={(text) => setSchema(text)}
onChange={handleOnChangeSchema}
handleEditorWillMount={undefined}
/>
),
Expand Down
1 change: 1 addition & 0 deletions frontend/src/constants/RegexExp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const CONTRACT_NAME_REGEX = RegExp(/^(\*|([a-z\d]+[-_])*[a-z\d]+)(\.*(\*|([a-z\d]+[-_])*[a-z\d]+))*\.(\w+)$/);
25 changes: 24 additions & 1 deletion frontend/src/utils/validators.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const CONTRACT_NAME_REGEX = RegExp(/^(\*|([a-z\d]+[-_])*[a-z\d]+)(\.*(\*|([a-z\d]+[-_])*[a-z\d]+))*\.(\w+)$/);
import { formatSQL } from "./formatters";
import { PgSchemaTypeGen } from "./pgSchemaTypeGen";
import { CONTRACT_NAME_REGEX } from '../constants/RegexExp';

export function validateContractId(accountId) {
return (
Expand All @@ -12,3 +14,24 @@ export function validateContractIds(accountIds) {
const ids = accountIds.split(',').map(id => id.trim());
return ids.every(accountId => validateContractId(accountId));
}

/**
* Validates formatting and type generation from a SQL schema.
*
* @param {string} schema - The SQL schema to validate and format.
* @returns {{ data: string | null, error: string | null }} - An object containing the formatted schema and error (if any).
*/
export async function validateSQLSchema(schema) {
const pgSchemaTypeGen = new PgSchemaTypeGen();

try {
const formattedSchema = await formatSQL(schema);
pgSchemaTypeGen.generateTypes(formattedSchema); // Sanity check

return { data: formattedSchema, error: null }
} catch (error) {

console.error(error.message)
return { data: null, error };
}
};
2 changes: 1 addition & 1 deletion frontend/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
"src/components/Editor/Editor.js",
"src/components/Editor/Editor.jsx",
"src/pages/query-api-editor/editor.js",
"src/components/CreateNewIndexer/CreateNewIndexer.js"
],
Expand Down
Loading

0 comments on commit 314dc2c

Please sign in to comment.