diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 89a5d44..1f85637 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -48,6 +48,16 @@ module.exports = { '@typescript-eslint/consistent-type-imports': 'error', '@typescript-eslint/no-floating-promises': 'error', '@typescript-eslint/no-misused-promises': 'error', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + // TypeScript by default allows params starting with _ + varsIgnorePattern: /^_/.source, + argsIgnorePattern: /^_/.source, + caughtErrorsIgnorePattern: /^_/.source, + destructuredArrayIgnorePattern: /^_/.source, + }, + ], '@typescript-eslint/ban-ts-comment': [ 'error', { diff --git a/cSpell.json b/cSpell.json index 3fabbad..c6cb8b9 100644 --- a/cSpell.json +++ b/cSpell.json @@ -2,6 +2,7 @@ "version": "0.2", "language": "en", "words": [ + "Alois", "Cataa", "colour", "Cookiebot", diff --git a/packages/sdk/CHANGELOG.md b/packages/sdk/CHANGELOG.md index f43ad74..8063089 100644 --- a/packages/sdk/CHANGELOG.md +++ b/packages/sdk/CHANGELOG.md @@ -5,6 +5,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changes + +- `MermaidChart#resetAccessToken()` no longer returns a `Promise`. + ## [0.2.0] - 2024-04-11 ### Added diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 389c28b..a4d12a0 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -14,6 +14,8 @@ "build:code:browser": "esbuild src/index.ts --bundle --minify --outfile=dist/bundle.iife.js", "build:code:node": "esbuild src/index.ts --bundle --platform=node --target=node18.18 --format=esm --packages=external --minify --outfile=dist/index.mjs", "build:types": "tsc -p ./tsconfig.json --emitDeclarationOnly", + "lint": "eslint src/ && prettier --check src/", + "lint:fix": "eslint --fix src/ && prettier --write src/", "prepare": "pnpm run build", "test": "vitest src/", "test:e2e": "vitest --config vitest.config.e2e.ts" @@ -31,7 +33,11 @@ }, "devDependencies": { "@types/node": "^18.18.0", - "@types/uuid": "^9.0.2" + "@types/uuid": "^9.0.2", + "@typescript-eslint/eslint-plugin": "^6.11.0", + "@typescript-eslint/parser": "^6.11.0", + "eslint": "^8.54.0", + "prettier": "^3.0.3" }, "publishConfig": { "access": "public" diff --git a/packages/sdk/src/index.e2e.test.ts b/packages/sdk/src/index.e2e.test.ts index 612f83e..a269881 100644 --- a/packages/sdk/src/index.e2e.test.ts +++ b/packages/sdk/src/index.e2e.test.ts @@ -6,28 +6,32 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import process from 'node:process'; import { AxiosError } from 'axios'; -import { MCDocument } from './types.js'; +import type { MCDocument } from './types.js'; let testProjectId = '316557b3-cb6f-47ed-acf7-fcfb7ce188d5'; let baseURL = new URL('https://test.mermaidchart.com'); let client: MermaidChart; -beforeAll(async() => { +beforeAll(async () => { if (process.env.TEST_MERMAIDCHART_BASE_URL) { try { baseURL = new URL(process.env.TEST_MERMAIDCHART_BASE_URL); } catch (err) { - throw new Error("Invalid URL in environment variable TEST_MERMAIDCHART_BASE_URL", { cause: err}); + throw new Error('Invalid URL in environment variable TEST_MERMAIDCHART_BASE_URL', { + cause: err, + }); } } else { - process.emitWarning(`Missing environment variable TEST_MERMAIDCHART_BASE_URL. Defaulting to ${baseURL.href}.`); + process.emitWarning( + `Missing environment variable TEST_MERMAIDCHART_BASE_URL. Defaulting to ${baseURL.href}.`, + ); } if (!process.env.TEST_MERMAIDCHART_API_TOKEN) { throw new Error( - "Missing required environment variable TEST_MERMAIDCHART_API_TOKEN. " - + `Please go to ${new URL('/app/user/settings', baseURL)} and create one.` + 'Missing required environment variable TEST_MERMAIDCHART_API_TOKEN. ' + + `Please go to ${new URL('/app/user/settings', baseURL)} and create one.`, ); } @@ -44,25 +48,30 @@ beforeAll(async() => { // confirm that testProjectId is valid if (process.env.TEST_MERMAIDCHART_PROJECT_ID) { testProjectId = process.env.TEST_MERMAIDCHART_PROJECT_ID; - if (!projects.find((project) => project.id === testProjectId)) { + if (!projects.some((project) => project.id === testProjectId)) { throw new Error( - `Invalid environment variable TEST_MERMAIDCHART_PROJECT_ID. ` - + `Please go to ${new URL('/app/projects', baseURL)} and create one that you have access to.` + `Invalid environment variable TEST_MERMAIDCHART_PROJECT_ID. ` + + `Please go to ${new URL( + '/app/projects', + baseURL, + )} and create one that you have access to.`, ); } } else { - if (!projects.find((project) => project.id === testProjectId)) { + if (!projects.some((project) => project.id === testProjectId)) { throw new Error( - `Missing environment variable TEST_MERMAIDCHART_PROJECT_ID. ` - + `Please go to ${new URL('/app/projects', baseURL)} and create one.` + `Missing environment variable TEST_MERMAIDCHART_PROJECT_ID. ` + + `Please go to ${new URL('/app/projects', baseURL)} and create one.`, ); } - process.emitWarning(`Missing optional environment variable TEST_MERMAIDCHART_PROJECT_ID. Defaulting to ${testProjectId}`); + process.emitWarning( + `Missing optional environment variable TEST_MERMAIDCHART_PROJECT_ID. Defaulting to ${testProjectId}`, + ); } }); describe('getUser', () => { - it("should get user", async() => { + it('should get user', async () => { const user = await client.getUser(); expect(user).toHaveProperty('emailAddress'); @@ -78,17 +87,19 @@ const documentMatcher = expect.objectContaining({ /** * Cleanup created documents at the end of this test. */ -const documentsToDelete = new Set(); -afterAll(async() => { - await Promise.all(Array.from(documentsToDelete).map(async(document) => { - if (documentsToDelete.delete(document)) { - await client.deleteDocument(document); - } - })); +const documentsToDelete = new Set(); +afterAll(async () => { + await Promise.all( + [...documentsToDelete].map(async (document) => { + if (documentsToDelete.delete(document)) { + await client.deleteDocument(document); + } + }), + ); }); describe('createDocument', () => { - it('should create document in project', async() => { + it('should create document in project', async () => { const existingDocuments = await client.getDocuments(testProjectId); const newDocument = await client.createDocument(testProjectId); @@ -105,7 +116,7 @@ describe('createDocument', () => { }); describe('setDocument', () => { - it('should set document', async() => { + it('should set document', async () => { const newDocument = await client.createDocument(testProjectId); documentsToDelete.add(newDocument.documentID); @@ -115,7 +126,7 @@ describe('setDocument', () => { await client.setDocument({ documentID: newDocument.documentID, projectID: newDocument.projectID, - title: "@mermaidchart/sdk E2E test diagram", + title: '@mermaidchart/sdk E2E test diagram', code, }); @@ -123,25 +134,27 @@ describe('setDocument', () => { documentID: newDocument.documentID, }); expect(updatedDoc).toMatchObject({ - title: "@mermaidchart/sdk E2E test diagram", + title: '@mermaidchart/sdk E2E test diagram', code, }); }); - it('should throw an error on invalid data', async() => { + it('should throw an error on invalid data', async () => { const newDocument = await client.createDocument(testProjectId); documentsToDelete.add(newDocument.documentID); - await expect(client.setDocument({ - documentID: newDocument.documentID, - // @ts-expect-error not setting diagram `projectID` should throw an error - projectID: null, - })).rejects.toThrowError("400"); // should throw HTTP 400 error + await expect( + client.setDocument({ + documentID: newDocument.documentID, + // @ts-expect-error not setting diagram `projectID` should throw an error + projectID: null, + }), + ).rejects.toThrowError('400'); // should throw HTTP 400 error }); }); describe('deleteDocument', () => { - it('should delete document', async() => { + it('should delete document', async () => { const newDocument = await client.createDocument(testProjectId); expect(await client.getDocuments(testProjectId)).toContainEqual(newDocument); @@ -154,8 +167,8 @@ describe('deleteDocument', () => { }); }); -describe("getDocument", () => { - it("should get diagram", async() => { +describe('getDocument', () => { + it('should get diagram', async () => { const newDocument = await client.createDocument(testProjectId); documentsToDelete.add(newDocument.documentID); @@ -176,7 +189,7 @@ describe("getDocument", () => { expect(earliestDocument).toStrictEqual(documentMatcher); }); - it("should throw 404 on unknown document", async() => { + it('should throw 404 on unknown document', async () => { let error: AxiosError | undefined = undefined; try { await client.getDocument({ @@ -190,4 +203,3 @@ describe("getDocument", () => { expect(error?.response?.status).toBe(404); }); }); - diff --git a/packages/sdk/src/index.test.ts b/packages/sdk/src/index.test.ts index 2f39cbb..0030f1d 100644 --- a/packages/sdk/src/index.test.ts +++ b/packages/sdk/src/index.test.ts @@ -1,6 +1,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { MermaidChart } from './index.js'; -import { AuthorizationData } from './types.js'; +import type { AuthorizationData } from './types.js'; import { OAuth2Client } from '@badgateway/oauth2-client'; diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index cb27da1..ca212ea 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -143,7 +143,7 @@ export class MermaidChart { /** * This method is used after authentication to save the access token. * It should be called by the plugins if any update to access token is made outside this lib. - * @param accessToken access token to use for requests + * @param accessToken - access token to use for requests */ public async setAccessToken(accessToken: string): Promise { this.axios.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`; @@ -152,7 +152,7 @@ export class MermaidChart { this.accessToken = accessToken; } - public async resetAccessToken(): Promise { + public resetAccessToken(): void { this.accessToken = undefined; this.axios.defaults.headers.common['Authorization'] = `Bearer none`; } @@ -204,38 +204,40 @@ export class MermaidChart { public async getDocument( document: Pick | Pick, ) { - const {data} = await this.axios.get(URLS.rest.documents.pick(document).self); + const { data } = await this.axios.get(URLS.rest.documents.pick(document).self); return data; } /** * Update the given document. * - * @param document The document to update. + * @param document - The document to update. */ public async setDocument( document: Pick & Partial, ) { - const {data} = await this.axios.put<{result: "ok"} | {result: "failed", error: any}>( + const { data } = await this.axios.put<{ result: 'ok' } | { result: 'failed'; error: unknown }>( URLS.rest.documents.pick(document).self, document, ); - if (data.result === "failed") { + if (data.result === 'failed') { throw new Error( - `setDocument(${JSON.stringify({documentID: document.documentID})} failed due to ${JSON.stringify(data.error)}` + `setDocument(${JSON.stringify({ + documentID: document.documentID, + })} failed due to ${JSON.stringify(data.error)}`, ); } } /** * Delete the given document. - * @param documentID The ID of the document to delete. + * @param documentID - The ID of the document to delete. * @returns Metadata about the deleted document. */ public async deleteDocument(documentID: MCDocument['documentID']) { const deletedDocument = await this.axios.delete( - URLS.rest.documents.pick({documentID}).self, + URLS.rest.documents.pick({ documentID }).self, {}, // force sending empty JSON to avoid triggering CSRF check ); return deletedDocument.data; diff --git a/packages/sdk/src/urls.ts b/packages/sdk/src/urls.ts index 3029c7a..c337f0a 100644 --- a/packages/sdk/src/urls.ts +++ b/packages/sdk/src/urls.ts @@ -7,12 +7,14 @@ export const URLS = { }, rest: { documents: { - pick: (opts: Pick | Pick) => { - const {documentID} = opts; - let queryParams = ""; + pick: ( + opts: Pick | Pick, + ) => { + const { documentID } = opts; + let queryParams = ''; if ('major' in opts) { - const {major, minor} = opts; + const { major, minor } = opts; queryParams = `v${major ?? 0}.${minor ?? 1}`; } @@ -21,9 +23,9 @@ export const URLS = { return { presentations: `${baseURL}/presentations`, self: baseURL, - withVersion: `${baseURL}${queryParams}` + withVersion: `${baseURL}${queryParams}`, }; - } + }, }, users: { self: `/rest-api/users/me`, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2a672c2..fdb6ae7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -408,6 +408,18 @@ importers: '@types/uuid': specifier: ^9.0.2 version: 9.0.2 + '@typescript-eslint/eslint-plugin': + specifier: ^6.11.0 + version: 6.12.0(@typescript-eslint/parser@6.13.1)(eslint@8.54.0)(typescript@5.2.2) + '@typescript-eslint/parser': + specifier: ^6.11.0 + version: 6.13.1(eslint@8.54.0)(typescript@5.2.2) + eslint: + specifier: ^8.54.0 + version: 8.54.0 + prettier: + specifier: ^3.0.3 + version: 3.0.3 packages: