mongodb-livedata-server 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +63 -0
  2. package/dist/livedata_server.js +9 -0
  3. package/dist/meteor/binary-heap/max_heap.js +186 -0
  4. package/dist/meteor/binary-heap/min_heap.js +17 -0
  5. package/dist/meteor/binary-heap/min_max_heap.js +48 -0
  6. package/dist/meteor/callback-hook/hook.js +78 -0
  7. package/dist/meteor/ddp/crossbar.js +136 -0
  8. package/dist/meteor/ddp/heartbeat.js +77 -0
  9. package/dist/meteor/ddp/livedata_server.js +403 -0
  10. package/dist/meteor/ddp/method-invocation.js +72 -0
  11. package/dist/meteor/ddp/random-stream.js +100 -0
  12. package/dist/meteor/ddp/session-collection-view.js +106 -0
  13. package/dist/meteor/ddp/session-document-view.js +82 -0
  14. package/dist/meteor/ddp/session.js +570 -0
  15. package/dist/meteor/ddp/stream_server.js +181 -0
  16. package/dist/meteor/ddp/subscription.js +347 -0
  17. package/dist/meteor/ddp/utils.js +104 -0
  18. package/dist/meteor/ddp/writefence.js +111 -0
  19. package/dist/meteor/diff-sequence/diff.js +257 -0
  20. package/dist/meteor/ejson/ejson.js +569 -0
  21. package/dist/meteor/ejson/stringify.js +119 -0
  22. package/dist/meteor/ejson/utils.js +42 -0
  23. package/dist/meteor/id-map/id_map.js +92 -0
  24. package/dist/meteor/mongo/caching_change_observer.js +94 -0
  25. package/dist/meteor/mongo/doc_fetcher.js +53 -0
  26. package/dist/meteor/mongo/geojson_utils.js +41 -0
  27. package/dist/meteor/mongo/live_connection.js +264 -0
  28. package/dist/meteor/mongo/live_cursor.js +57 -0
  29. package/dist/meteor/mongo/minimongo_common.js +2002 -0
  30. package/dist/meteor/mongo/minimongo_matcher.js +217 -0
  31. package/dist/meteor/mongo/minimongo_sorter.js +268 -0
  32. package/dist/meteor/mongo/observe_driver_utils.js +73 -0
  33. package/dist/meteor/mongo/observe_multiplexer.js +228 -0
  34. package/dist/meteor/mongo/oplog-observe-driver.js +919 -0
  35. package/dist/meteor/mongo/oplog_tailing.js +352 -0
  36. package/dist/meteor/mongo/oplog_v2_converter.js +126 -0
  37. package/dist/meteor/mongo/polling_observe_driver.js +195 -0
  38. package/dist/meteor/mongo/synchronous-cursor.js +261 -0
  39. package/dist/meteor/mongo/synchronous-queue.js +110 -0
  40. package/dist/meteor/ordered-dict/ordered_dict.js +198 -0
  41. package/dist/meteor/random/AbstractRandomGenerator.js +92 -0
  42. package/dist/meteor/random/AleaRandomGenerator.js +90 -0
  43. package/dist/meteor/random/NodeRandomGenerator.js +42 -0
  44. package/dist/meteor/random/createAleaGenerator.js +32 -0
  45. package/dist/meteor/random/createRandom.js +22 -0
  46. package/dist/meteor/random/main.js +12 -0
  47. package/livedata_server.ts +3 -0
  48. package/meteor/LICENSE +28 -0
  49. package/meteor/binary-heap/max_heap.ts +225 -0
  50. package/meteor/binary-heap/min_heap.ts +15 -0
  51. package/meteor/binary-heap/min_max_heap.ts +53 -0
  52. package/meteor/callback-hook/hook.ts +85 -0
  53. package/meteor/ddp/crossbar.ts +148 -0
  54. package/meteor/ddp/heartbeat.ts +97 -0
  55. package/meteor/ddp/livedata_server.ts +473 -0
  56. package/meteor/ddp/method-invocation.ts +86 -0
  57. package/meteor/ddp/random-stream.ts +102 -0
  58. package/meteor/ddp/session-collection-view.ts +119 -0
  59. package/meteor/ddp/session-document-view.ts +92 -0
  60. package/meteor/ddp/session.ts +708 -0
  61. package/meteor/ddp/stream_server.ts +204 -0
  62. package/meteor/ddp/subscription.ts +392 -0
  63. package/meteor/ddp/utils.ts +119 -0
  64. package/meteor/ddp/writefence.ts +130 -0
  65. package/meteor/diff-sequence/diff.ts +295 -0
  66. package/meteor/ejson/ejson.ts +601 -0
  67. package/meteor/ejson/stringify.ts +122 -0
  68. package/meteor/ejson/utils.ts +38 -0
  69. package/meteor/id-map/id_map.ts +84 -0
  70. package/meteor/mongo/caching_change_observer.ts +120 -0
  71. package/meteor/mongo/doc_fetcher.ts +52 -0
  72. package/meteor/mongo/geojson_utils.ts +42 -0
  73. package/meteor/mongo/live_connection.ts +302 -0
  74. package/meteor/mongo/live_cursor.ts +79 -0
  75. package/meteor/mongo/minimongo_common.ts +2440 -0
  76. package/meteor/mongo/minimongo_matcher.ts +275 -0
  77. package/meteor/mongo/minimongo_sorter.ts +331 -0
  78. package/meteor/mongo/observe_driver_utils.ts +79 -0
  79. package/meteor/mongo/observe_multiplexer.ts +256 -0
  80. package/meteor/mongo/oplog-observe-driver.ts +1049 -0
  81. package/meteor/mongo/oplog_tailing.ts +414 -0
  82. package/meteor/mongo/oplog_v2_converter.ts +124 -0
  83. package/meteor/mongo/polling_observe_driver.ts +247 -0
  84. package/meteor/mongo/synchronous-cursor.ts +293 -0
  85. package/meteor/mongo/synchronous-queue.ts +119 -0
  86. package/meteor/ordered-dict/ordered_dict.ts +229 -0
  87. package/meteor/random/AbstractRandomGenerator.ts +99 -0
  88. package/meteor/random/AleaRandomGenerator.ts +96 -0
  89. package/meteor/random/NodeRandomGenerator.ts +37 -0
  90. package/meteor/random/createAleaGenerator.ts +31 -0
  91. package/meteor/random/createRandom.ts +19 -0
  92. package/meteor/random/main.ts +8 -0
  93. package/package.json +30 -0
  94. package/tsconfig.json +10 -0
@@ -0,0 +1,569 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.clone = exports.equals = exports.isBinary = exports.parse = exports.stringify = exports.fromJSONValue = exports._adjustTypesFromJSONValue = exports.toJSONValue = exports._adjustTypesToJSONValue = exports._getConverters = exports._getTypes = exports._isCustomType = exports.addType = void 0;
7
+ const utils_1 = require("./utils");
8
+ const stringify_1 = __importDefault(require("./stringify"));
9
+ // Custom type interface definition
10
+ /**
11
+ * @class CustomType
12
+ * @instanceName customType
13
+ * @memberOf EJSON
14
+ * @summary The interface that a class must satisfy to be able to become an
15
+ * EJSON custom type via EJSON.addType.
16
+ */
17
+ /**
18
+ * @function typeName
19
+ * @memberOf EJSON.CustomType
20
+ * @summary Return the tag used to identify this type. This must match the
21
+ * tag used to register this type with
22
+ * [`EJSON.addType`](#ejson_add_type).
23
+ * @locus Anywhere
24
+ * @instance
25
+ */
26
+ /**
27
+ * @function toJSONValue
28
+ * @memberOf EJSON.CustomType
29
+ * @summary Serialize this instance into a JSON-compatible value.
30
+ * @locus Anywhere
31
+ * @instance
32
+ */
33
+ /**
34
+ * @function clone
35
+ * @memberOf EJSON.CustomType
36
+ * @summary Return a value `r` such that `this.equals(r)` is true, and
37
+ * modifications to `r` do not affect `this` and vice versa.
38
+ * @locus Anywhere
39
+ * @instance
40
+ */
41
+ /**
42
+ * @function equals
43
+ * @memberOf EJSON.CustomType
44
+ * @summary Return `true` if `other` has a value equal to `this`; `false`
45
+ * otherwise.
46
+ * @locus Anywhere
47
+ * @param {Object} other Another object to compare this to.
48
+ * @instance
49
+ */
50
+ const customTypes = new Map();
51
+ // Add a custom type, using a method of your choice to get to and
52
+ // from a basic JSON-able representation. The factory argument
53
+ // is a function of JSON-able --> your object
54
+ // The type you add must have:
55
+ // - A toJSONValue() method, so that Meteor can serialize it
56
+ // - a typeName() method, to show how to look it up in our type table.
57
+ // It is okay if these methods are monkey-patched on.
58
+ // EJSON.clone will use toJSONValue and the given factory to produce
59
+ // a clone, but you may specify a method clone() that will be
60
+ // used instead.
61
+ // Similarly, EJSON.equals will use toJSONValue to make comparisons,
62
+ // but you may provide a method equals() instead.
63
+ /**
64
+ * @summary Add a custom datatype to EJSON.
65
+ * @locus Anywhere
66
+ * @param {String} name A tag for your custom type; must be unique among
67
+ * custom data types defined in your project, and must
68
+ * match the result of your type's `typeName` method.
69
+ * @param {Function} factory A function that deserializes a JSON-compatible
70
+ * value into an instance of your type. This should
71
+ * match the serialization performed by your
72
+ * type's `toJSONValue` method.
73
+ */
74
+ function addType(name, factory) {
75
+ if (customTypes.has(name)) {
76
+ throw new Error(`Type ${name} already present`);
77
+ }
78
+ customTypes.set(name, factory);
79
+ }
80
+ exports.addType = addType;
81
+ ;
82
+ const builtinConverters = [
83
+ {
84
+ matchJSONValue(obj) {
85
+ return (0, utils_1.hasOwn)(obj, '$date') && (0, utils_1.lengthOf)(obj) === 1;
86
+ },
87
+ matchObject(obj) {
88
+ return obj instanceof Date;
89
+ },
90
+ toJSONValue(obj) {
91
+ return { $date: obj.getTime() };
92
+ },
93
+ fromJSONValue(obj) {
94
+ return new Date(obj.$date);
95
+ },
96
+ },
97
+ {
98
+ matchJSONValue(obj) {
99
+ return (0, utils_1.hasOwn)(obj, '$regexp')
100
+ && (0, utils_1.hasOwn)(obj, '$flags')
101
+ && (0, utils_1.lengthOf)(obj) === 2;
102
+ },
103
+ matchObject(obj) {
104
+ return obj instanceof RegExp;
105
+ },
106
+ toJSONValue(regexp) {
107
+ return {
108
+ $regexp: regexp.source,
109
+ $flags: regexp.flags
110
+ };
111
+ },
112
+ fromJSONValue(obj) {
113
+ // Replaces duplicate / invalid flags.
114
+ return new RegExp(obj.$regexp, obj.$flags
115
+ // Cut off flags at 50 chars to avoid abusing RegExp for DOS.
116
+ .slice(0, 50)
117
+ .replace(/[^gimuy]/g, '')
118
+ .replace(/(.)(?=.*\1)/g, ''));
119
+ },
120
+ },
121
+ {
122
+ // which we match.)
123
+ matchJSONValue(obj) {
124
+ return (0, utils_1.hasOwn)(obj, '$InfNaN') && (0, utils_1.lengthOf)(obj) === 1;
125
+ },
126
+ matchObject: utils_1.isInfOrNaN,
127
+ toJSONValue(obj) {
128
+ let sign;
129
+ if (Number.isNaN(obj)) {
130
+ sign = 0;
131
+ }
132
+ else if (obj === Infinity) {
133
+ sign = 1;
134
+ }
135
+ else {
136
+ sign = -1;
137
+ }
138
+ return { $InfNaN: sign };
139
+ },
140
+ fromJSONValue(obj) {
141
+ return obj.$InfNaN / 0;
142
+ },
143
+ },
144
+ {
145
+ matchJSONValue(obj) {
146
+ return (0, utils_1.hasOwn)(obj, '$binary') && (0, utils_1.lengthOf)(obj) === 1;
147
+ },
148
+ matchObject(obj) {
149
+ return typeof Uint8Array !== 'undefined' && obj instanceof Uint8Array
150
+ || (obj && (0, utils_1.hasOwn)(obj, '$Uint8ArrayPolyfill'));
151
+ },
152
+ toJSONValue(obj) {
153
+ return { $binary: Buffer.from(obj).toString("base64") };
154
+ },
155
+ fromJSONValue(obj) {
156
+ return Buffer.from(obj.$binary, "base64").toString();
157
+ },
158
+ },
159
+ {
160
+ matchJSONValue(obj) {
161
+ return (0, utils_1.hasOwn)(obj, '$escape') && (0, utils_1.lengthOf)(obj) === 1;
162
+ },
163
+ matchObject(obj) {
164
+ let match = false;
165
+ if (obj) {
166
+ const keyCount = (0, utils_1.lengthOf)(obj);
167
+ if (keyCount === 1 || keyCount === 2) {
168
+ match =
169
+ builtinConverters.some(converter => converter.matchJSONValue(obj));
170
+ }
171
+ }
172
+ return match;
173
+ },
174
+ toJSONValue(obj) {
175
+ const newObj = {};
176
+ (0, utils_1.keysOf)(obj).forEach(key => {
177
+ newObj[key] = toJSONValue(obj[key]);
178
+ });
179
+ return { $escape: newObj };
180
+ },
181
+ fromJSONValue(obj) {
182
+ const newObj = {};
183
+ (0, utils_1.keysOf)(obj.$escape).forEach(key => {
184
+ newObj[key] = fromJSONValue(obj.$escape[key]);
185
+ });
186
+ return newObj;
187
+ },
188
+ },
189
+ {
190
+ matchJSONValue(obj) {
191
+ return (0, utils_1.hasOwn)(obj, '$type')
192
+ && (0, utils_1.hasOwn)(obj, '$value') && (0, utils_1.lengthOf)(obj) === 2;
193
+ },
194
+ matchObject(obj) {
195
+ return _isCustomType(obj);
196
+ },
197
+ toJSONValue(obj) {
198
+ const jsonValue = obj.toJSONValue();
199
+ return { $type: obj.typeName(), $value: jsonValue };
200
+ },
201
+ fromJSONValue(obj) {
202
+ const typeName = obj.$type;
203
+ if (!customTypes.has(typeName)) {
204
+ throw new Error(`Custom EJSON type ${typeName} is not defined`);
205
+ }
206
+ const converter = customTypes.get(typeName);
207
+ return converter(obj.$value);
208
+ },
209
+ },
210
+ ];
211
+ function _isCustomType(obj) {
212
+ return obj &&
213
+ (0, utils_1.isFunction)(obj.toJSONValue) &&
214
+ (0, utils_1.isFunction)(obj.typeName) &&
215
+ customTypes.has(obj.typeName());
216
+ }
217
+ exports._isCustomType = _isCustomType;
218
+ function _getTypes(isOriginal = false) { return (isOriginal ? customTypes : (0, utils_1.convertMapToObject)(customTypes)); }
219
+ exports._getTypes = _getTypes;
220
+ function _getConverters() { return builtinConverters; }
221
+ exports._getConverters = _getConverters;
222
+ // Either return the JSON-compatible version of the argument, or undefined (if
223
+ // the item isn't itself replaceable, but maybe some fields in it are)
224
+ const toJSONValueHelper = item => {
225
+ for (let i = 0; i < builtinConverters.length; i++) {
226
+ const converter = builtinConverters[i];
227
+ if (converter.matchObject(item)) {
228
+ return converter.toJSONValue(item);
229
+ }
230
+ }
231
+ return undefined;
232
+ };
233
+ // for both arrays and objects, in-place modification.
234
+ function _adjustTypesToJSONValue(obj) {
235
+ // Is it an atom that we need to adjust?
236
+ if (obj === null) {
237
+ return null;
238
+ }
239
+ const maybeChanged = toJSONValueHelper(obj);
240
+ if (maybeChanged !== undefined) {
241
+ return maybeChanged;
242
+ }
243
+ // Other atoms are unchanged.
244
+ if (!(0, utils_1.isObject)(obj)) {
245
+ return obj;
246
+ }
247
+ // Iterate over array or object structure.
248
+ (0, utils_1.keysOf)(obj).forEach(key => {
249
+ const value = obj[key];
250
+ if (!(0, utils_1.isObject)(value) && value !== undefined &&
251
+ !(0, utils_1.isInfOrNaN)(value)) {
252
+ return; // continue
253
+ }
254
+ const changed = toJSONValueHelper(value);
255
+ if (changed) {
256
+ obj[key] = changed;
257
+ return; // on to the next key
258
+ }
259
+ // if we get here, value is an object but not adjustable
260
+ // at this level. recurse.
261
+ _adjustTypesToJSONValue(value);
262
+ });
263
+ return obj;
264
+ }
265
+ exports._adjustTypesToJSONValue = _adjustTypesToJSONValue;
266
+ ;
267
+ /**
268
+ * @summary Serialize an EJSON-compatible value into its plain JSON
269
+ * representation.
270
+ * @locus Anywhere
271
+ * @param {EJSON} val A value to serialize to plain JSON.
272
+ */
273
+ function toJSONValue(item) {
274
+ const changed = toJSONValueHelper(item);
275
+ if (changed !== undefined) {
276
+ return changed;
277
+ }
278
+ let newItem = item;
279
+ if ((0, utils_1.isObject)(item)) {
280
+ newItem = clone(item);
281
+ _adjustTypesToJSONValue(newItem);
282
+ }
283
+ return newItem;
284
+ }
285
+ exports.toJSONValue = toJSONValue;
286
+ ;
287
+ // Either return the argument changed to have the non-json
288
+ // rep of itself (the Object version) or the argument itself.
289
+ // DOES NOT RECURSE. For actually getting the fully-changed value, use
290
+ // EJSON.fromJSONValue
291
+ const fromJSONValueHelper = value => {
292
+ if ((0, utils_1.isObject)(value) && value !== null) {
293
+ const keys = (0, utils_1.keysOf)(value);
294
+ if (keys.length <= 2
295
+ && keys.every(k => typeof k === 'string' && k.substr(0, 1) === '$')) {
296
+ for (let i = 0; i < builtinConverters.length; i++) {
297
+ const converter = builtinConverters[i];
298
+ if (converter.matchJSONValue(value)) {
299
+ return converter.fromJSONValue(value);
300
+ }
301
+ }
302
+ }
303
+ }
304
+ return value;
305
+ };
306
+ // for both arrays and objects. Tries its best to just
307
+ // use the object you hand it, but may return something
308
+ // different if the object you hand it itself needs changing.
309
+ function _adjustTypesFromJSONValue(obj) {
310
+ if (obj === null) {
311
+ return null;
312
+ }
313
+ const maybeChanged = fromJSONValueHelper(obj);
314
+ if (maybeChanged !== obj) {
315
+ return maybeChanged;
316
+ }
317
+ // Other atoms are unchanged.
318
+ if (!(0, utils_1.isObject)(obj)) {
319
+ return obj;
320
+ }
321
+ (0, utils_1.keysOf)(obj).forEach(key => {
322
+ const value = obj[key];
323
+ if ((0, utils_1.isObject)(value)) {
324
+ const changed = fromJSONValueHelper(value);
325
+ if (value !== changed) {
326
+ obj[key] = changed;
327
+ return;
328
+ }
329
+ // if we get here, value is an object but not adjustable
330
+ // at this level. recurse.
331
+ _adjustTypesFromJSONValue(value);
332
+ }
333
+ });
334
+ return obj;
335
+ }
336
+ exports._adjustTypesFromJSONValue = _adjustTypesFromJSONValue;
337
+ ;
338
+ /**
339
+ * @summary Deserialize an EJSON value from its plain JSON representation.
340
+ * @locus Anywhere
341
+ * @param {JSONCompatible} val A value to deserialize into EJSON.
342
+ */
343
+ function fromJSONValue(item) {
344
+ let changed = fromJSONValueHelper(item);
345
+ if (changed === item && (0, utils_1.isObject)(item)) {
346
+ changed = clone(item);
347
+ _adjustTypesFromJSONValue(changed);
348
+ }
349
+ return changed;
350
+ }
351
+ exports.fromJSONValue = fromJSONValue;
352
+ ;
353
+ /**
354
+ * @summary Serialize a value to a string. For EJSON values, the serialization
355
+ * fully represents the value. For non-EJSON values, serializes the
356
+ * same way as `JSON.stringify`.
357
+ * @locus Anywhere
358
+ * @param {EJSON} val A value to stringify.
359
+ * @param {Object} [options]
360
+ * @param {Boolean | Integer | String} options.indent Indents objects and
361
+ * arrays for easy readability. When `true`, indents by 2 spaces; when an
362
+ * integer, indents by that number of spaces; and when a string, uses the
363
+ * string as the indentation pattern.
364
+ * @param {Boolean} options.canonical When `true`, stringifies keys in an
365
+ * object in sorted order.
366
+ */
367
+ function stringify(val, opts) {
368
+ return (0, utils_1.handleError)((item, options) => {
369
+ let serialized;
370
+ const json = toJSONValue(item);
371
+ if (options && (options.canonical || options.indent)) {
372
+ serialized = (0, stringify_1.default)(json, options);
373
+ }
374
+ else {
375
+ serialized = JSON.stringify(json);
376
+ }
377
+ return serialized;
378
+ }, val, opts);
379
+ }
380
+ exports.stringify = stringify;
381
+ /**
382
+ * @summary Parse a string into an EJSON value. Throws an error if the string
383
+ * is not valid EJSON.
384
+ * @locus Anywhere
385
+ * @param {String} str A string to parse into an EJSON value.
386
+ */
387
+ function parse(item) {
388
+ if (typeof item !== 'string') {
389
+ throw new Error('EJSON.parse argument should be a string');
390
+ }
391
+ return fromJSONValue(JSON.parse(item));
392
+ }
393
+ exports.parse = parse;
394
+ ;
395
+ /**
396
+ * @summary Returns true if `x` is a buffer of binary data, as returned from
397
+ * [`EJSON.newBinary`](#ejson_new_binary).
398
+ * @param {Object} x The variable to check.
399
+ * @locus Anywhere
400
+ */
401
+ function isBinary(obj) {
402
+ return !!((typeof Uint8Array !== 'undefined' && obj instanceof Uint8Array) ||
403
+ (obj && obj.$Uint8ArrayPolyfill));
404
+ }
405
+ exports.isBinary = isBinary;
406
+ ;
407
+ /**
408
+ * @summary Return true if `a` and `b` are equal to each other. Return false
409
+ * otherwise. Uses the `equals` method on `a` if present, otherwise
410
+ * performs a deep comparison.
411
+ * @locus Anywhere
412
+ * @param {EJSON} a
413
+ * @param {EJSON} b
414
+ * @param {Object} [options]
415
+ * @param {Boolean} options.keyOrderSensitive Compare in key sensitive order,
416
+ * if supported by the JavaScript implementation. For example, `{a: 1, b: 2}`
417
+ * is equal to `{b: 2, a: 1}` only when `keyOrderSensitive` is `false`. The
418
+ * default is `false`.
419
+ */
420
+ function equals(a, b, options) {
421
+ let i;
422
+ const keyOrderSensitive = !!(options && options.keyOrderSensitive);
423
+ if (a === b) {
424
+ return true;
425
+ }
426
+ // This differs from the IEEE spec for NaN equality, b/c we don't want
427
+ // anything ever with a NaN to be poisoned from becoming equal to anything.
428
+ if (Number.isNaN(a) && Number.isNaN(b)) {
429
+ return true;
430
+ }
431
+ // if either one is falsy, they'd have to be === to be equal
432
+ if (!a || !b) {
433
+ return false;
434
+ }
435
+ if (!((0, utils_1.isObject)(a) && (0, utils_1.isObject)(b))) {
436
+ return false;
437
+ }
438
+ if (a instanceof Date && b instanceof Date) {
439
+ return a.valueOf() === b.valueOf();
440
+ }
441
+ if (isBinary(a) && isBinary(b)) {
442
+ if (a.length !== b.length) {
443
+ return false;
444
+ }
445
+ for (i = 0; i < a.length; i++) {
446
+ if (a[i] !== b[i]) {
447
+ return false;
448
+ }
449
+ }
450
+ return true;
451
+ }
452
+ if ((0, utils_1.isFunction)(a.equals)) {
453
+ return a.equals(b, options);
454
+ }
455
+ if ((0, utils_1.isFunction)(b.equals)) {
456
+ return b.equals(a, options);
457
+ }
458
+ // Array.isArray works across iframes while instanceof won't
459
+ const aIsArray = Array.isArray(a);
460
+ const bIsArray = Array.isArray(b);
461
+ // if not both or none are array they are not equal
462
+ if (aIsArray !== bIsArray) {
463
+ return false;
464
+ }
465
+ if (aIsArray && bIsArray) {
466
+ if (a.length !== b.length) {
467
+ return false;
468
+ }
469
+ for (i = 0; i < a.length; i++) {
470
+ if (!equals(a[i], b[i], options)) {
471
+ return false;
472
+ }
473
+ }
474
+ return true;
475
+ }
476
+ // fallback for custom types that don't implement their own equals
477
+ switch (+_isCustomType(a) + +_isCustomType(b)) {
478
+ case 1: return false;
479
+ case 2: return equals(toJSONValue(a), toJSONValue(b));
480
+ default: // Do nothing
481
+ }
482
+ // fall back to structural equality of objects
483
+ let ret;
484
+ const aKeys = (0, utils_1.keysOf)(a);
485
+ const bKeys = (0, utils_1.keysOf)(b);
486
+ if (keyOrderSensitive) {
487
+ i = 0;
488
+ ret = aKeys.every(key => {
489
+ if (i >= bKeys.length) {
490
+ return false;
491
+ }
492
+ if (key !== bKeys[i]) {
493
+ return false;
494
+ }
495
+ if (!equals(a[key], b[bKeys[i]], options)) {
496
+ return false;
497
+ }
498
+ i++;
499
+ return true;
500
+ });
501
+ }
502
+ else {
503
+ i = 0;
504
+ ret = aKeys.every(key => {
505
+ if (!(0, utils_1.hasOwn)(b, key)) {
506
+ return false;
507
+ }
508
+ if (!equals(a[key], b[key], options)) {
509
+ return false;
510
+ }
511
+ i++;
512
+ return true;
513
+ });
514
+ }
515
+ return ret && i === bKeys.length;
516
+ }
517
+ exports.equals = equals;
518
+ ;
519
+ /**
520
+ * @summary Return a deep copy of `val`.
521
+ * @locus Anywhere
522
+ * @param {EJSON} val A value to copy.
523
+ */
524
+ function clone(v) {
525
+ let ret;
526
+ if (!(0, utils_1.isObject)(v)) {
527
+ return v;
528
+ }
529
+ if (v === null) {
530
+ return null; // null has typeof "object"
531
+ }
532
+ if (v instanceof Date) {
533
+ return new Date(v.getTime());
534
+ }
535
+ // RegExps are not really EJSON elements (eg we don't define a serialization
536
+ // for them), but they're immutable anyway, so we can support them in clone.
537
+ if (v instanceof RegExp) {
538
+ return v;
539
+ }
540
+ if (isBinary(v)) {
541
+ ret = new Uint8Array(v.length);
542
+ for (let i = 0; i < v.length; i++) {
543
+ ret[i] = v[i];
544
+ }
545
+ return ret;
546
+ }
547
+ if (Array.isArray(v)) {
548
+ return v.map(clone);
549
+ }
550
+ if ((0, utils_1.isArguments)(v)) {
551
+ return Array.from(v).map(clone);
552
+ }
553
+ // handle general user-defined typed Objects if they have a clone method
554
+ if ("clone" in v && (0, utils_1.isFunction)(v.clone)) {
555
+ return v.clone();
556
+ }
557
+ // handle other custom types
558
+ if (_isCustomType(v)) {
559
+ return fromJSONValue(clone(toJSONValue(v)));
560
+ }
561
+ // handle other objects
562
+ ret = {};
563
+ (0, utils_1.keysOf)(v).forEach((key) => {
564
+ ret[key] = clone(v[key]);
565
+ });
566
+ return ret;
567
+ }
568
+ exports.clone = clone;
569
+ ;
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ // Based on json2.js from https://github.com/douglascrockford/JSON-js
3
+ //
4
+ // json2.js
5
+ // 2012-10-08
6
+ //
7
+ // Public Domain.
8
+ //
9
+ // NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ function quote(string) {
12
+ return JSON.stringify(string);
13
+ }
14
+ const str = (key, holder, singleIndent, outerIndent, canonical) => {
15
+ const value = holder[key];
16
+ // What happens next depends on the value's type.
17
+ switch (typeof value) {
18
+ case 'string':
19
+ return quote(value);
20
+ case 'number':
21
+ // JSON numbers must be finite. Encode non-finite numbers as null.
22
+ return isFinite(value) ? String(value) : 'null';
23
+ case 'boolean':
24
+ return String(value);
25
+ // If the type is 'object', we might be dealing with an object or an array or
26
+ // null.
27
+ case 'object': {
28
+ // Due to a specification blunder in ECMAScript, typeof null is 'object',
29
+ // so watch out for that case.
30
+ if (!value) {
31
+ return 'null';
32
+ }
33
+ // Make an array to hold the partial results of stringifying this object
34
+ // value.
35
+ const innerIndent = outerIndent + singleIndent;
36
+ const partial = [];
37
+ let v;
38
+ // Is the value an array?
39
+ if (Array.isArray(value) || ({}).hasOwnProperty.call(value, 'callee')) {
40
+ // The value is an array. Stringify every element. Use null as a
41
+ // placeholder for non-JSON values.
42
+ const length = value.length;
43
+ for (let i = 0; i < length; i += 1) {
44
+ partial[i] =
45
+ str(i, value, singleIndent, innerIndent, canonical) || 'null';
46
+ }
47
+ // Join all of the elements together, separated with commas, and wrap
48
+ // them in brackets.
49
+ if (partial.length === 0) {
50
+ v = '[]';
51
+ }
52
+ else if (innerIndent) {
53
+ v = '[\n' +
54
+ innerIndent +
55
+ partial.join(',\n' +
56
+ innerIndent) +
57
+ '\n' +
58
+ outerIndent +
59
+ ']';
60
+ }
61
+ else {
62
+ v = '[' + partial.join(',') + ']';
63
+ }
64
+ return v;
65
+ }
66
+ // Iterate through all of the keys in the object.
67
+ let keys = Object.keys(value);
68
+ if (canonical) {
69
+ keys = keys.sort();
70
+ }
71
+ keys.forEach(k => {
72
+ v = str(k, value, singleIndent, innerIndent, canonical);
73
+ if (v) {
74
+ partial.push(quote(k) + (innerIndent ? ': ' : ':') + v);
75
+ }
76
+ });
77
+ // Join all of the member texts together, separated with commas,
78
+ // and wrap them in braces.
79
+ if (partial.length === 0) {
80
+ v = '{}';
81
+ }
82
+ else if (innerIndent) {
83
+ v = '{\n' +
84
+ innerIndent +
85
+ partial.join(',\n' +
86
+ innerIndent) +
87
+ '\n' +
88
+ outerIndent +
89
+ '}';
90
+ }
91
+ else {
92
+ v = '{' + partial.join(',') + '}';
93
+ }
94
+ return v;
95
+ }
96
+ default: // Do nothing
97
+ }
98
+ };
99
+ // If the JSON object does not yet have a stringify method, give it one.
100
+ const canonicalStringify = (value, options) => {
101
+ // Make a fake root object containing our value under the key of ''.
102
+ // Return the result of stringifying the value.
103
+ const allOptions = Object.assign({
104
+ indent: '',
105
+ canonical: false,
106
+ }, options);
107
+ if (allOptions.indent === true) {
108
+ allOptions.indent = ' ';
109
+ }
110
+ else if (typeof allOptions.indent === 'number') {
111
+ let newIndent = '';
112
+ for (let i = 0; i < allOptions.indent; i++) {
113
+ newIndent += ' ';
114
+ }
115
+ allOptions.indent = newIndent;
116
+ }
117
+ return str('', { '': value }, allOptions.indent, '', allOptions.canonical);
118
+ };
119
+ exports.default = canonicalStringify;