ohm
ohm copied to clipboard
Uncaught TypeError: ohm.makeRecipe is not a function
i have a generated ohm bundle file in my npm package
i use the npm package in my react app
but the client browser that loads the react app is throwing Uncaught TypeError: ohm.makeRecipe is not a function
error
in my package.json
: "ohm-js": "^16.3.2",
is this version related? should i generate the bundle differently?
i generated by the following command
npx ohm generateBundles --withTypes src/grammar.ohm
Hi, thanks for filing the issue and sorry for the slow reply...I'm currently on a 6-week camping trip with pretty limited internet access :-)
I don't think this is version-related. From what I can tell, the problem seems to be that makeRecipe
was never included in the type definitions. Unfortunately I probably won't be able to fix this for a few weeks, but am happy to approve a pull request if you'd like to submit one! Note that you need to edit index.d.ts.template rather than directly editing index.d.ts.
Facing a similar issue today -- not quite resolved but found I could work around in my case.
- I was able to correctly use the compiled bundles (
Language.ohm-bundle.d.ts
andLanguage.ohm-bundle.js
) directly in the context of Jest test execution andts-node
-based scripting. - The compiled bundles did not work in my setup when the same code was run in the browser (next.js react app) giving the error above (
ohm.makeGrammar
not a func) - The currently-working browser strategy with react (using next) I have is using
raw-loader
to parse the ohm grammar definition directly
Taking another look at this as I clean up some bugs in preparation for the v17 release.
After re-reading this, I see that it has nothing to do with the type definitions. @etsai-stripe or @jweissman, can you give me some more details about how you are bundling?
Never mind — I was able to reproduce this with webpack Ohm v16.3.4. It seems to be a problem related to ES modules and our use of a default export. For the record, I was able to fix it by modifying the .ohm-bundle.js file, replacing require('ohm-js')
with require('ohm-js').default
.
The good news is, it's already fixed on main
and will be in the next release of Ohm (v17) and @ohm-js/cli
. I'm also adding a test that ensures that grammars bundled with webpack work properly.
Facing a similar issue today -- not quite resolved but found I could work around in my case.
- I was able to correctly use the compiled bundles (
Language.ohm-bundle.d.ts
andLanguage.ohm-bundle.js
) directly in the context of Jest test execution andts-node
-based scripting.- The compiled bundles did not work in my setup when the same code was run in the browser (next.js react app) giving the error above (
ohm.makeGrammar
not a func)- The currently-working browser strategy with react (using next) I have is using
raw-loader
to parse the ohm grammar definition directly
Can you post the relevant code from your working next.config?
For anyone else, a temporary workaround for nextjs as of 16.4.0
is to change the require in your cli generated ohm-bundles:
let ohm;
if (typeof window !== 'undefined') ohm = require('ohm-js').default;
else ohm = require('ohm-js');
Any eta for v17 then?
@ex3ndr I plan to have it out by the end of the week.
Any updates on this type error? Im having the same issue in a typescript tryout problem with the following settings:
dependencies: "ohm-js": "^17.1.0" "react": "^18.2.0",
devDependencies: "@ohm-js/cli": "^2.0.0"
@GoncaloCamaz Hmmm, this should have been fixed with the v17 release. Can you share more details about how you are building/bundling your code?
@GoncaloCamaz Hmmm, this should have been fixed with the v17 release. Can you share more details about how you are building/bundling your code?
Sure, Im buiding a tryout to experiment the lib. Have already the grammar defined and tested. After that I followed the approach in the docs regarding the usage with Typescript https://ohmjs.org/docs/typescript and it has generated the bundle files without any error. I have a text field where I insert the content to be parsed and then submit. However I cannot even see this since the error occurs while the component is mount.
However, after that i tried another approach and put the grammar in a config file, importing it and with this approach that is also on the docs I did not have the same issue so, for now, I will resume with this approach (importing the grammar from a config and import * as ohm from 'ohm-js'
; .
@GoncaloCamaz Thanks for the details. Can you also tell me exactly how you are running the final code? It sounds like you are using React. Are you bundling your code in some way? E.g., which bundler, exactly what command line, etc. Without the details like this it's difficult for me to reproduce the problem.
Can you please also clarify what you mean by "importing the grammar from a config"?
In the current working version im doing the following imports:
import * as ohm from 'ohm-js';
import { GRAMMAR, OHM_ACTIONS_DICT } from './config';
In this config file I have the grammar in a string constant and the actions for the interpreter.
Bellow I instantiate the grammar like so:
const grammar = ohm.grammar(GRAMMAR);
const interpreter = grammar.createSemantics().addOperation("parseContent", OHM_ACTIONS_DICT);
And after I return the parse content result to a code editor to display the content in JSON format
return interpreter(match).parseContent();
This way works fine!
Previously I was using the grammar object generated by the bundle, importing it like you have on the docs (https://ohmjs.org/docs/typescript):
import grammar from '../src/grammar.ohm-bundle'
To generate the bundle files, i followed the docs example and used the following command line:
npx ohm generateBundles --withTypes src/grammar.ohm
The code sample where I instantiate the grammar object is displayed bellow and its the same for both versions:
const evaluateGrammar = useCallback((text: string): object | undefined=> {
const match = grammar.match(text);
if (match.succeeded()) {
setStatus(EMatchStatus.Valid);
setFailureMessage('');
return interpreter(match).parseContent();
} else {
setStatus(EMatchStatus.Invalid);
setFailureMessage(match.message);
return undefined;
}
}, [interpreter]);
For this tryout Im using React yes but the objective is to have this parser in a javascript utils program that acts as a middleware and that project is built in typescript. Since its built in typescript, I followed the docs example but I can work with the js example and then apply some interfaces to the results.
Thanks for the additional details. But I still don't know how you're running the final code. What does your TypeScript configuration look like? Are you using a bundler like Webpack, Rollup, etc.? And if so, what are the bundler options? It's very difficult to debug this without knowing those things. If you could push your repo to GitHub I could take a look.
One possibility is that the rest of your code is using ES module, while the Ohm bundles are using require
. Please note that there is a --esm
option to generateBundles, which makes the bundles use import
rather than require
.
@pdubroy thanks for your time and help! I was missing the --esm flag as I am working with ES Modules!
Thank you 👍