Keeping variables which are only referenced from %raw

rescript-relay generated code, references values from module A in module B but it uses those values inside %raw. A simple reduction of this idea is:

let node_TestRefetchingRefetchQuery = TestRefetchingRefetchQuery.node;
let node = %raw(json` {
  "argumentDefinitions": [
    {
"operation": node_TestRefetchingRefetchQuery,
}`);

this is just part of the code. The contents of raw are taken from an external tool and post processed so we cannot really “just rewrite it in rescript”.

The code above compiles to something like:

import * as TestRefetchingRefetchQuery from "./TestRefetchingRefetchQuery.bs";

var node$1 = ({
  "argumentDefinitions": [
    {
"operation": node_TestRefetchingRefetchQuery,
});

var node_TestRefetchingRefetchQuery = TestRefetchingRefetchQuery.node;

Note the order of values is reversed. I attempted to workaround it by generating code like:

let node = {
  let node_TestRefetchingRefetchQuery = TestRefetchingRefetchQuery.node;
  %raw(json` {
  "argumentDefinitions": [
    {
"operation": node_TestRefetchingRefetchQuery,
}`);
}

But then node_TestRefetchingRefetchQuery is unused and compiles to nothing. Is there a way to keep that value in the compiled output? To reiterate, my goal is to leverage Bucklescript to resolve the import for a given module.

We’ve currently solved it in rescript-relay as per the suggestion in this issue https://github.com/rescript-lang/rescript-compiler/issues/3195, roughly this way:

let makeNode = (node_TestRefetchingRefetchQuery) => {
  ignore(node_TestRefetchingRefetchQuery)
  %raw(json` {
     "operation": node_TestRefetchingRefetchQuery,
}`);
}

let node = makeNode(TestRefetchingRefetchQuery.node)

But it would be interesting to hear if it’d be possible to achieve without the extra function declaration.

Note why the order is reversed is that some inlining happens since TestRexx.node is side effect free.

In general, raw code is unsafe and using a function to capture all variables it rely on is recommended practice.

So I would say this is recommended practice instead of work around

Ok, sounds good. Thanks!

Same issue with graphql-ppx, we managed to solve it using Hongbo’s approach of wrapping it in a function. But it would be nicer to include variable names in a %raw extension point (also the function wrapping is sometimes problematic with interop).