amark / gun

An open source cybersecurity protocol for syncing decentralized graph data.
https://gun.eco/docs
Other
18.08k stars 1.16k forks source link

Dynamically Loading GUN Async Causes JSON/YSON Parse Errors #1279

Open Alengeorge-01 opened 2 years ago

Alengeorge-01 commented 2 years ago

Getting an error while injecting the Gun and SEA script file dynamically and trying to create a user

Below is the error :

Unhandled Promise rejection: Unexpected token 'a', "abc" is not valid JSON ; Zone: <root> ; Task: null ; Value: SyntaxError: Unexpected token 'a', "abc" is not valid JSON
    at JSON.parse (<anonymous>)
    at JSON.parseAsync (sea.min.js:formatted:154:35)
    at sea.min.js:formatted:170:22
    at new ZoneAwarePromise (zone.js:1427:1)
    at o.parse (sea.min.js:formatted:169:20)
    at Object.parse (sea.min.js:formatted:275:33)
    at s.pub (sea.min.js:formatted:1490:31)
    at Object.s [as next] (sea.min.js:formatted:1455:210)
    at Object.t [as on] (gun.min.js:1:2649)
    at t (gun.min.js:1:7398) SyntaxError: Unexpected token 'a', "abc" is not valid JSON
    at JSON.parse (<anonymous>)
    at JSON.parseAsync (http://localhost:4200/assets/js/sea.min.js:7:3305)
    at http://localhost:4200/assets/js/sea.min.js:7:3508
    at new ZoneAwarePromise (http://localhost:4200/polyfills.js:9485:29)
    at o.parse (http://localhost:4200/assets/js/sea.min.js:7:3476)
    at Object.parse (http://localhost:4200/assets/js/sea.min.js:7:5136)
    at s.pub (http://localhost:4200/assets/js/sea.min.js:7:25274)
    at Object.s [as next] (http://localhost:4200/assets/js/sea.min.js:7:24414)
    at Object.t [as on] (http://localhost:4200/assets/js/gun.min.js:1:2649)
    at t (http://localhost:4200/assets/js/gun.min.js:1:7398)
**This is the code implementation**
    let _window: any = window;

    // If script is not loaded, load first
    if (!_window.Gun && !_window.SEA) {
      this.loadGunScript();
      this.loadSeaScript();
    }

      // Creating gun and user instances and syncing with relay server
      let gun = _window.Gun({ peers: ['http://localhost:3000/gun'], localStorage: false });
      let sea = _window.SEA;
      let user = gun.user().recall({ sessionStorage: true });

      user.create("abc", "12345678", (ack) => {
        console.log(user.is, " is created");

        // check if no error on user authentication
        if (!('err' in ack)) {
          console.log("YES GOT IN!")
        } else {
          console.log("Got error-", ack.err, ack);
        }
      });

  /**
   * Load Gun script
   */
  loadGunScript() {
    let body = <HTMLDivElement>document.body;
    let script = document.createElement('script');
    script.innerHTML = '';
    script.src = "/assets/js/gun.min.js";
    script.async = true;
    script.defer = true;
    script.onload = (script) => {
      console.log("Gun Js loaded");
    };
    body.appendChild(script);
  }

  /**
   * Load SEA script
   */
  loadSeaScript() {
    // If script is not loaded, load first
    let body = <HTMLDivElement>document.body;
    let script = document.createElement('script');
    script.innerHTML = '';
    script.src = "/assets/js/sea.min.js";
    script.async = true;
    script.defer = true;
    script.onload = (script) => {
      console.log("SEA Js loaded");
    };
    body.appendChild(script);
  }
amark commented 2 years ago

Interesting. It is possible because GUN checks for parseAsync once at runtime, not everytime, and so dynamic loading is messing with things?

This does not happen when loaded normally.

Dynamically loading would be nice tho low priority - what is your use case? How many users do you currently have? @Alengeorge-01

Alengeorge-01 commented 2 years ago

Hi,

We are trying to load Gun dynamically because our website is server-side rendered and we want Gun to be loaded only when required, and not every time. Yeah, you are right, normal loading of the gun using the NPM package, I didn't face any issue. But while loading through scripts errors occur.

We are a startup and our product is BlockSurvey, a Web 3.0 end-to-end encrypted forms and surveys building platform. It's built on Stacks Ӿ and secured by Bitcoin. Primary we focus on privacy. Talking about the users, we do have 500+ members including some well-known organizations.

https://blocksurvey.io/

We are currently using Gaia storage provided by Stacks for decentralized storage. But before storing to Gaia we are using Firebase to fetch real-time data. Our main objective is to remove Firebase dependency and bring in Gun entirely for storage.

draeder commented 2 years ago

@Alengeorge-01 With ES6 you should be able to dynamically import like so:

const Gun = await import('/assets/js/gun.min.js')

This should work in both Node and the browser. Note that if you're using this in the browser the script tag needs to be like this:

<script type="module">
...
</script>

In node, you need to add type: "module" to your package.json file for const Gun = await import(gun)

Alengeorge-01 commented 2 years ago

Thanks a lot, @draeder. Will try this out.

amark commented 1 year ago

@Alengeorge-01 nice demo. Be neat to support. Is this the only breaking issue? (as in, does your product fully work, swapping Firebase for GUN, except just this one issue?)

Alengeorge01 commented 1 year ago

Hi @amark, The above solution helped in loading Gun dynamically. I didn't face the issue after that. We have started providing Gun as a storage option to users. Still in the beta phase and we are testing it out. I will definitely mention it if we come across any such issues. Thanks.