diff --git a/README.md b/README.md index 7a3d22e..d9f75a3 100644 --- a/README.md +++ b/README.md @@ -48,32 +48,46 @@ Dredd Transactions library is written in JavaScript (ES2015+). ## Usage -### `compile` +### `parse` -Compiles *HTTP Transactions* from given API description document. +Parses given API description document into API Elements with options specific +to Dredd. Assumes that documents with unrecognizable format are +[API Blueprint][api-blueprint]. Turns any parser failures, including +the unexpected ones, into [API Elements][api-elements] annotations. ```javascript -var dt = require('dredd-transactions'); +const parse = require('dredd-transactions/parse'); +// const { parse } = require('dredd-transactions'); -dt.compile('# My API\n...', 'apiary.apib', function (error, compileResult) { +parse('# My API\n...', (error, parseResult) => { // ... }); ``` -### Arguments +### `compile` + +Compiles *HTTP Transactions* from given [API Elements][api-elements]. *HTTP Transactions* are a backbone data structure to Dredd. -- (string) - API description document provided as string. -- (string) - Original file name of the API description document. **To be removed! See [#6][filename-deprecation].** -- (function) - Callback. +```javascript +const compile = require('dredd-transactions/compile'); +// const { compile } = require('dredd-transactions'); -### Callback Arguments +const compileResult = compile(mediaType, apiElements, filename); +``` -- (enum[null, object]) - Standard JavaScript error object. -- ([Compile Result][compile-result-object-spec]) +> **Note:** The `filename` argument is optional and about to get deprecated, see [#6][filename-deprecation] ## Data Structures + +### Parse Result (object) + +Result of parsing. + +- `mediaType`: `text/vnd.apiblueprint` (string, default, nullable) - Media type of the input format, can be empty in case of some fatal errors +- `apiElements` ([API Elements][api-elements]) - API Elements parse result + ### Compile Result (object) @@ -161,9 +175,10 @@ Description of an error or warning which occurred during parsing of the API desc > **Note:** These properties are to be superseded by whatever comes out of the proposal in [apiaryio/dredd#227](https://github.com/apiaryio/dredd/issues/227). -[dredd]: https://github.com/apiaryio/dredd +[dredd]: https://dredd.org [mson-spec]: https://github.com/apiaryio/mson [api-elements]: http://api-elements.readthedocs.org/ +[api-blueprint]: https://apiblueprint.org/ [api-blueprint-glossary]: https://github.com/apiaryio/api-blueprint/blob/master/Glossary%20of%20Terms.md [blueprint-transactions]: https://github.com/apiaryio/blueprint-transactions/ diff --git a/lib/compileTransactionName.js b/compile/compileTransactionName.js similarity index 100% rename from lib/compileTransactionName.js rename to compile/compileTransactionName.js diff --git a/lib/compileURI/compileParams.js b/compile/compileURI/compileParams.js similarity index 100% rename from lib/compileURI/compileParams.js rename to compile/compileURI/compileParams.js diff --git a/lib/compileURI/expandURItemplate.js b/compile/compileURI/expandURItemplate.js similarity index 100% rename from lib/compileURI/expandURItemplate.js rename to compile/compileURI/expandURItemplate.js diff --git a/lib/compileURI/index.js b/compile/compileURI/index.js similarity index 100% rename from lib/compileURI/index.js rename to compile/compileURI/index.js diff --git a/lib/compileURI/validateParams.js b/compile/compileURI/validateParams.js similarity index 100% rename from lib/compileURI/validateParams.js rename to compile/compileURI/validateParams.js diff --git a/lib/detectTransactionExampleNumbers.js b/compile/detectTransactionExampleNumbers.js similarity index 100% rename from lib/detectTransactionExampleNumbers.js rename to compile/detectTransactionExampleNumbers.js diff --git a/lib/compile.js b/compile/index.js similarity index 100% rename from lib/compile.js rename to compile/index.js diff --git a/index.js b/index.js new file mode 100644 index 0000000..59d0bc5 --- /dev/null +++ b/index.js @@ -0,0 +1,5 @@ +const parse = require('./parse'); +const compile = require('./compile'); + + +module.exports = { parse, compile }; diff --git a/lib/index.js b/lib/index.js deleted file mode 100644 index 3833380..0000000 --- a/lib/index.js +++ /dev/null @@ -1,25 +0,0 @@ -const parse = require('./parse'); -const compileFromApiElements = require('./compile'); - - -function compile(apiDescription, filename, callback) { - parse(apiDescription, (err, parseResult) => { - // Shouldn't happen, 'parse' turns all parser crashes into annotations - if (err) { callback(err); return; } - - // Should always set annotations and never throw, try/catch deals only - // with unexpected compiler crashes - let compileResult; - try { - const { mediaType, apiElements } = parseResult; - compileResult = compileFromApiElements(mediaType, apiElements, filename); - } catch (syncErr) { - callback(syncErr); - return; - } - callback(null, compileResult); - }); -} - - -module.exports = { compile }; diff --git a/package.json b/package.json index 7b3b3d6..723a494 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "dredd-transactions", "version": "0.0.0-semantically-released", "description": "Compiles HTTP Transactions (Request-Response pairs) from an API description document", - "main": "lib/index.js", + "main": "index.js", "engines": { "node": ">= 6" }, @@ -24,7 +24,8 @@ "url": "https://github.com/apiaryio/dredd-transactions" }, "files": [ - "lib", + "parse", + "compile", "README.md" ], "dependencies": { diff --git a/lib/parse.js b/parse/index.js similarity index 100% rename from lib/parse.js rename to parse/index.js diff --git a/scripts/pretest.js b/scripts/pretest.js index 0737d68..6361d96 100644 --- a/scripts/pretest.js +++ b/scripts/pretest.js @@ -5,7 +5,7 @@ const fs = require('fs'); const fury = require('fury'); -const parse = require('../lib/parse'); +const parse = require('../parse'); const FIXTURES_DIR = path.join(__dirname, '..', 'test', 'fixtures'); diff --git a/scripts/smoke.sh b/scripts/smoke.sh index e2ecbcd..11072f4 100755 --- a/scripts/smoke.sh +++ b/scripts/smoke.sh @@ -56,10 +56,29 @@ if [ ! -z "$TRAVIS" ]; then "The packaging of Dredd Transactions should have prevented this." echo "======================================================================" exit 1 - else - echo "SUCCESS" - echo "======================================================================" fi + + echo "Importing dredd-transactions" + echo "======================================================================" + echo "const assert = require('assert');" > index.js + echo "const dt = require('dredd-transactions');" >> index.js + echo "assert.ok(typeof dt.parse === 'function');" >> index.js + echo "assert.ok(typeof dt.compile === 'function');" >> index.js + node index.js + + echo "======================================================================" + echo "Importing dredd-transactions/parse and dredd-transactions/compile" + echo "======================================================================" + echo "const assert = require('assert');" > index.js + echo "const parse = require('dredd-transactions/parse');" >> index.js + echo "const compile = require('dredd-transactions/compile');" >> index.js + echo "assert.ok(typeof parse === 'function');" >> index.js + echo "assert.ok(typeof compile === 'function');" >> index.js + node index.js + + echo "======================================================================" + echo "SUCCESS" + echo "======================================================================" else exit 1 fi diff --git a/test/integration/compile-test.js b/test/integration/compile-test.js index a48be1b..9389e0b 100644 --- a/test/integration/compile-test.js +++ b/test/integration/compile-test.js @@ -4,7 +4,7 @@ const createAnnotationSchema = require('../schemas/createAnnotationSchema'); const createCompileResultSchema = require('../schemas/createCompileResultSchema'); const { assert, fixtures } = require('../support'); -const compile = require('../../lib/compile'); +const compile = require('../../compile'); describe('compile() · all API description formats', () => { @@ -146,8 +146,8 @@ describe('compile() · all API description formats', () => { // we need to pretend it's possible in this test. fixtures('ordinary').forEachDescribe(({ mediaType, apiElements }) => { const message = '... dummy warning message ...'; - const stubbedCompile = proxyquire('../../lib/compile', { - './compileURI': proxyquire('../../lib/compileURI', { + const stubbedCompile = proxyquire('../../compile', { + './compileURI': proxyquire('../../compile/compileURI', { './expandURItemplate': () => ({ uri: '/honey?beekeeper=Honza', errors: [], warnings: [message] }), }), }); @@ -207,8 +207,8 @@ describe('compile() · all API description formats', () => { // test. fixtures('ordinary').forEachDescribe(({ mediaType, apiElements }) => { const message = '... dummy warning message ...'; - const stubbedCompile = proxyquire('../../lib/compile', { - './compileURI': proxyquire('../../lib/compileURI', { + const stubbedCompile = proxyquire('../../compile', { + './compileURI': proxyquire('../../compile/compileURI', { './validateParams': () => ({ errors: [], warnings: [message] }), }), }); diff --git a/test/integration/compileAPIB-test.js b/test/integration/compileAPIB-test.js index 6695683..754858e 100644 --- a/test/integration/compileAPIB-test.js +++ b/test/integration/compileAPIB-test.js @@ -3,10 +3,10 @@ const proxyquire = require('proxyquire').noPreserveCache(); const createAnnotationSchema = require('../schemas/createAnnotationSchema'); const createCompileResultSchema = require('../schemas/createCompileResultSchema'); -const detectTransactionExampleNumbers = require('../../lib/detectTransactionExampleNumbers'); +const detectTransactionExampleNumbers = require('../../compile/detectTransactionExampleNumbers'); const { assert, fixtures } = require('../support'); -const compile = require('../../lib/compile'); +const compile = require('../../compile'); describe('compile() · API Blueprint', () => { @@ -52,7 +52,7 @@ describe('compile() · API Blueprint', () => { describe('with multiple transaction examples', () => { const detectTransactionExampleNumbersStub = sinon.spy(detectTransactionExampleNumbers); - const stubbedCompile = proxyquire('../../lib/compile', { + const stubbedCompile = proxyquire('../../compile', { './detectTransactionExampleNumbers': detectTransactionExampleNumbersStub, }); const { mediaType, apiElements } = fixtures('multiple-transaction-examples').apib; @@ -99,7 +99,7 @@ describe('compile() · API Blueprint', () => { describe('without multiple transaction examples', () => { const detectTransactionExampleNumbersStub = sinon.spy(detectTransactionExampleNumbers); - const stubbedCompile = proxyquire('../../lib/compile', { + const stubbedCompile = proxyquire('../../compile', { './detectTransactionExampleNumbers': detectTransactionExampleNumbersStub, }); const { mediaType, apiElements } = fixtures('one-transaction-example').apib; diff --git a/test/integration/compileOpenAPI2-test.js b/test/integration/compileOpenAPI2-test.js index b2d4b54..ed209bd 100644 --- a/test/integration/compileOpenAPI2-test.js +++ b/test/integration/compileOpenAPI2-test.js @@ -3,10 +3,10 @@ const proxyquire = require('proxyquire'); const createAnnotationSchema = require('../schemas/createAnnotationSchema'); const createCompileResultSchema = require('../schemas/createCompileResultSchema'); -const detectTransactionExampleNumbers = require('../../lib/detectTransactionExampleNumbers'); +const detectTransactionExampleNumbers = require('../../compile/detectTransactionExampleNumbers'); const { assert, fixtures } = require('../support'); -const compile = require('../../lib/compile'); +const compile = require('../../compile'); describe('compile() · OpenAPI 2', () => { @@ -135,7 +135,7 @@ describe('compile() · OpenAPI 2', () => { describe('with multiple responses', () => { const filename = 'apiDescription.json'; const detectTransactionExampleNumbersStub = sinon.spy(detectTransactionExampleNumbers); - const stubbedCompile = proxyquire('../../lib/compile', { + const stubbedCompile = proxyquire('../../compile', { './detectTransactionExampleNumbers': detectTransactionExampleNumbersStub, }); const { mediaType, apiElements } = fixtures('multiple-responses').openapi2; diff --git a/test/integration/compileOpenAPI3-test.js b/test/integration/compileOpenAPI3-test.js index 7927592..fdf7568 100644 --- a/test/integration/compileOpenAPI3-test.js +++ b/test/integration/compileOpenAPI3-test.js @@ -1,7 +1,7 @@ const createCompileResultSchema = require('../schemas/createCompileResultSchema'); const { assert, fixtures } = require('../support'); -const compile = require('../../lib/compile'); +const compile = require('../../compile'); describe('compile() · OpenAPI 3', () => { diff --git a/test/integration/dreddTransactions-test.js b/test/integration/dreddTransactions-test.js deleted file mode 100644 index a9ab9a0..0000000 --- a/test/integration/dreddTransactions-test.js +++ /dev/null @@ -1,212 +0,0 @@ -const proxyquire = require('proxyquire').noPreserveCache(); - -const createCompileResultSchema = require('../schemas/createCompileResultSchema'); -const createAnnotationSchema = require('../schemas/createAnnotationSchema'); -const dreddTransactions = require('../../lib/index'); - -const { assert, fixtures } = require('../support'); - - -describe('Dredd Transactions', () => { - describe('when compilation throws an exception', () => { - const error = new Error('... dummy message ...'); - let err; - let compileResult; - - beforeEach((done) => { - const stubbedDreddTransactions = proxyquire('../../lib/index', { - './compile': () => { throw error; }, - }); - stubbedDreddTransactions.compile('... dummy API description document ...', null, (...args) => { - [err, compileResult] = args; - done(); - }); - }); - - it('passes the error to callback', () => { - assert.equal(err, error); - }); - it('passes no compile result to callback', () => { - assert.isUndefined(compileResult); - }); - }); - - describe('when given empty API description document', () => { - let compileResult; - - beforeEach((done) => { - dreddTransactions.compile('', null, (err, result) => { - compileResult = result; - done(err); - }); - }); - - it('produces one annotation, no transactions', () => { - assert.jsonSchema(compileResult, createCompileResultSchema({ - annotations: 1, - transactions: 0, - })); - }); - it('produces warning about falling back to API Blueprint', () => { - assert.jsonSchema(compileResult.annotations[0], createAnnotationSchema({ - type: 'warning', - component: 'apiDescriptionParser', - message: 'assuming API Blueprint', - })); - }); - }); - - describe('when given unknown API description format', () => { - const apiDescription = '... unknown API description format ...'; - let compileResult; - - beforeEach((done) => { - dreddTransactions.compile(apiDescription, null, (err, result) => { - compileResult = result; - done(err); - }); - }); - - it('produces two annotations, no transactions', () => { - assert.jsonSchema(compileResult, createCompileResultSchema({ - annotations: 2, - transactions: 0, - })); - }); - it('produces warning about falling back to API Blueprint', () => { - assert.jsonSchema(compileResult.annotations[0], createAnnotationSchema({ - type: 'warning', - component: 'apiDescriptionParser', - message: 'assuming API Blueprint', - })); - }); - it('produces a warning about the API Blueprint not being valid', () => { - assert.jsonSchema(compileResult.annotations[1], createAnnotationSchema({ - type: 'warning', - component: 'apiDescriptionParser', - message: 'expected', - })); - }); - }); - - describe('when given unrecognizable API Blueprint format', () => { - let compileResult; - const { apiDescription } = fixtures('unrecognizable').apib; - - beforeEach((done) => { - dreddTransactions.compile(apiDescription, null, (err, result) => { - compileResult = result; - done(err); - }); - }); - - it('produces one annotation', () => { - assert.jsonSchema(compileResult, createCompileResultSchema({ - annotations: 1, - transactions: 0, - })); - }); - it('produces no errors', () => { - const errors = compileResult.annotations.filter(annotation => annotation.type === 'error'); - assert.deepEqual(errors, []); - }); - it('produces a warning about falling back to API Blueprint', () => { - assert.jsonSchema(compileResult.annotations[0], createAnnotationSchema({ - type: 'warning', - component: 'apiDescriptionParser', - message: 'assuming API Blueprint', - })); - }); - }); - - describe('when given API description with errors', () => { - fixtures('parser-error').forEachDescribe(({ apiDescription }) => { - let compileResult; - - beforeEach((done) => { - dreddTransactions.compile(apiDescription, null, (err, result) => { - compileResult = result; - done(err); - }); - }); - - it('produces some annotations, no transactions', () => { - assert.jsonSchema(compileResult, createCompileResultSchema({ - annotations: [1], - transactions: 0, - })); - }); - it('produces errors', () => { - assert.jsonSchema(compileResult.annotations, { - type: 'array', - items: createAnnotationSchema({ type: 'error' }), - }); - }); - }); - }); - - describe('when given API description with warnings', () => { - fixtures('parser-warning').forEachDescribe(({ apiDescription }) => { - let compileResult; - - beforeEach((done) => { - dreddTransactions.compile(apiDescription, null, (err, result) => { - compileResult = result; - done(err); - }); - }); - - it('produces some annotations', () => { - assert.jsonSchema(compileResult, createCompileResultSchema({ - annotations: [1], - })); - }); - it('produces warnings', () => { - assert.jsonSchema(compileResult.annotations, { - type: 'array', - items: createAnnotationSchema({ type: 'warning' }), - }); - }); - }); - }); - - describe('when given valid API description', () => { - fixtures('ordinary').forEachDescribe(({ apiDescription }) => { - let compileResult; - - beforeEach((done) => { - dreddTransactions.compile(apiDescription, null, (err, result) => { - compileResult = result; - done(err); - }); - }); - - it('produces no annotations and some transactions', () => { - assert.jsonSchema(compileResult, createCompileResultSchema()); - }); - }); - }); - - describe('when parser unexpectedly provides an error', () => { - const error = new Error('... dummy message ...'); - let err; - let compileResult; - - beforeEach((done) => { - const stubbedDreddTransactions = proxyquire('../../lib/index', { - './parse': (apiDescription, callback) => callback(error), - }); - stubbedDreddTransactions.compile('... dummy API description document ...', null, (...args) => { - [err, compileResult] = args; - done(); - }); - }); - - it('passes the error to callback', () => { - assert.equal(err, error); - }); - it('passes no compile result to callback', () => { - assert.isUndefined(compileResult); - }); - }); -}); diff --git a/test/unit/compile-test.js b/test/unit/compile-test.js index aaab79a..3a4fc4b 100644 --- a/test/unit/compile-test.js +++ b/test/unit/compile-test.js @@ -3,7 +3,7 @@ const { assert } = require('chai'); const { _compileBody: compileBody, _hasMultipartBody: hasMultipartBody, -} = require('../../lib/compile'); +} = require('../../compile'); describe('compile()', () => { diff --git a/test/unit/compileTransactionName-test.js b/test/unit/compileTransactionName-test.js index 29ce331..3773815 100644 --- a/test/unit/compileTransactionName-test.js +++ b/test/unit/compileTransactionName-test.js @@ -1,6 +1,6 @@ const { assert } = require('chai'); -const compileTransactionName = require('../../lib/compileTransactionName'); +const compileTransactionName = require('../../compile/compileTransactionName'); describe('compileTransactionName()', () => { diff --git a/test/unit/compileURI/compileParams-test.js b/test/unit/compileURI/compileParams-test.js index 31344d1..095c6e9 100644 --- a/test/unit/compileURI/compileParams-test.js +++ b/test/unit/compileURI/compileParams-test.js @@ -1,7 +1,7 @@ const { assert } = require('chai'); const fury = require('fury'); -const compileParams = require('../../../lib/compileURI/compileParams'); +const compileParams = require('../../../compile/compileURI/compileParams'); describe('compileParams()', () => { diff --git a/test/unit/compileURI/expandURItemplate-test.js b/test/unit/compileURI/expandURItemplate-test.js index 579af91..1701916 100644 --- a/test/unit/compileURI/expandURItemplate-test.js +++ b/test/unit/compileURI/expandURItemplate-test.js @@ -1,6 +1,6 @@ const { assert } = require('chai'); -const expandUriTemplate = require('../../../lib/compileURI/expandURItemplate'); +const expandUriTemplate = require('../../../compile/compileURI/expandURItemplate'); describe('expandUriTemplate()', () => { diff --git a/test/unit/compileURI/validateParams-test.js b/test/unit/compileURI/validateParams-test.js index 6b0a751..770b039 100644 --- a/test/unit/compileURI/validateParams-test.js +++ b/test/unit/compileURI/validateParams-test.js @@ -1,6 +1,6 @@ const { assert } = require('chai'); -const validateParams = require('../../../lib/compileURI/validateParams'); +const validateParams = require('../../../compile/compileURI/validateParams'); describe('validateParams()', () => { diff --git a/test/unit/detectTransactionExampleNumbers-test.js b/test/unit/detectTransactionExampleNumbers-test.js index 7bfb49d..9ee76f2 100644 --- a/test/unit/detectTransactionExampleNumbers-test.js +++ b/test/unit/detectTransactionExampleNumbers-test.js @@ -1,5 +1,5 @@ -const detectTransactionExampleNumbers = require('../../lib/detectTransactionExampleNumbers'); -const parse = require('../../lib/parse'); +const detectTransactionExampleNumbers = require('../../compile/detectTransactionExampleNumbers'); +const parse = require('../../parse'); const { assert } = require('../support'); diff --git a/test/unit/parse-test.js b/test/unit/parse-test.js index 543fda3..27a5c5f 100644 --- a/test/unit/parse-test.js +++ b/test/unit/parse-test.js @@ -1,6 +1,6 @@ const fury = require('fury'); -const parse = require('../../lib/parse'); +const parse = require('../../parse'); const { assert, fixtures } = require('../support');