Skip to content

Commit

Permalink
Closes #2. Completely working version.
Browse files Browse the repository at this point in the history
  • Loading branch information
Glavin001 committed Feb 20, 2014
1 parent 5702b1e commit 25dcf09
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 75 deletions.
64 changes: 62 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# feathers-swagger [![Build Status](https://travis-ci.org/Glavin001/feathers-swagger.png?branch=master)](https://travis-ci.org/Glavin001/feathers-swagger)

[![NPM](https://nodei.co/npm/feathers-swagger.png?downloads=true&stars=true)](https://nodei.co/npm/feathers-swagger/)


> Add documentation to your Featherjs services and feed them to Swagger UI.
![screenshot](/~https://github.com/Glavin001/feathers-swagger/raw/master/example/screenshot_1.png)
**Please see the [example](/~https://github.com/Glavin001/feathers-swagger#example) below.**

## Getting Started

Expand All @@ -20,17 +23,74 @@ var feathers = require('feathers');
var feathersSwagger = require('feathers-swagger');
// Setup
var app = feathers();

/* ===== Important: Feathers-Swagger part below ===== */
// Use Feathers Swagger Plugin
app.configure(feathersSwagger({ /* configuration */ }));

// Add your services
app.use('/examples', {
find: function(params, callback) {
callback([]);
}
docs: {
description: "Operations about examples.",
find: {
type: 'Example',
parameters: [{
name: 'name',
description: 'Filter Examples by name.',
required: false,
type: 'string',
paramType: 'form'
}],
errorResponses: [
{
code: 500,
reason: 'Example error.'
}
]
},
models: {
Example: {
id: 'Example',
description: 'This is an Example model.',
required: ['name'],
properties: {
name: {
type: 'string',
description: 'This is the example name.'
},
anotherProperty: {
type:'string',
description: 'This is the example description.'
}
}
}
}
}
});

// Finally, start your server.
app.listen(3000, function(){
console.log('Feathers server listening on port '+port+'.');
});
```

To view, go to [the Swagger UI demo at http://swagger.wordnik.com/](http://swagger.wordnik.com/)
and change the base url from `http://petstore.swagger.wordnik.com/api/api-docs`
to `http://localhost:3000/api/docs`

## Example

See the [example directory](/~https://github.com/Glavin001/feathers-swagger/tree/master/example).
See the [example directory](/~https://github.com/Glavin001/feathers-swagger/tree/master/example) for example source code.

To run the example, see the [Contributing instructions below](/~https://github.com/Glavin001/feathers-swagger/#contributing).

**The following screenshot was created with the example.**

![screenshot](/~https://github.com/Glavin001/feathers-swagger/raw/master/example/screenshot_1.png)

## Documentation

See the [docs directory](/~https://github.com/Glavin001/feathers-swagger/tree/master/docs).
Expand Down
44 changes: 40 additions & 4 deletions example/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ app.use(function(req, res, next) {

// configure
app.configure(feathersSwagger({
path:'/api/docs',
docsPath:'/docs',
version: pkg.version,
basePath: 'http://locahost:3000/',
basePath: '/api',
resourcePath: '/example',
info: {
'title': pkg.name,
Expand Down Expand Up @@ -44,8 +44,44 @@ app.use('/examples', {
remove: function(id, params, callback) {
callback({});
},
setup: function(app) {}
})
setup: function(app) {},
docs: {
description: "Operations about examples.",
find: {
type: 'Example',
parameters: [{
name: 'name',
description: 'Filter Examples by name.',
required: false,
type: 'string',
paramType: 'form'
}],
errorResponses: [
{
code: 500,
reason: 'Example error.'
}
]
},
models: {
Example: {
id: 'Example',
description: 'This is an Example model.',
required: ['name'],
properties: {
name: {
type: 'string',
description: 'This is the example name.'
},
anotherProperty: {
type:'string',
description: 'This is the example description.'
}
}
}
}
}
});


app.listen(port, function(){
Expand Down
Binary file modified example/screenshot_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example/screenshot_1.tiff
Binary file not shown.
162 changes: 94 additions & 68 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,126 +6,152 @@
*/

'use strict';
var path = require('path');

module.exports = function(config) {
return function() {
var app = this;
var services = {};

var docs = { };
config = config || {};

// Enable the swagger Plugin
app.enable('feathers swagger');

// Check for configuration
if (config) {
// Apply configuration
var path = config.path || '/docs';
// Setup docs from config
docs.apiVersion = config.version || '0.0.0';
docs.swaggerVersion = config.swaggerVersion || '1.2';
docs.info = config.info || {};
docs.apis = config.apis || [];
docs.models = config.models || {};
docs.basePath = config.basePath || '/';
docs.resourcePath = config.resourcePath || '/';
// Apply configuration
var rootDoc = { };
var basePath = config.basePath || '/';
var docsPath = config.docsPath || '/docs';
docsPath = path.join(basePath, docsPath);
console.log(docsPath);

// Setup docs from config
rootDoc.apiVersion = config.version || '0.0.0';
rootDoc.swaggerVersion = config.swaggerVersion || '1.2';
rootDoc.info = config.info || {};
rootDoc.apis = config.apis || [];
rootDoc.models = config.models || {};

app.get(path, function(req, res) {
//console.log(docs);
res.json(docs);
});
}
// Create API for Documentation
app.get(docsPath, function(req, res) {
res.json(rootDoc);
});

// Optional: Register this plugin as a Feathers provider
app.providers.push(function(path, service) {
console.log(path, service);
services[path] = service;

var api = {
service.docs = service.docs || {};
// Load documentation from service, if available.
var doc = service.docs;
doc.apiVersion = doc.apiVersion || rootDoc.apiVersion;
doc.swaggerVersion = doc.swaggerVersion || rootDoc.swaggerVersion;
doc.basePath = doc.basePath || rootDoc.basePath;
doc.resourcePath = doc.resourcePath || '/'+path;
doc.apis = doc.apis || [];
doc.produces = doc.produces || ['application/json'];

// Two different types of APIs with Operations.
var apiWithId = {
path: '/'+path+'/{resourceId}',
description: path,
operations: []
};
var apiWithoutId = {
path: '/'+path,
description: path,
operations: []
};

// Factory for Operations
var Operation = function(method, service, defaults)
{
defaults = defaults || {};
// Find is available
var operation = service.docs[method] || {};
operation.method = operation.method || defaults.method || method;
operation.nickname = operation.nickname || defaults.nickname || method+' '+path;
operation.type = operation.type || defaults.type || 'Object';
operation.parameters = operation.parameters || defaults.parameters || [];
operation.summary = operation.summary || defaults.summary || '';
operation.notes = operation.notes || defaults.notes || '';
operation.errorResponses = operation.errorResponses || defaults.errorResponses || [];
// Clean up
delete service.docs[method]; // Remove `find` from `docs`
return operation;
};

// FIND
if (typeof service.find === 'function')
{
// Find is available
var findOperation = {
var findOperation = new Operation('find', service, {
method: 'GET',
nickname: 'GET '+path,
type: 'Array',
parameters: [],
summary: 'Find all items of this type.',
notes: 'These are notes',
errorResponses: []
};
api.operations.push(findOperation);
summary: 'Retrieves a list of all resources from the service.',
notes: 'Retrieves a list of all resources from the service.'
});
// Add Operation to API
apiWithoutId.operations.push(findOperation);
}
// GET
if (typeof service.get === 'function')
{
// Find is available
var getOperation = {
var getOperation = new Operation('get', service, {
method: 'GET',
nickname: 'GET '+path,
type: 'Object',
parameters: [],
summary: 'Find single item of this type with ID.',
notes: 'These are notes',
errorResponses: []
};
api.operations.push(getOperation);
summary: 'Retrieves a single resource with the given id from the service.',
notes: 'Retrieves a single resource with the given id from the service.',
});
apiWithId.operations.push(getOperation);
}
// CREATE
if (typeof service.create === 'function')
{
// Find is available
var createOperation = {
var createOperation = new Operation('create', service, {
method: 'POST',
nickname: 'GET '+path,
type: 'Object',
parameters: [],
summary: 'Create an item of this type.',
notes: 'These are notes',
errorResponses: []
};
api.operations.push(createOperation);
summary: 'Creates a new resource with data.',
notes: 'Creates a new resource with data.'
});
apiWithoutId.operations.push(createOperation);
}
// UPDATE
if (typeof service.update === 'function')
{
// Find is available
var updateOperation = {
var updateOperation = new Operation('update', service, {
method: 'PUT',
nickname: 'GET '+path,
type: 'Object',
parameters: [],
summary: 'Update an item of this type.',
notes: 'These are notes',
errorResponses: []
};
api.operations.push(updateOperation);
summary: 'Updates the resource identified by id using data.',
notes: 'Updates the resource identified by id using data.',
});
apiWithId.operations.push(updateOperation);
}
// REMOVE
if (typeof service.remove === 'function')
{
// Find is available
var removeOperation = {
var removeOperation = new Operation('remove', service, {
method: 'DELETE',
nickname: 'GET '+path,
type: 'Object',
parameters: [],
summary: 'Delete an item of this type.',
notes: 'These are notes',
errorResponses: []
};
api.operations.push(removeOperation);
summary: 'Removes the resource with id.',
notes: 'Removes the resource with id.',
});
apiWithId.operations.push(removeOperation);
}

docs.apis.push(api);
// Add two types of APIs to the service's documentation object.
doc.apis.push(apiWithoutId);
doc.apis.push(apiWithId);

// Add the service to the list of available APIs in the root documentaion object.
rootDoc.apis.push({
'path': doc.path || '/'+path,
'description': doc.description || 'Operations about this resource.'
});

// Create handler for serving the service's documentation
app.get(docsPath+'/'+path, function(req, res) {
res.json(doc);
});

console.log(docs);
});

};
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "feathers-swagger",
"version": "0.1.1",
"version": "0.2.0",
"description": "Add documentation to your Featherjs services and feed them to Swagger UI. ",
"homepage": "/~https://github.com/Glavin001/feathers-swagger",
"keywords": [
Expand Down

0 comments on commit 25dcf09

Please sign in to comment.