From 127ea7636e02860c848f17b3cf2431cfa787db9d Mon Sep 17 00:00:00 2001 From: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com> Date: Tue, 4 Feb 2025 14:42:10 +0100 Subject: [PATCH] fix: drop ts type inference for event source (#706) fix error with dependency types and add test to catch install issues in the future closes #705 --- .github/workflows/build-and-test.yaml | 15 +++++++++++++++ .gitignore | 3 +++ package.json | 2 +- scripts/test-package/run.sh | 25 +++++++++++++++++++++++++ scripts/test-package/test-package.json | 19 +++++++++++++++++++ scripts/test-package/test-tsconfig.json | 19 +++++++++++++++++++ src/event-source.js | 3 +++ src/metrics.ts | 2 +- src/repository/index.ts | 5 ++--- src/test/repository.test.ts | 5 +++-- src/unleash.ts | 3 +-- tsconfig.json | 4 +++- yarn.lock | 15 +++++++++++---- 13 files changed, 106 insertions(+), 14 deletions(-) create mode 100755 scripts/test-package/run.sh create mode 100644 scripts/test-package/test-package.json create mode 100644 scripts/test-package/test-tsconfig.json create mode 100644 src/event-source.js diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml index 827e39ce..7743101e 100644 --- a/.github/workflows/build-and-test.yaml +++ b/.github/workflows/build-and-test.yaml @@ -46,3 +46,18 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + test-as-dependency: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version: 20.x + cache: yarn + - name: Yarn + run: yarn + - name: Test install in other package + run: ./scripts/test-package/run.sh diff --git a/.gitignore b/.gitignore index 5ac8ca3b..82e41ed5 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ build/Release # typescript lives in src, output in lib lib/ .vscode + +# test files +/test-package diff --git a/package.json b/package.json index b2fa2c1c..d683b2b3 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "@types/make-fetch-happen": "^10.0.4", "@types/murmurhash3js": "^3.0.3", "@types/nock": "^11.1.0", - "@types/node": "^20.2.5", + "@types/node": "^20.17.17", "@types/proxy-from-env": "^1.0.4", "@types/semver": "^7.5.0", "@types/sinon": "^17.0.0", diff --git a/scripts/test-package/run.sh b/scripts/test-package/run.sh new file mode 100755 index 00000000..2445d785 --- /dev/null +++ b/scripts/test-package/run.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e + +echo -e "\nTesting that the package can be installed in another project and compiled with TypeScript without errors" + +TEST_DIR="test-package" +mkdir "$TEST_DIR" + +cp scripts/test-package/test-tsconfig.json "$TEST_DIR/tsconfig.json" +cp scripts/test-package/test-package.json "$TEST_DIR/package.json" +cd "$TEST_DIR" +npm install --install-links +mkdir src +echo -e "import { Unleash } from 'unleash-client';\nvoid Unleash;\nconsole.log('Hello world');" > src/index.ts +./node_modules/.bin/tsc -b tsconfig.json + +if [ "$(node . 2>&1)" = "Hello world" ]; then + echo "Output is correct" + (cd .. && rm -rf "$TEST_DIR") +else + echo "Output is incorrect" >&2 + echo $(node . 2>&1) + (cd .. && rm -rf "$TEST_DIR") + exit 1 +fi diff --git a/scripts/test-package/test-package.json b/scripts/test-package/test-package.json new file mode 100644 index 00000000..d9295dfb --- /dev/null +++ b/scripts/test-package/test-package.json @@ -0,0 +1,19 @@ +{ + "name": "test", + "version": "1.0.0", + "main": "lib/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "tsc" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "devDependencies": { + "typescript": "^5.7.3" + }, + "dependencies": { + "unleash-client": "file:.." + } +} diff --git a/scripts/test-package/test-tsconfig.json b/scripts/test-package/test-tsconfig.json new file mode 100644 index 00000000..d38c022c --- /dev/null +++ b/scripts/test-package/test-tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "declaration": true, + "inlineSourceMap": true, + "pretty": true, + "noImplicitAny": true, + "allowJs": false, + "resolveJsonModule": true, + "composite": true, + "outDir": "./lib", + "rootDir": "./src" + }, + "include": ["src/**/*"] +} diff --git a/src/event-source.js b/src/event-source.js new file mode 100644 index 00000000..df4999a4 --- /dev/null +++ b/src/event-source.js @@ -0,0 +1,3 @@ +import { EventSource as moduleToPatch } from 'launchdarkly-eventsource'; + +export const EventSource = moduleToPatch; // Re-export from .js file, because the original module doesn't have types diff --git a/src/metrics.ts b/src/metrics.ts index 9030ba52..acfd2ff5 100644 --- a/src/metrics.ts +++ b/src/metrics.ts @@ -97,7 +97,7 @@ export default class Metrics extends EventEmitter { private url: string; - private timer: NodeJS.Timer | undefined; + private timer: NodeJS.Timeout | undefined; private started: Date; diff --git a/src/repository/index.ts b/src/repository/index.ts index ff7d6f75..972c1889 100644 --- a/src/repository/index.ts +++ b/src/repository/index.ts @@ -13,8 +13,7 @@ import { Segment, StrategyTransportInterface, } from '../strategy/strategy'; -// @ts-expect-error -import { EventSource } from 'launchdarkly-eventsource'; +import type { EventSource } from '../event-source'; export const SUPPORTED_SPEC_VERSION = '4.3.0'; @@ -50,7 +49,7 @@ interface FeatureToggleData { } export default class Repository extends EventEmitter implements EventEmitter { - private timer: NodeJS.Timer | undefined; + private timer: NodeJS.Timeout | undefined; private url: string; diff --git a/src/test/repository.test.ts b/src/test/repository.test.ts index e0182db0..306f4d0d 100644 --- a/src/test/repository.test.ts +++ b/src/test/repository.test.ts @@ -1413,7 +1413,7 @@ test('Streaming', async (t) => { }; setup(url, [{ ...feature, name: 'initialFetch' }]); const storageProvider: StorageProvider = new InMemStorageProvider(); - const eventSource = { + const eventSource: any = { eventEmitter: new EventEmitter(), listeners: new Set(), addEventListener(eventName: string, handler: () => void) { @@ -1421,7 +1421,7 @@ test('Streaming', async (t) => { eventSource.eventEmitter.on(eventName, handler); }, close() { - eventSource.listeners.forEach((eventName) => { + eventSource.listeners.forEach((eventName: string) => { eventSource.eventEmitter.removeAllListeners(eventName); }); }, @@ -1429,6 +1429,7 @@ test('Streaming', async (t) => { eventSource.eventEmitter.emit(eventName, data); }, }; + const repo = new Repository({ url, appName, diff --git a/src/unleash.ts b/src/unleash.ts index c970a04f..42dcafdf 100644 --- a/src/unleash.ts +++ b/src/unleash.ts @@ -19,8 +19,7 @@ import { ImpressionEvent, UnleashEvents } from './events'; import { UnleashConfig } from './unleash-config'; import FileStorageProvider from './repository/storage-provider-file'; import { resolveUrl } from './url-utils'; -// @ts-expect-error -import { EventSource } from 'launchdarkly-eventsource'; +import { EventSource } from './event-source'; import { buildHeaders } from './request'; import { uuidv4 } from './uuidv4'; export { Strategy, UnleashEvents, UnleashConfig }; diff --git a/tsconfig.json b/tsconfig.json index 84574deb..9a724197 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,9 @@ "declarationMap": true, "resolveJsonModule": true, "esModuleInterop": false, + "allowJs": true, "skipLibCheck": false }, - "exclude": ["examples/", "lib/", "node_modules/"] + "exclude": ["examples/", "lib/", "node_modules/"], + "include": ["src/**/*.ts", "src/**/*.js"] } diff --git a/yarn.lock b/yarn.lock index 4fc600af..285801ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -731,10 +731,12 @@ dependencies: undici-types "~5.26.4" -"@types/node@^20.2.5": - version "20.4.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.0.tgz#01d637d1891e419bc85763b46f42809cd2d5addb" - integrity sha512-jfT7iTf/4kOQ9S7CHV9BIyRaQqHu67mOjsIQBC3BKZvzvUB6zLxEwJ6sBE3ozcvP8kF6Uk5PXN0Q+c0dfhGX0g== +"@types/node@^20.17.17": + version "20.17.17" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.17.tgz#5cea2af2e271313742c14f418eaf5dcfa8ae2e3a" + integrity sha512-/WndGO4kIfMicEQLTi/mDANUu/iVUhT7KboZPdEqqHQ4aTS+3qT3U5gIqWDFV+XouorjfgGqvKILJeHhuQgFYg== + dependencies: + undici-types "~6.19.2" "@types/normalize-package-data@^2.4.0": version "2.4.4" @@ -5105,6 +5107,11 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + unique-filename@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea"