launchdarkly-js-sdk-common 3.5.0 → 4.0.3

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 (68) hide show
  1. package/.circleci/config.yml +22 -0
  2. package/.eslintignore +4 -0
  3. package/.eslintrc.yaml +103 -0
  4. package/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  5. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. package/.github/pull_request_template.md +21 -0
  7. package/.ldrelease/config.yml +24 -0
  8. package/.prettierignore +1 -0
  9. package/.prettierrc +5 -0
  10. package/CHANGELOG.md +17 -0
  11. package/CONTRIBUTING.md +45 -0
  12. package/babel.config.js +18 -0
  13. package/docs/typedoc.js +11 -0
  14. package/jest.config.js +12 -0
  15. package/package.json +4 -32
  16. package/scripts/better-audit.sh +76 -0
  17. package/src/EventEmitter.js +60 -0
  18. package/src/EventProcessor.js +175 -0
  19. package/src/EventSender.js +87 -0
  20. package/src/EventSummarizer.js +84 -0
  21. package/src/Identity.js +26 -0
  22. package/src/InitializationState.js +83 -0
  23. package/src/PersistentFlagStore.js +50 -0
  24. package/src/PersistentStorage.js +81 -0
  25. package/src/Requestor.js +111 -0
  26. package/src/Stream.js +154 -0
  27. package/src/UserFilter.js +75 -0
  28. package/src/UserValidator.js +56 -0
  29. package/src/__tests__/.eslintrc.yaml +6 -0
  30. package/src/__tests__/EventProcessor-test.js +559 -0
  31. package/src/__tests__/EventSender-test.js +252 -0
  32. package/src/__tests__/EventSource-mock.js +61 -0
  33. package/src/__tests__/EventSummarizer-test.js +103 -0
  34. package/src/__tests__/LDClient-events-test.js +757 -0
  35. package/src/__tests__/LDClient-localstorage-test.js +179 -0
  36. package/src/__tests__/LDClient-streaming-test.js +716 -0
  37. package/src/__tests__/LDClient-test.js +753 -0
  38. package/src/__tests__/PersistentFlagStore-test.js +111 -0
  39. package/src/__tests__/Requestor-test.js +362 -0
  40. package/src/__tests__/Stream-test.js +299 -0
  41. package/src/__tests__/UserFilter-test.js +93 -0
  42. package/src/__tests__/UserValidator-test.js +57 -0
  43. package/src/__tests__/configuration-test.js +217 -0
  44. package/src/__tests__/diagnosticEvents-test.js +449 -0
  45. package/src/__tests__/loggers-test.js +149 -0
  46. package/src/__tests__/mockHttp.js +122 -0
  47. package/src/__tests__/promiseCoalescer-test.js +128 -0
  48. package/src/__tests__/stubPlatform.js +148 -0
  49. package/src/__tests__/testUtils.js +77 -0
  50. package/src/__tests__/utils-test.js +148 -0
  51. package/src/configuration.js +151 -0
  52. package/src/diagnosticEvents.js +269 -0
  53. package/src/errors.js +39 -0
  54. package/src/index.js +788 -0
  55. package/src/jest.setup.js +1 -0
  56. package/src/loggers.js +93 -0
  57. package/src/messages.js +222 -0
  58. package/src/promiseCoalescer.js +52 -0
  59. package/src/utils.js +214 -0
  60. package/test-types.ts +94 -0
  61. package/tsconfig.json +13 -0
  62. package/typings.d.ts +4 -43
  63. package/dist/ldclient-common.cjs.js +0 -2
  64. package/dist/ldclient-common.cjs.js.map +0 -1
  65. package/dist/ldclient-common.es.js +0 -2
  66. package/dist/ldclient-common.es.js.map +0 -1
  67. package/dist/ldclient-common.min.js +0 -2
  68. package/dist/ldclient-common.min.js.map +0 -1
@@ -0,0 +1,22 @@
1
+ version: 2
2
+ jobs:
3
+ build:
4
+ docker:
5
+ - image: cimg/node:12.22
6
+ steps:
7
+ - checkout
8
+
9
+ - run: npm install
10
+ - run: npm run lint:all
11
+ - run:
12
+ command: npm test
13
+ environment:
14
+ JEST_JUNIT_OUTPUT: "reports/junit/js-test-results.xml"
15
+ - run: npm run check-typescript
16
+ - run:
17
+ name: dependency audit
18
+ command: ./scripts/better-audit.sh
19
+ - store_test_results:
20
+ path: reports/junit/
21
+ - store_artifacts:
22
+ path: reports/junit/
package/.eslintignore ADDED
@@ -0,0 +1,4 @@
1
+ node_modules/
2
+ coverage/
3
+ dist/
4
+ eventsource.js
package/.eslintrc.yaml ADDED
@@ -0,0 +1,103 @@
1
+ ---
2
+ parser: babel-eslint
3
+ root: true
4
+ extends:
5
+ - prettier
6
+ - eslint:recommended # https://eslint.org/docs/rules/
7
+ env:
8
+ es6: true
9
+ node: true
10
+ plugins:
11
+ - babel
12
+ - prettier
13
+ globals:
14
+ describe: true
15
+ it: true
16
+ expect: true
17
+ jest: true
18
+ beforeAll: true
19
+ afterAll: true
20
+ beforeEach: true
21
+ afterEach: true
22
+ window: false # platform-agnostic code should *not* reference "window" or "document"
23
+ document: false
24
+ rules:
25
+ # https://eslint.org/docs/rules/array-callback-return
26
+ array-callback-return: error
27
+
28
+ # https://eslint.org/docs/rules/arrow-body-style
29
+ arrow-body-style:
30
+ - error
31
+ - as-needed
32
+
33
+ # https://github.com/babel/eslint-plugin-babel
34
+ babel/semi: error
35
+
36
+ # Deprecations are required to turn enforce this
37
+ camelcase: warn
38
+
39
+ # https://eslint.org/docs/rules/curly
40
+ curly:
41
+ - error
42
+ - all
43
+
44
+ # https://eslint.org/docs/rules/eqeqeq
45
+ eqeqeq: error
46
+
47
+ # https://eslint.org/docs/rules/no-array-constructor
48
+ no-array-constructor: error
49
+
50
+ # https://eslint.org/docs/rules/no-eval
51
+ no-eval: error
52
+
53
+ # https://eslint.org/docs/rules/no-implicit-coercion
54
+ no-implicit-coercion:
55
+ - 'off'
56
+ - boolean: false
57
+ number: true
58
+ string: true
59
+ allow: []
60
+
61
+ # https://eslint.org/docs/rules/no-implied-eval
62
+ no-implied-eval: error
63
+
64
+ # https://eslint.org/docs/rules/no-nested-ternary
65
+ no-nested-ternary: error
66
+
67
+ # https://eslint.org/docs/rules/no-new-object
68
+ no-new-object: error
69
+
70
+ # https://eslint.org/docs/rules/no-new-wrappers
71
+ no-new-wrappers: error
72
+
73
+ # https://eslint.org/docs/rules/no-param-reassign
74
+ no-param-reassign:
75
+ - error
76
+ - props: true
77
+
78
+ # https://eslint.org/docs/rules/no-return-assign
79
+ no-return-assign: error
80
+
81
+ # https://eslint.org/docs/rules/no-self-compare
82
+ no-self-compare: error
83
+
84
+ # https://eslint.org/docs/rules/no-use-before-define
85
+ no-use-before-define:
86
+ - error
87
+ - functions: false
88
+
89
+ # https://eslint.org/docs/rules/no-var
90
+ no-var: error
91
+
92
+ # https://eslint.org/docs/rules/prefer-arrow-callback
93
+ prefer-arrow-callback: error
94
+
95
+ # https://eslint.org/docs/rules/prefer-const
96
+ prefer-const: error
97
+
98
+ # https://github.com/prettier/eslint-plugin-prettier
99
+ prettier/prettier:
100
+ - error
101
+
102
+ # https://eslint.org/docs/rules/radix
103
+ radix: error
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Is this a support request?**
11
+ This issue tracker is maintained by LaunchDarkly SDK developers and is intended for feedback on the SDK code. If you're not sure whether the problem you are having is specifically related to the SDK, or to the LaunchDarkly service overall, it may be more appropriate to contact the LaunchDarkly support team; they can help to investigate the problem and will consult the SDK team if necessary. You can submit a support request by going [here](https://support.launchdarkly.com/) and clicking "submit a request", or by emailing support@launchdarkly.com.
12
+
13
+ Note that issues filed on this issue tracker are publicly accessible. Do not provide any private account information on your issues. If your problem is specific to your account, you should submit a support request as described above.
14
+
15
+ **Describe the bug**
16
+ A clear and concise description of what the bug is.
17
+
18
+ **To reproduce**
19
+ Steps to reproduce the behavior.
20
+
21
+ **Expected behavior**
22
+ A clear and concise description of what you expected to happen.
23
+
24
+ **Logs**
25
+ If applicable, add any log output related to your problem.
26
+
27
+ **SDK version**
28
+ The version of this SDK that you are using.
29
+
30
+ **Language version, developer tools**
31
+ For instance, Go 1.11 or Ruby 2.5.3. If you are using a language that requires a separate compiler, such as C, please include the name and version of the compiler too.
32
+
33
+ **OS/platform**
34
+ For instance, Ubuntu 16.04, Windows 10, or Android 4.0.3. If your code is running in a browser, please also include the browser type and version.
35
+
36
+ **Additional context**
37
+ Add any other context about the problem here.
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Is your feature request related to a problem? Please describe.**
11
+ A clear and concise description of what the problem is. Ex. I would love to see the SDK [...does something new...]
12
+
13
+ **Describe the solution you'd like**
14
+ A clear and concise description of what you want to happen.
15
+
16
+ **Describe alternatives you've considered**
17
+ A clear and concise description of any alternative solutions or features you've considered.
18
+
19
+ **Additional context**
20
+ Add any other context about the feature request here.
@@ -0,0 +1,21 @@
1
+ **Requirements**
2
+
3
+ - [ ] I have added test coverage for new or changed functionality
4
+ - [ ] I have followed the repository's [pull request submission guidelines](../blob/master/CONTRIBUTING.md#submitting-pull-requests)
5
+ - [ ] I have validated my changes against all supported platform versions
6
+
7
+ **Related issues**
8
+
9
+ Provide links to any issues in this repository or elsewhere relating to this pull request.
10
+
11
+ **Describe the solution you've provided**
12
+
13
+ Provide a clear and concise description of what you expect to happen.
14
+
15
+ **Describe alternatives you've considered**
16
+
17
+ Provide a clear and concise description of any alternative solutions or features you've considered.
18
+
19
+ **Additional context**
20
+
21
+ Add any other context about the pull request here.
@@ -0,0 +1,24 @@
1
+ version: 2
2
+
3
+ repo:
4
+ public: js-sdk-common
5
+ private: js-sdk-common-private
6
+
7
+ branches:
8
+ - name: master
9
+ description: 4.x
10
+ - name: 3.x
11
+
12
+ publications:
13
+ - url: https://www.npmjs.com/package/launchdarkly-js-sdk-common
14
+ description: npm
15
+
16
+ jobs:
17
+ - docker:
18
+ image: node:12-buster
19
+ template:
20
+ name: npm
21
+
22
+ documentation:
23
+ gitHubPages: true
24
+ title: LaunchDarkly Javascript SDK Core Components
@@ -0,0 +1 @@
1
+ package.json
package/.prettierrc ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "trailingComma": "es5",
3
+ "singleQuote": true,
4
+ "printWidth": 120
5
+ }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  All notable changes to the `launchdarkly-js-sdk-common` package will be documented in this file. Changes that affect the dependent SDKs such as `launchdarkly-js-client-sdk` should also be logged in those projects, in the next release that uses the updated version of this package. This project adheres to [Semantic Versioning](http://semver.org).
4
4
 
5
+ ## [4.0.2] - 2022-01-25
6
+ ### Removed:
7
+ - Removed the `version` export which was originally a constant inserted by the Rollup build, but was no longer usable since Rollup is no longer being used. The SDKs never used this export, since they have `version` properties of their own; the version string of `launchdarkly-js-sdk-common` was never meant to be exposed to applications.
8
+
9
+ ## [4.0.1] - 2022-01-21
10
+ ### Changed:
11
+ - This package is now published as a regular Node module. Previously, it was published as minified bundles created by Rollup. There was no need for this since Rollup is only needed for web code, and the `js-client-sdk` build already runs Rollup to embed the `js-sdk-common` code. Using Rollup caused the platform-dependent behavior of `uuid` to fail because the code for only one platform (browser or Node) was embedded.
12
+
13
+ ## [4.0.0] - 2022-01-14
14
+ ### Changed:
15
+ - Updated `uuid` package to 8.x.
16
+ - In TypeScript, the property `LDEvaluationDetail.reason` is now nullable, which correctly reflects the fact that evaluation reasons may not always be available.
17
+
18
+ ### Removed:
19
+ - Removed the type `NonNullableLDEvaluationReason`, which was a side effect of the `LDEvaluationDetail.reason` being incorrectly defined before.
20
+ - Removed all types, properties, and functions that were deprecated as of the last 3.x release.
21
+
5
22
  ## [3.5.0] - 2022-01-14
6
23
  ### Added:
7
24
  - New configurable logger factory `commonBasicLogger` and `BasicLoggerOptions`. The `commonBasicLogger` method is not intended to be exported directly in the SDKs, but wrapped to provide platform-specific behavior.
@@ -0,0 +1,45 @@
1
+ # Contributing to This Project
2
+
3
+ The `launchdarkly-js-sdk-common` package provides core implementation components for several LaunchDarkly SDKs.
4
+
5
+ ## Submitting bug reports and feature requests
6
+
7
+ Bug reports and feature requests, unless they are very specifically related to a piece of code in this project, should be filed in the individual SDK repositories instead. If you do have an issue specifically for this repository, the LaunchDarkly SDK team monitors the [issue tracker](https://github.com/launchdarkly/js-sdk-common/issues) and will respond to all newly filed issues within two business days.
8
+
9
+ ## Submitting pull requests
10
+
11
+ We encourage pull requests and other contributions from the community. Before submitting pull requests, ensure that all temporary or unintended code is removed. Don't worry about adding reviewers to the pull request; the LaunchDarkly SDK team will add themselves. The SDK team will acknowledge all pull requests within two business days.
12
+
13
+ ## Build instructions
14
+
15
+ ### Prerequisites
16
+
17
+ The project uses `npm`, which is bundled in all supported versions of Node.
18
+
19
+ ### Setup
20
+
21
+ To install project dependencies, from the project root directory:
22
+
23
+ ```
24
+ npm install
25
+ ```
26
+
27
+ ### Testing
28
+
29
+ To run all unit tests:
30
+
31
+ ```
32
+ npm test
33
+ ```
34
+
35
+ To verify that the TypeScript declarations compile correctly (this involves compiling the file `test-types.ts`, so if you have changed any types or interfaces, you will want to update that code):
36
+
37
+ ```
38
+ npm run check-typescript
39
+ ```
40
+
41
+ ### Coding guidelines
42
+
43
+ This code is shared between several SDK projects: `js-client-sdk` which runs in browsers, `node-client-sdk` which runs in Node.js, and `electron-client-sdk` which uses it both in a Node environment and in a browser environment.
44
+
45
+ Therefore, it should not have any JavaScript usages that work _only_ in a browser or _only_ in Node.js. All such things, if they depend on the runtime environment, must be accessed indirectly via the "platform" abstraction, where each SDK provides its own platform-specific callbacks for the `js-sdk-common` code to use. Or, if it's just a question of JavaScript syntax usages, use whatever will work in both browsers and Node (for instance, use only `require` and `module.exports`, not ES6 imports).
@@ -0,0 +1,18 @@
1
+ module.exports = {
2
+ presets: [
3
+ [
4
+ '@babel/env',
5
+ {
6
+ targets: ["last 2 versions", "ie >= 10"],
7
+ },
8
+ ],
9
+ ],
10
+ env: {
11
+ test: {
12
+ plugins: [
13
+ '@babel/plugin-transform-regenerator',
14
+ '@babel/plugin-transform-runtime',
15
+ ],
16
+ },
17
+ },
18
+ };
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ out: '/tmp/project-releaser/project/docs/build/html',
3
+ exclude: [
4
+ '**/node_modules/**',
5
+ 'test-types.ts'
6
+ ],
7
+ name: "LaunchDarkly Javascript SDK Core Components (4.0.2)",
8
+ readme: 'none', // don't add a home page with a copy of README.md
9
+ entryPoints: "/tmp/project-releaser/project/typings.d.ts",
10
+ entryPointStrategy: "expand"
11
+ };
package/jest.config.js ADDED
@@ -0,0 +1,12 @@
1
+ const version = process.env.npm_package_version;
2
+
3
+ module.exports = {
4
+ automock: false,
5
+ resetModules: true,
6
+ rootDir: 'src',
7
+ setupFiles: ['./jest.setup.js'],
8
+ testMatch: ['**/__tests__/**/*-test.js'],
9
+ transform: {
10
+ '^.+\\.js$': 'babel-jest',
11
+ },
12
+ };
package/package.json CHANGED
@@ -1,23 +1,11 @@
1
1
  {
2
2
  "name": "launchdarkly-js-sdk-common",
3
- "version": "3.5.0",
3
+ "version": "4.0.3",
4
4
  "description": "LaunchDarkly SDK for JavaScript - common code",
5
5
  "author": "LaunchDarkly <team@launchdarkly.com>",
6
6
  "license": "Apache-2.0",
7
- "files": [
8
- "ldclient-common.cjs.js",
9
- "ldclient-common.cjs.js.map",
10
- "ldclient-common.es.js",
11
- "ldclient-common.es.js.map",
12
- "ldclient-common.min.js",
13
- "ldclient-common.min.js.map",
14
- "typings.d.ts"
15
- ],
16
7
  "types": "./typings.d.ts",
17
- "main": "dist/ldclient-common.cjs.js",
18
- "module": "dist/ldclient-common.es.js",
19
- "unpkg": "dist/ldclient-common.min.js",
20
- "jsdelivr": "dist/ldclient-common.min.js",
8
+ "main": "src/index.js",
21
9
  "scripts": {
22
10
  "lint": "eslint --format 'node_modules/eslint-formatter-pretty' --ignore-path .eslintignore",
23
11
  "lint:all": "eslint --format 'node_modules/eslint-formatter-pretty' --ignore-path .eslintignore src",
@@ -27,14 +15,8 @@
27
15
  "format:test": "npm run format:test:md && npm run format:test:js",
28
16
  "format:test:md": "prettier --parser markdown --ignore-path .prettierignore --list-different '*.md'",
29
17
  "format:test:js": "prettier --ignore-path .prettierignore --list-different 'src/**/*.js'",
30
- "build": "cross-env NODE_ENV=development rollup -c rollup.config.js",
31
- "build:min": "cross-env NODE_ENV=production rollup -c rollup.config.js",
32
18
  "test": "cross-env NODE_ENV=test jest",
33
- "test:junit": "cross-env NODE_ENV=test jest --testResultsProcessor jest-junit",
34
- "check-typescript": "node_modules/typescript/bin/tsc",
35
- "clean": "rimraf dist/**",
36
- "prepublishOnly": "npm run build:min",
37
- "prepare": "npm run build"
19
+ "check-typescript": "node_modules/typescript/bin/tsc"
38
20
  },
39
21
  "devDependencies": {
40
22
  "@babel/cli": "^7.8.4",
@@ -43,7 +25,6 @@
43
25
  "@babel/plugin-transform-runtime": "^7.6.2",
44
26
  "@babel/preset-env": "^7.6.3",
45
27
  "@babel/runtime": "7.6.3",
46
- "@rollup/plugin-node-resolve": "^6.0.0",
47
28
  "@rollup/plugin-replace": "^2.2.0",
48
29
  "babel-eslint": "^10.1.0",
49
30
  "babel-jest": "^25.1.0",
@@ -59,21 +40,12 @@
59
40
  "launchdarkly-js-test-helpers": "1.1.0",
60
41
  "prettier": "1.11.1",
61
42
  "readline-sync": "^1.4.9",
62
- "rimraf": "^2.6.2",
63
- "rollup": "^1.26.0",
64
- "rollup-plugin-babel": "^4.3.3",
65
- "rollup-plugin-commonjs": "^10.1.0",
66
- "rollup-plugin-filesize": "^6.2.1",
67
- "rollup-plugin-terser": "5.2.0",
68
- "rollup-plugin-uglify": "6.0.4",
69
- "semver": "^5.5.0",
70
- "semver-compare": "^1.0.0",
71
43
  "typescript": "~4.4.4"
72
44
  },
73
45
  "dependencies": {
74
46
  "base64-js": "^1.3.0",
75
47
  "fast-deep-equal": "^2.0.1",
76
- "uuid": "^3.3.2"
48
+ "uuid": "^8.0.0"
77
49
  },
78
50
  "repository": {
79
51
  "type": "git",
@@ -0,0 +1,76 @@
1
+ #!/bin/bash
2
+
3
+ # This script processes the output of "npm audit" to make it more useful, as follows:
4
+ # - For each flagged vulnerability, it looks at the "path" field and extracts both the flagged
5
+ # package (the last element in the path) and the topmost dependency that led to it (the first
6
+ # element in the path).
7
+ # - It sorts these and eliminates duplicates.
8
+ # - It then compares each of the topmost dependencies to package.json to see if it is from
9
+ # "dependencies", "peerDependencies", or "devDependencies". If it is either of the first two
10
+ # then this is a real runtime vulnerability, and must be fixed by updating the topmost
11
+ # dependency. If it is from devDependencies, then it can be safely fixed with "npm audit fix".
12
+
13
+ set -e
14
+
15
+ function readPackages() {
16
+ inCategory=$1
17
+ jq -r ".${inCategory} | keys | .[]" package.json 2>/dev/null || true
18
+ }
19
+
20
+ function isInList() {
21
+ item=$1
22
+ shift
23
+ for x in $@; do
24
+ if [ "$item" == "$x" ]; then
25
+ true
26
+ return
27
+ fi
28
+ done
29
+ false
30
+ }
31
+
32
+ dependencies=$(readPackages dependencies)
33
+ devDependencies=$(readPackages devDependencies)
34
+ peerDependencies=$(readPackages peerDependencies)
35
+
36
+ function processItems() {
37
+ flaggedRuntime=0
38
+ flaggedDev=0
39
+ while read -r badPackage topLevelDep; do
40
+ echo -n "flagged package \"$badPackage\", referenced via \"$topLevelDep\" "
41
+ for category in dependencies peerDependencies devDependencies; do
42
+ if isInList $topLevelDep ${!category}; then
43
+ if [ "$category" == "devDependencies" ]; then
44
+ echo "-- from \"$category\""
45
+ flaggedDev=1
46
+ else
47
+ echo "-- from \"$category\" (RUNTIME) ***"
48
+ flaggedRuntime=1
49
+ fi
50
+ break
51
+ fi
52
+ done
53
+ done
54
+ echo
55
+ if [ "$flaggedRuntime" == "1" ]; then
56
+ echo "*** At least one runtime dependency was flagged. These must be fixed by updating package.json."
57
+ echo "Do not use 'npm audit fix'."
58
+ exit 1 # return an error, causing the build to fail
59
+ elif [ "$flaggedDev" == "1" ]; then
60
+ echo "Only development dependencies were flagged. You may safely run 'npm audit fix', which will"
61
+ echo "fix these by adding overrides to package-lock.json."
62
+ else
63
+ echo "Congratulations! No dependencies were flagged by 'npm audit'."
64
+ fi
65
+ }
66
+
67
+ echo "Running npm audit..."
68
+ echo
69
+
70
+ npm audit --json \
71
+ | grep '"path":' \
72
+ | sort | uniq \
73
+ | sed -n -e 's#.*"path": "\([^"]*\)".*#\1#p' \
74
+ | awk -F '>' '{ print $NF,$1 }' \
75
+ | sort | uniq \
76
+ | processItems
@@ -0,0 +1,60 @@
1
+ function EventEmitter(logger) {
2
+ const emitter = {};
3
+ const events = {};
4
+
5
+ const listeningTo = event => !!events[event];
6
+
7
+ emitter.on = function(event, handler, context) {
8
+ events[event] = events[event] || [];
9
+ events[event] = events[event].concat({
10
+ handler: handler,
11
+ context: context,
12
+ });
13
+ };
14
+
15
+ emitter.off = function(event, handler, context) {
16
+ if (!events[event]) {
17
+ return;
18
+ }
19
+ for (let i = 0; i < events[event].length; i++) {
20
+ if (events[event][i].handler === handler && events[event][i].context === context) {
21
+ events[event] = events[event].slice(0, i).concat(events[event].slice(i + 1));
22
+ }
23
+ }
24
+ };
25
+
26
+ emitter.emit = function(event) {
27
+ if (!events[event]) {
28
+ return;
29
+ }
30
+ // Copy the list of handlers before iterating, in case any handler adds or removes another handler.
31
+ // Any such changes should not affect what we do here-- we want to notify every handler that existed
32
+ // at the moment that the event was fired.
33
+ const copiedHandlers = events[event].slice(0);
34
+ for (let i = 0; i < copiedHandlers.length; i++) {
35
+ copiedHandlers[i].handler.apply(copiedHandlers[i].context, Array.prototype.slice.call(arguments, 1));
36
+ }
37
+ };
38
+
39
+ emitter.getEvents = function() {
40
+ return Object.keys(events);
41
+ };
42
+
43
+ emitter.getEventListenerCount = function(event) {
44
+ return events[event] ? events[event].length : 0;
45
+ };
46
+
47
+ emitter.maybeReportError = function(error) {
48
+ if (!error) {
49
+ return;
50
+ }
51
+ if (listeningTo('error')) {
52
+ this.emit('error', error);
53
+ } else {
54
+ (logger || console).error(error.message);
55
+ }
56
+ };
57
+ return emitter;
58
+ }
59
+
60
+ module.exports = EventEmitter;