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

Syncronous API #14

Closed
damienleroux opened this issue Mar 22, 2016 · 34 comments
Closed

Syncronous API #14

damienleroux opened this issue Mar 22, 2016 · 34 comments

Comments

@damienleroux
Copy link

Hey!

You did a great job here!

I need to use your API syncronously ( because I need it in a syncronous framework). Is there any plan to do it in the future?

Thank you

@JamesMessinger
Copy link
Member

yeah, that's doable. obviously, it'll only work in Node though. Resolving external $refs in the browser has to be async, since it has to download the files

@damienleroux
Copy link
Author

Indeed, I need it server side only in my case

@willfarrell
Copy link

willfarrell commented Apr 2, 2016

Right now I'm using something like:

var data, done = false; 
    $RefParser.dereference(schema, function(err, schema) {
        if (err) {
            console.error(err);
                     return done = false;
        }
        data = schema;
        done = true;
    });
    require('deasync').loopWhile(function(){return !done;});
    return data;

@cabeese
Copy link

cabeese commented Jun 22, 2016

I'd love to see this as well.

@coltonlw
Copy link

+1

@aaronshaf
Copy link

This would make using supertest easier as well. +1

@Abrahamic-God
Copy link

Apologies for the +1 spam, but I'd love to see this as well. For my use case, I only need synchronous support for resolving local file references. I would not need to synchronously resolve remote HTTP references.

@JamesMessinger
Copy link
Member

Good news. I've already started working on a synchronous API 👍

@Abrahamic-God
Copy link

@BigstickCarpet I have a need for the synchronous API as soon as possible, and would be happy to contribute to help get it ready for release. Is there a branch and list of remaining tasks that I could dive into? Thanks!

@JamesMessinger
Copy link
Member

Hi @lange - You can see my work-in-progress here, but it's not finished yet or ready to use. I'm not quite ready to accept pull-requests yet, because the code is still very much in flux. This is a complete rewrite with a brand-new API, and nothing is fully solidified yet. It already has a synchronous API though, and a few tests that use it, so I'm definitely making good progress. I hope to have an alpha version ready for public feedback and testing within a few weeks.

@Abrahamic-God
Copy link

Understood - thanks for the reply @BigstickCarpet!

@mashpie
Copy link

mashpie commented Dec 12, 2017

add +1 to get notified - thanks a lot :)

@willfarrell
Copy link

@mashpie For future reference there is a Subscribe button on the right side under notifications.

@mashpie
Copy link

mashpie commented Dec 13, 2017

@willfarrell true, wanted to opt my plus one in addition

@MikeTaylor
Copy link

Did anything ever come of this? I, too, would very very much love to do

const expandedSchema = $RefParser.dereferenceNowDammit(mySchema);

without having to mess about with callbacks and promises.

@MikeTaylor
Copy link

In the mean time, I made this: https://github.com/MikeTaylor/json-schema-ref-parser-sync

I'm not proud of it, but it works. I hope it's of use to someone else.

@epicfaace
Copy link

This would be great to implement.

@joelgallant
Copy link

I've had to manually write this logic in my application because it supports a sync & async API. Does anyone have a rough outline of which APIs this would need to support? A bit of direction and I'd be willing to work on it.

@mhuggins
Copy link

The deasync solution mentioned by @willfarrell and used by apidoc-plugin-schema unfortunately no longer works with the latest versions of json-schema-ref-parser since it's built on async/await.

@mhuggins
Copy link

mhuggins commented Feb 27, 2020

I think this can be fixed by calling process.nextTick() (for node, anyway) within the deasync loop, but I haven't reached a final solution yet.

@llirikkk
Copy link

This library works for me: https://www.npmjs.com/package/json-schema-deref-sync

@philsturgeon
Copy link
Member

Is this still necessary in an async/await world? It seems like the complaints of “I don’t want to mess around with callbacks and promises” would no longer be relevant with a bit of await now?

@Abrahamic-God
Copy link

@philsturgeon The exception is in constructors, which must be sync.

@llirikkk
Copy link

@philsturgeon the problem is not in the complexity, but in that some use cases require synchronous behaviour. With async version the users of my function had to always add await, when invoking the function. But the often forgot to do this, because the function was meant to be used in a synchronous context. And because of this they often ended up with unhandled promise rejection errors, which were swallowed by Node.

@JamesMessinger
Copy link
Member

The problem is that the library currently does too much in a single function. Functions like dereference() and bundle() currently do all of the following:

  1. Read files from disk
  2. Download files from URLs
  3. Parse data from YAML, JSON, etc.
  4. Resolve all the $ref pointers in each file
  5. Dereference all $ref pointers in each file

Only #1 and #2 need to be async. All the rest can be done synchronously. And, indeed, many people don't need #1 and #2 at all because they already have the schema object in memory, not in a file on disk.

I'm currently working on separating the above functionality into separate functions so they'll work better with workflows that could be fully synchronous.

@iPherian
Copy link

@philsturgeon Node is still heavily synchronous. I have a node module which does dereference() while creating module.exports and it's used by most of the program.

@philsturgeon
Copy link
Member

I'm considering my question answered already folks, don't need to keep explaining it! 😅

From @JamesMessinger

I'm currently working on separating the above functionality into separate functions so they'll work better with workflows that could be fully synchronous.

Looking forward to that.

@michaelmelody91
Copy link

michaelmelody91 commented Sep 24, 2020

Hey all, reaching out in desperation as a bit of a JS/Node noob when it comes to async/await... I've a couple of questions that if anyone could help me with or at least point me in the right direction, I'd be massively grateful.

My use case is that I'm attempting to return an object from a function and within that function I'm required to parse out a schema.

  1. Other that using Syncronous API #14 (comment) (which I've not been able to use, a previous comment mentions that this is no longer possible with the latest version of the parser), is there any way to hack a sycnronous implementation of this - I've attempted to use a callback to set a done variable to true in combination with a while(!done) - again, I've not been able to configure this correctly and I fall into a never ending loop. See below.
    let savedError,
      savedResult,
      done = true;

    $RefParser.dereference(doc, (error, result) => {
      console.log('trying to deref....')
      savedError = error;
      savedResult = result;
      done = true;
    });

    while(!done){}
  1. What prevents the deasync module working with the latest version of the parser?

Note: I'm doing this in a TS project.

@anttiviljami
Copy link

@michaelmelody91 and for anyone interested, I was able to get synchronous dereferencing for a schema object like so:

import $RefParser from '@apidevtools/json-schema-ref-parser';
import _dereference from '@apidevtools/json-schema-ref-parser/lib/dereference';

export const dereference = (schema) => {
  const parser = new $RefParser();
  parser.parse(schema);
  parser.schema = schema;
  _dereference(parser); // NOTE: mutates schema
  return schema;
};

@anttiviljami
Copy link

The caveat of the solution above is that it mutates the original object, which may not be what you want.

You should probably make a deep copy of the schema object before running require('@apidevtools/json-schema-ref-parser/lib/dereference') on it.

@philsturgeon
Copy link
Member

Ok there are a couple of workarounds suggested and the new library will have a synchronous option, so lets call this thread a day. Thank you!

@minhpfg
Copy link

minhpfg commented Jun 16, 2021

Ok there are a couple of workarounds suggested and the new library will have a synchronous option, so lets call this thread a day. Thank you!

Hi @philsturgeon, can you elaborate more on "the new library will have a synchronous option"? What is this "new library" you speak of?

@philsturgeon
Copy link
Member

Over here: https://github.com/APIDevTools/json-schema-reader

This tool will eventually replace json-schema-ref-parser but is not yet complete. The goal is to continue meaningful changes over there whilst getting it ship shape, although priorities and availability for the maintainers is a struggle at the moment.

If you'd like to muck about with that lib and see how far you get that'd be handy.

@wozny1989
Copy link

@michaelmelody91 and for anyone interested, I was able to get synchronous dereferencing for a schema object like so:

import $RefParser from '@apidevtools/json-schema-ref-parser';
import _dereference from '@apidevtools/json-schema-ref-parser/lib/dereference';

export const dereference = (schema) => {
  const parser = new $RefParser();
  parser.parse(schema);
  parser.schema = schema;
  _dereference(parser); // NOTE: mutates schema
  return schema;
};

I had a problem with this solution, because the latest version require option attribute with specific keys.
I resolved that on this way and everything works synchronous fine:

_dereference(parser, { dereference: { circular: true } }); // NOTE: mutates schema

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests