Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I fork this repo ? #95

Closed
AlexUzan opened this issue Dec 3, 2019 · 6 comments
Closed

How can I fork this repo ? #95

AlexUzan opened this issue Dec 3, 2019 · 6 comments
Assignees
Labels
Needs More Information Further information needed from the requester

Comments

@AlexUzan
Copy link

AlexUzan commented Dec 3, 2019

Hi, I am trying to setup Stream in a react native app, but for customization issues I need to fork it and change some components. From what I understand this repo actually contains 3 npm packages, and the changes I need are in the stream-chat-react-native-core package. But then when I add the url to the fork in my package.json, I am stuck because yarn fetches stream-chat-react-native-core instead of stream-chat-react-native.
I know this might be a basic question, but I am not used to the way npm packages work. Is there a way to make it work just by forking or do I need to publish it on npm to make it work ?

Thanks !

@vishalnarkhede
Copy link
Contributor

Hey @AlexUzan ,

this is how your package.json should look like:

{
  "name": "Package Name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint ."
  },
  "dependencies": {
    ...
    // Following paths should be relative to your project directory
    "stream-chat-react-native": "link:../stream-chat-react-native/native-package",
    "stream-chat-react-native-core": "link:../stream-chat-react-native"
  },
  "devDependencies": {
    ...
  },
}

Also you will need to blacklist the node_modules directories of stream-chat-react-native folder via metro config to avoid conflict. Here is the metro.config.js file that I have. you will see blacklisted directories on lines 141-146 in following snippet,

/* eslint-env node */
function resolvePath(...parts) {
  const thisPath = PATH.resolve.apply(PATH, parts);
  if (!FS.existsSync(thisPath)) return;

  return FS.realpathSync(thisPath);
}

function isExternalModule(modulePath) {
  return modulePath.substring(0, __dirname.length) !== __dirname;
}

function listDirectories(rootPath, cb) {
  FS.readdirSync(rootPath).forEach(fileName => {
    if (fileName.charAt(0) === '.') return;

    let fullFileName = PATH.join(rootPath, fileName),
      stats = FS.lstatSync(fullFileName),
      symbolic = false;

    if (stats.isSymbolicLink()) {
      fullFileName = resolvePath(fullFileName);
      if (!fullFileName) return;

      stats = FS.lstatSync(fullFileName);

      symbolic = true;
    }

    if (!stats.isDirectory()) return;

    const external = isExternalModule(fullFileName);
    cb({rootPath, symbolic, external, fullFileName, fileName});
  });
}

function buildFullModuleMap(
  moduleRoot,
  mainModuleMap,
  externalModuleMap,
  _alreadyVisited,
  _prefix,
) {
  if (!moduleRoot) return;

  const alreadyVisited = _alreadyVisited || {},
    prefix = _prefix;

  if (alreadyVisited && alreadyVisited.hasOwnProperty(moduleRoot)) return;

  alreadyVisited[moduleRoot] = true;

  listDirectories(
    moduleRoot,
    ({fileName, fullFileName, symbolic, external}) => {
      if (symbolic)
        return buildFullModuleMap(
          resolvePath(fullFileName, 'node_modules'),
          mainModuleMap,
          externalModuleMap,
          alreadyVisited,
        );

      const moduleMap = external ? externalModuleMap : mainModuleMap,
        moduleName = prefix ? PATH.join(prefix, fileName) : fileName;

      if (fileName.charAt(0) !== '@') moduleMap[moduleName] = fullFileName;
      else
        return buildFullModuleMap(
          fullFileName,
          mainModuleMap,
          externalModuleMap,
          alreadyVisited,
          fileName,
        );
    },
  );
}

function buildModuleResolutionMap() {
  const moduleMap = {},
    externalModuleMap = {};

  buildFullModuleMap(baseModulePath, moduleMap, externalModuleMap);

  // Root project modules take precedence over external modules
  return Object.assign({}, externalModuleMap, moduleMap);
}

function findAlernateRoots(
  moduleRoot = baseModulePath,
  alternateRoots = [],
  _alreadyVisited,
) {
  const alreadyVisited = _alreadyVisited || {};
  if (alreadyVisited && alreadyVisited.hasOwnProperty(moduleRoot)) return;

  alreadyVisited[moduleRoot] = true;

  listDirectories(moduleRoot, ({fullFileName, fileName, external}) => {
    if (fileName.charAt(0) !== '@') {
      if (external) alternateRoots.push(fullFileName);
    } else {
      findAlernateRoots(fullFileName, alternateRoots, alreadyVisited);
    }
  });

  return alternateRoots;
}

function getPolyfillHelper() {
  let getPolyfills;

  // Get default react-native polyfills
  try {
    getPolyfills = require('react-native/rn-get-polyfills');
  } catch (e) {
    getPolyfills = () => [];
  }

  // See if project has custom polyfills, if so, include the PATH to them
  try {
    const customPolyfills = require.resolve('./polyfills.js');
    getPolyfills = (function(originalGetPolyfills) {
      return () => originalGetPolyfills().concat(customPolyfills);
    })(getPolyfills);
  } catch (e) {
    //ignore
  }

  return getPolyfills;
}

const PATH = require('path');
const FS = require('fs'),
  blacklist = require('metro-config/src/defaults/blacklist');

const repoDir = PATH.dirname(PATH.dirname(__dirname));

const moduleBlacklist = [
  new RegExp(repoDir + '/projects/stream-chat-react-native/examples/NativeMessaging/.*'),
  new RegExp(repoDir + '/projects/stream-chat-react-native/examples/ExpoMessaging/.*'),
  new RegExp(repoDir + '/projects/stream-chat-react-native/native-package/node_modules/.*'),
  new RegExp(repoDir + '/projects/stream-chat-react-native/expo-package/.*'),
  new RegExp(repoDir + '/projects/stream-chat-react-native/node_modules/.*'),
  ],
  baseModulePath = resolvePath(__dirname, 'node_modules'),
  // watch alternate roots (outside of project root)
  alternateRoots = findAlernateRoots(),
  // build full module map for proper
  // resolution of modules in external roots
  extraNodeModules = buildModuleResolutionMap();

module.exports = {
  resolver: {
    blacklistRE: blacklist(moduleBlacklist),
    extraNodeModules,
    useWatchman: false,
  },
  watchFolders: [PATH.resolve(__dirname)].concat(alternateRoots),
  // transformer: {
  //   babelTransformerPath: require.resolve('./compiler/transformer'),
  // },
  serializer: {
    getPolyfills: getPolyfillHelper(),
  },
};

Hope that helps :)

@vishalnarkhede vishalnarkhede self-assigned this Dec 5, 2019
@vishalnarkhede vishalnarkhede added the Needs More Information Further information needed from the requester label Dec 5, 2019
@AlexUzan
Copy link
Author

AlexUzan commented Dec 6, 2019

Hi @vishalnarkhede, thank you for your help !
I am having trouble installing the dependencies from a github repo the way you suggested:

"stream-chat-react-native": "https://github.com/MyFork/stream-chat-react-native:../stream-chat-react-native/native-package",
"stream-chat-react-native-core": "https://github.com/MyFork/stream-chat-react-native:../stream-chat-react-native"

Above is what I have right now in my package.json, but yarn does not find it (404 error). From my understanding neither yarn nor npm support linking subdirectories of github repos as dependencies (yarnpkg/yarn#4725).
How do you do it ? Do you have some kind of workaround ?

I found a useful tool allowing to publish packages to github repos the same way you would for npm so I might try this: https://github.com/ramasilveyra/gitpkg

@vishalnarkhede
Copy link
Contributor

vishalnarkhede commented Dec 18, 2019

Hey @AlexUzan , for me, I just have clone of these repos on my local machine. So I use them as following for development.

  "dependencies": {
    ...
    // Following paths should be relative to your project directory
    "stream-chat-react-native": "link:../stream-chat-react-native/native-package",
    "stream-chat-react-native-core": "link:../stream-chat-react-native"
  },

And for sample apps, I replace them with their corresponding npm packages

  "dependencies": {
    "stream-chat-react-native": "^0.3.9",
    // don't need to include `stream-chat-react-native-core`, since its already dependency of `stream-chat-react-native`
  },

@vishalnarkhede
Copy link
Contributor

@AlexUzan Can you give me an update if gitpkg tool worked for you?

@AlexUzan
Copy link
Author

@vishalnarkhede Yes, gitpkg has been working great for production builds, thank you for your help !

@vishalnarkhede
Copy link
Contributor

Thanks really great to hear @AlexUzan :)

Closing this issue now!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs More Information Further information needed from the requester
Projects
None yet
Development

No branches or pull requests

2 participants