From 99aecaafa553b50521d9f56db32233928114c70d Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Mon, 26 Aug 2024 11:14:53 -0500 Subject: [PATCH 1/5] deps: update aegir and typescript --- package.json | 4 ++-- test/configuration.spec.ts | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 0c3b160..f2cdf46 100644 --- a/package.json +++ b/package.json @@ -192,7 +192,7 @@ "@types/winston": "^2.4.4", "@typescript-eslint/eslint-plugin": "^5.22.0", "@typescript-eslint/parser": "^5.22.0", - "aegir": "^37.0.15", + "aegir": "^44.1.1", "check-aegir-project": "^1.0.3", "cors": "^2.8.5", "cp-cli": "^2.0.0", @@ -207,7 +207,7 @@ "regenerator-runtime": "^0.13.9", "ts-node": "^10.7.0", "tsc-silent": "^1.2.1", - "typescript": "^4.6.4", + "typescript": "^5.5.4", "winston": "^3.6.0" } } diff --git a/test/configuration.spec.ts b/test/configuration.spec.ts index 084f48d..37241da 100644 --- a/test/configuration.spec.ts +++ b/test/configuration.spec.ts @@ -1,13 +1,11 @@ /* eslint-env browser, node, mocha */ import { expect } from 'aegir/chai' -import { Configuration, ConfigurationParameters } from '../src/index.js' +import { Configuration, type ConfigurationParameters } from '../src/index.js' -// export default async (setup: () => Promise) => { describe('Configuration', () => { it('Can be instantiated', () => { const configuration: ConfigurationParameters = {} expect(() => new Configuration(configuration)).not.to.throw() }) }) -// } From 410fda9129396f7f91ecbe7d26c340fbf31b7968 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Mon, 26 Aug 2024 16:00:46 -0500 Subject: [PATCH 2/5] feat!: use native fetch, update all deps --- .aegir.js | 29 +++++++++++--- .eslintrc.json | 10 ++--- .gitignore | 1 + .vscode/settings.json | 13 ------- README.md | 2 +- fixtures.js | 1 - package.json | 52 +++++++++---------------- src/index.ts | 8 ++-- test/MockServer.ts | 32 +++++++-------- test/MockServerController.ts | 18 +++++---- test/client.spec.ts | 5 --- test/configuration.spec.ts | 1 - test/logger.ts | 1 - test/node-tests/mockServerController.ts | 16 +++----- tsconfig.json | 2 +- 15 files changed, 83 insertions(+), 108 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.aegir.js b/.aegir.js index 6f93464..0d30701 100644 --- a/.aegir.js +++ b/.aegir.js @@ -1,14 +1,32 @@ -import { MockServerController } from './dist/test/MockServerController.js' /** @type {import('aegir').PartialOptions} */ -const config = { +export default { + typescript: true, + dependencyCheck: { + ignore: [ + '@swc/cli', + '@swc/core', + '@swc/helpers', + 'cors', + 'dotenvrc', + 'express', + 'express-promise-router', + 'mock-ipfs-pinning-service', + 'portscanner', + 'regenerator-runtime', + 'winston', + ] + }, docs: { publish: true, entryPoint: './' }, build: { + types: true, config: { - platform: 'node' + format: 'esm', + platform: 'node', + external: ['electron', '#ansi-styles', 'yargs/yargs', '#supports-color'] }, bundlesizeMax: '44KB' }, @@ -17,6 +35,7 @@ const config = { progress: true, cov: false, async before () { + const { MockServerController } = await import('./dist/test/MockServerController.js') return { env: { MOCK_PINNING_SERVER_SECRET: 'ci', @@ -26,12 +45,10 @@ const config = { }, /** * @param {import('aegir').GlobalOptions & import('aegir').TestOptions} _ - * @param { {controller: MockServerController} } beforeResult + * @param { { controller: import('./test/MockServerController.js').MockServerController } } beforeResult */ async after (_, {controller}) { await controller.shutdown() } } } - -export default config diff --git a/.eslintrc.json b/.eslintrc.json index 66cf247..4b37648 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,8 +1,10 @@ { "root": true, - "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint", "import"], "extends": ["ipfs"], + "parserOptions": { + "project": true, + "sourceType": "module" + }, "overrides": [ { "parserOptions": { @@ -13,7 +15,6 @@ "./types/**/*.ts" ], "rules": { - "@typescript-eslint/strict-boolean-expressions": "off" } }, { @@ -32,8 +33,7 @@ "semi": "off", "indent": "off", "no-unused-vars": "off", - "no-undef": "off", - "@typescript-eslint/strict-boolean-expressions": "off" + "no-undef": "off" } } ], diff --git a/.gitignore b/.gitignore index f9db324..7acd789 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ logs .tsbuildinfo* # generated by nektos/act cli workflow +.coverage diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index c3e8b16..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "editor.tabSize": 2, - "typescript.format.semicolons": "remove", - "javascript.format.semicolons": "remove", - "typescript.suggest.includeAutomaticOptionalChainCompletions": true, - "cSpell.words": [ - "openapi", - "openapitools", - "postgen", - "posttest", - "pregen" - ], -} diff --git a/README.md b/README.md index 015b491..048cc54 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ import type { PinsGetRequest, PinResults } from '@ipfs-shipyard/pinning-service- const config = new Configuration({ endpointUrl, // the URI for your pinning provider, e.g. `http://localhost:3000` accessToken, // the secret token/key given to you by your pinning provider - // fetchApi: fetch, // You can pass your own fetchApi implementation, but we use fetch-ponyfill by default. + // fetchApi: fetch, // You can pass your own fetchApi implementation, but we use NodeJS fetch by default. }) const client = new RemotePinningServiceClient(config) diff --git a/fixtures.js b/fixtures.js index 2a2d4ec..9fffe54 100644 --- a/fixtures.js +++ b/fixtures.js @@ -1,4 +1,3 @@ - // @ts-check // export async function mochaGlobalSetup () { diff --git a/package.json b/package.json index f2cdf46..fe43124 100644 --- a/package.json +++ b/package.json @@ -58,12 +58,6 @@ "require": "./dist/dist.generated/apis" } }, - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "sourceType": "module" - } - }, "release": { "branches": [ "main" @@ -147,7 +141,7 @@ }, "scripts": { "ci:test": "run-s test:*", - "dep-check": "aegir dep-check dist/**/*.js -- --ignore @openapitools/openapi-generator-cli @typescript-eslint/eslint-plugin @typescript-eslint/parser", + "dep-check": "aegir dep-check dist/**/*.js", "fix": "run-s fix:*", "fix:lint": "aegir lint --fix", "release": "aegir release", @@ -165,7 +159,7 @@ "test:firefox": "aegir test -t browser -- --browser firefox", "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", "test:electron-main": "aegir test -t electron-main", - "posttest": "npx nyc report", + "posttest": "npx nyc report || echo 'coverage report temporarily broken'", "pregen": "openapi-generator-cli validate -i https://raw.githubusercontent.com/ipfs/pinning-services-api-spec/v1.0.0/ipfs-pinning-service.yaml", "gen": "run-p gen:fetch", "postgen": "run-s build:generated", @@ -173,41 +167,31 @@ "gen:node": "openapi-generator-cli generate --generator-key node", "gen:ts": "openapi-generator-cli generate --generator-key ts", "clean": "aegir clean", + "reset": "aegir clean node_modules dist dist.generated", "lint": "aegir lint" }, - "dependencies": { - "fetch-ponyfill": "^7.1.0" - }, "devDependencies": { - "@openapitools/openapi-generator-cli": "^2.4.26", - "@swc/cli": "^0.1.55", - "@swc/core": "^1.2.157", - "@swc/helpers": "^0.3.3", - "@types/cors": "^2.8.12", - "@types/eslint": "^8.4.2", - "@types/express": "^4.17.13", - "@types/mocha": "^10.0.0", - "@types/node": "^18.8.2", - "@types/portscanner": "^2.1.1", + "@openapitools/openapi-generator-cli": "^2.13.5", + "@swc/cli": "^0.4.0", + "@swc/core": "^1.7.18", + "@swc/helpers": "^0.5.12", + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/mocha": "^10.0.7", + "@types/node": "^22.5.0", + "@types/portscanner": "^2.1.4", "@types/winston": "^2.4.4", - "@typescript-eslint/eslint-plugin": "^5.22.0", - "@typescript-eslint/parser": "^5.22.0", - "aegir": "^44.1.1", - "check-aegir-project": "^1.0.3", + "aegir": "^43.0.3", "cors": "^2.8.5", "cp-cli": "^2.0.0", "dotenvrc": "^1.0.1", - "eslint": "^8.14.0", - "eslint-plugin-import": "^2.26.0", - "express": "^4.17.3", + "express": "^4.19.2", "express-promise-router": "^4.1.1", - "mock-ipfs-pinning-service": "^0.4.0", + "mock-ipfs-pinning-service": "^0.4.2", "npm-run-all": "^4.1.5", "portscanner": "^2.2.0", - "regenerator-runtime": "^0.13.9", - "ts-node": "^10.7.0", - "tsc-silent": "^1.2.1", - "typescript": "^5.5.4", - "winston": "^3.6.0" + "regenerator-runtime": "^0.14.1", + "tsc-silent": "^1.2.2", + "winston": "^3.14.2" } } diff --git a/src/index.ts b/src/index.ts index 3896864..6a61823 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,8 @@ -import fetchPonyfill from 'fetch-ponyfill' - +import { PinsApi as RemotePinningServiceClient } from '../dist.generated/apis/index.js' import { Configuration as GeneratedConfiguration } from '../dist.generated/index.js' import type { ConfigurationParameters as GeneratedConfigurationParameters } from '../dist.generated/index.js' -import { PinsApi as RemotePinningServiceClient } from '../dist.generated/apis/index.js' -interface ConfigurationParameters extends Omit{ +interface ConfigurationParameters extends Omit { endpointUrl?: string } class Configuration extends GeneratedConfiguration { @@ -14,7 +12,7 @@ class Configuration extends GeneratedConfiguration { * Prevent the need for everyone to have to override the fetch API... */ if (options.fetchApi == null) { - finalOptions.fetchApi = fetchPonyfill().fetch + finalOptions.fetchApi = fetch } // @see https://github.com/ipfs-shipyard/js-pinning-service-http-client/issues/3 diff --git a/test/MockServer.ts b/test/MockServer.ts index 8d3030f..5d37be2 100644 --- a/test/MockServer.ts +++ b/test/MockServer.ts @@ -1,14 +1,12 @@ -import type { Application } from 'express' -import type { Server } from 'http' -import portscanner from 'portscanner' import cors from 'cors' - import { setup } from 'mock-ipfs-pinning-service' - +import portscanner from 'portscanner' import { logger } from './logger.js' +import type { Application } from 'express' +import type { Server } from 'http' try { - import('dotenvrc') + await import('dotenvrc') } catch (err) { // no dotenvrc.. that's okay // eslint-disable-next-line no-console @@ -23,7 +21,7 @@ export class MockServer { public basePath: string = '' - constructor (private readonly config: Parameters[0] = { token: process.env.MOCK_PINNING_SERVER_SECRET }) { + constructor (private readonly config: Parameters[0] = { token: process.env.MOCK_PINNING_SERVER_SECRET }) { process.on('uncaughtException', MockServer.onEADDRINUSE) } @@ -84,14 +82,16 @@ export class MockServer { * Ensure the port set for this instance is not already in use by another MockServer */ private async getAvailablePort (): Promise { - return await new Promise((resolve, reject) => portscanner.findAPortNotInUse(3000, 3099, '127.0.0.1', (error, port) => { - if (error != null) { - return reject(error) - } - this.port = port.toString() - this.setBasePath() - resolve(this.port) - })) + return new Promise((resolve, reject) => { + portscanner.findAPortNotInUse(3000, 3099, '127.0.0.1', (error, port) => { + if (error != null) { + reject(error); return + } + this.port = port.toString() + this.setBasePath() + resolve(this.port) + }) + }) } private async service (): Promise { @@ -133,7 +133,7 @@ export class MockServer { }) } - private static onEADDRINUSE (err: Error & { code: string }) { + private static onEADDRINUSE (err: Error & { code: string }): void { if (err.code === 'EADDRINUSE') { logger.error('Unexpected conflict with port usage') } else { diff --git a/test/MockServerController.ts b/test/MockServerController.ts index 11c320f..298bc7a 100644 --- a/test/MockServerController.ts +++ b/test/MockServerController.ts @@ -1,9 +1,9 @@ +import cors from 'cors' import express from 'express' import Router from 'express-promise-router' -import cors from 'cors' - import { MockServer } from './MockServer.js' import { logger } from './logger.js' +import type { Server } from 'http' /** * MockServerController stands up a server on port 3000 @@ -14,11 +14,12 @@ class MockServerController { private readonly router = Router() private readonly port = 3000 - server: import('http').Server + server: Server constructor () { this.shutdown.bind(this) this.shutdownSync.bind(this) - this.router.get<'/start', {port?: string}>('/start', async (req, res, next) => { // eslint-disable-line @typescript-eslint/no-misused-promises + // eslint-disable-next-line @typescript-eslint/no-misused-promises + this.router.get<'/start', { port?: string }>('/start', async (req, res, next) => { logger.debug('MockServerController: /start GET request received') const { port } = req.params @@ -44,7 +45,8 @@ class MockServerController { /** * A client will request to shut down it's mockServer by port, which it should have received upon calling '/start' */ - this.router.get<'/stop/:port', {port: string}>('/stop/:port', async (req, res, next) => { // eslint-disable-line @typescript-eslint/no-misused-promises + // eslint-disable-next-line @typescript-eslint/no-misused-promises + this.router.get<'/stop/:port', { port: string }>('/stop/:port', async (req, res, next) => { const { port } = req.params logger.debug(`MockServerController: /stop/${port.toString()} GET request received`) @@ -82,13 +84,13 @@ class MockServerController { }) } - private shutdownSync () { + private shutdownSync (): void { this.shutdown().catch((err) => { logger.error(err) }) } - async shutdown () { + async shutdown (): Promise { // To prevent duplicated cleanup, remove the process listeners on server close. process.off('beforeExit', this.shutdownSync) process.off('SIGTERM', this.shutdownSync) @@ -115,7 +117,7 @@ class MockServerController { } } - private async startIpfsPinningServer (port?: string) { + private async startIpfsPinningServer (port?: string): Promise { const mockServer = new MockServer({ token: process.env.MOCK_PINNING_SERVER_SECRET }) diff --git a/test/client.spec.ts b/test/client.spec.ts index 7185917..28149f4 100644 --- a/test/client.spec.ts +++ b/test/client.spec.ts @@ -1,13 +1,8 @@ /* eslint-env browser, node, mocha */ -import fetchPonyfill from 'fetch-ponyfill' - import { expect } from 'aegir/chai' - import { Configuration, RemotePinningServiceClient, Status } from '../src/index.js' import type { Pin } from '../src/index.js' -const { fetch } = fetchPonyfill() - let Config = new Configuration({ endpointUrl: 'http://127.0.0.1:3000', accessToken: process.env.MOCK_PINNING_SERVER_SECRET diff --git a/test/configuration.spec.ts b/test/configuration.spec.ts index 37241da..d5d984e 100644 --- a/test/configuration.spec.ts +++ b/test/configuration.spec.ts @@ -1,6 +1,5 @@ /* eslint-env browser, node, mocha */ import { expect } from 'aegir/chai' - import { Configuration, type ConfigurationParameters } from '../src/index.js' describe('Configuration', () => { diff --git a/test/logger.ts b/test/logger.ts index ae96199..911dc92 100644 --- a/test/logger.ts +++ b/test/logger.ts @@ -1,5 +1,4 @@ import fs from 'fs' - import winston from 'winston' const { combine, timestamp, printf, colorize, align } = winston.format diff --git a/test/node-tests/mockServerController.ts b/test/node-tests/mockServerController.ts index c8835f4..c1e3c91 100755 --- a/test/node-tests/mockServerController.ts +++ b/test/node-tests/mockServerController.ts @@ -1,12 +1,7 @@ -import fetchPonyfill from 'fetch-ponyfill' - import { expect } from 'aegir/chai' - import { MockServerController } from '../MockServerController.js' -const { fetch } = fetchPonyfill() - -export default async (setup: () => Promise) => { +export default async (setup: () => Promise): Promise => { describe.skip('MockServerController', () => { it('can start and stop without errors', async () => { expect(async () => { @@ -17,14 +12,13 @@ export default async (setup: () => Promise) => { it('Can start multiple mockServers', async () => { const controller = new MockServerController() - const serverConfigs: Array<{basePath: string}> = [] + const serverConfigs: Array<{ basePath: string }> = [] - // eslint-disable-next-line @typescript-eslint/no-unused-vars - for await (const _ of Array(5)) { + await Promise.all(Array(5).fill(0).map(async () => { const response = await fetch('http://localhost:3000/start') serverConfigs.push(await response.json()) - } - // it('Can shutdown those mockServers', async () => { + })) + for await (const config of serverConfigs) { const { basePath } = config const [,, port] = basePath diff --git a/tsconfig.json b/tsconfig.json index 1e50a0d..9f802ff 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,7 @@ "test/**/*.ts", "types/**/*.d.ts", "dist/dist.generated" -, "config" ], + ], "exclude": [ "generated", "dist.test", From b0e93cd8a131ee62308ea913618bd39d382eff35 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Mon, 26 Aug 2024 16:19:54 -0500 Subject: [PATCH 3/5] docs: update instructions for devs --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 048cc54..33f6fd5 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,12 @@ npm install npm run build ``` +### Updating the generated client + +To update the client, you need to `npm run gen` npm script. This will fetch the latest version of the OpenAPI spec and generate the client. However, openapi-generator-cli does not currently generate the client code with proper import syntax. So you must modify the imports in `generated/fetch/**` directly, or just `git checkout -p` to remove the invalid import path changes. + +If you need to modify the generated code's import paths, you will have to run `npm run postgen` manually. + ### Contributing See [CONTRIBUTING.md](CONTRIBUTING.md). From 41b5eaef65ea21a61b483f0fa76567d5bfeebdbc Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Mon, 26 Aug 2024 16:23:03 -0500 Subject: [PATCH 4/5] chore: update to latest aegir --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fe43124..d498739 100644 --- a/package.json +++ b/package.json @@ -181,7 +181,7 @@ "@types/node": "^22.5.0", "@types/portscanner": "^2.1.4", "@types/winston": "^2.4.4", - "aegir": "^43.0.3", + "aegir": "^44.1.1", "cors": "^2.8.5", "cp-cli": "^2.0.0", "dotenvrc": "^1.0.1", From 159b0f8dfcd98b515c7a459dd6b264063b401474 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Mon, 26 Aug 2024 16:24:55 -0500 Subject: [PATCH 5/5] chore: use lts node in github actions --- .github/workflows/js-test-and-release.yml | 38 +++++++++++------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/js-test-and-release.yml b/.github/workflows/js-test-and-release.yml index d7f5324..9ecb884 100644 --- a/.github/workflows/js-test-and-release.yml +++ b/.github/workflows/js-test-and-release.yml @@ -12,8 +12,8 @@ jobs: check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master @@ -27,11 +27,11 @@ jobs: strategy: matrix: os: [windows-latest, ubuntu-latest, macos-latest] - node: [16] + node: [20] fail-fast: true steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} - uses: ipfs/aegir/actions/cache-node-modules@master @@ -46,8 +46,8 @@ jobs: needs: check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master @@ -62,8 +62,8 @@ jobs: needs: check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master @@ -78,8 +78,8 @@ jobs: needs: check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master @@ -94,8 +94,8 @@ jobs: needs: check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master @@ -110,8 +110,8 @@ jobs: needs: check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master @@ -126,8 +126,8 @@ jobs: needs: check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master @@ -143,10 +143,10 @@ jobs: runs-on: ubuntu-latest if: github.event_name == 'push' && github.ref == 'refs/heads/main' # with #262 - 'refs/heads/${{{ github.default_branch }}}' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v4 with: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master