From 8c2ab14e78b058dc09593dff3c81341948161964 Mon Sep 17 00:00:00 2001 From: Ian VanSchooten Date: Fri, 18 Aug 2023 17:42:34 -0400 Subject: [PATCH] Upgrade msw to next (2.0) --- lib/msw-config.ts | 102 ++++++++++++++++++---------- package.json | 4 +- pnpm-lock.yaml | 169 +++++++++++++++++++++++++++------------------- tsconfig.json | 5 ++ 4 files changed, 173 insertions(+), 107 deletions(-) diff --git a/lib/msw-config.ts b/lib/msw-config.ts index ada59c8..e9ca774 100644 --- a/lib/msw-config.ts +++ b/lib/msw-config.ts @@ -1,11 +1,6 @@ -import { - rest, - RestHandler, - setupWorker, - type RestRequest, - type SetupWorkerApi, -} from 'msw'; -import type { Server } from 'miragejs'; +import { http, HttpHandler, HttpResponse, delay } from 'msw'; +import { setupWorker, type SetupWorker } from 'msw/browser'; +import type { Request } from 'miragejs'; import type { RouteHandler, ServerConfig } from 'miragejs/server'; import type { AnyFactories, AnyModels, AnyRegistry } from 'miragejs/-types'; @@ -50,7 +45,7 @@ type MirageServer = { rawHandler?: RawHandler, customizedCode?: ResponseCode, options?: unknown - ) => (request: RestRequest) => ResponseData | PromiseLike; + ) => (request: Request) => ResponseData | PromiseLike; get?: BaseHandler; post?: BaseHandler; @@ -132,14 +127,14 @@ export default class MswConfig { timing?: number; - msw?: SetupWorkerApi; + msw?: SetupWorker; mirageServer?: MirageServer; // TODO: infer models and factories mirageConfig?: ServerConfig; - handlers: RestHandler[] = []; + handlers: HttpHandler[] = []; get?: BaseHandler; post?: BaseHandler; @@ -186,35 +181,72 @@ export default class MswConfig { options ); let fullPath = this._getFullPath(path); - let mswHandler = rest[verb](fullPath, async (req, res, ctx) => { + let mswHandler = http[verb](fullPath, async ({ request, params }) => { let queryParams: Record = {}; - req.url.searchParams.forEach((value, key) => { - let newValue: string | string[] = value; - if (key.includes('[]')) { - key = key.replace('[]', ''); - newValue = [...(queryParams[key] || []), value]; + const reqUrl = new URL(request.url); + for (const [paramKey, paramValue] of reqUrl.searchParams.entries()) { + let newValue: string | string[] = paramValue; + let newKey = paramKey; + if (newKey.includes('[]')) { + newKey = newKey.replace('[]', ''); + newValue = [...(queryParams[newKey] || []), paramValue]; } - queryParams[key] = newValue; - }); - let request = Object.assign(req, { - requestBody: - typeof req.body === 'string' - ? req.body - : JSON.stringify(req.body), - queryParams: queryParams, + queryParams[newKey] = newValue; + } + + // Determine how to process a request body + let requestBody: string = ''; + const contentType = + request.headers?.get('content-type')?.toLowerCase() || ''; + const hasJsonContent = contentType.includes('json'); + if (hasJsonContent) { + requestBody = JSON.stringify(await request.json()); + } else { + // This will parse multipart as text, which I think will work? Should be tested + requestBody = await request.text(); + } + const requestHeaders: Record = {}; + request.headers.forEach((v, k) => { + requestHeaders[k.toLowerCase()] = v; }); - let [code, headers, response] = await handler(request); - if (code === 204) { + + let req: Request = { + requestBody, + // @ts-expect-error this is fixed in an unreleased version of miragejs + queryParams, + requestHeaders, + // @ts-expect-error params can be an array, but mirage doesn't expect that + params, + }; + + let [status, headers, responseBody] = await handler(req); + + if (status === 204) { // MirageJS Incorrectly sets the body to "" on a 204. - response = undefined; + responseBody = undefined; + } + + const init = { + status, + headers, + }; + + // Delay the response if needed + if (this.timing) { + await delay(this.timing); + } + + // Return the correct type of response based on the `accept` header + const accept = request.headers?.get('accept')?.toLowerCase() || ''; + if (accept.includes('json')) { + return HttpResponse.json(responseBody, init); + } else if (accept.includes('text')) { + return HttpResponse.text(responseBody, init); + } else { + throw new Error( + `Mirage-msw: Only json and text responses are supported at this time. Please open an issue requesting support for ${accept}.` + ); } - return res(ctx.status(code), ctx.delay(this.timing), (res) => { - res.body = response; - Object.entries(headers || {}).forEach(([key, value]) => { - res.headers.set(key, value); - }); - return res; - }); }); if (this.msw) { this.msw.use(mswHandler); diff --git a/package.json b/package.json index 9cd58d4..99417fc 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "devDependencies": { "@tsconfig/recommended": "^1.0.2", "miragejs": "^0.1.47", - "msw": "^0.39.2", + "msw": "0.0.0-fetch.rc-19", "prettier": "^3.0.1", "tsup": "^7.2.0", "typescript": "^5.1.6" @@ -39,7 +39,7 @@ }, "peerDependancies": { "miragejs": "~0.1.43", - "msw": "^0.39.2" + "msw": "^0.0.0-fetch.rc-16" }, "author": "Brian Gantzler", "license": "MIT", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b886a42..87ce37e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ devDependencies: specifier: ^0.1.47 version: 0.1.47 msw: - specifier: ^0.39.2 - version: 0.39.2 + specifier: 0.0.0-fetch.rc-19 + version: 0.0.0-fetch.rc-19(typescript@5.1.6) prettier: specifier: ^3.0.1 version: 3.0.1 @@ -26,6 +26,24 @@ devDependencies: packages: + /@bundled-es-modules/cookie@2.0.0: + resolution: {integrity: sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==} + dependencies: + cookie: 0.5.0 + dev: true + + /@bundled-es-modules/js-levenshtein@2.0.1: + resolution: {integrity: sha512-DERMS3yfbAljKsQc0U2wcqGKUWpdFjwqWuoMugEJlqBnKO180/n+4SR/J8MRDt1AN48X1ovgoD9KrdVXcaa3Rg==} + dependencies: + js-levenshtein: 1.1.6 + dev: true + + /@bundled-es-modules/statuses@1.0.1: + resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==} + dependencies: + statuses: 2.0.1 + dev: true + /@esbuild/android-arm64@0.18.20: resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} engines: {node: '>=12'} @@ -258,26 +276,21 @@ packages: resolution: {integrity: sha512-M/BexG/p05C5lFfMunxo/QcgIJnMT2vDVCd00wNqK2ImZONIlEETZwWJu1QtLxtmYlSHlCFl3JNzp0tLe7OJ5g==} dev: true - /@mswjs/cookies@0.2.2: - resolution: {integrity: sha512-mlN83YSrcFgk7Dm1Mys40DLssI1KdJji2CMKN8eOlBqsTADYzj2+jWzsANsUTFbxDMWPD5e9bfA1RGqBpS3O1g==} + /@mswjs/cookies@1.0.0: + resolution: {integrity: sha512-TdXoBdI+h/EDTsVLCX/34s4+9U0sWi92qFnIGUEikpMCSKLhBeujovyYVSoORNbYgsBH5ga7/tfxyWcEZAxiYA==} engines: {node: '>=14'} - dependencies: - '@types/set-cookie-parser': 2.4.3 - set-cookie-parser: 2.6.0 dev: true - /@mswjs/interceptors@0.15.3: - resolution: {integrity: sha512-GJ1qzBq82EQ3bwhsvw5nScbrLzOSI5H/TyB2CGd1K7dDqX58DJDLJHexiN+S5Ucvl6/84FjRdIysz0RxE/L8MA==} - engines: {node: '>=14'} + /@mswjs/interceptors@0.25.1: + resolution: {integrity: sha512-iM/2Qp+y7zKrX1sf45sPvvE7CGly8AKSR8Ua7cXAszXCK/To5i/L8AwiheEaBSVcZ6R7Em7kTcyZWN5H2ivcEQ==} + engines: {node: '>=18'} dependencies: - '@open-draft/until': 1.0.3 - '@xmldom/xmldom': 0.7.13 - debug: 4.3.4 - headers-polyfill: 3.1.2 + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/logger': 0.3.0 + '@open-draft/until': 2.1.0 + is-node-process: 1.2.0 outvariant: 1.4.0 - strict-event-emitter: 0.2.8 - transitivePeerDependencies: - - supports-color + strict-event-emitter: 0.5.0 dev: true /@nodelib/fs.scandir@2.1.5: @@ -301,8 +314,19 @@ packages: fastq: 1.15.0 dev: true - /@open-draft/until@1.0.3: - resolution: {integrity: sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==} + /@open-draft/deferred-promise@2.2.0: + resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} + dev: true + + /@open-draft/logger@0.3.0: + resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} + dependencies: + is-node-process: 1.2.0 + outvariant: 1.4.0 + dev: true + + /@open-draft/until@2.1.0: + resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} dev: true /@tsconfig/recommended@1.0.2: @@ -317,19 +341,8 @@ packages: resolution: {integrity: sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g==} dev: true - /@types/node@20.4.9: - resolution: {integrity: sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ==} - dev: true - - /@types/set-cookie-parser@2.4.3: - resolution: {integrity: sha512-7QhnH7bi+6KAhBB+Auejz1uV9DHiopZqu7LfR/5gZZTkejJV5nYeZZpgfFoE0N8aDsXuiYpfKyfyMatCwQhyTQ==} - dependencies: - '@types/node': 20.4.9 - dev: true - - /@xmldom/xmldom@0.7.13: - resolution: {integrity: sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==} - engines: {node: '>=10.0.0'} + /@types/statuses@2.0.1: + resolution: {integrity: sha512-vVRgv7WXbhIZzILgr58b4Ki2uqpN/dlVCUBWCMkPbMDlV1CrQrgCl5hnIoUlMrgymGcTmdfVqbs1yWj/IRIRtQ==} dev: true /ansi-escapes@4.3.2: @@ -425,8 +438,8 @@ packages: engines: {node: '>=8'} dev: true - /chalk@4.1.1: - resolution: {integrity: sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==} + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} dependencies: ansi-styles: 4.3.0 @@ -503,8 +516,8 @@ packages: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true - /cookie@0.4.2: - resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} dev: true @@ -586,11 +599,6 @@ packages: engines: {node: '>=0.8.0'} dev: true - /events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - dev: true - /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -650,6 +658,14 @@ packages: to-regex-range: 5.0.1 dev: true + /formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + dev: true + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true @@ -712,8 +728,8 @@ packages: engines: {node: '>=8'} dev: true - /headers-polyfill@3.1.2: - resolution: {integrity: sha512-tWCK4biJ6hcLqTviLXVR9DTRfYGQMXEIUj3gwJ2rZ5wO/at3XtkI4g8mCvFdUF9l1KMBNCfmNAdnahm1cgavQA==} + /headers-polyfill@3.2.3: + resolution: {integrity: sha512-oj6MO8sdFQ9gQQedSVdMGh96suxTNp91vPQu7C4qx/57FqYsA5TiNr92nhIZwVQq8zygn4nu3xS1aEqpakGqdw==} dev: true /human-signals@2.1.0: @@ -757,7 +773,7 @@ packages: engines: {node: '>=12.0.0'} dependencies: ansi-escapes: 4.3.2 - chalk: 4.1.1 + chalk: 4.1.2 cli-cursor: 3.1.0 cli-width: 3.0.0 external-editor: 3.1.0 @@ -953,7 +969,7 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} dependencies: - chalk: 4.1.1 + chalk: 4.1.2 is-unicode-supported: 0.1.0 dev: true @@ -1021,34 +1037,43 @@ packages: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true - /msw@0.39.2: - resolution: {integrity: sha512-ju/HpqQpE4/qCxZ23t5Gaau0KREn4QuFzdG28nP1EpidMrymMJuIvNd32+2uGTGG031PMwrC41YW7vCxHOwyHA==} - engines: {node: '>=14'} + /msw@0.0.0-fetch.rc-19(typescript@5.1.6): + resolution: {integrity: sha512-AMFmUDGNsg/OJdaCTjiO5RUghdmfRJx2X8LU6apginM5Qqk4lyWmQvrtpF3e0KG/1DByFgxvEwoGarXRX88EZg==} + engines: {node: '>=18'} hasBin: true requiresBuild: true + peerDependencies: + typescript: '>= 4.4.x <= 5.2.x' + peerDependenciesMeta: + typescript: + optional: true dependencies: - '@mswjs/cookies': 0.2.2 - '@mswjs/interceptors': 0.15.3 - '@open-draft/until': 1.0.3 + '@bundled-es-modules/cookie': 2.0.0 + '@bundled-es-modules/js-levenshtein': 2.0.1 + '@bundled-es-modules/statuses': 1.0.1 + '@mswjs/cookies': 1.0.0 + '@mswjs/interceptors': 0.25.1 + '@open-draft/until': 2.1.0 '@types/cookie': 0.4.1 '@types/js-levenshtein': 1.1.1 - chalk: 4.1.1 + '@types/statuses': 2.0.1 + chalk: 4.1.2 chokidar: 3.5.3 - cookie: 0.4.2 + formdata-node: 4.4.1 graphql: 16.7.1 - headers-polyfill: 3.1.2 + headers-polyfill: 3.2.3 inquirer: 8.2.6 is-node-process: 1.2.0 js-levenshtein: 1.1.6 node-fetch: 2.6.12 + outvariant: 1.4.0 path-to-regexp: 6.2.1 - statuses: 2.0.1 - strict-event-emitter: 0.2.8 - type-fest: 1.4.0 + strict-event-emitter: 0.5.0 + type-fest: 2.19.0 + typescript: 5.1.6 yargs: 17.7.2 transitivePeerDependencies: - encoding - - supports-color dev: true /mute-stream@0.0.8: @@ -1063,6 +1088,11 @@ packages: thenify-all: 1.6.0 dev: true + /node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + dev: true + /node-fetch@2.6.12: resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==} engines: {node: 4.x || >=6.0.0} @@ -1110,7 +1140,7 @@ packages: engines: {node: '>=10'} dependencies: bl: 4.1.0 - chalk: 4.1.1 + chalk: 4.1.2 cli-cursor: 3.1.0 cli-spinners: 2.9.0 is-interactive: 1.0.0 @@ -1272,10 +1302,6 @@ packages: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} dev: true - /set-cookie-parser@2.6.0: - resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} - dev: true - /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -1309,10 +1335,8 @@ packages: engines: {node: '>= 0.8'} dev: true - /strict-event-emitter@0.2.8: - resolution: {integrity: sha512-KDf/ujU8Zud3YaLtMCcTI4xkZlZVIYxTLr+XIULexP+77EEVWixeXroLUXQXiVtH4XH2W7jr/3PT1v3zBuvc3A==} - dependencies: - events: 3.3.0 + /strict-event-emitter@0.5.0: + resolution: {integrity: sha512-sqnMpVJLSB3daNO6FcvsEk4Mq5IJeAwDeH80DP1S8+pgxrF6yZnE1+VeapesGled7nEcIkz1Ax87HzaIy+02kA==} dev: true /string-width@4.2.3: @@ -1458,9 +1482,9 @@ packages: engines: {node: '>=10'} dev: true - /type-fest@1.4.0: - resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} - engines: {node: '>=10'} + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} dev: true /typescript@5.1.6: @@ -1479,6 +1503,11 @@ packages: defaults: 1.0.4 dev: true + /web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + dev: true + /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} dev: true diff --git a/tsconfig.json b/tsconfig.json index 0c4952b..36497a5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,9 @@ { "extends": "@tsconfig/recommended/tsconfig.json", + "compilerOptions": { + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "Bundler" + }, "include": ["lib"] }