├── .gitignore
├── test
├── support
│ ├── entrypoint.json
│ └── api.json
└── test.js
├── examples
├── api-demo-model.html
├── calendar.js
├── api-demo-model.js
└── api-demo.js
├── package.json
├── LICENSE.md
├── lib
├── validation.js
├── utils.js
├── model.js
├── core.js
└── http-client.js
├── hydra-core.js
├── prepublish.js
├── README.md
└── dist
├── hydra-core.min.js
├── hydra-core.js.map
├── hydra-core.js
└── hydra-core.min.js.map
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | node_modules
--------------------------------------------------------------------------------
/test/support/entrypoint.json:
--------------------------------------------------------------------------------
1 | {
2 | "@context": {"@vocab": "http://www.w3.org/ns/hydra/core#"},
3 | "@id": "/hydra/api-demo/",
4 | "@type": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint",
5 | "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/issues": {"@id": "/hydra/api-demo/issues/"},
6 | "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/registerUser": {"@id": "/hydra/api-demo/users/"},
7 | "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/users": {"@id": "/hydra/api-demo/users/"}
8 | }
--------------------------------------------------------------------------------
/examples/api-demo-model.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hydra-core",
3 | "version": "0.0.2",
4 | "description": "Core Hydra API",
5 | "main": "hydra-core.js",
6 | "scripts": {
7 | "prepublish": "node prepublish.js",
8 | "test": "node_modules/.bin/mocha"
9 | },
10 | "keywords": [
11 | "hydra"
12 | ],
13 | "author": "bergi@axolotlfarm.org",
14 | "license": "MIT",
15 | "readmeFilename": "README.md",
16 | "repository": {
17 | "type": "git",
18 | "url": "git://github.com/bergos/hydra-core.git"
19 | },
20 | "dependencies": {
21 | "es6-promise": "2.*",
22 | "jsonld": "0.3.*",
23 | "lodash": "3.*",
24 | "request": "2.*"
25 | },
26 | "devDependencies": {
27 | "browserify": "10.*",
28 | "exorcist": "0.4.0",
29 | "mocha": "2.*",
30 | "uglifyjs": "2.*"
31 | }
32 | }
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # License
2 | The MIT License (MIT)
3 | Copyright © 2012–2015 Thomas Bergwinkl
4 |
5 | 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:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | 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.
10 |
--------------------------------------------------------------------------------
/lib/validation.js:
--------------------------------------------------------------------------------
1 | var
2 | hydra = require('./core'),
3 | utils = require('./utils'),
4 | jsonldp = utils.require('jsonld').promises();
5 |
6 |
7 | hydra.simpleValidateClass = function (object, read, write) {
8 | var self = this;
9 |
10 | if (!object) {
11 | return Promise.resolve();
12 | }
13 |
14 | return jsonldp.expand(object)
15 | .then(function (expanded) {
16 | if (expanded.length > 1) {
17 | return Promise.reject(new Error('object contains multiple subjects'));
18 | }
19 |
20 | expanded = expanded.shift();
21 |
22 | if (!('@type' in expanded)) {
23 | return Promise.reject(new Error('@type missing'));
24 | }
25 |
26 | if (utils.toArray(expanded['@type']).indexOf(self.iri) < 0) {
27 | return Promise.reject(new Error('expected class <' + self.iri + '>'));
28 | }
29 |
30 | var error = self.properties
31 | .map(function (property) {
32 | if (property.readonly && property.iri in object) {
33 | return new Error('readonly property <' + property.iri + '> filled with value "' + object[property.iri] + '"');
34 | }
35 |
36 | return false;
37 | })
38 | .filter(function (error) {
39 | return !!error;
40 | })
41 | .shift();
42 |
43 | if (error) {
44 | return Promise.reject(error);
45 | }
46 |
47 | return Promise.resolve();
48 | });
49 | };
50 |
51 |
--------------------------------------------------------------------------------
/hydra-core.js:
--------------------------------------------------------------------------------
1 | var
2 | hydra = require('./lib/core'),
3 | utils = require('./lib/utils');
4 |
5 |
6 | require('./lib/http-client');
7 | require('./lib/model');
8 | require('./lib/validation');
9 |
10 |
11 | hydra.loadApi = function (url) {
12 | return hydra.httpClient.request('GET', url)
13 | .then(function (response) {
14 | return hydra.api(response.body, url);
15 | })
16 | .then(function (api) {
17 | api.iri = url;
18 |
19 | return api;
20 | });
21 | };
22 |
23 |
24 | hydra.documentFromResponse = function (response) {
25 | return hydra.httpClient.apiLink(response.headers, response.request.url)
26 | .then(function (apiUrl) {
27 | return hydra.loadApi(apiUrl);
28 | })
29 | .then(function (api) {
30 | return hydra.document(api, response.body, response.request.url);
31 | })
32 | .then(function (document) {
33 | return hydra.httpClient.contentLocation(response.headers, response.request.url)
34 | .then(function (contentLocation) {
35 | document.iri = contentLocation || response.request.url;
36 |
37 | return document;
38 | });
39 | });
40 | };
41 |
42 |
43 | hydra.loadDocument = function (url) {
44 | return hydra.httpClient.request('GET', url)
45 | .then(function (response) {
46 | return hydra.documentFromResponse(response, url);
47 | });
48 | };
49 |
50 |
51 | // export utils
52 | hydra.utils = utils;
53 |
54 |
55 | // set defaults
56 | hydra.defaults = {};
57 | hydra.defaults.invokeOperation = hydra.httpClient.jsonLdInvoke;
58 | hydra.defaults.validateClass = hydra.simpleValidateClass;
59 | hydra.defaults.model = {};
60 | hydra.defaults.model.createInvoke = hydra.model.createHttpJsonLdInvoke;
61 | hydra.defaults.model.invokeOperation = hydra.httpClient.rawJsonLdInvoke;
62 |
63 |
64 | module.exports = hydra;
65 |
--------------------------------------------------------------------------------
/examples/calendar.js:
--------------------------------------------------------------------------------
1 | global.Promise = require('es6-promise').Promise;
2 |
3 | var
4 | hydra = require('../');
5 |
6 |
7 | var ns = {
8 | context: { '@vocab': 'http://schema.org/' },
9 | EntryPoint: 'http://schema.org/EntryPoint',
10 | Event: 'http://schema.org/Event',
11 | Person: 'http://schema.org/Person',
12 | event: 'http://schema.org/event',
13 | invite: 'http://schema.org/invite',
14 | invitee: 'http://schema.org/invitee'
15 | };
16 |
17 |
18 | var eventData = {
19 | '@context': ns.context,
20 | startDate: '2015-06-16T00:00:00Z',
21 | name: 'Test Event',
22 | description: 'This is a test event created by hydra core'
23 | };
24 |
25 |
26 | var person = {
27 | '@type': ns.Person,
28 | '@id': 'https://bergnet.org/people/bergi/card#me'
29 | };
30 |
31 |
32 | // create a entry point object
33 | hydra.model.load('http://localhost:8080/', {'@context': ns.context})
34 | .then(function (entryPoint) {
35 | console.log('loaded entry point: <' + entryPoint.document.iri + '>');
36 |
37 | // create a event object based on eventData
38 | return hydra.model.create(entryPoint.api.findClass(ns.Event), eventData)
39 | .then(function (event) {
40 | console.log('created event from abstract class with name: ' + event.name);
41 |
42 | // call the post method of property event
43 | return entryPoint.event['@post'](event);
44 | });
45 | })
46 | .then(function (event) {
47 | console.log('added event to calendar: <' + event['@id'] + '>');
48 |
49 | // call the patch method of property invite
50 | return event.invite['@patch'](person);
51 | })
52 | .then(function () {
53 | // no content in response -> Promise.resolve === success
54 |
55 | console.log('invited: <' + person['@id'] + '>');
56 | })
57 | .catch(function (error) {
58 | console.error(error.stack);
59 | });
60 |
--------------------------------------------------------------------------------
/prepublish.js:
--------------------------------------------------------------------------------
1 | var
2 | exec = require('child_process').exec;
3 |
4 |
5 | var run = function (command) {
6 | return new Promise(function (resolve, reject) {
7 | exec(command, function (error, stdout, stderr) {
8 | if (error != null) {
9 | return reject(error);
10 | }
11 |
12 | if (stderr.trim() !== '') {
13 | console.error(stderr.trim());
14 | }
15 |
16 | if (stdout.trim() !== '') {
17 | console.log(stdout.trim());
18 | }
19 |
20 | resolve();
21 | });
22 | });
23 | };
24 |
25 |
26 | var browserify = function (source, target, options) {
27 | options = options || {};
28 |
29 | var cmd = './node_modules/.bin/browserify ' + source + ' -o ' + target;
30 |
31 | if (options.debug) {
32 | cmd += ' --debug';
33 | }
34 |
35 | if (options.exclude) {
36 | cmd += ' ' + options.exclude
37 | .map(function (exclude) {
38 | return '-u ' + exclude;
39 | })
40 | .join(' ');
41 | }
42 |
43 | if (options.list) {
44 | cmd += ' --list';
45 | }
46 |
47 | if (options.noBuiltins) {
48 | cmd += ' --no-builtins';
49 | }
50 |
51 | if (options.noBundleExternal) {
52 | cmd += ' --no-bundle-external';
53 | }
54 |
55 | if (options.standalone) {
56 | cmd += ' --standalone=' + options.standalone;
57 | }
58 |
59 | return run(cmd);
60 | };
61 |
62 |
63 | var exorcist = function (source, target, options) {
64 | options = options || {};
65 |
66 | var cmd = 'cat ' + source + ' | ./node_modules/.bin/exorcist ' + target + ' > /dev/null';
67 |
68 | return run(cmd);
69 | };
70 |
71 |
72 | var uglify = function (source, target, options) {
73 | options = options || {};
74 |
75 | var cmd = './node_modules/.bin/uglifyjs ' + source + ' -o ' + target;
76 |
77 |
78 | if (options.compress) {
79 | cmd += ' --compress';
80 | }
81 |
82 | if (options.inSourceMap) {
83 | cmd += ' --in-source-map ' + options.inSourceMap;
84 | }
85 |
86 | if (options.sourceMap) {
87 | cmd += ' --source-map ' + options.sourceMap;
88 | }
89 |
90 | if (options.sourceMapUrl) {
91 | cmd += ' --source-map-url ' + options.sourceMapUrl;
92 | }
93 |
94 | return run(cmd);
95 | };
96 |
97 |
98 | browserify('hydra-core.js', 'dist/hydra-core.js', { debug: true, noBundleExternal:true, standalone: 'hydra' })
99 | .then(function () {
100 | return exorcist('dist/hydra-core.js', 'dist/hydra-core.js.map', {});
101 | })
102 | .then(function () {
103 | return browserify('hydra-core.js', 'dist/hydra-core.js', { noBundleExternal:true, standalone: 'hydra' })
104 | })
105 | .then(function () {
106 | return uglify('dist/hydra-core.js', 'dist/hydra-core.min.js', {
107 | compress: true,
108 | inSourceMap: 'dist/hydra-core.js.map',
109 | sourceMap: 'dist/hydra-core.min.js.map',
110 | sourceMapUrl: 'hydra-core.min.js.map'
111 | });
112 | })
113 | .catch(function (error) {
114 | console.error(error.stack);
115 | });
116 |
--------------------------------------------------------------------------------
/lib/utils.js:
--------------------------------------------------------------------------------
1 | var utils = {};
2 |
3 |
4 | utils.require = function (module) {
5 | var globalModule = module;
6 |
7 | if (globalModule === 'lodash') {
8 | globalModule = '_';
9 | }
10 |
11 | if (typeof window !== 'undefined' && globalModule in window) {
12 | return window[globalModule];
13 | }
14 |
15 | return require(module);
16 | };
17 |
18 |
19 | var
20 | _ = utils.require('lodash'),
21 | jsonldp = utils.require('jsonld').promises();
22 |
23 |
24 | /**
25 | * Creates a Hydra Collection from a map or array of members
26 | *
27 | * @param iri
28 | * @param members
29 | * @returns {Collection}
30 | */
31 | utils.collection = function (iri, members) {
32 | return {
33 | '@id': iri,
34 | '@type': 'http://www.w3.org/ns/hydra/core#Collection',
35 | 'http://www.w3.org/ns/hydra/core#member': _.values(members).map(function (member) {
36 | return {
37 | '@id': member['@id'],
38 | '@type': member['@type']
39 | };
40 | })
41 | };
42 | };
43 |
44 | /**
45 | * Uses the given context to create a short form of the IRI
46 | *
47 | * @param iri
48 | * @param context
49 | * @returns {Promise}
50 | */
51 | utils.compactIri = function (iri, context) {
52 | var dummy = {};
53 |
54 | dummy[iri] = '';
55 |
56 | return jsonldp.compact(dummy, context)
57 | .then(function (compactDummy) {
58 | return _.keys(compactDummy).pop();
59 | });
60 | };
61 |
62 | /**
63 | * Creates a long version of the IRI using the given base
64 | *
65 | * @param iri
66 | * @param base
67 | * @returns {Promise}
68 | */
69 | utils.expandIri = function (iri, base) {
70 | if (!base) {
71 | return Promise.resolve(iri);
72 | }
73 |
74 | var dummy = {
75 | '@context': {
76 | '@base': base,
77 | '@vocab': 'http://schema.org/'
78 | },
79 | 'name': {
80 | '@id': iri
81 | }
82 | };
83 |
84 | return jsonldp.expand(dummy)
85 | .then(function (expanded) {
86 | return expanded[0]['http://schema.org/name'][0]['@id'];
87 | });
88 | };
89 |
90 | /**
91 | * Extracts the IRI of an JSON-LD object
92 | *
93 | * @param obj
94 | * @returns {*}
95 | */
96 | utils.iri = function (obj) {
97 | obj = utils.unwrap(obj);
98 |
99 | if (!obj) {
100 | return undefined;
101 | }
102 |
103 | if (_.isString(obj)) {
104 | return obj;
105 | }
106 |
107 | if (!('@id' in obj)) {
108 | return undefined;
109 | }
110 |
111 | return obj['@id'];
112 | };
113 |
114 | /**
115 | * Checks if the given object is a Hydra Collection
116 | *
117 | * @param collection
118 | * @returns {boolean}
119 | */
120 | utils.isCollection = function (collection) {
121 | if (!_.isObject(collection)) {
122 | return false;
123 | }
124 |
125 | if (!collection.member && !('http://www.w3.org/ns/hydra/core#member' in collection)) {
126 | return false;
127 | }
128 |
129 | return true;
130 | };
131 |
132 | /**
133 | * Converts single objects and Hydra Collections to Arrays and forwards existing Arrays
134 | *
135 | * @param obj
136 | * @returns {Array}
137 | */
138 | utils.toArray = function (obj) {
139 | if (!obj) {
140 | return [];
141 | }
142 |
143 | if (utils.isCollection(obj)) {
144 | obj = obj.member;
145 | }
146 |
147 | if (!_.isArray(obj)) {
148 | return [obj];
149 | }
150 |
151 | return obj;
152 | };
153 |
154 | /**
155 | * Extracts the first subject of an JSON-Ld object
156 | *
157 | * @param obj
158 | * @returns {*}
159 | */
160 | utils.unwrap = function (obj) {
161 | if (!obj) {
162 | return undefined;
163 | }
164 |
165 | if (_.isString(obj)) {
166 | return obj;
167 | }
168 |
169 | if ('@graph' in obj) {
170 | obj = obj['@graph'];
171 | }
172 |
173 | if (_.isArray(obj)) {
174 | if (obj.length === 0) {
175 | return undefined;
176 | } else {
177 | obj = obj[0];
178 | }
179 | }
180 |
181 | return obj;
182 | };
183 |
184 |
185 | module.exports = utils;
--------------------------------------------------------------------------------
/examples/api-demo-model.js:
--------------------------------------------------------------------------------
1 | (function (root, factory) {
2 | if (typeof module !== 'undefined' && module.exports) {
3 | module.exports = factory(require('../'));
4 | } else {
5 | factory(hydra);
6 | }
7 | })(this, function (hydra) {
8 | /**
9 | * This example registers a new user at the Hydra Issue Tracker Demo application [1]. That user is used to create a new
10 | * issue. The issue and user will be deleted afterwards, if "dontDelete" is not changed to "true". The Hydra Console [2]
11 | * can be used to view the created objects.
12 | *
13 | * [1] http://www.markus-lanthaler.com/hydra/api-demo/
14 | * [2] http://www.markus-lanthaler.com/hydra/console/
15 | */
16 |
17 | /**
18 | * !!! change this to true if you want to keep the created objects !!!
19 | */
20 | var dontDelete = false;
21 |
22 |
23 | var ns = {
24 | EntryPoint: 'http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint',
25 | Issue: 'http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue',
26 | User: 'http://www.markus-lanthaler.com/hydra/api-demo/vocab#User',
27 | issues: 'http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/issues',
28 | registerUser: 'http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/registerUser'
29 | };
30 |
31 |
32 | var config = {
33 | //base: 'http://www.markus-lanthaler.com',
34 | base: 'http://localhost:8080',
35 | user: 'hydracore',
36 | email: 'hydracore@test.com',
37 | password: '123456'
38 | };
39 |
40 |
41 | var credentials = {
42 | user: config.email,
43 | password: config.password
44 | };
45 |
46 |
47 | var entryPointContext = {
48 | '@context': {
49 | '@vocab': ns.EntryPoint + '/'
50 | }
51 | };
52 |
53 |
54 | var userContext = {
55 | '@context': {
56 | '@vocab': ns.User + '/'
57 | }
58 | };
59 |
60 |
61 | var userData = {
62 | '@context': {
63 | '@vocab': ns.User + '/'
64 | },
65 | // no need to define @type here, because it will be injected with the model
66 | name: config.user,
67 | email: config.email,
68 | password: config.password
69 | };
70 |
71 |
72 | var issueData = {
73 | '@context': {
74 | '@vocab': ns.Issue + '/'
75 | },
76 | // no need to define @type here, because it will be injected with the model
77 | title: 'Hydra Core test issue',
78 | description: 'Test issues created by Hydra Core',
79 | is_open: true
80 | };
81 |
82 |
83 | hydra.model.load(config.base + '/hydra/api-demo/', entryPointContext)
84 | .then(function (entryPoint) {
85 | console.log('loaded entry point: <' + entryPoint.document.iri + '>');
86 |
87 | return Promise.all([
88 | hydra.model.create(entryPoint.api.findClass(ns.User), userData),
89 | hydra.model.create(entryPoint.api.findClass(ns.Issue), issueData)
90 | ]).then(function (result) {
91 | var user = result[0];
92 | var issue = result[1];
93 |
94 | console.log('created user from abstract class with name: ' + user.name);
95 | console.log('created issue from abstract class with title: ' + issue.title);
96 |
97 | return entryPoint.registerUser['@post'](user, userContext)
98 | .then(function (registeredUser) {
99 | console.log('registered user as: <' + registeredUser['@id'] + '>');
100 |
101 | return entryPoint.issues['@post'](issue, credentials)
102 | .then(function (createdIssue) {
103 | console.log('submitted issue as: <' + createdIssue['@id'] + '>');
104 |
105 | if (dontDelete) {
106 | return;
107 | } else {
108 | return createdIssue['@delete'](null, credentials);
109 | }
110 |
111 |
112 | })
113 | .then(function () {
114 | if (dontDelete) {
115 | return;
116 | } else {
117 | console.log('deleted issue');
118 |
119 | return registeredUser['@delete']();
120 | }
121 | })
122 | .then(function () {
123 | if (!dontDelete) {
124 | console.log('deleted user');
125 | }
126 | });
127 | });
128 | });
129 | })
130 | .catch(function (error) {
131 | console.error(error.stack);
132 | });
133 | });
--------------------------------------------------------------------------------
/examples/api-demo.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This example registers a new user at the Hydra Issue Tracker Demo application [1]. That user is used to create a new
3 | * issue. The issue and user will be deleted afterwards, if "dontDelete" is not changed to "true". The Hydra Console [2]
4 | * can be used to view the created objects.
5 | *
6 | * [1] http://www.markus-lanthaler.com/hydra/api-demo/
7 | * [2] http://www.markus-lanthaler.com/hydra/console/
8 | */
9 |
10 | global.Promise = require('es6-promise').Promise;
11 |
12 |
13 | /**
14 | * !!! change this to true if you want to keep the created objects !!!
15 | */
16 | var dontDelete = false;
17 |
18 |
19 | var
20 | hydra = require('../'),
21 | jsonldp = require('jsonld').promises();
22 |
23 |
24 | var ns = {
25 | Issue: 'http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue',
26 | User: 'http://www.markus-lanthaler.com/hydra/api-demo/vocab#User',
27 | issues: 'http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/issues',
28 | registerUser: 'http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/registerUser'
29 | };
30 |
31 |
32 | var config = {
33 | //base: 'http://www.markus-lanthaler.com',
34 | base: 'http://localhost:8080',
35 | user: 'hydracore',
36 | email: 'hydracore@test.com',
37 | password: '123456'
38 | };
39 |
40 |
41 | var user = {
42 | '@context': {
43 | '@vocab': ns.User + '/'
44 | },
45 | '@type': ns.User,
46 | name: config.user,
47 | email: config.email,
48 | password: config.password
49 | };
50 |
51 |
52 | var issue = {
53 | '@context': {
54 | '@vocab': ns.Issue + '/'
55 | },
56 | '@type': ns.Issue,
57 | title: 'Hydra Core test issue',
58 | description: 'Test issues created by Hydra Core',
59 | is_open: true
60 | };
61 |
62 |
63 | Promise.resolve()
64 | .then(function () {
65 | return hydra.loadDocument(config.base + '/hydra/api-demo/')
66 | .then(function (document) {
67 | // find "register user" operation using property IRI and method
68 | var registerUser = document.findOperation(ns.registerUser, 'POST').invoke;
69 |
70 | // find "create issue" operation using property IRI and method
71 | var createIssue = document.findOperation(ns.issues, 'POST').invoke;
72 |
73 | // invoke "register user" operation
74 | return registerUser(user)
75 | .then(function (response) {
76 | return jsonldp.compact(response, {'@vocab': 'http://www.markus-lanthaler.com/hydra/api-demo/vocab#User/'});
77 | })
78 | .then(function (response) {
79 | user = response;
80 |
81 | console.log('created user <' + user['@id'] + '>');
82 | console.log(user);
83 | })
84 | .then(function () {
85 | // invoke "create issue" operation using basic authentication
86 | return createIssue(issue, {user: config.email, password: config.password});
87 | })
88 | .then(function (response) {
89 | return jsonldp.compact(response, {'@vocab': 'http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue/'});
90 | })
91 | .then(function (response) {
92 | issue = response;
93 |
94 | console.log('created issue <' + issue['@id'] + '>');
95 | console.log(issue);
96 | });
97 | })
98 | })
99 | .then(function () {
100 | if (dontDelete) {
101 | return Promise.resolve();
102 | }
103 |
104 | return hydra.loadDocument(issue['@id'])
105 | .then(function (document) {
106 | // find "delete" class operation
107 | var deleteIssue = document.findOperation('DELETE').invoke;
108 |
109 | // invoke "delete" operation using basic authentication
110 | return deleteIssue(null, {user: config.email, password: config.password})
111 | .then(function () {
112 | console.log('deleted issue <' + issue['@id'] + '>');
113 | });
114 | });
115 | })
116 | .then(function () {
117 | if (dontDelete) {
118 | return Promise.resolve();
119 | }
120 |
121 | return hydra.loadDocument(user['@id'])
122 | .then(function (document) {
123 | // find "delete" class operation
124 | var deleteUser = document.findOperation('DELETE').invoke;
125 |
126 | // invoke "delete" operation using basic authentication
127 | return deleteUser(null, {user: config.email, password: config.password})
128 | .then(function () {
129 | console.log('deleted user <' + user['@id'] + '>');
130 | });
131 | });
132 | })
133 | .catch(function (error) {
134 | console.error(error.stack);
135 | });
136 |
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 | global.Promise = require('es6-promise').Promise;
2 |
3 |
4 | var
5 | assert = require('assert'),
6 | fs = require('fs'),
7 | hydra = require('../hydra-core');
8 |
9 |
10 | var promiseDone = function (done) {
11 | return function () {
12 | done();
13 | };
14 | };
15 |
16 | var promiseError = function (done) {
17 | return function (error) {
18 | done(error.stack);
19 | };
20 | };
21 |
22 |
23 | describe('hydra', function () {
24 | var base = 'http://www.markus-lanthaler.com';
25 | var apiString;
26 | var entryPointString;
27 |
28 | before(function () {
29 | apiString = fs.readFileSync('test/support/api.json').toString();
30 | entryPointString = fs.readFileSync('test/support/entrypoint.json').toString();
31 | });
32 |
33 | describe('utils', function () {
34 | it('finder should find a single item based on iri or given property', function () {
35 | var items = [
36 | {iri: '1', prop: 'a'},
37 | {iri: '2', prop: 'b'}
38 | ];
39 |
40 | var iriFinder = hydra.utils.finder(items);
41 | var propertyFinder = hydra.utils.finder(items, 'prop');
42 |
43 | assert.equal(iriFinder('3'), undefined, 'unknown item');
44 | assert.deepEqual(iriFinder('2'), {iri: '2', prop: 'b'}, 'known item');
45 | assert.equal(propertyFinder('c'), undefined, 'unknown item');
46 | assert.deepEqual(propertyFinder('a'), {iri: '1', prop: 'a'}, 'known item');
47 | });
48 |
49 | it('iri should return the IRI of an JSON-LD object', function () {
50 | assert.equal(hydra.utils.iri(null), undefined, 'null object');
51 | assert.equal(hydra.utils.iri({}), undefined, 'initial object');
52 | assert.equal(hydra.utils.iri({'@id': 'a'}), 'a', 'filled object');
53 | });
54 |
55 | it('toArray should convert anything to an array', function () {
56 | assert.deepEqual(hydra.utils.toArray(null), [], 'null');
57 | assert.deepEqual(hydra.utils.toArray('1'), ['1'], 'non array value');
58 | assert.deepEqual(hydra.utils.toArray(['1', '2']), ['1', '2'], 'array value');
59 | });
60 |
61 | it('unwrap should extract the graph of a JSON-LD object', function () {
62 | assert.equal(hydra.utils.unwrap(null), undefined, 'null');
63 | assert.equal(hydra.utils.unwrap('_:test'), '_:test', 'string');
64 | assert.deepEqual(hydra.utils.unwrap({'@id': 'test'}), {'@id': 'test'}, 'not wrapped graph');
65 | assert.deepEqual(hydra.utils.unwrap({'@graph': [{'@id': 'test1'}, {'@id': 'test2'}]}), {'@id': 'test1'}, 'wrapped graph');
66 | assert.deepEqual(hydra.utils.unwrap({'@graph': []}), undefined, 'empty graph');
67 | });
68 |
69 | it('values should return the values of an object', function () {
70 | assert.equal(hydra.utils.values(null), undefined, 'null object');
71 | assert.deepEqual(hydra.utils.values({}), [], 'initial object');
72 | assert.deepEqual(hydra.utils.values({a: 'ab', b: 'cd'}), ['ab', 'cd'], 'filled object with two properties');
73 | });
74 | });
75 |
76 | describe('Api', function () {
77 | it('should create a hydra.Api object from a JSON string', function (done) {
78 | hydra.api(apiString, base)
79 | .then(function (api) {
80 | assert(api instanceof hydra.Api);
81 | assert.equal(api.iri, base + '/hydra/api-demo/vocab');
82 | })
83 | .then(promiseDone(done))
84 | .catch(promiseError(done));
85 | });
86 |
87 | it('should create a hydra.Api object with classes and operations properties', function (done) {
88 | hydra.api(apiString, base)
89 | .then(function (api) {
90 | assert(Array.isArray(api.classes));
91 | assert.equal(api.classes.length, 6);
92 | assert(Array.isArray(api.operations));
93 | assert.equal(api.operations.length, 23);
94 | })
95 | .then(promiseDone(done))
96 | .catch(promiseError(done));
97 | });
98 | });
99 |
100 | describe('Document', function () {
101 | it('should create a hydra.Document object from a JSON string', function (done) {
102 | hydra.api(apiString)
103 | .then(function (api) {
104 | return hydra.document(api, entryPointString, base);
105 | })
106 | .then(function (document) {
107 | assert(document instanceof hydra.Document);
108 | assert.equal(document.iri, base + '/hydra/api-demo/');
109 | })
110 | .then(promiseDone(done))
111 | .catch(promiseError(done));
112 | });
113 |
114 | it('should create a hydra.Document object with classes and properties properties', function (done) {
115 | hydra.api(apiString)
116 | .then(function (api) {
117 | return hydra.document(api, entryPointString, base);
118 | })
119 | .then(function (document) {
120 | assert(Array.isArray(document.classes));
121 | assert.equal(document.classes.length, 1);
122 | assert(Array.isArray(document.properties));
123 | assert.equal(document.properties.length, 3);
124 | })
125 | .then(promiseDone(done))
126 | .catch(promiseError(done));
127 | });
128 | });
129 | });
--------------------------------------------------------------------------------
/lib/model.js:
--------------------------------------------------------------------------------
1 | var
2 | hydra = require('./core'),
3 | utils = require('./utils'),
4 | _ = utils.require('lodash'),
5 | jsonldp = utils.require('jsonld').promises();
6 |
7 |
8 | hydra.model = {};
9 |
10 |
11 | /**
12 | * Creates an invoke function for model objects that compacts the response using the given context
13 | *
14 | * @param operation
15 | * @returns {Function}
16 | */
17 | hydra.model.createHttpJsonLdInvoke = function (operation) {
18 | return function (input, options) {
19 | options = options || {};
20 |
21 | var context = {};
22 |
23 | if ('@context' in this) {
24 | context = this['@context'];
25 | }
26 |
27 | context = options.context || context;
28 |
29 | if (input && input.toJSON) {
30 | input = input.toJSON();
31 | }
32 |
33 | return hydra.httpClient.rawJsonLdInvoke.call(operation, input, options)
34 | .then(function (response) {
35 | if (!response.body) {
36 | return Promise.resolve(null);
37 | }
38 |
39 | return hydra.documentFromResponse(response)
40 | .then(function (document) {
41 | return jsonldp.compact(response.body, context)
42 | .then(function (output) {
43 | return hydra.model.create(document.classes, output);
44 | });
45 | });
46 | });
47 | };
48 | };
49 |
50 | /**
51 | * Converts a model object to serializable object without functions and property flagged with @omit
52 | */
53 | hydra.model.toJSON = function () {
54 | var copyProperties = function (object, root) {
55 | if (!object) {
56 | return null;
57 | }
58 |
59 | var copy = _.keys(object).reduce(function (json, key) {
60 | var value = object[key];
61 |
62 | // don't add function properties
63 | if (_.isFunction(value)) {
64 | return json;
65 | }
66 |
67 | // don't add properties with @omit flag
68 | if (_.isObject(value) && '@omit' in value && value['@omit']) {
69 | return json;
70 | }
71 |
72 | if (_.isObject(value)) {
73 | // copy sub properties
74 | json[key] = copyProperties(value, root);
75 | } else {
76 | // copy string values
77 | json[key] = value;
78 | }
79 |
80 | return json;
81 | }, {});
82 |
83 | // convert to Array if original object was an Array
84 | if (_.isArray(object)) {
85 | copy = _.values(object);
86 | }
87 |
88 | return copy;
89 | };
90 |
91 | return copyProperties(this);
92 | };
93 |
94 | /**
95 | * Adds a @omit property to an object to hide it from serialization
96 | *
97 | * @param property
98 | * @returns {Object}
99 | */
100 | hydra.model.hide = function (property) {
101 | property['@omit'] = true;
102 |
103 | return property;
104 | };
105 |
106 | /**
107 | * Creates a model object based on one or more classes
108 | *
109 | * @param classes The class or classes the model will be bases on
110 | * @param properties Properties to merge into the model object
111 | * @param options Additional options to control the model creation
112 | * @returns {*}
113 | */
114 | hydra.model.create = function (classes, properties, options) {
115 | var processOperations = function (root, operations) {
116 | operations.forEach(function (operation) {
117 | var key = '@' + operation.method.toLowerCase();
118 |
119 | if (!(key in root)) {
120 | root[key] = options.createInvoke(operation).bind(model);
121 | }
122 | });
123 |
124 | return Promise.resolve();
125 | };
126 |
127 | var processProperties = function (root, properties) {
128 | return Promise.all(properties.map(function (property) {
129 | return utils.compactIri(property.iri, model['@context'])
130 | .then(function (key) {
131 | if (!(key in root)) {
132 | root[key] = {};
133 | }
134 |
135 | return processOperations(root[key], property.operations);
136 | });
137 | }));
138 | };
139 |
140 | var processClass = function (apiClass) {
141 | model['@type'].push(apiClass.iri);
142 |
143 | return processOperations(model, apiClass.operations)
144 | .then(function () {
145 | return processProperties(model, apiClass.properties);
146 | });
147 | };
148 |
149 | classes = utils.toArray(classes);
150 |
151 | options = options || {};
152 | options.createInvoke = options.createInvoke || hydra.defaults.model.createInvoke;
153 |
154 | var model = _.clone(properties);
155 |
156 | _.defaults(model, {
157 | '@context': {},
158 | toJSON: hydra.model.toJSON
159 | });
160 |
161 | model['@type'] = [];
162 | model.api = classes[0].api || classes[0].abstract.api;
163 | model.api['@omit'] = true;
164 |
165 | if (classes[0].document) {
166 | model.document = classes[0].document;
167 | model.document['@omit'] = true;
168 | }
169 |
170 | return Promise.all(classes.map(function (apiClass) {
171 | return processClass(apiClass);
172 | })).then(function () {
173 | return model;
174 | });
175 | };
176 |
177 | /**
178 | * Creates a model object based on a GET request to the given URL
179 | *
180 | * @param url URL
181 | * @param properties Properties that will be merged into the model object
182 | * @param options Options for the request
183 | * @returns {Promise}
184 | */
185 | hydra.model.load = function (url, properties, options) {
186 | return hydra.loadDocument(url)
187 | .then(function (document) {
188 | return hydra.model.create(document.classes, properties, options);
189 | });
190 | };
191 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Hydra Core
2 |
3 | Hydra Core provides basic objects to work with Hydra enabled Web APIs.
4 |
5 | ## Usage
6 |
7 | ### Node.js
8 |
9 | hydra-core is available on `npm`, to install it run:
10 |
11 | ```shell
12 | npm install hydra-core
13 | ```
14 |
15 | In the code, import hydra-core:
16 |
17 | ```javascript
18 | var hydra = require('hydra-core');
19 | ```
20 |
21 | ## Examples
22 |
23 | The examples folder contains working example code for the Hydra Issue Tracker Demo application.
24 |
25 | ```shell
26 | cd examples
27 | node api-demo.js
28 | ```
29 |
30 | An alternative example code uses the object model to access the Hydra Issue Tracker Demo application.
31 |
32 | ```shell
33 | cd examples
34 | node api-demo-model.js
35 | ```
36 |
37 | ## API
38 |
39 | ### hydra.Api
40 |
41 | #### classes:
42 | `Array` of `hydra.Class` objects defined in the API documentation.
43 |
44 | #### operations:
45 | `Array` of `hydra.Operation` objects defined in the API documentation.
46 |
47 | #### findClass(iri):
48 | Returns a `hydra.Class` object for the given IRI or `undefined` if the IRI is unknown.
49 |
50 | #### findOperation(iri):
51 | Returns a `hydra.Operation` object for the given IRI or `undefined` if the IRI is unknown.
52 |
53 | ### hydra.Document
54 |
55 | #### classes
56 | `Array` of `hydra.ClassDocument` objects based on `rdf:type` triples in the document.
57 |
58 | #### properties
59 | `Array` of `hydra.PropertyDocument` objects based on triples in the document.
60 |
61 | #### findOperation([propertyIri], method):
62 | Returns a `hydra.OperationDocument` object or `undefined` if the operation was not found.
63 | Searches only in the classes of the document, if only the `method` argument is given.
64 | Searches for operations assigned to the property, if the `propertyIri` arguments is also given.
65 |
66 | #### findProperty
67 | Returns a `hydra.PropertyDocument` object for the given IRI or `undefined` if the IRI is unknown.
68 |
69 | ### hydra.Class
70 |
71 | ### hydra.ClassDocument
72 |
73 | ### hydra.Operation
74 |
75 | ### hydra.OperationDocument
76 |
77 | ### hydra.Property
78 |
79 | ### hydra.PropertyDocument
80 |
81 | ### hydra.api(json, base)
82 |
83 | Parses the given JSON-LD object or string and returns a `hydra.Api` object using a Promise.
84 | The `base` parameter is used to expand the given JSON-LD object.
85 |
86 | ### hydra.document(api, json, base)
87 |
88 | Parses the given JSON-LD object or string and returns a `hydra.Document` object using a Promise.
89 | `api` must be an instance of `hydra.Api`.
90 | The `base` parameter is used to expand the given JSON-LD object.
91 |
92 | ## API Model
93 |
94 | The hydra core object model uses JSON-LD objects extended with functions and additional `@` properties.
95 | Hydra operations are mapped into the objects with the `@` + lower case the HTTP method keys.
96 | For example, if an entry point class contains `http://schema.org/blogPost` property that implements a HTTP POST
97 | method to create a new blog post, the following code could be used:
98 |
99 | ```javascript
100 | // load the entry point from http://example.com/
101 | hydra.model.load('http://example.com/')
102 | .then(function (entryPoint) {
103 | // create a new blog post using the post method of http://schema.org/blogPost
104 | return entryPoint['http://schema.org/blogPost']['@post']({
105 | 'http://schema.org/name': 'blog post name',
106 | 'http://schema.org/articleBody': 'this is the content of the blog post'
107 | });
108 | })
109 | .then(function (blogPost) {
110 | // write the IRI of the created blog post to the console
111 | console.log(blogPost['@id']);
112 | });
113 | ```
114 |
115 | If a JSON-LD context is defined, the objects will be compacted using that context:
116 |
117 | ```javascript
118 | // define the context in the properties object, that will be merged into the model object
119 | hydra.model.load('http://example.com/', {'@context': {'@vocab': 'http://schema.org'}})
120 | .then(function (entryPoint) {
121 | // works also with the POST operation
122 | return entryPoint.blogPost['@post']({
123 | '@context': {'@vocab': 'http://schema.org'},
124 | name: 'blog post name',
125 | articleBody: 'this is the content of the blog post'
126 | }, {'@context': {'@vocab': 'http://schema.org'}});
127 | });
128 | ```
129 |
130 | It's possible to add properties to the model object and hide them from the serialization.
131 | A `@omit: true` key value pair must be added to the property.
132 | The `hydra.model.hide` method can be used for this:
133 |
134 | ```javascript
135 | // assign a new hidden variable
136 | blogPost.privateVariable = hydra.model.hide(privateVariable);
137 | ```
138 |
139 | Every model object built with `hydra.model.create` contains a hidden variable `api` that contains the API documentation.
140 | That object can be used to create model objects based on classes defined in the API documentation:
141 |
142 | ```javascript
143 | hydra.model.create(entryPoint.api.findClass('http://schema.org/BlogPost'))
144 | .then(function (blogPost) {
145 | });
146 | ```
147 |
148 | ### hydra.model.create(classes, properties, options)
149 |
150 | Creates a model object bases on a single or an `Array` of `hydra.Class` or `hydra.ClassDocument`.
151 | The properties object is merged into the model object.
152 | Additional options that control the model object building.
153 |
154 | ### hydra.model.hide(property)
155 |
156 | Adds a `@omit: true` key value pair to the property object and returns that property object.
157 | `property` must be an object.
158 |
159 | ### hydra.model.load(url, properties, options)
160 |
161 | Creates a model object based on the result of a `GET` request to the given `url`.
162 | The `properties` and `options` arguments will be forwarded to the `hydra.model.create` function.
163 |
164 | ### hydra.model.toJSON()
165 |
166 | A `toJSON` function that removes all functions and properties that contain a `@omit: true` key value pair.
167 |
--------------------------------------------------------------------------------
/lib/core.js:
--------------------------------------------------------------------------------
1 | var
2 | utils = require('./utils'),
3 | _ = utils.require('lodash'),
4 | jsonldp = utils.require('jsonld').promises();
5 |
6 |
7 | var hydra = {};
8 |
9 |
10 | hydra.ns = {
11 | vocab: 'http://www.w3.org/ns/hydra/core#',
12 | apiDocumentation: 'http://www.w3.org/ns/hydra/core#apiDocumentation',
13 | member: 'http://www.w3.org/ns/hydra/core#member'
14 | };
15 |
16 |
17 | var rdfs = {
18 | ns: {
19 | comment: 'http://www.w3.org/2000/01/rdf-schema#comment',
20 | label: 'http://www.w3.org/2000/01/rdf-schema#label',
21 | range: 'http://www.w3.org/2000/01/rdf-schema#range'
22 | }
23 | };
24 |
25 |
26 | hydra.Api = function (def) {
27 | var self = this;
28 |
29 | this.iri = utils.iri(def);
30 |
31 | this.init = function () {
32 | var classFrameDef = {
33 | '@context': {
34 | '@vocab': hydra.ns.vocab,
35 | 'label': rdfs.ns.label
36 | },
37 | '@type': 'Class'
38 | };
39 |
40 | var operationFrameDef = {
41 | '@context': {
42 | '@vocab': hydra.ns.vocab,
43 | 'label': rdfs.ns.label
44 | },
45 | '@type': 'Operation'
46 | };
47 |
48 | return Promise.all([
49 | jsonldp.frame(def, classFrameDef)
50 | .then(function (classDef) {
51 | self.classDef = classDef;
52 | }),
53 | jsonldp.frame(def, operationFrameDef)
54 | .then(function (operationDef) {
55 | self.operationDef = operationDef;
56 | })])
57 | .then(function () {
58 | var inits = [];
59 |
60 | self.classes = self.classDef['@graph'].map(function (def) {
61 | var instance = new hydra.Class(self, def);
62 |
63 | inits.push(instance.init());
64 |
65 | return instance;
66 | });
67 |
68 | self.findClass = _.find.bind(null, self.classes, 'iri');
69 |
70 | self.operations = self.operationDef['@graph'].map(function (def) {
71 | var instance = new hydra.Operation(self, def);
72 |
73 | inits.push(instance.init());
74 |
75 | return instance;
76 | });
77 |
78 | self.findOperation = _.find.bind(null, self.operations, 'iri');
79 |
80 | return Promise.all(inits)
81 | .then(function () {
82 | return self;
83 | });
84 | });
85 | };
86 | };
87 |
88 |
89 | hydra.Document = function (api, def, iri) {
90 | var self = this;
91 |
92 | this.api = api;
93 | this.iri = iri || utils.iri(def);
94 |
95 | this.init = function () {
96 | return Promise.resolve()
97 | .then(function () {
98 | def = utils.unwrap(def);
99 |
100 | if (!('@type' in def)) {
101 | return Promise.reject('type missing');
102 | }
103 |
104 | self.classes = _.values(def['@type'])
105 | .filter(function (type) {
106 | return !!self.api.findClass(type);
107 | })
108 | .map(function (type) {
109 | return new hydra.ClassDocument(self, self.api.findClass(type), def);
110 | });
111 |
112 | self.properties = self.classes
113 | .map(function (documentClass) {
114 | return documentClass.abstract.properties
115 | .filter(function (abstractProperty) {
116 | return abstractProperty.iri in def;
117 | })
118 | .map(function (abstractProperty) {
119 | return new hydra.PropertyDocument(self, abstractProperty, def[abstractProperty.iri]);
120 | });
121 | })
122 | .reduce(function (properties, classProperties) {
123 | return properties.concat(classProperties);
124 | }, []);
125 |
126 | self.findProperty = _.find.bind(null, self.properties, 'iri');
127 |
128 | self.findOperation = function() {
129 | if (arguments.length === 1) {
130 | var method = arguments[0];
131 |
132 | return self.classes
133 | .map(function (documentClass) {
134 | return documentClass.findOperation(method);
135 | })
136 | .shift();
137 | } else {
138 | var iri = arguments[0];
139 | var method = arguments[1];
140 |
141 | var documentProperty = self.findProperty(iri);
142 |
143 | if (!documentProperty) {
144 | return undefined;
145 | }
146 |
147 | return documentProperty.findOperation(method);
148 | }
149 | };
150 |
151 | return self;
152 | });
153 | };
154 | };
155 |
156 |
157 | hydra.Class = function (api, def) {
158 | var self = this;
159 |
160 | self.api = api;
161 | self.iri = def['@id'];
162 | _.extend(self, def)
163 |
164 | self.init = function () {
165 | return Promise.resolve().then(function () {
166 | self.operations = utils.toArray(def.supportedOperation).map(function (operationDef) {
167 | return self.api.findOperation(operationDef['@id']);
168 | });
169 |
170 | self.findOperation = _.find.bind(null, self.operations, 'method');
171 |
172 | self.properties = utils.toArray(def.supportedProperty).map(function (propertyDef) {
173 | return new hydra.Property(self.api, propertyDef);
174 | });
175 |
176 | self.findProperty = _.find.bind(null, self.properties, 'iri');
177 |
178 | return self;
179 | });
180 | };
181 |
182 | self.validate = hydra.defaults.validateClass;
183 | };
184 |
185 |
186 | hydra.ClassDocument = function (document, abstract, def) {
187 | this.document = document;
188 | this.iri = abstract.iri;
189 | this.abstract = abstract;
190 | this.label = this.abstract.label;
191 | this.operations = abstract.operations.map(function (operation) {
192 | return new hydra.OperationDocument(document, operation);
193 | });
194 | this.properties = abstract.properties
195 | .filter(function (property) {
196 | return property.iri in def;
197 | })
198 | .map(function (property) {
199 | return new hydra.PropertyDocument(document, property, def[property.iri]);
200 | });
201 |
202 | this.findOperation = _.find.bind(null, this.operations, 'method');
203 |
204 | this.findProperty = _.find.bind(null, this.properties, 'iri');
205 | };
206 |
207 |
208 | hydra.Operation = function (api, def) {
209 | var self = this;
210 |
211 | self.api = api;
212 | self.iri = def['@id'];
213 | _.extend(self, def)
214 |
215 | self.init = function () {
216 | return Promise.resolve().then(function () {
217 | self.method = def.method;
218 | self.statusCodes = def.statusCodes;
219 | self.expects = self.api.findClass(utils.iri(def.expects));
220 | self.returns = self.api.findClass(utils.iri(def.returns));
221 |
222 | return self;
223 | });
224 | };
225 | };
226 |
227 |
228 | hydra.OperationDocument = function (document, abstract, def) {
229 | this.document = document;
230 | this.iri = abstract.iri;
231 | this.abstract = abstract;
232 | this.link = !!def ? utils.iri(def) : null;
233 | this.label = this.abstract.label;
234 | this.method = this.abstract.method;
235 | this.statusCodes = this.abstract.statusCodes;
236 | this.expects = this.abstract.expects;
237 | this.returns = this.abstract.returns;
238 | this.invoke = hydra.defaults.invokeOperation.bind(this);
239 | };
240 |
241 |
242 | hydra.Property = function (api, def) {
243 | var self = this;
244 |
245 | self.api = api;
246 | self.iri = utils.iri(def.property);
247 | _.extend(self, def)
248 |
249 | self.operations = utils.toArray(def.property.supportedOperation)
250 | .map(function (operationDef) {
251 | return self.api.findOperation(utils.iri(operationDef));
252 | });
253 |
254 | self.findOperation = _.find.bind(null, self.operations, 'method');
255 | };
256 |
257 |
258 | hydra.PropertyDocument = function (document, abstract, def) {
259 | this.document = document;
260 | this.iri = abstract.iri;
261 | this.abstract = abstract;
262 | this.link = !!def ? utils.iri(def) : null;
263 | this.label = this.abstract.label;
264 | this.operations = abstract.operations.map(function (operation) {
265 | return new hydra.OperationDocument(document, operation, def);
266 | });
267 |
268 | this.findOperation = _.find.bind(null, this.operations, 'method');
269 | };
270 |
271 |
272 | hydra.api = function (json, base) {
273 | if (_.isString(json)) {
274 | json = JSON.parse(json);
275 | }
276 |
277 | return jsonldp.expand(json, {base: base})
278 | .then(function (compact) {
279 | return (new hydra.Api(compact)).init();
280 | });
281 | };
282 |
283 |
284 | hydra.document = function (api, json, base) {
285 | if (_.isString(json)) {
286 | json = JSON.parse(json);
287 | }
288 |
289 | return jsonldp.expand(json, {base: base})
290 | .then(function (compact) {
291 | return (new hydra.Document(api, compact, base)).init();
292 | });
293 | };
294 |
295 |
296 | module.exports = hydra;
297 |
--------------------------------------------------------------------------------
/lib/http-client.js:
--------------------------------------------------------------------------------
1 | var
2 | hydra = require('./core'),
3 | utils = require('./utils'),
4 | jsonld = utils.require('jsonld'),
5 | jsonldp = utils.require('jsonld').promises();
6 |
7 |
8 | hydra.httpClient = {};
9 |
10 |
11 | if (typeof XMLHttpRequest !== 'undefined') {
12 | /**
13 | * Converts a string to a UTF-8 encoded string
14 | * @param string The string to encode
15 | * @returns {string} The UTF-8 string
16 | */
17 | hydra.httpClient.utf8Encode = function (string) {
18 | string = string.replace(/\r\n/g, '\n');
19 |
20 | var utftext = '';
21 |
22 | for (var n = 0; n < string.length; n++) {
23 | var c = string.charCodeAt(n);
24 |
25 | if (c < 128) {
26 | utftext += String.fromCharCode(c);
27 | } else if ((c > 127) && (c < 2048)) {
28 | utftext += String.fromCharCode((c >> 6) | 192);
29 | utftext += String.fromCharCode((c & 63) | 128);
30 | } else {
31 | utftext += String.fromCharCode((c >> 12) | 224);
32 | utftext += String.fromCharCode(((c >> 6) & 63) | 128);
33 | utftext += String.fromCharCode((c & 63) | 128);
34 | }
35 | }
36 |
37 | return utftext;
38 | };
39 |
40 | /**
41 | * Converts a string to a base-64 encoded string
42 | * @param input The string to encode
43 | * @returns {string} The base-64 string
44 | */
45 | hydra.httpClient.base64Encode = function (input) {
46 | var keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
47 | var output = '';
48 | var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
49 | var i = 0;
50 |
51 | input = hydra.httpClient.utf8Encode(input);
52 |
53 | while (i < input.length) {
54 | chr1 = input.charCodeAt(i++);
55 | chr2 = input.charCodeAt(i++);
56 | chr3 = input.charCodeAt(i++);
57 |
58 | enc1 = chr1 >> 2;
59 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
60 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
61 | enc4 = chr3 & 63;
62 |
63 | if (isNaN(chr2)) {
64 | enc3 = enc4 = 64;
65 | } else if (isNaN(chr3)) {
66 | enc4 = 64;
67 | }
68 |
69 | output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
70 | }
71 |
72 | return output;
73 | };
74 |
75 | /**
76 | * Request implementation using XMLHttpRequest interface
77 | *
78 | * @param method HTTP method
79 | * @param url URL
80 | * @param headers Header key/value pairs
81 | * @param content Content
82 | * @param callback Callback function using with interface: statusCode, headers, content, error
83 | */
84 | hydra.httpClient.requestAsync = function (method, url, headers, content, callback, options) {
85 | options = options || {};
86 |
87 | var xhr = new XMLHttpRequest();
88 |
89 | xhr.onreadystatechange = function () {
90 | if (xhr.readyState === xhr.DONE) {
91 | var
92 | headerLines = xhr.getAllResponseHeaders().split('\r\n'),
93 | resHeaders = {};
94 |
95 | for (var i = 0; i < headerLines.length; i++) {
96 | var headerLine = headerLines[i].split(': ', 2);
97 | resHeaders[headerLine[0].toLowerCase()] = headerLine[1];
98 | }
99 |
100 | callback(xhr.status, resHeaders, xhr.responseText);
101 | }
102 | };
103 |
104 | xhr.open(method, url, true);
105 |
106 | for (var header in headers) {
107 | xhr.setRequestHeader(header, headers[header]);
108 | }
109 |
110 | if (options.user && options.password) {
111 | xhr.setRequestHeader("Authorization", "Basic " + hydra.httpClient.base64Encode(options.user + ":" + options.password));
112 | }
113 |
114 | xhr.send(content);
115 | };
116 | } else {
117 | /**
118 | * Request implementation using the npm request module
119 | *
120 | * @param method HTTP method
121 | * @param url URL
122 | * @param headers Header key/value pairs
123 | * @param content Content
124 | * @param callback Callback function using with interface: statusCode, headers, content, error
125 | * @param options Additional options like user or password
126 | */
127 | hydra.httpClient.requestAsync = function (method, url, headers, content, callback, options) {
128 | var request = require('request');
129 |
130 | options = options || {};
131 |
132 | var req = {
133 | method: method,
134 | url: url,
135 | headers: headers,
136 | body: content
137 | };
138 |
139 | if (options.user && options.password) {
140 | req.auth = {
141 | user: options.user,
142 | password: options.password
143 | };
144 | }
145 |
146 | request(req, function (error, res, body) {
147 | if (error) {
148 | callback(null, null, null, error);
149 | } else {
150 | callback(res.statusCode, res.headers, body);
151 | }
152 | });
153 | };
154 | }
155 |
156 | /**
157 | * Promise request implementation
158 | *
159 | * @param method HTTP method
160 | * @param url URL
161 | * @param headers Header key/value pairs
162 | * @param content Content
163 | * @param options Additional options like user or password
164 | * @returns {Promise}
165 | */
166 | hydra.httpClient.request = function (method, url, headers, content, options) {
167 | return new Promise(function (resolve, reject) {
168 | hydra.httpClient.requestAsync(method, url, headers, content, function (status, resHeaders, resBody, error) {
169 | var response = {
170 | status: status,
171 | headers: resHeaders,
172 | body: resBody,
173 | request: {
174 | url: url,
175 | method: method,
176 | headers: headers,
177 | body: content
178 | }
179 | };
180 |
181 | if (error) {
182 | reject(error);
183 | } else if (status >= 400) {
184 | reject(new Error('status code ' + status + ': ' + resBody));
185 | } else {
186 | resolve(response);
187 | }
188 | }, options);
189 | });
190 | };
191 |
192 | /**
193 | * Extracts the Hydra API Documentation value of the Link header field
194 | *
195 | * @param headers
196 | * @param base
197 | * @returns {Promise}
198 | */
199 | hydra.httpClient.apiLink = function (headers, base) {
200 | if (!('link' in headers)) {
201 | return Promise.resolve(undefined);
202 | }
203 |
204 | var rels = jsonld.parseLinkHeader(headers.link);
205 |
206 | if (!(hydra.ns.apiDocumentation in rels)) {
207 | return Promise.resolve(undefined);
208 | }
209 |
210 | return utils.expandIri(rels[hydra.ns.apiDocumentation].target, base);
211 | };
212 |
213 | /**
214 | * Extracts the value of the Content-Location header field
215 | *
216 | * @param headers
217 | * @param base
218 | * @returns {*}
219 | */
220 | hydra.httpClient.contentLocation = function (headers, base) {
221 | if (!('content-location' in headers)) {
222 | return Promise.resolve(undefined);
223 | }
224 |
225 | return utils.expandIri(headers['content-location'], base);
226 | };
227 |
228 | /**
229 | * Calls an operations with the given headers and content
230 | *
231 | * @param headers
232 | * @param content
233 | * @param options
234 | * @returns {Promise}
235 | */
236 | hydra.httpClient.rawInvoke = function (headers, content, options) {
237 | var self = this;
238 |
239 | var url = self.link || self.document.iri;
240 |
241 | return hydra.httpClient.request(self.method, url, headers, content, options);
242 | };
243 |
244 | /**
245 | * Calls an operations with the JSON-LD content and converts the response body to JSON-LD
246 | *
247 | * @param content
248 | * @param options
249 | * @returns {Promise}
250 | */
251 | hydra.httpClient.rawJsonLdInvoke = function (content, options) {
252 | var self = this;
253 |
254 | var headers = {
255 | 'Accept': 'application/ld+json'
256 | };
257 |
258 | if (self.method === 'PATCH' || self.method === 'POST' || self.method === 'PUT') {
259 | headers['Content-Type'] = 'application/ld+json';
260 | }
261 |
262 | return hydra.httpClient.rawInvoke.bind(self)(headers, JSON.stringify(content), options)
263 | .then(function (response) {
264 | if (response.body && response.body.trim() !== '') {
265 | return jsonldp.expand(JSON.parse(response.body), {base: response.request.url})
266 | .then(function (expandedBody) {
267 | response.body = expandedBody;
268 |
269 | return response;
270 | })
271 | } else {
272 | response.body = null;
273 |
274 | return response;
275 | }
276 | });
277 | };
278 |
279 | /**
280 | * Calls an operations with the JSON-LD content and returns the response body converted to JSON-LD
281 | *
282 | * @param content
283 | * @param options
284 | * @returns {Promise}
285 | */
286 | hydra.httpClient.jsonLdInvoke = function (content, options) {
287 | var self = this;
288 |
289 | return hydra.httpClient.rawJsonLdInvoke.bind(self)(content, options)
290 | .then(function (response) {
291 | return response.body;
292 | });
293 | };
294 |
--------------------------------------------------------------------------------
/dist/hydra-core.min.js:
--------------------------------------------------------------------------------
1 | !function(f){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=f();else if("function"==typeof define&&define.amd)define([],f);else{var g;g="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,g.hydra=f()}}(function(){return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;oc?utftext+=String.fromCharCode(c):c>127&&2048>c?(utftext+=String.fromCharCode(c>>6|192),utftext+=String.fromCharCode(63&c|128)):(utftext+=String.fromCharCode(c>>12|224),utftext+=String.fromCharCode(c>>6&63|128),utftext+=String.fromCharCode(63&c|128))}return utftext},hydra.httpClient.base64Encode=function(input){var chr1,chr2,chr3,enc1,enc2,enc3,enc4,keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",output="",i=0;for(input=hydra.httpClient.utf8Encode(input);i>2,enc2=(3&chr1)<<4|chr2>>4,enc3=(15&chr2)<<2|chr3>>6,enc4=63&chr3,isNaN(chr2)?enc3=enc4=64:isNaN(chr3)&&(enc4=64),output=output+keyStr.charAt(enc1)+keyStr.charAt(enc2)+keyStr.charAt(enc3)+keyStr.charAt(enc4);return output},hydra.httpClient.requestAsync=function(method,url,headers,content,callback,options){options=options||{};var xhr=new XMLHttpRequest;xhr.onreadystatechange=function(){if(xhr.readyState===xhr.DONE){for(var headerLines=xhr.getAllResponseHeaders().split("\r\n"),resHeaders={},i=0;i=400?reject(new Error("status code "+status+": "+resBody)):resolve(response)},options)})},hydra.httpClient.apiLink=function(headers,base){if(!("link"in headers))return Promise.resolve(void 0);var rels=jsonld.parseLinkHeader(headers.link);return hydra.ns.apiDocumentation in rels?utils.expandIri(rels[hydra.ns.apiDocumentation].target,base):Promise.resolve(void 0)},hydra.httpClient.contentLocation=function(headers,base){return"content-location"in headers?utils.expandIri(headers["content-location"],base):Promise.resolve(void 0)},hydra.httpClient.rawInvoke=function(headers,content,options){var self=this,url=self.link||self.document.iri;return hydra.httpClient.request(self.method,url,headers,content,options)},hydra.httpClient.rawJsonLdInvoke=function(content,options){var self=this,headers={Accept:"application/ld+json"};return("PATCH"===self.method||"POST"===self.method||"PUT"===self.method)&&(headers["Content-Type"]="application/ld+json"),hydra.httpClient.rawInvoke.bind(self)(headers,JSON.stringify(content),options).then(function(response){return response.body&&""!==response.body.trim()?jsonldp.expand(JSON.parse(response.body),{base:response.request.url}).then(function(expandedBody){return response.body=expandedBody,response}):(response.body=null,response)})},hydra.httpClient.jsonLdInvoke=function(content,options){var self=this;return hydra.httpClient.rawJsonLdInvoke.bind(self)(content,options).then(function(response){return response.body})}},{"./core":2,"./utils":5,request:void 0}],4:[function(require){var hydra=require("./core"),utils=require("./utils"),_=utils.require("lodash"),jsonldp=utils.require("jsonld").promises();hydra.model={},hydra.model.createHttpJsonLdInvoke=function(operation){return function(input,options){options=options||{};var context={};return"@context"in this&&(context=this["@context"]),context=options.context||context,input&&input.toJSON&&(input=input.toJSON()),hydra.httpClient.rawJsonLdInvoke.call(operation,input,options).then(function(response){return response.body?hydra.documentFromResponse(response).then(function(document){return jsonldp.compact(response.body,context).then(function(output){return hydra.model.create(document.classes,output)})}):Promise.resolve(null)})}},hydra.model.toJSON=function(){var copyProperties=function(object,root){if(!object)return null;var copy=_.keys(object).reduce(function(json,key){var value=object[key];return _.isFunction(value)?json:_.isObject(value)&&"@omit"in value&&value["@omit"]?json:(json[key]=_.isObject(value)?copyProperties(value,root):value,json)},{});return _.isArray(object)&&(copy=_.values(object)),copy};return copyProperties(this)},hydra.model.hide=function(property){return property["@omit"]=!0,property},hydra.model.create=function(classes,properties,options){var processOperations=function(root,operations){return operations.forEach(function(operation){var key="@"+operation.method.toLowerCase();key in root||(root[key]=options.createInvoke(operation).bind(model))}),Promise.resolve()},processProperties=function(root,properties){return Promise.all(properties.map(function(property){return utils.compactIri(property.iri,model["@context"]).then(function(key){return key in root||(root[key]={}),processOperations(root[key],property.operations)})}))},processClass=function(apiClass){return model["@type"].push(apiClass.iri),processOperations(model,apiClass.operations).then(function(){return processProperties(model,apiClass.properties)})};classes=utils.toArray(classes),options=options||{},options.createInvoke=options.createInvoke||hydra.defaults.model.createInvoke;var model=_.clone(properties);return _.defaults(model,{"@context":{},toJSON:hydra.model.toJSON}),model["@type"]=[],model.api=classes[0].api||classes[0]["abstract"].api,model.api["@omit"]=!0,classes[0].document&&(model.document=classes[0].document,model.document["@omit"]=!0),Promise.all(classes.map(function(apiClass){return processClass(apiClass)})).then(function(){return model})},hydra.model.load=function(url,properties,options){return hydra.loadDocument(url).then(function(document){return hydra.model.create(document.classes,properties,options)})}},{"./core":2,"./utils":5}],5:[function(require,module){var utils={};utils.require=function(module){var globalModule=module;return"lodash"===globalModule&&(globalModule="_"),"undefined"!=typeof window&&globalModule in window?window[globalModule]:require(module)};var _=utils.require("lodash"),jsonldp=utils.require("jsonld").promises();utils.collection=function(iri,members){return{"@id":iri,"@type":"http://www.w3.org/ns/hydra/core#Collection","http://www.w3.org/ns/hydra/core#member":_.values(members).map(function(member){return{"@id":member["@id"],"@type":member["@type"]}})}},utils.compactIri=function(iri,context){var dummy={};return dummy[iri]="",jsonldp.compact(dummy,context).then(function(compactDummy){return _.keys(compactDummy).pop()})},utils.expandIri=function(iri,base){if(!base)return Promise.resolve(iri);var dummy={"@context":{"@base":base,"@vocab":"http://schema.org/"},name:{"@id":iri}};return jsonldp.expand(dummy).then(function(expanded){return expanded[0]["http://schema.org/name"][0]["@id"]})},utils.iri=function(obj){return obj=utils.unwrap(obj),obj?_.isString(obj)?obj:"@id"in obj?obj["@id"]:void 0:void 0},utils.isCollection=function(collection){return _.isObject(collection)?!1:collection.member||ns.member in collection?!0:!1},utils.toArray=function(obj){return obj?(utils.isCollection(obj)&&(obj=obj.member),_.isArray(obj)?obj:[obj]):[]},utils.unwrap=function(obj){if(!obj)return void 0;if(_.isString(obj))return obj;if("@graph"in obj&&(obj=obj["@graph"]),_.isArray(obj)){if(0===obj.length)return void 0;obj=obj[0]}return obj},module.exports=utils},{}],6:[function(require){var hydra=require("./core"),utils=require("./utils"),jsonldp=utils.require("jsonld").promises();hydra.simpleValidateClass=function(object){var self=this;return object?jsonldp.expand(object).then(function(expanded){if(expanded.length>1)return Promise.reject(new Error("object contains multiple subjects"));if(expanded=expanded.shift(),!("@type"in expanded))return Promise.reject(new Error("@type missing"));if(utils.toArray(expanded["@type"]).indexOf(self.iri)<0)return Promise.reject(new Error("expected class <"+self.iri+">"));var error=self.properties.map(function(property){return property.readonly&&property.iri in object?new Error("readonly property <"+property.iri+'> filled with value "'+object[property.iri]+'"'):!1}).filter(function(error){return!!error}).shift();return error?Promise.reject(error):Promise.resolve()}):Promise.resolve()}},{"./core":2,"./utils":5}]},{},[1])(1)});
2 | //# sourceMappingURL=hydra-core.min.js.map
--------------------------------------------------------------------------------
/test/support/api.json:
--------------------------------------------------------------------------------
1 | {
2 | "@context": {"@vocab": "http://www.w3.org/ns/hydra/core#"},
3 | "@id": "/hydra/api-demo/vocab",
4 | "@type": "ApiDocumentation",
5 | "supportedClass": [
6 | {
7 | "@id": "http://www.w3.org/ns/hydra/core#Resource",
8 | "@type": "Class",
9 | "supportedOperation": [],
10 | "supportedProperty": [],
11 | "title": "Resource"
12 | },
13 | {
14 | "@id": "http://www.w3.org/ns/hydra/core#Collection",
15 | "@type": "Class",
16 | "supportedProperty": {
17 | "description": "The members of this collection.",
18 | "property": {"@id": "http://www.w3.org/ns/hydra/core#member"},
19 | "readonly": false,
20 | "title": "members",
21 | "writeonly": false
22 | },
23 | "title": "Collection"
24 | },
25 | {
26 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User",
27 | "@type": "Class",
28 | "http://www.w3.org/2000/01/rdf-schema#comment": "A User represents a person registered in the system.",
29 | "http://www.w3.org/2000/01/rdf-schema#label": "User",
30 | "supportedOperation": [
31 | {
32 | "@type": "Operation",
33 | "http://www.w3.org/2000/01/rdf-schema#label": "Replaces an existing User entity",
34 | "expects": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
35 | "method": "PUT",
36 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
37 | "statusCodes": {
38 | "http://www.w3.org/2000/01/rdf-schema#comment": "If the User entity wasn't found.",
39 | "statusCode": 404
40 | }
41 | },
42 | {
43 | "@type": "Operation",
44 | "http://www.w3.org/2000/01/rdf-schema#label": "Deletes a User entity",
45 | "method": "DELETE",
46 | "returns": {"@id": "http://www.w3.org/2002/07/owl#Nothing"},
47 | "statusCodes": []
48 | },
49 | {
50 | "@type": "Operation",
51 | "http://www.w3.org/2000/01/rdf-schema#label": "Retrieves a User entity",
52 | "method": "GET",
53 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
54 | "statusCodes": []
55 | }
56 | ],
57 | "supportedProperty": [
58 | {
59 | "description": "The user's full name",
60 | "property": {
61 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User/name",
62 | "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property",
63 | "http://www.w3.org/2000/01/rdf-schema#comment": "The user's full name",
64 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
65 | "http://www.w3.org/2000/01/rdf-schema#label": "name",
66 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/2001/XMLSchema#string"},
67 | "supportedOperation": []
68 | },
69 | "readonly": false,
70 | "title": "name",
71 | "writeonly": false
72 | },
73 | {
74 | "description": "The user's email address",
75 | "property": {
76 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User/email",
77 | "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property",
78 | "http://www.w3.org/2000/01/rdf-schema#comment": "The user's email address",
79 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
80 | "http://www.w3.org/2000/01/rdf-schema#label": "email",
81 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/2001/XMLSchema#string"},
82 | "supportedOperation": []
83 | },
84 | "readonly": false,
85 | "title": "email",
86 | "writeonly": false
87 | },
88 | {
89 | "description": "The user's password",
90 | "property": {
91 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User/password",
92 | "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property",
93 | "http://www.w3.org/2000/01/rdf-schema#comment": "The user's password",
94 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
95 | "http://www.w3.org/2000/01/rdf-schema#label": "password",
96 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/2001/XMLSchema#string"},
97 | "supportedOperation": []
98 | },
99 | "readonly": false,
100 | "title": "password",
101 | "writeonly": true
102 | },
103 | {
104 | "description": "The issues raised by this user",
105 | "property": {
106 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User/raisedIssues",
107 | "@type": "Link",
108 | "http://www.w3.org/2000/01/rdf-schema#comment": "The issues raised by this user",
109 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
110 | "http://www.w3.org/2000/01/rdf-schema#label": "raised_issues",
111 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/ns/hydra/core#Collection"},
112 | "supportedOperation": {
113 | "@type": "Operation",
114 | "http://www.w3.org/2000/01/rdf-schema#label": "Retrieves the issues raised by a User entity",
115 | "method": "GET",
116 | "returns": {"@id": "http://www.w3.org/ns/hydra/core#Collection"},
117 | "statusCodes": {
118 | "http://www.w3.org/2000/01/rdf-schema#comment": "If the User entity wasn't found.",
119 | "statusCode": 404
120 | }
121 | }
122 | },
123 | "readonly": true,
124 | "title": "raised_issues",
125 | "writeonly": false
126 | }
127 | ]
128 | },
129 | {
130 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue",
131 | "@type": "Class",
132 | "http://www.w3.org/2000/01/rdf-schema#comment": "An Issue tracked by the system.",
133 | "http://www.w3.org/2000/01/rdf-schema#label": "Issue",
134 | "supportedOperation": [
135 | {
136 | "@type": "Operation",
137 | "http://www.w3.org/2000/01/rdf-schema#label": "Replaces an existing Issue entity",
138 | "expects": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
139 | "method": "PUT",
140 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
141 | "statusCodes": {
142 | "http://www.w3.org/2000/01/rdf-schema#comment": "If the Issue entity wasn't found.",
143 | "statusCode": 404
144 | }
145 | },
146 | {
147 | "@type": "Operation",
148 | "http://www.w3.org/2000/01/rdf-schema#label": "Deletes a Issue entity",
149 | "method": "DELETE",
150 | "returns": {"@id": "http://www.w3.org/2002/07/owl#Nothing"},
151 | "statusCodes": []
152 | },
153 | {
154 | "@type": "Operation",
155 | "http://www.w3.org/2000/01/rdf-schema#label": "Retrieves a Issue entity",
156 | "method": "GET",
157 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
158 | "statusCodes": []
159 | }
160 | ],
161 | "supportedProperty": [
162 | {
163 | "description": "The issue's title",
164 | "property": {
165 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue/title",
166 | "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property",
167 | "http://www.w3.org/2000/01/rdf-schema#comment": "The issue's title",
168 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
169 | "http://www.w3.org/2000/01/rdf-schema#label": "title",
170 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/2001/XMLSchema#string"},
171 | "supportedOperation": []
172 | },
173 | "readonly": false,
174 | "title": "title",
175 | "writeonly": false
176 | },
177 | {
178 | "description": "A description of the issue",
179 | "property": {
180 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue/description",
181 | "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property",
182 | "http://www.w3.org/2000/01/rdf-schema#comment": "A description of the issue",
183 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
184 | "http://www.w3.org/2000/01/rdf-schema#label": "description",
185 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/2001/XMLSchema#string"},
186 | "supportedOperation": []
187 | },
188 | "readonly": false,
189 | "title": "description",
190 | "writeonly": false
191 | },
192 | {
193 | "description": "Is the issue open?\nUse for 1 yes, 0 for no when modifying this value.",
194 | "property": {
195 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#isOpen",
196 | "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property",
197 | "http://www.w3.org/2000/01/rdf-schema#comment": "Is the issue open?\nUse for 1 yes, 0 for no when modifying this value.",
198 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
199 | "http://www.w3.org/2000/01/rdf-schema#label": "is_open",
200 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/2001/XMLSchema#boolean"},
201 | "supportedOperation": []
202 | },
203 | "readonly": false,
204 | "title": "is_open",
205 | "writeonly": false
206 | },
207 | {
208 | "description": "The user who raised the issue",
209 | "property": {
210 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue/raisedBy",
211 | "@type": "Link",
212 | "http://www.w3.org/2000/01/rdf-schema#comment": "The user who raised the issue",
213 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
214 | "http://www.w3.org/2000/01/rdf-schema#label": "raised_by",
215 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
216 | "supportedOperation": {
217 | "@type": "Operation",
218 | "http://www.w3.org/2000/01/rdf-schema#label": "Retrieves a User entity",
219 | "method": "GET",
220 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
221 | "statusCodes": []
222 | }
223 | },
224 | "readonly": true,
225 | "title": "raised_by",
226 | "writeonly": false
227 | },
228 | {
229 | "description": "The date and time this issue was created",
230 | "property": {
231 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue/createdAt",
232 | "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property",
233 | "http://www.w3.org/2000/01/rdf-schema#comment": "The date and time this issue was created",
234 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
235 | "http://www.w3.org/2000/01/rdf-schema#label": "created_at",
236 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/2001/XMLSchema#dateTime"},
237 | "supportedOperation": []
238 | },
239 | "readonly": true,
240 | "title": "created_at",
241 | "writeonly": false
242 | },
243 | {
244 | "description": "The comments associated with this issue",
245 | "property": {
246 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue/comments",
247 | "@type": "Link",
248 | "http://www.w3.org/2000/01/rdf-schema#comment": "The comments associated with this issue",
249 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
250 | "http://www.w3.org/2000/01/rdf-schema#label": "comments",
251 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/ns/hydra/core#Collection"},
252 | "supportedOperation": [
253 | {
254 | "@type": "Operation",
255 | "http://www.w3.org/2000/01/rdf-schema#comment": "To create a new Comment you have to be authenticated.",
256 | "http://www.w3.org/2000/01/rdf-schema#label": "Creates a new Comment for a specific issue",
257 | "expects": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment"},
258 | "method": "POST",
259 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment"},
260 | "statusCodes": {
261 | "http://www.w3.org/2000/01/rdf-schema#comment": "If the Issue wasn't found.",
262 | "statusCode": 404
263 | }
264 | },
265 | {
266 | "@type": "Operation",
267 | "http://www.w3.org/2000/01/rdf-schema#label": "Retrieves all Comment entities for a specific issue",
268 | "method": "GET",
269 | "returns": {"@id": "http://www.w3.org/ns/hydra/core#Collection"},
270 | "statusCodes": []
271 | }
272 | ]
273 | },
274 | "readonly": true,
275 | "title": "comments",
276 | "writeonly": false
277 | }
278 | ]
279 | },
280 | {
281 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment",
282 | "@type": "Class",
283 | "http://www.w3.org/2000/01/rdf-schema#comment": "Comment",
284 | "http://www.w3.org/2000/01/rdf-schema#label": "Comment",
285 | "supportedOperation": [
286 | {
287 | "@type": "Operation",
288 | "http://www.w3.org/2000/01/rdf-schema#label": "Replaces an existing Comment entity",
289 | "expects": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment"},
290 | "method": "PUT",
291 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment"},
292 | "statusCodes": {
293 | "http://www.w3.org/2000/01/rdf-schema#comment": "If the Comment entity wasn't found.",
294 | "statusCode": 404
295 | }
296 | },
297 | {
298 | "@type": "Operation",
299 | "http://www.w3.org/2000/01/rdf-schema#label": "Deletes a Comment entity",
300 | "method": "DELETE",
301 | "returns": {"@id": "http://www.w3.org/2002/07/owl#Nothing"},
302 | "statusCodes": []
303 | },
304 | {
305 | "@type": "Operation",
306 | "http://www.w3.org/2000/01/rdf-schema#label": "Retrieves a Comment entity",
307 | "method": "GET",
308 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment"},
309 | "statusCodes": []
310 | }
311 | ],
312 | "supportedProperty": [
313 | {
314 | "description": "The comment",
315 | "property": {
316 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment/text",
317 | "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property",
318 | "http://www.w3.org/2000/01/rdf-schema#comment": "The comment",
319 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment"},
320 | "http://www.w3.org/2000/01/rdf-schema#label": "text",
321 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/2001/XMLSchema#string"},
322 | "supportedOperation": []
323 | },
324 | "readonly": false,
325 | "title": "text",
326 | "writeonly": false
327 | },
328 | {
329 | "description": "The issue this comment belongs to",
330 | "property": {
331 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment/issue",
332 | "@type": "Link",
333 | "http://www.w3.org/2000/01/rdf-schema#comment": "The issue this comment belongs to",
334 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment"},
335 | "http://www.w3.org/2000/01/rdf-schema#label": "issue",
336 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
337 | "supportedOperation": [
338 | {
339 | "@type": "Operation",
340 | "http://www.w3.org/2000/01/rdf-schema#label": "Retrieves a Issue entity",
341 | "method": "GET",
342 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
343 | "statusCodes": []
344 | },
345 | {
346 | "@type": "Operation",
347 | "http://www.w3.org/2000/01/rdf-schema#label": "Replaces an existing Issue entity",
348 | "expects": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
349 | "method": "PUT",
350 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
351 | "statusCodes": {
352 | "http://www.w3.org/2000/01/rdf-schema#comment": "If the Issue entity wasn't found.",
353 | "statusCode": 404
354 | }
355 | }
356 | ]
357 | },
358 | "readonly": true,
359 | "title": "issue",
360 | "writeonly": false
361 | },
362 | {
363 | "description": "The user who wrote this comment",
364 | "property": {
365 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment/user",
366 | "@type": "Link",
367 | "http://www.w3.org/2000/01/rdf-schema#comment": "The user who wrote this comment",
368 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment"},
369 | "http://www.w3.org/2000/01/rdf-schema#label": "user",
370 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
371 | "supportedOperation": {
372 | "@type": "Operation",
373 | "http://www.w3.org/2000/01/rdf-schema#label": "Retrieves a User entity",
374 | "method": "GET",
375 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
376 | "statusCodes": []
377 | }
378 | },
379 | "readonly": true,
380 | "title": "user",
381 | "writeonly": false
382 | },
383 | {
384 | "description": "The date and time this comment was created",
385 | "property": {
386 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment/createdAt",
387 | "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property",
388 | "http://www.w3.org/2000/01/rdf-schema#comment": "The date and time this comment was created",
389 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Comment"},
390 | "http://www.w3.org/2000/01/rdf-schema#label": "created_at",
391 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/2001/XMLSchema#dateTime"},
392 | "supportedOperation": []
393 | },
394 | "readonly": true,
395 | "title": "created_at",
396 | "writeonly": false
397 | }
398 | ]
399 | },
400 | {
401 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint",
402 | "@type": "Class",
403 | "http://www.w3.org/2000/01/rdf-schema#comment": "The main entry point or homepage of the API.",
404 | "http://www.w3.org/2000/01/rdf-schema#label": "EntryPoint",
405 | "supportedOperation": {
406 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/GET",
407 | "@type": "Operation",
408 | "http://www.w3.org/2000/01/rdf-schema#label": "The APIs main entry point.",
409 | "method": "GET",
410 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint"},
411 | "statusCodes": []
412 | },
413 | "supportedProperty": [
414 | {
415 | "description": "The collection of all issues",
416 | "property": {
417 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/issues",
418 | "@type": "Link",
419 | "http://www.w3.org/2000/01/rdf-schema#comment": "The collection of all issues",
420 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint"},
421 | "http://www.w3.org/2000/01/rdf-schema#label": "issues",
422 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/ns/hydra/core#Collection"},
423 | "supportedOperation": [
424 | {
425 | "@type": "Operation",
426 | "http://www.w3.org/2000/01/rdf-schema#label": "Creates a new Issue entity",
427 | "expects": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
428 | "method": "POST",
429 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#Issue"},
430 | "statusCodes": {
431 | "http://www.w3.org/2000/01/rdf-schema#comment": "If the Issue entity was created successfully.",
432 | "statusCode": 201
433 | }
434 | },
435 | {
436 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/issues/GET",
437 | "@type": "Operation",
438 | "http://www.w3.org/2000/01/rdf-schema#label": "Retrieves all Issue entities",
439 | "method": "GET",
440 | "returns": {"@id": "http://www.w3.org/ns/hydra/core#Collection"},
441 | "statusCodes": []
442 | }
443 | ]
444 | },
445 | "readonly": true,
446 | "title": "issues",
447 | "writeonly": false
448 | },
449 | {
450 | "description": "IRI to register a new user",
451 | "property": {
452 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/registerUser",
453 | "@type": "Link",
454 | "http://www.w3.org/2000/01/rdf-schema#comment": "IRI to register a new user",
455 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint"},
456 | "http://www.w3.org/2000/01/rdf-schema#label": "register_user",
457 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/ns/hydra/core#Resource"},
458 | "supportedOperation": {
459 | "@type": "Operation",
460 | "http://www.w3.org/2000/01/rdf-schema#label": "Creates a new User entity",
461 | "expects": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
462 | "method": "POST",
463 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
464 | "statusCodes": {
465 | "http://www.w3.org/2000/01/rdf-schema#comment": "If the User entity was created successfully.",
466 | "statusCode": 201
467 | }
468 | }
469 | },
470 | "readonly": true,
471 | "title": "register_user",
472 | "writeonly": false
473 | },
474 | {
475 | "description": "If logged in, a link to the user account",
476 | "property": {
477 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/myAccount",
478 | "@type": "Link",
479 | "http://www.w3.org/2000/01/rdf-schema#comment": "If logged in, a link to the user account",
480 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint"},
481 | "http://www.w3.org/2000/01/rdf-schema#label": "my_account",
482 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
483 | "supportedOperation": {
484 | "@type": "Operation",
485 | "http://www.w3.org/2000/01/rdf-schema#label": "Retrieves a User entity",
486 | "method": "GET",
487 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
488 | "statusCodes": []
489 | }
490 | },
491 | "readonly": true,
492 | "title": "my_account",
493 | "writeonly": false
494 | },
495 | {
496 | "description": "The collection of all users (for debugging purposes)",
497 | "property": {
498 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/users",
499 | "@type": "Link",
500 | "http://www.w3.org/2000/01/rdf-schema#comment": "The collection of all users (for debugging purposes)",
501 | "http://www.w3.org/2000/01/rdf-schema#domain": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint"},
502 | "http://www.w3.org/2000/01/rdf-schema#label": "users",
503 | "http://www.w3.org/2000/01/rdf-schema#range": {"@id": "http://www.w3.org/ns/hydra/core#Collection"},
504 | "supportedOperation": [
505 | {
506 | "@type": "Operation",
507 | "http://www.w3.org/2000/01/rdf-schema#label": "Creates a new User entity",
508 | "expects": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
509 | "method": "POST",
510 | "returns": {"@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#User"},
511 | "statusCodes": {
512 | "http://www.w3.org/2000/01/rdf-schema#comment": "If the User entity was created successfully.",
513 | "statusCode": 201
514 | }
515 | },
516 | {
517 | "@id": "http://www.markus-lanthaler.com/hydra/api-demo/vocab#EntryPoint/users/GET",
518 | "@type": "Operation",
519 | "http://www.w3.org/2000/01/rdf-schema#label": "Retrieves all User entities",
520 | "method": "GET",
521 | "returns": {"@id": "http://www.w3.org/ns/hydra/core#Collection"},
522 | "statusCodes": []
523 | }
524 | ]
525 | },
526 | "readonly": true,
527 | "title": "users",
528 | "writeonly": false
529 | }
530 | ]
531 | }
532 | ]
533 | }
--------------------------------------------------------------------------------
/dist/hydra-core.js.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "sources": [
4 | "node_modules/browserify/node_modules/browser-pack/_prelude.js",
5 | "hydra-core.js",
6 | "lib/core.js",
7 | "lib/http-client.js",
8 | "lib/model.js",
9 | "lib/utils.js",
10 | "lib/validation.js"
11 | ],
12 | "names": [],
13 | "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA",
14 | "file": "generated.js",
15 | "sourceRoot": "",
16 | "sourcesContent": [
17 | "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o 127) && (c < 2048)) {\n utftext += String.fromCharCode((c >> 6) | 192);\n utftext += String.fromCharCode((c & 63) | 128);\n } else {\n utftext += String.fromCharCode((c >> 12) | 224);\n utftext += String.fromCharCode(((c >> 6) & 63) | 128);\n utftext += String.fromCharCode((c & 63) | 128);\n }\n }\n\n return utftext;\n };\n\n /**\n * Converts a string to a base-64 encoded string\n * @param input The string to encode\n * @returns {string} The base-64 string\n */\n hydra.httpClient.base64Encode = function (input) {\n var keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n var output = '';\n var chr1, chr2, chr3, enc1, enc2, enc3, enc4;\n var i = 0;\n\n input = hydra.httpClient.utf8Encode(input);\n\n while (i < input.length) {\n chr1 = input.charCodeAt(i++);\n chr2 = input.charCodeAt(i++);\n chr3 = input.charCodeAt(i++);\n\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);\n }\n\n return output;\n };\n\n /**\n * Request implementation using XMLHttpRequest interface\n *\n * @param method HTTP method\n * @param url URL\n * @param headers Header key/value pairs\n * @param content Content\n * @param callback Callback function using with interface: statusCode, headers, content, error\n */\n hydra.httpClient.requestAsync = function (method, url, headers, content, callback, options) {\n options = options || {};\n\n var xhr = new XMLHttpRequest();\n\n xhr.onreadystatechange = function () {\n if (xhr.readyState === xhr.DONE) {\n var\n headerLines = xhr.getAllResponseHeaders().split('\\r\\n'),\n resHeaders = {};\n\n for (var i = 0; i < headerLines.length; i++) {\n var headerLine = headerLines[i].split(': ', 2);\n resHeaders[headerLine[0].toLowerCase()] = headerLine[1];\n }\n\n callback(xhr.status, resHeaders, xhr.responseText);\n }\n };\n\n xhr.open(method, url, true);\n\n for (var header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n\n if (options.user && options.password) {\n xhr.setRequestHeader(\"Authorization\", \"Basic \" + hydra.httpClient.base64Encode(options.user + \":\" + options.password));\n }\n\n xhr.send(content);\n };\n} else {\n /**\n * Request implementation using the npm request module\n *\n * @param method HTTP method\n * @param url URL\n * @param headers Header key/value pairs\n * @param content Content\n * @param callback Callback function using with interface: statusCode, headers, content, error\n * @param options Additional options like user or password\n */\n hydra.httpClient.requestAsync = function (method, url, headers, content, callback, options) {\n var request = require('request');\n\n options = options || {};\n\n var req = {\n method: method,\n url: url,\n headers: headers,\n body: content\n };\n\n if (options.user && options.password) {\n req.auth = {\n user: options.user,\n password: options.password\n };\n }\n\n request(req, function (error, res, body) {\n if (error) {\n callback(null, null, null, error);\n } else {\n callback(res.statusCode, res.headers, body);\n }\n });\n };\n}\n\n/**\n * Promise request implementation\n *\n * @param method HTTP method\n * @param url URL\n * @param headers Header key/value pairs\n * @param content Content\n * @param options Additional options like user or password\n * @returns {Promise}\n */\nhydra.httpClient.request = function (method, url, headers, content, options) {\n return new Promise(function (resolve, reject) {\n hydra.httpClient.requestAsync(method, url, headers, content, function (status, resHeaders, resBody, error) {\n var response = {\n status: status,\n headers: resHeaders,\n body: resBody,\n request: {\n url: url,\n method: method,\n headers: headers,\n body: content\n }\n };\n\n if (error) {\n reject(error);\n } else if (status >= 400) {\n reject(new Error('status code ' + status + ': ' + resBody));\n } else {\n resolve(response);\n }\n }, options);\n });\n};\n\n/**\n * Extracts the Hydra API Documentation value of the Link header field\n *\n * @param headers\n * @param base\n * @returns {Promise}\n */\nhydra.httpClient.apiLink = function (headers, base) {\n if (!('link' in headers)) {\n return Promise.resolve(undefined);\n }\n\n var rels = jsonld.parseLinkHeader(headers.link);\n\n if (!(hydra.ns.apiDocumentation in rels)) {\n return Promise.resolve(undefined);\n }\n\n return utils.expandIri(rels[hydra.ns.apiDocumentation].target, base);\n};\n\n/**\n * Extracts the value of the Content-Location header field\n *\n * @param headers\n * @param base\n * @returns {*}\n */\nhydra.httpClient.contentLocation = function (headers, base) {\n if (!('content-location' in headers)) {\n return Promise.resolve(undefined);\n }\n\n return utils.expandIri(headers['content-location'], base);\n};\n\n/**\n * Calls an operations with the given headers and content\n *\n * @param headers\n * @param content\n * @param options\n * @returns {Promise}\n */\nhydra.httpClient.rawInvoke = function (headers, content, options) {\n var self = this;\n\n var url = self.link || self.document.iri;\n\n return hydra.httpClient.request(self.method, url, headers, content, options);\n};\n\n/**\n * Calls an operations with the JSON-LD content and converts the response body to JSON-LD\n *\n * @param content\n * @param options\n * @returns {Promise}\n */\nhydra.httpClient.rawJsonLdInvoke = function (content, options) {\n var self = this;\n\n var headers = {\n 'Accept': 'application/ld+json'\n };\n\n if (self.method === 'PATCH' || self.method === 'POST' || self.method === 'PUT') {\n headers['Content-Type'] = 'application/ld+json';\n }\n\n return hydra.httpClient.rawInvoke.bind(self)(headers, JSON.stringify(content), options)\n .then(function (response) {\n if (response.body && response.body.trim() !== '') {\n return jsonldp.expand(JSON.parse(response.body), {base: response.request.url})\n .then(function (expandedBody) {\n response.body = expandedBody;\n\n return response;\n })\n } else {\n response.body = null;\n\n return response;\n }\n });\n};\n\n/**\n * Calls an operations with the JSON-LD content and returns the response body converted to JSON-LD\n *\n * @param content\n * @param options\n * @returns {Promise}\n */\nhydra.httpClient.jsonLdInvoke = function (content, options) {\n var self = this;\n\n return hydra.httpClient.rawJsonLdInvoke.bind(self)(content, options)\n .then(function (response) {\n return response.body;\n });\n};\n",
21 | "var\n hydra = require('./core'),\n utils = require('./utils'),\n _ = utils.require('lodash'),\n jsonldp = utils.require('jsonld').promises();\n\n\nhydra.model = {};\n\n\n/**\n * Creates an invoke function for model objects that compacts the response using the given context\n *\n * @param operation\n * @returns {Function}\n */\nhydra.model.createHttpJsonLdInvoke = function (operation) {\n return function (input, options) {\n options = options || {};\n\n var context = {};\n\n if ('@context' in this) {\n context = this['@context'];\n }\n\n context = options.context || context;\n\n if (input && input.toJSON) {\n input = input.toJSON();\n }\n\n return hydra.httpClient.rawJsonLdInvoke.call(operation, input, options)\n .then(function (response) {\n if (!response.body) {\n return Promise.resolve(null);\n }\n\n return hydra.documentFromResponse(response)\n .then(function (document) {\n return jsonldp.compact(response.body, context)\n .then(function (output) {\n return hydra.model.create(document.classes, output);\n });\n });\n });\n };\n};\n\n/**\n * Converts a model object to serializable object without functions and property flagged with @omit\n */\nhydra.model.toJSON = function () {\n var copyProperties = function (object, root) {\n if (!object) {\n return null;\n }\n\n var copy = _.keys(object).reduce(function (json, key) {\n var value = object[key];\n\n // don't add function properties\n if (_.isFunction(value)) {\n return json;\n }\n\n // don't add properties with @omit flag\n if (_.isObject(value) && '@omit' in value && value['@omit']) {\n return json;\n }\n\n if (_.isObject(value)) {\n // copy sub properties\n json[key] = copyProperties(value, root);\n } else {\n // copy string values\n json[key] = value;\n }\n\n return json;\n }, {});\n\n // convert to Array if original object was an Array\n if (_.isArray(object)) {\n copy = _.values(object);\n }\n\n return copy;\n };\n\n return copyProperties(this);\n};\n\n/**\n * Adds a @omit property to an object to hide it from serialization\n *\n * @param property\n * @returns {Object}\n */\nhydra.model.hide = function (property) {\n property['@omit'] = true;\n\n return property;\n};\n\n/**\n * Creates a model object based on one or more classes\n *\n * @param classes The class or classes the model will be bases on\n * @param properties Properties to merge into the model object\n * @param options Additional options to control the model creation\n * @returns {*}\n */\nhydra.model.create = function (classes, properties, options) {\n var processOperations = function (root, operations) {\n operations.forEach(function (operation) {\n var key = '@' + operation.method.toLowerCase();\n\n if (!(key in root)) {\n root[key] = options.createInvoke(operation).bind(model);\n }\n });\n\n return Promise.resolve();\n };\n\n var processProperties = function (root, properties) {\n return Promise.all(properties.map(function (property) {\n return utils.compactIri(property.iri, model['@context'])\n .then(function (key) {\n if (!(key in root)) {\n root[key] = {};\n }\n\n return processOperations(root[key], property.operations);\n });\n }));\n };\n\n var processClass = function (apiClass) {\n model['@type'].push(apiClass.iri);\n\n return processOperations(model, apiClass.operations)\n .then(function () {\n return processProperties(model, apiClass.properties);\n });\n };\n\n classes = utils.toArray(classes);\n\n options = options || {};\n options.createInvoke = options.createInvoke || hydra.defaults.model.createInvoke;\n\n var model = _.clone(properties);\n\n _.defaults(model, {\n '@context': {},\n toJSON: hydra.model.toJSON\n });\n\n model['@type'] = [];\n model.api = classes[0].api || classes[0].abstract.api;\n model.api['@omit'] = true;\n\n if (classes[0].document) {\n model.document = classes[0].document;\n model.document['@omit'] = true;\n }\n\n return Promise.all(classes.map(function (apiClass) {\n return processClass(apiClass);\n })).then(function () {\n return model;\n });\n};\n\n/**\n * Creates a model object based on a GET request to the given URL\n *\n * @param url URL\n * @param properties Properties that will be merged into the model object\n * @param options Options for the request\n * @returns {Promise}\n */\nhydra.model.load = function (url, properties, options) {\n return hydra.loadDocument(url)\n .then(function (document) {\n return hydra.model.create(document.classes, properties, options);\n });\n};\n",
22 | "var utils = {};\n\n\nutils.require = function (module) {\n var globalModule = module;\n\n if (globalModule === 'lodash') {\n globalModule = '_';\n }\n\n if (typeof window !== 'undefined' && globalModule in window) {\n return window[globalModule];\n }\n\n return require(module);\n};\n\n\nvar\n _ = utils.require('lodash'),\n jsonldp = utils.require('jsonld').promises();\n\n\n/**\n * Creates a Hydra Collection from a map or array of members\n *\n * @param iri\n * @param members\n * @returns {Collection}\n */\nutils.collection = function (iri, members) {\n return {\n '@id': iri,\n '@type': 'http://www.w3.org/ns/hydra/core#Collection',\n 'http://www.w3.org/ns/hydra/core#member': _.values(members).map(function (member) {\n return {\n '@id': member['@id'],\n '@type': member['@type']\n };\n })\n };\n};\n\n/**\n * Uses the given context to create a short form of the IRI\n *\n * @param iri\n * @param context\n * @returns {Promise}\n */\nutils.compactIri = function (iri, context) {\n var dummy = {};\n\n dummy[iri] = '';\n\n return jsonldp.compact(dummy, context)\n .then(function (compactDummy) {\n return _.keys(compactDummy).pop();\n });\n};\n\n/**\n * Creates a long version of the IRI using the given base\n *\n * @param iri\n * @param base\n * @returns {Promise}\n */\nutils.expandIri = function (iri, base) {\n if (!base) {\n return Promise.resolve(iri);\n }\n\n var dummy = {\n '@context': {\n '@base': base,\n '@vocab': 'http://schema.org/'\n },\n 'name': {\n '@id': iri\n }\n };\n\n return jsonldp.expand(dummy)\n .then(function (expanded) {\n return expanded[0]['http://schema.org/name'][0]['@id'];\n });\n};\n\n/**\n * Extracts the IRI of an JSON-LD object\n *\n * @param obj\n * @returns {*}\n */\nutils.iri = function (obj) {\n obj = utils.unwrap(obj);\n\n if (!obj) {\n return undefined;\n }\n\n if (_.isString(obj)) {\n return obj;\n }\n\n if (!('@id' in obj)) {\n return undefined;\n }\n\n return obj['@id'];\n};\n\n/**\n * Checks if the given object is a Hydra Collection\n *\n * @param collection\n * @returns {boolean}\n */\nutils.isCollection = function (collection) {\n if (_.isObject(collection)) {\n return false;\n }\n\n if (!collection.member && !(ns.member in collection)) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Converts single objects and Hydra Collections to Arrays and forwards existing Arrays\n *\n * @param obj\n * @returns {Array}\n */\nutils.toArray = function (obj) {\n if (!obj) {\n return [];\n }\n\n if (utils.isCollection(obj)) {\n obj = obj.member;\n }\n\n if (!_.isArray(obj)) {\n return [obj];\n }\n\n return obj;\n};\n\n/**\n * Extracts the first subject of an JSON-Ld object\n *\n * @param obj\n * @returns {*}\n */\nutils.unwrap = function (obj) {\n if (!obj) {\n return undefined;\n }\n\n if (_.isString(obj)) {\n return obj;\n }\n\n if ('@graph' in obj) {\n obj = obj['@graph'];\n }\n\n if (_.isArray(obj)) {\n if (obj.length === 0) {\n return undefined;\n } else {\n obj = obj[0];\n }\n }\n\n return obj;\n};\n\n\nmodule.exports = utils;",
23 | "var\n hydra = require('./core'),\n utils = require('./utils'),\n jsonldp = utils.require('jsonld').promises();\n\n\nhydra.simpleValidateClass = function (object, read, write) {\n var self = this;\n\n if (!object) {\n return Promise.resolve();\n }\n\n return jsonldp.expand(object)\n .then(function (expanded) {\n if (expanded.length > 1) {\n return Promise.reject(new Error('object contains multiple subjects'));\n }\n\n expanded = expanded.shift();\n\n if (!('@type' in expanded)) {\n return Promise.reject(new Error('@type missing'));\n }\n\n if (utils.toArray(expanded['@type']).indexOf(self.iri) < 0) {\n return Promise.reject(new Error('expected class <' + self.iri + '>'));\n }\n\n var error = self.properties\n .map(function (property) {\n if (property.readonly && property.iri in object) {\n return new Error('readonly property <' + property.iri + '> filled with value \"' + object[property.iri] + '\"');\n }\n\n return false;\n })\n .filter(function (error) {\n return !!error;\n })\n .shift();\n\n if (error) {\n return Promise.reject(error);\n }\n\n return Promise.resolve();\n });\n};\n\n"
24 | ]
25 | }
--------------------------------------------------------------------------------
/dist/hydra-core.js:
--------------------------------------------------------------------------------
1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.hydra = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 127) && (c < 2048)) {
395 | utftext += String.fromCharCode((c >> 6) | 192);
396 | utftext += String.fromCharCode((c & 63) | 128);
397 | } else {
398 | utftext += String.fromCharCode((c >> 12) | 224);
399 | utftext += String.fromCharCode(((c >> 6) & 63) | 128);
400 | utftext += String.fromCharCode((c & 63) | 128);
401 | }
402 | }
403 |
404 | return utftext;
405 | };
406 |
407 | /**
408 | * Converts a string to a base-64 encoded string
409 | * @param input The string to encode
410 | * @returns {string} The base-64 string
411 | */
412 | hydra.httpClient.base64Encode = function (input) {
413 | var keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
414 | var output = '';
415 | var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
416 | var i = 0;
417 |
418 | input = hydra.httpClient.utf8Encode(input);
419 |
420 | while (i < input.length) {
421 | chr1 = input.charCodeAt(i++);
422 | chr2 = input.charCodeAt(i++);
423 | chr3 = input.charCodeAt(i++);
424 |
425 | enc1 = chr1 >> 2;
426 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
427 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
428 | enc4 = chr3 & 63;
429 |
430 | if (isNaN(chr2)) {
431 | enc3 = enc4 = 64;
432 | } else if (isNaN(chr3)) {
433 | enc4 = 64;
434 | }
435 |
436 | output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
437 | }
438 |
439 | return output;
440 | };
441 |
442 | /**
443 | * Request implementation using XMLHttpRequest interface
444 | *
445 | * @param method HTTP method
446 | * @param url URL
447 | * @param headers Header key/value pairs
448 | * @param content Content
449 | * @param callback Callback function using with interface: statusCode, headers, content, error
450 | */
451 | hydra.httpClient.requestAsync = function (method, url, headers, content, callback, options) {
452 | options = options || {};
453 |
454 | var xhr = new XMLHttpRequest();
455 |
456 | xhr.onreadystatechange = function () {
457 | if (xhr.readyState === xhr.DONE) {
458 | var
459 | headerLines = xhr.getAllResponseHeaders().split('\r\n'),
460 | resHeaders = {};
461 |
462 | for (var i = 0; i < headerLines.length; i++) {
463 | var headerLine = headerLines[i].split(': ', 2);
464 | resHeaders[headerLine[0].toLowerCase()] = headerLine[1];
465 | }
466 |
467 | callback(xhr.status, resHeaders, xhr.responseText);
468 | }
469 | };
470 |
471 | xhr.open(method, url, true);
472 |
473 | for (var header in headers) {
474 | xhr.setRequestHeader(header, headers[header]);
475 | }
476 |
477 | if (options.user && options.password) {
478 | xhr.setRequestHeader("Authorization", "Basic " + hydra.httpClient.base64Encode(options.user + ":" + options.password));
479 | }
480 |
481 | xhr.send(content);
482 | };
483 | } else {
484 | /**
485 | * Request implementation using the npm request module
486 | *
487 | * @param method HTTP method
488 | * @param url URL
489 | * @param headers Header key/value pairs
490 | * @param content Content
491 | * @param callback Callback function using with interface: statusCode, headers, content, error
492 | * @param options Additional options like user or password
493 | */
494 | hydra.httpClient.requestAsync = function (method, url, headers, content, callback, options) {
495 | var request = require('request');
496 |
497 | options = options || {};
498 |
499 | var req = {
500 | method: method,
501 | url: url,
502 | headers: headers,
503 | body: content
504 | };
505 |
506 | if (options.user && options.password) {
507 | req.auth = {
508 | user: options.user,
509 | password: options.password
510 | };
511 | }
512 |
513 | request(req, function (error, res, body) {
514 | if (error) {
515 | callback(null, null, null, error);
516 | } else {
517 | callback(res.statusCode, res.headers, body);
518 | }
519 | });
520 | };
521 | }
522 |
523 | /**
524 | * Promise request implementation
525 | *
526 | * @param method HTTP method
527 | * @param url URL
528 | * @param headers Header key/value pairs
529 | * @param content Content
530 | * @param options Additional options like user or password
531 | * @returns {Promise}
532 | */
533 | hydra.httpClient.request = function (method, url, headers, content, options) {
534 | return new Promise(function (resolve, reject) {
535 | hydra.httpClient.requestAsync(method, url, headers, content, function (status, resHeaders, resBody, error) {
536 | var response = {
537 | status: status,
538 | headers: resHeaders,
539 | body: resBody,
540 | request: {
541 | url: url,
542 | method: method,
543 | headers: headers,
544 | body: content
545 | }
546 | };
547 |
548 | if (error) {
549 | reject(error);
550 | } else if (status >= 400) {
551 | reject(new Error('status code ' + status + ': ' + resBody));
552 | } else {
553 | resolve(response);
554 | }
555 | }, options);
556 | });
557 | };
558 |
559 | /**
560 | * Extracts the Hydra API Documentation value of the Link header field
561 | *
562 | * @param headers
563 | * @param base
564 | * @returns {Promise}
565 | */
566 | hydra.httpClient.apiLink = function (headers, base) {
567 | if (!('link' in headers)) {
568 | return Promise.resolve(undefined);
569 | }
570 |
571 | var rels = jsonld.parseLinkHeader(headers.link);
572 |
573 | if (!(hydra.ns.apiDocumentation in rels)) {
574 | return Promise.resolve(undefined);
575 | }
576 |
577 | return utils.expandIri(rels[hydra.ns.apiDocumentation].target, base);
578 | };
579 |
580 | /**
581 | * Extracts the value of the Content-Location header field
582 | *
583 | * @param headers
584 | * @param base
585 | * @returns {*}
586 | */
587 | hydra.httpClient.contentLocation = function (headers, base) {
588 | if (!('content-location' in headers)) {
589 | return Promise.resolve(undefined);
590 | }
591 |
592 | return utils.expandIri(headers['content-location'], base);
593 | };
594 |
595 | /**
596 | * Calls an operations with the given headers and content
597 | *
598 | * @param headers
599 | * @param content
600 | * @param options
601 | * @returns {Promise}
602 | */
603 | hydra.httpClient.rawInvoke = function (headers, content, options) {
604 | var self = this;
605 |
606 | var url = self.link || self.document.iri;
607 |
608 | return hydra.httpClient.request(self.method, url, headers, content, options);
609 | };
610 |
611 | /**
612 | * Calls an operations with the JSON-LD content and converts the response body to JSON-LD
613 | *
614 | * @param content
615 | * @param options
616 | * @returns {Promise}
617 | */
618 | hydra.httpClient.rawJsonLdInvoke = function (content, options) {
619 | var self = this;
620 |
621 | var headers = {
622 | 'Accept': 'application/ld+json'
623 | };
624 |
625 | if (self.method === 'PATCH' || self.method === 'POST' || self.method === 'PUT') {
626 | headers['Content-Type'] = 'application/ld+json';
627 | }
628 |
629 | return hydra.httpClient.rawInvoke.bind(self)(headers, JSON.stringify(content), options)
630 | .then(function (response) {
631 | if (response.body && response.body.trim() !== '') {
632 | return jsonldp.expand(JSON.parse(response.body), {base: response.request.url})
633 | .then(function (expandedBody) {
634 | response.body = expandedBody;
635 |
636 | return response;
637 | })
638 | } else {
639 | response.body = null;
640 |
641 | return response;
642 | }
643 | });
644 | };
645 |
646 | /**
647 | * Calls an operations with the JSON-LD content and returns the response body converted to JSON-LD
648 | *
649 | * @param content
650 | * @param options
651 | * @returns {Promise}
652 | */
653 | hydra.httpClient.jsonLdInvoke = function (content, options) {
654 | var self = this;
655 |
656 | return hydra.httpClient.rawJsonLdInvoke.bind(self)(content, options)
657 | .then(function (response) {
658 | return response.body;
659 | });
660 | };
661 |
662 | },{"./core":2,"./utils":5,"request":undefined}],4:[function(require,module,exports){
663 | var
664 | hydra = require('./core'),
665 | utils = require('./utils'),
666 | _ = utils.require('lodash'),
667 | jsonldp = utils.require('jsonld').promises();
668 |
669 |
670 | hydra.model = {};
671 |
672 |
673 | /**
674 | * Creates an invoke function for model objects that compacts the response using the given context
675 | *
676 | * @param operation
677 | * @returns {Function}
678 | */
679 | hydra.model.createHttpJsonLdInvoke = function (operation) {
680 | return function (input, options) {
681 | options = options || {};
682 |
683 | var context = {};
684 |
685 | if ('@context' in this) {
686 | context = this['@context'];
687 | }
688 |
689 | context = options.context || context;
690 |
691 | if (input && input.toJSON) {
692 | input = input.toJSON();
693 | }
694 |
695 | return hydra.httpClient.rawJsonLdInvoke.call(operation, input, options)
696 | .then(function (response) {
697 | if (!response.body) {
698 | return Promise.resolve(null);
699 | }
700 |
701 | return hydra.documentFromResponse(response)
702 | .then(function (document) {
703 | return jsonldp.compact(response.body, context)
704 | .then(function (output) {
705 | return hydra.model.create(document.classes, output);
706 | });
707 | });
708 | });
709 | };
710 | };
711 |
712 | /**
713 | * Converts a model object to serializable object without functions and property flagged with @omit
714 | */
715 | hydra.model.toJSON = function () {
716 | var copyProperties = function (object, root) {
717 | if (!object) {
718 | return null;
719 | }
720 |
721 | var copy = _.keys(object).reduce(function (json, key) {
722 | var value = object[key];
723 |
724 | // don't add function properties
725 | if (_.isFunction(value)) {
726 | return json;
727 | }
728 |
729 | // don't add properties with @omit flag
730 | if (_.isObject(value) && '@omit' in value && value['@omit']) {
731 | return json;
732 | }
733 |
734 | if (_.isObject(value)) {
735 | // copy sub properties
736 | json[key] = copyProperties(value, root);
737 | } else {
738 | // copy string values
739 | json[key] = value;
740 | }
741 |
742 | return json;
743 | }, {});
744 |
745 | // convert to Array if original object was an Array
746 | if (_.isArray(object)) {
747 | copy = _.values(object);
748 | }
749 |
750 | return copy;
751 | };
752 |
753 | return copyProperties(this);
754 | };
755 |
756 | /**
757 | * Adds a @omit property to an object to hide it from serialization
758 | *
759 | * @param property
760 | * @returns {Object}
761 | */
762 | hydra.model.hide = function (property) {
763 | property['@omit'] = true;
764 |
765 | return property;
766 | };
767 |
768 | /**
769 | * Creates a model object based on one or more classes
770 | *
771 | * @param classes The class or classes the model will be bases on
772 | * @param properties Properties to merge into the model object
773 | * @param options Additional options to control the model creation
774 | * @returns {*}
775 | */
776 | hydra.model.create = function (classes, properties, options) {
777 | var processOperations = function (root, operations) {
778 | operations.forEach(function (operation) {
779 | var key = '@' + operation.method.toLowerCase();
780 |
781 | if (!(key in root)) {
782 | root[key] = options.createInvoke(operation).bind(model);
783 | }
784 | });
785 |
786 | return Promise.resolve();
787 | };
788 |
789 | var processProperties = function (root, properties) {
790 | return Promise.all(properties.map(function (property) {
791 | return utils.compactIri(property.iri, model['@context'])
792 | .then(function (key) {
793 | if (!(key in root)) {
794 | root[key] = {};
795 | }
796 |
797 | return processOperations(root[key], property.operations);
798 | });
799 | }));
800 | };
801 |
802 | var processClass = function (apiClass) {
803 | model['@type'].push(apiClass.iri);
804 |
805 | return processOperations(model, apiClass.operations)
806 | .then(function () {
807 | return processProperties(model, apiClass.properties);
808 | });
809 | };
810 |
811 | classes = utils.toArray(classes);
812 |
813 | options = options || {};
814 | options.createInvoke = options.createInvoke || hydra.defaults.model.createInvoke;
815 |
816 | var model = _.clone(properties);
817 |
818 | _.defaults(model, {
819 | '@context': {},
820 | toJSON: hydra.model.toJSON
821 | });
822 |
823 | model['@type'] = [];
824 | model.api = classes[0].api || classes[0].abstract.api;
825 | model.api['@omit'] = true;
826 |
827 | if (classes[0].document) {
828 | model.document = classes[0].document;
829 | model.document['@omit'] = true;
830 | }
831 |
832 | return Promise.all(classes.map(function (apiClass) {
833 | return processClass(apiClass);
834 | })).then(function () {
835 | return model;
836 | });
837 | };
838 |
839 | /**
840 | * Creates a model object based on a GET request to the given URL
841 | *
842 | * @param url URL
843 | * @param properties Properties that will be merged into the model object
844 | * @param options Options for the request
845 | * @returns {Promise}
846 | */
847 | hydra.model.load = function (url, properties, options) {
848 | return hydra.loadDocument(url)
849 | .then(function (document) {
850 | return hydra.model.create(document.classes, properties, options);
851 | });
852 | };
853 |
854 | },{"./core":2,"./utils":5}],5:[function(require,module,exports){
855 | var utils = {};
856 |
857 |
858 | utils.require = function (module) {
859 | var globalModule = module;
860 |
861 | if (globalModule === 'lodash') {
862 | globalModule = '_';
863 | }
864 |
865 | if (typeof window !== 'undefined' && globalModule in window) {
866 | return window[globalModule];
867 | }
868 |
869 | return require(module);
870 | };
871 |
872 |
873 | var
874 | _ = utils.require('lodash'),
875 | jsonldp = utils.require('jsonld').promises();
876 |
877 |
878 | /**
879 | * Creates a Hydra Collection from a map or array of members
880 | *
881 | * @param iri
882 | * @param members
883 | * @returns {Collection}
884 | */
885 | utils.collection = function (iri, members) {
886 | return {
887 | '@id': iri,
888 | '@type': 'http://www.w3.org/ns/hydra/core#Collection',
889 | 'http://www.w3.org/ns/hydra/core#member': _.values(members).map(function (member) {
890 | return {
891 | '@id': member['@id'],
892 | '@type': member['@type']
893 | };
894 | })
895 | };
896 | };
897 |
898 | /**
899 | * Uses the given context to create a short form of the IRI
900 | *
901 | * @param iri
902 | * @param context
903 | * @returns {Promise}
904 | */
905 | utils.compactIri = function (iri, context) {
906 | var dummy = {};
907 |
908 | dummy[iri] = '';
909 |
910 | return jsonldp.compact(dummy, context)
911 | .then(function (compactDummy) {
912 | return _.keys(compactDummy).pop();
913 | });
914 | };
915 |
916 | /**
917 | * Creates a long version of the IRI using the given base
918 | *
919 | * @param iri
920 | * @param base
921 | * @returns {Promise}
922 | */
923 | utils.expandIri = function (iri, base) {
924 | if (!base) {
925 | return Promise.resolve(iri);
926 | }
927 |
928 | var dummy = {
929 | '@context': {
930 | '@base': base,
931 | '@vocab': 'http://schema.org/'
932 | },
933 | 'name': {
934 | '@id': iri
935 | }
936 | };
937 |
938 | return jsonldp.expand(dummy)
939 | .then(function (expanded) {
940 | return expanded[0]['http://schema.org/name'][0]['@id'];
941 | });
942 | };
943 |
944 | /**
945 | * Extracts the IRI of an JSON-LD object
946 | *
947 | * @param obj
948 | * @returns {*}
949 | */
950 | utils.iri = function (obj) {
951 | obj = utils.unwrap(obj);
952 |
953 | if (!obj) {
954 | return undefined;
955 | }
956 |
957 | if (_.isString(obj)) {
958 | return obj;
959 | }
960 |
961 | if (!('@id' in obj)) {
962 | return undefined;
963 | }
964 |
965 | return obj['@id'];
966 | };
967 |
968 | /**
969 | * Checks if the given object is a Hydra Collection
970 | *
971 | * @param collection
972 | * @returns {boolean}
973 | */
974 | utils.isCollection = function (collection) {
975 | if (_.isObject(collection)) {
976 | return false;
977 | }
978 |
979 | if (!collection.member && !(ns.member in collection)) {
980 | return false;
981 | }
982 |
983 | return true;
984 | };
985 |
986 | /**
987 | * Converts single objects and Hydra Collections to Arrays and forwards existing Arrays
988 | *
989 | * @param obj
990 | * @returns {Array}
991 | */
992 | utils.toArray = function (obj) {
993 | if (!obj) {
994 | return [];
995 | }
996 |
997 | if (utils.isCollection(obj)) {
998 | obj = obj.member;
999 | }
1000 |
1001 | if (!_.isArray(obj)) {
1002 | return [obj];
1003 | }
1004 |
1005 | return obj;
1006 | };
1007 |
1008 | /**
1009 | * Extracts the first subject of an JSON-Ld object
1010 | *
1011 | * @param obj
1012 | * @returns {*}
1013 | */
1014 | utils.unwrap = function (obj) {
1015 | if (!obj) {
1016 | return undefined;
1017 | }
1018 |
1019 | if (_.isString(obj)) {
1020 | return obj;
1021 | }
1022 |
1023 | if ('@graph' in obj) {
1024 | obj = obj['@graph'];
1025 | }
1026 |
1027 | if (_.isArray(obj)) {
1028 | if (obj.length === 0) {
1029 | return undefined;
1030 | } else {
1031 | obj = obj[0];
1032 | }
1033 | }
1034 |
1035 | return obj;
1036 | };
1037 |
1038 |
1039 | module.exports = utils;
1040 | },{}],6:[function(require,module,exports){
1041 | var
1042 | hydra = require('./core'),
1043 | utils = require('./utils'),
1044 | jsonldp = utils.require('jsonld').promises();
1045 |
1046 |
1047 | hydra.simpleValidateClass = function (object, read, write) {
1048 | var self = this;
1049 |
1050 | if (!object) {
1051 | return Promise.resolve();
1052 | }
1053 |
1054 | return jsonldp.expand(object)
1055 | .then(function (expanded) {
1056 | if (expanded.length > 1) {
1057 | return Promise.reject(new Error('object contains multiple subjects'));
1058 | }
1059 |
1060 | expanded = expanded.shift();
1061 |
1062 | if (!('@type' in expanded)) {
1063 | return Promise.reject(new Error('@type missing'));
1064 | }
1065 |
1066 | if (utils.toArray(expanded['@type']).indexOf(self.iri) < 0) {
1067 | return Promise.reject(new Error('expected class <' + self.iri + '>'));
1068 | }
1069 |
1070 | var error = self.properties
1071 | .map(function (property) {
1072 | if (property.readonly && property.iri in object) {
1073 | return new Error('readonly property <' + property.iri + '> filled with value "' + object[property.iri] + '"');
1074 | }
1075 |
1076 | return false;
1077 | })
1078 | .filter(function (error) {
1079 | return !!error;
1080 | })
1081 | .shift();
1082 |
1083 | if (error) {
1084 | return Promise.reject(error);
1085 | }
1086 |
1087 | return Promise.resolve();
1088 | });
1089 | };
1090 |
1091 |
1092 | },{"./core":2,"./utils":5}]},{},[1])(1)
1093 | });
--------------------------------------------------------------------------------
/dist/hydra-core.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"generated.js","sources":["node_modules/browserify/node_modules/browser-pack/_prelude.js","hydra-core.js","lib/core.js","lib/http-client.js","lib/model.js","lib/utils.js","lib/validation.js"],"names":["f","exports","module","define","amd","g","window","global","self","this","hydra","e","t","n","r","s","o","u","a","require","i","Error","code","l","call","length",1,"utils","loadApi","url","httpClient","request","then","response","api","body","iri","documentFromResponse","apiLink","headers","apiUrl","document","contentLocation","loadDocument","defaults","invokeOperation","jsonLdInvoke","validateClass","simpleValidateClass","model","createInvoke","createHttpJsonLdInvoke","rawJsonLdInvoke","_","jsonldp","promises","ns","vocab","apiDocumentation","member","rdfs","comment","label","range","Api","def","init","classFrameDef","@context","@vocab","@type","operationFrameDef","Promise","all","frame","classDef","operationDef","inits","classes","map","instance","Class","push","findClass","find","bind","operations","Operation","findOperation","Document","resolve","unwrap","values","filter","type","ClassDocument","properties","documentClass","abstractProperty","PropertyDocument","reduce","classProperties","concat","findProperty","arguments","method","shift","documentProperty","undefined","reject","toArray","supportedOperation","supportedProperty","propertyDef","Property","validate","abstract","operation","OperationDocument","property","statusCodes","expects","returns","link","invoke","title","description","readonly","writeonly","json","base","isString","JSON","parse","expand","compact","jsonld","XMLHttpRequest","utf8Encode","string","replace","utftext","c","charCodeAt","String","fromCharCode","base64Encode","input","chr1","chr2","chr3","enc1","enc2","enc3","enc4","keyStr","output","isNaN","charAt","requestAsync","content","callback","options","xhr","onreadystatechange","readyState","DONE","headerLines","getAllResponseHeaders","split","resHeaders","headerLine","toLowerCase","status","responseText","open","header","setRequestHeader","user","password","send","req","auth","error","res","statusCode","resBody","rels","parseLinkHeader","expandIri","target","rawInvoke","Accept","stringify","trim","expandedBody","context","toJSON","create","copyProperties","object","root","copy","keys","key","value","isFunction","isObject","isArray","hide","processOperations","forEach","processProperties","compactIri","processClass","apiClass","clone","load","globalModule","collection","members","@id","http://www.w3.org/ns/hydra/core#member","dummy","compactDummy","pop","@base","name","expanded","obj","isCollection","indexOf"],"mappings":"AAAA,CAAA,SAAAA,GAAA,GAAA,gBAAAC,UAAA,mBAAAC,QAAAA,OAAAD,QAAAD,QAAA,IAAA,kBAAAG,SAAAA,OAAAC,IAAAD,UAAAH,OAAA,CAAA,GAAAK,EAAAA,GAAA,mBAAAC,QAAAA,OAAA,mBAAAC,QAAAA,OAAA,mBAAAC,MAAAA,KAAAC,KAAAJ,EAAAK,MAAAV,MAAA,WAAA,MAAA,SAAAW,GAAAC,EAAAC,EAAAC,GAAA,QAAAC,GAAAC,EAAAC,GAAA,IAAAJ,EAAAG,GAAA,CAAA,IAAAJ,EAAAI,GAAA,CAAA,GAAAE,GAAA,kBAAAC,UAAAA,OAAA,KAAAF,GAAAC,EAAA,MAAAA,GAAAF,GAAA,EAAA,IAAAI,EAAA,MAAAA,GAAAJ,GAAA,EAAA,IAAAhB,GAAA,GAAAqB,OAAA,uBAAAL,EAAA,IAAA,MAAAhB,GAAAsB,KAAA,mBAAAtB,EAAA,GAAAuB,GAAAV,EAAAG,IAAAf,WAAAW,GAAAI,GAAA,GAAAQ,KAAAD,EAAAtB,QAAA,SAAAU,GAAA,GAAAE,GAAAD,EAAAI,GAAA,GAAAL,EAAA,OAAAI,GAAAF,EAAAA,EAAAF,IAAAY,EAAAA,EAAAtB,QAAAU,EAAAC,EAAAC,EAAAC,GAAA,MAAAD,GAAAG,GAAAf,QAAA,IAAA,GAAAmB,GAAA,kBAAAD,UAAAA,QAAAH,EAAA,EAAAA,EAAAF,EAAAW,OAAAT,IAAAD,EAAAD,EAAAE,GAAA,OAAAD,KAAAW,GAAA,SAAAP,QAAAjB,QCAA,GACAQ,OAAAS,QAAA,cACAQ,MAAAR,QAAA,cAGAA,SAAA,qBACAA,QAAA,eACAA,QAAA,oBAGAT,MAAAkB,QAAA,SAAAC,KACA,MAAAnB,OAAAoB,WAAAC,QAAA,MAAAF,KACAG,KAAA,SAAAC,UACA,MAAAvB,OAAAwB,IAAAD,SAAAE,KAAAN,OAEAG,KAAA,SAAAE,KAGA,MAFAA,KAAAE,IAAAP,IAEAK,OAKAxB,MAAA2B,qBAAA,SAAAJ,UACA,MAAAvB,OAAAoB,WAAAQ,QAAAL,SAAAM,QAAAN,SAAAF,QAAAF,KACAG,KAAA,SAAAQ,QACA,MAAA9B,OAAAkB,QAAAY,UAEAR,KAAA,SAAAE,KACA,MAAAxB,OAAA+B,SAAAP,IAAAD,SAAAE,KAAAF,SAAAF,QAAAF,OAEAG,KAAA,SAAAS,UACA,MAAA/B,OAAAoB,WAAAY,gBAAAT,SAAAM,QAAAN,SAAAF,QAAAF,KACAG,KAAA,SAAAU,iBAGA,MAFAD,UAAAL,IAAAM,iBAAAT,SAAAF,QAAAF,IAEAY,cAMA/B,MAAAiC,aAAA,SAAAd,KACA,MAAAnB,OAAAoB,WAAAC,QAAA,MAAAF,KACAG,KAAA,SAAAC,UACA,MAAAvB,OAAA2B,qBAAAJ,SAAAJ,QAMAnB,MAAAiB,MAAAA,MAIAjB,MAAAkC,YACAlC,MAAAkC,SAAAC,gBAAAnC,MAAAoB,WAAAgB,aACApC,MAAAkC,SAAAG,cAAArC,MAAAsC,oBACAtC,MAAAkC,SAAAK,SACAvC,MAAAkC,SAAAK,MAAAC,aAAAxC,MAAAuC,MAAAE,uBACAzC,MAAAkC,SAAAK,MAAAJ,gBAAAnC,MAAAoB,WAAAsB,gBAGAlD,OAAAD,QAAAS,gIC/DA,GACAiB,OAAAR,QAAA,WACAkC,EAAA1B,MAAAR,QAAA,UACAmC,QAAA3B,MAAAR,QAAA,UAAAoC,WAGA7C,QAGAA,OAAA8C,IACAC,MAAA,mCACAC,iBAAA,mDACAC,OAAA,yCAIA,IAAAC,OACAJ,IACAK,QAAA,+CACAC,MAAA,6CACAC,MAAA,8CAKArD,OAAAsD,IAAA,SAAAC,KACA,GAAAzD,MAAAC,IAEAA,MAAA2B,IAAAT,MAAAS,IAAA6B,KAEAxD,KAAAyD,KAAA,WACA,GAAAC,gBACAC,YACAC,SAAA3D,MAAA8C,GAAAC,MACAK,MAAAF,KAAAJ,GAAAM,OAEAQ,QAAA,SAGAC,mBACAH,YACAC,SAAA3D,MAAA8C,GAAAC,MACAK,MAAAF,KAAAJ,GAAAM,OAEAQ,QAAA,YAGA,OAAAE,SAAAC,KACAnB,QAAAoB,MAAAT,IAAAE,eACAnC,KAAA,SAAA2C,UACAnE,KAAAmE,SAAAA,WAEArB,QAAAoB,MAAAT,IAAAM,mBACAvC,KAAA,SAAA4C,cACApE,KAAAoE,aAAAA,iBAEA5C,KAAA,WACA,GAAA6C,SAsBA,OApBArE,MAAAsE,QAAAtE,KAAAmE,SAAA,UAAAI,IAAA,SAAAd,KACA,GAAAe,UAAA,GAAAtE,OAAAuE,MAAAzE,KAAAyD,IAIA,OAFAY,OAAAK,KAAAF,SAAAd,QAEAc,WAGAxE,KAAA2E,UAAA9B,EAAA+B,KAAAC,KAAA,KAAA7E,KAAAsE,QAAA,OAEAtE,KAAA8E,WAAA9E,KAAAoE,aAAA,UAAAG,IAAA,SAAAd,KACA,GAAAe,UAAA,GAAAtE,OAAA6E,UAAA/E,KAAAyD,IAIA,OAFAY,OAAAK,KAAAF,SAAAd,QAEAc,WAGAxE,KAAAgF,cAAAnC,EAAA+B,KAAAC,KAAA,KAAA7E,KAAA8E,WAAA,OAEAd,QAAAC,IAAAI,OACA7C,KAAA,WACA,MAAAxB,YAOAE,MAAA+E,SAAA,SAAAvD,IAAA+B,IAAA7B,KACA,GAAA5B,MAAAC,IAEAA,MAAAyB,IAAAA,IACAzB,KAAA2B,IAAAA,KAAAT,MAAAS,IAAA6B,KAEAxD,KAAAyD,KAAA,WACA,MAAAM,SAAAkB,UACA1D,KAAA,WAGA,MAFAiC,KAAAtC,MAAAgE,OAAA1B,KAEA,SAAAA,MAIAzD,KAAAsE,QAAAzB,EAAAuC,OAAA3B,IAAA,UACA4B,OAAA,SAAAC,MACA,QAAAtF,KAAA0B,IAAAiD,UAAAW,QAEAf,IAAA,SAAAe,MACA,MAAA,IAAApF,OAAAqF,cAAAvF,KAAAA,KAAA0B,IAAAiD,UAAAW,MAAA7B,OAGAzD,KAAAwF,WAAAxF,KAAAsE,QACAC,IAAA,SAAAkB,eACA,MAAAA,eAAAA,YAAAD,WACAH,OAAA,SAAAK,kBACA,MAAAA,kBAAA9D,MAAA6B,OAEAc,IAAA,SAAAmB,kBACA,MAAA,IAAAxF,OAAAyF,iBAAA3F,KAAA0F,iBAAAjC,IAAAiC,iBAAA9D,UAGAgE,OAAA,SAAAJ,WAAAK,iBACA,MAAAL,YAAAM,OAAAD,sBAGA7F,KAAA+F,aAAAlD,EAAA+B,KAAAC,KAAA,KAAA7E,KAAAwF,WAAA,OAEAxF,KAAAgF,cAAA,WACA,GAAA,IAAAgB,UAAA/E,OAAA,CACA,GAAAgF,QAAAD,UAAA,EAEA,OAAAhG,MAAAsE,QACAC,IAAA,SAAAkB,eACA,MAAAA,eAAAT,cAAAiB,UAEAC,QAEA,GAAAtE,KAAAoE,UAAA,GACAC,OAAAD,UAAA,GAEAG,iBAAAnG,KAAA+F,aAAAnE,IAEA,OAAAuE,kBAIAA,iBAAAnB,cAAAiB,QAHAG,QAOApG,MAlDAgE,QAAAqC,OAAA,oBAwDAnG,MAAAuE,MAAA,SAAA/C,IAAA+B,KACA,GAAAzD,MAAAC,IAEAA,MAAAyB,IAAAA,IACAzB,KAAA2B,IAAA6B,IAAA,OACAxD,KAAAqD,MAAAG,IAAAH,MAEArD,KAAAyD,KAAA,WACA,MAAAM,SAAAkB,UAAA1D,KAAA,WAaA,MAZAxB,MAAA8E,WAAA3D,MAAAmF,QAAA7C,IAAA8C,oBAAAhC,IAAA,SAAAH,cACA,MAAApE,MAAA0B,IAAAsD,cAAAZ,aAAA,UAGApE,KAAAgF,cAAAnC,EAAA+B,KAAAC,KAAA,KAAA7E,KAAA8E,WAAA,UAEA9E,KAAAwF,WAAArE,MAAAmF,QAAA7C,IAAA+C,mBAAAjC,IAAA,SAAAkC,aACA,MAAA,IAAAvG,OAAAwG,SAAA1G,KAAA0B,IAAA+E,eAGAzG,KAAA+F,aAAAlD,EAAA+B,KAAAC,KAAA,KAAA7E,KAAAwF,WAAA,OAEAxF,QAIAC,KAAA0G,SAAAzG,MAAAkC,SAAAG,eAIArC,MAAAqF,cAAA,SAAAtD,SAAA2E,SAAAnD,KACAxD,KAAAgC,SAAAA,SACAhC,KAAA2B,IAAAgF,SAAAhF,IACA3B,KAAAA,YAAA2G,SACA3G,KAAAqD,MAAArD,KAAAA,YAAAqD,MACArD,KAAA6E,WAAA8B,SAAA9B,WAAAP,IAAA,SAAAsC,WACA,MAAA,IAAA3G,OAAA4G,kBAAA7E,SAAA4E,aAEA5G,KAAAuF,WAAAoB,SAAApB,WACAH,OAAA,SAAA0B,UACA,MAAAA,UAAAnF,MAAA6B,OAEAc,IAAA,SAAAwC,UACA,MAAA,IAAA7G,OAAAyF,iBAAA1D,SAAA8E,SAAAtD,IAAAsD,SAAAnF,QAGA3B,KAAA+E,cAAAnC,EAAA+B,KAAAC,KAAA,KAAA5E,KAAA6E,WAAA,UAEA7E,KAAA8F,aAAAlD,EAAA+B,KAAAC,KAAA,KAAA5E,KAAAuF,WAAA,QAIAtF,MAAA6E,UAAA,SAAArD,IAAA+B,KACA,GAAAzD,MAAAC,IAEAA,MAAAyB,IAAAA,IACAzB,KAAA2B,IAAA6B,IAAA,OACAxD,KAAAqD,MAAAG,IAAAH,MAEArD,KAAAyD,KAAA,WACA,MAAAM,SAAAkB,UAAA1D,KAAA,WAMA,MALAxB,MAAAiG,OAAAxC,IAAAwC,OACAjG,KAAAgH,YAAAvD,IAAAuD,YACAhH,KAAAiH,QAAAjH,KAAA0B,IAAAiD,UAAAlB,IAAAwD,SACAjH,KAAAkH,QAAAlH,KAAA0B,IAAAiD,UAAAlB,IAAAyD,SAEAlH,SAMAE,MAAA4G,kBAAA,SAAA7E,SAAA2E,SAAAnD,KACAxD,KAAAgC,SAAAA,SACAhC,KAAA2B,IAAAgF,SAAAhF,IACA3B,KAAAA,YAAA2G,SACA3G,KAAAkH,KAAA1D,IAAAtC,MAAAS,IAAA6B,KAAA,KACAxD,KAAAqD,MAAArD,KAAAA,YAAAqD,MACArD,KAAAgG,OAAAhG,KAAAA,YAAAgG,OACAhG,KAAA+G,YAAA/G,KAAAA,YAAA+G,YACA/G,KAAAgH,QAAAhH,KAAAA,YAAAgH,QACAhH,KAAAiH,QAAAjH,KAAAA,YAAAiH,QACAjH,KAAAmH,OAAAlH,MAAAkC,SAAAC,gBAAAwC,KAAA5E,OAIAC,MAAAwG,SAAA,SAAAhF,IAAA+B,KACA,GAAAzD,MAAAC,IAEAA,MAAAyB,IAAAA,IACAzB,KAAA2B,IAAAT,MAAAS,IAAA6B,IAAAsD,UACA9G,KAAAoH,MAAA5D,IAAA4D,MACApH,KAAAqH,YAAA7D,IAAA6D,YACArH,KAAAqD,MAAAG,IAAAH,MACArD,KAAAsH,SAAA9D,IAAA8D,SACAtH,KAAAuH,UAAA/D,IAAA+D,UACAvH,KAAA6E,WAAA3D,MAAAmF,QAAA7C,IAAAsD,SAAAR,oBACAhC,IAAA,SAAAH,cACA,MAAApE,MAAA0B,IAAAsD,cAAA7D,MAAAS,IAAAwC,iBAGAnE,KAAA+E,cAAAnC,EAAA+B,KAAAC,KAAA,KAAA5E,KAAA6E,WAAA,WAIA5E,MAAAyF,iBAAA,SAAA1D,SAAA2E,SAAAnD,KACAxD,KAAAgC,SAAAA,SACAhC,KAAA2B,IAAAgF,SAAAhF,IACA3B,KAAAA,YAAA2G,SACA3G,KAAAkH,KAAA1D,IAAAtC,MAAAS,IAAA6B,KAAA,KACAxD,KAAAqD,MAAArD,KAAAA,YAAAqD,MACArD,KAAA6E,WAAA8B,SAAA9B,WAAAP,IAAA,SAAAsC,WACA,MAAA,IAAA3G,OAAA4G,kBAAA7E,SAAA4E,UAAApD,OAGAxD,KAAA+E,cAAAnC,EAAA+B,KAAAC,KAAA,KAAA5E,KAAA6E,WAAA,WAIA5E,MAAAwB,IAAA,SAAA+F,KAAAC,MAKA,MAJA7E,GAAA8E,SAAAF,QACAA,KAAAG,KAAAC,MAAAJ,OAGA3E,QAAAgF,OAAAL,MAAAC,KAAAA,OACAlG,KAAA,SAAAuG,SACA,MAAA,IAAA7H,OAAAsD,IAAAuE,SAAArE,UAKAxD,MAAA+B,SAAA,SAAAP,IAAA+F,KAAAC,MAKA,MAJA7E,GAAA8E,SAAAF,QACAA,KAAAG,KAAAC,MAAAJ,OAGA3E,QAAAgF,OAAAL,MAAAC,KAAAA,OACAlG,KAAA,SAAAuG,SACA,MAAA,IAAA7H,OAAA+E,SAAAvD,IAAAqG,QAAAL,MAAAhE,UAKAhE,OAAAD,QAAAS,2CC1SA,GACAA,OAAAS,QAAA,UACAQ,MAAAR,QAAA,WACAqH,OAAA7G,MAAAR,QAAA,UACAmC,QAAA3B,MAAAR,QAAA,UAAAoC,UAGA7C,OAAAoB,cAGA,mBAAA2G,iBAMA/H,MAAAoB,WAAA4G,WAAA,SAAAC,QACAA,OAAAA,OAAAC,QAAA,QAAA,KAIA,KAAA,GAFAC,SAAA,GAEAhI,EAAA,EAAAA,EAAA8H,OAAAlH,OAAAZ,IAAA,CACA,GAAAiI,GAAAH,OAAAI,WAAAlI,EAEA,KAAAiI,EACAD,SAAAG,OAAAC,aAAAH,GACAA,EAAA,KAAA,KAAAA,GACAD,SAAAG,OAAAC,aAAAH,GAAA,EAAA,KACAD,SAAAG,OAAAC,aAAA,GAAAH,EAAA,OAEAD,SAAAG,OAAAC,aAAAH,GAAA,GAAA,KACAD,SAAAG,OAAAC,aAAAH,GAAA,EAAA,GAAA,KACAD,SAAAG,OAAAC,aAAA,GAAAH,EAAA,MAIA,MAAAD,UAQAnI,MAAAoB,WAAAoH,aAAA,SAAAC,OACA,GAEAC,MAAAC,KAAAC,KAAAC,KAAAC,KAAAC,KAAAC,KAFAC,OAAA,oEACAC,OAAA,GAEAxI,EAAA,CAIA,KAFA+H,MAAAzI,MAAAoB,WAAA4G,WAAAS,OAEA/H,EAAA+H,MAAA1H,QACA2H,KAAAD,MAAAJ,WAAA3H,KACAiI,KAAAF,MAAAJ,WAAA3H,KACAkI,KAAAH,MAAAJ,WAAA3H,KAEAmI,KAAAH,MAAA,EACAI,MAAA,EAAAJ,OAAA,EAAAC,MAAA,EACAI,MAAA,GAAAJ,OAAA,EAAAC,MAAA,EACAI,KAAA,GAAAJ,KAEAO,MAAAR,MACAI,KAAAC,KAAA,GACAG,MAAAP,QACAI,KAAA,IAGAE,OAAAA,OAAAD,OAAAG,OAAAP,MAAAI,OAAAG,OAAAN,MAAAG,OAAAG,OAAAL,MAAAE,OAAAG,OAAAJ,KAGA,OAAAE,SAYAlJ,MAAAoB,WAAAiI,aAAA,SAAAtD,OAAA5E,IAAAU,QAAAyH,QAAAC,SAAAC,SACAA,QAAAA,WAEA,IAAAC,KAAA,GAAA1B,eAEA0B,KAAAC,mBAAA,WACA,GAAAD,IAAAE,aAAAF,IAAAG,KAAA,CAKA,IAAA,GAHAC,aAAAJ,IAAAK,wBAAAC,MAAA,QACAC,cAEAtJ,EAAA,EAAAA,EAAAmJ,YAAA9I,OAAAL,IAAA,CACA,GAAAuJ,YAAAJ,YAAAnJ,GAAAqJ,MAAA,KAAA,EACAC,YAAAC,WAAA,GAAAC,eAAAD,WAAA,GAGAV,SAAAE,IAAAU,OAAAH,WAAAP,IAAAW,gBAIAX,IAAAY,KAAAtE,OAAA5E,KAAA,EAEA,KAAA,GAAAmJ,UAAAzI,SACA4H,IAAAc,iBAAAD,OAAAzI,QAAAyI,QAGAd,SAAAgB,MAAAhB,QAAAiB,UACAhB,IAAAc,iBAAA,gBAAA,SAAAvK,MAAAoB,WAAAoH,aAAAgB,QAAAgB,KAAA,IAAAhB,QAAAiB,WAGAhB,IAAAiB,KAAApB,WAaAtJ,MAAAoB,WAAAiI,aAAA,SAAAtD,OAAA5E,IAAAU,QAAAyH,QAAAC,SAAAC,SACA,GAAAnI,SAAAZ,QAAA,UAEA+I,SAAAA,WAEA,IAAAmB,MACA5E,OAAAA,OACA5E,IAAAA,IACAU,QAAAA,QACAJ,KAAA6H,QAGAE,SAAAgB,MAAAhB,QAAAiB,WACAE,IAAAC,MACAJ,KAAAhB,QAAAgB,KACAC,SAAAjB,QAAAiB,WAIApJ,QAAAsJ,IAAA,SAAAE,MAAAC,IAAArJ,MACAoJ,MACAtB,SAAA,KAAA,KAAA,KAAAsB,OAEAtB,SAAAuB,IAAAC,WAAAD,IAAAjJ,QAAAJ,SAgBAzB,MAAAoB,WAAAC,QAAA,SAAA0E,OAAA5E,IAAAU,QAAAyH,QAAAE,SACA,MAAA,IAAA1F,SAAA,SAAAkB,QAAAmB,QACAnG,MAAAoB,WAAAiI,aAAAtD,OAAA5E,IAAAU,QAAAyH,QAAA,SAAAa,OAAAH,WAAAgB,QAAAH,OACA,GAAAtJ,WACA4I,OAAAA,OACAtI,QAAAmI,WACAvI,KAAAuJ,QACA3J,SACAF,IAAAA,IACA4E,OAAAA,OACAlE,QAAAA,QACAJ,KAAA6H,SAIAuB,OACA1E,OAAA0E,OACAV,QAAA,IACAhE,OAAA,GAAAxF,OAAA,eAAAwJ,OAAA,KAAAa,UAEAhG,QAAAzD,WAEAiI,YAWAxJ,MAAAoB,WAAAQ,QAAA,SAAAC,QAAA2F,MACA,KAAA,QAAA3F,UACA,MAAAiC,SAAAkB,QAAAkB,OAGA,IAAA+E,MAAAnD,OAAAoD,gBAAArJ,QAAAoF,KAEA,OAAAjH,OAAA8C,GAAAE,mBAAAiI,MAIAhK,MAAAkK,UAAAF,KAAAjL,MAAA8C,GAAAE,kBAAAoI,OAAA5D,MAHA1D,QAAAkB,QAAAkB,SAaAlG,MAAAoB,WAAAY,gBAAA,SAAAH,QAAA2F,MACA,MAAA,oBAAA3F,SAIAZ,MAAAkK,UAAAtJ,QAAA,oBAAA2F,MAHA1D,QAAAkB,QAAAkB,SAcAlG,MAAAoB,WAAAiK,UAAA,SAAAxJ,QAAAyH,QAAAE,SACA,GAAA1J,MAAAC,KAEAoB,IAAArB,KAAAmH,MAAAnH,KAAAiC,SAAAL,GAEA,OAAA1B,OAAAoB,WAAAC,QAAAvB,KAAAiG,OAAA5E,IAAAU,QAAAyH,QAAAE,UAUAxJ,MAAAoB,WAAAsB,gBAAA,SAAA4G,QAAAE,SACA,GAAA1J,MAAAC,KAEA8B,SACAyJ,OAAA,sBAOA,QAJA,UAAAxL,KAAAiG,QAAA,SAAAjG,KAAAiG,QAAA,QAAAjG,KAAAiG,UACAlE,QAAA,gBAAA,uBAGA7B,MAAAoB,WAAAiK,UAAA1G,KAAA7E,MAAA+B,QAAA6F,KAAA6D,UAAAjC,SAAAE,SACAlI,KAAA,SAAAC,UACA,MAAAA,UAAAE,MAAA,KAAAF,SAAAE,KAAA+J,OACA5I,QAAAgF,OAAAF,KAAAC,MAAApG,SAAAE,OAAA+F,KAAAjG,SAAAF,QAAAF,MACAG,KAAA,SAAAmK,cAGA,MAFAlK,UAAAE,KAAAgK,aAEAlK,YAGAA,SAAAE,KAAA,KAEAF,aAYAvB,MAAAoB,WAAAgB,aAAA,SAAAkH,QAAAE,SACA,GAAA1J,MAAAC,IAEA,OAAAC,OAAAoB,WAAAsB,gBAAAiC,KAAA7E,MAAAwJ,QAAAE,SACAlI,KAAA,SAAAC,UACA,MAAAA,UAAAE,uEClSA,GACAzB,OAAAS,QAAA,UACAQ,MAAAR,QAAA,WACAkC,EAAA1B,MAAAR,QAAA,UACAmC,QAAA3B,MAAAR,QAAA,UAAAoC,UAGA7C,OAAAuC,SASAvC,MAAAuC,MAAAE,uBAAA,SAAAkE,WACA,MAAA,UAAA8B,MAAAe,SACAA,QAAAA,WAEA,IAAAkC,WAYA,OAVA,YAAA3L,QACA2L,QAAA3L,KAAA,aAGA2L,QAAAlC,QAAAkC,SAAAA,QAEAjD,OAAAA,MAAAkD,SACAlD,MAAAA,MAAAkD,UAGA3L,MAAAoB,WAAAsB,gBAAA5B,KAAA6F,UAAA8B,MAAAe,SACAlI,KAAA,SAAAC,UACA,MAAAA,UAAAE,KAIAzB,MAAA2B,qBAAAJ,UACAD,KAAA,SAAAS,UACA,MAAAa,SAAAiF,QAAAtG,SAAAE,KAAAiK,SACApK,KAAA,SAAA4H,QACA,MAAAlJ,OAAAuC,MAAAqJ,OAAA7J,SAAAqC,QAAA8E,YAPApF,QAAAkB,QAAA,UAiBAhF,MAAAuC,MAAAoJ,OAAA,WACA,GAAAE,gBAAA,SAAAC,OAAAC,MACA,IAAAD,OACA,MAAA,KAGA,IAAAE,MAAArJ,EAAAsJ,KAAAH,QAAApG,OAAA,SAAA6B,KAAA2E,KACA,GAAAC,OAAAL,OAAAI,IAGA,OAAAvJ,GAAAyJ,WAAAD,OACA5E,KAIA5E,EAAA0J,SAAAF,QAAA,SAAAA,QAAAA,MAAA,SACA5E,MAKAA,KAAA2E,KAFAvJ,EAAA0J,SAAAF,OAEAN,eAAAM,MAAAJ,MAGAI,MAGA5E,UAQA,OAJA5E,GAAA2J,QAAAR,UACAE,KAAArJ,EAAAuC,OAAA4G,SAGAE,KAGA,OAAAH,gBAAA9L,OASAC,MAAAuC,MAAAgK,KAAA,SAAA1F,UAGA,MAFAA,UAAA,UAAA,EAEAA,UAWA7G,MAAAuC,MAAAqJ,OAAA,SAAAxH,QAAAkB,WAAAkE,SACA,GAAAgD,mBAAA,SAAAT,KAAAnH,YASA,MARAA,YAAA6H,QAAA,SAAA9F,WACA,GAAAuF,KAAA,IAAAvF,UAAAZ,OAAAmE,aAEAgC,OAAAH,QACAA,KAAAG,KAAA1C,QAAAhH,aAAAmE,WAAAhC,KAAApC,UAIAuB,QAAAkB,WAGA0H,kBAAA,SAAAX,KAAAzG,YACA,MAAAxB,SAAAC,IAAAuB,WAAAjB,IAAA,SAAAwC,UACA,MAAA5F,OAAA0L,WAAA9F,SAAAnF,IAAAa,MAAA,aACAjB,KAAA,SAAA4K,KAKA,MAJAA,OAAAH,QACAA,KAAAG,SAGAM,kBAAAT,KAAAG,KAAArF,SAAAjC,kBAKAgI,aAAA,SAAAC,UAGA,MAFAtK,OAAA,SAAAiC,KAAAqI,SAAAnL,KAEA8K,kBAAAjK,MAAAsK,SAAAjI,YACAtD,KAAA,WACA,MAAAoL,mBAAAnK,MAAAsK,SAAAvH,cAIAlB,SAAAnD,MAAAmF,QAAAhC,SAEAoF,QAAAA,YACAA,QAAAhH,aAAAgH,QAAAhH,cAAAxC,MAAAkC,SAAAK,MAAAC,YAEA,IAAAD,OAAAI,EAAAmK,MAAAxH,WAgBA,OAdA3C,GAAAT,SAAAK,OACAmB,cACAiI,OAAA3L,MAAAuC,MAAAoJ,SAGApJ,MAAA,YACAA,MAAAf,IAAA4C,QAAA,GAAA5C,KAAA4C,QAAA,GAAAA,YAAA5C,IACAe,MAAAf,IAAA,UAAA,EAEA4C,QAAA,GAAArC,WACAQ,MAAAR,SAAAqC,QAAA,GAAArC,SACAQ,MAAAR,SAAA,UAAA,GAGA+B,QAAAC,IAAAK,QAAAC,IAAA,SAAAwI,UACA,MAAAD,cAAAC,aACAvL,KAAA,WACA,MAAAiB,UAYAvC,MAAAuC,MAAAwK,KAAA,SAAA5L,IAAAmE,WAAAkE,SACA,MAAAxJ,OAAAiC,aAAAd,KACAG,KAAA,SAAAS,UACA,MAAA/B,OAAAuC,MAAAqJ,OAAA7J,SAAAqC,QAAAkB,WAAAkE,mEC3LA,GAAAvI,SAGAA,OAAAR,QAAA,SAAAjB,QACA,GAAAwN,cAAAxN,MAMA,OAJA,WAAAwN,eACAA,aAAA,KAGA,mBAAApN,SAAAoN,eAAApN,QACAA,OAAAoN,cAGAvM,QAAAjB,QAIA,IACAmD,GAAA1B,MAAAR,QAAA,UACAmC,QAAA3B,MAAAR,QAAA,UAAAoC,UAUA5B,OAAAgM,WAAA,SAAAvL,IAAAwL,SACA,OACAC,MAAAzL,IACAkC,QAAA,6CACAwJ,yCAAAzK,EAAAuC,OAAAgI,SAAA7I,IAAA,SAAApB,QACA,OACAkK,MAAAlK,OAAA,OACAW,QAAAX,OAAA,cAaAhC,MAAA0L,WAAA,SAAAjL,IAAAgK,SACA,GAAA2B,SAIA,OAFAA,OAAA3L,KAAA,GAEAkB,QAAAiF,QAAAwF,MAAA3B,SACApK,KAAA,SAAAgM,cACA,MAAA3K,GAAAsJ,KAAAqB,cAAAC,SAWAtM,MAAAkK,UAAA,SAAAzJ,IAAA8F,MACA,IAAAA,KACA,MAAA1D,SAAAkB,QAAAtD,IAGA,IAAA2L,QACA3J,YACA8J,QAAAhG,KACA7D,SAAA,sBAEA8J,MACAN,MAAAzL,KAIA,OAAAkB,SAAAgF,OAAAyF,OACA/L,KAAA,SAAAoM,UACA,MAAAA,UAAA,GAAA,0BAAA,GAAA,UAUAzM,MAAAS,IAAA,SAAAiM,KAGA,MAFAA,KAAA1M,MAAAgE,OAAA0I,KAEAA,IAIAhL,EAAA8E,SAAAkG,KACAA,IAGA,OAAAA,KAIAA,IAAA,OAHAzH,OARAA,QAoBAjF,MAAA2M,aAAA,SAAAX,YACA,MAAAtK,GAAA0J,SAAAY,aACA,EAGAA,WAAAhK,QAAAH,GAAAG,SAAAgK,aAIA,GAHA,GAYAhM,MAAAmF,QAAA,SAAAuH,KACA,MAAAA,MAIA1M,MAAA2M,aAAAD,OACAA,IAAAA,IAAA1K,QAGAN,EAAA2J,QAAAqB,KAIAA,KAHAA,UAYA1M,MAAAgE,OAAA,SAAA0I,KACA,IAAAA,IACA,MAAAzH,OAGA,IAAAvD,EAAA8E,SAAAkG,KACA,MAAAA,IAOA,IAJA,UAAAA,OACAA,IAAAA,IAAA,WAGAhL,EAAA2J,QAAAqB,KAAA,CACA,GAAA,IAAAA,IAAA5M,OACA,MAAAmF,OAEAyH,KAAAA,IAAA,GAIA,MAAAA,MAIAnO,OAAAD,QAAA0B,gCCxLA,GACAjB,OAAAS,QAAA,UACAQ,MAAAR,QAAA,WACAmC,QAAA3B,MAAAR,QAAA,UAAAoC,UAGA7C,OAAAsC,oBAAA,SAAAwJ,QACA,GAAAhM,MAAAC,IAEA,OAAA+L,QAIAlJ,QAAAgF,OAAAkE,QACAxK,KAAA,SAAAoM,UACA,GAAAA,SAAA3M,OAAA,EACA,MAAA+C,SAAAqC,OAAA,GAAAxF,OAAA,qCAKA,IAFA+M,SAAAA,SAAA1H,UAEA,SAAA0H,WACA,MAAA5J,SAAAqC,OAAA,GAAAxF,OAAA,iBAGA,IAAAM,MAAAmF,QAAAsH,SAAA,UAAAG,QAAA/N,KAAA4B,KAAA,EACA,MAAAoC,SAAAqC,OAAA,GAAAxF,OAAA,mBAAAb,KAAA4B,IAAA,KAGA,IAAAmJ,OAAA/K,KAAAwF,WACAjB,IAAA,SAAAwC,UACA,MAAAA,UAAAQ,UAAAR,SAAAnF,MAAAoK,QACA,GAAAnL,OAAA,sBAAAkG,SAAAnF,IAAA,wBAAAoK,OAAAjF,SAAAnF,KAAA,MAGA,IAEAyD,OAAA,SAAA0F,OACA,QAAAA,QAEA7E,OAEA,OAAA6E,OACA/G,QAAAqC,OAAA0E,OAGA/G,QAAAkB,YApCAlB,QAAAkB;ALVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o 127) && (c < 2048)) {\n utftext += String.fromCharCode((c >> 6) | 192);\n utftext += String.fromCharCode((c & 63) | 128);\n } else {\n utftext += String.fromCharCode((c >> 12) | 224);\n utftext += String.fromCharCode(((c >> 6) & 63) | 128);\n utftext += String.fromCharCode((c & 63) | 128);\n }\n }\n\n return utftext;\n };\n\n /**\n * Converts a string to a base-64 encoded string\n * @param input The string to encode\n * @returns {string} The base-64 string\n */\n hydra.httpClient.base64Encode = function (input) {\n var keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n var output = '';\n var chr1, chr2, chr3, enc1, enc2, enc3, enc4;\n var i = 0;\n\n input = hydra.httpClient.utf8Encode(input);\n\n while (i < input.length) {\n chr1 = input.charCodeAt(i++);\n chr2 = input.charCodeAt(i++);\n chr3 = input.charCodeAt(i++);\n\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n } else if (isNaN(chr3)) {\n enc4 = 64;\n }\n\n output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);\n }\n\n return output;\n };\n\n /**\n * Request implementation using XMLHttpRequest interface\n *\n * @param method HTTP method\n * @param url URL\n * @param headers Header key/value pairs\n * @param content Content\n * @param callback Callback function using with interface: statusCode, headers, content, error\n */\n hydra.httpClient.requestAsync = function (method, url, headers, content, callback, options) {\n options = options || {};\n\n var xhr = new XMLHttpRequest();\n\n xhr.onreadystatechange = function () {\n if (xhr.readyState === xhr.DONE) {\n var\n headerLines = xhr.getAllResponseHeaders().split('\\r\\n'),\n resHeaders = {};\n\n for (var i = 0; i < headerLines.length; i++) {\n var headerLine = headerLines[i].split(': ', 2);\n resHeaders[headerLine[0].toLowerCase()] = headerLine[1];\n }\n\n callback(xhr.status, resHeaders, xhr.responseText);\n }\n };\n\n xhr.open(method, url, true);\n\n for (var header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n\n if (options.user && options.password) {\n xhr.setRequestHeader(\"Authorization\", \"Basic \" + hydra.httpClient.base64Encode(options.user + \":\" + options.password));\n }\n\n xhr.send(content);\n };\n} else {\n /**\n * Request implementation using the npm request module\n *\n * @param method HTTP method\n * @param url URL\n * @param headers Header key/value pairs\n * @param content Content\n * @param callback Callback function using with interface: statusCode, headers, content, error\n * @param options Additional options like user or password\n */\n hydra.httpClient.requestAsync = function (method, url, headers, content, callback, options) {\n var request = require('request');\n\n options = options || {};\n\n var req = {\n method: method,\n url: url,\n headers: headers,\n body: content\n };\n\n if (options.user && options.password) {\n req.auth = {\n user: options.user,\n password: options.password\n };\n }\n\n request(req, function (error, res, body) {\n if (error) {\n callback(null, null, null, error);\n } else {\n callback(res.statusCode, res.headers, body);\n }\n });\n };\n}\n\n/**\n * Promise request implementation\n *\n * @param method HTTP method\n * @param url URL\n * @param headers Header key/value pairs\n * @param content Content\n * @param options Additional options like user or password\n * @returns {Promise}\n */\nhydra.httpClient.request = function (method, url, headers, content, options) {\n return new Promise(function (resolve, reject) {\n hydra.httpClient.requestAsync(method, url, headers, content, function (status, resHeaders, resBody, error) {\n var response = {\n status: status,\n headers: resHeaders,\n body: resBody,\n request: {\n url: url,\n method: method,\n headers: headers,\n body: content\n }\n };\n\n if (error) {\n reject(error);\n } else if (status >= 400) {\n reject(new Error('status code ' + status + ': ' + resBody));\n } else {\n resolve(response);\n }\n }, options);\n });\n};\n\n/**\n * Extracts the Hydra API Documentation value of the Link header field\n *\n * @param headers\n * @param base\n * @returns {Promise}\n */\nhydra.httpClient.apiLink = function (headers, base) {\n if (!('link' in headers)) {\n return Promise.resolve(undefined);\n }\n\n var rels = jsonld.parseLinkHeader(headers.link);\n\n if (!(hydra.ns.apiDocumentation in rels)) {\n return Promise.resolve(undefined);\n }\n\n return utils.expandIri(rels[hydra.ns.apiDocumentation].target, base);\n};\n\n/**\n * Extracts the value of the Content-Location header field\n *\n * @param headers\n * @param base\n * @returns {*}\n */\nhydra.httpClient.contentLocation = function (headers, base) {\n if (!('content-location' in headers)) {\n return Promise.resolve(undefined);\n }\n\n return utils.expandIri(headers['content-location'], base);\n};\n\n/**\n * Calls an operations with the given headers and content\n *\n * @param headers\n * @param content\n * @param options\n * @returns {Promise}\n */\nhydra.httpClient.rawInvoke = function (headers, content, options) {\n var self = this;\n\n var url = self.link || self.document.iri;\n\n return hydra.httpClient.request(self.method, url, headers, content, options);\n};\n\n/**\n * Calls an operations with the JSON-LD content and converts the response body to JSON-LD\n *\n * @param content\n * @param options\n * @returns {Promise}\n */\nhydra.httpClient.rawJsonLdInvoke = function (content, options) {\n var self = this;\n\n var headers = {\n 'Accept': 'application/ld+json'\n };\n\n if (self.method === 'PATCH' || self.method === 'POST' || self.method === 'PUT') {\n headers['Content-Type'] = 'application/ld+json';\n }\n\n return hydra.httpClient.rawInvoke.bind(self)(headers, JSON.stringify(content), options)\n .then(function (response) {\n if (response.body && response.body.trim() !== '') {\n return jsonldp.expand(JSON.parse(response.body), {base: response.request.url})\n .then(function (expandedBody) {\n response.body = expandedBody;\n\n return response;\n })\n } else {\n response.body = null;\n\n return response;\n }\n });\n};\n\n/**\n * Calls an operations with the JSON-LD content and returns the response body converted to JSON-LD\n *\n * @param content\n * @param options\n * @returns {Promise}\n */\nhydra.httpClient.jsonLdInvoke = function (content, options) {\n var self = this;\n\n return hydra.httpClient.rawJsonLdInvoke.bind(self)(content, options)\n .then(function (response) {\n return response.body;\n });\n};\n","var\n hydra = require('./core'),\n utils = require('./utils'),\n _ = utils.require('lodash'),\n jsonldp = utils.require('jsonld').promises();\n\n\nhydra.model = {};\n\n\n/**\n * Creates an invoke function for model objects that compacts the response using the given context\n *\n * @param operation\n * @returns {Function}\n */\nhydra.model.createHttpJsonLdInvoke = function (operation) {\n return function (input, options) {\n options = options || {};\n\n var context = {};\n\n if ('@context' in this) {\n context = this['@context'];\n }\n\n context = options.context || context;\n\n if (input && input.toJSON) {\n input = input.toJSON();\n }\n\n return hydra.httpClient.rawJsonLdInvoke.call(operation, input, options)\n .then(function (response) {\n if (!response.body) {\n return Promise.resolve(null);\n }\n\n return hydra.documentFromResponse(response)\n .then(function (document) {\n return jsonldp.compact(response.body, context)\n .then(function (output) {\n return hydra.model.create(document.classes, output);\n });\n });\n });\n };\n};\n\n/**\n * Converts a model object to serializable object without functions and property flagged with @omit\n */\nhydra.model.toJSON = function () {\n var copyProperties = function (object, root) {\n if (!object) {\n return null;\n }\n\n var copy = _.keys(object).reduce(function (json, key) {\n var value = object[key];\n\n // don't add function properties\n if (_.isFunction(value)) {\n return json;\n }\n\n // don't add properties with @omit flag\n if (_.isObject(value) && '@omit' in value && value['@omit']) {\n return json;\n }\n\n if (_.isObject(value)) {\n // copy sub properties\n json[key] = copyProperties(value, root);\n } else {\n // copy string values\n json[key] = value;\n }\n\n return json;\n }, {});\n\n // convert to Array if original object was an Array\n if (_.isArray(object)) {\n copy = _.values(object);\n }\n\n return copy;\n };\n\n return copyProperties(this);\n};\n\n/**\n * Adds a @omit property to an object to hide it from serialization\n *\n * @param property\n * @returns {Object}\n */\nhydra.model.hide = function (property) {\n property['@omit'] = true;\n\n return property;\n};\n\n/**\n * Creates a model object based on one or more classes\n *\n * @param classes The class or classes the model will be bases on\n * @param properties Properties to merge into the model object\n * @param options Additional options to control the model creation\n * @returns {*}\n */\nhydra.model.create = function (classes, properties, options) {\n var processOperations = function (root, operations) {\n operations.forEach(function (operation) {\n var key = '@' + operation.method.toLowerCase();\n\n if (!(key in root)) {\n root[key] = options.createInvoke(operation).bind(model);\n }\n });\n\n return Promise.resolve();\n };\n\n var processProperties = function (root, properties) {\n return Promise.all(properties.map(function (property) {\n return utils.compactIri(property.iri, model['@context'])\n .then(function (key) {\n if (!(key in root)) {\n root[key] = {};\n }\n\n return processOperations(root[key], property.operations);\n });\n }));\n };\n\n var processClass = function (apiClass) {\n model['@type'].push(apiClass.iri);\n\n return processOperations(model, apiClass.operations)\n .then(function () {\n return processProperties(model, apiClass.properties);\n });\n };\n\n classes = utils.toArray(classes);\n\n options = options || {};\n options.createInvoke = options.createInvoke || hydra.defaults.model.createInvoke;\n\n var model = _.clone(properties);\n\n _.defaults(model, {\n '@context': {},\n toJSON: hydra.model.toJSON\n });\n\n model['@type'] = [];\n model.api = classes[0].api || classes[0].abstract.api;\n model.api['@omit'] = true;\n\n if (classes[0].document) {\n model.document = classes[0].document;\n model.document['@omit'] = true;\n }\n\n return Promise.all(classes.map(function (apiClass) {\n return processClass(apiClass);\n })).then(function () {\n return model;\n });\n};\n\n/**\n * Creates a model object based on a GET request to the given URL\n *\n * @param url URL\n * @param properties Properties that will be merged into the model object\n * @param options Options for the request\n * @returns {Promise}\n */\nhydra.model.load = function (url, properties, options) {\n return hydra.loadDocument(url)\n .then(function (document) {\n return hydra.model.create(document.classes, properties, options);\n });\n};\n","var utils = {};\n\n\nutils.require = function (module) {\n var globalModule = module;\n\n if (globalModule === 'lodash') {\n globalModule = '_';\n }\n\n if (typeof window !== 'undefined' && globalModule in window) {\n return window[globalModule];\n }\n\n return require(module);\n};\n\n\nvar\n _ = utils.require('lodash'),\n jsonldp = utils.require('jsonld').promises();\n\n\n/**\n * Creates a Hydra Collection from a map or array of members\n *\n * @param iri\n * @param members\n * @returns {Collection}\n */\nutils.collection = function (iri, members) {\n return {\n '@id': iri,\n '@type': 'http://www.w3.org/ns/hydra/core#Collection',\n 'http://www.w3.org/ns/hydra/core#member': _.values(members).map(function (member) {\n return {\n '@id': member['@id'],\n '@type': member['@type']\n };\n })\n };\n};\n\n/**\n * Uses the given context to create a short form of the IRI\n *\n * @param iri\n * @param context\n * @returns {Promise}\n */\nutils.compactIri = function (iri, context) {\n var dummy = {};\n\n dummy[iri] = '';\n\n return jsonldp.compact(dummy, context)\n .then(function (compactDummy) {\n return _.keys(compactDummy).pop();\n });\n};\n\n/**\n * Creates a long version of the IRI using the given base\n *\n * @param iri\n * @param base\n * @returns {Promise}\n */\nutils.expandIri = function (iri, base) {\n if (!base) {\n return Promise.resolve(iri);\n }\n\n var dummy = {\n '@context': {\n '@base': base,\n '@vocab': 'http://schema.org/'\n },\n 'name': {\n '@id': iri\n }\n };\n\n return jsonldp.expand(dummy)\n .then(function (expanded) {\n return expanded[0]['http://schema.org/name'][0]['@id'];\n });\n};\n\n/**\n * Extracts the IRI of an JSON-LD object\n *\n * @param obj\n * @returns {*}\n */\nutils.iri = function (obj) {\n obj = utils.unwrap(obj);\n\n if (!obj) {\n return undefined;\n }\n\n if (_.isString(obj)) {\n return obj;\n }\n\n if (!('@id' in obj)) {\n return undefined;\n }\n\n return obj['@id'];\n};\n\n/**\n * Checks if the given object is a Hydra Collection\n *\n * @param collection\n * @returns {boolean}\n */\nutils.isCollection = function (collection) {\n if (_.isObject(collection)) {\n return false;\n }\n\n if (!collection.member && !(ns.member in collection)) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Converts single objects and Hydra Collections to Arrays and forwards existing Arrays\n *\n * @param obj\n * @returns {Array}\n */\nutils.toArray = function (obj) {\n if (!obj) {\n return [];\n }\n\n if (utils.isCollection(obj)) {\n obj = obj.member;\n }\n\n if (!_.isArray(obj)) {\n return [obj];\n }\n\n return obj;\n};\n\n/**\n * Extracts the first subject of an JSON-Ld object\n *\n * @param obj\n * @returns {*}\n */\nutils.unwrap = function (obj) {\n if (!obj) {\n return undefined;\n }\n\n if (_.isString(obj)) {\n return obj;\n }\n\n if ('@graph' in obj) {\n obj = obj['@graph'];\n }\n\n if (_.isArray(obj)) {\n if (obj.length === 0) {\n return undefined;\n } else {\n obj = obj[0];\n }\n }\n\n return obj;\n};\n\n\nmodule.exports = utils;","var\n hydra = require('./core'),\n utils = require('./utils'),\n jsonldp = utils.require('jsonld').promises();\n\n\nhydra.simpleValidateClass = function (object, read, write) {\n var self = this;\n\n if (!object) {\n return Promise.resolve();\n }\n\n return jsonldp.expand(object)\n .then(function (expanded) {\n if (expanded.length > 1) {\n return Promise.reject(new Error('object contains multiple subjects'));\n }\n\n expanded = expanded.shift();\n\n if (!('@type' in expanded)) {\n return Promise.reject(new Error('@type missing'));\n }\n\n if (utils.toArray(expanded['@type']).indexOf(self.iri) < 0) {\n return Promise.reject(new Error('expected class <' + self.iri + '>'));\n }\n\n var error = self.properties\n .map(function (property) {\n if (property.readonly && property.iri in object) {\n return new Error('readonly property <' + property.iri + '> filled with value \"' + object[property.iri] + '\"');\n }\n\n return false;\n })\n .filter(function (error) {\n return !!error;\n })\n .shift();\n\n if (error) {\n return Promise.reject(error);\n }\n\n return Promise.resolve();\n });\n};\n\n"]}
--------------------------------------------------------------------------------