├── .gitignore
├── .travis.yml
├── Procfile
├── README.md
├── index.js
├── package.json
└── test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | *~
3 | .*
4 | example.js
5 | Procfile
6 | node_modules
7 | tmp
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | before_install:
2 | # init xvfb
3 | # http://docs.travis-ci.com/user/gui-and-headless-browsers/
4 | - "export DISPLAY=:99.0 && sh -e /etc/init.d/xvfb start"
5 | # install mongodb 3.0
6 | # https://github.com/mongodb/mongo-ruby-driver/blob/master/.travis.yml
7 | - curl http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.5.tgz | tar xvz -C /tmp && mkdir -p /tmp/data && /tmp/mongodb-linux-x86_64-3.0.5/bin/mongod --dbpath /tmp/data &> /dev/null &
8 | branches:
9 | only:
10 | - alpha
11 | - beta
12 | - master
13 | env:
14 | global:
15 | # this value is auto-generated by shAesEncryptTravis
16 | - secure: ZaEFBVYOMJWn1/JgVC9qxkjfrr7G6/aX+N1v8dsToLd45mnSvHawTXKb3/rH9Y8phBH/uLFkQjjhL3YU1yblPSS/+lqR4jiDY36l9Es6pt2Bn1UP1Fk1KmCZu4elelssHSZac+S5o8j/yCVIn2oVWT447GFyfizQgMeYYBUTGZ+QRn0bu3uAbkLlQFSDGcgUxBzrxOMSlLpaP9ekszMQOn4UUYmIopgfeyqtUQn+nOwqdYYREV5AHB3tAH4QV8oxcZWj1sZ6JFkpa5D+p4waKg2xvgVi66iN/WNiUmydPzrZvWu3Z6jCUl9gq86x7FeUQ5AcKbcj8IkOQgV2BdBdP9u/ohPej/FLEzs0TtKezyRnHxl9/S9YsHJF35FnllCZfMMIgi+qF+LEpRJAdXsIH1FvQmSsHffTajTh9iO9UHAXU0xdUr9NQ1ZYoQR7rudgAOpcw9KNYqFVBuocuG5U9IcTgtTWr0T9NZg9IMu0iAcTGPS/OTBhRETwjTSvfk1KS0y4hy5eUJp0Uwh1K8swKmsHvpw0HzxSNjoad9X/iddPkrwXm6g35wUIrvSk5J/CkUKe+sfOkpuiadC/0UbafsS+etnoogdeINgR5t8Y0hHEXSDG5Hln56xAFIY4fwF3CCb8+Ix43RgRrGTVgT6yrVuW1bjFcQMKbqohcCFMhns= # AES_256_KEY
17 | # this value is auto-generated by shAesEncryptTravis
18 | # - AES_ENCRYPTED_SH: ZjU1ZThmOTRlNWVlMDFiZTY0MDgxMDg3YTNmZTVmZDggVJwx16+4xQGKhh2X7+oklO5U7Dxuo4Ds10hFjDz1F6Yuh8Qpd2aovzJ820uK5CoErpBRYKa4xBgvbuF2aBrP87jveyiJlCk5xiWmEmfTkzaqyA+OAPq07I4ag3V3/EOnOwaqnlaDcgSIMTyqHYJryqOGziuQet9/crF1C3yt7C1KH1ig5E041x5FO5GnILKerT1/Bir02blzuPMZyZQR2ZOi3Froq6cB3aZrjOsB4E7Zmb6mwQ/zPExUTdPUAbyXrcC+5/Xl6OPBMnnUPOKYSIMFzVcKFiW0PD4wSu4tJIcrDwAOvbO/Ca3OrrmqDsqh5q6ZMy9upxcWnZKPEwo3SviHh8TsEaV1hGJH61HYgG7X7m4sOKy7C5qR1XDG7vLOqcZLgjbB5648AGJZudJ1eM2G5riFyUrd3NbeJjbYwtNY84AnXSCQv6IVEUVQz84pIv2MJKN1IVK/v1/gDv0Ron8qZoD/l8bphR4rEqC247+skAtn4VtRGUh7oMf7RSYtWgzlAiFBV0m1rJyYEgITcapXfe1cnRO8/5RWMlTurHptm45c6Akr/ZMrxipvOTvn8nB7s29YaVJwl2SwyVgdG63G+AdgeO1k4QUKEyV0fjm7Ti6RyoOMUlqvzFrqs7zTK42BqTH2ANMFG6xpE1ivn7XONp5peE10K02rVajJ8F1ytYTtlhgbtZ9OVMO3ybJAZep0iTe1+BVqdl14V03eW1rat2MGgkCa6elLkb3ZT+mrexPtmLlXM9ar7qE98krm0boG3LLhuqKBjyTpgW2tX6w/vhsZL3Al3Jxew2ppucVwOViGNOsJIrSmJ9zlRtz/+qPesvn17+eMnfpwH7iOsbgRtzuzvcih0KhGyUQOeAbzsqJjAxmiD4VcibZzCi9TB7Uy7r0eF1WgOlpEA8u8/3zIQ/u80/ttPYf42imEzFlumpfwxyw5kmEglNE6y0uP0eQFdzS+VkDnN3V8ke1T3Pz/30aSpNeSUyoCWlWiYdLE4M8EDW/EuI+BsEEq6Wgienl7tbOQa77Z4LgC/EUwF2n984GsVYJJQqb4Zr6Wze9LFoWicNNK1OBytjAX7deYYcuuouGQpNtkUg3ATVoV/ftWIk83SsaLDTrP3j5UoyUUJkWNBP7hvW3CZ/8S/VAJYDybH9O9CNciZugMSDn3zbAd3yEN+FleP73wC74Kht0cZBm9K6fBgOXqv/v0GXGmz3yo5KA8+DUoh9nhaZmpeHpPopQGfqdZ369vlk0LbniADyiZRJ3ibi8SJrl3O5hlJDFnWotaWj65u1/CnNaGnwAcJoDN9v2S9ar+EZb6oh8b0trFzqLPjB+Tjcxqix8P05yWbGn2OWXCKEx89/El8zOp8VErCwH8dl9EpMiQsMwcyAk8/xjIgt8B5XbuG1xWRI0yS+PDbcCjFXk+lWnaf5f6eyUdVnmQsLfMioWKq8xogpzhY0fLAwYEhPifw+r6iisIqIxxwZ7KEYA/ru/XcJta5Ilzff3yVU9vvBu5sTUI42aYlRZFzi1TFRfItx4A+l/7Wmid1U/ISZaQO4G2hxYP4IeRp9kDrS3FnpJCpRWO4HvU9yt2ouD77W1qdpOPgs3GjWh3g7ayBb+XVBCYA70wKzG9iWzyEihKAsfymv0/aU8BR7gyepQuw+xLn48/WiTqSwEvTAE77k2Fv/Cg09hjkZp5LjsLexys4+4nFO92a0M52uejpdvEoRELbR3E9Je0MiyQLNy04JJPFTXp9eTtezb34lhiorUtIZ2z+XtRyWQc6VdkCU0ZxXY0ENEYgg+H9WOcyesbwiJ7plrdPwdPQInpd2gF55UQYYjr/y08Ca8mkvuar32jsVTw2E17K1jGyF8pP7+jGb4hqgJpQkilS3ztRzASftW5P7MvqcSydGjfsQcIuftHOWmm/LYVa9uGXmwPdXwssb4nDGxk9bzOuI8ktmRXsySQXRs0s8kt9LYNAq33mQDcend5kYDerrTD/i0QjufP4tge6RhwnpKKbSxkiYN+b2xj9D/snjIf4y0zJYbjrgHgxh/VVcFPSPC4n3nq/hHGV0dze8+qbugZkvLunmy99WKC47mApbSGAo43v8dw5WUnL/Rk/7aOSbYz/aORqCJEV62da6ee4yLpcf/c2GaOu5ByopkVlVgwF+ejb8Xs0WHxDL/7YBUSdMvBFpTg3XM/xOJq1YcWKJvOeFEbMYrShU6z0Q50hXeX4q5iWWzj3zjMdT0t7fXkSp04n0P/5wzxqSs3xb8wZ8Z1OE7yxsfnmMcugf5P/CaiVJs1KZJGDRHPfmLKKY+YBkSvspH8mcnWLz9myIbUiQHo8dXckAwwFObcVNvbTPW1Tvkmj+Rn56/HgNjT8DpcssBQfOChpNBx0KUqCh/tuexHxvIps8bo1goTyKXMEDBeFxdKjz5wVq+nZU8QsbzeQV6D2qu2GXTfenJiX8Ff3M1ExOp5W4szD+xrjJe+4ua6o+u48VsTDPbSLxaENxH6q49AuNFGPms5yVemKYxCZaFfVe7P0J+6zw/YVvw5qGkvsgt2dar3cOGFlqLBrQupncpxqByObLqiAfY7bMXQQTvAEDS9IlRiinxagXH/FNPDY5UmzUFmdTvI0BnxXRrzlcsjJZ5rrWc/dtz+3j9jv62oc935CTkIpI5FUmtbZ1tJjdwpeOGIe+yVVN1oVq585FILFPwSLlHC4TUM+Q3t3PdnRRFMYzURawKAXMu+2HrlO+g7LVB6EvKQasSUxksEvSms3tK9/5MklrawneB7ukdGGJgDWwvgbFmpSX6mxt/tMbmUw+iJFquphIW1ts0lmCxnVulrarQIwW4LimzAkSL8xme5czfx3n19aHicHVYO5MgKUq622ZH2BmrLW2cp/A4Wtqfx40oL/06JFElSdD5jO9R5ZO1C7hCJmkYAatg+QdWCB8UUW8vGzzMdki37nxm//a/ByC3TFhbkNNgjvpQ6wXaQ6GpEBmFN3NnSc+T7W2Sws1BvOXTDh0IIjwRhzm3vpwgFd9IVHED0UVbxy8v1cKbTrI5sI1vnrcphGT1p1kpulLWF7OBeH7dsh5mOOglxVr6AczBSmn73Arj/5xGix0gYPHMuCs87N4irCgFF7ofR6I0t90tlHLsvvRPpeiahn2z4y82A2tVWzLKzPvLDgV+QATkVma1nvylSAK1KgFNZEoQV1WTCVU7A2KEW8ydBz6cYwKGqrkZ6O7tgkoZEfQKKnYmZXcMRJifnhl0M/0ejLuxIKBVHZLs4si0dhO5WginLvdQf7DD7/JE9/5KyiDhqr4qWPdbTFMgs8JSXYVb9mmp9M8ZCFg5hOvrT # AES_ENCRYPTED_SH
19 | language:
20 | - node_js
21 | node_js:
22 | - "0.10"
23 | - "0.12"
24 | script:
25 | - npm run-script build-ci
26 | # http://docs.travis-ci.com/user/workers/container-based-infrastructure
27 | sudo:
28 | false
29 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: npm start --mongodb-url="$MONGOLAB_URI" --server-port=$PORT
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | swagger-mongodb
2 | ===============
3 | lightweight swagger-ui crud-middleware backed by mongodb
4 |
5 | [](https://www.npmjs.org/package/swagger-mongodb)
6 |
7 |
8 |
9 | # live test-server
10 | [](https://hrku01-swagger-mongodb-beta.herokuapp.com)
11 |
12 |
13 |
14 | # build-status [](https://travis-ci.org/kaizhu256/node-swagger-mongodb)
15 | [](https://travis-ci.org/kaizhu256/node-swagger-mongodb)
16 |
17 | | git-branch : | [master](https://github.com/kaizhu256/node-swagger-mongodb/tree/master) | [beta](https://github.com/kaizhu256/node-swagger-mongodb/tree/beta) | [alpha](https://github.com/kaizhu256/node-swagger-mongodb/tree/alpha)|
18 | |--:|:--|:--|:--|
19 | | test-server : | [](https://hrku01-swagger-mongodb-master.herokuapp.com) | [](https://hrku01-swagger-mongodb-beta.herokuapp.com) | [](https://hrku01-swagger-mongodb-alpha.herokuapp.com)|
20 | | test-report : | [](https://kaizhu256.github.io/node-swagger-mongodb/build..master..travis-ci.org/test-report.html) | [](https://kaizhu256.github.io/node-swagger-mongodb/build..beta..travis-ci.org/test-report.html) | [](https://kaizhu256.github.io/node-swagger-mongodb/build..alpha..travis-ci.org/test-report.html)|
21 | | coverage : | [](https://kaizhu256.github.io/node-swagger-mongodb/build..master..travis-ci.org/coverage.html/index.html) | [](https://kaizhu256.github.io/node-swagger-mongodb/build..beta..travis-ci.org/coverage.html/index.html) | [](https://kaizhu256.github.io/node-swagger-mongodb/build..alpha..travis-ci.org/coverage.html/index.html)|
22 | | build-artifacts : | [](https://github.com/kaizhu256/node-swagger-mongodb/tree/gh-pages/build..master..travis-ci.org) | [](https://github.com/kaizhu256/node-swagger-mongodb/tree/gh-pages/build..beta..travis-ci.org) | [](https://github.com/kaizhu256/node-swagger-mongodb/tree/gh-pages/build..alpha..travis-ci.org)|
23 |
24 | #### master branch
25 | - stable branch
26 | - HEAD should be tagged, npm-published package
27 |
28 | #### beta branch
29 | - semi-stable branch
30 | - HEAD should be latest, npm-published package
31 |
32 | #### alpha branch
33 | - unstable branch
34 | - HEAD is arbitrary
35 | - commit history may be rewritten
36 |
37 |
38 |
39 | # documentation
40 | #### this package requires
41 | - darwin or linux os
42 | - mongodb 2.6 or higher
43 |
44 | #### [api-doc](https://kaizhu256.github.io/node-swagger-mongodb/build/doc.api.html)
45 | [](https://kaizhu256.github.io/node-swagger-mongodb/build/doc.api.html)
46 |
47 |
48 |
49 | # quickstart web example
50 | #### to run this example, follow the instruction in the script below
51 | - example.js
52 |
53 | ```javascript
54 | /*
55 | example.js
56 |
57 | this node script will serve a lightweight swagger-ui crud-api backed by mongodb
58 |
59 | instruction
60 | 1. save this script as example.js
61 | 2. run the shell command:
62 | $ npm install swagger-mongodb && npm_config_server_port=1337 node example.js
63 | 3. open a browser to http://localhost:1337
64 | 4. interact with the swagger-ui crud-api
65 | */
66 |
67 | /*jslint
68 | browser: true,
69 | maxerr: 8,
70 | maxlen: 96,
71 | node: true,
72 | nomen: true,
73 | regexp: true,
74 | stupid: true
75 | */
76 |
77 | (function (local) {
78 | 'use strict';
79 | switch (local.modeJs) {
80 |
81 |
82 |
83 | // run node js-env code
84 | case 'node':
85 | // export local
86 | module.exports = local;
87 | // init assets
88 | local.utility2.cacheDict.assets['/'] = '\n' +
89 | /* jslint-ignore-begin */
90 | '\n' +
91 | '
\n' +
92 | ' \n' +
93 | ' \n' +
94 | ' {{envDict.npm_package_name}} [{{envDict.npm_package_version}}]\n' +
95 | ' \n' +
96 | ' \n' +
97 | ' \n' +
112 | ' {{envDict.npm_config_html_head_extra}}\n' +
113 | '\n' +
114 | '\n' +
115 | ' \n' +
116 | '
loading
\n' +
117 | '
\n' +
118 | ' {{envDict.npm_package_name}} [{{envDict.npm_package_version}}]
\n' +
119 | ' {{envDict.npm_package_description}}
\n' +
120 | ' \n' +
121 | ' \n' +
122 | ' \n' +
123 | ' \n' +
124 | ' \n' +
125 | ' \n' +
126 | ' \n' +
127 | ' \n' +
128 | ' \n' +
147 | ' {{envDict.npm_config_html_body_extra}}\n' +
148 | '\n' +
149 | /* jslint-ignore-end */
150 | '\n';
151 | local.utility2.cacheDict.assets['/'] = local.utility2.stringFormat(
152 | local.utility2.cacheDict.assets['/'],
153 | { envDict: local.utility2.envDict },
154 | ''
155 | );
156 | local.utility2.cacheDict.assets['/assets/example.js'] =
157 | local.utility2.istanbul_lite.instrumentSync(
158 | local.fs.readFileSync(__dirname + '/example.js', 'utf8'),
159 | __dirname + '/example.js'
160 | );
161 | local.utility2.cacheDict.assets['/test/test.js'] =
162 | local.utility2.istanbul_lite.instrumentInPackage(
163 | local.fs.readFileSync(local.swmg.__dirname + '/test.js', 'utf8'),
164 | local.swmg.__dirname + '/test.js',
165 | 'swagger-mongodb'
166 | );
167 | // init mongodb-client
168 | local.utility2.onReady.counter += 1;
169 | local.utility2.taskRunOrSubscribe({
170 | key: 'swagger-mongodb.mongodbConnect',
171 | onTask: function (onError) {
172 | local.mongodb.MongoClient.connect(
173 | local.utility2.envDict.npm_config_mongodb_url ||
174 | 'mongodb://localhost:27017/test',
175 | function (error, db) {
176 | // validate no error occurred
177 | local.utility2.assert(!error, error);
178 | local.swmg.db = db;
179 | onError();
180 | local.utility2.onReady();
181 | }
182 | );
183 | }
184 | });
185 | // init middleware
186 | local.middleware = local.utility2.middlewareGroupCreate([
187 | // init pre-middleware
188 | local.utility2.middlewareInit,
189 | // init cached-assets middleware
190 | local.utility2.middlewareAssetsCached,
191 | // init http-body-get middleware
192 | local.utility2.middlewareBodyGet,
193 | // init http-body-parse-upload middleware
194 | function (request, response, nextMiddleware) {
195 | var boundary, bodyText;
196 | // jslint-hack
197 | local.utility2.nop(response);
198 | local.utility2.testTryCatch(function () {
199 | if ((request.headers['content-type'] || '')
200 | .indexOf('multipart/form-data') !== 0) {
201 | nextMiddleware();
202 | return;
203 | }
204 | boundary =
205 | '--' + (/boundary=(.*)/).exec(request.headers['content-type'])[1];
206 | request.swmgBodyParsed = {};
207 | bodyText = String(request.bodyRaw);
208 | bodyText.split(boundary).slice(1, -1).forEach(function (part) {
209 | request.swmgBodyParsed[
210 | (/\bname="([^"]*)/).exec(part)[1]
211 | ] = part.split('\r\n\r\n').slice(1).join('\r\n\r\n').slice(0, -2);
212 | });
213 | // set file
214 | bodyText.replace('\r\n\r\n', function (match0, ii) {
215 | // jslint-hack
216 | local.utility2.nop(match0);
217 | request.swmgBodyParsed.file = request.bodyRaw
218 | .slice(ii + 4, -(boundary.length + 6))
219 | .toString('base64');
220 | });
221 | request.swmgBodyParsed.file = request.bodyRaw
222 | .slice(bodyText.lastIndexOf('\r\n\r\n') + 4, -(boundary.length + 6))
223 | .toString('base64');
224 | // set filename
225 | request.swmgBodyParsed.filename = (/\bfilename="([^"]+)/).exec(bodyText);
226 | request.swmgBodyParsed.filename =
227 | request.swmgBodyParsed.filename &&
228 | request.swmgBodyParsed.filename[1];
229 | nextMiddleware();
230 | }, nextMiddleware);
231 | },
232 | // init http-body-parse middleware
233 | local.swmg.middlewareBodyParse,
234 | // init swagger pre-middleware
235 | function (request, response, nextMiddleware) {
236 | // jslint-hack
237 | local.utility2.nop(request);
238 | // enable cors
239 | // http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
240 | response.setHeader(
241 | 'Access-Control-Allow-Methods',
242 | 'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'
243 | );
244 | response.setHeader('Access-Control-Allow-Origin', '*');
245 | // init content-type
246 | response.setHeader('Content-Type', 'application/json; charset=UTF-8');
247 | nextMiddleware();
248 | },
249 | // init swagger middleware
250 | local.swmg.middlewareSwagger
251 | ]);
252 | // init error-middleware
253 | local.middlewareError = local.swmg.middlewareError;
254 | // init petstore-api
255 | (function () {
256 | var methodPath, options, schema;
257 | options = local.utility2.jsonCopy(require(local.swmg.local
258 | .swagger_ui_lite.__dirname + '/swagger.json'));
259 | options = {
260 | definitions: options.definitions,
261 | paths: options.paths,
262 | tags: options.tags
263 | };
264 | // remove unused properties
265 | delete options.definitions.ApiResponse;
266 | // init schema
267 | Object.keys(options.definitions).forEach(function (schemaName) {
268 | schema = options.definitions[schemaName];
269 | // init id
270 | schema.properties.id = { type: 'string' };
271 | schema['x-inheritList'] = [{ $ref: '#/definitions/JsonapiResource' }];
272 | });
273 | local.utility2.objectSetOverride(options, {
274 | definitions: {
275 | // init Pet schema
276 | Pet: {
277 | // drop collection on init
278 | _collectionDrop: true,
279 | // upsert fixtures
280 | _collectionFixtureList: [{
281 | id: 'pet0',
282 | name: 'birdie',
283 | photoUrls: [],
284 | status: 'available',
285 | tags: [{ name: 'bird'}]
286 | }, {
287 | id: 'pet1',
288 | name: 'kittie',
289 | status: 'pending',
290 | photoUrls: [],
291 | tags: [{ name: 'cat'}]
292 | }, {
293 | id: 'pet2',
294 | name: 'doggie',
295 | photoUrls: [],
296 | status: 'sold',
297 | tags: [{ name: 'dog'}]
298 | }],
299 | _collectionName: 'SwmgPet'
300 | },
301 | // init Order schema
302 | Order: {
303 | // create index
304 | _collectionCreateIndexList: [{
305 | key: { status: 1 },
306 | name: 'status_1'
307 | }],
308 | // drop collection on init
309 | _collectionDrop: true,
310 | // upsert fixtures
311 | _collectionFixtureList: [{
312 | id: 'order0',
313 | status: 'available'
314 | }, {
315 | id: 'order1',
316 | status: 'pending'
317 | }, {
318 | id: 'order2',
319 | status: 'sold'
320 | }],
321 | _collectionName: 'SwmgOrder',
322 | properties: {
323 | petId: { type: 'string' }
324 | }
325 | },
326 | // init User schema
327 | User: {
328 | // create index
329 | _collectionCreateIndexList: [{
330 | key: { username: 1 },
331 | name: 'username_1',
332 | unique: true
333 | }],
334 | // drop collection on init
335 | _collectionDrop: true,
336 | // upsert fixtures
337 | _collectionFixtureList: [{
338 | email: 'john@doe.com',
339 | firstName: 'john',
340 | id: 'user0',
341 | lastName: 'doe',
342 | password: 'hello',
343 | phone: '1234-5678',
344 | username: 'john.doe'
345 | }, {
346 | email: 'jane@doe.com',
347 | firstName: 'jane',
348 | id: 'user1',
349 | lastName: 'doe',
350 | password: 'bye',
351 | phone: '8765-4321',
352 | username: 'jane.doe'
353 | }],
354 | _collectionName: 'SwmgUser'
355 | }
356 | },
357 | // init crud-api
358 | paths: {
359 | '/pet/crudGetByQueryMany': { get: {
360 | _collectionName: 'SwmgPet',
361 | _crudApi: 'pet',
362 | _schemaName: 'Pet',
363 | operationId: 'crudGetByQueryMany',
364 | tags: ['pet']
365 | } },
366 | '/store/crudGetByQueryMany': { get: {
367 | _collectionName: 'SwmgOrder',
368 | _crudApi: 'store',
369 | _schemaName: 'Order',
370 | operationId: 'crudGetByQueryMany',
371 | tags: ['store']
372 | } },
373 | '/user/crudGetByQueryMany': { get: {
374 | _collectionName: 'SwmgUser',
375 | _crudApi: 'user',
376 | _schemaName: 'User',
377 | operationId: 'crudGetByQueryMany',
378 | tags: ['user']
379 | } }
380 | }
381 | }, 4);
382 | // transform petstore-api to swagger-mongodb's crud-api
383 | Object.keys(options.paths).forEach(function (path) {
384 | Object.keys(options.paths[path]).forEach(function (method) {
385 | methodPath = options.paths[path][method];
386 | // init methodPath._schemaName
387 | switch (path.split('/')[1]) {
388 | case 'pet':
389 | methodPath._schemaName = 'Pet';
390 | break;
391 | case 'store':
392 | methodPath._schemaName = 'Order';
393 | break;
394 | case 'user':
395 | methodPath._schemaName = 'User';
396 | break;
397 | }
398 | methodPath._collectionName = 'Swmg' + methodPath._schemaName;
399 | delete methodPath.produces;
400 | delete methodPath.responses;
401 | delete methodPath.security;
402 | // init jsonapi response
403 | local.utility2.objectSetDefault(methodPath, { responses: {
404 | 200: {
405 | description: '200 ok - http://jsonapi.org/format' +
406 | '/#document-structure-top-level',
407 | schema: { $ref: '#/definitions/JsonapiResponse{{_schemaName}}' }
408 | }
409 | } }, 2);
410 | // init crudCreateMany / crudCreateOne / crudDeleteByIdOne / crudGetByIdOne
411 | switch (methodPath.operationId) {
412 | case 'addPet':
413 | case 'createUser':
414 | case 'placeOrder':
415 | methodPath.operationId = 'crudCreateOne';
416 | break;
417 | case 'createUsersWithArrayInput':
418 | case 'createUsersWithListInput':
419 | methodPath.operationId = 'crudCreateMany';
420 | break;
421 | case 'deleteOrder':
422 | case 'deletePet':
423 | case 'deleteUser':
424 | methodPath.operationId = 'crudDeleteByIdOne';
425 | break;
426 | case 'getOrderById':
427 | case 'getPetById':
428 | case 'getUserByName':
429 | methodPath.operationId = 'crudGetByIdOne';
430 | break;
431 | }
432 | // init id
433 | (methodPath.parameters || []).forEach(function (paramDef) {
434 | switch (paramDef.name) {
435 | case 'orderId':
436 | case 'petId':
437 | delete paramDef.format;
438 | paramDef.type = 'string';
439 | break;
440 | }
441 | });
442 | });
443 | });
444 | local.swmg.apiUpdate(options);
445 | }());
446 | // init petstore-middleware
447 | local.middleware.middlewareList.push(function (request, response, nextMiddleware) {
448 | var modeNext, onNext, options;
449 | modeNext = 0;
450 | onNext = function (error, data) {
451 | local.utility2.testTryCatch(function () {
452 | modeNext = error
453 | ? Infinity
454 | : modeNext + 1;
455 | switch (modeNext) {
456 | case 1:
457 | // init id
458 | ((request.swmgMethodPath && request.swmgMethodPath.parameters) || [
459 | ]).forEach(function (paramDef) {
460 | switch (paramDef.name) {
461 | case 'orderId':
462 | case 'petId':
463 | request.swmgParamDict.id = request.swmgParamDict[paramDef.name];
464 | break;
465 | }
466 | });
467 | // init options
468 | if (request.swmgMethodPath) {
469 | options = {
470 | collectionName: request.swmgMethodPath._collectionName,
471 | data: request.swmgParamDict,
472 | operationId: request.swmgMethodPath.operationId,
473 | paramDefList: request.swmgMethodPath.parameters,
474 | schemaName: request.swmgMethodPath._schemaName
475 | };
476 | }
477 | switch (request.swmgPathname) {
478 | // handle pet request
479 | case 'DELETE /pet/':
480 | case 'GET /pet/':
481 | case 'POST /pet':
482 | local.swmg._crudApi(options, onNext);
483 | break;
484 | case 'GET /pet/findByStatus':
485 | options.operationId = 'crudGetByQueryMany';
486 | options.data.fields = '{}';
487 | options.data.hint = '{}';
488 | options.data.limit = 100;
489 | options.data.query = '{"status":{"$in":' +
490 | JSON.stringify(options.data.status) + '}}';
491 | options.data.skip = 0;
492 | options.data.sort = '{"_timeModified":-1}';
493 | local.swmg._crudApi(options, onNext);
494 | break;
495 | case 'GET /pet/findByTags':
496 | options.operationId = 'crudGetByQueryMany';
497 | options.data.fields = '{}';
498 | options.data.hint = '{}';
499 | options.data.limit = 100;
500 | options.data.query = '{"status":{"$in":' +
501 | JSON.stringify(options.data.tags) + '}}';
502 | options.data.skip = 0;
503 | options.data.sort = '{"_timeModified":-1}';
504 | options.paramDefList[0].default = 'bird,cat,dog';
505 | local.swmg._crudApi(options, onNext);
506 | break;
507 | case 'POST /pet/':
508 | options.data.upsert = true;
509 | options.data.body = {
510 | id: options.data.id,
511 | name: options.data.name,
512 | status: options.data.status
513 | };
514 | options.operationId = 'crudUpdateOne';
515 | local.swmg._crudApi(options, onNext);
516 | break;
517 | case 'POST /pet//':
518 | options.data.body = {
519 | additionalMetadata: options.data.additionalMetadata,
520 | file: options.data.file,
521 | filename:
522 | request.swmgBodyParsed && request.swmgBodyParsed.filename,
523 | id: options.id
524 | };
525 | options.data.upsert = true;
526 | options.operationId = 'crudUpdateOne';
527 | local.swmg._crudApi(options, onNext);
528 | break;
529 | case 'PUT /pet':
530 | options.data.upsert = true;
531 | options.operationId = 'crudReplaceOne';
532 | local.swmg._crudApi(options, onNext);
533 | break;
534 | // handle store request
535 | case 'DELETE /store/order/':
536 | case 'GET /store/order/':
537 | case 'POST /store/order':
538 | local.swmg._crudApi(options, onNext);
539 | break;
540 | case 'GET /store/inventory':
541 | options.data = { body: [{
542 | $group: { _id: '$status', total: { $sum: 1} }
543 | }, {
544 | $project: { _id: 0, status: '$_id', total: '$total' }
545 | }]};
546 | options.operationId = 'crudAggregateMany';
547 | local.swmg._crudApi(options, onNext);
548 | break;
549 | // handle user request
550 | case 'DELETE /user/':
551 | case 'GET /user/':
552 | case 'POST /user/createWithArray':
553 | case 'POST /user/createWithList':
554 | options.optionsId = { username: request.swmgParamDict.username};
555 | local.swmg._crudApi(options, onNext);
556 | break;
557 | case 'POST /user':
558 | options.data.username = options.data.body.username;
559 | options.optionsId = { username: request.swmgParamDict.username};
560 | local.swmg._crudApi(options, onNext);
561 | break;
562 | case 'PUT /user/':
563 | options.data.body.username = options.data.username;
564 | options.data.upsert = true;
565 | options.operationId = 'crudReplaceOne';
566 | options.optionsId = { username: request.swmgParamDict.username};
567 | local.swmg._crudApi(options, onNext);
568 | break;
569 | default:
570 | nextMiddleware();
571 | }
572 | break;
573 | default:
574 | // validate no error occurred
575 | local.utility2.assert(!error, error);
576 | // respond with json-object
577 | response.end(JSON.stringify(data));
578 | }
579 | }, nextMiddleware);
580 | };
581 | onNext();
582 | });
583 | // run server-test
584 | local.utility2.testRunServer(local);
585 | break;
586 | }
587 | }((function () {
588 | 'use strict';
589 | var local;
590 |
591 |
592 |
593 | // run shared js-env code
594 | (function () {
595 | // init local
596 | local = {};
597 | // init js-env
598 | local.modeJs = (function () {
599 | try {
600 | return module.exports &&
601 | typeof process.versions.node === 'string' &&
602 | typeof require('http').createServer === 'function' &&
603 | 'node';
604 | } catch (errorCaughtNode) {
605 | return typeof navigator.userAgent === 'string' &&
606 | typeof document.querySelector('body') === 'object' &&
607 | 'browser';
608 | }
609 | }());
610 | // init global
611 | local.global = local.modeJs === 'browser'
612 | ? window
613 | : global;
614 | // export local
615 | local.global.local = local;
616 | // init swagger-mongodb
617 | local.swmg = local.modeJs === 'browser'
618 | ? window.swmg
619 | : require('swagger-mongodb');
620 | // import swmg.local
621 | Object.keys(local.swmg.local).forEach(function (key) {
622 | local[key] = local[key] || local.swmg.local[key];
623 | });
624 | // init utility2
625 | local.utility2 = local.swmg.local.utility2;
626 | // init onReady
627 | local.utility2.onReadyInit();
628 | }());
629 | return local;
630 | }())));
631 | ```
632 |
633 | #### output from shell
634 | [](https://travis-ci.org/kaizhu256/node-swagger-mongodb)
635 |
636 | #### output from phantomjs-lite
637 | [](https://hrku01-swagger-mongodb-beta.herokuapp.com)
638 |
639 |
640 |
641 | # npm-dependencies
642 | - [mongodb-minimal](https://www.npmjs.com/package/mongodb-minimal)
643 | - [swagger-ui-lite](https://www.npmjs.com/package/swagger-ui-lite)
644 | - [utility2](https://www.npmjs.com/package/utility2)
645 |
646 |
647 |
648 | # package-listing
649 | [](https://github.com/kaizhu256/node-swagger-mongodb)
650 |
651 |
652 |
653 | # package.json
654 | ```json
655 | {
656 | "author": "kai zhu ",
657 | "bin": { "swagger-mongodb": "index.js" },
658 | "dependencies": {
659 | "mongodb-minimal": "2015.8.1",
660 | "swagger-ui-lite": "2015.6.2",
661 | "utility2": "~2015.8.5"
662 | },
663 | "description": "lightweight swagger-ui crud-middleware backed by mongodb",
664 | "devDependencies": {
665 | "phantomjs-lite": "2015.7.1"
666 | },
667 | "engines": { "node": ">=0.10 <=0.12" },
668 | "keywords": [
669 | "api",
670 | "browser",
671 | "cms", "crud",
672 | "mongo", "mongodb",
673 | "swagger", "swagger-ui",
674 | "web"
675 | ],
676 | "license": "MIT",
677 | "name": "swagger-mongodb",
678 | "os": ["darwin", "linux"],
679 | "repository" : {
680 | "type" : "git",
681 | "url" : "https://github.com/kaizhu256/node-swagger-mongodb.git"
682 | },
683 | "scripts": {
684 | "build-ci": "node_modules/.bin/utility2 shRun shReadmeBuild",
685 | "build-doc": "node_modules/.bin/utility2 shRun shReadmeExportPackageJson && \
686 | node_modules/.bin/utility2 shRun shDocApiCreate \"{ \
687 | exampleFileList:['example.js','test.js','index.js'], \
688 | moduleDict:{'swagger-mongodb':{aliasList:['swmg'],exports:require('./index.js')}} \
689 | }\"",
690 | "start": "npm_config_mode_auto_restart=1 node_modules/.bin/utility2 shRun node test.js",
691 | "test": "node_modules/.bin/utility2 shRun shReadmeExportPackageJson && \
692 | node_modules/.bin/utility2 test test.js"
693 | },
694 | "version": "2015.8.3"
695 | }
696 | ```
697 |
698 |
699 |
700 | # todo
701 | - add logging feature
702 | - rename delete to remove for naming consistency
703 | - migrate to travis-ci docker container build
704 | - add cached param for crudGetByQueryMany
705 | - add SwmgUserLoginTokenCapped
706 | - re-enable user login/logout
707 | - test /user/login and /user/logout
708 | - add max / min validation
709 | - none
710 |
711 |
712 |
713 | # change since af87c5b9
714 | - npm publish 2015.8.3
715 | - lockdown npm dependencies
716 | - none
717 |
718 |
719 |
720 | # changelog of last 50 commits
721 | [](https://github.com/kaizhu256/node-swagger-mongodb/commits)
722 |
723 |
724 |
725 | # internal build-script
726 | - build.sh
727 |
728 | ```shell
729 | # build.sh
730 |
731 | # this shell script will run the build for this package
732 |
733 | shBuild() {
734 | # this function will run the main build
735 | local TEST_URL || return $?
736 |
737 | # init env
738 | export npm_config_mode_slimerjs=1 || return $?
739 | . node_modules/.bin/utility2 && shInit || return $?
740 |
741 | # run npm-test on published package
742 | shRun shNpmTestPublished || return $?
743 |
744 | # test example js script
745 | export npm_config_timeout_exit=10000 || return $?
746 | MODE_BUILD=testExampleJs shRunScreenCapture shReadmeTestJs example.js || return $?
747 | unset npm_config_timeout_exit || return $?
748 |
749 | # run npm-test
750 | MODE_BUILD=npmTest shRunScreenCapture npm test || return $?
751 |
752 | # create api-doc
753 | npm run-script build-doc || return $?
754 |
755 | # if running legacy-node, then do not continue
756 | [ "$(node --version)" \< "v0.12" ] && return
757 |
758 | # deploy app to heroku
759 | shRun shHerokuDeploy hrku01-$npm_package_name-$CI_BRANCH || return $?
760 |
761 | # test deployed app to heroku
762 | if [ "$CI_BRANCH" = alpha ] ||
763 | [ "$CI_BRANCH" = beta ] ||
764 | [ "$CI_BRANCH" = master ]
765 | then
766 | TEST_URL="https://hrku01-$npm_package_name-$CI_BRANCH.herokuapp.com" || return $?
767 | TEST_URL="$TEST_URL?modeTest=phantom&timeExit={{timeExit}}" || return $?
768 | MODE_BUILD=herokuTest shPhantomTest "$TEST_URL" || return $?
769 | fi
770 | }
771 | shBuild
772 |
773 | # save exit-code
774 | EXIT_CODE=$?
775 | # create package-listing
776 | MODE_BUILD=gitLsTree shRunScreenCapture shGitLsTree || exit $?
777 | # create recent changelog of last 50 commits
778 | MODE_BUILD=gitLog shRunScreenCapture git log -50 --pretty="%ai\u000a%B" || exit $?
779 | # if running legacy-node, then do not continue
780 | [ "$(node --version)" \< "v0.12" ] && exit $EXIT_CODE
781 | # upload build-artifacts to github, and if number of commits > 16, then squash older commits
782 | COMMIT_LIMIT=16 shBuildGithubUpload || exit $?
783 | exit $EXIT_CODE
784 | ```
785 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /*jslint
2 | bitwise: true,
3 | browser: true,
4 | maxerr: 8,
5 | maxlen: 96,
6 | node: true,
7 | nomen: true,
8 | regexp: true,
9 | stupid: true
10 | */
11 | (function (local) {
12 | 'use strict';
13 |
14 |
15 |
16 | // run shared js-env code
17 | (function () {
18 | local.swmg.normalizeIdMongodb = function (data) {
19 | /*
20 | * this function will recursively convert the property id to _id
21 | */
22 | local.utility2.objectTraverse(data, function (element) {
23 | if (element && element.id) {
24 | element._id = element._id || element.id;
25 | delete element.id;
26 | }
27 | });
28 | return data;
29 | };
30 |
31 | local.swmg.normalizeIdSwagger = function (data) {
32 | /*
33 | * this function will recursively convert the property _id to id
34 | */
35 | local.utility2.objectTraverse(data, function (element) {
36 | if (element && element._id) {
37 | element.id = element.id || element._id;
38 | delete element._id;
39 | }
40 | });
41 | return data;
42 | };
43 |
44 | local.swmg.normalizeParamDictSwagger = function (data, methodPath) {
45 | /*
46 | * this function will parse the data according to methodPath.parameters
47 | */
48 | var tmp;
49 | methodPath.parameters.forEach(function (paramDef) {
50 | tmp = data[paramDef.name];
51 | // init default value
52 | if (tmp === undefined) {
53 | // jsonCopy object to prevent side-effects
54 | data[paramDef.name] = local.utility2.jsonCopy(paramDef.default);
55 | }
56 | // parse csv array
57 | if (paramDef.type === 'array' &&
58 | paramDef.collectionFormat &&
59 | typeof tmp === 'string') {
60 | switch (paramDef.collectionFormat) {
61 | case 'csv':
62 | tmp = tmp.split(',');
63 | break;
64 | case 'pipes':
65 | tmp = tmp.split('|');
66 | break;
67 | case 'ssv':
68 | tmp = tmp.split(' ');
69 | break;
70 | case 'tsv':
71 | tmp = tmp.split('\t');
72 | break;
73 | }
74 | }
75 | // JSON.parse swmgParamDict
76 | if (paramDef.type !== 'string' &&
77 | (typeof tmp === 'string' ||
78 | (local.modeJs === 'node' && Buffer.isBuffer(tmp)))) {
79 | try {
80 | tmp = JSON.parse(tmp);
81 | } catch (ignore) {
82 | }
83 | }
84 | data[paramDef.name] = tmp;
85 | });
86 | return data;
87 | };
88 |
89 | local.swmg.onErrorJsonapi = function (options, onError) {
90 | /*
91 | * this function will convert the error and data to jsonapi format,
92 | * http://jsonapi.org/format/#errors
93 | * and pass them to onError
94 | */
95 | return function (error, data) {
96 | if (typeof options === 'function') {
97 | options = options();
98 | }
99 | options = options || {};
100 | options.id = options.id || local.utility2.uuidTime();
101 | // handle error
102 | if (error) {
103 | if (error.errors && Array.isArray(error.errors) && error.errors[0]) {
104 | onError(error);
105 | return;
106 | }
107 | // prepend mongodb-errmsg
108 | if (error.errmsg) {
109 | local.utility2.errorMessagePrepend(error, error.errmsg + '\n');
110 | }
111 | options.message = error.message;
112 | options.stack = error.stack;
113 | options.statusCode = Number(error.statusCode) || 500;
114 | options.errors = local.utility2
115 | .jsonCopy(local.swmg.normalizeIdSwagger(error));
116 | local.utility2.objectSetDefault(options.errors, {
117 | code: options.statusCode,
118 | detail: options.stack,
119 | id: options.id,
120 | message: options.message
121 | });
122 | options.errors.code = String(options.errors.code);
123 | options.errors.detail = String(options.errors.detail);
124 | options.errors.id = String(options.errors.id);
125 | options.errors.message = String(options.errors.message);
126 | options.errors = [options.errors];
127 | onError(options);
128 | return;
129 | }
130 | // handle data
131 | options.data = data;
132 | local.swmg.normalizeIdSwagger(options);
133 | if (!Array.isArray(options.data)) {
134 | options.data = [options.data];
135 | }
136 | onError(null, options);
137 | };
138 | };
139 |
140 | local.swmg.schemaDereference = function ($ref) {
141 | /*
142 | * this function will try to dereference the schema from $ref
143 | */
144 | try {
145 | return ((local.global.swaggerUi &&
146 | local.global.swaggerUi.api &&
147 | local.global.swaggerUi.api.swaggerJson) ||
148 | local.swmg.swaggerJson)
149 | .definitions[(/^\#\/definitions\/(\w+)$/).exec($ref)[1]];
150 | } catch (ignore) {
151 | }
152 | };
153 |
154 | local.swmg.validateByParamDefList = function (options) {
155 | /*
156 | * this function will validate options.data against options.paramDefList
157 | */
158 | var data, key;
159 | try {
160 | data = options.data;
161 | // validate data
162 | local.utility2.assert(data && typeof data === 'object', data);
163 | (options.paramDefList || []).forEach(function (paramDef) {
164 | key = paramDef.name;
165 | local.swmg.validateByPropertyDef({
166 | data: data[key],
167 | key: key,
168 | propertyDef: paramDef,
169 | required: paramDef.required
170 | });
171 | });
172 | } catch (errorCaught) {
173 | local.utility2.errorMessagePrepend(errorCaught, '"' + options.key + '.' + key +
174 | '" - ');
175 | throw errorCaught;
176 | }
177 | };
178 |
179 | local.swmg.validateByPropertyDef = function (options) {
180 | /*
181 | * this function will validate options.data against options.propertyDef
182 | */
183 | var assert, data, propertyDef, tmp;
184 | assert = function (valid) {
185 | if (!valid) {
186 | throw new Error('invalid "' + options.key + ':' + (propertyDef.format ||
187 | propertyDef.type) + '" property - ' + JSON.stringify(data));
188 | }
189 | };
190 | data = options.data;
191 | propertyDef = options.propertyDef;
192 | // validate undefined data
193 | if (data === null || data === undefined) {
194 | if (options.required) {
195 | throw new Error('required "' + options.key + ':' + (propertyDef.format ||
196 | propertyDef.type) + '" property cannot be null or undefined');
197 | }
198 | return;
199 | }
200 | // validate schema
201 | tmp = propertyDef.$ref || (propertyDef.schema && propertyDef.schema.$ref);
202 | if (tmp) {
203 | local.swmg.validateBySchema({
204 | circularList: options.circularList,
205 | data: data,
206 | key: tmp,
207 | schema: local.swmg.schemaDereference(tmp)
208 | });
209 | return;
210 | }
211 | // init circularList
212 | if (data && typeof data === 'object') {
213 | options.circularList = options.circularList || [];
214 | if (options.circularList.indexOf(data) >= 0) {
215 | return;
216 | }
217 | options.circularList.push(data);
218 | }
219 | // validate propertyDef embedded in propertyDef.schema.type
220 | if (!propertyDef.type && propertyDef.schema && propertyDef.schema.type) {
221 | propertyDef = propertyDef.schema;
222 | }
223 | // validate propertyDef.type
224 | // https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md
225 | // #data-types
226 | switch (propertyDef.type) {
227 | case 'array':
228 | assert(Array.isArray(data) && propertyDef.items);
229 | // recurse - validate elements in list
230 | data.forEach(function (element) {
231 | local.swmg.validateByPropertyDef({
232 | circularList: options.circularList,
233 | data: element,
234 | key: options.key,
235 | propertyDef: propertyDef.items
236 | });
237 | });
238 | break;
239 | case 'boolean':
240 | assert(typeof data === 'boolean');
241 | break;
242 | case 'integer':
243 | assert(typeof data === 'number' && isFinite(data) && (data | 0) === data);
244 | switch (propertyDef.format) {
245 | case 'int32':
246 | case 'int64':
247 | break;
248 | }
249 | break;
250 | case 'number':
251 | assert(typeof data === 'number' && isFinite(data));
252 | switch (propertyDef.format) {
253 | case 'double':
254 | case 'float':
255 | break;
256 | }
257 | break;
258 | case 'object':
259 | assert(typeof data === 'object');
260 | break;
261 | case 'string':
262 | assert(typeof data === 'string');
263 | switch (propertyDef.format) {
264 | // https://github.com/swagger-api/swagger-spec/issues/50
265 | case 'byte':
266 | assert(!(/[^\n\r\+\/0-9\=A-Za-z]/).test(data));
267 | break;
268 | case 'date':
269 | tmp = new Date(data);
270 | assert(tmp.getTime() && data === tmp.toISOString().slice(0, 10));
271 | break;
272 | case 'date-time':
273 | tmp = new Date(data);
274 | assert(tmp.getTime() &&
275 | data.slice(0, 19) === tmp.toISOString().slice(0, 19));
276 | break;
277 | case 'email':
278 | assert(local.utility2.regexpEmailValidate.test(data));
279 | break;
280 | case 'json':
281 | try {
282 | JSON.parse(data);
283 | } catch (errorCaught) {
284 | assert(null);
285 | }
286 | break;
287 | }
288 | break;
289 | }
290 | };
291 |
292 | local.swmg.validateBySchema = function (options) {
293 | /*
294 | * this function will validate options.data against options.schema
295 | */
296 | var data, key, schema;
297 | try {
298 | data = options.data;
299 | // init circularList
300 | if (data && typeof data === 'object') {
301 | options.circularList = options.circularList || [];
302 | if (options.circularList.indexOf(data) >= 0) {
303 | return;
304 | }
305 | options.circularList.push(data);
306 | }
307 | // validate data
308 | switch (options.key) {
309 | // ignore undefined schema
310 | case '#/definitions/Undefined':
311 | return;
312 | }
313 | local.utility2.assert(data && typeof data === 'object', 'invalid data ' + data);
314 | schema = options.schema;
315 | // validate schema
316 | local.utility2.assert(
317 | schema && typeof schema === 'object',
318 | 'invalid schema ' + schema
319 | );
320 | Object.keys(schema.properties || {}).forEach(function (_) {
321 | key = _;
322 | local.swmg.validateByPropertyDef({
323 | circularList: options.circularList,
324 | data: data[key],
325 | depth: options.depth - 1,
326 | key: key,
327 | propertyDef: schema.properties[key],
328 | required: schema.required && schema.required.indexOf(key) >= 0
329 | });
330 | });
331 | } catch (errorCaught) {
332 | local.utility2.errorMessagePrepend(errorCaught, '"' + options.key + '.' + key +
333 | '" - ');
334 | throw errorCaught;
335 | }
336 | };
337 |
338 | local.swmg.validateBySwagger = function (options) {
339 | /*
340 | * this function will validate the entire swagger json object
341 | */
342 | local.swagger_tools.v2.validate(
343 | // jsonCopy object to prevent side-effects
344 | local.utility2.jsonCopy(options),
345 | function (error, result) {
346 | // validate no error occurred
347 | local.utility2.assert(!error, error);
348 | ['errors', 'undefined', 'warnings'].forEach(function (errorType) {
349 | ((result && result[errorType]) || [
350 | ]).slice(0, 8).forEach(function (element) {
351 | console.error('swagger schema - ' + errorType.slice(0, -1) + ' - ' +
352 | element.code + ' - ' + element.message + ' - ' +
353 | JSON.stringify(element.path));
354 | });
355 | });
356 | error = result && result.errors && result.errors[0];
357 | // validate no error occurred
358 | local.utility2.assert(!error, new Error(error && error.message));
359 | }
360 | );
361 | };
362 | }());
363 | switch (local.modeJs) {
364 |
365 |
366 |
367 | // run node js-env code
368 | case 'node':
369 | local.swmg._crudApi = function (options, onError) {
370 | /*
371 | * this function will run the low-level crud-api on the given options.data
372 | */
373 | var modeNext, onNext;
374 | options.onError2 = local.swmg.onErrorJsonapi(function () {
375 | return options.response;
376 | }, onError);
377 | modeNext = 0;
378 | onNext = local.utility2.onErrorWithStack(function (error, data) {
379 | local.utility2.testTryCatch(function () {
380 | modeNext = error
381 | ? Infinity
382 | : modeNext + 1;
383 | switch (modeNext) {
384 | case 1:
385 | // jsonCopy object to prevent side-effects
386 | options.data = local.utility2.jsonCopy(options.data);
387 | // validate params
388 | local.swmg.validateByParamDefList({
389 | data: options.data,
390 | key: options.schemaName + '.' + options.operationId,
391 | paramDefList: options.paramDefList
392 | });
393 | // convert id to mongodb format
394 | local.swmg.normalizeIdMongodb(options);
395 | // init body
396 | options.data.body = options.data.body || {};
397 | // init id
398 | options.data._id = options.data.body._id =
399 | String(options.data.body._id ||
400 | options.data._id ||
401 | local.utility2.uuidTime());
402 | options.optionsId = options.optionsId || { _id: options.data._id };
403 | options.optionsIdKey = Object.keys(options.optionsId)[0];
404 | // init collection
405 | options.collection =
406 | local.swmg.cacheDict.collection[options.collectionName];
407 | // init response
408 | options.response = { _id: options.data._id };
409 | // init _timeCreated
410 | switch (options.operationId) {
411 | case 'crudUpdateOne':
412 | options.collection
413 | .findOne(options.optionsId, { _timeCreated: 1 }, onNext);
414 | return;
415 | }
416 | onNext();
417 | break;
418 | case 2:
419 | // init _timeCreated and _timeModified
420 | options.tmp = data && data._timeCreated;
421 | switch (options.operationId) {
422 | case 'crudCreateOne':
423 | case 'crudReplaceOne':
424 | options.data.body._timeCreated =
425 | options.data.body._timeModified = new Date().toISOString();
426 | break;
427 | case 'crudUpdateOne':
428 | options.data.body._timeCreated =
429 | options.data.body._timeModified = new Date().toISOString();
430 | if (options.tmp < options.data.body._timeCreated &&
431 | new Date(options.tmp).getTime()) {
432 | options.data.body._timeCreated = options.tmp;
433 | }
434 | break;
435 | }
436 | switch (options.operationId) {
437 | case 'crudAggregateMany':
438 | // aggregate data
439 | options.collection.aggregate(local.swmg
440 | .normalizeIdMongodb(options.data.body), onNext);
441 | break;
442 | case 'crudCountByQueryOne':
443 | // count data
444 | options.collection.count(local.swmg
445 | .normalizeIdMongodb(JSON.parse(options.data.query)), onNext);
446 | break;
447 | case 'crudCreateOne':
448 | // insert data
449 | options.collection.insert(options.data.body, onNext);
450 | break;
451 | case 'crudDeleteByIdOne':
452 | // delete data
453 | options.collection.removeOne(options.optionsId, onNext);
454 | break;
455 | case 'crudDeleteByQueryMany':
456 | // delete data
457 | options.collection.remove(local.swmg
458 | .normalizeIdMongodb(JSON.parse(options.data.query)), onNext);
459 | break;
460 | case 'crudExistsByIdOne':
461 | // find data
462 | options.collection.findOne(options.optionsId, { _id: 1 }, onNext);
463 | break;
464 | case 'crudGetByIdOne':
465 | // find data
466 | options.collection.findOne(options.optionsId, onNext);
467 | break;
468 | case 'crudGetByQueryMany':
469 | data = local.swmg.normalizeIdMongodb([
470 | JSON.parse(options.data.query),
471 | JSON.parse(options.data.fields),
472 | {
473 | hint: JSON.parse(options.data.hint),
474 | limit: options.data.limit,
475 | skip: options.data.skip,
476 | sort: JSON.parse(options.data.sort)
477 | }
478 | ]);
479 | // find data
480 | options.cursor = options.collection.find(data[0], data[1], data[2]);
481 | options.cursor.toArray(onNext);
482 | break;
483 | case 'crudGetDistinctValueByPropertyMany':
484 | // find data
485 | options.collection.distinct(
486 | options.data.field.replace((/^id$/), '_id'),
487 | local.swmg.normalizeIdMongodb(JSON.parse(options.data.query)),
488 | onNext
489 | );
490 | break;
491 | case 'crudCreateMany':
492 | case 'crudReplaceMany':
493 | // insert / replace data
494 | if (!options.data.body.length) {
495 | options.response.data = [];
496 | modeNext = Infinity;
497 | onNext();
498 | break;
499 | }
500 | options.bulk = options.collection.initializeOrderedBulkOp();
501 | options.data.body.forEach(function (element) {
502 | // init id
503 | element._id = element._id || local.utility2.uuidTime();
504 | element[options.optionsIdKey] = element[options.optionsIdKey] ||
505 | element._id;
506 | // init _timeCreated and _timeModified
507 | element._timeCreated =
508 | element._timeModified = new Date().toISOString();
509 | switch (options.operationId) {
510 | case 'crudCreateMany':
511 | // insert data
512 | options.bulk.insert(element);
513 | break;
514 | case 'crudReplaceMany':
515 | options.bulkFindQuery = {};
516 | options.bulkFindQuery[options.optionsIdKey] =
517 | element[options.optionsIdKey];
518 | options.bulkFind = options.bulk.find(options.bulkFindQuery);
519 | // upsert data
520 | if (options.data.upsert) {
521 | options.bulkFind = options.bulkFind.upsert();
522 | }
523 | // replace data
524 | options.bulkFind.replaceOne(element);
525 | break;
526 | }
527 | });
528 | options.bulk.execute(onNext);
529 | break;
530 | case 'crudReplaceOne':
531 | // replace data
532 | options.collection.update(options.optionsId, options.data.body, {
533 | upsert: options.data.upsert
534 | }, onNext);
535 | break;
536 | case 'crudUpdateOne':
537 | // update data
538 | options.collection.update(options
539 | .optionsId, { $set: options.data.body }, {
540 | upsert: options.data.upsert
541 | }, onNext);
542 | break;
543 | default:
544 | onNext(new Error('undefined crud operation - ' +
545 | options.schemaName + '.' + options.operationId));
546 | }
547 | break;
548 | case 3:
549 | // jsonCopy object to prevent side-effects
550 | data = local.utility2.jsonCopy(data);
551 | switch (options.operationId) {
552 | case 'crudAggregateMany':
553 | case 'crudCountByQueryOne':
554 | case 'crudGetByIdOne':
555 | case 'crudGetDistinctValueByPropertyMany':
556 | case 'crudGetByQueryMany':
557 | options.response.data = data;
558 | break;
559 | case 'crudCreateMany':
560 | case 'crudReplaceMany':
561 | options.response.meta = data;
562 | options.collection.find({
563 | _id: { $in: options.data.body.map(function (element) {
564 | return element._id;
565 | }) }
566 | }).toArray(onNext);
567 | return;
568 | case 'crudCreateOne':
569 | case 'crudReplaceOne':
570 | case 'crudUpdateOne':
571 | options.response.meta = data;
572 | if ((data.n || (data.result && data.result.n)) !== 1) {
573 | onNext(new Error(options.operationId + ' failed'));
574 | return;
575 | }
576 | options.collection.findOne(options.optionsId, onNext);
577 | return;
578 | case 'crudDeleteByIdOne':
579 | case 'crudDeleteByQueryMany':
580 | options.response.meta = data;
581 | break;
582 | case 'crudExistsByIdOne':
583 | options.response.data = !!data;
584 | break;
585 | }
586 | modeNext += 1;
587 | onNext(error);
588 | break;
589 | case 4:
590 | switch (options.operationId) {
591 | case 'crudCreateMany':
592 | case 'crudReplaceMany':
593 | options.tmp = {};
594 | data.forEach(function (element) {
595 | options.tmp[element._id] = element;
596 | });
597 | options.response.data = options.data.body.map(function (element) {
598 | return options.tmp[element._id];
599 | });
600 | break;
601 | default:
602 | // jsonCopy object to prevent side-effects
603 | options.response.data = local.utility2.jsonCopy(data);
604 | }
605 | onNext();
606 | break;
607 | default:
608 | options.onError2(error, options.response.data);
609 | }
610 | }, options.onError2);
611 | });
612 | onNext();
613 | };
614 |
615 | local.swmg.apiUpdate = function (options) {
616 | /*
617 | * this function will update the api
618 | */
619 | var methodPath, tmp;
620 | options.definitions = options.definitions || {};
621 | options.paths = options.paths || {};
622 | Object.keys(options.definitions).forEach(function (schemaName) {
623 | var schema;
624 | schema = options.definitions[schemaName];
625 | schema._schemaName = schemaName;
626 | if (!schema._collectionName) {
627 | return;
628 | }
629 | local.utility2.objectSetDefault(options, JSON.parse(JSON.stringify({
630 | definitions: {
631 | // init JsonapiResponse{{_schemaName}}
632 | 'JsonapiResponse{{_schemaName}}': {
633 | properties: { data: {
634 | items: { $ref: '#/definitions/{{_schemaName}}' },
635 | type: 'array'
636 | } },
637 | 'x-inheritList': [{ $ref: '#/definitions/JsonapiResponse' }]
638 | }
639 | }
640 | }).replace((/\{\{_schemaName\}\}/g), schemaName)), 2);
641 | // hack - init swaggerJson$$Dummy,
642 | // to pass validation warnings for auto-created schemas
643 | tmp = local.swmg.swaggerJson$$Dummy;
644 | local.utility2.objectSetOverride(tmp, JSON.parse(JSON.stringify({
645 | paths: { '/$$Dummy/{{_schemaName}}': { get: {
646 | responses: {
647 | 200: {
648 | description: '',
649 | schema: { $ref:
650 | '#/definitions/JsonapiResponse{{_schemaName}}' }
651 | }
652 | }
653 | } } }
654 | }).replace((/\{\{_schemaName\}\}/g), schemaName)), 2);
655 | // init crud-api
656 | (schema._crudApiList || []).forEach(function (methodPath) {
657 | methodPath = JSON.parse(local.swmg.cacheDict.methodPathCrudDefault[
658 | methodPath
659 | ]
660 | .replace((/\{\{_collectionName\}\}/g), schema._collectionName)
661 | .replace((/\{\{_crudApi\}\}/g), schema._crudApi)
662 | .replace((/\{\{_schemaName\}\}/g), schema._schemaName));
663 | options.paths[methodPath._path] = options.paths[methodPath._path] || {};
664 | options.paths[methodPath._path][methodPath._method] = methodPath;
665 | });
666 | // init collectionName / crudApi / schemaName
667 | schema = options.definitions[schemaName] = JSON.parse(
668 | JSON.stringify(schema)
669 | .replace((/\{\{_collectionName\}\}/g), schema._collectionName)
670 | .replace((/\{\{_crudApi\}\}/g), schema._crudApi)
671 | .replace((/\{\{_schemaName\}\}/g), schema._schemaName)
672 | );
673 | // update cacheDict.collection
674 | local.utility2.onReady.counter += 1;
675 | local.utility2.taskRunOrSubscribe({
676 | key: 'swagger-mongodb.mongodbConnect'
677 | }, function () {
678 | local.swmg.collectionCreate(schema, local.utility2.onReady);
679 | });
680 | });
681 | // update paths
682 | Object.keys(options.paths).forEach(function (path) {
683 | Object.keys(options.paths[path]).forEach(function (method) {
684 | methodPath = options.paths[path][method];
685 | methodPath._method = method;
686 | methodPath._path = path;
687 | // init crud-api
688 | tmp = methodPath._crudApi &&
689 | local.swmg.cacheDict.methodPathCrudDefault[methodPath.operationId];
690 | if (tmp) {
691 | local.utility2.objectSetDefault(methodPath, JSON.parse(tmp), 2);
692 | }
693 | // init methodPath
694 | local.utility2.objectSetDefault(methodPath, {
695 | parameters: [],
696 | responses: {
697 | 200: {
698 | description: 'ok - ' +
699 | 'http://jsonapi.org/format/#document-top-level',
700 | schema: { $ref: '#/definitions/JsonapiResponse' }
701 | }
702 | },
703 | tags: []
704 | }, 2);
705 | // init collectionName / crudApi / schemaName
706 | local.utility2.objectSetOverride(methodPath, JSON.parse(
707 | JSON.stringify(methodPath)
708 | .replace((/\{\{_collectionName\}\}/g), methodPath._collectionName)
709 | .replace((/\{\{_crudApi\}\}/g), methodPath._crudApi)
710 | .replace((/\{\{_schemaName\}\}/g), methodPath._schemaName)
711 | ), 1);
712 | // update cacheDict.methodPath
713 | local.swmg.cacheDict.methodPath[method.toUpperCase() + ' ' + path.replace(
714 | (/\{.*/),
715 | function (match0) {
716 | return match0.replace((/[^\/]/g), '');
717 | }
718 | )] = JSON.stringify(methodPath);
719 | });
720 | });
721 | // merge tags
722 | tmp = {};
723 | // update tags from options._tagDict
724 | Object.keys(options._tagDict || {}).forEach(function (key) {
725 | tmp[key] = options._tagDict[key];
726 | tmp[key].name = key;
727 | });
728 | // update tags from options.tags
729 | [local.swmg.swaggerJson.tags, options.tags].forEach(function (tags) {
730 | (tags || []).forEach(function (element) {
731 | tmp[element.name] = element;
732 | });
733 | });
734 | tmp = local.swmg.swaggerJson.tags = Object.keys(tmp).sort().map(function (key) {
735 | return tmp[key];
736 | });
737 | // update swaggerJson with options, with underscore keys removed
738 | local.utility2.objectSetOverride(
739 | local.swmg.swaggerJson,
740 | local.utility2.objectTraverse(
741 | // jsonCopy object to prevent side-effects
742 | local.utility2.jsonCopy(options),
743 | function (element) {
744 | if (element && typeof element === 'object') {
745 | Object.keys(element).forEach(function (key) {
746 | // security - remove underscore key
747 | if (key[0] === '_') {
748 | delete element[key];
749 | }
750 | });
751 | }
752 | }
753 | ),
754 | 2
755 | );
756 | // restore tags
757 | local.swmg.swaggerJson.tags = tmp;
758 | // init properties from x-inheritList
759 | [0, 1, 2, 3].forEach(function () {
760 | Object.keys(local.swmg.swaggerJson.definitions).forEach(function (schema) {
761 | schema = local.swmg.swaggerJson.definitions[schema];
762 | // jsonCopy object to prevent side-effects
763 | local.utility2.jsonCopy(schema['x-inheritList'] || [])
764 | .reverse()
765 | .forEach(function (element) {
766 | local.utility2.objectSetDefault(schema, {
767 | properties:
768 | local.swmg.schemaDereference(element.$ref).properties
769 | }, 2);
770 | });
771 | });
772 | });
773 | // jsonCopy object to prevent side-effects
774 | local.swmg.swaggerJson = JSON.parse(local.utility2
775 | .jsonStringifyOrdered(local.utility2.jsonCopy(local.swmg.swaggerJson)));
776 | // validate swaggerJson
777 | local.swmg.validateBySwagger(local.utility2.objectSetDefault(
778 | local.utility2.jsonCopy(local.swmg.swaggerJson),
779 | local.swmg.swaggerJson$$Dummy,
780 | 2
781 | ));
782 | // init crud-api
783 | local.swmg.api = new local.swmg.SwaggerClient({
784 | url: 'http://localhost:' + local.utility2.serverPortInit()
785 | });
786 | local.swmg.api.buildFromSpec(local.utility2.jsonCopy(local.swmg.swaggerJson));
787 | };
788 |
789 | local.swmg.collectionCreate = function (schema, onError) {
790 | /*
791 | * this function will create a mongodb collection
792 | */
793 | var collection, modeNext, onNext;
794 | modeNext = 0;
795 | onNext = function (error) {
796 | // validate no error occurred
797 | local.utility2.assert(!error, error);
798 | modeNext += 1;
799 | switch (modeNext) {
800 | case 1:
801 | collection = local.swmg.cacheDict.collection[schema._collectionName] =
802 | local.swmg.db.collection(schema._collectionName);
803 | // if $npm_config_mode_mongodb_readonly, then return this function
804 | if (local.utility2.envDict.npm_config_mode_mongodb_readonly ||
805 | schema._collectionReadonly) {
806 | onError();
807 | return;
808 | }
809 | // drop collection on init
810 | if (schema._collectionDrop) {
811 | console.warn('dropping collection ' + schema._collectionName + ' ...');
812 | local.swmg.db.command({ drop: schema._collectionName }, function () {
813 | onNext();
814 | });
815 | return;
816 | }
817 | onNext();
818 | return;
819 | case 2:
820 | // create collection
821 | if (schema._collectionCreate) {
822 | local.swmg.db.createCollection(
823 | schema._collectionName,
824 | schema._collectionCreate,
825 | function () {
826 | // convert existing collection to capped collection
827 | collection.isCapped(function (error, data) {
828 | if (!error && !data && schema._collectionCreate.capped) {
829 | local.swmg.db.command({
830 | convertToCapped: schema._collectionName,
831 | size: schema._collectionCreate.size
832 | }, onNext);
833 | return;
834 | }
835 | onNext();
836 | });
837 | }
838 | );
839 | return;
840 | }
841 | onNext();
842 | return;
843 | case 3:
844 | // create index
845 | if (schema._collectionCreateIndexList) {
846 | local.swmg.db.command({
847 | createIndexes: schema._collectionName,
848 | indexes: schema._collectionCreateIndexList
849 | }, onNext);
850 | return;
851 | }
852 | onNext();
853 | return;
854 | case 4:
855 | // upsert fixtures
856 | local.swmg._crudApi({
857 | collectionName: schema._collectionName,
858 | data: {
859 | body: local.utility2.jsonCopy(schema._collectionFixtureList || []),
860 | upsert: true
861 | },
862 | operationId: 'crudReplaceMany',
863 | schemaName: schema._schemaName
864 | }, onNext);
865 | return;
866 | default:
867 | onError();
868 | }
869 | };
870 | onNext();
871 | };
872 |
873 | local.swmg.middlewareBodyParse = function (request, response, nextMiddleware) {
874 | /*
875 | * this function will parse the request-body
876 | */
877 | // jslint-hack
878 | local.utility2.nop(response);
879 | local.utility2.testTryCatch(function () {
880 | if (request.swmgBodyParsed) {
881 | nextMiddleware();
882 | return;
883 | }
884 | request.swmgBodyParsed = String(request.bodyRaw);
885 | switch ((/[^;]*/).exec(request.headers['content-type'] || '')[0]) {
886 | case 'application/x-www-form-urlencoded':
887 | request.swmgBodyParsed =
888 | local.url.parse('?' + request.swmgBodyParsed, true).query;
889 | break;
890 | default:
891 | try {
892 | request.swmgBodyParsed = JSON.parse(request.swmgBodyParsed);
893 | } catch (ignore) {
894 | }
895 | }
896 | nextMiddleware();
897 | }, nextMiddleware);
898 | };
899 |
900 | local.swmg.middlewareError = function (error, request, response) {
901 | /*
902 | * this function will handle errors according to http://jsonapi.org/format/#errors
903 | */
904 | if (!error) {
905 | error = new Error('404 Not Found');
906 | error.statusCode = 404;
907 | }
908 | local.swmg.onErrorJsonapi(null, function (error) {
909 | local.utility2.serverRespondHeadSet(request, response, error.statusCode, {});
910 | // debug statusCode / method / url
911 | local.utility2.errorMessagePrepend(error, response.statusCode + ' ' +
912 | request.method + ' ' + request.url + '\n');
913 | // print error.stack to stderr
914 | local.utility2.onErrorDefault(error);
915 | response.end(JSON.stringify(error));
916 | })(error);
917 | };
918 |
919 | local.swmg.middlewareSwagger = function (request, response, nextMiddleware) {
920 | /*
921 | * this function will run the main swagger-mongodb middleware
922 | */
923 | var modeNext, onNext, tmp;
924 | modeNext = 0;
925 | onNext = function (error) {
926 | local.utility2.testTryCatch(function () {
927 | modeNext = error
928 | ? Infinity
929 | : modeNext + 1;
930 | switch (modeNext) {
931 | case 1:
932 | // if request.url is not prefixed with swaggerJson.basePath,
933 | // then default to nextMiddleware
934 | if (request.urlParsed.pathnameNormalized
935 | .indexOf(local.swmg.swaggerJson.basePath) !== 0) {
936 | modeNext = Infinity;
937 | onNext();
938 | return;
939 | }
940 | // init swmgPathname
941 | request.swmgPathname = request.method + ' ' +
942 | request.urlParsed.pathnameNormalized
943 | .replace(local.swmg.swaggerJson.basePath, '');
944 | switch (request.swmgPathname) {
945 | // serve swagger.json
946 | case 'GET /swagger.json':
947 | response.end(JSON.stringify(local.swmg.swaggerJson));
948 | return;
949 | }
950 | // init swmgMethodPath
951 | while (true) {
952 | request.swmgMethodPath =
953 | local.swmg.cacheDict.methodPath[request.swmgPathname];
954 | // if swmgMethodPath exists, then break and continue
955 | if (request.swmgMethodPath) {
956 | request.swmgMethodPath = JSON.parse(request.swmgMethodPath);
957 | onNext();
958 | break;
959 | }
960 | // if cannot init swmgMethodPath, then default to nextMiddleware
961 | if (request.swmgPathname === request.swmgPathnameOld) {
962 | modeNext = Infinity;
963 | onNext();
964 | break;
965 | }
966 | request.swmgPathnameOld = request.swmgPathname;
967 | request.swmgPathname =
968 | request.swmgPathname.replace((/\/[^\/]+?(\/*?)$/), '/$1');
969 | }
970 | break;
971 | case 2:
972 | // init swmgParamDict
973 | request.swmgParamDict = {};
974 | // parse path param
975 | tmp = request.urlParsed.pathname
976 | .replace(local.swmg.swaggerJson.basePath, '').split('/');
977 | request.swmgMethodPath._path.split('/').forEach(function (key, ii) {
978 | if ((/^\{\S*?\}$/).test(key)) {
979 | request.swmgParamDict[key.slice(1, -1)] =
980 | decodeURIComponent(tmp[ii]);
981 | }
982 | });
983 | request.swmgMethodPath.parameters.forEach(function (paramDef) {
984 | switch (paramDef.in) {
985 | // parse body param
986 | case 'body':
987 | request.swmgParamDict[paramDef.name] =
988 | request.swmgParamDict[paramDef.name] ||
989 | request.swmgBodyParsed;
990 | break;
991 | // parse formData param
992 | case 'formData':
993 | request.swmgParamDict[paramDef.name] =
994 | request.swmgParamDict[paramDef.name] ||
995 | request.swmgBodyParsed[paramDef.name];
996 | break;
997 | // parse header param
998 | case 'header':
999 | request.swmgParamDict[paramDef.name] =
1000 | request.headers[paramDef.name.toLowerCase()];
1001 | break;
1002 | // parse query param
1003 | case 'query':
1004 | request.swmgParamDict[paramDef.name] =
1005 | request.urlParsed.query[paramDef.name];
1006 | break;
1007 | }
1008 | // init default param
1009 | request.swmgParamDict[paramDef.name] =
1010 | request.swmgParamDict[paramDef.name] || paramDef.default;
1011 | });
1012 | onNext();
1013 | break;
1014 | case 3:
1015 | // normalize params
1016 | local.swmg.normalizeParamDictSwagger(request
1017 | .swmgParamDict, request.swmgMethodPath);
1018 | // validate params
1019 | local.swmg.validateByParamDefList({
1020 | data: request.swmgParamDict,
1021 | key: request.swmgPathname,
1022 | paramDefList: request.swmgMethodPath.parameters
1023 | });
1024 | // run default crud-api
1025 | if (request.swmgMethodPath._crudApi) {
1026 | local.swmg._crudApi({
1027 | collectionName: request.swmgMethodPath._collectionName,
1028 | data: request.swmgParamDict,
1029 | operationId: request.swmgMethodPath.operationId,
1030 | paramDefList: request.swmgMethodPath.parameters,
1031 | schemaName: request.swmgMethodPath._schemaName
1032 | }, function (error, data) {
1033 | if (!error && data) {
1034 | response.end(JSON.stringify(data));
1035 | return;
1036 | }
1037 | onNext(error);
1038 | });
1039 | return;
1040 | }
1041 | onNext();
1042 | break;
1043 | default:
1044 | nextMiddleware(error);
1045 | }
1046 | }, nextMiddleware);
1047 | };
1048 | onNext();
1049 | };
1050 | break;
1051 | }
1052 | switch (local.modeJs) {
1053 |
1054 |
1055 |
1056 | // run browser js-env code
1057 | case 'browser':
1058 | // export swagger-mongodb
1059 | window.swmg = local.swmg;
1060 | // require modules
1061 | local.utility2 = window.utility2;
1062 | break;
1063 |
1064 |
1065 |
1066 | // run node js-env code
1067 | case 'node':
1068 | // export swagger-mongodb
1069 | module.exports = local.swmg;
1070 | module.exports.__dirname = __dirname;
1071 | // require modules
1072 | local.fs = require('fs');
1073 | local.mongodb = require('mongodb-minimal');
1074 | local.path = require('path');
1075 | local.swagger_tools = require('swagger-ui-lite/swagger-tools-standalone-min.js');
1076 | local.swagger_ui_lite = require('swagger-ui-lite');
1077 | local.url = require('url');
1078 | local.utility2 = require('utility2');
1079 | local.vm = require('vm');
1080 | // init swaggerJson
1081 | local.swmg.swaggerJson = {
1082 | basePath: local.utility2.envDict.npm_config_mode_api_prefix || '/api/v0',
1083 | definitions: {
1084 | Array: { items: {}, type: 'array' },
1085 | // http://jsonapi.org/format/#errors
1086 | JsonapiError: {
1087 | properties: {
1088 | code: { type: 'string' },
1089 | detail: { type: 'string' },
1090 | id: { type: 'string' },
1091 | message: { type: 'string' }
1092 | }
1093 | },
1094 | // http://jsonapi.org/format/#document-structure-resource-objects
1095 | JsonapiResource: {
1096 | properties: {
1097 | id: { type: 'string' }
1098 | }
1099 | },
1100 | // http://jsonapi.org/format/#document-structure-top-level
1101 | JsonapiResponse: {
1102 | properties: {
1103 | data: {
1104 | items: { $ref: '#/definitions/JsonapiResource' },
1105 | type: 'array'
1106 | },
1107 | errors: {
1108 | items: { $ref: '#/definitions/JsonapiError' },
1109 | type: 'array'
1110 | },
1111 | meta: { $ref: '#/definitions/Object' },
1112 | statusCode: { type: 'integer' }
1113 | }
1114 | },
1115 | // http://docs.mongodb.org/manual/reference/operator/aggregation/
1116 | MongodbAggregationPipeline: {
1117 | properties: {
1118 | $group: { default: { "_id": "all", "count": { "$sum": 1 } } }
1119 | }
1120 | },
1121 | Object: { type: 'object' },
1122 | Undefined: {}
1123 | },
1124 | info: {
1125 | description: 'demo of swagger-mongodb crud-api',
1126 | title: 'swagger-mongodb api',
1127 | version: '0'
1128 | },
1129 | paths: {},
1130 | swagger: '2.0',
1131 | tags: []
1132 | };
1133 | // hack - init swaggerJson$$Dummy to pass validation warnings for auto-created schemas
1134 | local.swmg.swaggerJson$$Dummy = {
1135 | definitions: {
1136 | $$Dummy: {
1137 | properties: {
1138 | propArray: {
1139 | items: { $ref: '#/definitions/Array' },
1140 | type: 'array'
1141 | },
1142 | propMongodbAggregationPipeline: {
1143 | items: { $ref: '#/definitions/MongodbAggregationPipeline' },
1144 | type: 'array'
1145 | },
1146 | propObject: { items: { $ref: '#/definitions/Object' } },
1147 | propUndefined: { items: { $ref: '#/definitions/Undefined' } }
1148 | }
1149 | },
1150 | JsonapiResponse$$Dummy: {
1151 | properties: { data: {
1152 | items: { $ref: '#/definitions/$$Dummy' },
1153 | type: 'array'
1154 | } },
1155 | 'x-inheritList': [{ $ref: '#/definitions/JsonapiResponse' }]
1156 | }
1157 | },
1158 | paths: { '/$$Dummy': { get: {
1159 | responses: {
1160 | 200: {
1161 | description: '',
1162 | schema: { $ref: '#/definitions/JsonapiResponse$$Dummy' }
1163 | }
1164 | }
1165 | } } }
1166 | };
1167 | // init assets
1168 | local.utility2.cacheDict.assets['/assets/swagger-mongodb.js'] =
1169 | local.utility2.istanbul_lite.instrumentInPackage(
1170 | local.fs.readFileSync(__filename, 'utf8'),
1171 | __filename,
1172 | 'swagger-mongodb'
1173 | );
1174 | local.utility2.cacheDict.assets['/assets/swagger-ui.html'] = local.fs
1175 | .readFileSync(
1176 | local.swagger_ui_lite.__dirname + '/swagger-ui.html',
1177 | 'utf8'
1178 | )
1179 | // swagger-hack - add extra assets
1180 | .replace(
1181 | "",
1182 | "" +
1183 | '' +
1184 | ''
1185 | )
1186 | // swagger-hack - update swagger.json url
1187 | .replace(
1188 | 'http://petstore.swagger.io/v2/swagger.json',
1189 | local.swmg.swaggerJson.basePath + '/swagger.json'
1190 | );
1191 | local.utility2.cacheDict.assets['/assets/swagger-ui.rollup.css'] = local.fs
1192 | .readFileSync(
1193 | local.swagger_ui_lite.__dirname + '/swagger-ui.rollup.css',
1194 | 'utf8'
1195 | );
1196 | local.utility2.cacheDict.assets['/assets/swagger-ui.rollup.js'] = local.fs
1197 | .readFileSync(
1198 | local.swagger_ui_lite.__dirname + '/swagger-ui.rollup.js',
1199 | 'utf8'
1200 | )
1201 | // swagger-hack - disable underscore-min.map
1202 | .replace('//# sourceMappingURL=underscore-min.map', '')
1203 | // swagger-hack - save swaggerJson
1204 | .replace(
1205 | 'this.apis = {};',
1206 | 'this.apis = {}; this.swaggerJson = JSON.parse(JSON.stringify(response));'
1207 | )
1208 | // swagger-hack - disable missingParams validation handling
1209 | .replace(
1210 | 'var missingParams = this.getMissingParams(args);',
1211 | 'var missingParams = [];'
1212 | )
1213 | // swagger-hack - add modeErroData and validation handling
1214 | .replace('new SwaggerHttp().execute(obj, opts);', 'if (opts.modeErrorData) {' +
1215 | 'var onError = success;' +
1216 | 'error = function (error) {' +
1217 | 'error = error.obj || error;' +
1218 | 'error = error.data || error;' +
1219 | 'try { error = JSON.parse(error) } catch (ignore) {}' +
1220 | 'if (typeof error === "string") {' +
1221 | 'error = { message: error };' +
1222 | '}' +
1223 | 'onError(error);' +
1224 | '};' +
1225 | 'success = function (data) { onError(null, data); };' +
1226 | '}' +
1227 | 'try {' +
1228 | 'if (window.swmg) {' +
1229 | 'window.swmg.validateByParamDefList({' +
1230 | 'data: window.swmg.normalizeParamDictSwagger(' +
1231 | 'JSON.parse(JSON.stringify(args)),' +
1232 | 'this' +
1233 | '),' +
1234 | 'key: this.operation.operationId,' +
1235 | 'paramDefList: this.parameters' +
1236 | '});' +
1237 | '}' +
1238 | '} catch (errorCaught) {' +
1239 | 'window.swmg.onErrorJsonapi(null, function (error) {' +
1240 | 'console.error(error);' +
1241 | 'obj.on.error({' +
1242 | 'data: JSON.stringify(error),' +
1243 | 'headers: { "Content-Type": "application/json" }' +
1244 | '});' +
1245 | '})(errorCaught);' +
1246 | 'return;' +
1247 | '}' +
1248 | 'new SwaggerHttp().execute(obj, opts);')
1249 | // swagger-hack - handle json error
1250 | .replace('new_err.status = res.status;', 'new_err.status = res.status;' +
1251 | 'if (res.body && res.body.message && res.body.stack) { err = res.body; }')
1252 | // swagger-hack - disable online validation
1253 | .replace("if ('validatorUrl' in opts.swaggerOptions) {", "if (true) {");
1254 | local.utility2.cacheDict.assets['/assets/swagger-ui.explorer_icons.png'] = local.fs
1255 | .readFileSync(local.swagger_ui_lite.__dirname +
1256 | '/swagger-ui.explorer_icons.png');
1257 | local.utility2.cacheDict.assets['/assets/swagger-ui.logo_small.png'] = local.fs
1258 | .readFileSync(local.swagger_ui_lite.__dirname +
1259 | '/swagger-ui.logo_small.png');
1260 | local.utility2.cacheDict.assets['/assets/swagger-ui.throbber.gif'] = local.fs
1261 | .readFileSync(local.swagger_ui_lite.__dirname +
1262 | '/swagger-ui.throbber.gif');
1263 | // init SwaggerClient
1264 | (function () {
1265 | local.Handlebars = {
1266 | registerHelper: local.utility2.nop,
1267 | template: local.utility2.nop
1268 | };
1269 | local.XMLHttpRequest = function () {
1270 | var self;
1271 | self = this;
1272 | self.headers = {};
1273 | };
1274 | local.XMLHttpRequest.prototype.onreadystatechange = local.utility2.nop;
1275 | local.XMLHttpRequest.prototype.open = function (method, url) {
1276 | this.method = method;
1277 | this.url = url;
1278 | };
1279 | local.XMLHttpRequest.prototype.send = function (data) {
1280 | var self;
1281 | self = this;
1282 | self.data = data;
1283 | self.xhr = self;
1284 | local.utility2.ajax(self, local.utility2.onErrorDefault);
1285 | };
1286 | local.XMLHttpRequest.prototype.setRequestHeader = function (key, value) {
1287 | this.headers[key.toLowerCase()] = value;
1288 | };
1289 | local.$ = local.utility2.nop;
1290 | local.console = console;
1291 | local.clearTimeout = clearTimeout;
1292 | local.location = {};
1293 | local.setTimeout = setTimeout;
1294 | local.window = local;
1295 | local.vm.runInNewContext(
1296 | local.utility2.cacheDict.assets['/assets/swagger-ui.rollup.js']
1297 | // swagger-hack - remove browser js-env code
1298 | .replace((/[\S\s]+?\/underscore-min\.js \*\//), function (match0) {
1299 | return match0.replace((/\S+/g), '');
1300 | }),
1301 | local,
1302 | __dirname + '/swagger-ui.rollup.js'
1303 | );
1304 | local.swmg.SwaggerClient = local.SwaggerClient;
1305 | local.swmg.SwaggerUi = local.SwaggerUi;
1306 | }());
1307 | // init api
1308 | local.swmg.apiUpdate({});
1309 | break;
1310 | }
1311 | }((function () {
1312 | 'use strict';
1313 | var local;
1314 |
1315 |
1316 |
1317 | // run shared js-env code
1318 | (function () {
1319 | // init local
1320 | local = {};
1321 | // init js-env
1322 | local.modeJs = (function () {
1323 | try {
1324 | return module.exports &&
1325 | typeof process.versions.node === 'string' &&
1326 | typeof require('http').createServer === 'function' &&
1327 | 'node';
1328 | } catch (errorCaughtNode) {
1329 | return typeof navigator.userAgent === 'string' &&
1330 | typeof document.querySelector('body') === 'object' &&
1331 | 'browser';
1332 | }
1333 | }());
1334 | // init global
1335 | local.global = local.modeJs === 'browser'
1336 | ? window
1337 | : global;
1338 | // init utility2
1339 | local.utility2 = local.modeJs === 'browser'
1340 | ? window.utility2
1341 | : require('utility2');
1342 | // init swagger-mongodb
1343 | local.swmg = { cacheDict: { collection: {}, methodPath: {} }, local: local };
1344 | /* jslint-indent-begin 8 */
1345 | /*jslint maxlen: 104*/
1346 | // init methodPathCrudDefault
1347 | local.swmg.cacheDict.methodPathCrudDefault = {
1348 | crudAggregateMany: {
1349 | _collectionName: '{{_collectionName}}',
1350 | _crudApi: '{{_crudApi}}',
1351 | _method: 'post',
1352 | _path: '/{{_crudApi}}/crudAggregateMany',
1353 | operationId: 'crudAggregateMany',
1354 | parameters: [{
1355 | description: 'mongodb aggregation array',
1356 | in: 'body',
1357 | name: 'body',
1358 | required: true,
1359 | schema: {
1360 | items: { $ref: '#/definitions/MongodbAggregationPipeline' },
1361 | type: 'array'
1362 | }
1363 | }],
1364 | summary: 'aggregate many {{_schemaName}} objects',
1365 | tags: ['{{_crudApi}}']
1366 | },
1367 | crudCountByQueryOne: {
1368 | _collectionName: '{{_collectionName}}',
1369 | _crudApi: '{{_crudApi}}',
1370 | _method: 'get',
1371 | _path: '/{{_crudApi}}/crudCountByQueryOne',
1372 | operationId: 'crudCountByQueryOne',
1373 | parameters: [{
1374 | default: '{}',
1375 | description: 'mongodb query param',
1376 | format: 'json',
1377 | in: 'query',
1378 | name: 'query',
1379 | type: 'string'
1380 | }],
1381 | summary: 'count many {{_schemaName}} objects by query',
1382 | tags: ['{{_crudApi}}']
1383 | },
1384 | crudCreateMany: {
1385 | _collectionName: '{{_collectionName}}',
1386 | _crudApi: '{{_crudApi}}',
1387 | _method: 'put',
1388 | _path: '/{{_crudApi}}/crudCreateMany',
1389 | operationId: 'crudCreateMany',
1390 | parameters: [{
1391 | description: '{{_schemaName}} object list',
1392 | in: 'body',
1393 | name: 'body',
1394 | required: true,
1395 | schema: { items: { $ref: '#/definitions/{{_schemaName}}' }, type: 'array' }
1396 | }],
1397 | summary: 'create many {{_schemaName}} objects in ordered list',
1398 | tags: ['{{_crudApi}}']
1399 | },
1400 | crudCreateOne: {
1401 | _collectionName: '{{_collectionName}}',
1402 | _crudApi: '{{_crudApi}}',
1403 | _method: 'post',
1404 | _path: '/{{_crudApi}}/crudCreateOne',
1405 | operationId: 'crudCreateOne',
1406 | parameters: [{
1407 | description: '{{_schemaName}} object',
1408 | in: 'body',
1409 | name: 'body',
1410 | required: true,
1411 | schema: { $ref: '#/definitions/{{_schemaName}}' }
1412 | }],
1413 | responses: {
1414 | 200: {
1415 | description: '200 ok - http://jsonapi.org/format/#document-structure-top-level',
1416 | schema: { $ref: '#/definitions/JsonapiResponse{{_schemaName}}' }
1417 | }
1418 | },
1419 | summary: 'create one {{_schemaName}} object',
1420 | tags: ['{{_crudApi}}']
1421 | },
1422 | crudDeleteByIdOne: {
1423 | _collectionName: '{{_collectionName}}',
1424 | _crudApi: '{{_crudApi}}',
1425 | _method: 'delete',
1426 | _path: '/{{_crudApi}}/crudDeleteByIdOne/{id}',
1427 | operationId: 'crudDeleteByIdOne',
1428 | parameters: [{
1429 | description: '{{_schemaName}} id',
1430 | in: 'path',
1431 | name: 'id',
1432 | required: true,
1433 | type: 'string'
1434 | }],
1435 | summary: 'delete one {{_schemaName}} object by id',
1436 | tags: ['{{_crudApi}}']
1437 | },
1438 | crudDeleteByQueryMany: {
1439 | _collectionName: '{{_collectionName}}',
1440 | _crudApi: '{{_crudApi}}',
1441 | _method: 'delete',
1442 | _path: '/{{_crudApi}}/crudDeleteByQueryMany',
1443 | operationId: 'crudDeleteByQueryMany',
1444 | parameters: [{
1445 | default: '{"_id":{"$in":["id0","id1"]}}',
1446 | description: 'mongodb query param',
1447 | format: 'json',
1448 | in: 'query',
1449 | name: 'query',
1450 | required: true,
1451 | type: 'string'
1452 | }],
1453 | responses: {
1454 | 200: {
1455 | description: '200 ok - http://jsonapi.org/format/#document-structure-top-level',
1456 | schema: { $ref: '#/definitions/JsonapiResponse{{_schemaName}}' }
1457 | }
1458 | },
1459 | summary: 'get many {{_schemaName}} objects by query',
1460 | tags: ['{{_crudApi}}']
1461 | },
1462 | crudExistsByIdOne: {
1463 | _collectionName: '{{_collectionName}}',
1464 | _crudApi: '{{_crudApi}}',
1465 | _method: 'get',
1466 | _path: '/{{_crudApi}}/crudExistsByIdOne/{id}',
1467 | operationId: 'crudExistsByIdOne',
1468 | parameters: [{
1469 | description: '{{_schemaName}} id',
1470 | in: 'path',
1471 | name: 'id',
1472 | required: true,
1473 | type: 'string'
1474 | }],
1475 | summary: 'check if one {{_schemaName}} object exists by id',
1476 | tags: ['{{_crudApi}}']
1477 | },
1478 | crudGetByIdOne: {
1479 | _collectionName: '{{_collectionName}}',
1480 | _crudApi: '{{_crudApi}}',
1481 | _method: 'get',
1482 | _path: '/{{_crudApi}}/crudGetByIdOne/{id}',
1483 | operationId: 'crudGetByIdOne',
1484 | parameters: [{
1485 | description: '{{_schemaName}} id',
1486 | in: 'path',
1487 | name: 'id',
1488 | required: true,
1489 | type: 'string'
1490 | }],
1491 | responses: {
1492 | 200: {
1493 | description: '200 ok - http://jsonapi.org/format/#document-structure-top-level',
1494 | schema: { $ref: '#/definitions/JsonapiResponse{{_schemaName}}' }
1495 | }
1496 | },
1497 | summary: 'get one {{_schemaName}} object by id',
1498 | tags: ['{{_crudApi}}']
1499 | },
1500 | crudGetByQueryMany: {
1501 | _collectionName: '{{_collectionName}}',
1502 | _crudApi: '{{_crudApi}}',
1503 | _method: 'get',
1504 | _path: '/{{_crudApi}}/crudGetByQueryMany',
1505 | operationId: 'crudGetByQueryMany',
1506 | parameters: [{
1507 | default: '{}',
1508 | description: 'mongodb query param',
1509 | format: 'json',
1510 | in: 'query',
1511 | name: 'query',
1512 | required: true,
1513 | type: 'string'
1514 | }, {
1515 | default: '{}',
1516 | description: 'mongodb fields param',
1517 | format: 'json',
1518 | in: 'query',
1519 | name: 'fields',
1520 | type: 'string'
1521 | }, {
1522 | default: '{}',
1523 | description: 'mongodb cursor hint param',
1524 | format: 'json',
1525 | in: 'query',
1526 | name: 'hint',
1527 | type: 'string'
1528 | }, {
1529 | default: 10,
1530 | description: 'mongodb cursor limit param',
1531 | in: 'query',
1532 | name: 'limit',
1533 | required: true,
1534 | type: 'integer'
1535 | }, {
1536 | default: 0,
1537 | description: 'mongodb cursor skip param',
1538 | in: 'query',
1539 | name: 'skip',
1540 | type: 'integer'
1541 | }, {
1542 | default: '{"_timeModified":-1}',
1543 | description: 'mongodb cursor sort param',
1544 | format: 'json',
1545 | in: 'query',
1546 | name: 'sort',
1547 | type: 'string'
1548 | }],
1549 | responses: {
1550 | 200: {
1551 | description: '200 ok - http://jsonapi.org/format/#document-structure-top-level',
1552 | schema: { $ref: '#/definitions/JsonapiResponse{{_schemaName}}' }
1553 | }
1554 | },
1555 | summary: 'get many {{_schemaName}} objects by query',
1556 | tags: ['{{_crudApi}}']
1557 | },
1558 | crudGetDistinctValueByPropertyMany: {
1559 | _collectionName: '{{_collectionName}}',
1560 | _crudApi: '{{_crudApi}}',
1561 | _method: 'get',
1562 | _path: '/{{_crudApi}}/crudGetDistinctValueByPropertyMany',
1563 | operationId: 'crudGetDistinctValueByPropertyMany',
1564 | parameters: [{
1565 | default: 'id',
1566 | description: 'mongodb query param',
1567 | in: 'query',
1568 | name: 'field',
1569 | required: true,
1570 | type: 'string'
1571 | }, {
1572 | default: '{}',
1573 | description: 'mongodb query param',
1574 | format: 'json',
1575 | in: 'query',
1576 | name: 'query',
1577 | type: 'string'
1578 | }],
1579 | summary: 'get many distinct {{_schemaName}} values by field',
1580 | tags: ['{{_crudApi}}']
1581 | },
1582 | crudReplaceMany: {
1583 | _collectionName: '{{_collectionName}}',
1584 | _crudApi: '{{_crudApi}}',
1585 | _method: 'put',
1586 | _path: '/{{_crudApi}}/crudReplaceMany',
1587 | operationId: 'crudReplaceMany',
1588 | parameters: [{
1589 | description: '{{_schemaName}} object list',
1590 | in: 'body',
1591 | name: 'body',
1592 | required: true,
1593 | schema: { items: { $ref: '#/definitions/{{_schemaName}}' }, type: 'array' }
1594 | }, {
1595 | default: false,
1596 | description: 'upsert {{_schemaName}} object if it does not exist',
1597 | in: 'query',
1598 | name: 'upsert',
1599 | type: 'boolean'
1600 | }],
1601 | summary: 'replace many {{_schemaName}} objects in ordered list',
1602 | tags: ['{{_crudApi}}']
1603 | },
1604 | crudReplaceOne: {
1605 | _collectionName: '{{_collectionName}}',
1606 | _crudApi: '{{_crudApi}}',
1607 | _method: 'put',
1608 | _path: '/{{_crudApi}}/crudReplaceOne',
1609 | operationId: 'crudReplaceOne',
1610 | parameters: [{
1611 | description: '{{_schemaName}} object',
1612 | in: 'body',
1613 | name: 'body',
1614 | required: true,
1615 | schema: { $ref: '#/definitions/{{_schemaName}}' }
1616 | }, {
1617 | default: false,
1618 | description: 'upsert {{_schemaName}} object if it does not exist',
1619 | in: 'query',
1620 | name: 'upsert',
1621 | type: 'boolean'
1622 | }],
1623 | responses: {
1624 | 200: {
1625 | description: '200 ok - http://jsonapi.org/format/#document-structure-top-level',
1626 | schema: { $ref: '#/definitions/JsonapiResponse{{_schemaName}}' }
1627 | }
1628 | },
1629 | summary: 'replace one {{_schemaName}} object',
1630 | tags: ['{{_crudApi}}']
1631 | },
1632 | crudUpdateOne: {
1633 | _collectionName: '{{_collectionName}}',
1634 | _crudApi: '{{_crudApi}}',
1635 | _method: 'put',
1636 | _path: '/{{_crudApi}}/crudUpdateOne',
1637 | operationId: 'crudUpdateOne',
1638 | parameters: [{
1639 | description: '{{_schemaName}} object with no validation check',
1640 | in: 'body',
1641 | name: 'body',
1642 | required: true,
1643 | schema: { $ref: '#/definitions/Object' }
1644 | }, {
1645 | default: false,
1646 | description: 'upsert {{_schemaName}} object if it does not exist',
1647 | in: 'query',
1648 | name: 'upsert',
1649 | type: 'boolean'
1650 | }],
1651 | responses: {
1652 | 200: {
1653 | description: '200 ok - http://jsonapi.org/format/#document-structure-top-level',
1654 | schema: { $ref: '#/definitions/JsonapiResponse{{_schemaName}}' }
1655 | }
1656 | },
1657 | summary: 'update one {{_schemaName}} object',
1658 | tags: ['{{_crudApi}}']
1659 | }
1660 | };
1661 | /* jslint-indent-end */
1662 | Object.keys(local.swmg.cacheDict.methodPathCrudDefault).forEach(function (key) {
1663 | local.swmg.cacheDict.methodPathCrudDefault[key] =
1664 | JSON.stringify(local.swmg.cacheDict.methodPathCrudDefault[key]);
1665 | });
1666 | }());
1667 | return local;
1668 | }())));
1669 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": "kai zhu ",
3 | "bin": { "swagger-mongodb": "index.js" },
4 | "dependencies": {
5 | "mongodb-minimal": "2015.8.1",
6 | "swagger-ui-lite": "2015.6.2",
7 | "utility2": "~2015.8.5"
8 | },
9 | "description": "lightweight swagger-ui crud-middleware backed by mongodb",
10 | "devDependencies": {
11 | "phantomjs-lite": "2015.7.1"
12 | },
13 | "engines": { "node": ">=0.10 <=0.12" },
14 | "keywords": [
15 | "api",
16 | "browser",
17 | "cms", "crud",
18 | "mongo", "mongodb",
19 | "swagger", "swagger-ui",
20 | "web"
21 | ],
22 | "license": "MIT",
23 | "name": "swagger-mongodb",
24 | "os": ["darwin", "linux"],
25 | "repository" : {
26 | "type" : "git",
27 | "url" : "https://github.com/kaizhu256/node-swagger-mongodb.git"
28 | },
29 | "scripts": {
30 | "build-ci": "node_modules/.bin/utility2 shRun shReadmeBuild",
31 | "build-doc": "node_modules/.bin/utility2 shRun shReadmeExportPackageJson && node_modules/.bin/utility2 shRun shDocApiCreate \"{ exampleFileList:['example.js','test.js','index.js'], moduleDict:{'swagger-mongodb':{aliasList:['swmg'],exports:require('./index.js')}} }\"",
32 | "start": "npm_config_mode_auto_restart=1 node_modules/.bin/utility2 shRun node test.js",
33 | "test": "node_modules/.bin/utility2 shRun shReadmeExportPackageJson && node_modules/.bin/utility2 test test.js"
34 | },
35 | "version": "2015.8.3"
36 | }
--------------------------------------------------------------------------------
/test.js:
--------------------------------------------------------------------------------
1 | /*jslint
2 | browser: true,
3 | maxerr: 8,
4 | maxlen: 96,
5 | node: true,
6 | nomen: true,
7 | regexp: true,
8 | stupid: true
9 | */
10 | (function (local) {
11 | 'use strict';
12 |
13 |
14 |
15 | // run shared js-env code
16 | (function () {
17 | local.optionsId = function (options) {
18 | /*
19 | * this function will init petstore id's
20 | */
21 | return local.utility2.objectSetDefault(options, {
22 | name: options.id,
23 | orderId: options.id,
24 | petId: options.id,
25 | photoUrls: [options.id],
26 | status: options.id,
27 | tags: [{ id: options.id, name: options.id }],
28 | username: options.id
29 | });
30 | };
31 |
32 | // init tests
33 | local.testCase_ajax_404 = function (options, onError) {
34 | /*
35 | * this function will test ajax's "404 not found" handling-behavior
36 | */
37 | // jslint-hack
38 | local.utility2.nop(options);
39 | // test '/_test/undefined'
40 | local.utility2.ajax({ url: '/_test/undefined' }, function (error) {
41 | local.utility2.testTryCatch(function () {
42 | // validate error occurred
43 | local.utility2.assert(error, error);
44 | // validate 404 http statusCode
45 | local.utility2.assert(error.statusCode === 404, error.statusCode);
46 | onError();
47 | }, onError);
48 | });
49 | };
50 |
51 | local.testCase_crudCreateMany_default = function (options, onError) {
52 | /*
53 | * this function will test crudCreateMany's default handling-behavior
54 | */
55 | var api, modeNext, onError2, onNext, onParallel;
56 | if (!options) {
57 | onParallel = local.utility2.onParallel(onError);
58 | onParallel.counter += 1;
59 | [
60 | '',
61 | 'pet',
62 | 'store',
63 | 'user'
64 | ].forEach(function (api) {
65 | // test create handling-behavior
66 | [
67 | 'crudCreateMany',
68 | 'crudReplaceMany',
69 | 'createUsersWithArrayInput',
70 | 'createUsersWithListInput'
71 | ].forEach(function (operationId) {
72 | onParallel.counter += 1;
73 | local.testCase_crudCreateMany_default({
74 | api: api,
75 | id: 'test_' + local.utility2.uuidTime(),
76 | operationId: operationId
77 | }, onParallel);
78 | });
79 | // test upsert handling-behavior
80 | [
81 | 'crudReplaceMany'
82 | ].forEach(function (operationId) {
83 | onParallel.counter += 1;
84 | local.testCase_crudCreateMany_default({
85 | api: api,
86 | id: 'test_' + local.utility2.uuidTime(),
87 | operationId: operationId,
88 | upsert: true
89 | }, onParallel);
90 | });
91 | });
92 | onParallel();
93 | return;
94 | }
95 | onError2 = function (error, data) {
96 | if (error) {
97 | // update error.message
98 | local.utility2.errorMessagePrepend(error, options.api + '.' +
99 | options.operationId + ' - ');
100 | }
101 | onError(error, data);
102 | };
103 | modeNext = 0;
104 | onNext = function (error, data) {
105 | local.utility2.testTryCatch(function () {
106 | modeNext = error
107 | ? Infinity
108 | : modeNext + 1;
109 | switch (modeNext) {
110 | case 1:
111 | // init options
112 | options.body = [
113 | local.optionsId({ id: options.id + '0', propRequired: true }),
114 | local.optionsId({ id: options.id + '1', propRequired: true }),
115 | // test default id handling-behavior
116 | local.optionsId({ propRequired: true })
117 | ];
118 | options.modeErrorData = true;
119 | // init api
120 | options.api = options.api || '_test';
121 | api = local.swmg.api[options.api];
122 | // if api does not have the operation, then skip testCase
123 | if (!api[options.operationId]) {
124 | onError2();
125 | return;
126 | }
127 | // test crudCreateMany's default handling-behavior
128 | data = local.utility2.jsonCopy(options);
129 | api[options.operationId](data, options, onNext);
130 | break;
131 | case 2:
132 | // validate object
133 | data = data.obj.data;
134 | local.utility2.assert(data.length === options.body.length, data.length);
135 | switch (options.operationId) {
136 | case 'crudReplaceMany':
137 | if (!options.upsert) {
138 | local.utility2.assert(data.every(function (element) {
139 | return !element;
140 | }), data);
141 | modeNext = Infinity;
142 | onNext();
143 | return;
144 | }
145 | break;
146 | }
147 | local.utility2.assert(data.every(function (element) {
148 | return element;
149 | }), data);
150 | options.body = data;
151 | // init query
152 | options.query = JSON.stringify({ id: { $in: options.body.map(
153 | function (element) {
154 | return element.id;
155 | }
156 | ) } });
157 | // validate object
158 | api.crudGetByQueryMany({
159 | limit: 8,
160 | query: options.query
161 | }, options, onNext);
162 | break;
163 | case 3:
164 | // validate object
165 | data = data.obj.data;
166 | local.utility2.assert(data.length === options.body.length, data.length);
167 | local.utility2.assert(data.every(function (element) {
168 | return element;
169 | }), data);
170 | onNext();
171 | break;
172 | default:
173 | // validate no error occurred
174 | local.utility2.assert(!error, error);
175 | // remove object by query
176 | local.testCase_crudDeleteByQueryMany_default(options, onError2);
177 | }
178 | }, onError2);
179 | };
180 | onNext(options && options.error);
181 | };
182 |
183 | local.testCase_crudCreateXxx_default = function (options, onError) {
184 | /*
185 | * this function will test crudCreateXxx's default handling-behavior
186 | */
187 | var api, modeNext, onError2, onNext, onParallel;
188 | if (!options) {
189 | onParallel = local.utility2.onParallel(onError);
190 | onParallel.counter += 1;
191 | [
192 | '',
193 | 'pet',
194 | 'store',
195 | 'user'
196 | ].forEach(function (api) {
197 | // test create handling-behavior
198 | [
199 | 'crudCreateOne',
200 | 'crudReplaceOne',
201 | 'crudUpdateOne',
202 | 'updatePet',
203 | 'updatePetWithForm',
204 | 'updateUser'
205 | ].forEach(function (operationId) {
206 | onParallel.counter += 1;
207 | local.testCase_crudCreateXxx_default({
208 | api: api,
209 | id: 'test_' + local.utility2.uuidTime(),
210 | operationId: operationId
211 | }, onParallel);
212 | });
213 | // test upsert handling-behavior
214 | [
215 | 'crudReplaceOne',
216 | 'crudUpdateOne'
217 | ].forEach(function (operationId) {
218 | onParallel.counter += 1;
219 | local.testCase_crudCreateXxx_default({
220 | api: api,
221 | id: 'test_' + local.utility2.uuidTime(),
222 | operationId: operationId,
223 | upsert: true
224 | }, onParallel);
225 | });
226 | });
227 | onParallel();
228 | return;
229 | }
230 | onError2 = function (error, data) {
231 | if (error) {
232 | // update error.message
233 | local.utility2.errorMessagePrepend(error, options.api + '.' +
234 | options.operationId + ' - ');
235 | }
236 | onError(error, data);
237 | };
238 | modeNext = 0;
239 | onNext = function (error, data) {
240 | local.utility2.testTryCatch(function () {
241 | modeNext += 1;
242 | switch (modeNext) {
243 | case 1:
244 | // validate no error occurred
245 | local.utility2.assert(!error, error);
246 | // init options
247 | options.body = local.optionsId({
248 | id: options.id,
249 | propExtra: 'hello',
250 | propRequired: true
251 | });
252 | options.modeErrorData = true;
253 | // init api
254 | options.api = options.api || '_test';
255 | api = local.swmg.api[options.api];
256 | // if api does not have the operation, then skip testCase
257 | if (!api[options.operationId]) {
258 | onError2();
259 | return;
260 | }
261 | // get object
262 | api.crudGetByIdOne(local.optionsId({
263 | id: options.id
264 | }), options, onNext);
265 | break;
266 | case 2:
267 | // validate no error occurred
268 | local.utility2.assert(!error, error);
269 | // validate object does not exist
270 | local.utility2.assert(data.obj.data[0] === null, data.obj.data[0]);
271 | // test createXxx's default handling-behavior
272 | data = local.utility2.jsonCopy(options);
273 | api[options.operationId](local.optionsId(data), options, onNext);
274 | break;
275 | case 3:
276 | switch (options.operationId) {
277 | case 'crudReplaceOne':
278 | case 'crudUpdateOne':
279 | if (!options.upsert) {
280 | // validate error occurred
281 | local.utility2.assert(error, error);
282 | modeNext = Infinity;
283 | onNext();
284 | return;
285 | }
286 | break;
287 | default:
288 | // validate no error occurred
289 | local.utility2.assert(!error, error);
290 | }
291 | // validate object
292 | data = data.obj.data[0];
293 | options._timeCreated = data._timeCreated;
294 | options._timeModified = data._timeModified;
295 | local.utility2.assert(data.name === options.id, data.name);
296 | local.utility2.assert(data.status === options.id, data.status);
297 | switch (options.operationId) {
298 | case 'updatePetWithForm':
299 | local.utility2
300 | .assert(data.propExtra === undefined, data.propExtra);
301 | local.utility2
302 | .assert(data.propRequired === undefined, data.propRequired);
303 | break;
304 | default:
305 | local.utility2.assert(data.propExtra === 'hello', data.propExtra);
306 | local.utility2
307 | .assert(data.propRequired === true, data.propRequired);
308 | }
309 | // get object
310 | api.crudGetByIdOne(local.optionsId({
311 | id: options.id
312 | }), options, onNext);
313 | break;
314 | case 4:
315 | // validate no error occurred
316 | local.utility2.assert(!error, error);
317 | // validate object
318 | data = data.obj.data[0];
319 | local.utility2.assert(
320 | data._timeCreated === options._timeCreated,
321 | [data._timeCreated, options._timeCreated]
322 | );
323 | local.utility2.assert(
324 | data._timeModified === options._timeModified,
325 | [data._timeModified, options._timeModified]
326 | );
327 | local.utility2.assert(data.name === options.id, data.name);
328 | local.utility2.assert(data.status === options.id, data.status);
329 | switch (options.operationId) {
330 | case 'updatePetWithForm':
331 | local.utility2
332 | .assert(data.propExtra === undefined, data.propExtra);
333 | local.utility2
334 | .assert(data.propRequired === undefined, data.propRequired);
335 | break;
336 | default:
337 | local.utility2.assert(data.propExtra === 'hello', data.propExtra);
338 | local.utility2
339 | .assert(data.propRequired === true, data.propRequired);
340 | }
341 | switch (options.operationId) {
342 | case 'crudCreateOne':
343 | // test duplicate createXxx's error handling-behavior
344 | data = local.utility2.jsonCopy(options);
345 | api[options.operationId](local.optionsId(data), options, onNext);
346 | break;
347 | default:
348 | onNext();
349 | }
350 | break;
351 | case 5:
352 | switch (options.operationId) {
353 | case 'crudCreateOne':
354 | // validate error occurred
355 | local.utility2.assert(error, error);
356 | modeNext = Infinity;
357 | onNext();
358 | return;
359 | default:
360 | // validate no error occurred
361 | local.utility2.assert(!error, error);
362 | }
363 | onNext();
364 | break;
365 | default:
366 | if (options.modeNoDelete) {
367 | onError2(error, options);
368 | return;
369 | }
370 | // validate no error occurred
371 | local.utility2.assert(!error, error);
372 | // remove object by id
373 | local.testCase_crudDeleteByIdOne_default(options, onError2);
374 | }
375 | }, onError2);
376 | };
377 | onNext(options && options.error);
378 | };
379 |
380 | local.testCase_crudEcho_default = function (options, onError) {
381 | /*
382 | * this function will test crudEcho's default handling-behavior
383 | */
384 | // jslint-hack
385 | local.utility2.nop(options);
386 | local.swmg.api._test.echo({
387 | id: 'test_' + local.utility2.uuidTime(),
388 | // test array-csv-param handling-behavior
389 | paramArrayCsv: 'aa,bb',
390 | // test array-pipes-param handling-behavior
391 | paramArrayPipes: 'aa|bb',
392 | // test array-ssv-param handling-behavior
393 | paramArraySsv: 'aa bb',
394 | // test array-tsv-param handling-behavior
395 | paramArrayTsv: 'aa\tbb',
396 | // test body-param handling-behavior
397 | paramBody: 'hello!',
398 | // test header-param handling-behavior
399 | paramHeader: 'hello'
400 | }, { modeErrorData: true }, function (error, data) {
401 | local.utility2.testTryCatch(function () {
402 | // validate no error occurred
403 | local.utility2.assert(!error, error);
404 | // validate object
405 | data = local.utility2.jsonStringifyOrdered(data.obj);
406 | local.utility2.assert(data === JSON.stringify({
407 | paramArrayCsv: ['aa', 'bb'],
408 | paramArrayPipes: ['aa', 'bb'],
409 | paramArraySsv: ['aa', 'bb'],
410 | paramArrayTsv: ['aa', 'bb'],
411 | paramBody: 'hello!',
412 | paramHeader: 'hello'
413 | }), data);
414 | onError();
415 | }, onError);
416 | });
417 | };
418 |
419 | local.testCase_crudGetXxx_default = function (options, onError) {
420 | /*
421 | * this function will test crudGetXxx's default handling-behavior
422 | */
423 | var api, modeNext, onError2, onNext, onParallel;
424 | if (!options) {
425 | onParallel = local.utility2.onParallel(onError);
426 | onParallel.counter += 1;
427 | [
428 | '',
429 | 'pet',
430 | 'store',
431 | 'user'
432 | ].forEach(function (api) {
433 | [
434 | 'crudAggregateMany',
435 | 'crudCountByQueryOne',
436 | 'crudGetByIdOne',
437 | 'crudGetByQueryMany',
438 | 'crudGetDistinctValueByPropertyMany',
439 | 'crudExistsByIdOne',
440 | 'findPetsByStatus',
441 | 'findPetsByTags',
442 | 'getInventory'
443 | ].forEach(function (operationId) {
444 | onParallel.counter += 1;
445 | local.testCase_crudGetXxx_default({
446 | api: api,
447 | id: 'test_' + local.utility2.uuidTime(),
448 | operationId: operationId
449 | }, onParallel);
450 | });
451 | });
452 | onParallel();
453 | return;
454 | }
455 | onError2 = function (error, data) {
456 | if (error) {
457 | // update error.message
458 | local.utility2.errorMessagePrepend(error, options.api + '.' +
459 | options.operationId + ' - ');
460 | }
461 | onError(error, data);
462 | };
463 | modeNext = 0;
464 | onNext = function (error, data) {
465 | local.utility2.testTryCatch(function () {
466 | modeNext = error
467 | ? Infinity
468 | : modeNext + 1;
469 | switch (modeNext) {
470 | case 1:
471 | // init options
472 | options.field = 'id';
473 | options.limit = 2;
474 | options.modeErrorData = true;
475 | options.query = JSON.stringify({ id: options.id });
476 | // init api
477 | options.api = options.api || '_test';
478 | api = local.swmg.api[options.api];
479 | // if api does not have the operation, then skip testCase
480 | if (!api[options.operationId]) {
481 | onError2();
482 | return;
483 | }
484 | // create object
485 | local.testCase_crudCreateXxx_default({
486 | api: options.api,
487 | id: options.id,
488 | modeNoDelete: true,
489 | operationId: 'crudCreateOne'
490 | }, onNext);
491 | break;
492 | case 2:
493 | // validate object exists
494 | data = local.utility2.jsonCopy(options);
495 | data.body = [{ $group: { "_id": "all", "count": { "$sum": 1 } } }];
496 | data.tags = options.id;
497 | api[options.operationId](local.optionsId(data), options, onNext);
498 | break;
499 | case 3:
500 | // validate object exists
501 | data = data.obj.data;
502 | switch (options.operationId) {
503 | case 'crudAggregateMany':
504 | case 'crudGetDistinctValueByPropertyMany':
505 | case 'getInventory':
506 | local.utility2.assert(data.length >= 1, data.length);
507 | break;
508 | default:
509 | local.utility2.assert(data.length === 1, data.length);
510 | }
511 | local.utility2.assert(data[0], data[0]);
512 | onNext();
513 | break;
514 | default:
515 | // validate no error occurred
516 | local.utility2.assert(!error, error);
517 | // remove object by id
518 | local.testCase_crudDeleteByIdOne_default(options, onError2);
519 | }
520 | }, onError2);
521 | };
522 | onNext(options && options.error);
523 | };
524 |
525 | local.testCase_crudDeleteByQueryMany_default = function (options, onError) {
526 | /*
527 | * this function will test crudDeleteByQueryMany's default handling-behavior
528 | */
529 | var api, modeNext, onNext, onParallel;
530 | modeNext = 0;
531 | onNext = function (error, data) {
532 | local.utility2.testTryCatch(function () {
533 | modeNext = error
534 | ? Infinity
535 | : modeNext + 1;
536 | switch (modeNext) {
537 | case 1:
538 | // init options
539 | options = options || {};
540 | options.id = options.id || local.utility2.uuidTime();
541 | options.modeErrorData = true;
542 | // init api
543 | options.api = options.api || '_test';
544 | api = local.swmg.api[options.api];
545 | // remove object by query
546 | options.query = options.query || '{"id":{"$in":["id0","id1"]}}';
547 | if (!api.crudDeleteByQueryMany) {
548 | onParallel = local.utility2.onParallel(onNext);
549 | onParallel.counter += 1;
550 | JSON.parse(options.query).id.$in.forEach(function (id) {
551 | onParallel.counter += 1;
552 | api.crudDeleteByIdOne(local
553 | .optionsId({ id: id }), options, onParallel);
554 | });
555 | onParallel();
556 | return;
557 | }
558 | api.crudDeleteByQueryMany({ query: options.query }, options, onNext);
559 | break;
560 | case 2:
561 | // validate object does not exist
562 | api.crudGetByQueryMany({
563 | limit: 8,
564 | query: options.query
565 | }, options, onNext);
566 | break;
567 | case 3:
568 | // validate object does not exist
569 | data = data.obj.data;
570 | local.utility2.assert(data.length === 0, data.length);
571 | onNext();
572 | break;
573 | default:
574 | onError(error);
575 | }
576 | }, onError);
577 | };
578 | onNext(options && options.error);
579 | };
580 |
581 | local.testCase_crudDeleteByIdOne_default = function (options, onError) {
582 | /*
583 | * this function will test crudDeleteByIdOne's default handling-behavior
584 | */
585 | var api, modeNext, onNext;
586 | modeNext = 0;
587 | onNext = function (error, data) {
588 | local.utility2.testTryCatch(function () {
589 | modeNext = error
590 | ? Infinity
591 | : modeNext + 1;
592 | switch (modeNext) {
593 | case 1:
594 | // init options
595 | options = options || {};
596 | options.id = options.id || local.utility2.uuidTime();
597 | options.modeErrorData = true;
598 | // init api
599 | options.api = options.api || '_test';
600 | api = local.swmg.api[options.api];
601 | // remove object by id
602 | api.crudDeleteByIdOne(local.optionsId({
603 | id: options.id
604 | }), options, onNext);
605 | break;
606 | case 2:
607 | // validate object does not exist
608 | api.crudGetByIdOne(local.optionsId({
609 | id: options.id
610 | }), options, onNext);
611 | break;
612 | case 3:
613 | // validate object does not exist
614 | local.utility2.assert(data.obj.data[0] === null, data.obj.data[0]);
615 | onNext();
616 | break;
617 | default:
618 | onError(error);
619 | }
620 | }, onError);
621 | };
622 | onNext(options && options.error);
623 | };
624 |
625 | local.testCase_crudReplaceXxx_default = function (options, onError) {
626 | /*
627 | * this function will test crudReplaceXxx's default handling-behavior
628 | */
629 | var api, modeNext, onError2, onNext, onParallel;
630 | if (!options) {
631 | onParallel = local.utility2.onParallel(onError);
632 | onParallel.counter += 1;
633 | [
634 | '',
635 | 'pet',
636 | 'store',
637 | 'user'
638 | ].forEach(function (api) {
639 | // test update handling-behavior
640 | [
641 | 'crudReplaceOne',
642 | 'crudUpdateOne',
643 | 'updatePetWithForm'
644 | ].forEach(function (operationId) {
645 | onParallel.counter += 1;
646 | local.testCase_crudReplaceXxx_default({
647 | api: api,
648 | id: 'test_' + local.utility2.uuidTime(),
649 | operationId: operationId
650 | }, onParallel);
651 | });
652 | // test upsert handling-behavior
653 | [
654 | 'crudReplaceOne',
655 | 'crudUpdateOne'
656 | ].forEach(function (operationId) {
657 | onParallel.counter += 1;
658 | local.testCase_crudReplaceXxx_default({
659 | api: api,
660 | id: 'test_' + local.utility2.uuidTime(),
661 | operationId: operationId,
662 | upsert: true
663 | }, onParallel);
664 | });
665 | });
666 | onParallel();
667 | return;
668 | }
669 | onError2 = function (error, data) {
670 | if (error) {
671 | // update error.message
672 | local.utility2.errorMessagePrepend(error, options.api + '.' +
673 | options.operationId + ' - ');
674 | }
675 | onError(error, data);
676 | };
677 | modeNext = 0;
678 | onNext = function (error, data) {
679 | local.utility2.testTryCatch(function () {
680 | modeNext = error
681 | ? Infinity
682 | : modeNext + 1;
683 | switch (modeNext) {
684 | case 1:
685 | // init options
686 | options.body = local.optionsId({
687 | id: options.id,
688 | propRequired: false
689 | });
690 | options.modeErrorData = true;
691 | // init api
692 | options.api = options.api || '_test';
693 | api = local.swmg.api[options.api];
694 | // if api does not have the operation, then skip testCase
695 | if (!api[options.operationId]) {
696 | onError2();
697 | return;
698 | }
699 | // create object
700 | local.testCase_crudCreateXxx_default({
701 | api: options.api,
702 | id: options.id,
703 | modeNoDelete: true,
704 | operationId: 'crudCreateOne'
705 | }, onNext);
706 | break;
707 | case 2:
708 | options._timeCreated = data._timeCreated;
709 | options._timeModified = data._timeModified;
710 | // test updateXxx's default handling-behavior
711 | data = local.utility2.jsonCopy(options);
712 | api[options.operationId](local.optionsId(data), options, onNext);
713 | break;
714 | case 3:
715 | // validate object
716 | data = data.obj.data[0];
717 | local.utility2.assert(
718 | data._timeModified > options._timeModified,
719 | [data._timeModified, options._timeModified]
720 | );
721 | local.utility2.assert(data.name === options.id, data.name);
722 | local.utility2.assert(data.status === options.id, data.status);
723 | switch (options.operationId) {
724 | case 'crudReplaceOne':
725 | local.utility2.assert(
726 | data._timeCreated > options._timeCreated,
727 | [data._timeCreated, options._timeCreated]
728 | );
729 | local.utility2
730 | .assert(data.propExtra === undefined, data.propExtra);
731 | local.utility2
732 | .assert(data.propRequired === false, data.propRequired);
733 | break;
734 | case 'updatePetWithForm':
735 | local.utility2.assert(
736 | data._timeCreated === options._timeCreated,
737 | [data._timeCreated, options._timeCreated]
738 | );
739 | local.utility2.assert(data.propExtra === 'hello', data.propExtra);
740 | local.utility2
741 | .assert(data.propRequired === true, data.propRequired);
742 | break;
743 | default:
744 | local.utility2.assert(
745 | data._timeCreated === options._timeCreated,
746 | [data._timeCreated, options._timeCreated]
747 | );
748 | local.utility2.assert(data.propExtra === 'hello', data.propExtra);
749 | local.utility2
750 | .assert(data.propRequired === false, data.propRequired);
751 | }
752 | // get object
753 | api.crudGetByIdOne(local.optionsId({
754 | id: options.id
755 | }), options, onNext);
756 | break;
757 | case 4:
758 | // validate object
759 | data = data.obj.data[0];
760 | local.utility2.assert(
761 | data._timeModified > options._timeModified,
762 | [data._timeModified, options._timeModified]
763 | );
764 | local.utility2.assert(data.name === options.id, data.name);
765 | local.utility2.assert(data.status === options.id, data.status);
766 | switch (options.operationId) {
767 | case 'crudReplaceOne':
768 | local.utility2.assert(
769 | data._timeCreated > options._timeCreated,
770 | [data._timeCreated, options._timeCreated]
771 | );
772 | local.utility2
773 | .assert(data.propExtra === undefined, data.propExtra);
774 | local.utility2
775 | .assert(data.propRequired === false, data.propRequired);
776 | break;
777 | case 'updatePetWithForm':
778 | local.utility2.assert(
779 | data._timeCreated === options._timeCreated,
780 | [data._timeCreated, options._timeCreated]
781 | );
782 | local.utility2.assert(data.propExtra === 'hello', data.propExtra);
783 | local.utility2
784 | .assert(data.propRequired === true, data.propRequired);
785 | break;
786 | default:
787 | local.utility2.assert(
788 | data._timeCreated === options._timeCreated,
789 | [data._timeCreated, options._timeCreated]
790 | );
791 | local.utility2.assert(data.propExtra === 'hello', data.propExtra);
792 | local.utility2
793 | .assert(data.propRequired === false, data.propRequired);
794 | }
795 | onNext();
796 | break;
797 | default:
798 | // validate no error occurred
799 | local.utility2.assert(!error, error);
800 | // remove object by id
801 | local.testCase_crudDeleteByIdOne_default(options, onError2);
802 | }
803 | }, onError2);
804 | };
805 | onNext(options && options.error);
806 | };
807 |
808 | local.testCase_crudUploadFile_default = function (options, onError) {
809 | /*
810 | * this function will test crudUploadFile's default handling-behavior
811 | */
812 | var api, modeNext, onNext;
813 | modeNext = 0;
814 | onNext = function (error, data) {
815 | local.utility2.testTryCatch(function () {
816 | modeNext = error
817 | ? Infinity
818 | : modeNext + 1;
819 | switch (modeNext) {
820 | case 1:
821 | // init options
822 | options = options || {};
823 | options.id = options.id || local.utility2.uuidTime();
824 | options.modeErrorData = true;
825 | // init api
826 | options.api = 'pet';
827 | api = local.swmg.api[options.api];
828 | // create object
829 | local.testCase_crudCreateXxx_default({
830 | api: options.api,
831 | id: options.id,
832 | modeNoDelete: true,
833 | operationId: 'crudCreateOne'
834 | }, onNext);
835 | break;
836 | case 2:
837 | options._timeCreated = data._timeCreated;
838 | options._timeModified = data._timeModified;
839 | // test file-upload handling-behavior
840 | local.utility2.ajax({
841 | /* jslint-ignore-begin */
842 | data: '------FormBoundaryXxx\r\nContent-Disposition: form-data; name="additionalMetadata"\r\n\r\nhello\r\n------FormBoundaryXxx\r\nContent-Disposition: form-data; name="file"; filename="hello.png"\r\nContent-Type: image/png\r\n\r\ndata\r\n------FormBoundaryXxx--\r\n',
843 | /* jslint-ignore-end */
844 | headers: {
845 | 'Content-Type':
846 | 'multipart/form-data; boundary=----FormBoundaryXxx'
847 | },
848 | method: 'POST',
849 | url: '/api/v0/pet/' + options.id + '/uploadImage'
850 | }, onNext);
851 | break;
852 | case 3:
853 | // validate object
854 | data = JSON.parse(data.responseText).data[0];
855 | local.utility2.assert(
856 | data._timeCreated === options._timeCreated,
857 | [data._timeCreated, options._timeCreated]
858 | );
859 | local.utility2.assert(
860 | data._timeModified > options._timeModified,
861 | [data._timeModified, options._timeModified]
862 | );
863 | local.utility2.assert(
864 | data.additionalMetadata === 'hello',
865 | data.additionalMetadata
866 | );
867 | local.utility2.assert(data.file === 'ZGF0YQ==', data.file);
868 | local.utility2.assert(data.filename === 'hello.png', data.filename);
869 | local.utility2.assert(data.petId === options.id, data.petId);
870 | local.utility2.assert(data.propExtra === 'hello', data.propExtra);
871 | local.utility2
872 | .assert(data.propRequired === true, data.propRequired);
873 | // get object
874 | api.crudGetByIdOne(local.optionsId({
875 | id: options.id
876 | }), options, onNext);
877 | break;
878 | case 4:
879 | // validate object
880 | data = data.obj.data[0];
881 | local.utility2.assert(
882 | data._timeCreated === options._timeCreated,
883 | [data._timeCreated, options._timeCreated]
884 | );
885 | local.utility2.assert(
886 | data._timeModified > options._timeModified,
887 | [data._timeModified, options._timeModified]
888 | );
889 | onNext();
890 | break;
891 | default:
892 | // validate no error occurred
893 | local.utility2.assert(!error, error);
894 | // remove object by id
895 | local.testCase_crudDeleteByIdOne_default(options, onError);
896 | }
897 | }, onError);
898 | };
899 | onNext(options && options.error);
900 | };
901 |
902 | local.testCase_crudXxx_error = function (options, onError) {
903 | /*
904 | * this function will test crudXxx's error handling-behavior
905 | */
906 | var api, onParallel, optionsCopy;
907 | onParallel = local.utility2.onParallel(onError);
908 | onParallel.counter += 1;
909 | // init options
910 | options = {};
911 | options.modeErrorData = true;
912 | options.paramHeader = '1';
913 | // init api
914 | api = local.swmg.api._test;
915 | // test api-error handling-behavior
916 | [
917 | 'errorMiddleware',
918 | 'errorUndefinedApi',
919 | 'errorUndefinedCrud'
920 | ].forEach(function (operationId) {
921 | optionsCopy = local.utility2.jsonCopy(options);
922 | optionsCopy.id = 'test_' + local.utility2.uuidTime();
923 | optionsCopy.operationId = operationId;
924 | onParallel.counter += 1;
925 | api[optionsCopy.operationId](optionsCopy, optionsCopy, function (error) {
926 | local.utility2.testTryCatch(function () {
927 | // validate error occurred
928 | local.utility2.assert(error, error);
929 | onParallel();
930 | }, onParallel);
931 | });
932 | });
933 | // test low-level ajax-error handling-behavior
934 | [{
935 | url: '/api/v0/_test/errorUndefined'
936 | }].forEach(function (options) {
937 | onParallel.counter += 1;
938 | local.utility2.ajax(options, function (error) {
939 | local.utility2.testTryCatch(function () {
940 | // validate error occurred
941 | local.utility2.assert(error, error);
942 | onParallel();
943 | }, onParallel);
944 | });
945 | });
946 | // test testCase-error handling-behavior
947 | [
948 | 'testCase_collectionCreate_misc',
949 | 'testCase_crudAggregateMany_default',
950 | 'testCase_crudCreateMany_default',
951 | 'testCase_crudCreateXxx_default',
952 | 'testCase_crudGetXxx_default',
953 | 'testCase_crudDeleteByIdOne_default',
954 | 'testCase_crudDeleteByQueryMany_default',
955 | 'testCase_crudReplaceXxx_default',
956 | 'testCase_crudUploadFile_default'
957 | ].forEach(function (testCase) {
958 | if (local[testCase]) {
959 | onParallel.counter += 1;
960 | local[testCase]({
961 | error: local.utility2.errorDefault
962 | }, function (error) {
963 | local.utility2.testTryCatch(function () {
964 | // validate error occurred
965 | local.utility2.assert(error, error);
966 | onParallel();
967 | }, onParallel);
968 | });
969 | }
970 | });
971 | onParallel();
972 | };
973 |
974 | local.testCase_validateByParamDefList_default = function (options, onError) {
975 | /*
976 | * this function will test validateByParamDefList's default handling-behavior
977 | */
978 | var error;
979 | // jslint-hack
980 | local.utility2.nop(options);
981 | [{
982 | data: { body: { propRequired: true } },
983 | key: 'crudCreateOne',
984 | method: 'post'
985 | }, {
986 | data: { query: '{}' },
987 | key: 'crudCountByQueryOne',
988 | method: 'get'
989 | }].forEach(function (options) {
990 | options.paramDefList = local.swmg.swaggerJson
991 | .paths['/_test/' + options.key][options.method]
992 | .parameters;
993 | local.swmg.validateByParamDefList(options);
994 | });
995 | // test validateByParamDefList's error handling-behavior
996 | [{
997 | data: { body: { propRequired: null } },
998 | key: 'crudCreateOne',
999 | method: 'post'
1000 | }, {
1001 | data: { query: 'syntax error' },
1002 | key: 'crudCountByQueryOne',
1003 | method: 'get'
1004 | }].forEach(function (options) {
1005 | try {
1006 | error = null;
1007 | options.paramDefList = local.swmg.swaggerJson
1008 | .paths['/_test/' + options.key][options.method]
1009 | .parameters;
1010 | local.swmg.validateByParamDefList(options);
1011 | } catch (errorCaught) {
1012 | error = errorCaught;
1013 | }
1014 | // validate error occurred
1015 | local.utility2.assert(error, error);
1016 | });
1017 | // test validateByPropertyDef's circular-reference handling-behavior
1018 | local.swmg.validateByPropertyDef({
1019 | data: { propObject: {} },
1020 | propertyDef: { propObject: { type: 'object' } }
1021 | });
1022 | onError();
1023 | };
1024 |
1025 | local.testCase_validateBySchema_default = function (options, onError) {
1026 | /*
1027 | * this function will test validateBySchema's default handling-behavior
1028 | */
1029 | var optionsCopy;
1030 | options = {
1031 | data: { propRequired: true },
1032 | schema: local.swmg.swaggerJson.definitions.TestCrudModel
1033 | };
1034 | [
1035 | { key: 'propArray', value: [null] },
1036 | { key: 'propArraySubdoc', value: [{ propRequired: true }] },
1037 | { key: 'propBoolean', value: true },
1038 | { key: 'propInteger', value: 0 },
1039 | { key: 'propIntegerInt32', value: 0 },
1040 | { key: 'propIntegerInt64', value: 0 },
1041 | { key: 'propNumberFloat', value: 0.5 },
1042 | { key: 'propNumberDouble', value: 0.5 },
1043 | { key: 'propObject', value: {} },
1044 | { key: 'propObjectSubdoc', value: {} },
1045 | { key: 'propString', value: '' },
1046 | { key: 'propStringByte', value: local.modeJs === 'browser'
1047 | ? local.global.btoa(local.utility2.stringAsciiCharset)
1048 | : new Buffer(local.utility2.stringAsciiCharset).toString('base64') },
1049 | { key: 'propStringDate', value: '1971-01-01' },
1050 | { key: 'propStringDatetime', value: '1971-01-01T00:00:00Z' },
1051 | { key: 'propStringEmail', value: 'q@q.com' },
1052 | { key: 'propStringJson', value: 'null' },
1053 | { key: 'propUndefined', value: null },
1054 | { key: 'propUndefined', value: undefined },
1055 | { key: 'propUndefined', value: true }
1056 | ].forEach(function (element) {
1057 | optionsCopy = local.utility2.jsonCopy(options.data);
1058 | optionsCopy[element.key] = element.value;
1059 | // test circular-reference handling-behavior
1060 | optionsCopy.propArraySubdoc = optionsCopy.propArraySubdoc || [optionsCopy];
1061 | optionsCopy.propObject = optionsCopy.propObject || optionsCopy;
1062 | optionsCopy.propObjectSubdoc = optionsCopy.propObjectSubdoc || optionsCopy;
1063 | local.swmg.validateBySchema({ data: optionsCopy, schema: options.schema });
1064 | });
1065 | onError();
1066 | };
1067 |
1068 | local.testCase_validateBySchema_error = function (options, onError) {
1069 | /*
1070 | * this function will test validateBySchema's error handling-behavior
1071 | */
1072 | var error, optionsCopy;
1073 | options = {
1074 | data: { propRequired: true },
1075 | schema: local.swmg.swaggerJson.definitions.TestCrudModel
1076 | };
1077 | [
1078 | { data: null },
1079 | { key: 'propArray', value: true },
1080 | { key: 'propArraySubdoc', value: [{ propRequired: null }] },
1081 | { key: 'propBoolean', value: 0 },
1082 | { key: 'propInteger', value: true },
1083 | { key: 'propInteger', value: Infinity },
1084 | { key: 'propInteger', value: NaN },
1085 | { key: 'propIntegerInt32', value: 0.5 },
1086 | { key: 'propIntegerInt64', value: 0.5 },
1087 | { key: 'propNumber', value: true },
1088 | { key: 'propNumber', value: Infinity },
1089 | { key: 'propNumber', value: NaN },
1090 | { key: 'propNumberFloat', value: true },
1091 | { key: 'propNumberDouble', value: true },
1092 | { key: 'propObject', value: true },
1093 | { key: 'propObjectSubdoc', value: 'non-object' },
1094 | { key: 'propRequired', value: null },
1095 | { key: 'propRequired', value: undefined },
1096 | { key: 'propString', value: true },
1097 | { key: 'propStringByte', value: local.utility2.stringAsciiCharset },
1098 | { key: 'propStringDate', value: 'null' },
1099 | { key: 'propStringDatetime', value: 'null' },
1100 | { key: 'propStringEmail', value: 'null' },
1101 | { key: 'propStringJson', value: 'syntax error' }
1102 | ].forEach(function (element) {
1103 | try {
1104 | error = null;
1105 | optionsCopy = local.utility2.jsonCopy(options.data);
1106 | optionsCopy[element.key] = element.value;
1107 | local.swmg.validateBySchema({
1108 | data: element.data === null
1109 | ? null
1110 | : optionsCopy,
1111 | schema: options.schema
1112 | });
1113 | } catch (errorCaught) {
1114 | error = errorCaught;
1115 | }
1116 | // validate error occurred
1117 | local.utility2.assert(error, error);
1118 | });
1119 | onError();
1120 | };
1121 |
1122 | local.testCase_validateBySwagger_default = function (options, onError) {
1123 | /*
1124 | * this function will test validateBySwagger's default handling-behavior
1125 | */
1126 | var error;
1127 | // jslint-hack
1128 | local.utility2.nop(options);
1129 | local.utility2.testMock([
1130 | // suppress console.error
1131 | [console, { error: local.utility2.nop }]
1132 | ], function (onError) {
1133 | [null, {}].forEach(function (element) {
1134 | try {
1135 | local.swmg.validateBySwagger(element);
1136 | } catch (errorCaught) {
1137 | error = errorCaught;
1138 | }
1139 | // validate error occurred
1140 | local.utility2.assert(error, error);
1141 | });
1142 | onError();
1143 | }, onError);
1144 | };
1145 | }());
1146 | switch (local.modeJs) {
1147 |
1148 |
1149 |
1150 | // run node js-env code
1151 | case 'node':
1152 | // init tests
1153 | local.testCase_collectionCreate_misc = function (options, onError) {
1154 | /*
1155 | * this function will test the collectionCreate's misc handling-behavior
1156 | */
1157 | var modeNext, onNext;
1158 | modeNext = 0;
1159 | onNext = function (error) {
1160 | modeNext = error
1161 | ? Infinity
1162 | : modeNext + 1;
1163 | switch (modeNext) {
1164 | case 1:
1165 | // test null schema handling-behavior
1166 | local.swmg.collectionCreate({
1167 | _collectionName: 'SwmgTestMisc',
1168 | // test _collectionReadonly handling-behavior
1169 | _collectionReadonly: true
1170 | }, onNext);
1171 | break;
1172 | case 2:
1173 | local.swmg.collectionCreate({
1174 | // test _collectionCreate handling-behavior
1175 | _collectionCreate: {},
1176 | // test _collectionDrop handling-behavior
1177 | _collectionDrop: true,
1178 | _collectionName: 'SwmgTestMisc'
1179 | }, onNext);
1180 | break;
1181 | case 3:
1182 | local.swmg.collectionCreate({
1183 | // test capped-collection handling-behavior
1184 | _collectionCreate: { capped: true, size: 1 },
1185 | // test _collectionCreateIndexList handling-behavior
1186 | _collectionCreateIndexList: [{
1187 | key: { propIndexed: 1 },
1188 | name: 'propIndexed_1'
1189 | }],
1190 | _collectionName: 'SwmgTestMisc'
1191 | }, onNext);
1192 | break;
1193 | default:
1194 | onError(error);
1195 | }
1196 | };
1197 | onNext(options && options.error);
1198 | };
1199 |
1200 | local.testCase_middlewareBodyParse_misc = function (options, onError) {
1201 | /*
1202 | * this function will test middlewareBodyParse's misc handling-behavior
1203 | */
1204 | var onParallel;
1205 | // jslint-hack
1206 | local.utility2.nop(options);
1207 | onParallel = local.utility2.onParallel(onError);
1208 | onParallel.counter += 1;
1209 | // test swmgBodyParsed exists handling-behavior
1210 | onParallel.counter += 1;
1211 | local.swmg.middlewareBodyParse({
1212 | swmgBodyParsed: {},
1213 | swmgMethodPath: { parameters: [] }
1214 | }, {}, onParallel);
1215 | onParallel();
1216 | };
1217 |
1218 | local.testCase_testPage_default = function (options, onError) {
1219 | /*
1220 | * this function will test the test-page's default handling-behavior
1221 | */
1222 | // jslint-hack
1223 | local.utility2.nop(options);
1224 | local.utility2.phantomTest({
1225 | url: 'http://localhost:' +
1226 | local.utility2.envDict.npm_config_server_port +
1227 | '?modeTest=phantom&timeExit={{timeExit}}'
1228 | }, onError);
1229 | };
1230 | break;
1231 | }
1232 | switch (local.modeJs) {
1233 |
1234 |
1235 |
1236 | // run browser js-env code
1237 | case 'browser':
1238 | // init swaggerUi
1239 | local.utility2.onReady.counter += 1;
1240 | window.swaggerUi = new window.SwaggerUi({
1241 | dom_id: "swagger-ui-container",
1242 | onComplete: function () {
1243 | local.swmg.swaggerJson = local.swmg.api.swaggerJson;
1244 | local.utility2.onReady();
1245 | },
1246 | supportedSubmitMethods: ['delete', 'get', 'patch', 'post', 'put'],
1247 | url: '/api/v0/swagger.json'
1248 | });
1249 | // init api
1250 | window.swaggerUi.load();
1251 | local.swmg.api = window.swaggerUi.api;
1252 | // run test
1253 | local.utility2.testRun(local);
1254 | break;
1255 |
1256 |
1257 |
1258 | // run node js-env code
1259 | case 'node':
1260 | // test null apiUpdate handling-behavior
1261 | local.swmg.apiUpdate({});
1262 | // init test api
1263 | local.swmg.apiUpdate({
1264 | definitions: {
1265 | // init TestCrudModel schema
1266 | TestCrudModel: {
1267 | // drop collection on init
1268 | _collectionDrop: true,
1269 | _collectionName: 'SwmgTestCrud',
1270 | // init default crud-api
1271 | _crudApi: '_test',
1272 | _crudApiList: [
1273 | 'crudAggregateMany',
1274 | 'crudCountByQueryOne',
1275 | 'crudCreateMany',
1276 | 'crudCreateOne',
1277 | 'crudDeleteByQueryMany',
1278 | 'crudDeleteByIdOne',
1279 | 'crudExistsByIdOne',
1280 | 'crudGetByIdOne',
1281 | 'crudGetByQueryMany',
1282 | 'crudGetDistinctValueByPropertyMany',
1283 | 'crudReplaceMany',
1284 | 'crudReplaceOne',
1285 | 'crudUpdateOne'
1286 | ],
1287 | properties: {
1288 | propArray: { items: {}, type: 'array' },
1289 | propArraySubdoc: {
1290 | default: [{ propRequired: true }],
1291 | items: { $ref: '#/definitions/TestCrudModel' },
1292 | type: 'array'
1293 | },
1294 | propBoolean: { type: 'boolean' },
1295 | propInteger: { type: 'integer' },
1296 | propIntegerInt32: { format: 'int32', type: 'integer' },
1297 | propIntegerInt64: { format: 'int64', type: 'integer' },
1298 | propNumber: { type: 'number' },
1299 | propNumberDouble: { format: 'double', type: 'number' },
1300 | propNumberFloat: { format: 'float', type: 'number' },
1301 | propObject: { type: 'object' },
1302 | propObjectSubdoc: { $ref: '#/definitions/TestNullModel' },
1303 | propRequired: { default: true },
1304 | propString: { type: 'string' },
1305 | propStringByte: { format: 'byte', type: 'string' },
1306 | propStringDate: { format: 'date', type: 'string' },
1307 | propStringDatetime: { format: 'date-time', type: 'string' },
1308 | propStringEmail:
1309 | { default: 'a@a.com', format: 'email', type: 'string' },
1310 | propStringJson:
1311 | { default: 'null', format: 'json', type: 'string' },
1312 | propUndefined: {}
1313 | },
1314 | required: ['propRequired'],
1315 | 'x-inheritList': [{ $ref: '#/definitions/JsonapiResource' }]
1316 | },
1317 | // init TestNullModel schema
1318 | TestNullModel: {}
1319 | },
1320 | paths: {
1321 | // test custom api handling-behavior
1322 | '/_test/echo': { post: {
1323 | _collectionName: 'SwmgTestCrud',
1324 | operationId: 'echo',
1325 | parameters: [{
1326 | // test array-csv-param handling-behavior
1327 | collectionFormat: 'csv',
1328 | description: 'csv-array param',
1329 | in: 'query',
1330 | items: { type: 'string' },
1331 | name: 'paramArrayCsv',
1332 | type: 'array'
1333 | }, {
1334 | // test array-pipes-param handling-behavior
1335 | collectionFormat: 'pipes',
1336 | description: 'pipes-array param',
1337 | in: 'query',
1338 | items: { type: 'string' },
1339 | name: 'paramArrayPipes',
1340 | type: 'array'
1341 | }, {
1342 | // test array-ssv-param handling-behavior
1343 | collectionFormat: 'ssv',
1344 | description: 'ssv-array param',
1345 | in: 'query',
1346 | items: { type: 'string' },
1347 | name: 'paramArraySsv',
1348 | type: 'array'
1349 | }, {
1350 | // test array-tsv-param handling-behavior
1351 | collectionFormat: 'tsv',
1352 | description: 'tsv-array param',
1353 | in: 'query',
1354 | items: { type: 'string' },
1355 | name: 'paramArrayTsv',
1356 | type: 'array'
1357 | }, {
1358 | description: 'body',
1359 | // test body-param handling-behavior
1360 | in: 'body',
1361 | name: 'paramBody',
1362 | schema: { $ref: '#/definitions/Undefined' }
1363 | }, {
1364 | description: 'header param',
1365 | // test header-param handling-behavior
1366 | in: 'header',
1367 | name: 'paramHeader',
1368 | type: 'string'
1369 | }, {
1370 | description: 'optional param',
1371 | in: 'query',
1372 | // test optional-param handling-behavior
1373 | name: 'paramOptional',
1374 | type: 'string'
1375 | }],
1376 | summary: 'echo request params back to client',
1377 | tags: ['_test']
1378 | } },
1379 | // test midddleware-error handling-behavior
1380 | '/_test/errorMiddleware': { get: {
1381 | operationId: 'errorMiddleware',
1382 | tags: ['_test']
1383 | } },
1384 | // test undefined api handling-behavior
1385 | '/_test/errorUndefinedApi': { get: {
1386 | operationId: 'errorUndefinedApi',
1387 | tags: ['_test']
1388 | } },
1389 | // test undefined crud-api handling-behavior
1390 | '/_test/errorUndefinedCrud': { get: {
1391 | _collectionName: 'SwmgTestCrud',
1392 | _crudApi: true,
1393 | operationId: 'errorUndefinedCrud',
1394 | tags: ['_test']
1395 | } }
1396 | },
1397 | _tagDict: { _test: { description: 'internal test-api' } }
1398 | });
1399 | // init test-middleware
1400 | local.middleware.middlewareList.push(function (request, response, nextMiddleware) {
1401 | switch (request.swmgPathname) {
1402 | case 'POST /_test/echo':
1403 | response.end(JSON.stringify(request.swmgParamDict));
1404 | break;
1405 | case 'GET /_test/errorMiddleware':
1406 | nextMiddleware(new Error('dummy error'));
1407 | break;
1408 | default:
1409 | nextMiddleware();
1410 | }
1411 | });
1412 | // run validation test
1413 | local.testCase_validateByParamDefList_default(null, local.utility2.onErrorDefault);
1414 | local.testCase_validateBySchema_default(null, local.utility2.onErrorDefault);
1415 | local.testCase_validateBySwagger_default(null, local.utility2.onErrorDefault);
1416 | // jslint dir
1417 | [
1418 | __dirname
1419 | ].forEach(function (dir) {
1420 | local.fs.readdirSync(dir).forEach(function (file) {
1421 | file = dir + '/' + file;
1422 | // if the file is modified, then restart the process
1423 | local.utility2.onFileModifiedRestart(file);
1424 | switch (local.path.extname(file)) {
1425 | case '.js':
1426 | case '.json':
1427 | // jslint file
1428 | local.utility2.jslint_lite
1429 | .jslintAndPrint(local.fs.readFileSync(file, 'utf8'), file);
1430 | break;
1431 | }
1432 | });
1433 | });
1434 | // init repl debugger
1435 | local.utility2.replStart();
1436 | break;
1437 | }
1438 | }((function () {
1439 | 'use strict';
1440 | var local;
1441 |
1442 |
1443 |
1444 | // run shared js-env code
1445 | (function () {
1446 | // init local
1447 | local = {};
1448 | // init js-env
1449 | local.modeJs = (function () {
1450 | try {
1451 | return module.exports &&
1452 | typeof process.versions.node === 'string' &&
1453 | typeof require('http').createServer === 'function' &&
1454 | 'node';
1455 | } catch (errorCaughtNode) {
1456 | return typeof navigator.userAgent === 'string' &&
1457 | typeof document.querySelector('body') === 'object' &&
1458 | 'browser';
1459 | }
1460 | }());
1461 | switch (local.modeJs) {
1462 | // re-init local from window.local
1463 | case 'browser':
1464 | local = window.local;
1465 | break;
1466 | // re-init local from example.js
1467 | case 'node':
1468 | [
1469 | process.cwd(),
1470 | // test dir !== __dirname handling-behavior
1471 | ''
1472 | ].forEach(function (dir) {
1473 | if (dir !== __dirname) {
1474 | local = require(__dirname + '/example.js');
1475 | return;
1476 | }
1477 | require('fs').writeFileSync(
1478 | __dirname + '/example.js',
1479 | require('fs').readFileSync(__dirname + '/README.md', 'utf8')
1480 | // support syntax-highlighting
1481 | .replace((/[\S\s]+?\n.*?example.js\s*?```\w*?\n/), function (match0) {
1482 | // preserve lineno
1483 | return match0.replace((/.+/g), '');
1484 | })
1485 | .replace((/\n```[\S\s]+/), '')
1486 | // disable mock package.json env
1487 | .replace(/(process.env.npm_package_\w+ = )/g, '// $1')
1488 | // alias require('$npm_package_name') to require('index.js');
1489 | .replace(
1490 | "require('" + process.env.npm_package_name + "')",
1491 | "require(__dirname + '/index.js')"
1492 | )
1493 | );
1494 | local = require(__dirname + '/example.js');
1495 | });
1496 | break;
1497 | }
1498 | }());
1499 | return local;
1500 | }())));
1501 |
--------------------------------------------------------------------------------