diff --git a/.gitignore b/.gitignore index 8f901a885..9dd897367 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ node_modules/ build/ /.idea /.vscode +/.log /integration/*/pbjs.js /integration/*/pbjs.d.ts coverage/ diff --git a/integration/async-iterable-services/simple.bin b/integration/async-iterable-services/simple.bin index c79a53287..51973c2d8 100644 Binary files a/integration/async-iterable-services/simple.bin and b/integration/async-iterable-services/simple.bin differ diff --git a/integration/async-iterable-services/simple.proto b/integration/async-iterable-services/simple.proto index 6456036f0..73d6a5180 100644 --- a/integration/async-iterable-services/simple.proto +++ b/integration/async-iterable-services/simple.proto @@ -1,11 +1,19 @@ syntax = "proto3"; - package simple; -service Test { - rpc BidiStreaming(stream TestMessage) returns (stream TestMessage) {} +// Echoer service returns the given message. +service Echoer { + // Echo returns the given message. + rpc Echo(EchoMsg) returns (EchoMsg); + // EchoServerStream is an example of a server -> client one-way stream. + rpc EchoServerStream(EchoMsg) returns (stream EchoMsg); + // EchoClientStream is an example of client->server one-way stream. + rpc EchoClientStream(stream EchoMsg) returns (EchoMsg); + // EchoBidiStream is an example of a two-way stream. + rpc EchoBidiStream(stream EchoMsg) returns (stream EchoMsg); } -message TestMessage { - string value = 1; +// EchoMsg is the message body for Echo. +message EchoMsg { + string body = 1; } diff --git a/integration/async-iterable-services/simple.ts b/integration/async-iterable-services/simple.ts index 8a335f812..7284fb9df 100644 --- a/integration/async-iterable-services/simple.ts +++ b/integration/async-iterable-services/simple.ts @@ -3,31 +3,32 @@ import * as _m0 from 'protobufjs/minimal'; export const protobufPackage = 'simple'; -export interface TestMessage { - value: string; +/** EchoMsg is the message body for Echo. */ +export interface EchoMsg { + body: string; } -function createBaseTestMessage(): TestMessage { - return { value: '' }; +function createBaseEchoMsg(): EchoMsg { + return { body: '' }; } -export const TestMessage = { - encode(message: TestMessage, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.value !== '') { - writer.uint32(10).string(message.value); +export const EchoMsg = { + encode(message: EchoMsg, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.body !== '') { + writer.uint32(10).string(message.body); } return writer; }, - decode(input: _m0.Reader | Uint8Array, length?: number): TestMessage { + decode(input: _m0.Reader | Uint8Array, length?: number): EchoMsg { const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseTestMessage(); + const message = createBaseEchoMsg(); while (reader.pos < end) { const tag = reader.uint32(); switch (tag >>> 3) { case 1: - message.value = reader.string(); + message.body = reader.string(); break; default: reader.skipType(tag & 7); @@ -38,70 +39,99 @@ export const TestMessage = { }, // encodeTransform encodes a source of message objects. - // Transform + // Transform async *encodeTransform( - source: AsyncIterable | Iterable + source: AsyncIterable | Iterable ): AsyncIterable { for await (const pkt of source) { if (Array.isArray(pkt)) { for (const p of pkt) { - yield* [TestMessage.encode(p).finish()]; + yield* [EchoMsg.encode(p).finish()]; } } else { - yield* [TestMessage.encode(pkt).finish()]; + yield* [EchoMsg.encode(pkt).finish()]; } } }, // decodeTransform decodes a source of encoded messages. - // Transform + // Transform async *decodeTransform( source: AsyncIterable | Iterable - ): AsyncIterable { + ): AsyncIterable { for await (const pkt of source) { if (Array.isArray(pkt)) { for (const p of pkt) { - yield* [TestMessage.decode(p)]; + yield* [EchoMsg.decode(p)]; } } else { - yield* [TestMessage.decode(pkt)]; + yield* [EchoMsg.decode(pkt)]; } } }, - fromJSON(object: any): TestMessage { + fromJSON(object: any): EchoMsg { return { - value: isSet(object.value) ? String(object.value) : '', + body: isSet(object.body) ? String(object.body) : '', }; }, - toJSON(message: TestMessage): unknown { + toJSON(message: EchoMsg): unknown { const obj: any = {}; - message.value !== undefined && (obj.value = message.value); + message.body !== undefined && (obj.body = message.body); return obj; }, - fromPartial, I>>(object: I): TestMessage { - const message = createBaseTestMessage(); - message.value = object.value ?? ''; + fromPartial, I>>(object: I): EchoMsg { + const message = createBaseEchoMsg(); + message.body = object.body ?? ''; return message; }, }; -export interface Test { - BidiStreaming(request: AsyncIterable): AsyncIterable; +/** Echoer service returns the given message. */ +export interface Echoer { + /** Echo returns the given message. */ + Echo(request: EchoMsg): Promise; + /** EchoServerStream is an example of a server -> client one-way stream. */ + EchoServerStream(request: EchoMsg): AsyncIterable; + /** EchoClientStream is an example of client->server one-way stream. */ + EchoClientStream(request: AsyncIterable): Promise; + /** EchoBidiStream is an example of a two-way stream. */ + EchoBidiStream(request: AsyncIterable): AsyncIterable; } -export class TestClientImpl implements Test { +export class EchoerClientImpl implements Echoer { private readonly rpc: Rpc; constructor(rpc: Rpc) { this.rpc = rpc; - this.BidiStreaming = this.BidiStreaming.bind(this); + this.Echo = this.Echo.bind(this); + this.EchoServerStream = this.EchoServerStream.bind(this); + this.EchoClientStream = this.EchoClientStream.bind(this); + this.EchoBidiStream = this.EchoBidiStream.bind(this); } - BidiStreaming(request: AsyncIterable): AsyncIterable { - const data = TestMessage.encodeTransform(request); - const result = this.rpc.bidirectionalStreamingRequest('simple.Test', 'BidiStreaming', data); - return TestMessage.decodeTransform(result); + Echo(request: EchoMsg): Promise { + const data = EchoMsg.encode(request).finish(); + const promise = this.rpc.request('simple.Echoer', 'Echo', data); + return promise.then((data) => EchoMsg.decode(new _m0.Reader(data))); + } + + EchoServerStream(request: EchoMsg): AsyncIterable { + const data = EchoMsg.encode(request).finish(); + const result = this.rpc.serverStreamingRequest('simple.Echoer', 'EchoServerStream', data); + return EchoMsg.decodeTransform(result); + } + + EchoClientStream(request: AsyncIterable): Promise { + const data = EchoMsg.encodeTransform(request); + const promise = this.rpc.clientStreamingRequest('simple.Echoer', 'EchoClientStream', data); + return promise.then((data) => EchoMsg.decode(new _m0.Reader(data))); + } + + EchoBidiStream(request: AsyncIterable): AsyncIterable { + const data = EchoMsg.encodeTransform(request); + const result = this.rpc.bidirectionalStreamingRequest('simple.Echoer', 'EchoBidiStream', data); + return EchoMsg.decodeTransform(result); } } diff --git a/integration/grpc-web-promise/.gitignore b/integration/grpc-web-promise/.gitignore new file mode 100644 index 000000000..c795b054e --- /dev/null +++ b/integration/grpc-web-promise/.gitignore @@ -0,0 +1 @@ +build \ No newline at end of file diff --git a/integration/grpc-web-promise/README.md b/integration/grpc-web-promise/README.md new file mode 100644 index 000000000..25db8211f --- /dev/null +++ b/integration/grpc-web-promise/README.md @@ -0,0 +1,21 @@ +`grpc-web` client stream need `WebSocket` transport. + +Because need bundle single `.js` file to browser, so you need to install `webpack toolchain`. + +``` +cd grpc-web +npm install +npx webpack +``` + +Then, use you browser open `index.html` file. + +## server + +Running the rpc server. + +``` +cd grpc-web-go-server +./build.sh +GRPC_GO_LOG_SEVERITY_LEVEL=info GRPC_GO_LOG_VERBOSITY_LEVEL=0 ./grpc-web-go-server +``` diff --git a/integration/grpc-web-promise/client-ts.ts b/integration/grpc-web-promise/client-ts.ts new file mode 100755 index 000000000..7b3ef2a15 --- /dev/null +++ b/integration/grpc-web-promise/client-ts.ts @@ -0,0 +1,94 @@ +#!/usr/bin/env node + +import { DashAPICredsClientImpl, DashStateClientImpl, GrpcWebImpl, DashUserSettingsState } from './example'; +import { grpc } from '@improbable-eng/grpc-web'; + +const defTransport = grpc.CrossBrowserHttpTransport({ withCredentials: false }); +const ws = grpc.WebsocketTransport(); + +const rpc = new GrpcWebImpl('http://localhost:9090', { + transport: defTransport, + debug: true, + metadata: new grpc.Metadata({ SomeHeader: 'bar' }), +}); + +const client = new DashStateClientImpl(rpc); +const creds = new DashAPICredsClientImpl(rpc); + +async function main() { + console.log('calling client.UserSettings'); + console.log(await client.UserSettings({})); + + console.log('calling creds.Create'); + const cred = await creds.Create({ description: 'test desc fooo' }); + console.log(cred); + + console.log('calling creds.Delete'); + const del = await creds.Delete({ id: cred.id }); + console.log(del); + + console.log('calling creds.Update'); + try { + await creds.Update({ description: 'test desc2' }); + } catch (e) { + console.log('got expected error', e); + } + + console.log('(server-stream) calling client.ActiveUserSettingsStream'); + const serverStream = await client.ActiveUserSettingsStream({}); + serverStream.on('data', (message) => console.log('(server-stream) message: ', message)); + serverStream.on('end', (status) => console.log('(server-stream) end: ', status)); + serverStream.on('status', (status) => console.log('(server-stream) status: ', status)); + + console.log('(client-stream) calling client.ManyUserSettingsStream'); + const clientStream = await client.ManyUserSettingsStream({ + rpcOptions: { transport: ws }, + }); + // will only receive one message when client stream finish. + clientStream.on('data', (message) => console.log('(client-stream) message: ', message)); + clientStream.on('end', (status) => console.log('(client-stream) end: ', status)); + clientStream.on('status', (status) => console.log('(client-stream) status: ', status)); + await (function () { + return new Promise((resolve, _) => { + let clientStreamCount = 0; + const clientStreanIntervalId = setInterval(() => { + if (clientStreamCount >= 10) { + clientStream.end(); + clearInterval(clientStreanIntervalId); + resolve(true); + return; + } + clientStream.write({ email: 'ping@example.com' }); + clientStreamCount++; + }, 1000); + }); + })(); + + console.log('(client-server bidirectional stream) calling client.ChangeUserSettingsStream'); + const bidirectional = await client.ChangeUserSettingsStream({ + rpcOptions: { transport: ws }, + }); + bidirectional.on('data', (message) => console.log('(bidirectional-stream) message: ', message)); + bidirectional.on('end', (status) => console.log('(bidirectional-stream) end: ', status)); + bidirectional.on('status', (status) => console.log('(bidirectional-stream) status: ', status)); + await (function () { + return new Promise((resolve, _) => { + let bidirectionalCount = 0; + const biDiIntervalId = setInterval(() => { + if (bidirectionalCount >= 10) { + bidirectional.end(); + clearInterval(biDiIntervalId); + resolve(true); + return; + } + bidirectional.write({ email: 'ping@example.com' }); + bidirectionalCount++; + }, 1000); + }); + })(); +} + +main().then( + () => console.log('done'), + (err) => console.log('failed', err) +); diff --git a/integration/grpc-web-promise/example-test.ts b/integration/grpc-web-promise/example-test.ts new file mode 100644 index 000000000..f4abbdc67 --- /dev/null +++ b/integration/grpc-web-promise/example-test.ts @@ -0,0 +1,35 @@ +import { DashStateClientImpl } from './example'; +import { EMPTY } from 'rxjs'; + +describe('grpc-web', () => { + it('at least compiles', () => { + // TODO move the hand-run `client-ts` integration into here, but for now + // at least check that things compile + const rpc = { + unary: jest.fn(), + invoke: jest.fn(), + stream: jest.fn(), + }; + const client = new DashStateClientImpl(rpc); + client.UserSettings({}); + }); + it('binds rpc function', () => { + const rpc = { + unary: jest.fn(), + invoke: jest.fn(), + stream: jest.fn(), + }; + const client = new DashStateClientImpl(rpc); + const userSettings = client.UserSettings; + userSettings({}); + }); + it('throws on client streaming call', () => { + const rpc = { + unary: jest.fn(), + invoke: jest.fn(), + stream: jest.fn(), + }; + const client = new DashStateClientImpl(rpc); + client.ChangeUserSettingsStream({}); + }); +}); diff --git a/integration/grpc-web-promise/example.bin b/integration/grpc-web-promise/example.bin new file mode 100644 index 000000000..39770daa3 Binary files /dev/null and b/integration/grpc-web-promise/example.bin differ diff --git a/integration/grpc-web-promise/example.proto b/integration/grpc-web-promise/example.proto new file mode 100644 index 000000000..1e1cfb922 --- /dev/null +++ b/integration/grpc-web-promise/example.proto @@ -0,0 +1,69 @@ +syntax = "proto3"; + +package rpx; + +service DashState { + rpc UserSettings(Empty) returns (DashUserSettingsState); + rpc ActiveUserSettingsStream(Empty) returns (stream DashUserSettingsState); + rpc ManyUserSettingsStream(stream DashUserSettingsState) returns (DashUserSettingsState); + rpc ChangeUserSettingsStream (stream DashUserSettingsState) returns (stream DashUserSettingsState) {} +} + +message DashFlash { + string msg = 1; + Type type = 2; + + enum Type { + Undefined = 0; + Success = 1; + Warn = 2; + Error = 3; + } +} + +message DashUserSettingsState { + string email = 1; + URLs urls = 6; + repeated DashFlash flashes = 7; + + message URLs { + string connect_google = 1; + string connect_github = 2; + } +} + + +//---------------------- +// API Creds +//---------------------- +service DashAPICreds { + rpc Create(DashAPICredsCreateReq) returns (DashCred); + rpc Update(DashAPICredsUpdateReq) returns (DashCred); + rpc Delete(DashAPICredsDeleteReq) returns (DashCred); +} + +message DashCred { + string description = 2; + string metadata = 3; + string token = 4; + string id = 7; +} + +message DashAPICredsCreateReq { + string description = 1; + string metadata = 2; +} + +message DashAPICredsUpdateReq { + string cred_sid = 1; + string description = 2; + string metadata = 3; + string id = 5; +} + +message DashAPICredsDeleteReq { + string cred_sid = 1; + string id = 3; +} + +message Empty {} diff --git a/integration/grpc-web-promise/example.ts b/integration/grpc-web-promise/example.ts new file mode 100644 index 000000000..389d7617c --- /dev/null +++ b/integration/grpc-web-promise/example.ts @@ -0,0 +1,1100 @@ +/* eslint-disable */ +import { grpc } from '@improbable-eng/grpc-web'; +import { BrowserHeaders } from 'browser-headers'; +import * as _m0 from 'protobufjs/minimal'; + +export const protobufPackage = 'rpx'; + +export interface DashFlash { + msg: string; + type: DashFlash_Type; +} + +export enum DashFlash_Type { + Undefined = 0, + Success = 1, + Warn = 2, + Error = 3, + UNRECOGNIZED = -1, +} + +export function dashFlash_TypeFromJSON(object: any): DashFlash_Type { + switch (object) { + case 0: + case 'Undefined': + return DashFlash_Type.Undefined; + case 1: + case 'Success': + return DashFlash_Type.Success; + case 2: + case 'Warn': + return DashFlash_Type.Warn; + case 3: + case 'Error': + return DashFlash_Type.Error; + case -1: + case 'UNRECOGNIZED': + default: + return DashFlash_Type.UNRECOGNIZED; + } +} + +export function dashFlash_TypeToJSON(object: DashFlash_Type): string { + switch (object) { + case DashFlash_Type.Undefined: + return 'Undefined'; + case DashFlash_Type.Success: + return 'Success'; + case DashFlash_Type.Warn: + return 'Warn'; + case DashFlash_Type.Error: + return 'Error'; + case DashFlash_Type.UNRECOGNIZED: + default: + return 'UNRECOGNIZED'; + } +} + +export interface DashUserSettingsState { + email: string; + urls: DashUserSettingsState_URLs | undefined; + flashes: DashFlash[]; +} + +export interface DashUserSettingsState_URLs { + connectGoogle: string; + connectGithub: string; +} + +export interface DashCred { + description: string; + metadata: string; + token: string; + id: string; +} + +export interface DashAPICredsCreateReq { + description: string; + metadata: string; +} + +export interface DashAPICredsUpdateReq { + credSid: string; + description: string; + metadata: string; + id: string; +} + +export interface DashAPICredsDeleteReq { + credSid: string; + id: string; +} + +export interface Empty {} + +function createBaseDashFlash(): DashFlash { + return { msg: '', type: 0 }; +} + +export const DashFlash = { + encode(message: DashFlash, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.msg !== '') { + writer.uint32(10).string(message.msg); + } + if (message.type !== 0) { + writer.uint32(16).int32(message.type); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): DashFlash { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseDashFlash(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.msg = reader.string(); + break; + case 2: + message.type = reader.int32() as any; + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): DashFlash { + return { + msg: isSet(object.msg) ? String(object.msg) : '', + type: isSet(object.type) ? dashFlash_TypeFromJSON(object.type) : 0, + }; + }, + + toJSON(message: DashFlash): unknown { + const obj: any = {}; + message.msg !== undefined && (obj.msg = message.msg); + message.type !== undefined && (obj.type = dashFlash_TypeToJSON(message.type)); + return obj; + }, + + fromPartial, I>>(object: I): DashFlash { + const message = createBaseDashFlash(); + message.msg = object.msg ?? ''; + message.type = object.type ?? 0; + return message; + }, +}; + +function createBaseDashUserSettingsState(): DashUserSettingsState { + return { email: '', urls: undefined, flashes: [] }; +} + +export const DashUserSettingsState = { + encode(message: DashUserSettingsState, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.email !== '') { + writer.uint32(10).string(message.email); + } + if (message.urls !== undefined) { + DashUserSettingsState_URLs.encode(message.urls, writer.uint32(50).fork()).ldelim(); + } + for (const v of message.flashes) { + DashFlash.encode(v!, writer.uint32(58).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): DashUserSettingsState { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseDashUserSettingsState(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.email = reader.string(); + break; + case 6: + message.urls = DashUserSettingsState_URLs.decode(reader, reader.uint32()); + break; + case 7: + message.flashes.push(DashFlash.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): DashUserSettingsState { + return { + email: isSet(object.email) ? String(object.email) : '', + urls: isSet(object.urls) ? DashUserSettingsState_URLs.fromJSON(object.urls) : undefined, + flashes: Array.isArray(object?.flashes) ? object.flashes.map((e: any) => DashFlash.fromJSON(e)) : [], + }; + }, + + toJSON(message: DashUserSettingsState): unknown { + const obj: any = {}; + message.email !== undefined && (obj.email = message.email); + message.urls !== undefined && + (obj.urls = message.urls ? DashUserSettingsState_URLs.toJSON(message.urls) : undefined); + if (message.flashes) { + obj.flashes = message.flashes.map((e) => (e ? DashFlash.toJSON(e) : undefined)); + } else { + obj.flashes = []; + } + return obj; + }, + + fromPartial, I>>(object: I): DashUserSettingsState { + const message = createBaseDashUserSettingsState(); + message.email = object.email ?? ''; + message.urls = + object.urls !== undefined && object.urls !== null + ? DashUserSettingsState_URLs.fromPartial(object.urls) + : undefined; + message.flashes = object.flashes?.map((e) => DashFlash.fromPartial(e)) || []; + return message; + }, +}; + +function createBaseDashUserSettingsState_URLs(): DashUserSettingsState_URLs { + return { connectGoogle: '', connectGithub: '' }; +} + +export const DashUserSettingsState_URLs = { + encode(message: DashUserSettingsState_URLs, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.connectGoogle !== '') { + writer.uint32(10).string(message.connectGoogle); + } + if (message.connectGithub !== '') { + writer.uint32(18).string(message.connectGithub); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): DashUserSettingsState_URLs { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseDashUserSettingsState_URLs(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.connectGoogle = reader.string(); + break; + case 2: + message.connectGithub = reader.string(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): DashUserSettingsState_URLs { + return { + connectGoogle: isSet(object.connectGoogle) ? String(object.connectGoogle) : '', + connectGithub: isSet(object.connectGithub) ? String(object.connectGithub) : '', + }; + }, + + toJSON(message: DashUserSettingsState_URLs): unknown { + const obj: any = {}; + message.connectGoogle !== undefined && (obj.connectGoogle = message.connectGoogle); + message.connectGithub !== undefined && (obj.connectGithub = message.connectGithub); + return obj; + }, + + fromPartial, I>>(object: I): DashUserSettingsState_URLs { + const message = createBaseDashUserSettingsState_URLs(); + message.connectGoogle = object.connectGoogle ?? ''; + message.connectGithub = object.connectGithub ?? ''; + return message; + }, +}; + +function createBaseDashCred(): DashCred { + return { description: '', metadata: '', token: '', id: '' }; +} + +export const DashCred = { + encode(message: DashCred, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.description !== '') { + writer.uint32(18).string(message.description); + } + if (message.metadata !== '') { + writer.uint32(26).string(message.metadata); + } + if (message.token !== '') { + writer.uint32(34).string(message.token); + } + if (message.id !== '') { + writer.uint32(58).string(message.id); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): DashCred { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseDashCred(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 2: + message.description = reader.string(); + break; + case 3: + message.metadata = reader.string(); + break; + case 4: + message.token = reader.string(); + break; + case 7: + message.id = reader.string(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): DashCred { + return { + description: isSet(object.description) ? String(object.description) : '', + metadata: isSet(object.metadata) ? String(object.metadata) : '', + token: isSet(object.token) ? String(object.token) : '', + id: isSet(object.id) ? String(object.id) : '', + }; + }, + + toJSON(message: DashCred): unknown { + const obj: any = {}; + message.description !== undefined && (obj.description = message.description); + message.metadata !== undefined && (obj.metadata = message.metadata); + message.token !== undefined && (obj.token = message.token); + message.id !== undefined && (obj.id = message.id); + return obj; + }, + + fromPartial, I>>(object: I): DashCred { + const message = createBaseDashCred(); + message.description = object.description ?? ''; + message.metadata = object.metadata ?? ''; + message.token = object.token ?? ''; + message.id = object.id ?? ''; + return message; + }, +}; + +function createBaseDashAPICredsCreateReq(): DashAPICredsCreateReq { + return { description: '', metadata: '' }; +} + +export const DashAPICredsCreateReq = { + encode(message: DashAPICredsCreateReq, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.description !== '') { + writer.uint32(10).string(message.description); + } + if (message.metadata !== '') { + writer.uint32(18).string(message.metadata); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): DashAPICredsCreateReq { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseDashAPICredsCreateReq(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.description = reader.string(); + break; + case 2: + message.metadata = reader.string(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): DashAPICredsCreateReq { + return { + description: isSet(object.description) ? String(object.description) : '', + metadata: isSet(object.metadata) ? String(object.metadata) : '', + }; + }, + + toJSON(message: DashAPICredsCreateReq): unknown { + const obj: any = {}; + message.description !== undefined && (obj.description = message.description); + message.metadata !== undefined && (obj.metadata = message.metadata); + return obj; + }, + + fromPartial, I>>(object: I): DashAPICredsCreateReq { + const message = createBaseDashAPICredsCreateReq(); + message.description = object.description ?? ''; + message.metadata = object.metadata ?? ''; + return message; + }, +}; + +function createBaseDashAPICredsUpdateReq(): DashAPICredsUpdateReq { + return { credSid: '', description: '', metadata: '', id: '' }; +} + +export const DashAPICredsUpdateReq = { + encode(message: DashAPICredsUpdateReq, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.credSid !== '') { + writer.uint32(10).string(message.credSid); + } + if (message.description !== '') { + writer.uint32(18).string(message.description); + } + if (message.metadata !== '') { + writer.uint32(26).string(message.metadata); + } + if (message.id !== '') { + writer.uint32(42).string(message.id); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): DashAPICredsUpdateReq { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseDashAPICredsUpdateReq(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.credSid = reader.string(); + break; + case 2: + message.description = reader.string(); + break; + case 3: + message.metadata = reader.string(); + break; + case 5: + message.id = reader.string(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): DashAPICredsUpdateReq { + return { + credSid: isSet(object.credSid) ? String(object.credSid) : '', + description: isSet(object.description) ? String(object.description) : '', + metadata: isSet(object.metadata) ? String(object.metadata) : '', + id: isSet(object.id) ? String(object.id) : '', + }; + }, + + toJSON(message: DashAPICredsUpdateReq): unknown { + const obj: any = {}; + message.credSid !== undefined && (obj.credSid = message.credSid); + message.description !== undefined && (obj.description = message.description); + message.metadata !== undefined && (obj.metadata = message.metadata); + message.id !== undefined && (obj.id = message.id); + return obj; + }, + + fromPartial, I>>(object: I): DashAPICredsUpdateReq { + const message = createBaseDashAPICredsUpdateReq(); + message.credSid = object.credSid ?? ''; + message.description = object.description ?? ''; + message.metadata = object.metadata ?? ''; + message.id = object.id ?? ''; + return message; + }, +}; + +function createBaseDashAPICredsDeleteReq(): DashAPICredsDeleteReq { + return { credSid: '', id: '' }; +} + +export const DashAPICredsDeleteReq = { + encode(message: DashAPICredsDeleteReq, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.credSid !== '') { + writer.uint32(10).string(message.credSid); + } + if (message.id !== '') { + writer.uint32(26).string(message.id); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): DashAPICredsDeleteReq { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseDashAPICredsDeleteReq(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.credSid = reader.string(); + break; + case 3: + message.id = reader.string(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): DashAPICredsDeleteReq { + return { + credSid: isSet(object.credSid) ? String(object.credSid) : '', + id: isSet(object.id) ? String(object.id) : '', + }; + }, + + toJSON(message: DashAPICredsDeleteReq): unknown { + const obj: any = {}; + message.credSid !== undefined && (obj.credSid = message.credSid); + message.id !== undefined && (obj.id = message.id); + return obj; + }, + + fromPartial, I>>(object: I): DashAPICredsDeleteReq { + const message = createBaseDashAPICredsDeleteReq(); + message.credSid = object.credSid ?? ''; + message.id = object.id ?? ''; + return message; + }, +}; + +function createBaseEmpty(): Empty { + return {}; +} + +export const Empty = { + encode(_: Empty, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Empty { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseEmpty(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(_: any): Empty { + return {}; + }, + + toJSON(_: Empty): unknown { + const obj: any = {}; + return obj; + }, + + fromPartial, I>>(_: I): Empty { + const message = createBaseEmpty(); + return message; + }, +}; + +export interface DashState { + UserSettings(request: DeepPartial, metadata?: grpc.Metadata): Promise; + ActiveUserSettingsStream( + request: DeepPartial, + metadata?: grpc.Metadata + ): Promise>; + ManyUserSettingsStream(options?: { + metadata?: grpc.Metadata; + rpcOptions?: grpc.RpcOptions; + }): Promise, DashUserSettingsState>>; + ChangeUserSettingsStream(options?: { + metadata?: grpc.Metadata; + rpcOptions?: grpc.RpcOptions; + }): Promise, DashUserSettingsState>>; +} + +export class DashStateClientImpl implements DashState { + private readonly rpc: Rpc; + + constructor(rpc: Rpc) { + this.rpc = rpc; + this.UserSettings = this.UserSettings.bind(this); + this.ActiveUserSettingsStream = this.ActiveUserSettingsStream.bind(this); + this.ManyUserSettingsStream = this.ManyUserSettingsStream.bind(this); + this.ChangeUserSettingsStream = this.ChangeUserSettingsStream.bind(this); + } + + UserSettings(request: DeepPartial, metadata?: grpc.Metadata): Promise { + return this.rpc.unary(DashStateUserSettingsDesc, Empty.fromPartial(request), metadata); + } + + ActiveUserSettingsStream( + request: DeepPartial, + metadata?: grpc.Metadata + ): Promise> { + return this.rpc.invoke(DashStateActiveUserSettingsStreamDesc, Empty.fromPartial(request), metadata); + } + + ManyUserSettingsStream(options?: { + metadata?: grpc.Metadata; + rpcOptions?: grpc.RpcOptions; + }): Promise, DashUserSettingsState>> { + return this.rpc.stream( + DashStateManyUserSettingsStreamDesc, + DashUserSettingsState.fromPartial, + options?.metadata, + options?.rpcOptions + ); + } + + ChangeUserSettingsStream(options?: { + metadata?: grpc.Metadata; + rpcOptions?: grpc.RpcOptions; + }): Promise, DashUserSettingsState>> { + return this.rpc.stream( + DashStateChangeUserSettingsStreamDesc, + DashUserSettingsState.fromPartial, + options?.metadata, + options?.rpcOptions + ); + } +} + +export const DashStateDesc = { + serviceName: 'rpx.DashState', +}; + +export const DashStateUserSettingsDesc: UnaryMethodDefinitionish = { + methodName: 'UserSettings', + service: DashStateDesc, + requestStream: false, + responseStream: false, + requestType: { + serializeBinary() { + return Empty.encode(this).finish(); + }, + } as any, + responseType: { + deserializeBinary(data: Uint8Array) { + return { + ...DashUserSettingsState.decode(data), + toObject() { + return this; + }, + }; + }, + } as any, +}; + +export const DashStateActiveUserSettingsStreamDesc: MethodDefinitionish = { + methodName: 'ActiveUserSettingsStream', + service: DashStateDesc, + requestStream: false, + responseStream: true, + requestType: { + serializeBinary() { + return Empty.encode(this).finish(); + }, + } as any, + responseType: { + deserializeBinary(data: Uint8Array) { + return { + ...DashUserSettingsState.decode(data), + toObject() { + return this; + }, + }; + }, + } as any, +}; + +export const DashStateManyUserSettingsStreamDesc: MethodDefinitionish = { + methodName: 'ManyUserSettingsStream', + service: DashStateDesc, + requestStream: true, + responseStream: false, + requestType: { + serializeBinary() { + return DashUserSettingsState.encode(this).finish(); + }, + } as any, + responseType: { + deserializeBinary(data: Uint8Array) { + return { + ...DashUserSettingsState.decode(data), + toObject() { + return this; + }, + }; + }, + } as any, +}; + +export const DashStateChangeUserSettingsStreamDesc: MethodDefinitionish = { + methodName: 'ChangeUserSettingsStream', + service: DashStateDesc, + requestStream: true, + responseStream: true, + requestType: { + serializeBinary() { + return DashUserSettingsState.encode(this).finish(); + }, + } as any, + responseType: { + deserializeBinary(data: Uint8Array) { + return { + ...DashUserSettingsState.decode(data), + toObject() { + return this; + }, + }; + }, + } as any, +}; + +/** + * ---------------------- + * API Creds + * ---------------------- + */ +export interface DashAPICreds { + Create(request: DeepPartial, metadata?: grpc.Metadata): Promise; + Update(request: DeepPartial, metadata?: grpc.Metadata): Promise; + Delete(request: DeepPartial, metadata?: grpc.Metadata): Promise; +} + +export class DashAPICredsClientImpl implements DashAPICreds { + private readonly rpc: Rpc; + + constructor(rpc: Rpc) { + this.rpc = rpc; + this.Create = this.Create.bind(this); + this.Update = this.Update.bind(this); + this.Delete = this.Delete.bind(this); + } + + Create(request: DeepPartial, metadata?: grpc.Metadata): Promise { + return this.rpc.unary(DashAPICredsCreateDesc, DashAPICredsCreateReq.fromPartial(request), metadata); + } + + Update(request: DeepPartial, metadata?: grpc.Metadata): Promise { + return this.rpc.unary(DashAPICredsUpdateDesc, DashAPICredsUpdateReq.fromPartial(request), metadata); + } + + Delete(request: DeepPartial, metadata?: grpc.Metadata): Promise { + return this.rpc.unary(DashAPICredsDeleteDesc, DashAPICredsDeleteReq.fromPartial(request), metadata); + } +} + +export const DashAPICredsDesc = { + serviceName: 'rpx.DashAPICreds', +}; + +export const DashAPICredsCreateDesc: UnaryMethodDefinitionish = { + methodName: 'Create', + service: DashAPICredsDesc, + requestStream: false, + responseStream: false, + requestType: { + serializeBinary() { + return DashAPICredsCreateReq.encode(this).finish(); + }, + } as any, + responseType: { + deserializeBinary(data: Uint8Array) { + return { + ...DashCred.decode(data), + toObject() { + return this; + }, + }; + }, + } as any, +}; + +export const DashAPICredsUpdateDesc: UnaryMethodDefinitionish = { + methodName: 'Update', + service: DashAPICredsDesc, + requestStream: false, + responseStream: false, + requestType: { + serializeBinary() { + return DashAPICredsUpdateReq.encode(this).finish(); + }, + } as any, + responseType: { + deserializeBinary(data: Uint8Array) { + return { + ...DashCred.decode(data), + toObject() { + return this; + }, + }; + }, + } as any, +}; + +export const DashAPICredsDeleteDesc: UnaryMethodDefinitionish = { + methodName: 'Delete', + service: DashAPICredsDesc, + requestStream: false, + responseStream: false, + requestType: { + serializeBinary() { + return DashAPICredsDeleteReq.encode(this).finish(); + }, + } as any, + responseType: { + deserializeBinary(data: Uint8Array) { + return { + ...DashCred.decode(data), + toObject() { + return this; + }, + }; + }, + } as any, +}; + +interface UnaryMethodDefinitionishR extends grpc.UnaryMethodDefinition { + requestStream: any; + responseStream: any; +} + +type UnaryMethodDefinitionish = UnaryMethodDefinitionishR; + +interface MethodDefinitionishR extends grpc.MethodDefinition { + requestStream: any; + responseStream: any; +} + +type MethodDefinitionish = MethodDefinitionishR; + +export type GrpcWebStatus = { details: string; code: number; metadata: grpc.Metadata }; +type GrpcWebOnType = 'data' | 'end' | 'status'; +type GrpcWebOnDataHandler = (message: T) => void; +type GrpcWebOnEndHandler = (status?: GrpcWebStatus) => void; +type GrpcWebOnStatusHandler = (status: GrpcWebStatus) => void; +type GrpcWebListeners = { + data: GrpcWebOnDataHandler[]; + end: GrpcWebOnEndHandler[]; + status: GrpcWebOnStatusHandler[]; +}; +interface GrpcWebResponseStream { + cancel(): void; + on(type: 'data', handler: GrpcWebOnDataHandler): GrpcWebResponseStream; + on(type: 'end', handler: GrpcWebOnEndHandler): GrpcWebResponseStream; + on(type: 'status', handler: GrpcWebOnStatusHandler): GrpcWebResponseStream; +} +interface GrpcWebBidirectionalStream { + write(message: ReqT): GrpcWebBidirectionalStream; + end(): void; + cancel(): void; + on(type: 'data', handler: GrpcWebOnDataHandler): GrpcWebBidirectionalStream; + on(type: 'end', handler: GrpcWebOnEndHandler): GrpcWebBidirectionalStream; + on(type: 'status', handler: GrpcWebOnStatusHandler): GrpcWebBidirectionalStream; +} + +interface Rpc { + unary( + methodDesc: T, + request: any, + metadata: grpc.Metadata | undefined + ): Promise; + invoke( + methodDesc: T, + request: any, + metadata: grpc.Metadata | undefined + ): Promise>; + stream( + methodDesc: T, + fromPartial: (request: any) => Req, + metadata: grpc.Metadata | undefined, + rpcOptions: grpc.RpcOptions | undefined + ): Promise>; +} + +export class GrpcWebImpl { + private host: string; + private options: { + transport?: grpc.TransportFactory; + streamingTransport?: grpc.TransportFactory; + debug?: boolean; + metadata?: grpc.Metadata; + upStreamRetryCodes?: number[]; + }; + + constructor( + host: string, + options: { + transport?: grpc.TransportFactory; + streamingTransport?: grpc.TransportFactory; + debug?: boolean; + metadata?: grpc.Metadata; + upStreamRetryCodes?: number[]; + } + ) { + this.host = host; + this.options = options; + } + + unary( + methodDesc: T, + _request: any, + metadata: grpc.Metadata | undefined + ): Promise { + const request = { ..._request, ...methodDesc.requestType }; + const maybeCombinedMetadata = + metadata && this.options.metadata + ? new BrowserHeaders({ ...this.options?.metadata.headersMap, ...metadata?.headersMap }) + : metadata || this.options.metadata; + return new Promise((resolve, reject) => { + grpc.unary(methodDesc, { + request, + host: this.host, + metadata: maybeCombinedMetadata, + transport: this.options.transport, + debug: this.options.debug, + onEnd: function (response) { + if (response.status === grpc.Code.OK) { + resolve(response.message); + } else { + const err = new Error(response.statusMessage) as any; + err.code = response.status; + err.metadata = response.trailers; + reject(err); + } + }, + }); + }); + } + + invoke( + methodDesc: T, + _request: any, + metadata: grpc.Metadata | undefined + ): Promise> { + const request = { ..._request, ...methodDesc.requestType }; + const maybeCombinedMetadata = + metadata && this.options.metadata + ? new BrowserHeaders({ ...this.options?.metadata.headersMap, ...metadata?.headersMap }) + : metadata || this.options.metadata; + + let listeners: GrpcWebListeners = { + data: [], + end: [], + status: [], + }; + + const client = grpc.invoke(methodDesc, { + host: this.host, + request, + transport: this.options.streamingTransport || this.options.transport, + metadata: maybeCombinedMetadata, + debug: this.options.debug, + onMessage: function (message) { + listeners.data.forEach(function (handler) { + handler(message); + }); + }, + onEnd: function (code: grpc.Code, message: string, trailers: grpc.Metadata) { + listeners.status.forEach(function (handler) { + handler({ code, details: message, metadata: trailers }); + }); + listeners.end.forEach(function (handler) { + handler({ code, details: message, metadata: trailers }); + }); + listeners = { data: [], end: [], status: [] }; + }, + }); + + const invoke: GrpcWebResponseStream = { + on: function ( + listenType: GrpcWebOnType, + hanlder: GrpcWebOnDataHandler | GrpcWebOnEndHandler | GrpcWebOnStatusHandler + ) { + listeners[listenType].push(hanlder); + return this; + }, + cancel: function () { + listeners = { data: [], end: [], status: [] }; + client.close(); + }, + }; + return Promise.resolve(invoke); + } + + stream( + methodDesc: T, + fromPartial: (request: DeepPartial) => any, + metadata: grpc.Metadata | undefined, + rpcOptions: grpc.RpcOptions | undefined + ): Promise, any>> { + const defaultOptions = { + host: this.host, + debug: rpcOptions?.debug || this.options.debug, + transport: rpcOptions?.transport || this.options.streamingTransport || this.options.transport, + }; + + let listeners: GrpcWebListeners = { + data: [], + end: [], + status: [], + }; + + const client = grpc.client(methodDesc, defaultOptions); + client.onMessage(function (message) { + listeners.data.forEach(function (handler) { + handler(message); + }); + }); + client.onEnd(function (code: grpc.Code, message: string, trailers: grpc.Metadata) { + listeners.status.forEach(function (handler) { + handler({ code, details: message, metadata: trailers }); + }); + listeners.end.forEach(function (handler) { + handler({ code, details: message, metadata: trailers }); + }); + listeners = { data: [], end: [], status: [] }; + }); + + client.start(metadata); + + const bidi: GrpcWebBidirectionalStream, any> = { + on: function ( + listenType: GrpcWebOnType, + hanlder: GrpcWebOnDataHandler | GrpcWebOnEndHandler | GrpcWebOnStatusHandler + ) { + listeners[listenType].push(hanlder); + return this; + }, + write: function (message: DeepPartial) { + const request = fromPartial(message); + client.send({ ...request, ...methodDesc.requestType }); + return this; + }, + end: function () { + client.finishSend(); + }, + cancel: function () { + listeners = { data: [], end: [], status: [] }; + client.close(); + }, + }; + return Promise.resolve(bidi); + } +} + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin + ? T + : T extends Array + ? Array> + : T extends ReadonlyArray + ? ReadonlyArray> + : T extends {} + ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin + ? P + : P & { [K in keyof P]: Exact } & Record>, never>; + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} diff --git a/integration/grpc-web-promise/index.html b/integration/grpc-web-promise/index.html new file mode 100644 index 000000000..dcdc31902 --- /dev/null +++ b/integration/grpc-web-promise/index.html @@ -0,0 +1,10 @@ + + + + example + + + + Open devtools see more info + + diff --git a/integration/grpc-web-promise/package-lock.json b/integration/grpc-web-promise/package-lock.json new file mode 100644 index 000000000..d0ca0ed36 --- /dev/null +++ b/integration/grpc-web-promise/package-lock.json @@ -0,0 +1,2529 @@ +{ + "name": "grpc-web", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "grpc-web", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "ts-loader": "^9.3.1", + "typescript": "^4.7.4", + "webpack": "^5.73.0", + "webpack-cli": "^4.10.0" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.14", + "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@types/eslint": { + "version": "8.4.5", + "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.4.5.tgz", + "integrity": "sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmmirror.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.0.3", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-18.0.3.tgz", + "integrity": "sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz", + "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", + "dev": true, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x", + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/@webpack-cli/info/-/info-1.5.0.tgz", + "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", + "dev": true, + "dependencies": { + "envinfo": "^7.7.3" + }, + "peerDependencies": { + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/@webpack-cli/serve/-/serve-1.7.0.tgz", + "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", + "dev": true, + "peerDependencies": { + "webpack-cli": "4.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmmirror.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.21.1", + "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.21.1.tgz", + "integrity": "sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30001359", + "electron-to-chromium": "^1.4.172", + "node-releases": "^2.0.5", + "update-browserslist-db": "^1.0.4" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001365", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001365.tgz", + "integrity": "sha512-VDQZ8OtpuIPMBA4YYvZXECtXbddMCUFJk1qu8Mqxfm/SZJNSr1cy4IuLCOL7RJ/YASrvJcYg1Zh+UEUQ5m6z8Q==", + "dev": true + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.186", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.186.tgz", + "integrity": "sha512-YoVeFrGd/7ROjz4R9uPoND1K/hSRC/xADy9639ZmIZeJSaBnKdYx3I6LMPsY7CXLpK7JFgKQVzeZ/dk2br6Eaw==", + "dev": true + }, + "node_modules/enhanced-resolve": { + "version": "5.10.0", + "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", + "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmmirror.com/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmmirror.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmmirror.com/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "dependencies": { + "resolve": "^1.9.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.14.1", + "resolved": "https://registry.npmmirror.com/terser/-/terser-5.14.1.tgz", + "integrity": "sha512-+ahUAE+iheqBTDxXhTisdA8hgvbEG1hHOQ9xmNjeUJSoi6DU/gMrKNcfZjHkyY6Alnuyc+ikYJaxxfHkT3+WuQ==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.3", + "resolved": "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz", + "integrity": "sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.7", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.7.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-loader": { + "version": "9.3.1", + "resolved": "https://registry.npmmirror.com/ts-loader/-/ts-loader-9.3.1.tgz", + "integrity": "sha512-OkyShkcZTsTwyS3Kt7a4rsT/t2qvEVQuKCTg4LJmpj9fhFR7ukGdZwV6Qq3tRUkqcXtfGpPR7+hFKHCG/0d3Lw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", + "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", + "dev": true, + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack": { + "version": "5.73.0", + "resolved": "https://registry.npmmirror.com/webpack/-/webpack-5.73.0.tgz", + "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.3", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "4.10.0", + "resolved": "https://registry.npmmirror.com/webpack-cli/-/webpack-cli-4.10.0.tgz", + "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.2.0", + "@webpack-cli/info": "^1.5.0", + "@webpack-cli/serve": "^1.7.0", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "cross-spawn": "^7.0.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "@webpack-cli/migrate": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + }, + "dependencies": { + "@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.14", + "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@types/eslint": { + "version": "8.4.5", + "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.4.5.tgz", + "integrity": "sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmmirror.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "@types/node": { + "version": "18.0.3", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-18.0.3.tgz", + "integrity": "sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webpack-cli/configtest": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz", + "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", + "dev": true, + "requires": {} + }, + "@webpack-cli/info": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/@webpack-cli/info/-/info-1.5.0.tgz", + "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", + "dev": true, + "requires": { + "envinfo": "^7.7.3" + } + }, + "@webpack-cli/serve": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/@webpack-cli/serve/-/serve-1.7.0.tgz", + "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", + "dev": true, + "requires": {} + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true + }, + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmmirror.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.21.1", + "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.21.1.tgz", + "integrity": "sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001359", + "electron-to-chromium": "^1.4.172", + "node-releases": "^2.0.5", + "update-browserslist-db": "^1.0.4" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001365", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001365.tgz", + "integrity": "sha512-VDQZ8OtpuIPMBA4YYvZXECtXbddMCUFJk1qu8Mqxfm/SZJNSr1cy4IuLCOL7RJ/YASrvJcYg1Zh+UEUQ5m6z8Q==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "electron-to-chromium": { + "version": "1.4.186", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.186.tgz", + "integrity": "sha512-YoVeFrGd/7ROjz4R9uPoND1K/hSRC/xADy9639ZmIZeJSaBnKdYx3I6LMPsY7CXLpK7JFgKQVzeZ/dk2br6Eaw==", + "dev": true + }, + "enhanced-resolve": { + "version": "5.10.0", + "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", + "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmmirror.com/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true + }, + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmmirror.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true + }, + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "requires": { + "mime-db": "1.52.0" + } + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmmirror.com/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, + "terser": { + "version": "5.14.1", + "resolved": "https://registry.npmmirror.com/terser/-/terser-5.14.1.tgz", + "integrity": "sha512-+ahUAE+iheqBTDxXhTisdA8hgvbEG1hHOQ9xmNjeUJSoi6DU/gMrKNcfZjHkyY6Alnuyc+ikYJaxxfHkT3+WuQ==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + } + }, + "terser-webpack-plugin": { + "version": "5.3.3", + "resolved": "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz", + "integrity": "sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.7", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.7.2" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "ts-loader": { + "version": "9.3.1", + "resolved": "https://registry.npmmirror.com/ts-loader/-/ts-loader-9.3.1.tgz", + "integrity": "sha512-OkyShkcZTsTwyS3Kt7a4rsT/t2qvEVQuKCTg4LJmpj9fhFR7ukGdZwV6Qq3tRUkqcXtfGpPR7+hFKHCG/0d3Lw==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + } + }, + "typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", + "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "webpack": { + "version": "5.73.0", + "resolved": "https://registry.npmmirror.com/webpack/-/webpack-5.73.0.tgz", + "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.3", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + } + }, + "webpack-cli": { + "version": "4.10.0", + "resolved": "https://registry.npmmirror.com/webpack-cli/-/webpack-cli-4.10.0.tgz", + "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.2.0", + "@webpack-cli/info": "^1.5.0", + "@webpack-cli/serve": "^1.7.0", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "cross-spawn": "^7.0.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + } + } + }, + "webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } +} diff --git a/integration/grpc-web-promise/package.json b/integration/grpc-web-promise/package.json new file mode 100644 index 000000000..a83508426 --- /dev/null +++ b/integration/grpc-web-promise/package.json @@ -0,0 +1,17 @@ +{ + "name": "grpc-web", + "version": "1.0.0", + "description": "", + "main": "webpack.config.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "ts-loader": "^9.3.1", + "typescript": "^4.7.4", + "webpack": "^5.73.0", + "webpack-cli": "^4.10.0" + } +} diff --git a/integration/grpc-web-promise/parameters.txt b/integration/grpc-web-promise/parameters.txt new file mode 100644 index 000000000..03af13770 --- /dev/null +++ b/integration/grpc-web-promise/parameters.txt @@ -0,0 +1 @@ +outputClientImpl=grpc-web diff --git a/integration/grpc-web-promise/tsconfig.json b/integration/grpc-web-promise/tsconfig.json new file mode 100644 index 000000000..f205fe6cf --- /dev/null +++ b/integration/grpc-web-promise/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es5", "es6", "dom"], + "rootDir": "." + }, + "exclude": [ + "node_modules", + "example-test.ts" + ] +} diff --git a/integration/grpc-web-promise/webpack.config.js b/integration/grpc-web-promise/webpack.config.js new file mode 100644 index 000000000..3927bc8d3 --- /dev/null +++ b/integration/grpc-web-promise/webpack.config.js @@ -0,0 +1,25 @@ +//webpack.config.js +const path = require('path'); + +module.exports = { + mode: "development", + devtool: "inline-source-map", + entry: { + main: "./client-ts.ts", + }, + output: { + path: path.resolve(__dirname, './build'), + filename: "[name]-bundle.js" // <--- Will be compiled to this single file + }, + resolve: { + extensions: [".ts", ".tsx", ".js"], + }, + module: { + rules: [ + { + test: /\.tsx?$/, + loader: "ts-loader" + } + ] + } +}; diff --git a/integration/grpc-web/client-ts.ts b/integration/grpc-web/client-ts.ts index 16313013f..1eec658d0 100755 --- a/integration/grpc-web/client-ts.ts +++ b/integration/grpc-web/client-ts.ts @@ -18,26 +18,36 @@ const creds = new DashAPICredsClientImpl(rpc); async function main() { console.log('calling client.UserSettings'); - console.log(await client.UserSettings({})); + const settingObs = client.UserSettings({}); + await settingObs.forEach(value => { + console.log("[setting] Got", value); + }); console.log('calling creds.Create'); - const cred = await creds.Create({ description: 'test desc fooo' }); - console.log(cred); + const credObs = creds.Create({ description: 'test desc fooo' }); + let credId = undefined; + await credObs.forEach(value => { + credId = value.id; + console.log("[create] Got", value); + }); console.log('calling creds.Delete'); - const del = await creds.Delete({ id: cred.id }); - console.log(del); + const delObs = creds.Delete({ id: credId }); + await delObs.forEach(value => { + console.log("[delete] Got", value); + }); console.log('calling creds.Update'); - try { - await creds.Update({ description: 'test desc2' }); - } catch (e) { - console.log('got expected error', e); - } + const updateObs = creds.Update({ description: 'test desc2' }); + updateObs.subscribe({ + next(x) { console.log("[update] Got", x) }, + error(err){ console.error('got expected error', err) }, + complete() { console.log("update Done") } + }); console.log('(server-stream) calling client.ActiveUserSettingsStream'); - const obs = client.ActiveUserSettingsStream({}); - await obs.forEach(value => { + const activeObs = client.ActiveUserSettingsStream({}); + await activeObs.forEach(value => { console.log("[server-stream] Got", value); }); diff --git a/integration/grpc-web/example.ts b/integration/grpc-web/example.ts index 2ec8bf60a..f95e26e62 100644 --- a/integration/grpc-web/example.ts +++ b/integration/grpc-web/example.ts @@ -1,7 +1,7 @@ /* eslint-disable */ import { grpc } from '@improbable-eng/grpc-web'; import { BrowserHeaders } from 'browser-headers'; -import { share } from 'rxjs/operators'; +import { take, share } from 'rxjs/operators'; import { Observable } from 'rxjs'; import * as _m0 from 'protobufjs/minimal'; @@ -593,7 +593,7 @@ export const Empty = { }; export interface DashState { - UserSettings(request: DeepPartial, metadata?: grpc.Metadata): Promise; + UserSettings(request: DeepPartial, metadata?: grpc.Metadata): Observable; ActiveUserSettingsStream(request: DeepPartial, metadata?: grpc.Metadata): Observable; ManyUserSettingsStream( request: Observable>, @@ -622,7 +622,7 @@ export class DashStateClientImpl implements DashState { this.ChangeUserSettingsStream = this.ChangeUserSettingsStream.bind(this); } - UserSettings(request: DeepPartial, metadata?: grpc.Metadata): Promise { + UserSettings(request: DeepPartial, metadata?: grpc.Metadata): Observable { return this.rpc.unary(DashStateUserSettingsDesc, Empty.fromPartial(request), metadata); } @@ -749,9 +749,9 @@ export const DashStateChangeUserSettingsStreamDesc: MethodDefinitionish = { * ---------------------- */ export interface DashAPICreds { - Create(request: DeepPartial, metadata?: grpc.Metadata): Promise; - Update(request: DeepPartial, metadata?: grpc.Metadata): Promise; - Delete(request: DeepPartial, metadata?: grpc.Metadata): Promise; + Create(request: DeepPartial, metadata?: grpc.Metadata): Observable; + Update(request: DeepPartial, metadata?: grpc.Metadata): Observable; + Delete(request: DeepPartial, metadata?: grpc.Metadata): Observable; } export class DashAPICredsClientImpl implements DashAPICreds { @@ -764,15 +764,15 @@ export class DashAPICredsClientImpl implements DashAPICreds { this.Delete = this.Delete.bind(this); } - Create(request: DeepPartial, metadata?: grpc.Metadata): Promise { + Create(request: DeepPartial, metadata?: grpc.Metadata): Observable { return this.rpc.unary(DashAPICredsCreateDesc, DashAPICredsCreateReq.fromPartial(request), metadata); } - Update(request: DeepPartial, metadata?: grpc.Metadata): Promise { + Update(request: DeepPartial, metadata?: grpc.Metadata): Observable { return this.rpc.unary(DashAPICredsUpdateDesc, DashAPICredsUpdateReq.fromPartial(request), metadata); } - Delete(request: DeepPartial, metadata?: grpc.Metadata): Promise { + Delete(request: DeepPartial, metadata?: grpc.Metadata): Observable { return this.rpc.unary(DashAPICredsDeleteDesc, DashAPICredsDeleteReq.fromPartial(request), metadata); } } @@ -866,7 +866,7 @@ interface Rpc { methodDesc: T, request: any, metadata: grpc.Metadata | undefined - ): Promise; + ): Observable; invoke( methodDesc: T, request: any, @@ -908,31 +908,29 @@ export class GrpcWebImpl { methodDesc: T, _request: any, metadata: grpc.Metadata | undefined - ): Promise { + ): Observable { const request = { ..._request, ...methodDesc.requestType }; const maybeCombinedMetadata = metadata && this.options.metadata ? new BrowserHeaders({ ...this.options?.metadata.headersMap, ...metadata?.headersMap }) : metadata || this.options.metadata; - return new Promise((resolve, reject) => { + return new Observable((observer) => { grpc.unary(methodDesc, { request, host: this.host, metadata: maybeCombinedMetadata, transport: this.options.transport, debug: this.options.debug, - onEnd: function (response) { - if (response.status === grpc.Code.OK) { - resolve(response.message); + onEnd: (next) => { + if (next.status !== 0) { + observer.error({ code: next.status, message: next.statusMessage }); } else { - const err = new Error(response.statusMessage) as any; - err.code = response.status; - err.metadata = response.trailers; - reject(err); + observer.next(next.message as any); + observer.complete(); } }, }); - }); + }).pipe(take(1)); } invoke( diff --git a/integration/grpc-web/parameters.txt b/integration/grpc-web/parameters.txt index 03af13770..f9e39f25b 100644 --- a/integration/grpc-web/parameters.txt +++ b/integration/grpc-web/parameters.txt @@ -1 +1 @@ -outputClientImpl=grpc-web +outputClientImpl=grpc-web,returnObservable=true diff --git a/integration/use-numeric-enum-json/google/protobuf/struct.ts b/integration/use-numeric-enum-json/google/protobuf/struct.ts index 3ca8fa9c2..70d9008f2 100644 --- a/integration/use-numeric-enum-json/google/protobuf/struct.ts +++ b/integration/use-numeric-enum-json/google/protobuf/struct.ts @@ -60,8 +60,8 @@ export interface Struct_FieldsEntry { /** * `Value` represents a dynamically typed value which can be either * null, a number, a string, a boolean, a recursive struct value, or a - * list of values. A producer of value is expected to set one of that - * variants, absence of any variant indicates an error. + * list of values. A producer of value is expected to set one of these + * variants. Absence of any variant indicates an error. * * The JSON representation for `Value` is JSON value. */ diff --git a/integration/use-numeric-enum-json/simple.bin b/integration/use-numeric-enum-json/simple.bin index 15a0e057a..091d8c01e 100644 Binary files a/integration/use-numeric-enum-json/simple.bin and b/integration/use-numeric-enum-json/simple.bin differ diff --git a/src/generate-grpc-web.ts b/src/generate-grpc-web.ts index 1f3685648..3c81b7fa8 100644 --- a/src/generate-grpc-web.ts +++ b/src/generate-grpc-web.ts @@ -1,5 +1,12 @@ import { MethodDescriptorProto, FileDescriptorProto, ServiceDescriptorProto } from 'ts-proto-descriptors'; -import { rawRequestType, requestType, responsePromiseOrObservable, responseType, observableType } from './types'; +import { + rawRequestType, + requestType, + responseType, + observableType, + responseObservable, + responsePromise, +} from './types'; import { Code, code, imp, joinCode } from 'ts-poet'; import { Context } from './context'; import { assertInstanceOf, FormattedMethodDescriptor, maybePrefixPackage } from './utils'; @@ -45,34 +52,79 @@ export function generateGrpcClientImpl( return joinCode(chunks, { trim: false, on: '\n' }); } +function grpcWebResponseStreamPromise(ctx: Context, methodDesc: MethodDescriptorProto): Code { + return code`Promise>`; +} + +function grpcWebBidirectionalStreamPromise(ctx: Context, methodDesc: MethodDescriptorProto): Code { + let typeName = rawRequestType(ctx, methodDesc); + const inputType = code`${ctx.utils.DeepPartial}<${typeName}>`; + return code`Promise>`; +} + +export function grpcWebResponsePromiseOrObservable(ctx: Context, methodDesc: MethodDescriptorProto): Code { + const { options } = ctx; + if (options.returnObservable) { + return responseObservable(ctx, methodDesc); + } + if (methodDesc.clientStreaming && methodDesc.serverStreaming) { + return grpcWebBidirectionalStreamPromise(ctx, methodDesc); + } else if (methodDesc.clientStreaming) { + return grpcWebBidirectionalStreamPromise(ctx, methodDesc); + } else if (methodDesc.serverStreaming) { + return grpcWebResponseStreamPromise(ctx, methodDesc); + } else { + return responsePromise(ctx, methodDesc); + } +} + /** Creates the RPC methods that client code actually calls. */ function generateRpcMethod(ctx: Context, serviceDesc: ServiceDescriptorProto, methodDesc: MethodDescriptorProto) { assertInstanceOf(methodDesc, FormattedMethodDescriptor); const requestMessage = rawRequestType(ctx, methodDesc); const inputType = requestType(ctx, methodDesc, true); - const returns = responsePromiseOrObservable(ctx, methodDesc); - - if (methodDesc.clientStreaming) { - return code` + const returns = grpcWebResponsePromiseOrObservable(ctx, methodDesc); + const { options } = ctx; + if (options.returnObservable) { + if (methodDesc.clientStreaming) { + return code` ${methodDesc.formattedName}( request: ${inputType}, options?: { - metadata?: grpc.Metadata, - rpcOptions?: grpc.RpcOptions, + metadata?: ${grpc}.Metadata, + rpcOptions?: ${grpc}.RpcOptions, }): ${returns} { return this.rpc.stream(${methodDescName( serviceDesc, methodDesc - )}, request, options?.metadata, options?.rpcOptions) + )}, request, options?.metadata, options?.rpcOptions); } `; + } + } else { + if (methodDesc.clientStreaming) { + return code` + ${methodDesc.formattedName}( + options?: { + metadata?: ${grpc}.Metadata, + rpcOptions?: ${grpc}.RpcOptions, + }): ${returns} { + return this.rpc.stream( + ${methodDescName(serviceDesc, methodDesc)}, + ${requestMessage}.fromPartial, + options?.metadata, + options?.rpcOptions + ); + } + `; + } } const method = methodDesc.serverStreaming ? 'invoke' : 'unary'; return code` ${methodDesc.formattedName}( request: ${inputType}, - metadata?: grpc.Metadata, + metadata?: ${grpc}.Metadata, ): ${returns} { return this.rpc.${method}( ${methodDescName(serviceDesc, methodDesc)}, @@ -154,7 +206,7 @@ function methodDescName(serviceDesc: ServiceDescriptorProto, methodDesc: MethodD } /** Adds misc top-level definitions for grpc-web functionality. */ -export function addGrpcWebMisc(ctx: Context, hasStreamingMethods: boolean): Code { +export function addGrpcWebMisc(ctx: Context, hasClientStreaming: boolean, hasServerStreaming: boolean): Code { const { options } = ctx; const chunks: Code[] = []; chunks.push(code` @@ -167,13 +219,49 @@ export function addGrpcWebMisc(ctx: Context, hasStreamingMethods: boolean): Code `); chunks.push(code`type MethodDefinitionish = MethodDefinitionishR;`); - chunks.push(generateGrpcWebRpcType(ctx, options.returnObservable, hasStreamingMethods)); - chunks.push(generateGrpcWebImpl(ctx, options.returnObservable, hasStreamingMethods)); + if (!options.returnObservable) { + if (hasServerStreaming || hasClientStreaming) { + chunks.push(code` +export type GrpcWebStatus = { details: string; code: number; metadata: grpc.Metadata }; +type GrpcWebOnType = 'data' | 'end' | 'status'; +type GrpcWebOnDataHandler = (message: T) => void; +type GrpcWebOnEndHandler = (status?: GrpcWebStatus) => void; +type GrpcWebOnStatusHandler = (status: GrpcWebStatus) => void; +type GrpcWebListeners = { + data: GrpcWebOnDataHandler[]; + end: GrpcWebOnEndHandler[]; + status: GrpcWebOnStatusHandler[]; +}; +interface GrpcWebResponseStream { + cancel(): void; + on(type: 'data', handler: GrpcWebOnDataHandler): GrpcWebResponseStream; + on(type: 'end', handler: GrpcWebOnEndHandler): GrpcWebResponseStream; + on(type: 'status', handler: GrpcWebOnStatusHandler): GrpcWebResponseStream; +} +interface GrpcWebBidirectionalStream { + write(message: ReqT): GrpcWebBidirectionalStream; + end(): void; + cancel(): void; + on(type: 'data', handler: GrpcWebOnDataHandler): GrpcWebBidirectionalStream; + on(type: 'end', handler: GrpcWebOnEndHandler): GrpcWebBidirectionalStream; + on(type: 'status', handler: GrpcWebOnStatusHandler): GrpcWebBidirectionalStream; +} +`); + } + } + + chunks.push(generateGrpcWebRpcType(ctx, options.returnObservable, hasClientStreaming, hasServerStreaming)); + chunks.push(generateGrpcWebImpl(ctx, options.returnObservable, hasClientStreaming, hasServerStreaming)); return joinCode(chunks, { on: '\n\n' }); } /** Makes an `Rpc` interface to decouple from the low-level grpc-web `grpc.invoke and grpc.unary`/etc. methods. */ -function generateGrpcWebRpcType(ctx: Context, returnObservable: boolean, hasStreamingMethods: boolean): Code { +function generateGrpcWebRpcType( + ctx: Context, + returnObservable: boolean, + hasClientStreaming: boolean, + hasServerStreaming: boolean +): Code { const chunks: Code[] = []; chunks.push(code`interface Rpc {`); @@ -183,25 +271,44 @@ function generateGrpcWebRpcType(ctx: Context, returnObservable: boolean, hasStre unary( methodDesc: T, request: any, - metadata: grpc.Metadata | undefined, + metadata: ${grpc}.Metadata | undefined, ): ${wrapper}; `); - if (hasStreamingMethods) { - chunks.push(code` + if (returnObservable) { + if (hasServerStreaming || hasClientStreaming) { + chunks.push(code` invoke( methodDesc: T, request: any, - metadata: grpc.Metadata | undefined, - ): ${observableType(ctx)};`); - - chunks.push(code` + metadata: ${grpc}.Metadata | undefined, +): ${observableType(ctx)};`); + chunks.push(code` stream( methodDesc: T, request: ${observableType(ctx)}, - metadata: grpc.Metadata | undefined, - rpcOptions: grpc.RpcOptions | undefined - ): ${observableType(ctx)};`); + metadata: ${grpc}.Metadata | undefined, + rpcOptions: ${grpc}.RpcOptions | undefined +): ${observableType(ctx)};`); + } + } else { + if (hasServerStreaming || hasClientStreaming) { + chunks.push(code` + invoke( + methodDesc: T, + request: any, + metadata: ${grpc}.Metadata | undefined + ): Promise>; +`); + chunks.push(code` + stream( + methodDesc: T, + fromPartial: (request: any) => Req, + metadata: ${grpc}.Metadata | undefined, + rpcOptions: ${grpc}.RpcOptions | undefined + ): Promise>; +`); + } } chunks.push(code`}`); @@ -209,13 +316,20 @@ function generateGrpcWebRpcType(ctx: Context, returnObservable: boolean, hasStre } /** Implements the `Rpc` interface by making calls using the `grpc.unary` method. */ -function generateGrpcWebImpl(ctx: Context, returnObservable: boolean, hasStreamingMethods: boolean): Code { +function generateGrpcWebImpl( + ctx: Context, + returnObservable: boolean, + hasClientStreaming: boolean, + hasServerStreaming: boolean +): Code { + const streamTransport = + hasClientStreaming || hasClientStreaming ? code`streamingTransport?: ${grpc}.TransportFactory,` : ''; const options = code` { - transport?: grpc.TransportFactory, - ${hasStreamingMethods ? 'streamingTransport?: grpc.TransportFactory,' : ``} + transport?: ${grpc}.TransportFactory, + ${streamTransport} debug?: boolean, - metadata?: grpc.Metadata, + metadata?: ${grpc}.Metadata, upStreamRetryCodes?: number[], } `; @@ -234,15 +348,19 @@ function generateGrpcWebImpl(ctx: Context, returnObservable: boolean, hasStreami if (returnObservable) { chunks.push(createObservableUnaryMethod(ctx)); + // client streaming with observable same with bi-streaming + if (hasServerStreaming || hasClientStreaming) { + chunks.push(createInvokeMethod(ctx)); + chunks.push(createStreamMethod(ctx)); + } } else { chunks.push(createPromiseUnaryMethod()); + // client streaming with Promise same with bi-streaming + if (hasClientStreaming || hasServerStreaming) { + chunks.push(createPromiseInvokeMethod()); + chunks.push(createPromiseStreamMethod()); + } } - - if (hasStreamingMethods) { - chunks.push(createInvokeMethod(ctx)); - chunks.push(createStreamMethod(ctx)); - } - chunks.push(code`}`); return joinCode(chunks, { trim: false }); } @@ -252,7 +370,7 @@ function createPromiseUnaryMethod(): Code { unary( methodDesc: T, _request: any, - metadata: grpc.Metadata | undefined + metadata: ${grpc}.Metadata | undefined ): Promise { const request = { ..._request, ...methodDesc.requestType }; const maybeCombinedMetadata = @@ -267,7 +385,7 @@ function createPromiseUnaryMethod(): Code { transport: this.options.transport, debug: this.options.debug, onEnd: function (response) { - if (response.status === grpc.Code.OK) { + if (response.status === ${grpc}.Code.OK) { resolve(response.message); } else { const err = new Error(response.statusMessage) as any; @@ -287,7 +405,7 @@ function createObservableUnaryMethod(ctx: Context): Code { unary( methodDesc: T, _request: any, - metadata: grpc.Metadata | undefined + metadata: ${grpc}.Metadata | undefined ): ${observableType(ctx)} { const request = { ..._request, ...methodDesc.requestType }; const maybeCombinedMetadata = @@ -320,7 +438,7 @@ function createInvokeMethod(ctx: Context) { invoke( methodDesc: T, _request: any, - metadata: grpc.Metadata | undefined + metadata: ${grpc}.Metadata | undefined ): ${observableType(ctx)} { const upStreamCodes = this.options.upStreamRetryCodes || []; const DEFAULT_TIMEOUT_TIME: number = 3_000; @@ -359,6 +477,65 @@ function createInvokeMethod(ctx: Context) { `; } +function createPromiseInvokeMethod() { + return code` + invoke( + methodDesc: T, + _request: any, + metadata: ${grpc}.Metadata | undefined + ): Promise> { + const request = { ..._request, ...methodDesc.requestType }; + const maybeCombinedMetadata = + metadata && this.options.metadata + ? new ${BrowserHeaders}({ ...this.options?.metadata.headersMap, ...metadata?.headersMap }) + : metadata || this.options.metadata; + + let listeners: GrpcWebListeners = { + data: [], + end: [], + status: [], + }; + + const client = ${grpc}.invoke(methodDesc, { + host: this.host, + request, + transport: this.options.streamingTransport || this.options.transport, + metadata: maybeCombinedMetadata, + debug: this.options.debug, + onMessage: function (message) { + listeners.data.forEach(function (handler) { + handler(message); + }); + }, + onEnd: function (code: ${grpc}.Code, message: string, trailers: ${grpc}.Metadata) { + listeners.status.forEach(function (handler) { + handler({ code, details: message, metadata: trailers }); + }); + listeners.end.forEach(function (handler) { + handler({ code, details: message, metadata: trailers }); + }); + listeners = { data: [], end: [], status: [] }; + }, + }); + + const invoke: GrpcWebResponseStream = { + on: function ( + listenType: GrpcWebOnType, + hanlder: GrpcWebOnDataHandler | GrpcWebOnEndHandler | GrpcWebOnStatusHandler + ) { + listeners[listenType].push(hanlder); + return this; + }, + cancel: function () { + listeners = { data: [], end: [], status: [] }; + client.close(); + }, + }; + return Promise.resolve(invoke); + } +`; +} + function createStreamMethod(ctx: Context) { return code` stream( @@ -406,3 +583,67 @@ function createStreamMethod(ctx: Context) { } `; } + +function createPromiseStreamMethod() { + return code` + stream( + methodDesc: T, + fromPartial: (request: DeepPartial) => any, + metadata: ${grpc}.Metadata | undefined, + rpcOptions: ${grpc}.RpcOptions | undefined + ): Promise, any>> { + const defaultOptions = { + host: this.host, + debug: rpcOptions?.debug || this.options.debug, + transport: rpcOptions?.transport || this.options.streamingTransport || this.options.transport, + }; + + let listeners: GrpcWebListeners = { + data: [], + end: [], + status: [], + }; + + const client = ${grpc}.client(methodDesc, defaultOptions); + client.onMessage(function (message) { + listeners.data.forEach(function (handler) { + handler(message); + }); + }); + client.onEnd(function (code: ${grpc}.Code, message: string, trailers: ${grpc}.Metadata) { + listeners.status.forEach(function (handler) { + handler({ code, details: message, metadata: trailers }); + }); + listeners.end.forEach(function (handler) { + handler({ code, details: message, metadata: trailers }); + }); + listeners = { data: [], end: [], status: [] }; + }); + + client.start(metadata); + + const bidi: GrpcWebBidirectionalStream, any> = { + on: function ( + listenType: GrpcWebOnType, + hanlder: GrpcWebOnDataHandler | GrpcWebOnEndHandler | GrpcWebOnStatusHandler + ) { + listeners[listenType].push(hanlder); + return this; + }, + write: function (message: DeepPartial) { + const request = fromPartial(message); + client.send({ ...request, ...methodDesc.requestType }); + return this; + }, + end: function () { + client.finishSend(); + }, + cancel: function () { + listeners = { data: [], end: [], status: [] }; + client.close(); + }, + }; + return Promise.resolve(bidi); + } +`; +} diff --git a/src/generate-services.ts b/src/generate-services.ts index 85bc01e77..526ac2c4e 100644 --- a/src/generate-services.ts +++ b/src/generate-services.ts @@ -20,6 +20,7 @@ import { import SourceInfo, { Fields } from './sourceInfo'; import { contextTypeVar } from './main'; import { Context } from './context'; +import { grpcWebResponsePromiseOrObservable } from './generate-grpc-web'; const hash = imp('hash*object-hash'); const dataloader = imp('DataLoader*dataloader'); @@ -57,11 +58,18 @@ export function generateService( params.push(code`ctx: Context`); } - // the grpc-web clients auto-`fromPartial` the input before handing off to grpc-web's - // serde runtime, so it's okay to accept partial results from the client - const partialInput = options.outputClientImpl === 'grpc-web'; - const inputType = requestType(ctx, methodDesc, partialInput); - params.push(code`request: ${inputType}`); + // grpc-web client stream or bidirectional stream not request params when use Promise. + if (!options.returnObservable && options.outputClientImpl === 'grpc-web' && methodDesc.clientStreaming) { + // skip + } else { + // the grpc-web clients auto-`fromPartial` the input before handing off to grpc-web's + // serde runtime, so it's okay to accept partial results from the client + const partialInput = options.outputClientImpl === 'grpc-web'; + + // add request params + const inputType = requestType(ctx, methodDesc, partialInput); + params.push(code`request: ${inputType}`); + } // Use metadata as last argument for interface only configuration if (options.outputClientImpl === 'grpc-web') { @@ -85,12 +93,13 @@ export function generateService( params.push(code`...rest: any`); } - chunks.push( - code`${methodDesc.formattedName}(${joinCode(params, { on: ',' })}): ${responsePromiseOrObservable( - ctx, - methodDesc - )};` - ); + let returns: Code; + if (options.outputClientImpl === 'grpc-web') { + returns = grpcWebResponsePromiseOrObservable(ctx, methodDesc); + } else { + returns = responsePromiseOrObservable(ctx, methodDesc); + } + chunks.push(code`${methodDesc.formattedName}(${joinCode(params, { on: ',' })}): ${returns};`); // If this is a batch method, auto-generate the singular version of it if (options.context) { diff --git a/src/main.ts b/src/main.ts index f5b6ed879..95eafbecd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -208,7 +208,8 @@ export function generateFile(ctx: Context, fileDesc: FileDescriptorProto): [stri ); } - let hasStreamingMethods = false; + let hasServerStreamingMethods = false; + let hasClientStreamingMethods = false; visitServices(fileDesc, sourceInfo, (serviceDesc, sInfo) => { if (options.nestJs) { @@ -253,9 +254,12 @@ export function generateFile(ctx: Context, fileDesc: FileDescriptorProto): [stri } }); } - serviceDesc.method.forEach((methodDesc, index) => { - if (methodDesc.serverStreaming || methodDesc.clientStreaming) { - hasStreamingMethods = true; + serviceDesc.method.forEach((methodDesc) => { + if (methodDesc.serverStreaming) { + hasServerStreamingMethods = true; + } + if (methodDesc.clientStreaming) { + hasClientStreamingMethods = true; } }); }); @@ -266,9 +270,9 @@ export function generateFile(ctx: Context, fileDesc: FileDescriptorProto): [stri fileDesc.service.length > 0 ) { if (options.outputClientImpl === true) { - chunks.push(generateRpcType(ctx, hasStreamingMethods)); + chunks.push(generateRpcType(ctx, hasServerStreamingMethods || hasClientStreamingMethods)); } else if (options.outputClientImpl === 'grpc-web') { - chunks.push(addGrpcWebMisc(ctx, hasStreamingMethods)); + chunks.push(addGrpcWebMisc(ctx, hasClientStreamingMethods, hasServerStreamingMethods)); } } diff --git a/src/types.ts b/src/types.ts index 0c0a5283a..77e9ceef5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -698,7 +698,7 @@ export function responseObservable(ctx: Context, methodDesc: MethodDescriptorPro export function responsePromiseOrObservable(ctx: Context, methodDesc: MethodDescriptorProto): Code { const { options } = ctx; - if (options.returnObservable || methodDesc.serverStreaming || methodDesc.clientStreaming) { + if (options.returnObservable || methodDesc.serverStreaming) { return responseObservable(ctx, methodDesc); } return responsePromise(ctx, methodDesc);