diff --git a/.eslintrc b/.eslintrc index 0647dd7..bf9b15c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -29,9 +29,14 @@ "allowSeparatedGroups": true }, ], - "import/no-unresolved": "error", - "import/order": [ + "import/no-unresolved": [ "error", + { + "ignore": ["^msw/.+"], + } + ], + "import/order": [ + "warn", { "groups": [ "builtin", diff --git a/.prettierrc b/.prettierrc index b052136..dcd6331 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,6 +1,6 @@ { "semi": false, - "trailingComma": "none", + "trailingComma": "all", "singleQuote": false, "tabWidth": 4, "arrowParens": "avoid", diff --git a/README.md b/README.md index 989a40d..4ed55d8 100644 --- a/README.md +++ b/README.md @@ -31,15 +31,15 @@ export const config: VendureConfig = { shortCodeType: "SHORTCODE_TYPE", passkey: "YOUR_PASSKEY", environment: "APP_ENVIRONMENT", - vendureHost: "https://yourvendurestore.com" - }) - ] + vendureHost: "https://yourvendureserver.com", + }), + ], } ``` 2. Start the server and navigate to `Settings > Payment methods`. Add a new payment method, selecting `Lipa na Mpesa Online` as the handler. -> Note: Select the 'Check whether Mpesa supports the payment' eligibility checker when creating the payment method. +> Be sure to select the 'Check whether Mpesa supports the payment' eligibility checker when creating the payment method. This plugin consumes the Mpesa Daraja API which currently only supports Safaricom numbers in Kenya. 3. Calling the `addPaymentToOrder` mutation on the storefront with the corresponing payment method code will initiate an STK push to the customer's phone. diff --git a/e2e/config.ts b/e2e/config.ts index eede397..efeee6e 100644 --- a/e2e/config.ts +++ b/e2e/config.ts @@ -10,7 +10,7 @@ const envSchema = z.object({ PASSKEY: z.string(), ENVIRONMENT: z.enum(["sandbox", "live"]), SHORTCODE_TYPE: z.enum(["till", "paybill"]), - VENDURE_HOST: z.string() + VENDURE_HOST: z.string(), }) export const config = envSchema.parse(process.env) diff --git a/e2e/dev-server.ts b/e2e/dev-server.ts index be87204..59a80db 100644 --- a/e2e/dev-server.ts +++ b/e2e/dev-server.ts @@ -6,13 +6,13 @@ import { DefaultLogger, DefaultSearchPlugin, LogLevel, - mergeConfig + mergeConfig, } from "@vendure/core" import { SqljsInitializer, createTestEnvironment, registerInitializer, - testConfig + testConfig, } from "@vendure/testing" import { config } from "./config" @@ -23,18 +23,18 @@ import { MpesaPlugin } from "../src/mpesa.plugin" const devConfig = mergeConfig(testConfig, { dbConnectionOptions: { - synchronize: true + synchronize: true, }, logger: new DefaultLogger({ level: LogLevel.Debug }), plugins: [ AssetServerPlugin.init({ assetUploadDir: path.join(__dirname, "__data__/assets"), - route: "assets" + route: "assets", }), DefaultSearchPlugin, AdminUiPlugin.init({ port: 3050, - route: "admin" + route: "admin", }), MpesaPlugin.init({ consumerKey: config.CONSUMER_KEY, @@ -43,21 +43,21 @@ import { MpesaPlugin } from "../src/mpesa.plugin" shortCode: config.SHORTCODE, passkey: config.PASSKEY, shortCodeType: config.SHORTCODE_TYPE, - vendureHost: config.VENDURE_HOST - }) + vendureHost: config.VENDURE_HOST, + }), ], apiOptions: { shopApiPlayground: true, - adminApiPlayground: true - } + adminApiPlayground: true, + }, }) const { server } = createTestEnvironment(devConfig) await server.init({ initialData: { ...initialData, - shippingMethods: [{ name: "Standard Shipping", price: 500 }] + shippingMethods: [{ name: "Standard Shipping", price: 500 }], }, - productsCsvPath: path.join(__dirname, "product-import.csv") + productsCsvPath: path.join(__dirname, "product-import.csv"), }) })() diff --git a/e2e/initial-data.ts b/e2e/initial-data.ts index ee9371d..b694029 100644 --- a/e2e/initial-data.ts +++ b/e2e/initial-data.ts @@ -13,10 +13,13 @@ export const initialData: InitialData = { filters: [ { code: "facet-value-filter", - args: { facetValueNames: ["computers"], containsAny: false } - } - ] - } + args: { + facetValueNames: ["computers"], + containsAny: false, + }, + }, + ], + }, ], - paymentMethods: [] + paymentMethods: [], } diff --git a/e2e/mocks/handlers.ts b/e2e/mocks/handlers.ts new file mode 100644 index 0000000..1203d25 --- /dev/null +++ b/e2e/mocks/handlers.ts @@ -0,0 +1 @@ +export const handlers = [] diff --git a/e2e/mocks/server.ts b/e2e/mocks/server.ts new file mode 100644 index 0000000..50f96c0 --- /dev/null +++ b/e2e/mocks/server.ts @@ -0,0 +1,5 @@ +import { setupServer } from "msw/node" + +import { handlers } from "./handlers" + +export const server = setupServer(...handlers) diff --git a/package.json b/package.json index 760b252..a90e774 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "eslint-plugin-prettier": "^5.1.3", "husky": "^8.0.0", "lint-staged": "^15.2.1", + "msw": "^2.1.7", "prettier": "^3.2.5", "rimraf": "^5.0.5", "ts-node": "^10.9.2", diff --git a/src/api/callback-webhook.controller.ts b/src/api/callback-webhook.controller.ts index 10b5a02..c6fc89c 100644 --- a/src/api/callback-webhook.controller.ts +++ b/src/api/callback-webhook.controller.ts @@ -3,7 +3,7 @@ import { ChannelService, LanguageCode, Logger, - RequestContext + RequestContext, } from "@vendure/core" import { CALLBACK_URL_ENDPOINT, loggerCtx } from "../constants" @@ -14,7 +14,7 @@ import { STKCallbackPayload } from "../types" export class CallbackWebhookController { constructor( private channelService: ChannelService, - private mpesaService: MpesaService + private mpesaService: MpesaService, ) {} @Post() @@ -22,7 +22,7 @@ export class CallbackWebhookController { const { CheckoutRequestID, ResultCode } = payload.Body.stkCallback Logger.info( `Mpesa Callback ${CheckoutRequestID}, status: ${ResultCode}`, - loggerCtx + loggerCtx, ) const ctx = await this.createRequestContext() @@ -36,7 +36,7 @@ export class CallbackWebhookController { isAuthorized: true, authorizedAsOwnerOnly: false, channel, - languageCode: LanguageCode.en + languageCode: LanguageCode.en, }) } } diff --git a/src/api/mpesa-shop.resolver.ts b/src/api/mpesa-shop.resolver.ts index 52a7af4..aecbc25 100644 --- a/src/api/mpesa-shop.resolver.ts +++ b/src/api/mpesa-shop.resolver.ts @@ -10,11 +10,11 @@ export class MpesaShopResolver { @Mutation() async verifyMpesaTransaction( @Ctx() ctx: RequestContext, - @Args() args: { transactionId: string } + @Args() args: { transactionId: string }, ): Promise { const isSuccessful = await this.mpesaService.verifyMpesaPayment( ctx, - args.transactionId + args.transactionId, ) return isSuccessful } diff --git a/src/config/mpesa-eligibility-checker.ts b/src/config/mpesa-eligibility-checker.ts index 2749b9e..34fb453 100644 --- a/src/config/mpesa-eligibility-checker.ts +++ b/src/config/mpesa-eligibility-checker.ts @@ -1,7 +1,7 @@ import { LanguageCode, Logger, - PaymentMethodEligibilityChecker + PaymentMethodEligibilityChecker, } from "@vendure/core" import { loggerCtx } from "../constants" @@ -12,8 +12,8 @@ export const mpesaEligibilityChecker = new PaymentMethodEligibilityChecker({ description: [ { languageCode: LanguageCode.en, - value: "Check whether Mpesa supports the payment" - } + value: "Check whether Mpesa supports the payment", + }, ], args: {}, check: async (_, order) => { @@ -27,7 +27,7 @@ export const mpesaEligibilityChecker = new PaymentMethodEligibilityChecker({ if (!customerPhoneNumber) { Logger.info( "Could not get valid phone number from order", - loggerCtx + loggerCtx, ) return false } @@ -36,11 +36,11 @@ export const mpesaEligibilityChecker = new PaymentMethodEligibilityChecker({ if (!isMpesaNumber) { Logger.info( `Phone number ${customerPhoneNumber} is not a Safaricom number`, - loggerCtx + loggerCtx, ) return false } return true - } + }, }) diff --git a/src/config/mpesa.handler.ts b/src/config/mpesa.handler.ts index 874a16e..c6d3004 100644 --- a/src/config/mpesa.handler.ts +++ b/src/config/mpesa.handler.ts @@ -2,7 +2,7 @@ import { CreatePaymentResult, Injector, LanguageCode, - PaymentMethodHandler + PaymentMethodHandler, } from "@vendure/core" import { MpesaService } from "../service/mpesa.service" @@ -13,7 +13,7 @@ let mpesaService: MpesaService export const mpesaPaymentMethodHandler = new PaymentMethodHandler({ code: "mpesa", description: [ - { languageCode: LanguageCode.en, value: "Lipa na Mpesa Online" } + { languageCode: LanguageCode.en, value: "Lipa na Mpesa Online" }, ], args: {}, init(injector: Injector) { @@ -28,26 +28,26 @@ export const mpesaPaymentMethodHandler = new PaymentMethodHandler({ const result = await mpesaService.initiateStkPush( amountInShillings, phoneNumber, - order.code + order.code, ) if (!result) { return { amount: order.totalWithTax, state: "Declined", - errorMessage: "Could not initiate Mpesa payment." + errorMessage: "Could not initiate Mpesa payment.", } } return { amount: order.totalWithTax, state: "Authorized", - transactionId: result.CheckoutRequestID + transactionId: result.CheckoutRequestID, } }, settlePayment: async () => { return { - success: true + success: true, } - } + }, }) diff --git a/src/mpesa.plugin.ts b/src/mpesa.plugin.ts index 135f1a7..90eba10 100644 --- a/src/mpesa.plugin.ts +++ b/src/mpesa.plugin.ts @@ -63,24 +63,24 @@ export interface MpesaPluginOptions { controllers: [CallbackWebhookController], configuration: config => { config.paymentOptions.paymentMethodHandlers.push( - mpesaPaymentMethodHandler + mpesaPaymentMethodHandler, ) config.paymentOptions.paymentMethodEligibilityCheckers?.push( - mpesaEligibilityChecker + mpesaEligibilityChecker, ) return config }, shopApiExtensions: { schema: shopApiExtensions, - resolvers: [MpesaShopResolver] + resolvers: [MpesaShopResolver], }, providers: [ { provide: MPESA_PLUGIN_INIT_OPTIONS, - useFactory: () => MpesaPlugin.options + useFactory: () => MpesaPlugin.options, }, - MpesaService - ] + MpesaService, + ], }) export class MpesaPlugin { static options: MpesaPluginOptions diff --git a/src/service/mpesa.service.ts b/src/service/mpesa.service.ts index 9d952e4..8080812 100644 --- a/src/service/mpesa.service.ts +++ b/src/service/mpesa.service.ts @@ -4,7 +4,7 @@ import { OrderService, Payment, RequestContext, - TransactionalConnection + TransactionalConnection, } from "@vendure/core" import axios, { AxiosInstance } from "axios" @@ -13,7 +13,7 @@ import { LIVE_BASE_URL, MPESA_PLUGIN_INIT_OPTIONS, SANDBOX_BASE_URL, - loggerCtx + loggerCtx, } from "../constants" import { MpesaPluginOptions } from "../mpesa.plugin" import { STKPushResponse, STKStatusResponse, TokenResponse } from "../types" @@ -27,13 +27,13 @@ export class MpesaService { @Inject(MPESA_PLUGIN_INIT_OPTIONS) private pluginOptions: MpesaPluginOptions, private connection: TransactionalConnection, - private orderService: OrderService + private orderService: OrderService, ) {} async initiateStkPush( amount: number, phoneNumber: string, - orderCode: string + orderCode: string, ) { const client = await this.getRequestClient() @@ -58,8 +58,8 @@ export class MpesaService { PhoneNumber: phoneNumber, CallBackURL: this.getCallBackUrl(), AccountReference: orderCode, - TransactionDesc: "Vendure Order Payment" - } + TransactionDesc: "Vendure Order Payment", + }, ) return data @@ -82,8 +82,8 @@ export class MpesaService { BusinessShortCode: shortCode, Password: password, Timestamp: timestamp, - CheckoutRequestID: transactionId - } + CheckoutRequestID: transactionId, + }, ) const isSuccessful = @@ -93,7 +93,7 @@ export class MpesaService { } catch (err) { Logger.error( `Couldn't query transaction ${transactionId} status`, - loggerCtx + loggerCtx, ) return false } @@ -118,7 +118,7 @@ export class MpesaService { if (isTransactionSuccessful) { Logger.info( `Transaction ${transactionId} was successful`, - loggerCtx + loggerCtx, ) if (payment) { @@ -127,7 +127,7 @@ export class MpesaService { } else { Logger.info( `Transaction ${transactionId} was not successful`, - loggerCtx + loggerCtx, ) if (payment) { await this.orderService.cancelPayment(ctx, payment.id) @@ -160,7 +160,7 @@ export class MpesaService { private getTransactionPassword(timestamp: string): string { const { shortCode, passkey } = this.pluginOptions return Buffer.from(`${shortCode}${passkey}${timestamp}`).toString( - "base64" + "base64", ) } @@ -179,7 +179,7 @@ export class MpesaService { try { const { data } = await axios.get(url, { - headers: { Authorization: auth } + headers: { Authorization: auth }, }) this._accessToken = data.access_token @@ -187,14 +187,14 @@ export class MpesaService { this._accessTokenExpiryDate.setSeconds( this._accessTokenExpiryDate.getSeconds() + parseInt(data.expires_in) - - 60 + 60, ) return data.access_token } catch (err) { Logger.error( "Could not authenticate to the Mpesa API. Please check your consumer key, secret and environment configuration.", - loggerCtx + loggerCtx, ) return "" } @@ -205,26 +205,26 @@ export class MpesaService { return axios.create({ baseURL: `${this.getBaseUrl()}/mpesa`, headers: { - Authorization: `Bearer ${accessToken}` - } + Authorization: `Bearer ${accessToken}`, + }, }) } private async getPaymentByTransactionId( ctx: RequestContext, - transactionId: string + transactionId: string, ): Promise { const payment = await this.connection .getRepository(ctx, Payment) .findOne({ where: { transactionId }, - relations: ["order", "order.payments", "refunds"] + relations: ["order", "order.payments", "refunds"], }) if (!payment) { Logger.error( `There isn't a payment related with the transaction ID ${transactionId}`, - loggerCtx + loggerCtx, ) return } diff --git a/src/util/phone-utils.test.ts b/src/util/phone-utils.test.ts index 796ec15..6ad97e1 100644 --- a/src/util/phone-utils.test.ts +++ b/src/util/phone-utils.test.ts @@ -3,7 +3,7 @@ import { Order } from "@vendure/core" import { formatPhoneNumber, getPhoneNumberFromOrder, - isSafaricomNumber + isSafaricomNumber, } from "./phone-utils" describe("phone-utils", () => { @@ -23,14 +23,14 @@ describe("phone-utils", () => { it("gets phone number from order in correct order", () => { const order = { customer: { - phoneNumber: "0714345678" + phoneNumber: "0714345678", }, billingAddress: { - phoneNumber: "0712345678" + phoneNumber: "0712345678", }, shippingAddress: { - phoneNumber: "0713345678" - } + phoneNumber: "0713345678", + }, } as Order expect(getPhoneNumberFromOrder(order)).toBe("254712345678") }) diff --git a/src/util/phone-utils.ts b/src/util/phone-utils.ts index 397b92a..8f5f89a 100644 --- a/src/util/phone-utils.ts +++ b/src/util/phone-utils.ts @@ -6,7 +6,7 @@ export function formatPhoneNumber(number: string) { const { countryCallingCode, nationalNumber } = parsePhoneNumber( number, - "KE" + "KE", ) return `${countryCallingCode}${nationalNumber}` } diff --git a/yarn.lock b/yarn.lock index d64fc68..14d9d38 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1470,6 +1470,20 @@ dependencies: tslib "^1.9.0" +"@bundled-es-modules/cookie@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz#c3b82703969a61cf6a46e959a012b2c257f6b164" + integrity sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw== + dependencies: + cookie "^0.5.0" + +"@bundled-es-modules/statuses@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz#761d10f44e51a94902c4da48675b71a76cc98872" + integrity sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg== + dependencies: + statuses "^2.0.1" + "@cds/city@^1.1.0": version "1.1.0" resolved "https://registry.npmjs.org/@cds/city/-/city-1.1.0.tgz" @@ -2506,6 +2520,23 @@ dependencies: make-plural "^7.0.0" +"@mswjs/cookies@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@mswjs/cookies/-/cookies-1.1.0.tgz#1528eb43630caf83a1d75d5332b30e75e9bb1b5b" + integrity sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw== + +"@mswjs/interceptors@^0.25.16": + version "0.25.16" + resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.25.16.tgz#7955fbb8da479bc691df117dd4c8d889e507ecc2" + integrity sha512-8QC8JyKztvoGAdPgyZy49c9vSHHAZjHagwl4RY9E8carULk8ym3iTaiawrT1YoLF/qb449h48f71XDPgkUSOUg== + 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" + "@nestjs/apollo@^12.0.7": version "12.0.11" resolved "https://registry.npmjs.org/@nestjs/apollo/-/apollo-12.0.11.tgz" @@ -2715,6 +2746,24 @@ consola "^2.15.0" node-fetch "^2.6.1" +"@open-draft/deferred-promise@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" + integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA== + +"@open-draft/logger@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@open-draft/logger/-/logger-0.3.0.tgz#2b3ab1242b360aa0adb28b85f5d7da1c133a0954" + integrity sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ== + dependencies: + is-node-process "^1.2.0" + outvariant "^1.4.0" + +"@open-draft/until@^2.0.0", "@open-draft/until@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-2.1.0.tgz#0acf32f470af2ceaf47f095cdecd40d68666efda" + integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" @@ -2981,6 +3030,11 @@ dependencies: "@types/node" "*" +"@types/cookie@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" + integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== + "@types/eslint-scope@^3.7.3": version "3.7.7" resolved "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz" @@ -3164,6 +3218,11 @@ dependencies: "@types/node" "*" +"@types/statuses@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/statuses/-/statuses-2.0.4.tgz#041143ba4a918e8f080f8b0ffbe3d4cb514e2315" + integrity sha512-eqNDvZsCNY49OAXB0Firg/Sc2BgoWsntsLUdybGFOhAfCD6QJ2n9HXUIHGqt5qjrxmMv4wS8WLAw43ZkKcJ8Pw== + "@types/trusted-types@^2.0.2": version "2.0.7" resolved "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz" @@ -4463,6 +4522,21 @@ chokidar@3.5.3, "chokidar@>=3.0.0 <4.0.0", chokidar@^3.0.0, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chokidar@^3.4.2: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chownr@^1.1.1: version "1.1.4" resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz" @@ -4747,7 +4821,7 @@ cookie-signature@1.0.6: resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.5.0: +cookie@0.5.0, cookie@^0.5.0: version "0.5.0" resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== @@ -6419,6 +6493,11 @@ graphql@16.8.0: resolved "https://registry.npmjs.org/graphql/-/graphql-16.8.0.tgz" integrity sha512-0oKGaR+y3qcS5mCu1vb7KG+a89vjn06C7Ihq/dDl3jA+A8B3TKomvi3CiEcVLJQGalbu8F52LxkOym7U5sSfbg== +graphql@^16.8.1: + version "16.8.1" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" + integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw== + guess-parser@0.4.22: version "0.4.22" resolved "https://registry.npmjs.org/guess-parser/-/guess-parser-0.4.22.tgz" @@ -6501,6 +6580,11 @@ hdr-histogram-percentiles-obj@^3.0.0: resolved "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz" integrity sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw== +headers-polyfill@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-4.0.2.tgz#9115a76eee3ce8fbf95b6e3c6bf82d936785b44a" + integrity sha512-EWGTfnTqAO2L/j5HZgoM/3z82L7necsJ0pO9Tp0X1wil3PDLrkypTBRgVO2ExehEEvUycejZD3FuRaXpZZc3kw== + highlight.js@^10.7.1: version "10.7.3" resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz" @@ -6818,6 +6902,27 @@ inquirer@8.2.4: through "^2.3.6" wrap-ansi "^7.0.0" +inquirer@^8.2.0: + version "8.2.6" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.6.tgz#733b74888195d8d400a67ac332011b5fae5ea562" + integrity sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg== + dependencies: + ansi-escapes "^4.2.1" + chalk "^4.1.1" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.21" + mute-stream "0.0.8" + ora "^5.4.1" + run-async "^2.4.0" + rxjs "^7.5.5" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + wrap-ansi "^6.0.1" + internal-slot@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" @@ -6960,6 +7065,11 @@ is-negative-zero@^2.0.2: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== +is-node-process@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134" + integrity sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw== + is-number-object@^1.0.4: version "1.0.7" resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" @@ -8038,6 +8148,30 @@ ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +msw@^2.1.7: + version "2.1.7" + resolved "https://registry.yarnpkg.com/msw/-/msw-2.1.7.tgz#0d7872af286cc5f6621dc40a496f8da8308cd198" + integrity sha512-yTIYqEMqDSrdbVMrfmqP6rTKQsnIbglTvVmAHDWwNegyXPXRcV+RjsaFEqubRS266gwWCDLm9YdOkWSKLdDvJQ== + dependencies: + "@bundled-es-modules/cookie" "^2.0.0" + "@bundled-es-modules/statuses" "^1.0.1" + "@mswjs/cookies" "^1.1.0" + "@mswjs/interceptors" "^0.25.16" + "@open-draft/until" "^2.1.0" + "@types/cookie" "^0.6.0" + "@types/statuses" "^2.0.4" + chalk "^4.1.2" + chokidar "^3.4.2" + graphql "^16.8.1" + headers-polyfill "^4.0.2" + inquirer "^8.2.0" + 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" + multer@1.4.4-lts.1: version "1.4.4-lts.1" resolved "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz" @@ -8523,6 +8657,11 @@ outdent@^0.5.0: resolved "https://registry.yarnpkg.com/outdent/-/outdent-0.5.0.tgz#9e10982fdc41492bb473ad13840d22f9655be2ff" integrity sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q== +outvariant@^1.2.1, outvariant@^1.4.0, outvariant@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.2.tgz#f54f19240eeb7f15b28263d5147405752d8e2066" + integrity sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ== + p-filter@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-filter/-/p-filter-2.1.0.tgz#1b1472562ae7a0f742f0f3d3d3718ea66ff9c09c" @@ -8748,6 +8887,11 @@ path-to-regexp@3.2.0: resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz" integrity sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA== +path-to-regexp@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5" + integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" @@ -10126,7 +10270,7 @@ stackback@0.0.2: resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== -statuses@2.0.1: +statuses@2.0.1, statuses@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== @@ -10161,6 +10305,11 @@ streamx@^2.15.0: fast-fifo "^1.1.0" queue-tick "^1.0.1" +strict-event-emitter@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" + integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== + string-argv@0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" @@ -10714,6 +10863,11 @@ type-fest@^3.0.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-3.13.1.tgz#bb744c1f0678bea7543a2d1ec24e83e68e8c8706" integrity sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g== +type-fest@^4.9.0: + version "4.10.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.10.2.tgz#3abdb144d93c5750432aac0d73d3e85fcab45738" + integrity sha512-anpAG63wSpdEbLwOqH8L84urkL6PiVIov3EMmgIhhThevh9aiMQov+6Btx0wldNcvm4wV+e2/Rt1QdDwKHFbHw== + type-is@^1.6.4, type-is@~1.6.18: version "1.6.18" resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" @@ -11344,7 +11498,7 @@ wildcard@^2.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^6.2.0: +wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== @@ -11475,7 +11629,7 @@ yargs-parser@^21.1.1: resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@17.7.2, yargs@^17.2.1, yargs@^17.3.1, yargs@^17.7.1: +yargs@17.7.2, yargs@^17.2.1, yargs@^17.3.1, yargs@^17.7.1, yargs@^17.7.2: version "17.7.2" resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==