diff --git a/mocks/handlers.ts b/mocks/handlers.ts new file mode 100644 index 0000000..b6c0352 --- /dev/null +++ b/mocks/handlers.ts @@ -0,0 +1,540 @@ +/** + * This file is AUTO GENERATED by [msw-auto-mock](https://github.com/zoubingwu/msw-auto-mock) + * Feel free to commit/edit it as you need. + */ + +/* tslint:disable */ +import { faker } from '@faker-js/faker'; +import { HttpResponse, http } from 'msw'; +import { setupWorker } from 'msw/browser'; + +faker.seed(1); + +const baseURL = 'http://localhost:3000/api'; +const MAX_ARRAY_LENGTH = 20; + +let i = 0; +const next = () => { + if (i === Number.MAX_SAFE_INTEGER - 1) { + i = 0; + } + return i++; +}; + +export const handlers = [ + http.get(`${baseURL}/questionnaires`, () => { + const resultArray = [ + [getGetQuestionnaires200Response(), { status: 200 }], + [null, { status: 400 }], + [null, { status: 500 }], + [null, { status: 503 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }), + http.post(`${baseURL}/questionnaires`, () => { + const resultArray = [ + [getPostQuestionnaire201Response(), { status: 201 }], + [null, { status: 400 }], + [null, { status: 500 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }), + http.get(`${baseURL}/questionnaires/:questionnaireId`, () => { + const resultArray = [ + [getGetQuestionnaire200Response(), { status: 200 }], + [null, { status: 400 }], + [null, { status: 404 }], + [null, { status: 500 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }), + http.patch(`${baseURL}/questionnaires/:questionnaireId`, () => { + const resultArray = [ + [null, { status: 200 }], + [null, { status: 400 }], + [null, { status: 500 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }), + http.delete(`${baseURL}/questionnaires/:questionnaireId`, () => { + const resultArray = [ + [null, { status: 200 }], + [null, { status: 400 }], + [null, { status: 500 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }), + http.get(`${baseURL}/questionnaires/:questionnaireId/myRemindStatus`, () => { + const resultArray = [ + [getGetQuestionnaireMyRemindStatus200Response(), { status: 200 }], + [null, { status: 400 }], + [null, { status: 404 }], + [null, { status: 500 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }), + http.patch( + `${baseURL}/questionnaires/:questionnaireId/myRemindStatus`, + () => { + const resultArray = [ + [null, { status: 200 }], + [null, { status: 400 }], + [null, { status: 404 }], + [null, { status: 500 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }, + ), + http.get(`${baseURL}/questionnaires/:questionnaireId/responses`, () => { + const resultArray = [ + [getGetQuestionnaireResponses200Response(), { status: 200 }], + [null, { status: 400 }], + [null, { status: 403 }], + [null, { status: 404 }], + [null, { status: 500 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }), + http.post(`${baseURL}/questionnaires/:questionnaireId/responses`, () => { + const resultArray = [ + [getPostQuestionnaireResponse201Response(), { status: 201 }], + [null, { status: 400 }], + [null, { status: 404 }], + [null, { status: 422 }], + [null, { status: 500 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }), + http.get(`${baseURL}/questionnaires/:questionnaireId/result`, () => { + const resultArray = [ + [getGetQuestionnaireResult200Response(), { status: 200 }], + [null, { status: 400 }], + [null, { status: 403 }], + [null, { status: 404 }], + [null, { status: 500 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }), + http.get(`${baseURL}/responses/:responseId`, () => { + const resultArray = [ + [getGetResponse200Response(), { status: 200 }], + [null, { status: 400 }], + [null, { status: 403 }], + [null, { status: 404 }], + [null, { status: 500 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }), + http.patch(`${baseURL}/responses/:responseId`, () => { + const resultArray = [ + [null, { status: 200 }], + [null, { status: 400 }], + [null, { status: 403 }], + [null, { status: 404 }], + [null, { status: 405 }], + [null, { status: 500 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }), + http.delete(`${baseURL}/responses/:responseId`, () => { + const resultArray = [ + [null, { status: 200 }], + [null, { status: 400 }], + [null, { status: 403 }], + [null, { status: 404 }], + [null, { status: 405 }], + [null, { status: 500 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }), + http.get(`${baseURL}/responses/myResponses`, () => { + const resultArray = [ + [getGetMyResponses200Response(), { status: 200 }], + [null, { status: 500 }], + ]; + + return HttpResponse.json(...resultArray[next() % resultArray.length]); + }), +]; + +export function getGetQuestionnaires200Response() { + return { + page_max: 1, + questionnaires: [ + ...new Array(faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH })).keys(), + ].map((_) => ({ + questionnaire_id: 1, + title: '第1回集会らん☆ぷろ募集アンケート', + description: + '第1回メンバー集会でのらん☆ぷろで発表したい人を募集します らん☆ぷろで発表したい人あつまれー!', + response_due_date_time: '2019-12-31T15:00:00.000Z', + response_viewable_by: 'anyone', + is_anonymous: true, + is_allowing_multiple_responses: true, + is_published: true, + is_targeting_me: true, + created_at: '2019-12-31T15:00:00.000Z', + modified_at: '2019-12-31T15:00:00.000Z', + has_my_draft: faker.datatype.boolean(), + has_my_response: faker.datatype.boolean(), + responded_date_time_by_me: faker.date.past(), + all_responded: true, + })), + }; +} + +export function getPostQuestionnaire201Response() { + return { + title: '第1回集会らん☆ぷろ募集アンケート', + description: + '第1回メンバー集会でのらん☆ぷろで発表したい人を募集します らん☆ぷろで発表したい人あつまれー!', + response_due_date_time: '2019-12-31T15:00:00.000Z', + response_viewable_by: 'anyone', + is_anonymous: true, + is_allowing_multiple_responses: true, + is_published: true, + targets: { + users: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => 'cp20'), + groups: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => 1), + }, + admins: { + users: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => 'cp20'), + groups: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => 1), + }, + questionnaire_id: 1, + created_at: '2019-12-31T15:00:00.000Z', + modified_at: '2019-12-31T15:00:00.000Z', + questions: [ + ...new Array(faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH })).keys(), + ].map((_) => null), + respondents: null, + }; +} + +export function getGetQuestionnaire200Response() { + return { + title: '第1回集会らん☆ぷろ募集アンケート', + description: + '第1回メンバー集会でのらん☆ぷろで発表したい人を募集します らん☆ぷろで発表したい人あつまれー!', + response_due_date_time: '2019-12-31T15:00:00.000Z', + response_viewable_by: 'anyone', + is_anonymous: true, + is_allowing_multiple_responses: true, + is_published: true, + targets: { + users: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => 'cp20'), + groups: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => 1), + }, + admins: { + users: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => 'cp20'), + groups: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => 1), + }, + questionnaire_id: 1, + created_at: '2019-12-31T15:00:00.000Z', + modified_at: '2019-12-31T15:00:00.000Z', + questions: [ + ...new Array(faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH })).keys(), + ].map((_) => null), + respondents: null, + }; +} + +export function getGetQuestionnaireMyRemindStatus200Response() { + return { + is_remind_enabled: faker.datatype.boolean(), + }; +} + +export function getGetQuestionnaireResponses200Response() { + return [ + ...new Array(faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH })).keys(), + ].map((_) => ({ + questionnaire_id: 1, + response_id: 1, + respondent: 'cp20', + submitted_at: '2019-12-31T15:00:00.000Z', + modified_at: '2019-12-31T15:00:00.000Z', + is_draft: true, + body: [ + ...new Array(faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH })).keys(), + ].map((_) => + faker.helpers.arrayElement([ + { + question_type: faker.helpers.arrayElement(['Text']), + answer: faker.lorem.slug(1), + }, + { + question_type: faker.helpers.arrayElement(['TextLong']), + answer: faker.lorem.slug(1), + }, + { + question_type: faker.helpers.arrayElement(['Number']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + { + question_type: faker.helpers.arrayElement(['SingleChoice']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + { + question_type: faker.helpers.arrayElement(['MultipleChoice']), + answer: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => faker.number.int({ min: undefined, max: undefined })), + }, + { + question_type: faker.helpers.arrayElement(['Scale']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + ]), + ), + })); +} + +export function getPostQuestionnaireResponse201Response() { + return { + questionnaire_id: 1, + response_id: 1, + respondent: 'cp20', + submitted_at: '2019-12-31T15:00:00.000Z', + modified_at: '2019-12-31T15:00:00.000Z', + is_draft: true, + body: [ + ...new Array(faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH })).keys(), + ].map((_) => + faker.helpers.arrayElement([ + { + question_type: faker.helpers.arrayElement(['Text']), + answer: faker.lorem.slug(1), + }, + { + question_type: faker.helpers.arrayElement(['TextLong']), + answer: faker.lorem.slug(1), + }, + { + question_type: faker.helpers.arrayElement(['Number']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + { + question_type: faker.helpers.arrayElement(['SingleChoice']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + { + question_type: faker.helpers.arrayElement(['MultipleChoice']), + answer: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => faker.number.int({ min: undefined, max: undefined })), + }, + { + question_type: faker.helpers.arrayElement(['Scale']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + ]), + ), + }; +} + +export function getGetQuestionnaireResult200Response() { + return [ + ...new Array(faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH })).keys(), + ].map((_) => ({ + questionnaire_id: 1, + response_id: 1, + submitted_at: '2019-12-31T15:00:00.000Z', + modified_at: '2019-12-31T15:00:00.000Z', + is_draft: true, + body: [ + ...new Array(faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH })).keys(), + ].map((_) => + faker.helpers.arrayElement([ + { + question_type: faker.helpers.arrayElement(['Text']), + answer: faker.lorem.slug(1), + }, + { + question_type: faker.helpers.arrayElement(['TextLong']), + answer: faker.lorem.slug(1), + }, + { + question_type: faker.helpers.arrayElement(['Number']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + { + question_type: faker.helpers.arrayElement(['SingleChoice']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + { + question_type: faker.helpers.arrayElement(['MultipleChoice']), + answer: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => faker.number.int({ min: undefined, max: undefined })), + }, + { + question_type: faker.helpers.arrayElement(['Scale']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + ]), + ), + })); +} + +export function getGetResponse200Response() { + return { + questionnaire_id: 1, + response_id: 1, + respondent: 'cp20', + submitted_at: '2019-12-31T15:00:00.000Z', + modified_at: '2019-12-31T15:00:00.000Z', + is_draft: true, + body: [ + ...new Array(faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH })).keys(), + ].map((_) => + faker.helpers.arrayElement([ + { + question_type: faker.helpers.arrayElement(['Text']), + answer: faker.lorem.slug(1), + }, + { + question_type: faker.helpers.arrayElement(['TextLong']), + answer: faker.lorem.slug(1), + }, + { + question_type: faker.helpers.arrayElement(['Number']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + { + question_type: faker.helpers.arrayElement(['SingleChoice']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + { + question_type: faker.helpers.arrayElement(['MultipleChoice']), + answer: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => faker.number.int({ min: undefined, max: undefined })), + }, + { + question_type: faker.helpers.arrayElement(['Scale']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + ]), + ), + }; +} + +export function getGetMyResponses200Response() { + return [ + ...new Array(faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH })).keys(), + ].map((_) => + [ + ...new Array(faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH })).keys(), + ].map((_) => ({ + questionnaire_id: 1, + response_id: 1, + respondent: 'cp20', + submitted_at: '2019-12-31T15:00:00.000Z', + modified_at: '2019-12-31T15:00:00.000Z', + is_draft: true, + body: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => + faker.helpers.arrayElement([ + { + question_type: faker.helpers.arrayElement(['Text']), + answer: faker.lorem.slug(1), + }, + { + question_type: faker.helpers.arrayElement(['TextLong']), + answer: faker.lorem.slug(1), + }, + { + question_type: faker.helpers.arrayElement(['Number']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + { + question_type: faker.helpers.arrayElement(['SingleChoice']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + { + question_type: faker.helpers.arrayElement(['MultipleChoice']), + answer: [ + ...new Array( + faker.number.int({ min: 1, max: MAX_ARRAY_LENGTH }), + ).keys(), + ].map((_) => faker.number.int({ min: undefined, max: undefined })), + }, + { + question_type: faker.helpers.arrayElement(['Scale']), + answer: faker.number.int({ min: undefined, max: undefined }), + }, + ]), + ), + questionnaire_info: { + title: '第1回集会らん☆ぷろ募集アンケート', + response_due_date_time: '2019-12-31T15:00:00.000Z', + created_at: '2019-12-31T15:00:00.000Z', + modified_at: '2019-12-31T15:00:00.000Z', + is_targeting_me: true, + }, + })), + ); +} + +// This configures a Service Worker with the given request handlers. +export const startWorker = () => { + const worker = setupWorker(...handlers); + worker.start(); +}; diff --git a/package-lock.json b/package-lock.json index 600eae4..743b5b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "js-sha256": "^0.10.1" }, "devDependencies": { + "@faker-js/faker": "^8.4.1", "@nuxt/devtools": "latest", "@nuxt/test-utils": "^3.9.0", "@nuxtjs/eslint-config-typescript": "^12.1.0", @@ -25,6 +26,8 @@ "eslint-plugin-unused-imports": "^3.0.0", "eslint-plugin-vue": "^9.19.2", "happy-dom": "^12.10.3", + "msw": "^2.2.14", + "msw-auto-mock": "^0.18.0", "nuxt": "^3.8.2", "nuxt-icon": "^0.6.7", "nuxt-primevue": "^0.2.2", @@ -78,6 +81,108 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz", + "integrity": "sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg==", + "dev": true, + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "js-yaml": "^3.13.1" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "dev": true + }, + "node_modules/@apidevtools/swagger-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.1.0.tgz", + "integrity": "sha512-9Kt7EuS/7WbMAUv2gSziqjvxwDbFSg3Xeyfuj5laUODX8o/k/CpsAKiQ8W7/R88eXFTMbJYg6+7uAmOWNKmwnw==", + "dev": true, + "dependencies": { + "@apidevtools/json-schema-ref-parser": "9.0.6", + "@apidevtools/openapi-schemas": "^2.1.0", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "ajv": "^8.6.3", + "ajv-draft-04": "^1.0.0", + "call-me-maybe": "^1.0.1" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@apidevtools/swagger-parser/node_modules/ajv": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@apidevtools/swagger-parser/node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@apidevtools/swagger-parser/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/@babel/code-frame": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", @@ -757,6 +862,24 @@ "node": ">=6.9.0" } }, + "node_modules/@bundled-es-modules/cookie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz", + "integrity": "sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==", + "dev": true, + "dependencies": { + "cookie": "^0.5.0" + } + }, + "node_modules/@bundled-es-modules/statuses": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", + "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", + "dev": true, + "dependencies": { + "statuses": "^2.0.1" + } + }, "node_modules/@cloudflare/kv-asset-handler": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.0.tgz", @@ -1298,6 +1421,28 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@exodus/schemasafe": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", + "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==", + "dev": true + }, + "node_modules/@faker-js/faker": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.1.tgz", + "integrity": "sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0", + "npm": ">=6.14.13" + } + }, "node_modules/@fastify/busboy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", @@ -1392,6 +1537,87 @@ "vue": ">=3" } }, + "node_modules/@inquirer/confirm": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.6.tgz", + "integrity": "sha512-Mj4TU29g6Uy+37UtpA8UpEOI2icBfpCwSW1QDtfx60wRhUy90s/kHPif2OXSSvuwDQT1lhAYRWUfkNf9Tecxvg==", + "dev": true, + "dependencies": { + "@inquirer/core": "^8.1.0", + "@inquirer/type": "^1.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.1.0.tgz", + "integrity": "sha512-kfx0SU9nWgGe1f03ao/uXc85SFH1v2w3vQVH7QDGjKxdtJz+7vPitFtG++BTyJMYyYgH8MpXigutcXJeiQwVRw==", + "dev": true, + "dependencies": { + "@inquirer/figures": "^1.0.1", + "@inquirer/type": "^1.3.1", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.12.7", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.1.tgz", + "integrity": "sha512-mtup3wVKia3ZwULPHcbs4Mor8Voi+iIXEWD7wCNbIO6lYR62oPCTQyrddi5OMYVXHzeCSoneZwJuS8sBvlEwDw==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.3.1.tgz", + "integrity": "sha512-Pe3PFccjPVJV1vtlfVvm9OnlbxqdnP5QcscFEFEnK5quChf1ufZtM0r8mR5ToWHMxZOh0s8o/qp9ANGRTo/DAw==", + "dev": true, + "engines": { + "node": ">=18" + } + }, "node_modules/@ioredis/commands": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", @@ -1581,6 +1807,12 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "dev": true + }, "node_modules/@kwsites/file-exists": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", @@ -1616,6 +1848,32 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, + "node_modules/@mswjs/cookies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-1.1.0.tgz", + "integrity": "sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@mswjs/interceptors": { + "version": "0.26.15", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.26.15.tgz", + "integrity": "sha512-HM47Lu1YFmnYHKMBynFfjCp0U/yRskHj/8QEJW0CBEPOlw8Gkmjfll+S9b8M7V5CNDw2/ciRxjjnWeaCiblSIQ==", + "dev": true, + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@netlify/functions": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-2.4.1.tgz", @@ -2891,6 +3149,28 @@ } } }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true + }, "node_modules/@parcel/watcher": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.3.0.tgz", @@ -3740,6 +4020,12 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "dev": true + }, "node_modules/@types/eslint": { "version": "8.56.2", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz", @@ -3818,10 +4104,19 @@ "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", "dev": true }, + "node_modules/@types/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { - "version": "20.11.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz", - "integrity": "sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==", + "version": "20.12.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.8.tgz", + "integrity": "sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -3845,6 +4140,18 @@ "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, + "node_modules/@types/statuses": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", + "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", + "dev": true + }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", + "dev": true + }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -5553,6 +5860,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -5791,6 +6104,27 @@ "node": "*" } }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/clipboardy": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-4.0.0.tgz", @@ -5983,6 +6317,15 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-es": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.0.0.tgz", @@ -6855,6 +7198,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", + "dev": true + }, "node_modules/esbuild": { "version": "0.19.11", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.11.tgz", @@ -7578,6 +7927,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", @@ -7738,6 +8100,12 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -8340,6 +8708,15 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/graphql": { + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, "node_modules/gzip-size": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-7.0.0.tgz", @@ -8496,6 +8873,12 @@ "he": "bin/he" } }, + "node_modules/headers-polyfill": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", + "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", + "dev": true + }, "node_modules/hookable": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", @@ -8611,6 +8994,12 @@ "node": ">= 0.12.0" } }, + "node_modules/http2-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", + "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==", + "dev": true + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -9034,6 +9423,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -10286,12 +10681,100 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/msw": { + "version": "2.2.14", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.2.14.tgz", + "integrity": "sha512-64i8rNCa1xzDK8ZYsTrVMli05D687jty8+Th+PU5VTbJ2/4P7fkQFVyDQ6ZFT5FrNR8z2BHhbY47fKNvfHrumA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@bundled-es-modules/cookie": "^2.0.0", + "@bundled-es-modules/statuses": "^1.0.1", + "@inquirer/confirm": "^3.0.0", + "@mswjs/cookies": "^1.1.0", + "@mswjs/interceptors": "^0.26.14", + "@open-draft/until": "^2.1.0", + "@types/cookie": "^0.6.0", + "@types/statuses": "^2.0.4", + "chalk": "^4.1.2", + "graphql": "^16.8.1", + "headers-polyfill": "^4.0.2", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.2", + "path-to-regexp": "^6.2.0", + "strict-event-emitter": "^0.5.1", + "type-fest": "^4.9.0", + "yargs": "^17.7.2" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.7.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw-auto-mock": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/msw-auto-mock/-/msw-auto-mock-0.18.0.tgz", + "integrity": "sha512-mFpsq+EM2W05Vb07VMRbJJarahUtxzq4hapwUYhoLM5MtU6tM2D5tRK9xEP7hBRZc6rWT+tfCwvjB0KhxoNEPQ==", + "dev": true, + "dependencies": { + "@apidevtools/swagger-parser": "^10.1.0", + "cac": "^6.7.12", + "lodash": "^4.17.21", + "oazapfts": "^4.5.2", + "prettier": "3.1.0", + "swagger2openapi": "^7.0.8" + }, + "bin": { + "msw-auto-mock": "bin/cli.js" + }, + "peerDependencies": { + "@faker-js/faker": "^8.2.0", + "msw": "^2.0.1" + } + }, + "node_modules/msw-auto-mock/node_modules/prettier": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/muggle-string": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", "dev": true }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/nanoid": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz", @@ -10469,6 +10952,18 @@ } } }, + "node_modules/node-fetch-h2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", + "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", + "dev": true, + "dependencies": { + "http2-client": "^1.2.5" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, "node_modules/node-fetch-native": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.1.tgz", @@ -10589,6 +11084,15 @@ "node": "^16.13.0 || >=18.0.0" } }, + "node_modules/node-readfiles": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz", + "integrity": "sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==", + "dev": true, + "dependencies": { + "es6-promise": "^3.2.1" + } + }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", @@ -10995,6 +11499,119 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/oas-kit-common": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", + "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", + "dev": true, + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/oas-linter": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz", + "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==", + "dev": true, + "dependencies": { + "@exodus/schemasafe": "^1.0.0-rc.2", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-linter/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/oas-resolver": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz", + "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==", + "dev": true, + "dependencies": { + "node-fetch-h2": "^2.3.0", + "oas-kit-common": "^1.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "resolve": "resolve.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-resolver/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/oas-schema-walker": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", + "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", + "dev": true, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-validator": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz", + "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==", + "dev": true, + "dependencies": { + "call-me-maybe": "^1.0.1", + "oas-kit-common": "^1.0.8", + "oas-linter": "^3.2.2", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "reftools": "^1.1.9", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-validator/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/oazapfts": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/oazapfts/-/oazapfts-4.12.0.tgz", + "integrity": "sha512-hNKRG4eLYceuJuqDDx7Uqsi8p3j5k83gNKSo2qnUOTiiU03sCQOjXxOqCXDbzRcuDFyK94+1PBIpotK4NoxIjw==", + "dev": true, + "dependencies": { + "@apidevtools/swagger-parser": "^10.1.0", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "swagger2openapi": "^7.0.8", + "typescript": "^5.2.2" + }, + "bin": { + "oazapfts": "lib/codegen/cli.js" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -11183,6 +11800,13 @@ "node": ">=8" } }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "dev": true, + "peer": true + }, "node_modules/openapi-typescript": { "version": "6.7.3", "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-6.7.3.tgz", @@ -11229,6 +11853,12 @@ "node": ">= 0.8.0" } }, + "node_modules/outvariant": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.2.tgz", + "integrity": "sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==", + "dev": true + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -11461,6 +12091,12 @@ "node": "14 || >=16.14" } }, + "node_modules/path-to-regexp": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "dev": true + }, "node_modules/path-type": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", @@ -12590,6 +13226,15 @@ "node": ">=4" } }, + "node_modules/reftools": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", + "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==", + "dev": true, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, "node_modules/regexp-tree": { "version": "0.1.27", "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", @@ -13288,6 +13933,60 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, + "dependencies": { + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", + "dev": true, + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", + "dev": true + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -13524,6 +14223,12 @@ "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", "dev": true }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, "node_modules/ssri": { "version": "10.0.5", "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", @@ -13573,6 +14278,12 @@ "queue-tick": "^1.0.1" } }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -14250,6 +14961,42 @@ "url": "https://opencollective.com/svgo" } }, + "node_modules/swagger2openapi": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", + "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==", + "dev": true, + "dependencies": { + "call-me-maybe": "^1.0.1", + "node-fetch": "^2.6.1", + "node-fetch-h2": "^2.3.0", + "node-readfiles": "^0.2.0", + "oas-kit-common": "^1.0.8", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "oas-validator": "^5.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "boast": "boast.js", + "oas-validate": "oas-validate.js", + "swagger2openapi": "swagger2openapi.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/swagger2openapi/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/system-architecture": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/system-architecture/-/system-architecture-0.1.0.tgz", diff --git a/package.json b/package.json index 2feb108..ed60ec7 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,11 @@ "lint:fix": "eslint --fix --ext .js,.ts,.vue --ignore-path .gitignore .", "test": "npx nuxi test", "openapi:traq": "npx openapi-typescript https://raw.githubusercontent.com/traPtitech/traQ/master/docs/v3-api.yaml --output ./composables/type-fetch/traq/openapi.ts", - "openapi:anke-to": "npx openapi-typescript https://raw.githubusercontent.com/traPtitech/anke-to/main/docs/swagger/swagger.yaml --output ./composables/type-fetch/anke-to/openapi.ts" + "openapi:anke-to": "npx openapi-typescript https://raw.githubusercontent.com/traPtitech/anke-to/main/docs/swagger/swagger.yaml --output ./composables/type-fetch/anke-to/openapi.ts", + "gen:api-mock": "msw-auto-mock https://raw.githubusercontent.com/traPtitech/anke-to/main/docs/swagger/swagger.yaml -o ./mocks/handlers.ts --base-url http://localhost:3000/api" }, "devDependencies": { + "@faker-js/faker": "^8.4.1", "@nuxt/devtools": "latest", "@nuxt/test-utils": "^3.9.0", "@nuxtjs/eslint-config-typescript": "^12.1.0", @@ -33,6 +35,8 @@ "eslint-plugin-unused-imports": "^3.0.0", "eslint-plugin-vue": "^9.19.2", "happy-dom": "^12.10.3", + "msw": "^2.2.14", + "msw-auto-mock": "^0.18.0", "nuxt": "^3.8.2", "nuxt-icon": "^0.6.7", "nuxt-primevue": "^0.2.2", @@ -56,5 +60,10 @@ }, "dependencies": { "js-sha256": "^0.10.1" + }, + "msw": { + "workerDirectory": [ + "public" + ] } -} +} \ No newline at end of file diff --git a/plugins/00.msw.client.ts b/plugins/00.msw.client.ts new file mode 100644 index 0000000..e56ea0b --- /dev/null +++ b/plugins/00.msw.client.ts @@ -0,0 +1,16 @@ +import { setupWorker } from 'msw/browser'; +import { handlers } from '~/mocks/handlers'; + +export default defineNuxtPlugin(async () => { + if (process.env.NODE_ENV === 'development') { + const worker = setupWorker(...handlers); + await worker.start({ + onUnhandledRequest(req, print) { + if (req.url.includes('/_nuxt')) { + return; + } + print.warning(); + }, + }); + } +}); diff --git a/public/mockServiceWorker.js b/public/mockServiceWorker.js new file mode 100644 index 0000000..e891a68 --- /dev/null +++ b/public/mockServiceWorker.js @@ -0,0 +1,284 @@ +/* eslint-disable */ +/* tslint:disable */ + +/** + * Mock Service Worker. + * @see https://github.com/mswjs/msw + * - Please do NOT modify this file. + * - Please do NOT serve this file on production. + */ + +const PACKAGE_VERSION = '2.2.14' +const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423' +const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') +const activeClientIds = new Set() + +self.addEventListener('install', function () { + self.skipWaiting() +}) + +self.addEventListener('activate', function (event) { + event.waitUntil(self.clients.claim()) +}) + +self.addEventListener('message', async function (event) { + const clientId = event.source.id + + if (!clientId || !self.clients) { + return + } + + const client = await self.clients.get(clientId) + + if (!client) { + return + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }) + + switch (event.data) { + case 'KEEPALIVE_REQUEST': { + sendToClient(client, { + type: 'KEEPALIVE_RESPONSE', + }) + break + } + + case 'INTEGRITY_CHECK_REQUEST': { + sendToClient(client, { + type: 'INTEGRITY_CHECK_RESPONSE', + payload: { + packageVersion: PACKAGE_VERSION, + checksum: INTEGRITY_CHECKSUM, + }, + }) + break + } + + case 'MOCK_ACTIVATE': { + activeClientIds.add(clientId) + + sendToClient(client, { + type: 'MOCKING_ENABLED', + payload: true, + }) + break + } + + case 'MOCK_DEACTIVATE': { + activeClientIds.delete(clientId) + break + } + + case 'CLIENT_CLOSED': { + activeClientIds.delete(clientId) + + const remainingClients = allClients.filter((client) => { + return client.id !== clientId + }) + + // Unregister itself when there are no more clients + if (remainingClients.length === 0) { + self.registration.unregister() + } + + break + } + } +}) + +self.addEventListener('fetch', function (event) { + const { request } = event + + // Bypass navigation requests. + if (request.mode === 'navigate') { + return + } + + // Opening the DevTools triggers the "only-if-cached" request + // that cannot be handled by the worker. Bypass such requests. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + return + } + + // Bypass all requests when there are no active clients. + // Prevents the self-unregistered worked from handling requests + // after it's been deleted (still remains active until the next reload). + if (activeClientIds.size === 0) { + return + } + + // Generate unique request ID. + const requestId = crypto.randomUUID() + event.respondWith(handleRequest(event, requestId)) +}) + +async function handleRequest(event, requestId) { + const client = await resolveMainClient(event) + const response = await getResponse(event, client, requestId) + + // Send back the response clone for the "response:*" life-cycle events. + // Ensure MSW is active and ready to handle the message, otherwise + // this message will pend indefinitely. + if (client && activeClientIds.has(client.id)) { + ;(async function () { + const responseClone = response.clone() + + sendToClient( + client, + { + type: 'RESPONSE', + payload: { + requestId, + isMockedResponse: IS_MOCKED_RESPONSE in response, + type: responseClone.type, + status: responseClone.status, + statusText: responseClone.statusText, + body: responseClone.body, + headers: Object.fromEntries(responseClone.headers.entries()), + }, + }, + [responseClone.body], + ) + })() + } + + return response +} + +// Resolve the main client for the given event. +// Client that issues a request doesn't necessarily equal the client +// that registered the worker. It's with the latter the worker should +// communicate with during the response resolving phase. +async function resolveMainClient(event) { + const client = await self.clients.get(event.clientId) + + if (client?.frameType === 'top-level') { + return client + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }) + + return allClients + .filter((client) => { + // Get only those clients that are currently visible. + return client.visibilityState === 'visible' + }) + .find((client) => { + // Find the client ID that's recorded in the + // set of clients that have registered the worker. + return activeClientIds.has(client.id) + }) +} + +async function getResponse(event, client, requestId) { + const { request } = event + + // Clone the request because it might've been already used + // (i.e. its body has been read and sent to the client). + const requestClone = request.clone() + + function passthrough() { + const headers = Object.fromEntries(requestClone.headers.entries()) + + // Remove internal MSW request header so the passthrough request + // complies with any potential CORS preflight checks on the server. + // Some servers forbid unknown request headers. + delete headers['x-msw-intention'] + + return fetch(requestClone, { headers }) + } + + // Bypass mocking when the client is not active. + if (!client) { + return passthrough() + } + + // Bypass initial page load requests (i.e. static assets). + // The absence of the immediate/parent client in the map of the active clients + // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet + // and is not ready to handle requests. + if (!activeClientIds.has(client.id)) { + return passthrough() + } + + // Notify the client that a request has been intercepted. + const requestBuffer = await request.arrayBuffer() + const clientMessage = await sendToClient( + client, + { + type: 'REQUEST', + payload: { + id: requestId, + url: request.url, + mode: request.mode, + method: request.method, + headers: Object.fromEntries(request.headers.entries()), + cache: request.cache, + credentials: request.credentials, + destination: request.destination, + integrity: request.integrity, + redirect: request.redirect, + referrer: request.referrer, + referrerPolicy: request.referrerPolicy, + body: requestBuffer, + keepalive: request.keepalive, + }, + }, + [requestBuffer], + ) + + switch (clientMessage.type) { + case 'MOCK_RESPONSE': { + return respondWithMock(clientMessage.data) + } + + case 'PASSTHROUGH': { + return passthrough() + } + } + + return passthrough() +} + +function sendToClient(client, message, transferrables = []) { + return new Promise((resolve, reject) => { + const channel = new MessageChannel() + + channel.port1.onmessage = (event) => { + if (event.data && event.data.error) { + return reject(event.data.error) + } + + resolve(event.data) + } + + client.postMessage( + message, + [channel.port2].concat(transferrables.filter(Boolean)), + ) + }) +} + +async function respondWithMock(response) { + // Setting response status code to 0 is a no-op. + // However, when responding with a "Response.error()", the produced Response + // instance will have status code set to 0. Since it's not possible to create + // a Response instance with status code 0, handle that use-case separately. + if (response.status === 0) { + return Response.error() + } + + const mockedResponse = new Response(response.body, response) + + Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, { + value: true, + enumerable: true, + }) + + return mockedResponse +}