gorules / jdm-editor

JDM Editor is an open-source React component for crafting and designing JDM (JSON Decision model) files.
https://gorules.io
MIT License
146 stars 38 forks source link

Issue: Module not Found in Next js for version 1.23.3 for @gorules/jdm-editor --> Invalid generator object #119

Open rohitkule opened 1 day ago

rohitkule commented 1 day ago

versions after 1.7.3 are not working in the Next js showing the error

⨯ ./node_modules/@gorules/jdm-editor/dist/style.css:5:1
Module not found: Invalid generator object. Asset Modules Plugin has been initialized using a generator object that does not match the API schema.
- generator has an unknown property 'filename'. These properties are valid:
   object { binary?, dataUrl? }
   -> Generator options for asset/inline modules.

https://nextjs.org/docs/messages/module-not-found

Import trace for requested module:
./node_modules/@gorules/jdm-editor/dist/style.css
./src/components/common/Editor/index.tsx
./src/components/PageEditor/index.tsx
container entry

I have tried with dynamic imports but still not working. if someone resolved this issue i would appreciate your help

d-sooter commented 1 day ago

Here is how i did it (in the pages router) i still havent gotten it working in the app router with babel. i get a monaco error

There might be a better way to do it and i would love to get it working in the app router at some point

// JDM EDITOR 

'use client';

import dynamic from 'next/dynamic';
import { Loading } from '../Loading';

const JdmEditorClient = dynamic(() => import('./JdmEditor.client').then((mod) => mod.JdmEditorClient), {
  ssr: false,
  loading: () => <Loading />,
});

export const JdmEditor = () => {
  return <JdmEditorClient />;
};

// JdmEditor.client

'use client';

import { useEnv } from '@/contexts';
import {
  DecisionGraph,
  DecisionGraphRef,
  DecisionGraphType,
  GraphSimulator,
  JdmConfigProvider,
} from '@gorules/jdm-editor';
import '@gorules/jdm-editor/dist/style.css';
import { loader, Monaco } from '@monaco-editor/react';
import { useTheme } from '@nimbit/ui/theme';
import { TestTube } from '@phosphor-icons/react';
import json5 from 'json5';
import * as monaco from 'monaco-editor';
import { useSession } from 'next-auth/react';
import React from 'react';

declare global {
  interface Window {
    monaco?: Monaco;
  }
}

self.monaco = monaco;

loader.config({
  monaco,
});

type GraphSimilationReq = {
  graph: DecisionGraphType;
  context: unknown;
};

/// TODO MOVE THIS TO API
const symulateGraph = async (payload: GraphSimilationReq, token: string, baseUrl: string) => {
  const response = await fetch(`${baseUrl}/config/Rule/transformation/validate`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${token}`,
    },
    body: JSON.stringify(payload),
  });
  return response.json();
};

export type PanelType = {
  id: string;
  icon: React.ReactNode;
  title: string;
  renderPanel?: React.FC;
  onClick?: () => void;
};

export const JdmEditorClient = () => {
  const { darkMode, palette } = useTheme();
  const { data: session } = useSession();
  const graphRef = React.useRef<DecisionGraphRef>(null);
  const env = useEnv();
  const [graph, setGraph] = React.useState<any | undefined>(undefined);
  const [graphTrace, setGraphTrace] = React.useState<any | undefined>(undefined);

  const panels: PanelType[] = [
    {
      id: 'simulator',
      title: 'Simulator',
      icon: <TestTube size={18} />,
      renderPanel: () => (
        <GraphSimulator
          defaultRequest={json5.stringify(
            {
              age: 20,
            },
            null,
            2,
          )}
          onRun={(payload) => {
            symulateGraph(payload, session?.accessToken as string, env.ocbRestBaseUrl as string)
              .then((result) => {
                setGraphTrace({ result });
              })
              .catch((err) => {
                setGraphTrace({
                  error: {
                    message: 'invalid graph',
                  },
                });
              });
          }}
          onClear={() => setGraphTrace(undefined)}
        />
      ),
    },
  ];

  return (
    <JdmConfigProvider
      theme={{
        mode: darkMode ? 'dark' : 'light',
        token: {
          colorPrimary: palette.colors.primary['500'].hex,
          colorPrimaryActive: palette.colors.primary['600'].hex,
          colorLink: palette.colors.primary['500'].hex,
          colorPrimaryHover: palette.colors.primary['400'].hex,
          colorSuccessBg: palette.colors.primary['100'].hex,
        },
      }}
    >
      <DecisionGraph
        ref={graphRef}
        value={graph}
        onChange={(val) => setGraph(val as any)}
        onPanelsChange={(val) => {
          console.log(val);
        }}
        reactFlowProOptions={{ hideAttribution: true }}
        simulate={graphTrace}
        defaultActivePanel={'simulator'}
        panels={panels}
      />
    </JdmConfigProvider>
  );
};
padmakarkasture commented 17 hours ago

Hi @d-sooter, Thanks for Your reply. I have implemented same in next js project with page router . now it is showing image

versions

This is my package.json

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@emotion/react": "^11.13.5",
    "@emotion/styled": "^11.13.5",
    "@gorules/jdm-editor": "^1.23.3",
    "@monaco-editor/react": "^4.6.0",
    "@mui/icons-material": "^6.1.8",
    "@mui/material": "^6.1.8",
    "json5": "^2.2.3",
    "monaco-editor": "^0.52.0",
    "next": "15.0.3",
    "react": "18.2.0",
    "react-dom": "18.2.0"
  },
  "devDependencies": {
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "typescript": "^5"
  }
}

is there any difference in versions at your end. or am i doing something wrong? also you have mentioned babel so do i have to update .babelrc

{
    "presets": ["next/babel"],
    "plugins": []
  }
d-sooter commented 16 hours ago

How are you intergrating monaco? In my version im not using CDN but providing the needed worker myself. I you are using a cdn i think you can leave out most of the monaco imports and global stuff i did.

If you want to include the needed workers in you bundle then you need to provide some additional webpack config in you next.config.js file

const MonacoEditorWebpackPlugin = require('monaco-editor-webpack-plugin');

const nextConfig = {
 // ... your current config 
 webpack: (config, { dev, isServer }) => {

    if (!isServer) {
      config.plugins.push(
        new MonacoEditorWebpackPlugin({
          languages: ['javascript', 'typescript', 'html', 'css', 'json'],
          filename: 'static/[name].worker.js',
        }),
      );
    }

    return config;
 }
}