This commit is contained in:
47
node_modules/apollo-utilities/src/util/__tests__/assign.ts
generated
vendored
Normal file
47
node_modules/apollo-utilities/src/util/__tests__/assign.ts
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
import { assign } from '../assign';
|
||||
|
||||
describe('assign', () => {
|
||||
it('will merge many objects together', () => {
|
||||
expect(assign({ a: 1 }, { b: 2 })).toEqual({ a: 1, b: 2 });
|
||||
expect(assign({ a: 1 }, { b: 2 }, { c: 3 })).toEqual({
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3,
|
||||
});
|
||||
expect(assign({ a: 1 }, { b: 2 }, { c: 3 }, { d: 4 })).toEqual({
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3,
|
||||
d: 4,
|
||||
});
|
||||
});
|
||||
|
||||
it('will merge many objects together shallowly', () => {
|
||||
expect(assign({ x: { a: 1 } }, { x: { b: 2 } })).toEqual({ x: { b: 2 } });
|
||||
expect(assign({ x: { a: 1 } }, { x: { b: 2 } }, { x: { c: 3 } })).toEqual({
|
||||
x: { c: 3 },
|
||||
});
|
||||
expect(
|
||||
assign(
|
||||
{ x: { a: 1 } },
|
||||
{ x: { b: 2 } },
|
||||
{ x: { c: 3 } },
|
||||
{ x: { d: 4 } },
|
||||
),
|
||||
).toEqual({ x: { d: 4 } });
|
||||
});
|
||||
|
||||
it('will mutate and return the source objects', () => {
|
||||
const source1 = { a: 1 };
|
||||
const source2 = { a: 1 };
|
||||
const source3 = { a: 1 };
|
||||
|
||||
expect(assign(source1, { b: 2 })).toEqual(source1);
|
||||
expect(assign(source2, { b: 2 }, { c: 3 })).toEqual(source2);
|
||||
expect(assign(source3, { b: 2 }, { c: 3 }, { d: 4 })).toEqual(source3);
|
||||
|
||||
expect(source1).toEqual({ a: 1, b: 2 });
|
||||
expect(source2).toEqual({ a: 1, b: 2, c: 3 });
|
||||
expect(source3).toEqual({ a: 1, b: 2, c: 3, d: 4 });
|
||||
});
|
||||
});
|
||||
70
node_modules/apollo-utilities/src/util/__tests__/cloneDeep.ts
generated
vendored
Normal file
70
node_modules/apollo-utilities/src/util/__tests__/cloneDeep.ts
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
import { cloneDeep } from '../cloneDeep';
|
||||
|
||||
describe('cloneDeep', () => {
|
||||
it('will clone primitive values', () => {
|
||||
expect(cloneDeep(undefined)).toEqual(undefined);
|
||||
expect(cloneDeep(null)).toEqual(null);
|
||||
expect(cloneDeep(true)).toEqual(true);
|
||||
expect(cloneDeep(false)).toEqual(false);
|
||||
expect(cloneDeep(-1)).toEqual(-1);
|
||||
expect(cloneDeep(+1)).toEqual(+1);
|
||||
expect(cloneDeep(0.5)).toEqual(0.5);
|
||||
expect(cloneDeep('hello')).toEqual('hello');
|
||||
expect(cloneDeep('world')).toEqual('world');
|
||||
});
|
||||
|
||||
it('will clone objects', () => {
|
||||
const value1 = {};
|
||||
const value2 = { a: 1, b: 2, c: 3 };
|
||||
const value3 = { x: { a: 1, b: 2, c: 3 }, y: { a: 1, b: 2, c: 3 } };
|
||||
|
||||
const clonedValue1 = cloneDeep(value1);
|
||||
const clonedValue2 = cloneDeep(value2);
|
||||
const clonedValue3 = cloneDeep(value3);
|
||||
|
||||
expect(clonedValue1).toEqual(value1);
|
||||
expect(clonedValue2).toEqual(value2);
|
||||
expect(clonedValue3).toEqual(value3);
|
||||
|
||||
expect(clonedValue1).toEqual(value1);
|
||||
expect(clonedValue2).toEqual(value2);
|
||||
expect(clonedValue3).toEqual(value3);
|
||||
expect(clonedValue3.x).toEqual(value3.x);
|
||||
expect(clonedValue3.y).toEqual(value3.y);
|
||||
});
|
||||
|
||||
it('will clone arrays', () => {
|
||||
const value1: Array<number> = [];
|
||||
const value2 = [1, 2, 3];
|
||||
const value3 = [[1, 2, 3], [1, 2, 3]];
|
||||
|
||||
const clonedValue1 = cloneDeep(value1);
|
||||
const clonedValue2 = cloneDeep(value2);
|
||||
const clonedValue3 = cloneDeep(value3);
|
||||
|
||||
expect(clonedValue1).toEqual(value1);
|
||||
expect(clonedValue2).toEqual(value2);
|
||||
expect(clonedValue3).toEqual(value3);
|
||||
|
||||
expect(clonedValue1).toEqual(value1);
|
||||
expect(clonedValue2).toEqual(value2);
|
||||
expect(clonedValue3).toEqual(value3);
|
||||
expect(clonedValue3[0]).toEqual(value3[0]);
|
||||
expect(clonedValue3[1]).toEqual(value3[1]);
|
||||
});
|
||||
|
||||
it('should not attempt to follow circular references', () => {
|
||||
const someObject = {
|
||||
prop1: 'value1',
|
||||
anotherObject: null,
|
||||
};
|
||||
const anotherObject = {
|
||||
someObject,
|
||||
};
|
||||
someObject.anotherObject = anotherObject;
|
||||
let chk;
|
||||
expect(() => {
|
||||
chk = cloneDeep(someObject);
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
70
node_modules/apollo-utilities/src/util/__tests__/environment.ts
generated
vendored
Normal file
70
node_modules/apollo-utilities/src/util/__tests__/environment.ts
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
import { isEnv, isProduction, isDevelopment, isTest } from '../environment';
|
||||
|
||||
describe('environment', () => {
|
||||
let keepEnv: string | undefined;
|
||||
|
||||
beforeEach(() => {
|
||||
// save the NODE_ENV
|
||||
keepEnv = process.env.NODE_ENV;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// restore the NODE_ENV
|
||||
process.env.NODE_ENV = keepEnv;
|
||||
});
|
||||
|
||||
describe('isEnv', () => {
|
||||
it(`should match when there's a value`, () => {
|
||||
['production', 'development', 'test'].forEach(env => {
|
||||
process.env.NODE_ENV = env;
|
||||
expect(isEnv(env)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it(`should treat no proces.env.NODE_ENV as it'd be in development`, () => {
|
||||
delete process.env.NODE_ENV;
|
||||
expect(isEnv('development')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isProduction', () => {
|
||||
it('should return true if in production', () => {
|
||||
process.env.NODE_ENV = 'production';
|
||||
expect(isProduction()).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if not in production', () => {
|
||||
process.env.NODE_ENV = 'test';
|
||||
expect(!isProduction()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isTest', () => {
|
||||
it('should return true if in test', () => {
|
||||
process.env.NODE_ENV = 'test';
|
||||
expect(isTest()).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true if not in test', () => {
|
||||
process.env.NODE_ENV = 'development';
|
||||
expect(!isTest()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isDevelopment', () => {
|
||||
it('should return true if in development', () => {
|
||||
process.env.NODE_ENV = 'development';
|
||||
expect(isDevelopment()).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true if not in development and environment is defined', () => {
|
||||
process.env.NODE_ENV = 'test';
|
||||
expect(!isDevelopment()).toBe(true);
|
||||
});
|
||||
|
||||
it('should make development as the default environment', () => {
|
||||
delete process.env.NODE_ENV;
|
||||
expect(isDevelopment()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
174
node_modules/apollo-utilities/src/util/__tests__/isEqual.ts
generated
vendored
Normal file
174
node_modules/apollo-utilities/src/util/__tests__/isEqual.ts
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
import { isEqual } from '../isEqual';
|
||||
|
||||
describe('isEqual', () => {
|
||||
it('should return true for equal primitive values', () => {
|
||||
expect(isEqual(undefined, undefined)).toBe(true);
|
||||
expect(isEqual(null, null)).toBe(true);
|
||||
expect(isEqual(true, true)).toBe(true);
|
||||
expect(isEqual(false, false)).toBe(true);
|
||||
expect(isEqual(-1, -1)).toBe(true);
|
||||
expect(isEqual(+1, +1)).toBe(true);
|
||||
expect(isEqual(42, 42)).toBe(true);
|
||||
expect(isEqual(0, 0)).toBe(true);
|
||||
expect(isEqual(0.5, 0.5)).toBe(true);
|
||||
expect(isEqual('hello', 'hello')).toBe(true);
|
||||
expect(isEqual('world', 'world')).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for not equal primitive values', () => {
|
||||
expect(!isEqual(undefined, null)).toBe(true);
|
||||
expect(!isEqual(null, undefined)).toBe(true);
|
||||
expect(!isEqual(true, false)).toBe(true);
|
||||
expect(!isEqual(false, true)).toBe(true);
|
||||
expect(!isEqual(-1, +1)).toBe(true);
|
||||
expect(!isEqual(+1, -1)).toBe(true);
|
||||
expect(!isEqual(42, 42.00000000000001)).toBe(true);
|
||||
expect(!isEqual(0, 0.5)).toBe(true);
|
||||
expect(!isEqual('hello', 'world')).toBe(true);
|
||||
expect(!isEqual('world', 'hello')).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when comparing primitives with objects', () => {
|
||||
expect(!isEqual({}, null)).toBe(true);
|
||||
expect(!isEqual(null, {})).toBe(true);
|
||||
expect(!isEqual({}, true)).toBe(true);
|
||||
expect(!isEqual(true, {})).toBe(true);
|
||||
expect(!isEqual({}, 42)).toBe(true);
|
||||
expect(!isEqual(42, {})).toBe(true);
|
||||
expect(!isEqual({}, 'hello')).toBe(true);
|
||||
expect(!isEqual('hello', {})).toBe(true);
|
||||
});
|
||||
|
||||
it('should correctly compare shallow objects', () => {
|
||||
expect(isEqual({}, {})).toBe(true);
|
||||
expect(isEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 })).toBe(true);
|
||||
expect(!isEqual({ a: 1, b: 2, c: 3 }, { a: 3, b: 2, c: 1 })).toBe(true);
|
||||
expect(!isEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2 })).toBe(true);
|
||||
expect(!isEqual({ a: 1, b: 2 }, { a: 1, b: 2, c: 3 })).toBe(true);
|
||||
});
|
||||
|
||||
it('should correctly compare deep objects', () => {
|
||||
expect(isEqual({ x: {} }, { x: {} })).toBe(true);
|
||||
expect(
|
||||
isEqual({ x: { a: 1, b: 2, c: 3 } }, { x: { a: 1, b: 2, c: 3 } }),
|
||||
).toBe(true);
|
||||
expect(
|
||||
!isEqual({ x: { a: 1, b: 2, c: 3 } }, { x: { a: 3, b: 2, c: 1 } }),
|
||||
).toBe(true);
|
||||
expect(!isEqual({ x: { a: 1, b: 2, c: 3 } }, { x: { a: 1, b: 2 } })).toBe(
|
||||
true,
|
||||
);
|
||||
expect(!isEqual({ x: { a: 1, b: 2 } }, { x: { a: 1, b: 2, c: 3 } })).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it('should correctly compare deep objects without object prototype ', () => {
|
||||
// Solves https://github.com/apollographql/apollo-client/issues/2132
|
||||
const objNoProto = Object.create(null);
|
||||
objNoProto.a = { b: 2, c: [3, 4] };
|
||||
objNoProto.e = Object.create(null);
|
||||
objNoProto.e.f = 5;
|
||||
expect(isEqual(objNoProto, { a: { b: 2, c: [3, 4] }, e: { f: 5 } })).toBe(
|
||||
true,
|
||||
);
|
||||
expect(!isEqual(objNoProto, { a: { b: 2, c: [3, 4] }, e: { f: 6 } })).toBe(
|
||||
true,
|
||||
);
|
||||
expect(!isEqual(objNoProto, { a: { b: 2, c: [3, 4] }, e: null })).toBe(
|
||||
true,
|
||||
);
|
||||
expect(!isEqual(objNoProto, { a: { b: 2, c: [3] }, e: { f: 5 } })).toBe(
|
||||
true,
|
||||
);
|
||||
expect(!isEqual(objNoProto, null)).toBe(true);
|
||||
});
|
||||
|
||||
it('should correctly handle modified prototypes', () => {
|
||||
Array.prototype.foo = null;
|
||||
expect(isEqual([1, 2, 3], [1, 2, 3])).toBe(true);
|
||||
expect(!isEqual([1, 2, 3], [1, 2, 4])).toBe(true);
|
||||
delete Array.prototype.foo;
|
||||
});
|
||||
|
||||
describe('comparing objects with circular refs', () => {
|
||||
// copied with slight modification from lodash test suite
|
||||
it('should compare objects with circular references', () => {
|
||||
const object1 = {},
|
||||
object2 = {};
|
||||
|
||||
object1.a = object1;
|
||||
object2.a = object2;
|
||||
|
||||
expect(isEqual(object1, object2)).toBe(true);
|
||||
|
||||
object1.b = 0;
|
||||
object2.b = Object(0);
|
||||
|
||||
expect(isEqual(object1, object2)).toBe(true);
|
||||
|
||||
object1.c = Object(1);
|
||||
object2.c = Object(2);
|
||||
|
||||
expect(isEqual(object1, object2)).toBe(false);
|
||||
|
||||
object1 = { a: 1, b: 2, c: 3 };
|
||||
object1.b = object1;
|
||||
object2 = { a: 1, b: { a: 1, b: 2, c: 3 }, c: 3 };
|
||||
|
||||
expect(isEqual(object1, object2)).toBe(false);
|
||||
});
|
||||
|
||||
it('should have transitive equivalence for circular references of objects', () => {
|
||||
const object1 = {},
|
||||
object2 = { a: object1 },
|
||||
object3 = { a: object2 };
|
||||
|
||||
object1.a = object1;
|
||||
|
||||
expect(isEqual(object1, object2)).toBe(true);
|
||||
expect(isEqual(object2, object3)).toBe(true);
|
||||
expect(isEqual(object1, object3)).toBe(true);
|
||||
});
|
||||
|
||||
it('should compare objects with multiple circular references', () => {
|
||||
const array1 = [{}],
|
||||
array2 = [{}];
|
||||
|
||||
(array1[0].a = array1).push(array1);
|
||||
(array2[0].a = array2).push(array2);
|
||||
|
||||
expect(isEqual(array1, array2)).toBe(true);
|
||||
|
||||
array1[0].b = 0;
|
||||
array2[0].b = Object(0);
|
||||
|
||||
expect(isEqual(array1, array2)).toBe(true);
|
||||
|
||||
array1[0].c = Object(1);
|
||||
array2[0].c = Object(2);
|
||||
|
||||
expect(isEqual(array1, array2)).toBe(false);
|
||||
});
|
||||
|
||||
it('should compare objects with complex circular references', () => {
|
||||
const object1 = {
|
||||
foo: { b: { c: { d: {} } } },
|
||||
bar: { a: 2 },
|
||||
};
|
||||
|
||||
const object2 = {
|
||||
foo: { b: { c: { d: {} } } },
|
||||
bar: { a: 2 },
|
||||
};
|
||||
|
||||
object1.foo.b.c.d = object1;
|
||||
object1.bar.b = object1.foo.b;
|
||||
|
||||
object2.foo.b.c.d = object2;
|
||||
object2.bar.b = object2.foo.b;
|
||||
|
||||
expect(isEqual(object1, object2)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
17
node_modules/apollo-utilities/src/util/__tests__/maybeDeepFeeze.ts
generated
vendored
Normal file
17
node_modules/apollo-utilities/src/util/__tests__/maybeDeepFeeze.ts
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { maybeDeepFreeze } from '../maybeDeepFreeze';
|
||||
|
||||
describe('maybeDeepFreeze', () => {
|
||||
it('should deep freeze', () => {
|
||||
const foo: any = { bar: undefined };
|
||||
maybeDeepFreeze(foo);
|
||||
expect(() => (foo.bar = 1)).toThrow();
|
||||
expect(foo.bar).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should properly freeze objects without hasOwnProperty', () => {
|
||||
const foo = Object.create(null);
|
||||
foo.bar = undefined;
|
||||
maybeDeepFreeze(foo);
|
||||
expect(() => (foo.bar = 1)).toThrow();
|
||||
});
|
||||
});
|
||||
139
node_modules/apollo-utilities/src/util/__tests__/mergeDeep.ts
generated
vendored
Normal file
139
node_modules/apollo-utilities/src/util/__tests__/mergeDeep.ts
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
import { mergeDeep, mergeDeepArray } from '../mergeDeep';
|
||||
|
||||
describe('mergeDeep', function() {
|
||||
it('should return an object if first argument falsy', function() {
|
||||
expect(mergeDeep()).toEqual({});
|
||||
expect(mergeDeep(null)).toEqual({});
|
||||
expect(mergeDeep(null, { foo: 42 })).toEqual({ foo: 42 });
|
||||
});
|
||||
|
||||
it('should preserve identity for single arguments', function() {
|
||||
const arg = Object.create(null);
|
||||
expect(mergeDeep(arg)).toBe(arg);
|
||||
});
|
||||
|
||||
it('should preserve identity when merging non-conflicting objects', function() {
|
||||
const a = { a: { name: 'ay' } };
|
||||
const b = { b: { name: 'bee' } };
|
||||
const c = mergeDeep(a, b);
|
||||
expect(c.a).toBe(a.a);
|
||||
expect(c.b).toBe(b.b);
|
||||
expect(c).toEqual({
|
||||
a: { name: 'ay' },
|
||||
b: { name: 'bee' },
|
||||
});
|
||||
});
|
||||
|
||||
it('should shallow-copy conflicting fields', function() {
|
||||
const a = { conflict: { fromA: [1, 2, 3] } };
|
||||
const b = { conflict: { fromB: [4, 5] } };
|
||||
const c = mergeDeep(a, b);
|
||||
expect(c.conflict).not.toBe(a.conflict);
|
||||
expect(c.conflict).not.toBe(b.conflict);
|
||||
expect(c.conflict.fromA).toBe(a.conflict.fromA);
|
||||
expect(c.conflict.fromB).toBe(b.conflict.fromB);
|
||||
expect(c).toEqual({
|
||||
conflict: {
|
||||
fromA: [1, 2, 3],
|
||||
fromB: [4, 5],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should resolve conflicts among more than two objects', function() {
|
||||
const sources = [];
|
||||
|
||||
for (let i = 0; i < 100; ++i) {
|
||||
sources.push({
|
||||
['unique' + i]: { value: i },
|
||||
conflict: {
|
||||
['from' + i]: { value: i },
|
||||
nested: {
|
||||
['nested' + i]: { value: i },
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const merged = mergeDeep(...sources);
|
||||
|
||||
sources.forEach((source, i) => {
|
||||
expect(merged['unique' + i].value).toBe(i);
|
||||
expect(source['unique' + i]).toBe(merged['unique' + i]);
|
||||
|
||||
expect(merged.conflict).not.toBe(source.conflict);
|
||||
expect(merged.conflict['from' + i].value).toBe(i);
|
||||
expect(merged.conflict['from' + i]).toBe(source.conflict['from' + i]);
|
||||
|
||||
expect(merged.conflict.nested).not.toBe(source.conflict.nested);
|
||||
expect(merged.conflict.nested['nested' + i].value).toBe(i);
|
||||
expect(merged.conflict.nested['nested' + i]).toBe(
|
||||
source.conflict.nested['nested' + i],
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('can merge array elements', function() {
|
||||
const a = [{ a: 1 }, { a: 'ay' }, 'a'];
|
||||
const b = [{ b: 2 }, { b: 'bee' }, 'b'];
|
||||
const c = [{ c: 3 }, { c: 'cee' }, 'c'];
|
||||
const d = { 1: { d: 'dee' } };
|
||||
|
||||
expect(mergeDeep(a, b, c, d)).toEqual([
|
||||
{ a: 1, b: 2, c: 3 },
|
||||
{ a: 'ay', b: 'bee', c: 'cee', d: 'dee' },
|
||||
'c',
|
||||
]);
|
||||
});
|
||||
|
||||
it('lets the last conflicting value win', function() {
|
||||
expect(mergeDeep('a', 'b', 'c')).toBe('c');
|
||||
|
||||
expect(
|
||||
mergeDeep(
|
||||
{ a: 'a', conflict: 1 },
|
||||
{ b: 'b', conflict: 2 },
|
||||
{ c: 'c', conflict: 3 },
|
||||
),
|
||||
).toEqual({
|
||||
a: 'a',
|
||||
b: 'b',
|
||||
c: 'c',
|
||||
conflict: 3,
|
||||
});
|
||||
|
||||
expect(mergeDeep(
|
||||
['a', ['b', 'c'], 'd'],
|
||||
[/*empty*/, ['B'], 'D'],
|
||||
)).toEqual(
|
||||
['a', ['B', 'c'], 'D'],
|
||||
);
|
||||
|
||||
expect(mergeDeep(
|
||||
['a', ['b', 'c'], 'd'],
|
||||
['A', [/*empty*/, 'C']],
|
||||
)).toEqual(
|
||||
['A', ['b', 'C'], 'd'],
|
||||
);
|
||||
});
|
||||
|
||||
it('mergeDeep returns the intersection of its argument types', function() {
|
||||
const abc = mergeDeep({ str: "hi", a: 1 }, { a: 3, b: 2 }, { b: 1, c: 2 });
|
||||
// The point of this test is that the following lines type-check without
|
||||
// resorting to any `any` loopholes:
|
||||
expect(abc.str.slice(0)).toBe("hi");
|
||||
expect(abc.a * 2).toBe(6);
|
||||
expect(abc.b - 0).toBe(1);
|
||||
expect(abc.c / 2).toBe(1);
|
||||
});
|
||||
|
||||
it('mergeDeepArray returns the supertype of its argument types', function() {
|
||||
class F {
|
||||
check() { return "ok" };
|
||||
}
|
||||
const fs: F[] = [new F, new F, new F];
|
||||
// Although mergeDeepArray doesn't have the same tuple type awareness as
|
||||
// mergeDeep, it does infer that F should be the return type here:
|
||||
expect(mergeDeepArray(fs).check()).toBe("ok");
|
||||
});
|
||||
});
|
||||
15
node_modules/apollo-utilities/src/util/__tests__/stripSymbols.ts
generated
vendored
Normal file
15
node_modules/apollo-utilities/src/util/__tests__/stripSymbols.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import { stripSymbols } from '../stripSymbols';
|
||||
|
||||
interface SymbolConstructor {
|
||||
(description?: string | number): symbol;
|
||||
}
|
||||
|
||||
declare const Symbol: SymbolConstructor;
|
||||
|
||||
describe('stripSymbols', () => {
|
||||
it('should strip symbols (only)', () => {
|
||||
const sym = Symbol('id');
|
||||
const data = { foo: 'bar', [sym]: 'ROOT_QUERY' };
|
||||
expect(stripSymbols(data)).toEqual({ foo: 'bar' });
|
||||
});
|
||||
});
|
||||
61
node_modules/apollo-utilities/src/util/__tests__/warnOnce.ts
generated
vendored
Normal file
61
node_modules/apollo-utilities/src/util/__tests__/warnOnce.ts
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
import { warnOnceInDevelopment } from '../warnOnce';
|
||||
|
||||
let lastWarning: string | null;
|
||||
let keepEnv: string | undefined;
|
||||
let numCalls = 0;
|
||||
let oldConsoleWarn: any;
|
||||
|
||||
describe('warnOnce', () => {
|
||||
beforeEach(() => {
|
||||
keepEnv = process.env.NODE_ENV;
|
||||
numCalls = 0;
|
||||
lastWarning = null;
|
||||
oldConsoleWarn = console.warn;
|
||||
console.warn = (msg: any) => {
|
||||
numCalls++;
|
||||
lastWarning = msg;
|
||||
};
|
||||
});
|
||||
afterEach(() => {
|
||||
process.env.NODE_ENV = keepEnv;
|
||||
console.warn = oldConsoleWarn;
|
||||
});
|
||||
it('actually warns', () => {
|
||||
process.env.NODE_ENV = 'development';
|
||||
warnOnceInDevelopment('hi');
|
||||
expect(lastWarning).toBe('hi');
|
||||
expect(numCalls).toEqual(1);
|
||||
});
|
||||
|
||||
it('does not warn twice', () => {
|
||||
process.env.NODE_ENV = 'development';
|
||||
warnOnceInDevelopment('ho');
|
||||
warnOnceInDevelopment('ho');
|
||||
expect(lastWarning).toEqual('ho');
|
||||
expect(numCalls).toEqual(1);
|
||||
});
|
||||
|
||||
it('warns two different things once each', () => {
|
||||
process.env.NODE_ENV = 'development';
|
||||
warnOnceInDevelopment('slow');
|
||||
expect(lastWarning).toEqual('slow');
|
||||
warnOnceInDevelopment('mo');
|
||||
expect(lastWarning).toEqual('mo');
|
||||
expect(numCalls).toEqual(2);
|
||||
});
|
||||
|
||||
it('does not warn in production', () => {
|
||||
process.env.NODE_ENV = 'production';
|
||||
warnOnceInDevelopment('lo');
|
||||
warnOnceInDevelopment('lo');
|
||||
expect(numCalls).toEqual(0);
|
||||
});
|
||||
|
||||
it('warns many times in test', () => {
|
||||
process.env.NODE_ENV = 'test';
|
||||
warnOnceInDevelopment('yo');
|
||||
warnOnceInDevelopment('yo');
|
||||
expect(lastWarning).toEqual('yo');
|
||||
expect(numCalls).toEqual(2);
|
||||
});
|
||||
});
|
||||
31
node_modules/apollo-utilities/src/util/assign.ts
generated
vendored
Normal file
31
node_modules/apollo-utilities/src/util/assign.ts
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Adds the properties of one or more source objects to a target object. Works exactly like
|
||||
* `Object.assign`, but as a utility to maintain support for IE 11.
|
||||
*
|
||||
* @see https://github.com/apollostack/apollo-client/pull/1009
|
||||
*/
|
||||
export function assign<A, B>(a: A, b: B): A & B;
|
||||
export function assign<A, B, C>(a: A, b: B, c: C): A & B & C;
|
||||
export function assign<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D;
|
||||
export function assign<A, B, C, D, E>(
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
e: E,
|
||||
): A & B & C & D & E;
|
||||
export function assign(target: any, ...sources: Array<any>): any;
|
||||
export function assign(
|
||||
target: { [key: string]: any },
|
||||
...sources: Array<{ [key: string]: any }>
|
||||
): { [key: string]: any } {
|
||||
sources.forEach(source => {
|
||||
if (typeof source === 'undefined' || source === null) {
|
||||
return;
|
||||
}
|
||||
Object.keys(source).forEach(key => {
|
||||
target[key] = source[key];
|
||||
});
|
||||
});
|
||||
return target;
|
||||
}
|
||||
4
node_modules/apollo-utilities/src/util/canUse.ts
generated
vendored
Normal file
4
node_modules/apollo-utilities/src/util/canUse.ts
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
export const canUseWeakMap = typeof WeakMap === 'function' && !(
|
||||
typeof navigator === 'object' &&
|
||||
navigator.product === 'ReactNative'
|
||||
);
|
||||
37
node_modules/apollo-utilities/src/util/cloneDeep.ts
generated
vendored
Normal file
37
node_modules/apollo-utilities/src/util/cloneDeep.ts
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
const { toString } = Object.prototype;
|
||||
|
||||
/**
|
||||
* Deeply clones a value to create a new instance.
|
||||
*/
|
||||
export function cloneDeep<T>(value: T): T {
|
||||
return cloneDeepHelper(value, new Map());
|
||||
}
|
||||
|
||||
function cloneDeepHelper<T>(val: T, seen: Map<any, any>): T {
|
||||
switch (toString.call(val)) {
|
||||
case "[object Array]": {
|
||||
if (seen.has(val)) return seen.get(val);
|
||||
const copy: T & any[] = (val as any).slice(0);
|
||||
seen.set(val, copy);
|
||||
copy.forEach(function (child, i) {
|
||||
copy[i] = cloneDeepHelper(child, seen);
|
||||
});
|
||||
return copy;
|
||||
}
|
||||
|
||||
case "[object Object]": {
|
||||
if (seen.has(val)) return seen.get(val);
|
||||
// High fidelity polyfills of Object.create and Object.getPrototypeOf are
|
||||
// possible in all JS environments, so we will assume they exist/work.
|
||||
const copy = Object.create(Object.getPrototypeOf(val));
|
||||
seen.set(val, copy);
|
||||
Object.keys(val).forEach(key => {
|
||||
copy[key] = cloneDeepHelper((val as any)[key], seen);
|
||||
});
|
||||
return copy;
|
||||
}
|
||||
|
||||
default:
|
||||
return val;
|
||||
}
|
||||
}
|
||||
24
node_modules/apollo-utilities/src/util/environment.ts
generated
vendored
Normal file
24
node_modules/apollo-utilities/src/util/environment.ts
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
export function getEnv(): string | undefined {
|
||||
if (typeof process !== 'undefined' && process.env.NODE_ENV) {
|
||||
return process.env.NODE_ENV;
|
||||
}
|
||||
|
||||
// default environment
|
||||
return 'development';
|
||||
}
|
||||
|
||||
export function isEnv(env: string): boolean {
|
||||
return getEnv() === env;
|
||||
}
|
||||
|
||||
export function isProduction(): boolean {
|
||||
return isEnv('production') === true;
|
||||
}
|
||||
|
||||
export function isDevelopment(): boolean {
|
||||
return isEnv('development') === true;
|
||||
}
|
||||
|
||||
export function isTest(): boolean {
|
||||
return isEnv('test') === true;
|
||||
}
|
||||
15
node_modules/apollo-utilities/src/util/errorHandling.ts
generated
vendored
Normal file
15
node_modules/apollo-utilities/src/util/errorHandling.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import { ExecutionResult } from 'graphql';
|
||||
|
||||
export function tryFunctionOrLogError(f: Function) {
|
||||
try {
|
||||
return f();
|
||||
} catch (e) {
|
||||
if (console.error) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function graphQLResultHasError(result: ExecutionResult) {
|
||||
return result.errors && result.errors.length;
|
||||
}
|
||||
14
node_modules/apollo-utilities/src/util/filterInPlace.ts
generated
vendored
Normal file
14
node_modules/apollo-utilities/src/util/filterInPlace.ts
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
export function filterInPlace<T>(
|
||||
array: T[],
|
||||
test: (elem: T) => boolean,
|
||||
context?: any,
|
||||
): T[] {
|
||||
let target = 0;
|
||||
array.forEach(function (elem, i) {
|
||||
if (test.call(this, elem, i, array)) {
|
||||
array[target++] = elem;
|
||||
}
|
||||
}, context);
|
||||
array.length = target;
|
||||
return array;
|
||||
}
|
||||
1
node_modules/apollo-utilities/src/util/isEqual.ts
generated
vendored
Normal file
1
node_modules/apollo-utilities/src/util/isEqual.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export { equal as isEqual } from '@wry/equality';
|
||||
33
node_modules/apollo-utilities/src/util/maybeDeepFreeze.ts
generated
vendored
Normal file
33
node_modules/apollo-utilities/src/util/maybeDeepFreeze.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { isDevelopment, isTest } from './environment';
|
||||
|
||||
// Taken (mostly) from https://github.com/substack/deep-freeze to avoid
|
||||
// import hassles with rollup.
|
||||
function deepFreeze(o: any) {
|
||||
Object.freeze(o);
|
||||
|
||||
Object.getOwnPropertyNames(o).forEach(function(prop) {
|
||||
if (
|
||||
o[prop] !== null &&
|
||||
(typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
|
||||
!Object.isFrozen(o[prop])
|
||||
) {
|
||||
deepFreeze(o[prop]);
|
||||
}
|
||||
});
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
export function maybeDeepFreeze(obj: any) {
|
||||
if (isDevelopment() || isTest()) {
|
||||
// Polyfilled Symbols potentially cause infinite / very deep recursion while deep freezing
|
||||
// which is known to crash IE11 (https://github.com/apollographql/apollo-client/issues/3043).
|
||||
const symbolIsPolyfilled =
|
||||
typeof Symbol === 'function' && typeof Symbol('') === 'string';
|
||||
|
||||
if (!symbolIsPolyfilled) {
|
||||
return deepFreeze(obj);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
115
node_modules/apollo-utilities/src/util/mergeDeep.ts
generated
vendored
Normal file
115
node_modules/apollo-utilities/src/util/mergeDeep.ts
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
const { hasOwnProperty } = Object.prototype;
|
||||
|
||||
// These mergeDeep and mergeDeepArray utilities merge any number of objects
|
||||
// together, sharing as much memory as possible with the source objects, while
|
||||
// remaining careful to avoid modifying any source objects.
|
||||
|
||||
// Logically, the return type of mergeDeep should be the intersection of
|
||||
// all the argument types. The binary call signature is by far the most
|
||||
// common, but we support 0- through 5-ary as well. After that, the
|
||||
// resulting type is just the inferred array element type. Note to nerds:
|
||||
// there is a more clever way of doing this that converts the tuple type
|
||||
// first to a union type (easy enough: T[number]) and then converts the
|
||||
// union to an intersection type using distributive conditional type
|
||||
// inference, but that approach has several fatal flaws (boolean becomes
|
||||
// true & false, and the inferred type ends up as unknown in many cases),
|
||||
// in addition to being nearly impossible to explain/understand.
|
||||
export type TupleToIntersection<T extends any[]> =
|
||||
T extends [infer A] ? A :
|
||||
T extends [infer A, infer B] ? A & B :
|
||||
T extends [infer A, infer B, infer C] ? A & B & C :
|
||||
T extends [infer A, infer B, infer C, infer D] ? A & B & C & D :
|
||||
T extends [infer A, infer B, infer C, infer D, infer E] ? A & B & C & D & E :
|
||||
T extends (infer U)[] ? U : any;
|
||||
|
||||
export function mergeDeep<T extends any[]>(
|
||||
...sources: T
|
||||
): TupleToIntersection<T> {
|
||||
return mergeDeepArray(sources);
|
||||
}
|
||||
|
||||
// In almost any situation where you could succeed in getting the
|
||||
// TypeScript compiler to infer a tuple type for the sources array, you
|
||||
// could just use mergeDeep instead of mergeDeepArray, so instead of
|
||||
// trying to convert T[] to an intersection type we just infer the array
|
||||
// element type, which works perfectly when the sources array has a
|
||||
// consistent element type.
|
||||
export function mergeDeepArray<T>(sources: T[]): T {
|
||||
let target = sources[0] || {} as T;
|
||||
const count = sources.length;
|
||||
if (count > 1) {
|
||||
const pastCopies: any[] = [];
|
||||
target = shallowCopyForMerge(target, pastCopies);
|
||||
for (let i = 1; i < count; ++i) {
|
||||
target = mergeHelper(target, sources[i], pastCopies);
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
function isObject(obj: any): obj is Record<string | number, any> {
|
||||
return obj !== null && typeof obj === 'object';
|
||||
}
|
||||
|
||||
function mergeHelper(
|
||||
target: any,
|
||||
source: any,
|
||||
pastCopies: any[],
|
||||
) {
|
||||
if (isObject(source) && isObject(target)) {
|
||||
// In case the target has been frozen, make an extensible copy so that
|
||||
// we can merge properties into the copy.
|
||||
if (Object.isExtensible && !Object.isExtensible(target)) {
|
||||
target = shallowCopyForMerge(target, pastCopies);
|
||||
}
|
||||
|
||||
Object.keys(source).forEach(sourceKey => {
|
||||
const sourceValue = source[sourceKey];
|
||||
if (hasOwnProperty.call(target, sourceKey)) {
|
||||
const targetValue = target[sourceKey];
|
||||
if (sourceValue !== targetValue) {
|
||||
// When there is a key collision, we need to make a shallow copy of
|
||||
// target[sourceKey] so the merge does not modify any source objects.
|
||||
// To avoid making unnecessary copies, we use a simple array to track
|
||||
// past copies, since it's safe to modify copies created earlier in
|
||||
// the merge. We use an array for pastCopies instead of a Map or Set,
|
||||
// since the number of copies should be relatively small, and some
|
||||
// Map/Set polyfills modify their keys.
|
||||
target[sourceKey] = mergeHelper(
|
||||
shallowCopyForMerge(targetValue, pastCopies),
|
||||
sourceValue,
|
||||
pastCopies,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// If there is no collision, the target can safely share memory with
|
||||
// the source, and the recursion can terminate here.
|
||||
target[sourceKey] = sourceValue;
|
||||
}
|
||||
});
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
// If source (or target) is not an object, let source replace target.
|
||||
return source;
|
||||
}
|
||||
|
||||
function shallowCopyForMerge<T>(value: T, pastCopies: any[]): T {
|
||||
if (
|
||||
value !== null &&
|
||||
typeof value === 'object' &&
|
||||
pastCopies.indexOf(value) < 0
|
||||
) {
|
||||
if (Array.isArray(value)) {
|
||||
value = (value as any).slice(0);
|
||||
} else {
|
||||
value = {
|
||||
__proto__: Object.getPrototypeOf(value),
|
||||
...value,
|
||||
};
|
||||
}
|
||||
pastCopies.push(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
14
node_modules/apollo-utilities/src/util/stripSymbols.ts
generated
vendored
Normal file
14
node_modules/apollo-utilities/src/util/stripSymbols.ts
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* In order to make assertions easier, this function strips `symbol`'s from
|
||||
* the incoming data.
|
||||
*
|
||||
* This can be handy when running tests against `apollo-client` for example,
|
||||
* since it adds `symbol`'s to the data in the store. Jest's `toEqual`
|
||||
* function now covers `symbol`'s (https://github.com/facebook/jest/pull/3437),
|
||||
* which means all test data used in a `toEqual` comparison would also have to
|
||||
* include `symbol`'s, to pass. By stripping `symbol`'s from the cache data
|
||||
* we can compare against more simplified test data.
|
||||
*/
|
||||
export function stripSymbols<T>(data: T): T {
|
||||
return JSON.parse(JSON.stringify(data));
|
||||
}
|
||||
24
node_modules/apollo-utilities/src/util/warnOnce.ts
generated
vendored
Normal file
24
node_modules/apollo-utilities/src/util/warnOnce.ts
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import { isProduction, isTest } from './environment';
|
||||
|
||||
const haveWarned = Object.create({});
|
||||
|
||||
/**
|
||||
* Print a warning only once in development.
|
||||
* In production no warnings are printed.
|
||||
* In test all warnings are printed.
|
||||
*
|
||||
* @param msg The warning message
|
||||
* @param type warn or error (will call console.warn or console.error)
|
||||
*/
|
||||
export function warnOnceInDevelopment(msg: string, type = 'warn') {
|
||||
if (!isProduction() && !haveWarned[msg]) {
|
||||
if (!isTest()) {
|
||||
haveWarned[msg] = true;
|
||||
}
|
||||
if (type === 'error') {
|
||||
console.error(msg);
|
||||
} else {
|
||||
console.warn(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user