launchdarkly-js-sdk-common 4.3.2 → 5.0.0-alpha.2

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 (37) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/package.json +3 -1
  3. package/src/AnonymousContextProcessor.js +95 -0
  4. package/src/ContextFilter.js +137 -0
  5. package/src/EventProcessor.js +30 -13
  6. package/src/EventSender.js +1 -1
  7. package/src/Identity.js +10 -11
  8. package/src/InspectorManager.js +1 -1
  9. package/src/PersistentFlagStore.js +3 -3
  10. package/src/Requestor.js +4 -4
  11. package/src/SafeInspector.js +1 -1
  12. package/src/Stream.js +5 -5
  13. package/src/__tests__/ContextFilter-test.js +427 -0
  14. package/src/__tests__/EventProcessor-test.js +50 -121
  15. package/src/__tests__/LDClient-events-test.js +9 -152
  16. package/src/__tests__/LDClient-inspectors-test.js +1 -1
  17. package/src/__tests__/LDClient-test.js +18 -15
  18. package/src/__tests__/TransientContextProcessor-test.js +115 -0
  19. package/src/__tests__/attributeReference-test.js +400 -0
  20. package/src/__tests__/configuration-test.js +20 -21
  21. package/src/__tests__/context-test.js +93 -0
  22. package/src/__tests__/diagnosticEvents-test.js +0 -4
  23. package/src/__tests__/testUtils.js +0 -2
  24. package/src/__tests__/utils-test.js +3 -9
  25. package/src/attributeReference.js +143 -0
  26. package/src/configuration.js +4 -8
  27. package/src/context.js +96 -0
  28. package/src/diagnosticEvents.js +0 -2
  29. package/src/index.js +76 -89
  30. package/src/messages.js +8 -8
  31. package/src/utils.js +19 -16
  32. package/test-types.ts +3 -8
  33. package/typings.d.ts +296 -139
  34. package/src/UserFilter.js +0 -75
  35. package/src/UserValidator.js +0 -56
  36. package/src/__tests__/UserFilter-test.js +0 -93
  37. package/src/__tests__/UserValidator-test.js +0 -57
package/src/UserFilter.js DELETED
@@ -1,75 +0,0 @@
1
- const utils = require('./utils');
2
-
3
- /**
4
- * The UserFilter object transforms user objects into objects suitable to be sent as JSON to
5
- * the server, hiding any private user attributes.
6
- *
7
- * @param {Object} the LaunchDarkly client configuration object
8
- **/
9
- function UserFilter(config) {
10
- const filter = {};
11
- const allAttributesPrivate = config.allAttributesPrivate;
12
- const privateAttributeNames = config.privateAttributeNames || [];
13
- const ignoreAttrs = { key: true, custom: true, anonymous: true };
14
- const allowedTopLevelAttrs = {
15
- key: true,
16
- secondary: true,
17
- ip: true,
18
- country: true,
19
- email: true,
20
- firstName: true,
21
- lastName: true,
22
- avatar: true,
23
- name: true,
24
- anonymous: true,
25
- custom: true,
26
- };
27
-
28
- filter.filterUser = function(user) {
29
- if (!user) {
30
- return null;
31
- }
32
- const userPrivateAttrs = user.privateAttributeNames || [];
33
-
34
- const isPrivateAttr = function(name) {
35
- return (
36
- !ignoreAttrs[name] &&
37
- (allAttributesPrivate || userPrivateAttrs.indexOf(name) !== -1 || privateAttributeNames.indexOf(name) !== -1)
38
- );
39
- };
40
- const filterAttrs = function(props, isAttributeAllowed) {
41
- return Object.keys(props).reduce(
42
- (acc, name) => {
43
- const ret = acc;
44
- if (isAttributeAllowed(name)) {
45
- if (isPrivateAttr(name)) {
46
- // add to hidden list
47
- ret[1][name] = true;
48
- } else {
49
- ret[0][name] = props[name];
50
- }
51
- }
52
- return ret;
53
- },
54
- [{}, {}]
55
- );
56
- };
57
- const result = filterAttrs(user, key => allowedTopLevelAttrs[key]);
58
- const filteredProps = result[0];
59
- let removedAttrs = result[1];
60
- if (user.custom) {
61
- const customResult = filterAttrs(user.custom, () => true);
62
- filteredProps.custom = customResult[0];
63
- removedAttrs = utils.extend({}, removedAttrs, customResult[1]);
64
- }
65
- const removedAttrNames = Object.keys(removedAttrs);
66
- if (removedAttrNames.length) {
67
- removedAttrNames.sort();
68
- filteredProps.privateAttrs = removedAttrNames;
69
- }
70
- return filteredProps;
71
- };
72
- return filter;
73
- }
74
-
75
- module.exports = UserFilter;
@@ -1,56 +0,0 @@
1
- const { v1: uuidv1 } = require('uuid');
2
-
3
- const errors = require('./errors');
4
- const messages = require('./messages');
5
- const utils = require('./utils');
6
-
7
- // Transforms the user object if necessary to make sure it has a valid key.
8
- // 1. If a key is present, but is not a string, change it to a string.
9
- // 2. If no key is present, and "anonymous" is true, use a UUID as a key. This is cached in local
10
- // storage if possible.
11
- // 3. If there is no key (or no user object), return an error.
12
-
13
- const ldUserIdKey = 'ld:$anonUserId';
14
-
15
- function UserValidator(persistentStorage) {
16
- function getCachedUserId() {
17
- return persistentStorage.get(ldUserIdKey);
18
- }
19
-
20
- function setCachedUserId(id) {
21
- return persistentStorage.set(ldUserIdKey, id);
22
- }
23
-
24
- const ret = {};
25
-
26
- // Validates the user, returning a Promise that resolves to the validated user, or rejects if there is an error.
27
- ret.validateUser = user => {
28
- if (!user) {
29
- return Promise.reject(new errors.LDInvalidUserError(messages.userNotSpecified()));
30
- }
31
-
32
- const userOut = utils.clone(user);
33
- if (userOut.key !== null && userOut.key !== undefined) {
34
- userOut.key = userOut.key.toString();
35
- return Promise.resolve(userOut);
36
- }
37
- if (userOut.anonymous) {
38
- return getCachedUserId().then(cachedId => {
39
- if (cachedId) {
40
- userOut.key = cachedId;
41
- return userOut;
42
- } else {
43
- const id = uuidv1();
44
- userOut.key = id;
45
- return setCachedUserId(id).then(() => userOut);
46
- }
47
- });
48
- } else {
49
- return Promise.reject(new errors.LDInvalidUserError(messages.invalidUser()));
50
- }
51
- };
52
-
53
- return ret;
54
- }
55
-
56
- module.exports = UserValidator;
@@ -1,93 +0,0 @@
1
- import UserFilter from '../UserFilter';
2
-
3
- describe('UserFilter', () => {
4
- // users to serialize
5
- const user = {
6
- key: 'abc',
7
- firstName: 'Sue',
8
- custom: { bizzle: 'def', dizzle: 'ghi' },
9
- };
10
-
11
- const userSpecifyingOwnPrivateAttr = {
12
- key: 'abc',
13
- firstName: 'Sue',
14
- custom: { bizzle: 'def', dizzle: 'ghi' },
15
- privateAttributeNames: ['dizzle', 'unused'],
16
- };
17
-
18
- const userWithUnknownTopLevelAttrs = {
19
- key: 'abc',
20
- firstName: 'Sue',
21
- species: 'human',
22
- hatSize: 6,
23
- custom: { bizzle: 'def', dizzle: 'ghi' },
24
- };
25
-
26
- const anonUser = {
27
- key: 'abc',
28
- anonymous: true,
29
- custom: { bizzle: 'def', dizzle: 'ghi' },
30
- };
31
-
32
- // expected results from serializing user
33
- const userWithAllAttrsHidden = {
34
- key: 'abc',
35
- custom: {},
36
- privateAttrs: ['bizzle', 'dizzle', 'firstName'],
37
- };
38
-
39
- const userWithSomeAttrsHidden = {
40
- key: 'abc',
41
- custom: { dizzle: 'ghi' },
42
- privateAttrs: ['bizzle', 'firstName'],
43
- };
44
-
45
- const userWithOwnSpecifiedAttrHidden = {
46
- key: 'abc',
47
- firstName: 'Sue',
48
- custom: { bizzle: 'def' },
49
- privateAttrs: ['dizzle'],
50
- };
51
-
52
- const anonUserWithAllAttrsHidden = {
53
- key: 'abc',
54
- anonymous: true,
55
- custom: {},
56
- privateAttrs: ['bizzle', 'dizzle'],
57
- };
58
-
59
- it('includes all user attributes by default', () => {
60
- const uf = UserFilter({});
61
- expect(uf.filterUser(user)).toEqual(user);
62
- });
63
-
64
- it('hides all except key if allAttributesPrivate is true', () => {
65
- const uf = UserFilter({ allAttributesPrivate: true });
66
- expect(uf.filterUser(user)).toEqual(userWithAllAttrsHidden);
67
- });
68
-
69
- it('hides some attributes if privateAttributeNames is set', () => {
70
- const uf = UserFilter({ privateAttributeNames: ['firstName', 'bizzle'] });
71
- expect(uf.filterUser(user)).toEqual(userWithSomeAttrsHidden);
72
- });
73
-
74
- it('hides attributes specified in per-user privateAttrs', () => {
75
- const uf = UserFilter({});
76
- expect(uf.filterUser(userSpecifyingOwnPrivateAttr)).toEqual(userWithOwnSpecifiedAttrHidden);
77
- });
78
-
79
- it('looks at both per-user privateAttrs and global config', () => {
80
- const uf = UserFilter({ privateAttributeNames: ['firstName', 'bizzle'] });
81
- expect(uf.filterUser(userSpecifyingOwnPrivateAttr)).toEqual(userWithAllAttrsHidden);
82
- });
83
-
84
- it('strips unknown top-level attributes', () => {
85
- const uf = UserFilter({});
86
- expect(uf.filterUser(userWithUnknownTopLevelAttrs)).toEqual(user);
87
- });
88
-
89
- it('leaves the "anonymous" attribute as is', () => {
90
- const uf = UserFilter({ allAttributesPrivate: true });
91
- expect(uf.filterUser(anonUser)).toEqual(anonUserWithAllAttrsHidden);
92
- });
93
- });
@@ -1,57 +0,0 @@
1
- import UserValidator from '../UserValidator';
2
-
3
- describe('UserValidator', () => {
4
- let localStorage;
5
- let logger;
6
- let uv;
7
-
8
- beforeEach(() => {
9
- localStorage = {};
10
- logger = {
11
- warn: jest.fn(),
12
- };
13
- uv = UserValidator(localStorage, logger);
14
- });
15
-
16
- it('rejects null user', async () => {
17
- await expect(uv.validateUser(null)).rejects.toThrow();
18
- });
19
-
20
- it('leaves user with string key unchanged', async () => {
21
- const u = { key: 'someone', name: 'me' };
22
- expect(await uv.validateUser(u)).toEqual(u);
23
- });
24
-
25
- it('stringifies non-string key', async () => {
26
- const u0 = { key: 123, name: 'me' };
27
- const u1 = { key: '123', name: 'me' };
28
- expect(await uv.validateUser(u0)).toEqual(u1);
29
- });
30
-
31
- it('uses cached key for anonymous user', async () => {
32
- const cachedKey = 'thing';
33
- let storageKey;
34
- localStorage.get = async key => {
35
- storageKey = key;
36
- return cachedKey;
37
- };
38
- const u = { anonymous: true };
39
- expect(await uv.validateUser(u)).toEqual({ key: cachedKey, anonymous: true });
40
- expect(storageKey).toEqual('ld:$anonUserId');
41
- });
42
-
43
- it('generates and stores key for anonymous user', async () => {
44
- let storageKey;
45
- let storedValue;
46
- localStorage.get = async () => null;
47
- localStorage.set = async (key, value) => {
48
- storageKey = key;
49
- storedValue = value;
50
- };
51
- const u0 = { anonymous: true };
52
- const u1 = await uv.validateUser(u0);
53
- expect(storedValue).toEqual(expect.anything());
54
- expect(u1).toEqual({ key: storedValue, anonymous: true });
55
- expect(storageKey).toEqual('ld:$anonUserId');
56
- });
57
- });