John Jenkins
John Jenkins

Reputation: 21

How to create a script within my React Native app

I have a React Native app. As part of the release process, I need to run a script that uses some of the code in my app to generate a static file. Specifically, my app is a game that uses pre-computed boards, that are costly to compute, so I'm building a script to generate the boards during the release phase and storing them in a local file. I would like to create a script within the same code-base as my app that will import other parts of the code base to generate boards. For example, a subset of my working tree is:

-lib
 \-Helper.tsx
  -Solver.tsx
-scripts
 \-GenerateBoards.js
  -generated_boards.out
App.tsx
package.json
tsconfig.json

Helper.tsx and Solver.tsx are standalone files with no imports. GenerateBoards.js needs to import those two files and use its own internal logic to generate boards and write them out to generated_boards.out.

I have a version of GenerateBoards.js that will write the file, e.g.:

fs = require('fs');
function main() {
  fs.writeFile(
    './scripts/generated_boards.out',
    'Hello, World!',
    function (err) {
      if (err) return console.log(err);
      console.log("Finished writing file.");
    });
}
main();

I can use node scripts\GenerateBoards.js to create the file. The next step is to import Helper.tsx or Solver.tsx, but I cannot figure out any incantation to get it to work. I've tried Helper = require("../lib/Helper.tsx"), but that gives me some MODULE_NOT_FOUND error. I've tried converting GenerateBoards.js to a .tsx file and doing import * as Helper from "../lib/Helper", but that complains because I'm not allowed to import from outside of a module.

It seems that there's some concept around modules or defining modules that I'm not understanding. Typescript's module docs state that "any file containing a top-level import or export is considered a module", so it seems that by doing import * as ..., I'm creating a module. But, the compiler/transpiler/runner seem to claim the opposite.

Upvotes: 1

Views: 833

Answers (1)

John Jenkins
John Jenkins

Reputation: 21

I was able to solve this by properly setting up a Module in a sub-directory of my React Native project.

Structure

-lib
 \-Helper.tsx
  -Solver.tsx
-scripts
 \-GenerateBoards.tsx
  -index.tsx*
  -package.json*
  -tsconfig.json*
  -generated_boards.out
App.tsx
package.json
tsconfig.json

index.tsx

import { GenerateBoards } from "./GenerateBoards";

async function main() {
  const generateBoards = new GenerateBoards();

  await generateBoards.generate();
}

main().then(() => console.log("Complete."));

package.json

{
  "module": "esnext"
}

tsconfig.json

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "jsx": "react",
    "lib": ["dom", "esnext"],
    "moduleResolution": "node",
    "noEmit": true,
    "resolveJsonModule": true,
    "strict": true,
    "noImplicitAny": false,
    "target": "es2017"
  }
}

Now, my normal Typescript development environment works as expected; GenerateBoards.tsx can import Helper.tsx and Solver.tsx. To run my script and/or add dependencies to it, I first cd into that folder and then run commands like it were any other Typescript environment, e.g.:

cd scripts
npm i some_package
npx ts-node index.tsx

This is nice because it is completely isolated from my "base" package.json, which has all of my app dependencies which would otherwise get polluted with things that are only needed in my script.

Upvotes: 1

Related Questions