edgedb-js icon indicating copy to clipboard operation
edgedb-js copied to clipboard

React Native / Expo support.

Open izakfilmalter opened this issue 2 years ago • 5 comments

Would be great to use the query builder on react native.

My goal is to use the query builder to construct my query and then send it to a proxy endpoint to verify auth. This seems nicer than trying to make a bunch of server side endpoints right now for me.

Env:

"expo": "45.0.6",
"react-native": "0.68.2",

I started pulling the library in and found the following issues trying to get it to compile.

  1. Need to add @babel/plugin-proposal-export-namespace-from.

  2. Patching cypto and buffer within edgedb https://github.com/margelo/react-native-quick-crypto https://github.com/craftzdog/react-native-buffer

    module.exports = {
      presets: ['module:metro-react-native-babel-preset'],
      plugins: [
    +   [
    +     'module-resolver',
    +     {
    +       alias: {
    +         'crypto': 'react-native-quick-crypto',
    +         'stream': 'stream-browserify',
    +         'buffer': '@craftzdog/react-native-buffer',
    +       },
    +     },
    +   ],
        ...
      ],
    };
    
  3. React Native will pull in the browser package of edgedb which doesn't contain $.

My current edgedb patch:

diff --git a/node_modules/edgedb/dist/codecs/ifaces.js b/node_modules/edgedb/dist/codecs/ifaces.js
index 229e919..51bfba3 100644
--- a/node_modules/edgedb/dist/codecs/ifaces.js
+++ b/node_modules/edgedb/dist/codecs/ifaces.js
@@ -19,6 +19,7 @@
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.ScalarCodec = exports.Codec = void 0;
 const consts_1 = require("./consts");
+const Buffer = require('buffer').Buffer
 class Codec {
     constructor(tid) {
         Object.defineProperty(this, "tid", {
diff --git a/node_modules/edgedb/dist/index.browser.d.ts b/node_modules/edgedb/dist/index.browser.d.ts
index a5fc930..89967ae 100644
--- a/node_modules/edgedb/dist/index.browser.d.ts
+++ b/node_modules/edgedb/dist/index.browser.d.ts
@@ -16,3 +16,5 @@
  * limitations under the License.
  */
 export * from "./index.shared";
+export * as $ from "./reflection";
+
diff --git a/node_modules/edgedb/dist/index.browser.js b/node_modules/edgedb/dist/index.browser.js
index ec1e3f6..6c57092 100644
--- a/node_modules/edgedb/dist/index.browser.js
+++ b/node_modules/edgedb/dist/index.browser.js
@@ -32,3 +32,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
 };
 Object.defineProperty(exports, "__esModule", { value: true });
 __exportStar(require("./index.shared"), exports);
+exports.$ = __importStar(require("./reflection"));
diff --git a/node_modules/edgedb/dist/primitives/buffer.js b/node_modules/edgedb/dist/primitives/buffer.js
index 38a480a..7f15e52 100644
--- a/node_modules/edgedb/dist/primitives/buffer.js
+++ b/node_modules/edgedb/dist/primitives/buffer.js
@@ -16,6 +16,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
     if (k2 === undefined) k2 = k;
     var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -46,6 +47,7 @@ const ring_1 = require("./ring");
 const bi = __importStar(require("./bigint"));
 const compat = __importStar(require("../compat"));
 const ifaces_1 = require("../ifaces");
+const Buffer = require('buffer').Buffer
 const BUFFER_INC_SIZE = 4096;
 const BUFFER_RING_CAPACITY = 2048;
 const EMPTY_BUFFER = Buffer.allocUnsafe(0);

Idk if this patch would be accepted, but that got it working for me within react-native as well as node at the same time in my monorepo.

I also had to edit the query client that is produced to fix buffer. Basically, if we can always do the following it works for react-native and everything else from what I can tell:

const buffer = require('buffer').Buffer

izakfilmalter avatar Jul 27 '22 11:07 izakfilmalter

Awesome. I am taking a similar approach to auth and also use React Native, so this was helpful. 👍

Looking toward long-term solutions, it appears compileForDeno includes a Buffer polyfill: https://github.com/edgedb/edgedb-js/blob/master/tools/compileForDeno.ts#L26 Perhaps a similar approach would be desireable for RN.

Side note, our team also uses expo-web so I will look into / document my efforts to get this to work with Create React App.

samwinslow avatar Aug 02 '22 20:08 samwinslow

Progress! Maybe there's a less hacky way to do this with Metro or Babel config, but I resolved Buffer by creating a custom app entrypoint (referenced via main in package.json):

import { Buffer } from 'buffer'
import registerRootComponent from 'expo/build/launch/registerRootComponent'

global.Buffer = Buffer

// eslint-disable-next-line @typescript-eslint/no-var-requires
const App = require('./App').default

registerRootComponent(App)

Edit: The query builder works as expected when using the above pattern in your entry file, and also incorporate this change: https://github.com/samwinslow/edgedb-js/commit/d4a289ea73de20ae8dd62728662ac45af4b12fed

samwinslow avatar Aug 05 '22 19:08 samwinslow

From what I can tell, I still need to patch const Buffer = require('buffer').Buffer to get it working on iOS.

My index.js looks like this:

import 'react-native-get-random-values'
import 'react-native-gesture-handler'
import { registerRootComponent } from 'expo'
import { activateKeepAwake } from 'expo-keep-awake'
import 'expo-asset'

import App from './App'

if (typeof Buffer === 'undefined') {
  global.Buffer = require('@craftzdog/react-native-buffer').Buffer
}

if (__DEV__) {
  activateKeepAwake()
}

// noinspection JSCheckFunctionSignatures
registerRootComponent(App)

izakfilmalter avatar Aug 09 '22 18:08 izakfilmalter

This seems like a better way around the issues with buffer: https://github.com/margelo/react-native-quick-crypto/issues/81#issue-1321407304

I think the only thing then is to do export * as $ from "./reflection";


Edit: After testing, I still need to patch in buffer.

izakfilmalter avatar Aug 16 '22 21:08 izakfilmalter

Any recent news on this? I don't have a React Native environment easily at hand, but I'm willing to make some changes to make this easier to integrate.

scotttrinh avatar May 02 '23 16:05 scotttrinh