Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pids
*.seed
lib-cov
.idea
.vscode
build
node_modules
typings
Expand Down
123 changes: 61 additions & 62 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,64 +1,63 @@
{
"name": "swagger2",
"version": "0.0.20",
"description": "Typescript-based tools for working with Swagger v2.0 documents",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/carlansley/swagger2.git"
},
"keywords": [
"swagger",
"typescript",
"koa",
"koa2"
],
"author": "Carl Ansley",
"license": "MIT",
"bugs": {
"url": "https://github.com/carlansley/swagger2/issues"
},
"homepage": "https://github.com/carlansley/swagger2#readme",
"typings": "./dist/swagger.d.ts",
"dependencies": {
"is-my-json-valid": "^2.15.0",
"json-refs": "^2.1.6",
"json-schema-deref-sync": "^0.3.3",
"yamljs": "^0.2.8"
},
"devDependencies": {
"@types/mocha": "^2.2.33",
"@types/nock": "^8.2.0",
"@types/node": "^6.0.52",
"@types/yamljs": "^0.2.30",
"coveralls": "^2.11.15",
"expectations": "^0.6.0",
"istanbul": "^1.1.0-alpha.1",
"mocha": "^3.2.0",
"nock": "^9.0.2",
"remap-istanbul": "^0.8.0",
"tslint": "^4.0.2",
"typescript": "^2.1.4"
},
"maintainers": [
{
"email": "carl.ansley@gmail.com",
"name": "Carl Ansley"
"name": "swagger2",
"version": "0.0.20",
"description": "Typescript-based tools for working with Swagger v2.0 documents",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/carlansley/swagger2.git"
},
"keywords": [
"swagger",
"typescript",
"koa",
"koa2"
],
"author": "Carl Ansley",
"license": "MIT",
"bugs": {
"url": "https://github.com/carlansley/swagger2/issues"
},
"homepage": "https://github.com/carlansley/swagger2#readme",
"typings": "./dist/swagger.d.ts",
"dependencies": {
"is-my-json-valid": "^2.15.0",
"json-refs": "^2.1.6",
"json-schema-deref": "^0.3.5",
"json-schema-deref-sync": "^0.3.3",
"yamljs": "^0.2.8"
},
"devDependencies": {
"@types/mocha": "^2.2.33",
"@types/nock": "^8.2.0",
"@types/node": "^6.0.52",
"@types/yamljs": "^0.2.30",
"coveralls": "^2.11.15",
"expectations": "^0.6.0",
"istanbul": "^1.1.0-alpha.1",
"mocha": "^3.2.0",
"nock": "^9.0.2",
"remap-istanbul": "^0.8.0",
"tslint": "^4.0.2",
"typescript": "^2.1.4"
},
"maintainers": [{
"email": "carl.ansley@gmail.com",
"name": "Carl Ansley"
}],
"scripts": {
"preversion": "npm test",
"version": "npm run dist && git add -A dist",
"postversion": "git push && git push --tags",
"build": "rm -rf build && tsc && cp src/schema.json build",
"dist": "rm -rf dist && tsc src/typings.d.ts src/swagger.ts -m commonjs --outDir dist --sourcemap --target es5 -d --pretty --noImplicitAny && cp src/schema.json dist",
"clean": "rm -rf build && rm -rf coverage && rm -rf node_modules",
"lint": "tslint -c ./tslint.json --project ./tsconfig.json",
"test": "npm run build && _mocha --require expectations $(find build -name '*.spec.js') && npm run lint",
"cover": "npm run build && npm run cover:istanbul && npm run cover:remap",
"cover:browser": "npm run cover && istanbul report html && open coverage/coverage-remapped/index.html",
"cover:istanbul": "rm -rf ./coverage && istanbul cover _mocha -- --require expectations $(find build -name '*.spec.js')",
"cover:remap": "remap-istanbul -i coverage/coverage.raw.json -o coverage/coverage-remapped.json && remap-istanbul -i coverage/coverage.raw.json -o coverage/coverage-remapped.lcov -t lcovonly && remap-istanbul -i coverage/coverage.raw.json -o coverage/coverage-remapped -t html",
"coveralls": "npm run-script cover && coveralls < coverage/coverage-remapped.lcov"
}
],
"scripts": {
"preversion": "npm test",
"version": "npm run dist && git add -A dist",
"postversion": "git push && git push --tags",
"build": "rm -rf build && tsc && cp src/schema.json build",
"dist": "rm -rf dist && tsc src/typings.d.ts src/swagger.ts -m commonjs --outDir dist --sourcemap --target es5 -d --pretty --noImplicitAny && cp src/schema.json dist",
"clean": "rm -rf build && rm -rf coverage && rm -rf node_modules",
"lint": "tslint -c ./tslint.json --project ./tsconfig.json",
"test": "npm run build && _mocha --require expectations $(find build -name '*.spec.js') && npm run lint",
"cover": "npm run build && npm run cover:istanbul && npm run cover:remap",
"cover:browser": "npm run cover && istanbul report html && open coverage/coverage-remapped/index.html",
"cover:istanbul": "rm -rf ./coverage && istanbul cover _mocha -- --require expectations $(find build -name '*.spec.js')",
"cover:remap": "remap-istanbul -i coverage/coverage.raw.json -o coverage/coverage-remapped.json && remap-istanbul -i coverage/coverage.raw.json -o coverage/coverage-remapped.lcov -t lcovonly && remap-istanbul -i coverage/coverage.raw.json -o coverage/coverage-remapped -t html",
"coveralls": "npm run-script cover && coveralls < coverage/coverage-remapped.lcov"
}
}
}
14 changes: 5 additions & 9 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
*/

import * as jsonValidator from 'is-my-json-valid';
import * as deref from 'json-schema-deref-sync';

import {CollectionFormat, Definition, Document, Parameter, PathItem} from './schema';

Expand Down Expand Up @@ -142,12 +141,9 @@ function stringValidator(schema: any) {


export function compile(document: Document): Compiled {
// get the de-referenced version of the swagger document
let swagger = deref(document);

// add a validator for every parameter in swagger document
Object.keys(swagger.paths).forEach((pathName) => {
let path = swagger.paths[pathName];
Object.keys(document.paths).forEach((pathName) => {
let path = document.paths[pathName];
Object.keys(path).filter((name) => name !== 'parameters').forEach((operationName) => {
let operation = path[operationName];

Expand Down Expand Up @@ -188,12 +184,12 @@ export function compile(document: Document): Compiled {
});
});

let basePath = swagger.basePath || '';
let matcher: CompiledPath[] = Object.keys(swagger.paths)
let basePath = document.basePath || '';
let matcher: CompiledPath[] = Object.keys(document.paths)
.map((name) => {
return {
name,
path: swagger.paths[name],
path: document.paths[name],
regex: new RegExp(basePath + name.replace(/\{[^}]*}/g, '[^/]+') + '$'),
expected: (name.match(/[^\/]+/g) || []).map((s) => s.toString())
};
Expand Down
99 changes: 99 additions & 0 deletions src/deref.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// dref.spec.ts

/*
The MIT License

Copyright (c) 2016 Christian Holzberger

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the 'Software'), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
import * as assert from 'assert';
import * as swagger from './swagger';

const EXT_YML = {
name: 'base',
ref: {
name: 'ext'
}
};
/* see nested dereference bug
const ext_nested_yml = {
name: 'base',
ref: {
name: 'nested',
}
};
*/

const INT_YML = {
name: 'base',
intname: 'int',
ref: {
name: 'int'
}
};

const SUB_YML = {
name: 'base-sub',
sub: {
name: 'sub-level1',
sub: {
name: 'sub-level2'
}
}
};

const baseFolder = __dirname + '/../test/yaml/deref/';

describe('Reference resolution', () => {

describe('in async mode', () => {

it('does dereference external references in yaml files', () => {
const raw = swagger.loadDocumentSync(baseFolder + 'base.yaml');
return swagger.deref(raw, {baseFolder}).then ((document) => {
assert.deepStrictEqual(document, EXT_YML);
});
});
/*
* this doesn't work and i can't figure out why...
* perhaps a bug in json-schema-deref?

it('does dereference nested external references in yaml files', () => {
const raw = swagger.loadDocumentSync(baseFolder + 'base.nested.yaml');
return swagger.deref(raw, {baseFolder: baseFolder}).then ((document) => {
assert.deepStrictEqual(document, ext_nested_yml);
});
});
*/
it('does dereference internal references in yaml files', () => {
const raw = swagger.loadDocumentSync(baseFolder + 'internal.yaml');
return swagger.deref(raw, {baseFolder}).then ((document) => {
assert.deepStrictEqual(document, INT_YML);
});
});

it('does dereference external references to yaml files in sub folders', () => {
const raw = swagger.loadDocumentSync(baseFolder + 'base.sub.yaml');
return swagger.deref(raw, {baseFolder}).then ((document) => {
assert.deepStrictEqual(document, SUB_YML);
});
});
});
});
98 changes: 98 additions & 0 deletions src/deref.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// deref.ts

/*
The MIT License

Copyright (c) 2014-2016 Carl Ansley, Christian Holzberger

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
import js_deref = require('json-schema-deref');
import js_deref_sync = require('json-schema-deref-sync');
import * as YAML from 'yamljs';
import path = require('path');

/**
* deref is not exporting their options interface
*/
export interface DerefOptions {
baseFolder?: string;
cache?: boolean;
cacheTTL?: number;
failOnMissing?: boolean;
loader?: any;
}

/**
* custom loader for yml references
*/
async function ymlLoader( ref: string, derefOptions: DerefOptions, fn: any ) {
const isYamlRegex = /(.*\.y(a|)ml)($|#)/i;
const match = ref.match(isYamlRegex);

if ( match !== null ) {
const refFileName = match[1];
let yamlRef = YAML.load(path.join(derefOptions.baseFolder, refFileName));

const optionsOverride = {
loader: ymlLoader,
baseFolder: path.dirname(path.join(derefOptions.baseFolder, refFileName))
};

const options = Object.assign({}, derefOptions, optionsOverride);
let resolved = await derefp(yamlRef, options);
fn(null, resolved);
} else {
fn();
}
}

/*
* A wrapper for async deref to provide a promise instead
*/
async function derefp(document: any, options?: any): Promise<any> {
let p = new Promise<any> ((resolve, reject) => {
js_deref(document, options, (err: any, derefedDocument: any) => {
if ( err ) {
reject(err);
} else {
resolve(derefedDocument);
}
});
});
return p;
}

/**
* just an alias for sync dereffing of input document
*/
export function derefSync(document: any) {
return js_deref_sync(document);
}

/**
* async dereffing of input document
*/
export async function deref(document: any, derefOptions?: DerefOptions ) {
let optionsOverride: DerefOptions = {
loader: ymlLoader
};
const options = Object.assign({}, derefOptions , optionsOverride);
return await derefp(document, options);
}
2 changes: 1 addition & 1 deletion src/swagger.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import * as swagger from './swagger';

function compile(fileName: string) {
const raw = swagger.loadDocumentSync(fileName);
const document: swagger.Document | undefined = swagger.validateDocument(raw);
const document: swagger.Document | undefined = swagger.derefSync( swagger.validateDocument(raw) );

/* istanbul ignore if */
if (document === undefined) {
Expand Down
4 changes: 4 additions & 0 deletions src/swagger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
*/

import * as compiler from './compiler';
import * as ref from './deref';
import * as document from './document';
import * as schema from './schema';
import * as validate from './validate';
Expand All @@ -42,5 +43,8 @@ export const validateRequest = validate.request;
export const validateResponse = validate.response;
export const compileDocument = compiler.compile;

export const deref = ref.deref;
export const derefSync = ref.derefSync;

export import Compiled = compiler.Compiled;
export import Document = schema.Document;
Loading