UNPKG

11 kBJavaScriptView Raw
1'use strict';
2
3var
4 _ = require('lodash'),
5 RandExp = require('randexp'),
6 chance = require('chance').Chance(),
7 djson = require('describe-json');
8
9var _schemas = [];
10var _customTypes = [
11 {
12 name: 'number',
13 customType: function () {
14 return chance.natural();
15 }
16 },
17 {
18 name: 'boolean',
19 customType: function () {
20 return chance.bool();
21 }
22 },
23 {
24 name: 'null',
25 customType: function () {
26 return null;
27 }
28 },
29 {
30 name: 'string',
31 customType: function () {
32 return chance.string();
33 }
34 },
35 {
36 name: 'array',
37 customType: function () {
38 return [];
39 }
40 },
41 {
42 name: 'object',
43 customType: function () {
44 return {};
45 }
46 },
47 {
48 name: 'function',
49 customType: function () {
50 return function(){};
51 }
52 }
53];
54
55var _dreamHelper = {
56 chance: chance,
57 oneOf: function (collection) {
58 return _.sample(collection);
59 }
60};
61
62var _defaultOutput = {
63 Dream: 'Hello World'
64};
65
66var _genericSchema = {
67 name: 'generic',
68 schema: {
69 default: String
70 }
71};
72
73function Dream() {
74
75 //this._selectedSchema;
76 //this._output;
77 this._dreamHelper = _dreamHelper;
78 //this._input;
79
80 this.defaultSchema = function (schema) {
81 _genericSchema = validateAndReturnSchema(schema);
82 return this;
83 }.bind(this);
84
85 this.useSchema = function useSchema(schema) {
86 var
87 schemaToUse,
88 dreamInstance;
89
90 schemaToUse = validateAndReturnSchema(schema);
91 dreamInstance = new Dream();
92 dreamInstance.schema(schemaToUse);
93 dreamInstance._selectedSchema = schemaToUse;
94
95 return dreamInstance;
96 }.bind(this);
97
98 this.input = function input(input) {
99 this._dreamHelper.input = input;
100 return (this);
101 }.bind(this);
102
103 this.generateSchema = function () {
104 var
105 describedJson,
106 schemaName = '',
107 jsonInput = '',
108 validatedJsonInput,
109 guessProperties = false,
110 newSchema,
111 args = [];
112
113 Array.prototype.push.apply(args, arguments);
114
115 args.forEach(function (argument) {
116 switch (typeof (argument)) {
117 case 'string':
118 schemaName = argument;
119 break;
120 case 'object':
121 jsonInput = argument;
122 break;
123 case 'boolean':
124 guessProperties = argument;
125 break;
126 }
127 });
128
129 validatedJsonInput = _.first(_.flatten([jsonInput]));
130 describedJson = djson.describe(validatedJsonInput || {});
131
132 newSchema = {
133 name: schemaName || 'generic',
134 schema: describedJson
135 };
136
137 if (guessProperties === true) {
138 newSchema.schema = guessCustomTypes(describedJson);
139 }
140 addOrReplace(_schemas, newSchema);
141 return this;
142 }.bind(this);
143
144 this.customType = function (typeName, customType) {
145 var
146 newCustomType = {},
147 validTypeName;
148
149 validTypeName = typeof (typeName) === 'string' ? typeName : 'generic';
150
151 if (customType.constructor === RegExp) {
152 newCustomType = {
153 name: validTypeName,
154 customType: function () {
155 return new RandExp(customType).gen();
156 }
157 };
158 } else if (typeof (customType) === 'function') {
159 newCustomType = {
160 name: validTypeName,
161 customType: customType
162 };
163 } else {
164 newCustomType = {
165 name: validTypeName,
166 customType: function () {
167 return '[Invalid Custom Type]';
168 }
169 };
170 }
171
172 addOrReplace(_customTypes, newCustomType);
173
174 return this;
175 }.bind(this);
176
177 this.cleanse = function () {
178 this._output = null;
179 this._selectedSchema = null;
180 }.bind(this);
181
182 this.output = function output(callback) {
183 var output;
184
185 output = this._output || generateOutput();
186 this.cleanse();
187
188 if (typeof (callback) === 'function') {
189 callback(null, output);
190 return this;
191 } else {
192 return output;
193 }
194
195 }.bind(this);
196
197 //this.flushSchemas = function () {
198 // _schemas = [];
199 // return this;
200 //}.bind(this);
201
202 this.schema = function schema(schema) {
203 var
204 validatedSchema,
205 newSchema,
206 args = [];
207
208 Array.prototype.push.apply(args, arguments);
209
210 if (args.length > 1) {
211 newSchema = {
212 name: typeof (args[0]) === 'string' ? args.shift() : 'generic',
213 schema: typeof (args[0]) === 'object' ? args.shift() : {}
214 };
215 } else {
216 newSchema = schema;
217 }
218
219 validatedSchema = validateAndReturnSchema(newSchema);
220
221 if (validatedSchema.name === 'generic') {
222 this._selectedSchema = validatedSchema;
223 } else {
224
225 addOrReplace(_schemas, validatedSchema);
226
227 if (_schemas.length === 1) {
228 this._selectedSchema = validatedSchema;
229 }
230 }
231
232 return this;
233 }.bind(this);
234
235 this.generate = function generate(amount, generateRandomData) {
236 var
237 outputItem,
238 iterations = amount || 1,
239 outputArray = [],
240 i = 0;
241
242 for (; i < iterations; i++) {
243 outputItem = generateOutputFromSchema(selectAvailableSchema(), generateRandomData);
244 outputArray.push(outputItem);
245 }
246
247 this._output = outputArray.length === 1 ? outputArray[0] : outputArray;
248 return this;
249 }.bind(this);
250
251 this.generateRnd = function generateRnd(amount) {
252 return this.generate(amount, true);
253 };
254
255 var addOrReplace = function addOrReplace(collection, item) {
256 var
257 index;
258
259 index = _.indexOf(collection, _.find(collection, { name: item.name }));
260 if (index >= 0) {
261 collection.splice(index, 1, item);
262 } else {
263 collection.push(item);
264 }
265
266 return collection;
267 };
268
269 var guessCustomTypes = function guessCustomTypes(schemaObject) {
270 var
271 customTypeExists,
272 temporaryList = [];
273
274 _.forIn(schemaObject, function (value, key) {
275 if (typeof (value) === 'object') {
276 if (Array.isArray(value)) {
277 value.forEach(function (item) {
278 if (typeof (item) === 'object') {
279 temporaryList.push(guessCustomTypes(item));
280 } else {
281 temporaryList.push(item.toString());
282 }
283 });
284 schemaObject[key] = temporaryList;
285 } else {
286 schemaObject[key] = guessCustomTypes(value);
287 }
288 } else {
289
290 customTypeExists = _.find(_customTypes, { name: key.toString() });
291
292 if (typeof (chance[key.toString()]) === 'function' || customTypeExists !== undefined) {
293 schemaObject[key] = key.toString();
294 }
295 }
296 });
297
298 return schemaObject;
299 };
300
301 var validateAndReturnSchema = function (schema) {
302 if (isValidSchema(schema)) return schema;
303
304 if (typeof (schema) === 'string') {
305 var foundSchema = _.findWhere(_schemas, { name: schema });
306 return isValidSchema(foundSchema) ? foundSchema : _genericSchema;
307 }
308
309 if (typeof (schema) === 'object') {
310 return {
311 name: 'generic',
312 schema: schema
313 };
314 }
315
316 return _genericSchema;
317 }.bind(this);
318
319 var selectAvailableSchema = function () {
320 if (this._selectedSchema) {
321 return this._selectedSchema;
322 }
323
324 if (thereIsSchema() && _schemas.length === 1) {
325 return _schemas[0];
326 }
327
328 return _genericSchema;
329 }.bind(this);
330
331 var generateOutput = function () {
332
333 if (this._selectedSchema) {
334 return generateOutputFromSchema(this._selectedSchema);
335 } else {
336 return _defaultOutput;
337 }
338
339 }.bind(this);
340
341 var generateOutputFromSchema = function (schema, generateValues) {
342 var
343 outputObject = {},
344 schemaToUse = validateAndReturnSchema(schema);
345 _.forIn(schemaToUse.schema, function (value, key) {
346 outputObject[key] = getValueFromType(value, generateValues);
347 });
348 return outputObject;
349 }.bind(this);
350
351 var getValueFromType = function getValueFromType(propertyType, generateValues) {
352 var
353 value,
354 temporaryList = [],
355 temporaryObject = {},
356 temporaryValue,
357 customTypeIndex,
358 customTypeNeedle,
359 context = this,
360 types = {
361 'number': Number,
362 'string': String,
363 'boolean': Boolean,
364 'array': Array,
365 'object': Object,
366 'function': Function,
367 'date': Date
368 };
369
370 if (propertyType.constructor === RegExp) {
371 if (generateValues) {
372 return new RandExp(propertyType).gen();
373 } else {
374 return types[typeof (new RandExp(propertyType).gen())]();
375 }
376 }
377
378 switch (typeof (propertyType)) {
379 case 'string':
380 customTypeNeedle = _.find(_customTypes, { name: propertyType });
381 customTypeIndex = _.indexOf(_customTypes, customTypeNeedle);
382
383 if (customTypeIndex >= 0) {
384 temporaryValue = customTypeNeedle.customType(this._dreamHelper);
385 } else {
386 if (propertyType === 'array') {
387 temporaryValue = [];
388 } else {
389 temporaryValue = (typeof (chance[propertyType]) === 'function') ? chance[propertyType]() : '[Unknown Custom Type]';
390 }
391 }
392
393 if (generateValues) {
394 value = temporaryValue;
395 } else {
396 value = types[typeof (temporaryValue)]();
397 }
398
399 break;
400 case 'function':
401
402 temporaryValue = propertyType();
403
404 if (propertyType === Date) {
405 value = new Date(temporaryValue);
406 } else {
407
408 if (generateValues) {
409 customTypeNeedle = _.find(_customTypes, { name: typeof (temporaryValue) });
410 value = isNative(propertyType) ? customTypeNeedle() : temporaryValue;
411 } else {
412 value = Array.isArray(temporaryValue) ? types['array']() : types[typeof (temporaryValue)]();
413 }
414
415 }
416
417 break;
418 case 'object':
419
420 if (Array.isArray(propertyType)) {
421 propertyType.forEach(function (item) {
422 temporaryList.push(getValueFromType.call(context, item, generateValues));
423 });
424
425 value = temporaryList;
426 } else {
427 _.forIn(propertyType, function (value, key) {
428 temporaryObject[key] = getValueFromType.call(context, value, generateValues);
429 });
430
431 value = temporaryObject;
432 }
433
434 break;
435 default:
436 value = '[Invalid Property]';
437 }
438
439 return value;
440 }.bind(this);
441
442 var isValidSchema = function isValidSchema(schema) {
443 return _.has(schema, 'name') && _.has(schema, 'schema');
444 };
445
446 var thereIsSchema = function thereIsSchema() {
447 return _schemas.length > 0;
448 };
449
450 function isNative(fn) {
451 return (/^function\s*[a-z0-9_\$]*\s*\([^)]*\)\s*\{\s*\[native code\]\s*\}/i).test('' + fn);
452 };
453
454}
455
456module.exports = new Dream();