New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

semantic-graphql

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

semantic-graphql - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

coverage/coverage.json

46

CHANGELOG.md
# Changelog
# 0.5.0
**Breaking changes:**
- `getIriLocalName` is not exposed/exported by the package anymore.
**New features:**
- On in-graph properties, new `shouldAlwaysUseInverseOf` and `shouldNeverUseInverseOf` config keys to modify the resolver's behavior.
**Bug fixes:**
- `isGraphqlList` is now also infered from `isGraphqlConnection`.
- `preventIdField` config option can now also prevent the Relay id field.
**Miscellaneous:**
- Tests! :tada: (very basic for now)
- Better docs
# 0.4.0
**Breaking changes:**
- resolveSourceTypes must now be sync.
- `resolvers.resolveSourceTypes` must now be sync.
- Interface type resolving was rolled back on InterfaceTypes (instead of ObjectTypes). Better support, although still incomplete. External ObjectTypes must not provide an `isTypeOf` method anymore, instead external InterfaceTypes must provide a `resolveType` method.

@@ -18,3 +34,3 @@

**Bug fixes:**
- Warn when traversing graph and encoutering missing vertices
- Warn when traversing graph and encoutering missing vertices.

@@ -27,3 +43,3 @@ # 0.3.0

**Bug fixes:**
- Bug concerning the creation of Relay types
- Bug concerning the creation of Relay types.

@@ -33,3 +49,3 @@ # 0.2.1

**Bug fixes:**
- Fixed a bug concerning the inference of owl:inverseOf
- Fixed a bug concerning the inference of owl:inverseOf.

@@ -39,20 +55,20 @@ # 0.2.0

**Breaking changes:**
- Removed resolvers.resolveSourceClassIri
- Added resolvers.resolveSourceTypes
- Removed `resolvers.resolveSourceClassIri`.
- Added `resolvers.resolveSourceTypes`.
- Interface type resolving now happens on GraphQLObjectTypes. This means that your external GraphQLObjectTypes must provide an `isTypeOf` method.
**New features:**
- Promise support for all resolvers
- Promise support for all resolvers.
**Bug fixes:**
- Fixed requireGraphqlRelay behavior
- Fixed a bug on SemanticGraph#addFieldOnObjectType
- Fixed a bug that happened when inferring owl:inverseOf on properties that are a rdfs:subProperty with no rdfs:range
- Fixed a circular dependency in ./src/graphql
- Fixed `requireGraphqlRelay` behavior.
- Fixed a bug on `SemanticGraph#addFieldOnObjectType`.
- Fixed a bug that happened when inferring owl:inverseOf on properties that are a rdfs:subProperty with no rdfs:range.
- Fixed a circular dependency in ./src/graphql.
**Miscellaneous:**
- Add MIT license
- Add .npmignore file
- id field now appears on top when introspecting
- graphqlDescription are now created from the locale in config
- Add MIT license.
- Add .npmignore file.
- id field now appears on top when introspecting.
- graphqlDescription are now created from the locale in config.

@@ -59,0 +75,0 @@ # 0.1.0

@@ -1,6 +0,1 @@

const SemanticGraph = require('./src/SemanticGraph');
const getIriLocalName = require('./src/utils/getIriLocalName');
SemanticGraph.getIriLocalName = getIriLocalName;
module.exports = SemanticGraph;
module.exports = require('./src/SemanticGraph');
{
"name": "semantic-graphql",
"version": "0.4.0",
"version": "0.5.0",
"description": "Create GraphQL schemas from RDF-based ontologies",

@@ -19,8 +19,8 @@ "main": "index.js",

},
"//test": "./node_modules/.bin/mocha $npm_package_options_mocha",
"//prepublish": "./scripts/checkgit.sh && npm test && npm run build",
"//coverage": "./node_modules/.bin/istanbul cover _mocha -- $npm_package_options_mocha",
"//coverage:serve": "cd coverage/lcov-report && python -m SimpleHTTPServer",
"//coverage:all": "npm run coverage && npm run coverage:serve",
"scripts": {
"test": "./node_modules/.bin/mocha $npm_package_options_mocha",
"coverage": "./node_modules/.bin/istanbul cover _mocha -- $npm_package_options_mocha",
"coverage:serve": "cd coverage/lcov-report && python -m SimpleHTTPServer",
"coverage:all": "npm run coverage && npm run coverage:serve",
"dev": "cd examples/basic && npm run watch"

@@ -27,0 +27,0 @@ },

@@ -10,7 +10,14 @@ # Semantic GraphQL

**Table of contents**:
- x
- y
- z
**Table of contents:**
- [Installation](#installation)
- [Getting started](#getting-started)
- [SemanticGraph API](#semanticgraph-api)
- [Resolvers](#resolvers)
- [Overriding default values](#overriding-default-values)
- [Using Relay](#using-relay)
- [OWL features roadmap](#owl-features-roadmap)
- [Contributing](#contributing)
- [License](#license)
## Installation

@@ -24,5 +31,5 @@

Semantic-graphql makes no assumption about the shape of your data and only passes it around. You have to provide six functions to resolve it in different ways. See the [resolvers section](#).
Semantic-graphql makes no assumption about the shape of your data and only passes it around. You have to provide six functions to resolve it in different ways. See the [resolvers section](#resolvers).
```javascript
```js
const resolvers = { /* Choose how to resolve data */ };

@@ -33,3 +40,3 @@ ```

```javascript
```js
const SemanticGraph = require('semantic-graphql');

@@ -42,3 +49,3 @@

```javascript
```js
_.addTriple({

@@ -55,5 +62,5 @@ subject: 'http://foo.com#MyClass',

When Semantic-graphql translates a rdf:Property to a GraphQLFieldConfig, the resulting type will be wrapped in a GraphQLList unless the property is a owl:FunctionalProperty. Therefore you may have to do some adjustments in order to prevent that. Almost anything can be overriden, see the [override section](#).
When Semantic-graphql translates a rdf:Property to a GraphQLFieldConfig, the resulting type will be wrapped in a GraphQLList unless the property is a owl:FunctionalProperty. Therefore you may have to do some adjustments in order to prevent that. Almost anything can be overriden, see the [override section](#overriding-default-values).
```javascript
```js
// We do not want rdfs:label to resolve arrays

@@ -65,3 +72,3 @@ _['http://www.w3.org/2000/01/rdf-schema#label'].isGraphqlList = false;

```javascript
```js
const schema = new GraphQLSchema({

@@ -89,35 +96,214 @@ query: new GraphQLObjectType({

Have a look at the [examples folder](#) to see a complete setup.
Have a look at the [examples folder](examples/) to see a complete setup.
## Using relay
## SemanticGraph API
By using the `relay: true` option:
```
class SemanticGraph {
constructor(resolvers: Resolvers, config: ?SemanticGraphConfig),
[subject: Iri]: object,
# Public methods:
addTriple: AddTripleFn,
parse: ParseFn,
parseFile: ParseFileFn,
getObjectType: GetObjectTypeFn,
getInterfaceType: GetInterfaceTypeFn,
getEdgeType: GetEdgeTypeFn,
getConnectionType: GetConnectionTypeFn,
addFieldOnObjectType: AddFieldOnObjectTypeFn,
extendFieldOnObjectType: ExtendFieldOnObjectTypeFn,
# When the relay option is on:
nodeField: GraphQLFieldConfig,
nodeInterface: GraphQLInterfaceType,
}
- The `_.nodeField` and `_.nodeInterface` object are available
- The `_.getConnectionType` and `_.getEdgeType` methods are available
- All ObjectTypes exhibit the Node interface
- The id field is a globalIdField
type SemanticGraphConfig = {
prefixes?: PrefixConfig,
# Activates the Relay features
relay?: boolean,
# Your reprefered locale when inferring names and descriptions from rdfs:label and rdfs:comment
locale?: string = 'en',
# Prevents the id field to be automatically added to every GraphlQLFieldConfigMap
preventIdField?: boolean,
}
```
See the [Relay example](#).
To prevent GraphQL names collisions, you can edit the name directly (see the [override section](#overriding-default-values))
or specifify prefixes for ontology namespaces.
The names of the generated GraphQL objects will be prefixed.
RDF, RDFS and OWL ontologies are by default prefixed with "Rdf", "Rdfs" and "Owl".
So a fragment on rdfs:Resource should be "on RdfsResource".
## API
```
type PrefixConfig = {
[prefix: string]: Iri,
}
### SemanticGraph
# Must represent a valid IRI
type Iri = string
```
### Resolvers
### addTriple
#### resolveSourceId
```
type AddTripleFn(triple: Triple) => undefined
#### resolveSourceTypes
type Triple = {
subject: Iri,
predicate: Iri,
object: Iri | string,
}
```
Must be sync. See [this GraphQL issue](https://github.com/graphql/graphql-js/issues/398).
Appends a triple to the graph. No-op if the subject or predicate IRI is invalid, or if the triple already exists.
#### resolveSourcePropertyValue
### parse
#### resolveResource
Will be removed someday
#### resolveResources
### parseFile
#### resolveResourcesByPredicate
Will be removed someday
### getObjectType
```
type GetObjectTypeFn = (classIri: Iri) => GraphQLObjectType
```
Returns the GraphQLObjectType corresponding to a given individual of rdfs:Class or its sub-classes (like owl:Class). Throws if the IRI is not found in the graph.
### getInterfaceType
```
type GetInterfaceTypeFn = (classIri: Iri) => GraphQLInterfaceType
```
### getEdgeType
```
type GetEdgeTypeFn = (classIri: Iri) => ?RelayEdgeType
```
Returns a value only when the `relay: true` option is on.
### getConnectionType
```
type GetConnectionTypeFn = (classIri: Iri) => ?RelayConnectionType
```
Returns a value only when the `relay: true` option is on.
### addFieldOnObjectType
```
type AddFieldOnObjectTypeFn = (
classIri: Iri,
fieldName: string,
graphqlFieldConfig: GraphQLFieldConfig
) => Iri
```
Adds a custom field "fieldName" on the GraphQLObjectType and GraphQLInterfaceType representing "classIri".
Throws if "classIri" is not found in the graph.
Returns a random IRI referencing the new virtual rdf:Property.
### extendFieldOnObjectType
```
type AddFieldOnObjectTypeFn = (
classIri: Iri,
propertyIri: Iri,
graphqlFieldConfig: PseudoGraphQLFieldConfig
) => undefined
```
Similar to overriding a field using `_['http://foo.com/someProperty'].graphqlFieldConfigExtension = /* ... */` but only for a particular class, not for all of the classes on the property's domain.
A `PseudoGraphQLFieldConfig` is just a `GraphQLFieldConfig` where every key is optional. The other keys will be infered.
Throws if "classIri" is not found in the graph.
## Resolvers
```
type Resolvers = {
resolveSourceId: ResolveSourceIdFn,
resolveSourceTypes: ResolveSourceTypesFn,
resolveSourcePropertyValue: ResolveSourcePropertyValueFn,
resolveResource: ResolveResourceFn,
resolveResources: ResolveResourcesFn,
resolveResourcesByPredicate: ResolveResourcesByPredicateFn,
}
type ResolverOutput<x> = x | Array<x> | Promise<x> | Promise<Array<x>>
```
### resolveSourceId
```
type ResolveSourceIdFn = (
source?: any,
context?: any,
info?: GraphQLResolveInfo
) => ?ID | ?Promise<ID>
```
Must be sync if you use Relay.
See [`globalIdField` source code](https://github.com/graphql/graphql-relay-js/blob/master/src/node/node.js#L107)
### resolveSourceTypes
```
type ResolveSourceTypesFn = (
source?: any,
info?: GraphQLResolveInfo
) => Iri | Array<Iri>
```
Must be sync.
See [this GraphQL issue](https://github.com/graphql/graphql-js/issues/398).
### resolveSourcePropertyValue
```
type ResolveSourcePropertyValueFn = (
source?: any,
propertyIri?: Iri,
context?: any,
info?: GraphQLResolveInfo
) => ?ResolverOutput<any>
```
### resolveResource
```
type ResolveResourceFn = (
resourceIri?: Iri,
context?: any,
info?: GraphQLResolveInfo
) => ?ResolverOutput<any>
```
### resolveResources
```
type ResolveResourcesFn = (
resourceIris?: Array<Iri>,
context?: any,
info?: GraphQLResolveInfo
) => ?ResolverOutput<any>
```
### resolveResourcesByPredicate
```
type ResolveResourcesByPredicateFn = (
typeIri?: Array<Iri>,
predicateIri?: Iri,
value?: any,
context?: any,
info?: GraphQLResolveInfo
) => ?ResolverOutput<any>
```
## Overriding default values

@@ -127,3 +313,3 @@

```javascript
```js
_['http://the.resource.to/be#altered'].key = value;

@@ -146,7 +332,9 @@ ```

| property | graphqlFieldConfigExtension | partial GraphQLFieldConfig, to modify only parts of it |
| property | shouldAlwaysUseInverseOf | Boolean |
| property | shouldNeverUseInverseOf | Boolean |
Note that the following overrides must be performed *before* invoking `getObjectType` or `getInterfaceType` or `getEdgeType` or `getConnectionType` since those methods create the GraphQL objects you want to override.
Example:
```javascript
Examples:
```js
_['http://foo.com#worksForCompany'].graphqlName = 'company';

@@ -156,8 +344,22 @@ // Now the field name for foo:worksForCompany will be 'company'

// Partial modifications to fields are achieved using
_['http://foo/com#worksForCompany'].graphqlFieldConfigExtension = {
_['http://foo.com#worksForCompany'].graphqlFieldConfigExtension = {
args: /* Look Ma', arguments! */
resolve: customResolveFn,
};
// Completly overriding a GraphQLObject can be done with
_['http://foo.com/MyClass'].graphqlObjectType = new GraphQLObjectType({ /* ... */});
```
## Using Relay
By using the `relay: true` option:
- The `_.nodeField` and `_.nodeInterface` object are available
- The `_.getConnectionType` and `_.getEdgeType` methods are available
- All ObjectTypes exhibit the Node interface
- The id field is a globalIdField
See the [Relay example](examples/relay).
## OWL features roadmap

@@ -187,3 +389,3 @@

- Some items of the preceding list might be impossible to implement and end up here
- Some items of the preceding list might be impossible to implement and end up here.

@@ -194,6 +396,8 @@ ## Contributing

## Licence
## License
Semantic GraphQL is released under the MIT License.
GraphQL is released by Facebook, inc. under the [BSD-license](https://github.com/graphql/graphql-js/blob/master/LICENSE) with an additional [patent grant](https://github.com/graphql/graphql-js/blob/master/PATENTS).
GraphQL is released by Facebook, inc. under the [BSD-license](https://github.com/graphql/graphql-js/blob/master/LICENSE)
with an additional
[patent grant](https://github.com/graphql/graphql-js/blob/master/PATENTS).

@@ -20,4 +20,2 @@ const { GraphQLList } = require('graphql');

function getGraphqlFieldConfig(g, iri) {
// console.log('getGraphqlFieldConfig', iri);
// Look for a range, return it if found

@@ -24,0 +22,0 @@ // Otherwise for each super-property, look for a range, if not found, check their super-properties and so on

@@ -27,12 +27,14 @@ const { GraphQLID } = require('graphql');

// Add id field
if (g.config.relay) {
fieldConfigMap.id = requireGraphqlRelay().globalIdField(getGraphqlName(g, iri), g.resolvers.resolveSourceId);
if (!g.config.preventIdField) {
if (g.config.relay) {
fieldConfigMap.id = requireGraphqlRelay().globalIdField(getGraphqlName(g, iri), g.resolvers.resolveSourceId);
}
else {
fieldConfigMap.id = {
type: GraphQLID,
description: 'A unique identifier for the resource.',
resolve: (source, args, context, info) => g.resolvers.resolveSourceId(source, context, info),
};
}
}
else if (!g.config.preventIdField) {
fieldConfigMap.id = {
type: GraphQLID,
description: 'A unique identifier for the resource.',
resolve: (source, args, context, info) => g.resolvers.resolveSourceId(source, context, info),
};
}

@@ -39,0 +41,0 @@ // Add other fields

@@ -9,3 +9,2 @@ const { owlInverseOf, _owlInverseOf, rdfsDomain, _rdfsSubClassOf } = require('../constants');

function getGraphqlObjectResolver(g, iri, ranges) {
const { resolvers } = g;
const isList = isGraphqlList(g, iri);

@@ -16,3 +15,3 @@

// If inverseProperties exists, we can use them to retrieve missing remote data
if (g[iri][owlInverseOf] || g[iri][_owlInverseOf]) {
if (!g[iri].shouldNeverUseInverseOf && ([iri][owlInverseOf] || g[iri][_owlInverseOf])) {
const extendedRanges = new Set();

@@ -49,41 +48,52 @@ const inverseProperties = new Set();

// XXX: put outside of scope to avoid re-allocation ?
// The actual resolve function
const resolver = (source, args, context, info) => Promise.resolve(resolvers.resolveSourcePropertyValue(source, iri, context, info))
.then(ref => {
const hasNoInverseOf = !(inverseOfMap && inverseOfMap.size);
const resolveNothing = () => isList ? [] : null;
const resolveResource = isList ? g.resolvers.resolveResources : g.resolvers.resolveResource;
if (!isNil(ref)) {
return (isList ? resolvers.resolveResources : resolvers.resolveResource)(castArrayShape(ref, isList), context, info);
}
// A resolver for inverseOf properties
const inverseOfResolver = (source, args, context, info) => {
if (hasNoInverseOf) return resolveNothing();
// No reference(s) to data was resolved, maybe the data is on an inverse Property
if (inverseOfMap && inverseOfMap.size) {
return Promise.resolve(g.resolvers.resolveSourceId(source, context, info))
.then(sourceId => {
return Promise.resolve(resolvers.resolveSourceId(source, context, info))
.then(sourceId => {
const promises = [];
const promises = [];
inverseOfMap.forEach((admitingRanges, propertyIri) => {
promises.push(g.resolvers.resolveResourcesByPredicate(admitingRanges, propertyIri, sourceId, context, info));
});
inverseOfMap.forEach((admitingRanges, propertyIri) => {
promises.push(resolvers.resolveResourcesByPredicate(admitingRanges, propertyIri, sourceId, context, info));
});
return Promise.all(promises)
.then(results => {
const finalResult = results.reduce((a, b) => a.concat(b), []);
return Promise.all(promises)
.then(results => {
const finalResult = results.reduce((a, b) => a.concat(b), []);
return isList ? finalResult : finalResult[0];
});
return isList ? finalResult : finalResult[0];
});
}
});
};
// Give up
return isList ? [] : null;
});
// XXX: put outside of scope to avoid re-allocation ?
// The actual resolve function
const resolver = (source, args, context, info) => {
if (g[iri].shouldAlwaysUseInverseOf) return inverseOfResolver(source, args, context, info);
return Promise.resolve(g.resolvers.resolveSourcePropertyValue(source, iri, context, info))
.then(ref => {
// A reference to data was resolved, we resolve the underlying resources
// NOTE: this does not aggregate both direct and inverse data
if (!isNil(ref)) return resolveResource(castArrayShape(ref, isList), context, info);
// No reference to data was resolved, maybe the data is on an inverse Property
if (!g[iri].shouldNeverUseInverseOf) return inverseOfResolver(source, args, context, info);
// Give up
return resolveNothing();
});
};
if (g.config.relay && g[iri].isRelayConnection) {
const { connectionFromArray, connectionFromPromisedArray } = requireGraphqlRelay();
return (node, args, context, info) => {
const results = resolver(node, args, context, info);
return (source, args, context, info) => {
const results = resolver(source, args, context, info);

@@ -90,0 +100,0 @@ return (Array.isArray(results) ? connectionFromArray : connectionFromPromisedArray)(results, args);

@@ -5,5 +5,5 @@ const { rdfType, owlFunctionalProperty } = require('../constants');

function isGraphqlList(g, iri) {
return !(g[iri][rdfType] && g[iri][rdfType].includes(owlFunctionalProperty));
return g[iri].isRelayConnection || !(g[iri][rdfType] && g[iri][rdfType].includes(owlFunctionalProperty));
}
module.exports = memorize(isGraphqlList, 'isGraphqlList');
let graphqlRelay;
// optionnalPeerDependencies still don't exist, so graphql-relay is a ghost dep
// optionalPeerDependencies still don't exist, so graphql-relay is a ghost dep
// let's find it

@@ -5,0 +5,0 @@ function requireGraphqlRelay() {

@@ -86,2 +86,4 @@ const path = require('path');

/* Private methods */
function indexTriple(g, { subject, predicate, object }) {

@@ -88,0 +90,0 @@ if (!(isIri(subject) && isIri(predicate)) || g[subject] && g[subject][predicate] && g[subject][predicate].includes(object)) return;

function warn(message) {
console.log(`[semantic-graphql warning]: ${message}`);
console.warn(`[semantic-graphql] ${message}`);
}
module.exports = warn;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc