sri4node v1.2.36
About
An implementation of SRI (Standard ROA Interface). SRI is a set of standards to make RESTful interfaces. It specifies how resources are accesses, queried, updated, deleted. The specification can be found here.
The implementation supports storage on a postgres database.
Installing
Installation is simple using npm :
$ cd [your_project]
$ npm install --save sri4nodeYou will also want to install Express.js and node-postgres :
$ npm install --save express
$ npm install --save pgExpress.js and node-postgress are technically not dependencies (as in npm dependencies) of sri4node. But you need to pass them in when configuring. This allows you to keep full control over the order of registering express middleware, and allows you to share and configure the node-postgres library.
Usage
Start by requiring the module in your code. Then we'll create some convenient aliasses for the utility functions bundled with sri4node as well.
var express = require('express');
var app = express();
var pg = require('pg');
var sri4node = require('sri4node');
var $u = sri4node.utils;
var $m = sri4node.mapUtils;
var $s = sri4node.schemaUtils;
var $q = sri4node.queryUtils;Finally we configure handlers for 1 example resource.
This example shows a resource for storing content as html with meta-data like authors, themes and editor.
The declaration of the editor is a reference to a second resource (/person), which itself is not shown here.
var promise = sri4node.configure(app,pg,
{
// Log and time HTTP requests ?
logrequests : true,
// Log SQL ?
logsql: false,
// Log debugging information ?
logdebug: false,
// Log middleware timing ?
logmiddleware: true,
// The URL of the postgres database
defaultdatabaseurl : "postgres://user:pwd@localhost:5432/postgres",
authenticate: $u.basicAuthentication(myAuthenticator),
identify : functionToConstructSecurityContext,
// All URLs force SSL and allow cross origin access.
forceSecureSockets: true,
description: 'A description about the collection of resources',
resources : [
{
// Base url, maps 1:1 with a table in postgres
// Can be defined as /x or /x/y/..
// Table name will be the last part of the path
type: '/content',
// Is this resource public ?
// Can it be read / updated / inserted publicly ?
public: false,
// Multiple function that check access control
// They receive a database object and the security context
// as determined by the 'identify' function above.
secure : [
checkAccessOnResource,
checkSomeMoreRules
],
// Enable cache (default false)
cache: {
ttl: 60, // in seconds, the time the objects live (0 means forever)
type: 'local' // will store in an in-memory local cache
},
// custom routes can be defined. See #custom-routes
customroutes: [
{route: '/content/:key/:attachment', handler: getAttachment}
],
// Standard JSON Schema definition.
// It uses utility functions, for compactness.
schema: {
$schema: "http://json-schema.org/schema#",
title: "An article on the websites/mailinglists.",
type: "object",
properties : {
authors: $s.string("Comma-separated list of authors."),
themes: $s.string("Comma-separated list of themes."),
html: $s.string("HTML content of the article.")
},
required: ["authors","themes","html"]
},
// Functions that validate the incoming resource
// when a PUT operation is executed.
validate: [
validateAuthorVersusThemes
],
// Supported URL parameters are configured
// for list resources. $q is an alias for
// sri4node.queryUtils.
// This is a collection of predefined functions.
// You can build your own (see below).
// These functions can execute an arbitrary set
// of preparatory queries on the database,
// You can execute stored procedures and create
// temporary tables to allow you to add things like :
// ' AND key IN (SELECT key FROM mytemptable) '
// to the query being executed.
// Allowig any kind of filtering on
// the resulting list resource.
query: {
editor: $q.filterReferencedType('/persons','editor'),
defaultFilter: $q.defaultFilter
},
// The limit for queries. If not provided a default will be used
defaultlimit: 5,
// The maximum allowed limit for queries. If not provided a default will be used
maxlimit: 50,
// All columns in the table that appear in the
// resource should be declared in the 'map' object.
// Optionally mapping functions can be given.
// Mapping functions can be registered
// for onread, onwrite and onupdate.
//
// For GET operations the key in the 'map' object
// is the name of the key as it will appear in the JSON output.
//
// For PUT operations it is the key that appears
// on the input resource. The end result after mapping
// is created / updated in the database table.
map: {
authors: {},
themes: {},
html: {},
// Reference to another resource of type /persons.
// (mapping of 'persons' is not shown in this example)
// Can also be referenced as /x/y/.. if another resources is defined like this
editor: {references : '/persons'}
},
// After read, update, insert or delete
// you can perform extra actions.
afterread: [
addAdditionalInfoToOutputJSON
],
afterupdate: [],
afterinsert: [],
afterdelete: [
cleanupFunction
]
}
]
});Configure returns a Q promise. Now we can start Express.js to start serving up our SRI REST interface :
promise.then(function () {
app.listen(5000, function() {
console.log("Node app is running at localhost:" + app.get('port'))
});
});Reserved and required fields (mandatory)
There are 3 columns that every resource table must have (it's mandatory).
Those are:
- "$$meta.deleted" boolean not null default false,
- "$$meta.modified" timestamp with time zone not null default current_timestamp,
- "$$meta.created" timestamp with time zone not null default current_timestamp
For performance reasons it's highly suggested that an index is created for each column:
- CREATE INDEX table_created ON table ("$$meta.created");
- CREATE INDEX table_modified ON table ("$$meta.modified");
- CREATE INDEX table_deleted ON table ("$$meta.deleted");
The following index is for the default order by:
- CREATE INDEX table_created_key ON table ("$$meta.created", "key");
The application will fail to register a resource that lacks these fields (and show a message to the user)
Processing Pipeline
sri4node has a very simple processing pipeline for mapping SRI resources onto a database. We explain the possible HTTP operations below :
- reading regular resources (GET)
- updating/creating regular resources (PUT)
- deleting regular resources (DELETE)
- reading list resources (queries) (GET)
In essence we map 1 regular resource to a database row. A list resource corresponds to a query on a database table.
Expansion on list resource can be specified as expand=results, this will include all regular resources in your list resource.
A shorthand version of this is expand=full.
Expansion on list resource can also be specified as expand=results.x.y,results.u.v.w, where x.y and u.v.w can be any path in the expanded regular resource.
This will include related regular resources.
Expansion on regular resource can be specified as expand=u.v,x.y.z, where u.v and x.y.z can be any reference to related regular resources.
This will include related regular resources.
When reading a regular resource a database row is transformed into an SRI resource by doing this :
- Check if you have permission by executing all registered
securefunctions in the configuration. If any of these functions rejects its promise, the client will receive 403 Forbidden. - Retrieve the row and convert all columns into a JSON key-value pair (keys map directly to the database column name).
All standard postgreSQL datatypes are converted automatically to JSON.
Values can be transformed by an onread function (if configured).
By default references to other resources (GUIDs in the database) are expanded to form a relative URL.
As they are mapped with
{ references: '/type' }. - Add a
$$metasection to the response document. - Execute any
afterreadfunctions to allow you to manipulate the result JSON.
When creating or updating a regular resource, a database row is updated/inserted by doing this :
- Check if you have permission by executing all registered
securefunctions. If any of these functions rejects its promise, the client will receive 403 Forbidden. - Perform schema validation on the incoming resource. If the schema is violated, the client will receive a 409 Conflict.
- Execute
validatefunctions. If any of of thevalidatefunctions rejects its promise, the client receives a 409 Conflict. - Convert the JSON document into a simple key-value object.
Keys map 1:1 with database columns.
All incoming values are passed through the
onwrite/oninsertfunction for conversion (if configured). By default references to other resources (relative links in the JSON document) are reduced to foreign keys values (GUIDs) in the database. - insert or update the database row.
- Execute
afterupdateorafterinsertfunctions.
When deleting a regular resource :
- Check if you have permission by executing all registered
securefunctions in the mapping. If any of these functions rejects its promise, the client will receive 403 Forbidden. - Delete the row from the database.
- Execute any
afterdeletefunctions.
When reading a list resource :
- Check if you have read permission by executing all registered
securefunctions in the mapping. If any of these functions rejects its promise, the client will receive 403 Forbidden. - Generate a
SELECT COUNTstatement and execute all registeredqueryfunctions to annotate theWHEREclause of the query. - Execute a
SELECTstatement and execute all registeredqueryfunctions to annotate theWHEREclause of the query. Thequeryfunctions are executed if they appear in the request URL as parameters. Thequerysection can also define adefaultFilterfunction. It is this default function that will be called if no other query function was registered. - Retrieve the results, and expand if necessary (i.e. generate a JSON document for the result row - and add it as
$$expanded). See the SRI specification for more details. - Build a list resource with a
$$metasection + aresultssection. - Execute any
afterreadfunctions to allow you to manipulate the result JSON.
That's it ! :-).
Timing
If logmiddleware is true in the configuration the application will display a log of the timing of each
middleware.
Function Definitions
Below is a description of the different types of functions that you can use in the configuration of sri4node.
It describes the inputs and outputs of the different functions.
Most of these function return a Q promise.
Some of the function are called with a database context, allowing you to execute SQL inside your function.
Such a database object can be used together with sri4node.utils.prepareSQL() and sri4node.utils.executeSQL().
Transaction demarcation is handled by sri4node, on a per-request-basis.
That implies that /batch operations are all handled in a single transaction.
For more details on batch operations see the SRI specification.
onread
Database columns are mapped 1:1 to keys in the output JSON object.
The onread function receives these arguments :
keyis the key the function was registered on.elementis the the result of the query that was executed.
Functions are executed in order of listing in the map section of the configuration.
No return value is expected, this function manipulates the element in-place.
These functions allow you to do al sorts of things,
like remove the key if it is NULL in the database,
always remove a certain key, rename a key, etc..
A selection of predefined functions is available in sri4node.mapUtils (usually assigned to $m).
See below for details.
oninsert / onupdate
JSON properties are mapped 1:1 to columns in the postgres table.
The onupdate and oninsert functions recieves these parameters :
keyis the key they were registered on.elementis the JSON object being PUT.
All functions are executed in order of listing in the map section of the configuration.
All are allowed to manipulate the element, before it is inserted/updated in the table.
No return value is expected, the functions manipulate the element in-place.
A selection of predefined functions is available in sri4node.mapUtils (usually assign to $m).
See below for details.
secure
A secure function receives these parameters :
requestis the Express.js request object for this operation.responseis the Express.js response object for this operation.databaseis a database object (see above) that you can use for querying the database.meis the security context of the user performing the current HTTP operation. This is the result of theidentifyfunction.batchan array of the operations requested. Each element has attributeshrefandverb.
The function must return a Q promise.
It should resolve() the promise if the function allows the HTTP operation.
It should reject() the promise if the function disallows the HTTP operation.
In the later case the client will receive a 403 Forbidden as response to his operation.
validate
Validation functions are executed before update/insert. All validation functions are executed for every PUT operation.
A validate function receives these arguments :
bodyis the full JSON document being PUT.databaseis a database object (see above) that you can use for querying the database.
The function must return a Q promise.
It should reject() the returned promise if the validation fails, with one or more objects that correspond to the SRI definition of an error.
The implementation can return an array, or a single object.
If any of the validate functions reject their promise, the client receives 409 Conflict.
In the response body the client will then find all responses generated by all rejecting validate functions combined.
query
All queries are URLs.
Any allowed URL parameter is interpreted by these functions.
The functions can annotate the WHERE clause of the query executed.
The functions receive these parameters :
valueis the value of the request parameter (string).selectis a query object (as returned bysri4node.prepareSQL()) for adding SQL to theWHEREclause. See below for more details.parameteris the name of the URL parameter.databaseis a database object that you can use to execute extra SQL statements.countis a boolean telling you if you are currently decorating theSELECT COUNTquery, or the finalSELECTquery. Useful for making sure some statements are not executed twice (when using the database object)mappingis the mapping in the configuration of sri4node.
All the configured query functions should extend the SQL statement with an AND clause.
The function must return a Q promise.
When the URL parameter was applied to the query object, then the promise should resolve().
If one query function rejects its promise, the client received 404 Not Found and all error objects by all rejecting query functions in the body.
It should reject with one or an array of error objects that correspond to the SRI definition.
Mind you that path does not makes sense for errors on URL parameters, so it is ommited.
If a query parameter is supplied that is not supported, the client also receives a 404 Not Found and a listing of supported query parameters.
handlelistqueryresult
An optional function to override the default code for building the JSON result based on the database query result.
This function receives these parameters :
reqthe express.js request object.resultis an object containing the query result.
The function must return a Q promise JSON output object.
afterread
Hook for post-processing a GET operation (both regular and list resources).
It applies to both regular resources, and list resources (with at least expand=results).
The function receives these parameters :
databaseis a database object, allowing you to execute extra SQL statements.elementsis an array of one or more resources that you can manipulate.methe return of the identify functionroutethe url route that originated the responseheadersFnA function of the form (field , value): Sets the response’s HTTP header field to value. To set multiple fields at once, pass an object as the parameter.
The function must return a Q promise.
If one of the afterread methods rejects its promise, all error objects are returned to the client, who receives a 500 Internal Error response by default. It should reject() with an object that correspond to the SRI definition of an error.
When rejecting, an object can be provided to produce a different output. The object must have the following properties:
statusCodeis the http status code to be returned in the response.bodyis the body of the http response Mind you that path does not makes sense for errors in afterread methods, so you should omit it.
afterupdate / afterinsert
Hooks for post-processing a PUT operation can be registered to perform desired things, like clear a cache, do further processing, update other tables, etc.. The function receives these parameters :
databaseis a database object, allowing you to execute extra SQL statements.elementsis an array of one or more objects. Each object contains two attributes:pathis the route of the requestbodyis the JSON element (as it was PUT, so without mapping/processing) that was just updated / created.
methe return of the identify function
The function must return a Q promise.
In case the returned promise is rejected, all executed SQL (including the INSERT/UPDATE of the resource) is rolled back.
The function should reject() its promise with an object that correspond to the SRI definition of an error.
If any of the functions rejects its promise the client receives 409 Conflict by default, an a combination of all error objects in the response body.
When rejecting, an object can be provided to produce a different output. The object must have the following properties:
statusCodeis the http status code to be returned in the response.bodyis the body of the http response
afterdelete
Hook for post-processing when a record is deleted. The function receives these parameters :
databaseis a database object, allowing you to execute extra SQL statements.elementsis an array of one or more objects. Each object contains two attributes:pathis the route of the requestbodyis the permalink of the object that was deleted.
methe return of the identify function
The function must return a Q promise.
In case the returned promise is rejected, the database transaction (including the DELETE of the resource) is rolled back.
The function should reject() its promise with an object that correspond to the SRI definition of an error.
If any of the functions rejects its promise the client receives 409 Conflict by default, an a combination of all error objects in the response body.
When rejecting, an object can be provided to produce a different output. The object must have the following properties:
statusCodeis the http status code to be returned in the response.bodyis the body of the http response
authenticate
This function handles authentication of the current user. This function receives these parameters :
reqthe express.js request object.resthe express.js response object.nexta function that can be called to delegate response handling to the next handler in the chain.
checkAuthentication
If this function is configured it takes precedence over #authenticate for read (GET) operations. This must be accompanied by the #postAuthenticationFailed function.
The difference with authenticate is that this function tries to authenticate the user but continues regardless of whether there's a valid user or not. If there's a valid user it puts it in the req object for subsequent checks.
reqthe express.js request object.resthe express.js response object.nexta function that can be called to delegate response handling to the next handler in the chain.
postAuthenticationFailed
This function is called if the read (GET) operation didn't succeed because of permission issues.
If there's a valid user, then the user is not authorized. If there's no user, then it's not authenticated.
The error can be used to send a specific error.
reqthe express.js request object.resthe express.js response object.usera function that can be called to delegate response handling to the next handler in the chain.errora function that can be called to delegate response handling to the next handler in the chain.
identify
This function determines the /me resource. The same information is also passed into query functions as an argument.
It receives these parameter :
reqthe express.js request object, allowing you to analyze any headers on the request.databasea database obejct, allowing you to perform queries.
The function must return a Q promise, with the me object.
This will be returned in the body of a request to /me, and it will also be passed into your secure functions.
resource specific configuration variables
methods
Can be used to restrict the methods which are allowed on a resource. If not specified the default is 'GET','PUT','POST','DELETE'
table
Can be used to override the tablename in case it does not match the resource name.
Caching
By default resources are not cached. By defining a cache section we can store results in a cache not to hit the database.
The key of the cache is the requested url.
There are currently two supported types of caches: local and redis.
localstores the output in a local in-memory cache.redisconnects to a Redis store and stores objects there. This allows for horizontal scalability since multiple application instances can share the cache.
Examples
cache: { ttl: 0, type: 'local' }
Will store objects in a local cache without an expiration time. The object will live in the cache until replaced by a new version
cache: { ttl: 60, // store objects for 60 seconds. After 60 seconds the objects are purged. type: 'redis', redis: 'redis://user@host.com:9000' }
If type is redis the URL to a Redis server must be provided.
Custom Routes
Allows you to set extra routes besides the defaults GET, PUT, DELETE for the resource. Each element of the customroutes array contains:
routeuri to be added required.methodthe route method, possible values GET, PUT. Default GET.handlerfunction called when the route is accessed required.middlewareoptional Express.js middleware function or array of such functions to be called before the handler.descriptiona description of the custom route.
A handler function receives this arguments:
reqthe express.js request object.resthe express.js response object.databaseis a database object (see above) that you can use for querying the database.methe return of the identify function
Limiting results
The following attributes dictate how the lists are paginated:
defaultlimit: the number of resources per page. If empty, a default of 30 is used.maxlimit: The maximum limit allowed. If empty, a default of 500 is used.
The limit query parameter can be used to specify the amount of retrieved results. A special case is allowed where the limit value is '*' and the expand parameter is 'NONE', this means unlimited results.
Bundled Utility Functions
These utilities live independently of the basic processing described above. In other words, they provide no magic for the developer. They are provided for convenience. If you understand the above processing pipeline, reading the source for one of these functions should contain no surprises.
General Utilities
The utilities are found in sri4node.utils.
getConnection(pg, configuration)
Used for obtaining a new connection to the database. It must be properly closed after done using it. Failure to do so will create connection leaks in the pool. Arguments:
pg: a postgres object (https://www.npmjs.com/package/pg)config: a configuration object with the attributes:{defaultdatabaseurl: databaseUrl, logsql: verbose}
Example usage:
var db;
getConnection(pg, config)
.then(function (database) {
db = database;
// do something with the database
})
.finally(function () {
db.done();
});prepareSQL()
Used for preparing SQL. Supply a name to keep the query in the database as a prepared statement.
It returns a query object with these functions :
sql()is a method for appending sql.param(value)is a method for appending a parameter to the SQL statement.array(value)is a method for appending an array of parameters to the SQL statement (comma-separated). Useful for generating things likeINclauses.keys(value)adds all keys in an object comma-separated to the SQL statement.values(value)is a method for appending all values of an object as parameters to the SQL statement.keysandvalueshave the same iteration order.with(query, virtualtablename)is a method for adding a different query object asWITHstatement to this query. Allows you to use postgres Common Table Expressions (CTE) in your request parameters. You can refer in the query to the virtual table you named withvirtualtablename. Use$u.prepareSQL()to build the SQL statement for your CTE.
All the methods on the query object can be chained. It forms a simple fluent interface.
Example of using a common table expression :
var query = $u.prepareSQL();
query.sql('SELECT * FROM xyz WHERE c1 IN (SELECT * FROM virtualtable)');
var cte = $u.prepareSQL();
cte.sql(...);
query.with(cte,'virtualtable');executeSQL(database, query)
Used for executing SQL.
Call with the a database object you received, and a query object (as returned by prepareSQL(), or as received for query functions).
The function returns a Q promise.
It's not a responsible of this function to close the connection on error since it's an argument, hence the caller must properly
make sure that the connection is disposed regardless of the result.
addReferencingResources(type, foreignkey, targetkey)
Afterread utility function. Adds, for convenience, an array of referencing resource to the currently retrieved resource(s).
It will add an array of references to resource of type to the currently retrieved resource.
Specify the foreign key column (in the table of those referencing resource) via foreignkey.
Specify the desired key (should be $$somekey, as it is not actually a part of the resource, but provided for convenience) to add to the currently retrieved resource(s) via targetkey.
convertListResourceURLToSQL(req, mapping, count, database, query)
Receives a query object and constructs the SQL for a list query.
Arguments:
reqis the request object.mappingis the mapping in the configuration of sri4node.counta boolean to indicate if the query wanted is a count query or not.databasea database obejct, allowing you to perform queries.querya query obtain viaprepareSQL
This returns a promise that it's fulfilled when the query object contains the constructed SQL.
basicAuthentication(authenticator)
Used for protecting a resource with BASIC authentication.
It accepts a single parameter, that is in turn a function that is responsible for checking username/password.
The function authenticator, receives these parameters :
databaseis a database connection, that may be used to perform queries.usernamethe username, that sent on the HTTPAuthenticationheader.passwordthe password, that was sent on the HTTPAuthenticationheader.
The authenticator function should return a Q promise that is resolved with a boolean true or false to indicate that username and password match, or do not match.
It should reject the promise in any other case.
Mapping Utilities
Provides various utilities for mapping between postgres and JSON.
These functions can be found in sri4node.mapUtils.
removeifnull
Remove key from object if value was null/undefined.
sri4node = require('sri4node');
$m = sri4node.mapUtils;
...
{
type: '/content',
...
map: {
...
title: { onread: $m.removeifnull }
...
},
...
}remove
Always remove this key.
sri4node = require('sri4node');
$m = sri4node.mapUtils;
...
{
type: '/content',
...
map: {
...
title: { onread: $m.remove }
...
},
...
}now
Override with current server timestamp.
sri4node = require('sri4node');
$m = sri4node.mapUtils;
...
{
type: '/content',
...
map: {
...
publicationdate: { onupdate: $m.now, oninsert: $m.now }
...
},
...
}value()
Override with a fixed value.
sri4node = require('sri4node');
$m = sri4node.mapUtils;
...
{
type: '/content',
...
map: {
...
status: { oninsert: $m.value('active') }
...
},
...
}parse
Convert string into JSON.
sri4node = require('sri4node');
$m = sri4node.mapUtils;
...
{
type: '/content',
...
map: {
...
details: {
onread: $m.parse,
oninsert: $m.stringify,
onupdate: $m.stringify
}
...
},
...
}stringify
Convert JSON into string.
sri4node = require('sri4node');
$m = sri4node.mapUtils;
...
{
type: '/content',
...
map: {
...
details: {
onread: $m.parse,
oninsert: $m.stringify,
onupdate: $m.stringify
}
...
},
...
}JSON Schema Utilities
These functions are found in sri4node.schemaUtils.
Provides various utilities for keeping your JSON schema definition compact and readable.
description is always used to document your resources.
General usage:
sri4node = require('sri4node');
$s = sri4node.schemaUtils;
...
{
type: '/content',
...
schema: {
$schema: "http://json-schema.org/schema#",
title: "An article on the websites/mailinglists.",
type: "object",
properties : {
title: $s.string('Title of the article.',1);
},
...
},
...
}We describe the generated JSON schema fragment below.
You can use these functions, but when they are insufficient you can insert any valid JSON schema manually in the schema property of a resource configuration.
They are only provided for convenience.
permalink(type, description)
Used for declaring permalinks.
Example : $s.permalink('/persons','The creator of the article.').
Generated schema fragment :
{
type: "object",
properties: {
href: {
type: "string",
pattern: "^\/" + name + "\/[-0-9a-f].*$",
minLength: name.length + 38,
maxLength: name.length + 38,
description: description
}
},
required: ["href"]
}string(description, min, max)
As you should define your postgres columns as type text setting minimum and maximum length is usually omitted.
Example: $s.string('Title of the article.',5).
Generated schema fragment :
{
type: "string",
description: description,
minLength: min, // if supplied.
maxLength: max, // if supplied.
}numeric(description)
Defines a property as numeric.
Example: $s.numeric('The amount of ...').
Generated schema fragment :
{
type: "numeric",
multipleOf: "1.0",
description: description
}email(description)
Defines an email.
Example: $s.email('Personal email of the customer.').
Generated schema fragment :
{
type: "string",
format: "email",
minLength: 1,
maxLength: 254,
description: description
}url(description)
Defines a URL.
Example: $s.url('The homepage of the organisational unit.').
Generated schema fragment :
{
type: "string",
minLength: 1,
maxLength: 2000,
format: "uri",
description: description
}belgianzipcode(description)
Defines a Belgian zipcode.
Example: $s.zipcode('The zipcode of the address').
Generated schema fragment :
{
type: "string",
pattern: "^[0-9][0-9][0-9][0-9]$",
description: description
}phone(description)
Defines a telephone number.
Example: $s.phone('The telephone of the customer').
Generated schema fragment :
{
type: "string",
pattern: "^[0-9]*$",
minLength: 9,
maxLength: 10,
description: description
}timestamp(description)
Defines a JSON timestamp.
Example: $s.timestamp('The creation date/time of this resource').
Generated schema fragment :
{
type: "string",
format: "date-time",
description: description
}boolean(description)
Defines a JSON boolean.
Example: $s.boolean('Does she love me or does she not ?')
Generated schema fragment :
{
type: "boolean",
description: description
}guid(description)
Defines a column as GUID.
Example: $s.guid('API-key for a plugin')
Generated schema fragment :
{
type: 'string',
description: description,
pattern: '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$'
}Query functions
The functions are found in sri4node.queryUtils.
Provides pre-packaged filters for use as query function in a resource configuration.
The example assume you have stored sri4node.queryUtils in $q as a shortcut.
var sri4node = require('sri4node');
...
var $q = sri4node.queryUtils;filterReferencedType(type, columnname)
Can be used to filter on referenced resources.
Example: /content resources have a key creator that references /persons.
A list resource /content?creator=/persons/{guid} can be created by adding this query function :
{
type: '/content',
map: {
...
creator: { references: '/persons' },
...
},
...
query: [
creator: $q.filterReferencedType('/persons','creator')
],
...
}Do a query to retrieve all content, created by person X :
GET /content?creator=/persons/{guid-X}The value being passed in as a URL parameter can be a single href, or a comma-separated list of hrefs. The filter will match on any of the given permalinks.
defaultFilter
An implementation of sri-query. SRI-query defines default, basic filtering on list resources. The function is a default, shared implementation of that.
{
type: '/schools',
map: {
...
},
...
query: [
...
defaultFilter: $q.defaultFilter
]
}Read the specification for details. Example queries are :
GET /schools?institutionNumberGreater=100000
GET /schools?nameContains=vbs
GET /schools?nameCaseInsensitive=Minnestraal
GET /schools?seatAddresses.key=a39c809e-a3a4-11e3-ace8-005056872b95Relations query filters
When a resource is detected as a relation (has from and to properties) some query filters are added for the list resources.
{
type: '/relations',
map: {
from: {references: '/messages'},
to: {references: '/messages'}
},
...
query: {
...
}
}fromTypes
Can be used to filter those relations where the 'from' resource is some of the given types.
toTypes
Can be used to filter those relations where the 'to' resource is some of the given types.
froms
Filter those relations where the 'from' resources is one of the given ones.
tos
Filter those relations where the 'to' resources is one of the given ones.
Example queries are :
GET /relations?fromTypes=request,offer
GET /relations?toTypes=response
GET /relations?froms=/messages/{guid}
GET /relations?tos=/messages/{guid}Generated API Documentation
Documentation will be generated based on the configuration.
On the /docs endpoint you can access general documentation about all the resources that are available.
When you want more information about a resource you can access /resource/docs
validateDocs
To document validate functions you need to add validateDocs to the resource configuration. validateDocs has to include a description and possible error codes of the validate function.
validate: [
validateAuthorVersusThemes
],
validateDocs: {
validateAuthorVersusThemes: {
description: "Validate if author or theme exists",
errors: [{
code: 'not.a.desert',
description: 'This is not a desert.'
}]
}
}queryDocs
To document a custom query function you need to add queryDocs to the resource configuration. queryDocs has to include the description of the query function.
query: {
editor: $q.filterReferencedType('/persons','editor'),
defaultFilter: $q.defaultFilter
},
queryDocs: {
editor: 'Allow to filer on an editor.'
}##Description
####Interface You can describe your sri interface by using the description variable in the root for your configuration
description: 'A description about the collection of resources'####Resource You can describe a resource by using the to use schema > title
title: 'An article on the websites/mailinglists'####Property If you want to describe a property of a resource you need to use schema > properties > property > description :
properties : {
authors: {
type: 'string'
description: 'Comma-separated list of authors.'
}
}Or use the schemaUtils function:
properties : {
authors: $s.string('Comma-separated list of authors.')
}Contributions
Contributions are welcome. Contact me on dimitry-underscore-dhondt-at-yahoo-dot-com.
License
The software is licensed under LGPL license.
8 years ago
8 years ago
8 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago