datatype-expansion
Advanced tools
Comparing version 0.2.0 to 0.2.1
{ | ||
"name": "datatype-expansion", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "Utility tool to expand a given RAML type and create a canonical form", | ||
"main": "src/index.js", | ||
"browser": "dist/datatype-expansion.js", | ||
"repository": "raml-org/datatype-expansion", | ||
"scripts": { | ||
"lint": "standard", | ||
"test-cov": "istanbul --include-all-sources cover --root src node_modules/mocha/bin/_mocha --report lcovonly -- -R dot --recursive --bail test/", | ||
"test-cov": "istanbul --include-all-sources cover -x index.es6.js --root src node_modules/mocha/bin/_mocha --report lcovonly -- -R dot --recursive --bail test/", | ||
"test-spec": "_mocha -R spec --recursive --bail test/", | ||
"test": "npm run lint && npm run test-cov", | ||
"browserify": "browserify src/index.js -o datatype-expansion.js -s datexp" | ||
"test": "npm-run-all lint test-cov", | ||
"build": "npm-run-all clean rollup", | ||
"clean": "rimraf dist && mkdirp dist", | ||
"rollup": "rollup -c rollup.config.js -f iife -m dist/datatype-expansion.js.map -n expansion -o dist/datatype-expansion.js", | ||
"prepublishOnly": "npm run build" | ||
}, | ||
"standard": { | ||
"ignore": [ | ||
"coverage/**", | ||
"node_modules/**", | ||
"dist/**" | ||
] | ||
}, | ||
"keywords": [ | ||
@@ -22,7 +34,19 @@ "raml", | ||
"devDependencies": { | ||
"browserify": "^14.4.0", | ||
"chai": "^4.0.2", | ||
"babel-core": "^6.26.0", | ||
"babel-plugin-external-helpers": "^6.22.0", | ||
"babel-plugin-lodash": "^3.2.11", | ||
"babel-preset-env": "^1.6.0", | ||
"chai": "^4.1.1", | ||
"cross-env": "^5.0.5", | ||
"istanbul": "^0.4.5", | ||
"mocha": "^3.4.2", | ||
"standard": "^10.0.2" | ||
"mkdirp": "^0.5.1", | ||
"mocha": "^3.5.0", | ||
"npm-run-all": "^4.0.2", | ||
"rimraf": "^2.6.1", | ||
"rollup": "^0.48.2", | ||
"rollup-plugin-babel": "^3.0.2", | ||
"rollup-plugin-commonjs": "^8.1.0", | ||
"rollup-plugin-node-resolve": "^3.0.0", | ||
"rollup-plugin-uglify": "^2.0.1", | ||
"standard": "^10.0.3" | ||
}, | ||
@@ -34,2 +58,3 @@ "dependencies": { | ||
"src/**", | ||
"dist/**", | ||
"LICENSE", | ||
@@ -36,0 +61,0 @@ "test/**" |
197
README.md
# RAML Data Type Expansion | ||
[![Build Status](https://travis-ci.org/raml-org/datatype-expansion.svg?branch=master)](https://travis-ci.org/raml-org/datatype-expansion) | ||
[![Coverage Status](https://coveralls.io/repos/github/raml-org/datatype-expansion/badge.svg?branch=master)](https://coveralls.io/github/raml-org/datatype-expansion?branch=master) | ||
@@ -12,1 +14,196 @@ > Often, tools need the full expansion of RAML data types where there are no references. This module gives you a utility tool to expand a given type and create a canonical form. | ||
``` | ||
## RAML type expanded form | ||
The RAML expanded form for a RAML type, resolves references and fills missing information to compute a fully expanded representation of the type. | ||
The form and the algorithm to compute is [documented here](doc/algorithms.md). | ||
### Usage | ||
The Node.js interface for the library offers the `expandedForm` function to compute the expanded form. | ||
It accepts an in-memory JSON representation of the type, the types mapping and a callback function. | ||
If the invocation succeeds, it will return the expanded form as an argument to the provided callback function. | ||
#### Sync API | ||
```js | ||
const tools = require('datatype-expansion'); | ||
const typesContext = { | ||
Song: { | ||
properties: { | ||
title: 'string', | ||
length: 'number' | ||
} | ||
}, | ||
Album: { | ||
properties: { | ||
title: 'string', | ||
songs: 'Songs.Song[]' | ||
} | ||
} | ||
}; | ||
const expanded = tools.expandedForm(typesContext['Album'], typesContext) | ||
console.log(JSON.stringify(expanded,null,2)); | ||
``` | ||
#### Callback API | ||
```js | ||
const tools = require('datatype-expansion'); | ||
const typesContext = { | ||
Song: { | ||
properties: { | ||
title: 'string', | ||
length: 'number' | ||
} | ||
}, | ||
Album: { | ||
properties: { | ||
title: 'string', | ||
songs: 'Songs.Song[]' | ||
} | ||
} | ||
}; | ||
tools.expandedForm(typesContext['Album'], typesContext, function(err, expanded) { | ||
// expanded contains the computed expanded form | ||
console.log(JSON.stringify(expanded,null,2)); | ||
}); | ||
``` | ||
#### Result | ||
```json | ||
{ | ||
"properties": { | ||
"title": { | ||
"type": "string", | ||
"required": true | ||
}, | ||
"songs": { | ||
"type": "array", | ||
"items": { | ||
"properties": { | ||
"title": { | ||
"type": "string", | ||
"required": true | ||
}, | ||
"length": { | ||
"type": "number", | ||
"required": true | ||
} | ||
}, | ||
"additionalProperties": true, | ||
"type": "object", | ||
"required": true | ||
}, | ||
"required": true | ||
} | ||
}, | ||
"additionalProperties": true, | ||
"type": "object", | ||
"required": true | ||
} | ||
``` | ||
## RAML type canonical form | ||
The canonical form computes inheritance and pushes unions to the top level of the type structure of an expanded RAML type. It is described in the [documentation section](doc/algorithms.md) of this repository. | ||
### Usage | ||
The Node.js version of the canonical form function is defined in the `canonicalForm` function of the library module. | ||
It accepts a JSON in-memory representation of an expanded RAML type and a callback function. It returns the canonical form or an exception: | ||
#### Sync API | ||
```js | ||
const tools = require('datatype-expansion'); | ||
const typesContext = { | ||
SimpleUnion: { | ||
properties: { | ||
a: 'string', | ||
b: 'number | string' | ||
} | ||
}, | ||
}; | ||
const expanded = tools.expandedForm(typesContext['SimpleUnion'], typesContext) | ||
const canonical = tools.canonicalForm(expanded) | ||
console.log(JSON.stringify(canonical,null,2)); | ||
``` | ||
#### Callback API | ||
```js | ||
const tools = require('datatype-expansion'); | ||
const typesContext = { | ||
SimpleUnion: { | ||
properties: { | ||
a: 'string', | ||
b: 'number | string' | ||
} | ||
}, | ||
}; | ||
tools.expandedForm(typesContext['Songs.Album'], typesContext, function(err, expanded) { | ||
tools.canonicalForm(expanded, function(err, canonical) { | ||
// canonical contains the computed canonical form | ||
console.log(canonical); | ||
}); | ||
}); | ||
``` | ||
#### Result | ||
```json | ||
{ | ||
"type": "union", | ||
"additionalProperties": true, | ||
"anyOf": [ | ||
{ | ||
"properties": { | ||
"a": { | ||
"type": "string", | ||
"required": true | ||
}, | ||
"b": { | ||
"type": "number", | ||
"required": true | ||
} | ||
}, | ||
"type": "object", | ||
"additionalProperties": true | ||
}, | ||
{ | ||
"properties": { | ||
"a": { | ||
"type": "string", | ||
"required": true | ||
}, | ||
"b": { | ||
"type": "string", | ||
"required": true | ||
} | ||
}, | ||
"type": "object", | ||
"additionalProperties": true | ||
} | ||
] | ||
} | ||
``` | ||
## Browser usage | ||
Include it via unpkg ( if you don't use a bundler like webpack ) | ||
```html | ||
<script src="https://unpkg.com/datatype-expansion"></script> | ||
``` | ||
It gets exported as `expansion` | ||
```js | ||
expansion.expandedForm('string', {}) | ||
``` | ||
## Running tests | ||
Tests for the library can be run using: | ||
``` shell | ||
$ npm run test | ||
``` |
@@ -18,10 +18,16 @@ 'use strict' | ||
module.exports.canonicalForm = function canonicalForm (expForm, cb) { | ||
let result | ||
try { | ||
result = toCanonical(expForm) | ||
} catch (e) { | ||
cb(e, null) | ||
return | ||
if (cb == null) { | ||
return toCanonical(expForm) | ||
} | ||
cb(null, result) | ||
setTimeout(() => { | ||
let result | ||
try { | ||
result = toCanonical(expForm) | ||
} catch (e) { | ||
cb(e, null) | ||
return | ||
} | ||
cb(null, result) | ||
}, 0) | ||
} | ||
@@ -28,0 +34,0 @@ |
@@ -20,10 +20,17 @@ 'use strict' | ||
const typename = keys[keys.map(t => types[t]).indexOf(type)] | ||
let result | ||
try { | ||
result = expandForm(type, types, typename ? [typename] : []) | ||
} catch (e) { | ||
cb(e, null) | ||
return | ||
if (cb == null) { | ||
return expandForm(type, types, typename ? [typename] : []) | ||
} | ||
cb(null, result) | ||
setTimeout(() => { | ||
let result | ||
try { | ||
result = expandForm(type, types, typename ? [typename] : []) | ||
} catch (e) { | ||
cb(e, null) | ||
return | ||
} | ||
cb(null, result) | ||
}, 0) | ||
} | ||
@@ -30,0 +37,0 @@ |
@@ -15,15 +15,11 @@ 'use strict' | ||
_.each(types, function (type, name) { | ||
// These two types give error in cljs library. | ||
it('should generate canonical form of type ' + name, function () { | ||
expandedForm(types[name], types, function (err, expForm) { | ||
err = null | ||
// don't run tests for forms that don't exist | ||
if (forms[name] == null) return | ||
canonicalForm(expForm, function (err, canForm) { | ||
expect(err).to.equal(null) | ||
expect(canForm).to.deep.equal(forms[name]) | ||
}) | ||
}) | ||
// don't run tests for forms that don't exist | ||
if (forms[name] == null) return | ||
const expForm = expandedForm(types[name], types) | ||
const canForm = canonicalForm(expForm) | ||
expect(canForm).to.deep.equal(forms[name]) | ||
}) | ||
}) | ||
}) |
@@ -26,2 +26,10 @@ 'use strict' | ||
it('incompatible types should throw', function () { | ||
try { | ||
const expForm = expandedForm(types['error'], types) | ||
canonicalForm(expForm) | ||
expect.fail() | ||
} catch (err) {} | ||
}) | ||
it('callback errors should work', function () { | ||
expandedForm(types['error'], types, function (err, expForm) { | ||
@@ -36,65 +44,64 @@ err = null | ||
it('invalid types should throw', function () { | ||
expandedForm('nothing', {}, function (err) { | ||
expect(err).to.not.equal(null) | ||
}) | ||
try { | ||
expandedForm('nothing', {}) | ||
expect.fail() | ||
} catch (err) {} | ||
}) | ||
it('invalid consistency check should throw', function () { | ||
expandedForm({ | ||
type: 'object', | ||
minProperties: 5, | ||
maxProperties: 1 | ||
}, {}, function (err, expForm) { | ||
err = null | ||
canonicalForm(expForm, function (err) { | ||
expect(err).to.not.equal(null) | ||
}) | ||
}) | ||
try { | ||
const expForm = expandedForm({ | ||
type: 'object', | ||
minProperties: 5, | ||
maxProperties: 1 | ||
}, {}) | ||
canonicalForm(expForm) | ||
expect.fail() | ||
} catch (err) {} | ||
expandedForm({ | ||
type: 'string', | ||
minLength: 5, | ||
maxLength: 1 | ||
}, {}, function (err, expForm) { | ||
err = null | ||
canonicalForm(expForm, function (err) { | ||
expect(err).to.not.equal(null) | ||
}) | ||
}) | ||
try { | ||
const expForm = expandedForm({ | ||
type: 'string', | ||
minLength: 5, | ||
maxLength: 1 | ||
}, {}) | ||
canonicalForm(expForm) | ||
expect.fail() | ||
} catch (err) {} | ||
expandedForm({ | ||
type: 'number', | ||
minimum: 5, | ||
maximum: 1 | ||
}, {}, function (err, expForm) { | ||
err = null | ||
canonicalForm(expForm, function (err) { | ||
expect(err).to.not.equal(null) | ||
}) | ||
}) | ||
try { | ||
const expForm = expandedForm({ | ||
type: 'number', | ||
minimum: 5, | ||
maximum: 1 | ||
}, {}) | ||
canonicalForm(expForm) | ||
expect.fail() | ||
} catch (err) {} | ||
expandedForm({ | ||
type: 'array', | ||
items: 'number', | ||
minItems: 5, | ||
maxItems: 1 | ||
}, {}, function (err, expForm) { | ||
err = null | ||
canonicalForm(expForm, function (err) { | ||
expect(err).to.not.equal(null) | ||
}) | ||
}) | ||
try { | ||
const expForm = expandedForm({ | ||
type: 'array', | ||
items: 'number', | ||
minItems: 5, | ||
maxItems: 1 | ||
}, {}) | ||
canonicalForm(expForm) | ||
expect.fail() | ||
} catch (err) {} | ||
}) | ||
it('null should throw', function () { | ||
expandedForm(null, {}, function (err) { | ||
expect(err).to.not.equal(null) | ||
}) | ||
try { | ||
expandedForm(null, {}) | ||
expect.fail() | ||
} catch (err) {} | ||
}) | ||
it('only string or object', function () { | ||
expandedForm(32, {}, function (err) { | ||
expect(err).to.not.equal(null) | ||
}) | ||
try { | ||
expandedForm(42, {}) | ||
expect.fail() | ||
} catch (err) {} | ||
}) | ||
}) |
@@ -15,8 +15,6 @@ 'use strict' | ||
it('should generate expanded form of type ' + name, function () { | ||
expandedForm(types[name], types, function (err, expForm) { | ||
expect(err).to.equal(null) | ||
expect(expForm).to.deep.equal(forms[name]) | ||
}) | ||
const expForm = expandedForm(types[name], types) | ||
expect(expForm).to.deep.equal(forms[name]) | ||
}) | ||
}) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
910723
17
3518
209
0
17