Search code examples
javascriptreact-nativeexpoopenapiopenapi-generator

Unable to resolve own module - Expo


I have created my own expo project with pure javascript (not typescript). I generated a javascript Api Client using OpenApi Generator.

To integrate the api with my code I need to link that package manually as:

To use the library locally without publishing to a remote npm registry, first install the dependencies by changing into the directory containing package.json (and this README). Let's call this JAVASCRIPT_CLIENT_DIR. Then run:

npm install

Next, link it globally in npm with the following, also from JAVASCRIPT_CLIENT_DIR:

npm link

To use the link you just defined in your project, switch to the directory you want to use your wizard_card_game_api from, and run:

npm link /path/to/<JAVASCRIPT_CLIENT_DIR>

Finally, you need to build the module:

npm run build

I managed to see my module in node_modules folder.

When I run expo start always get:

Unable to resolve module wizard-card-game-api from C:\Users\myUser\Documents\Code\React-Native\react-native-wizard-client\client\features\login\actions.js: wizard-card-game-api could not be found within the project.

If you are sure the module exists, try these steps:
 1. Clear watchman watches: watchman watch-del-all
 2. Delete node_modules and run yarn install
 3. Reset Metro's cache: yarn start --reset-cache
 4. Remove the cache: rm -rf /tmp/metro-*

Btw, I don't have tsconfig.json file, since I'm not using typescript.

I have created a type for my module because was suggested by Visual Code. A placed it in the root folder with the name desc.d.ts:

declare module 'wizard-card-game-api';

I have read also: Expo question

Also read about configuration regarding typescript and tsconfig.json which I cannot follow.

package.json

{
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "@babel/eslint-parser": "^7.14.7",
    "@expo/vector-icons": "^12.0.0",
    "@react-native-async-storage/async-storage": "~1.15.0",
    "@react-native-community/masked-view": "0.1.10",
    "@react-navigation/bottom-tabs": "^5.11.11",
    "@react-navigation/drawer": "^5.12.5",
    "@react-navigation/native": "^5.9.4",
    "@react-navigation/stack": "^5.14.5",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-prettier": "^3.4.0",
    "expo": "~42.0.1",
    "expo-status-bar": "~1.0.4",
    "install": "^0.13.0",
    "prettier": "^2.3.2",
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "react-native": "https://github.com/expo/react-native/archive/sdk-42.0.0.tar.gz",
    "react-native-gesture-handler": "~1.10.2",
    "react-native-reanimated": "~2.2.0",
    "react-native-safe-area-context": "3.2.0",
    "react-native-screens": "~3.4.0",
    "react-native-web": "~0.13.12",
    "react-redux": "^7.2.4",
    "redux": "^4.1.0",
    "redux-immutable-state-invariant": "^2.1.0",
    "redux-logger": "^3.0.6",
    "redux-persist": "^6.0.0",
    "redux-saga": "^1.1.3",
    "redux-thunk": "^2.3.0"
  },
  "devDependencies": {
    "@babel/core": "^7.14.6",
    "eslint": "^7.31.0",
    "eslint-config-standard": "^16.0.3",
    "eslint-plugin-import": "^2.23.4",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-promise": "^5.1.0",
    "eslint-plugin-react": "^7.24.0"
  },
  "private": true
}

loginAction.js

/* tslint:disable */
import WizardCardGameApi from 'wizard-card-game-api';  // <<< --- ERROR HERE

import constants from './constants';

const loginActions = {
  login: (playerName, wizardId) => {
    let api = new WizardCardGameApi.LobbyControllerApi();
    let joinLobbyRequest = new api.JoinLobbyRequest('SlinkmanSorcery', playerName, wizardId);
    let callback = function (error, data, response) {
      if (error) {
        console.error(`Error: ${error}`);
      } else {
        console.log(`API called successfully. Returned data: ${data}`);
      }
    };
    api.joinLobby(joinLobbyRequest, callback);

    return {
      type: constants.LOGIN,
      playerName,
      wizardId,
    };
  },
  logout: () => {
    return {
      type: constants.LOGOUT,
    };
  },
};

export default loginActions;

babel.config.js

module.exports = function (api) {
  api.cache(true);
  return {
    presets: ['babel-preset-expo'],
    env: {
      production: {
        plugins: ['react-native-paper/babel'],
      },
    },
  };
};

Api index.js file

/**
 * Wizard Card Game API
 * This API drives the Wizard Card Game.
 *
 * The version of the OpenAPI document: 1.0.0
 * Contact: rw.slinkman@gmail.com
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 *
 */
import ApiClient from './ApiClient';
import CardEntity from './model/CardEntity';
import CreateGameRequest from './model/CreateGameRequest';
/* ... */
import UserRoundStateResponse from './model/UserRoundStateResponse';
import GameControllerApi from './api/GameControllerApi';
import LobbyControllerApi from './api/LobbyControllerApi';

export {
    /**
     * The ApiClient constructor.
     * @property {module:ApiClient}
     */
    ApiClient,

    /**
     * The CardEntity model constructor.
     * @property {module:model/CardEntity}
     */
    CardEntity,

    /**
     * The CreateGameRequest model constructor.
     * @property {module:model/CreateGameRequest}
     */
    CreateGameRequest,

    /**
     * The EstimateRequest model constructor.
     * @property {module:model/EstimateRequest}
     */
    EstimateRequest,

    /* ... */

    /**
    * The GameControllerApi service constructor.
    * @property {module:api/GameControllerApi}
    */
    GameControllerApi,

    /**
    * The LobbyControllerApi service constructor.
    * @property {module:api/LobbyControllerApi}
    */
    LobbyControllerApi
};

Any idea?


Solution

  • I solved my problem. Here are the steps I did:

    1. Change my api folder to be within react-native app. enter image description here

    2. Install babel-plugin-module-resolver

    expo install babel-plugin-module-resolver
    
    1. Create a .babelrc.json file in the root of my client app:
    {
      "presets": ["babel-preset-expo"],
      "plugins": [
        [
          "module-resolver",
          {
            "root": ["./"],
            "alias": {
              "wizard-card-game-api": "./api/WizardApiClient/src"
            }
          }
        ]
      ]
    }
    
    1. Stop expo app and re-rerun it as:
    expo start -c
    

    Now, loginAction.js works great:

    import WizardCardGameApi from 'wizard-card-game-api';
    

    Cheers.

    Important resource: https://stackoverflow.com/a/53865634/992347