feat: introduce dioc into hoppscotch-common

This commit is contained in:
Andrew Bastin
2023-06-07 15:15:56 +05:30
parent e75391cdf1
commit 81a7e23a12
20 changed files with 1117 additions and 65 deletions

24
packages/dioc/.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

141
packages/dioc/README.md Normal file
View File

@@ -0,0 +1,141 @@
# dioc
A small and lightweight dependency injection / inversion of control system.
### About
`dioc` is a really simple **DI/IOC** system where you write services (which are singletons per container) that can depend on each other and emit events that can be listened upon.
### Demo
```ts
import { Service, Container } from "dioc"
// Here is a simple service, which you can define by extending the Service class
// and providing an ID static field (of type string)
export class PersistenceService extends Service {
// This should be unique for each container
public static ID = "PERSISTENCE_SERVICE"
public read(key: string): string | undefined {
// ...
}
public write(key: string, value: string) {
// ...
}
}
type TodoServiceEvent =
| { type: "TODO_CREATED"; index: number }
| { type: "TODO_DELETED"; index: number }
// Services have a built in event system
// Define the generic argument to say what are the possible emitted values
export class TodoService extends Service<TodoServiceEvent> {
public static ID = "TODO_SERVICE"
// Inject persistence service into this service
private readonly persistence = this.bind(PersistenceService)
public todos = []
// Service constructors cannot have arguments
constructor() {
super()
this.todos = JSON.parse(this.persistence.read("todos") ?? "[]")
}
public addTodo(text: string) {
// ...
// You can access services via the bound fields
this.persistence.write("todos", JSON.stringify(this.todos))
// This is how you emit an event
this.emit({
type: "TODO_CREATED",
index,
})
}
public removeTodo(index: number) {
// ...
this.emit({
type: "TODO_DELETED",
index,
})
}
}
// Services need a container to run in
const container = new Container()
// You can initialize and get services using Container#bind
// It will automatically initialize the service (and its dependencies)
const todoService = container.bind(TodoService) // Returns an instance of TodoService
```
### Demo (Unit Test)
`dioc/testing` contains `TestContainer` which lets you bind mocked services to the container.
```ts
import { TestContainer } from "dioc/testing"
import { TodoService, PersistenceService } from "./demo.ts" // The above demo code snippet
import { describe, it, expect, vi } from "vitest"
describe("TodoService", () => {
it("addTodo writes to persistence", () => {
const container = new TestContainer()
const writeFn = vi.fn()
// The first parameter is the service to mock and the second parameter
// is the mocked service fields and functions
container.bindMock(PersistenceService, {
read: () => undefined, // Not really important for this test
write: writeFn,
})
// the peristence service bind in TodoService will now use the
// above defined mocked implementation
const todoService = container.bind(TodoService)
todoService.addTodo("sup")
expect(writeFn).toHaveBeenCalledOnce()
expect(writeFn).toHaveBeenCalledWith("todos", JSON.stringify(["sup"]))
})
})
```
### Demo (Vue)
`dioc/vue` contains a Vue Plugin and a `useService` composable that allows Vue components to use the defined services.
In the app entry point:
```ts
import { createApp } from "vue"
import { diocPlugin } from "dioc/vue"
const app = createApp()
app.use(diocPlugin, {
container: new Container(), // You can pass in the container you want to provide to the components here
})
```
In your Vue components:
```vue
<script setup>
import { TodoService } from "./demo.ts" // The above demo
import { useService } from "dioc/vue"
const todoService = useService(TodoService) // Returns an instance of the TodoService class
</script>
```

2
packages/dioc/index.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
export { default } from "./dist/main.d.ts"
export * from "./dist/main.d.ts"

View File

@@ -0,0 +1,147 @@
import { Service } from "./service"
import { Observable, Subject } from 'rxjs'
/**
* Stores the current container instance in the current operating context.
*
* NOTE: This should not be used outside of dioc library code
*/
export let currentContainer: Container | null = null
/**
* The events emitted by the container
*
* `SERVICE_BIND` - emitted when a service is bound to the container directly or as a dependency to another service
* `SERVICE_INIT` - emitted when a service is initialized
*/
export type ContainerEvent =
| {
type: 'SERVICE_BIND';
/** The Service ID of the service being bounded (the dependency) */
boundeeID: string;
/**
* The Service ID of the bounder that is binding the boundee (the dependent)
*
* NOTE: This will be undefined if the service is bound directly to the container
*/
bounderID: string | undefined
}
| {
type: 'SERVICE_INIT';
/** The Service ID of the service being initialized */
serviceID: string
}
/**
* The dependency injection container, allows for services to be initialized and maintains the dependency trees.
*/
export class Container {
/** Used during the `bind` operation to detect circular dependencies */
private bindStack: string[] = []
/** The map of bound services to their IDs */
protected boundMap = new Map<string, Service<unknown>>()
/** The RxJS observable representing the event stream */
protected event$ = new Subject<ContainerEvent>()
/**
* Returns whether a container has the given service bound
* @param service The service to check for
*/
public hasBound<
T extends typeof Service<any> & { ID: string }
>(service: T): boolean {
return this.boundMap.has(service.ID)
}
/**
* Returns the service bound to the container with the given ID or if not found, undefined.
*
* NOTE: This is an advanced method and should not be used as much as possible.
*
* @param serviceID The ID of the service to get
*/
public getBoundServiceWithID(serviceID: string): Service<unknown> | undefined {
return this.boundMap.get(serviceID)
}
/**
* Binds a service to the container. This is equivalent to marking a service as a dependency.
* @param service The class reference of a service to bind
* @param bounder The class reference of the service that is binding the service (if bound directly to the container, this should be undefined)
*/
public bind<T extends typeof Service<any> & { ID: string }>(
service: T,
bounder: ((typeof Service<T>) & { ID: string }) | undefined = undefined
): InstanceType<T> {
// We need to store the current container in a variable so that we can restore it after the bind operation
const oldCurrentContainer = currentContainer;
currentContainer = this;
// If the service is already bound, return the existing instance
if (this.hasBound(service)) {
this.event$.next({
type: 'SERVICE_BIND',
boundeeID: service.ID,
bounderID: bounder?.ID // Return the bounder ID if it is defined, else assume its the container
})
return this.boundMap.get(service.ID) as InstanceType<T> // Casted as InstanceType<T> because service IDs and types are expected to match
}
// Detect circular dependency and throw error
if (this.bindStack.findIndex((serviceID) => serviceID === service.ID) !== -1) {
const circularServices = `${this.bindStack.join(' -> ')} -> ${service.ID}`
throw new Error(`Circular dependency detected.\nChain: ${circularServices}`)
}
// Push the service ID onto the bind stack to detect circular dependencies
this.bindStack.push(service.ID)
// Initialize the service and emit events
// NOTE: We need to cast the service to any as TypeScript thinks that the service is abstract
const instance: Service<any> = new (service as any)()
this.boundMap.set(service.ID, instance)
this.bindStack.pop()
this.event$.next({
type: 'SERVICE_INIT',
serviceID: service.ID,
})
this.event$.next({
type: 'SERVICE_BIND',
boundeeID: service.ID,
bounderID: bounder?.ID
})
// Restore the current container
currentContainer = oldCurrentContainer;
// We expect the return type to match the service definition
return instance as InstanceType<T>
}
/**
* Returns an iterator of the currently bound service IDs and their instances
*/
public getBoundServices(): IterableIterator<[string, Service<any>]> {
return this.boundMap.entries()
}
/**
* Returns the public container event stream
*/
public getEventStream(): Observable<ContainerEvent> {
return this.event$.asObservable()
}
}

View File

@@ -0,0 +1,2 @@
export * from "./container"
export * from "./service"

View File

@@ -0,0 +1,65 @@
import { Observable, Subject } from 'rxjs'
import { Container, currentContainer } from './container'
/**
* A Dioc service that can bound to a container and can bind dependency services.
*
* NOTE: Services cannot have a constructor that takes arguments.
*
* @template EventDef The type of events that can be emitted by the service. These will be accessible by event streams
*/
export abstract class Service<EventDef = {}> {
/**
* The internal event stream of the service
*/
private event$ = new Subject<EventDef>()
/** The container the service is bound to */
#container: Container
constructor() {
if (!currentContainer) {
throw new Error(
`Tried to initialize service with no container (ID: ${ (this.constructor as any).ID })`
)
}
this.#container = currentContainer
}
/**
* Binds a dependency service into this service.
* @param service The class reference of the service to bind
*/
protected bind<T extends typeof Service<any> & { ID: string }>(service: T): InstanceType<T> {
if (!currentContainer) {
throw new Error('No currentContainer defined.')
}
return currentContainer.bind(service, this.constructor as typeof Service<any> & { ID: string })
}
/**
* Returns the container the service is bound to
*/
protected getContainer(): Container {
return this.#container
}
/**
* Emits an event on the service's event stream
* @param event The event to emit
*/
protected emit(event: EventDef) {
this.event$.next(event)
}
/**
* Returns the event stream of the service
*/
public getEventStream(): Observable<EventDef> {
return this.event$.asObservable()
}
}

View File

@@ -0,0 +1,33 @@
import { Container, Service } from "./main";
/**
* A container that can be used for writing tests, contains additional methods
* for binding suitable for writing tests. (see `bindMock`).
*/
export class TestContainer extends Container {
/**
* Binds a mock service to the container.
*
* @param service
* @param mock
*/
public bindMock<
T extends typeof Service<any> & { ID: string },
U extends Partial<InstanceType<T>>
>(service: T, mock: U): U {
if (this.boundMap.has(service.ID)) {
throw new Error(`Service '${service.ID}' already bound to container. Did you already call bindMock on this ?`)
}
this.boundMap.set(service.ID, mock as any)
this.event$.next({
type: "SERVICE_BIND",
boundeeID: service.ID,
bounderID: undefined,
})
return mock
}
}

34
packages/dioc/lib/vue.ts Normal file
View File

@@ -0,0 +1,34 @@
import { Plugin, inject } from "vue"
import { Container } from "./container"
import { Service } from "./service"
const VUE_CONTAINER_KEY = Symbol()
// TODO: Some Vue version issue with plugin generics is breaking type checking
/**
* The Vue Dioc Plugin, this allows the composables to work and access the container
*
* NOTE: Make sure you add `vue` as dependency to be able to use this plugin (duh)
*/
export const diocPlugin: Plugin = {
install(app, { container }) {
app.provide(VUE_CONTAINER_KEY, container)
}
}
/**
* A composable that binds a service to a Vue Component
*
* @param service The class reference of the service to bind
*/
export function useService<
T extends typeof Service<any> & { ID: string }
>(service: T): InstanceType<T> {
const container = inject(VUE_CONTAINER_KEY) as Container | undefined | null
if (!container) {
throw new Error("Container not found, did you forget to install the dioc plugin?")
}
return container.bind(service)
}

View File

@@ -0,0 +1,54 @@
{
"name": "dioc",
"private": true,
"version": "0.1.0",
"type": "module",
"files": [
"dist",
"index.d.ts"
],
"main": "./dist/counter.umd.cjs",
"module": "./dist/counter.js",
"types": "./index.d.ts",
"exports": {
".": {
"types": "./dist/main.d.ts",
"require": "./dist/index.cjs",
"import": "./dist/index.js"
},
"./vue": {
"types": "./dist/vue.d.ts",
"require": "./dist/vue.cjs",
"import": "./dist/vue.js"
},
"./testing": {
"types": "./dist/testing.d.ts",
"require": "./dist/testing.cjs",
"import": "./dist/testing.js"
}
},
"scripts": {
"dev": "vite",
"build": "vite build && tsc --emitDeclarationOnly",
"prepare": "pnpm run build",
"test": "vitest run",
"do-test": "pnpm run test",
"test:watch": "vitest"
},
"devDependencies": {
"typescript": "^4.9.4",
"vite": "^4.0.4",
"vitest": "^0.29.3"
},
"dependencies": {
"rxjs": "^7.8.1"
},
"peerDependencies": {
"vue": "^3.2.25"
},
"peerDependenciesMeta": {
"vue": {
"optional": true
}
}
}

View File

@@ -0,0 +1,262 @@
import { it, expect, describe, vi } from "vitest"
import { Service } from "../lib/service"
import { Container, currentContainer, ContainerEvent } from "../lib/container"
class TestServiceA extends Service {
public static ID = "TestServiceA"
}
class TestServiceB extends Service {
public static ID = "TestServiceB"
// Marked public to allow for testing
public readonly serviceA = this.bind(TestServiceA)
}
describe("Container", () => {
describe("getBoundServiceWithID", () => {
it("returns the service instance if it is bound to the container", () => {
const container = new Container()
const service = container.bind(TestServiceA)
expect(container.getBoundServiceWithID(TestServiceA.ID)).toBe(service)
})
it("returns undefined if the service is not bound to the container", () => {
const container = new Container()
expect(container.getBoundServiceWithID(TestServiceA.ID)).toBeUndefined()
})
})
describe("bind", () => {
it("correctly binds the service to it", () => {
const container = new Container()
const service = container.bind(TestServiceA)
// @ts-expect-error getContainer is defined as a protected property, but we are leveraging it here to check
expect(service.getContainer()).toBe(container)
})
it("after bind, the current container is set back to its previous value", () => {
const originalValue = currentContainer
const container = new Container()
container.bind(TestServiceA)
expect(currentContainer).toBe(originalValue)
})
it("dependent services are registered in the same container", () => {
const container = new Container()
const serviceB = container.bind(TestServiceB)
// @ts-expect-error getContainer is defined as a protected property, but we are leveraging it here to check
expect(serviceB.serviceA.getContainer()).toBe(container)
})
it("binding an already initialized service returns the initialized instance (services are singletons)", () => {
const container = new Container()
const serviceA = container.bind(TestServiceA)
const serviceA2 = container.bind(TestServiceA)
expect(serviceA).toBe(serviceA2)
})
it("binding a service which is a dependency of another service returns the same instance created from the dependency resolution (services are singletons)", () => {
const container = new Container()
const serviceB = container.bind(TestServiceB)
const serviceA = container.bind(TestServiceA)
expect(serviceB.serviceA).toBe(serviceA)
})
it("binding an initialized service as a dependency returns the same instance", () => {
const container = new Container()
const serviceA = container.bind(TestServiceA)
const serviceB = container.bind(TestServiceB)
expect(serviceB.serviceA).toBe(serviceA)
})
it("container emits an init event when an uninitialized service is initialized via bind and event only called once", () => {
const container = new Container()
const serviceFunc = vi.fn<
[ContainerEvent & { type: "SERVICE_INIT" }],
void
>()
container.getEventStream().subscribe((ev) => {
if (ev.type === "SERVICE_INIT") {
serviceFunc(ev)
}
})
const instance = container.bind(TestServiceA)
expect(serviceFunc).toHaveBeenCalledOnce()
expect(serviceFunc).toHaveBeenCalledWith(<ContainerEvent>{
type: "SERVICE_INIT",
serviceID: TestServiceA.ID,
})
})
it("the bind event emitted has an undefined bounderID when the service is bound directly to the container", () => {
const container = new Container()
const serviceFunc = vi.fn<
[ContainerEvent & { type: "SERVICE_BIND" }],
void
>()
container.getEventStream().subscribe((ev) => {
if (ev.type === "SERVICE_BIND") {
serviceFunc(ev)
}
})
container.bind(TestServiceA)
expect(serviceFunc).toHaveBeenCalledOnce()
expect(serviceFunc).toHaveBeenCalledWith(<ContainerEvent>{
type: "SERVICE_BIND",
boundeeID: TestServiceA.ID,
bounderID: undefined,
})
})
it("the bind event emitted has the correct bounderID when the service is bound to another service", () => {
const container = new Container()
const serviceFunc = vi.fn<
[ContainerEvent & { type: "SERVICE_BIND" }],
void
>()
container.getEventStream().subscribe((ev) => {
// We only care about the bind event of TestServiceA
if (ev.type === "SERVICE_BIND" && ev.boundeeID === TestServiceA.ID) {
serviceFunc(ev)
}
})
container.bind(TestServiceB)
expect(serviceFunc).toHaveBeenCalledOnce()
expect(serviceFunc).toHaveBeenCalledWith(<ContainerEvent>{
type: "SERVICE_BIND",
boundeeID: TestServiceA.ID,
bounderID: TestServiceB.ID,
})
})
})
describe("hasBound", () => {
it("returns true if the given service is bound to the container", () => {
const container = new Container()
container.bind(TestServiceA)
expect(container.hasBound(TestServiceA)).toEqual(true)
})
it("returns false if the given service is not bound to the container", () => {
const container = new Container()
expect(container.hasBound(TestServiceA)).toEqual(false)
})
it("returns true when the service is bound because it is a dependency of another service", () => {
const container = new Container()
container.bind(TestServiceB)
expect(container.hasBound(TestServiceA)).toEqual(true)
})
})
describe("getEventStream", () => {
it("returns an observable which emits events correctly when services are initialized", () => {
const container = new Container()
const serviceFunc = vi.fn<
[ContainerEvent & { type: "SERVICE_INIT" }],
void
>()
container.getEventStream().subscribe((ev) => {
if (ev.type === "SERVICE_INIT") {
serviceFunc(ev)
}
})
container.bind(TestServiceB)
expect(serviceFunc).toHaveBeenCalledTimes(2)
expect(serviceFunc).toHaveBeenNthCalledWith(1, <ContainerEvent>{
type: "SERVICE_INIT",
serviceID: TestServiceA.ID,
})
expect(serviceFunc).toHaveBeenNthCalledWith(2, <ContainerEvent>{
type: "SERVICE_INIT",
serviceID: TestServiceB.ID,
})
})
it("returns an observable which emits events correctly when services are bound", () => {
const container = new Container()
const serviceFunc = vi.fn<
[ContainerEvent & { type: "SERVICE_BIND" }],
void
>()
container.getEventStream().subscribe((ev) => {
if (ev.type === "SERVICE_BIND") {
serviceFunc(ev)
}
})
container.bind(TestServiceB)
expect(serviceFunc).toHaveBeenCalledTimes(2)
expect(serviceFunc).toHaveBeenNthCalledWith(1, <ContainerEvent>{
type: "SERVICE_BIND",
boundeeID: TestServiceA.ID,
bounderID: TestServiceB.ID,
})
expect(serviceFunc).toHaveBeenNthCalledWith(2, <ContainerEvent>{
type: "SERVICE_BIND",
boundeeID: TestServiceB.ID,
bounderID: undefined,
})
})
})
describe("getBoundServices", () => {
it("returns an iterator over all services bound to the container in the format [service id, service instance]", () => {
const container = new Container()
const instanceB = container.bind(TestServiceB)
const instanceA = instanceB.serviceA
expect(Array.from(container.getBoundServices())).toEqual([
[TestServiceA.ID, instanceA],
[TestServiceB.ID, instanceB],
])
})
it("returns an empty iterator if no services are bound", () => {
const container = new Container()
expect(Array.from(container.getBoundServices())).toEqual([])
})
})
})

View File

@@ -0,0 +1,66 @@
import { describe, expect, it, vi } from "vitest"
import { Service, Container } from "../lib/main"
class TestServiceA extends Service {
public static ID = "TestServiceA"
}
class TestServiceB extends Service<"test"> {
public static ID = "TestServiceB"
// Marked public to allow for testing
public readonly serviceA = this.bind(TestServiceA)
public emitTestEvent() {
this.emit("test")
}
}
describe("Service", () => {
describe("constructor", () => {
it("throws an error if the service is initialized without a container", () => {
expect(() => new TestServiceA()).toThrowError(
"Tried to initialize service with no container (ID: TestServiceA)"
)
})
})
describe("bind", () => {
it("correctly binds the dependency service using the container", () => {
const container = new Container()
const serviceA = container.bind(TestServiceA)
const serviceB = container.bind(TestServiceB)
expect(serviceB.serviceA).toBe(serviceA)
})
})
describe("getContainer", () => {
it("returns the container the service is bound to", () => {
const container = new Container()
const serviceA = container.bind(TestServiceA)
// @ts-expect-error getContainer is a protected member, we are just using it to help with testing
expect(serviceA.getContainer()).toBe(container)
})
})
describe("getEventStream", () => {
it("returns the valid event stream of the service", () => {
const container = new Container()
const serviceB = container.bind(TestServiceB)
const serviceFunc = vi.fn()
serviceB.getEventStream().subscribe(serviceFunc)
serviceB.emitTestEvent()
expect(serviceFunc).toHaveBeenCalledOnce()
expect(serviceFunc).toHaveBeenCalledWith("test")
})
})
})

View File

@@ -0,0 +1,92 @@
import { describe, expect, it, vi } from "vitest"
import { TestContainer } from "../lib/testing"
import { Service } from "../lib/service"
import { ContainerEvent } from "../lib/container"
class TestServiceA extends Service {
public static ID = "TestServiceA"
public test() {
return "real"
}
}
class TestServiceB extends Service {
public static ID = "TestServiceB"
// declared public to help with testing
public readonly serviceA = this.bind(TestServiceA)
public test() {
return this.serviceA.test()
}
}
describe("TestContainer", () => {
describe("bindMock", () => {
it("returns the fake service defined", () => {
const container = new TestContainer()
const fakeService = {
test: () => "fake",
}
const result = container.bindMock(TestServiceA, fakeService)
expect(result).toBe(fakeService)
})
it("new services bound to the container get the mock service", () => {
const container = new TestContainer()
const fakeServiceA = {
test: () => "fake",
}
container.bindMock(TestServiceA, fakeServiceA)
const serviceB = container.bind(TestServiceB)
expect(serviceB.serviceA).toBe(fakeServiceA)
})
it("container emits SERVICE_BIND event", () => {
const container = new TestContainer()
const fakeServiceA = {
test: () => "fake",
}
const serviceFunc = vi.fn<[ContainerEvent, void]>()
container.getEventStream().subscribe((ev) => {
serviceFunc(ev)
})
container.bindMock(TestServiceA, fakeServiceA)
expect(serviceFunc).toHaveBeenCalledOnce()
expect(serviceFunc).toHaveBeenCalledWith(<ContainerEvent>{
type: "SERVICE_BIND",
boundeeID: TestServiceA.ID,
bounderID: undefined,
})
})
it("throws if service already bound", () => {
const container = new TestContainer()
const fakeServiceA = {
test: () => "fake",
}
container.bindMock(TestServiceA, fakeServiceA)
expect(() => {
container.bindMock(TestServiceA, fakeServiceA)
}).toThrowError(
"Service 'TestServiceA' already bound to container. Did you already call bindMock on this ?"
)
})
})
})

2
packages/dioc/testing.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
export { default } from "./dist/testing.d.ts"
export * from "./dist/testing.d.ts"

View File

@@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"moduleResolution": "Node",
"strict": true,
"declaration": true,
"sourceMap": true,
"outDir": "dist",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"skipLibCheck": true
},
"include": ["lib"]
}

View File

@@ -0,0 +1,16 @@
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
entry: {
index: './lib/main.ts',
vue: './lib/vue.ts',
testing: './lib/testing.ts',
},
},
rollupOptions: {
external: ['vue'],
}
},
})

View File

@@ -0,0 +1,7 @@
import { defineConfig } from "vitest/config"
export default defineConfig({
test: {
}
})

2
packages/dioc/vue.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
export { default } from "./dist/vue.d.ts"
export * from "./dist/vue.d.ts"

View File

@@ -18,6 +18,7 @@
"do-lintfix": "pnpm run lintfix"
},
"dependencies": {
"dioc": "workspace:^",
"@apidevtools/swagger-parser": "^10.1.0",
"@codemirror/autocomplete": "^6.0.3",
"@codemirror/commands": "^6.0.1",

View File

@@ -0,0 +1,13 @@
import { HoppModule } from "."
import { Container } from "dioc"
import { diocPlugin } from "dioc/vue"
export default <HoppModule>{
onVueAppInit(app) {
// TODO: look into this
// @ts-expect-error Something weird with Vue versions
app.use(diocPlugin, {
container: new Container(),
})
},
}

198
pnpm-lock.yaml generated
View File

@@ -58,6 +58,25 @@ importers:
specifier: ^4.6.3
version: 4.7.4
packages/dioc:
dependencies:
rxjs:
specifier: ^7.8.1
version: 7.8.1
vue:
specifier: ^3.2.25
version: 3.2.45
devDependencies:
typescript:
specifier: ^4.9.4
version: 4.9.4
vite:
specifier: ^4.0.4
version: 4.0.4(@types/node@17.0.45)
vitest:
specifier: ^0.29.3
version: 0.29.8(terser@5.14.1)
packages/hoppscotch-backend:
dependencies:
'@nestjs-modules/mailer':
@@ -442,6 +461,9 @@ importers:
buffer:
specifier: ^6.0.3
version: 6.0.3
dioc:
specifier: workspace:^
version: link:../dioc
esprima:
specifier: ^4.0.1
version: 4.0.1
@@ -1619,7 +1641,7 @@ packages:
'@babel/parser': 7.21.2
'@babel/runtime': 7.18.6
'@babel/traverse': 7.18.6
'@babel/types': 7.21.2
'@babel/types': 7.18.7
babel-preset-fbjs: 3.4.0(@babel/core@7.18.6)
chalk: 4.1.2
fb-watchman: 2.0.1
@@ -1648,7 +1670,7 @@ packages:
'@babel/parser': 7.21.2
'@babel/runtime': 7.18.6
'@babel/traverse': 7.18.6
'@babel/types': 7.21.2
'@babel/types': 7.18.7
babel-preset-fbjs: 3.4.0(@babel/core@7.18.6)
chalk: 4.1.2
fb-watchman: 2.0.1
@@ -1696,10 +1718,10 @@ packages:
'@babel/helper-compilation-targets': 7.18.6(@babel/core@7.18.6)
'@babel/helper-module-transforms': 7.18.6
'@babel/helpers': 7.18.6
'@babel/parser': 7.21.2
'@babel/parser': 7.18.6
'@babel/template': 7.18.6
'@babel/traverse': 7.18.6
'@babel/types': 7.21.2
'@babel/types': 7.18.7
convert-source-map: 1.8.0
debug: 4.3.4(supports-color@9.2.2)
gensync: 1.0.0-beta.2
@@ -1713,7 +1735,7 @@ packages:
resolution: {integrity: sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.21.2
'@babel/types': 7.18.7
'@jridgewell/gen-mapping': 0.3.2
jsesc: 2.5.2
dev: true
@@ -1820,14 +1842,14 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
'@babel/template': 7.18.6
'@babel/types': 7.21.2
'@babel/types': 7.18.7
dev: true
/@babel/helper-hoist-variables@7.18.6:
resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.21.2
'@babel/types': 7.18.7
dev: true
/@babel/helper-member-expression-to-functions@7.18.6:
@@ -1852,10 +1874,10 @@ packages:
'@babel/helper-module-imports': 7.18.6
'@babel/helper-simple-access': 7.18.6
'@babel/helper-split-export-declaration': 7.18.6
'@babel/helper-validator-identifier': 7.19.1
'@babel/helper-validator-identifier': 7.18.6
'@babel/template': 7.18.6
'@babel/traverse': 7.18.6
'@babel/types': 7.21.2
'@babel/types': 7.18.7
transitivePeerDependencies:
- supports-color
dev: true
@@ -1923,13 +1945,17 @@ packages:
resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.21.2
'@babel/types': 7.18.7
dev: true
/@babel/helper-string-parser@7.19.4:
resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==}
engines: {node: '>=6.9.0'}
/@babel/helper-validator-identifier@7.18.6:
resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==}
engines: {node: '>=6.9.0'}
/@babel/helper-validator-identifier@7.19.1:
resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==}
engines: {node: '>=6.9.0'}
@@ -1957,7 +1983,7 @@ packages:
dependencies:
'@babel/template': 7.18.6
'@babel/traverse': 7.18.6
'@babel/types': 7.21.2
'@babel/types': 7.18.7
transitivePeerDependencies:
- supports-color
dev: true
@@ -1966,7 +1992,7 @@ packages:
resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-validator-identifier': 7.19.1
'@babel/helper-validator-identifier': 7.18.6
chalk: 2.4.2
js-tokens: 4.0.0
@@ -1982,7 +2008,7 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
dependencies:
'@babel/types': 7.21.2
'@babel/types': 7.20.7
dev: true
/@babel/parser@7.21.2:
@@ -1990,7 +2016,7 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
dependencies:
'@babel/types': 7.18.7
'@babel/types': 7.21.2
/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.18.6):
resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==}
@@ -2686,7 +2712,7 @@ packages:
'@babel/helper-module-imports': 7.18.6
'@babel/helper-plugin-utils': 7.18.6
'@babel/plugin-syntax-jsx': 7.18.6(@babel/core@7.18.6)
'@babel/types': 7.21.2
'@babel/types': 7.18.7
dev: true
/@babel/plugin-transform-regenerator@7.18.6(@babel/core@7.18.6):
@@ -2897,7 +2923,7 @@ packages:
dependencies:
'@babel/code-frame': 7.18.6
'@babel/parser': 7.21.2
'@babel/types': 7.21.2
'@babel/types': 7.18.7
dev: true
/@babel/template@7.20.7:
@@ -2905,8 +2931,8 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.18.6
'@babel/parser': 7.21.2
'@babel/types': 7.21.2
'@babel/parser': 7.20.15
'@babel/types': 7.20.7
dev: true
/@babel/traverse@7.18.6:
@@ -2920,7 +2946,7 @@ packages:
'@babel/helper-hoist-variables': 7.18.6
'@babel/helper-split-export-declaration': 7.18.6
'@babel/parser': 7.21.2
'@babel/types': 7.21.2
'@babel/types': 7.18.7
debug: 4.3.4(supports-color@9.2.2)
globals: 11.12.0
transitivePeerDependencies:
@@ -2931,7 +2957,7 @@ packages:
resolution: {integrity: sha512-QG3yxTcTIBoAcQmkCs+wAPYZhu7Dk9rXKacINfNbdJDNERTbLQbHGyVG8q/YGMPeCJRIhSY0+fTc5+xuh6WPSQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-validator-identifier': 7.19.1
'@babel/helper-validator-identifier': 7.18.6
to-fast-properties: 2.0.0
/@babel/types@7.20.7:
@@ -3178,10 +3204,10 @@ packages:
'@commitlint/execute-rule': 16.2.1
'@commitlint/resolve-extends': 16.2.1
'@commitlint/types': 16.2.1
'@types/node': 18.11.10
'@types/node': 17.0.45
chalk: 4.1.2
cosmiconfig: 7.0.1
cosmiconfig-typescript-loader: 2.0.2(@types/node@18.11.10)(cosmiconfig@7.0.1)(typescript@4.9.4)
cosmiconfig-typescript-loader: 2.0.2(@types/node@17.0.45)(cosmiconfig@7.0.1)(typescript@4.9.4)
lodash: 4.17.21
resolve-from: 5.0.0
typescript: 4.9.4
@@ -4952,9 +4978,9 @@ packages:
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@babel/parser': 7.21.2
'@babel/parser': 7.18.6
'@babel/traverse': 7.18.6
'@babel/types': 7.21.2
'@babel/types': 7.18.7
'@graphql-tools/utils': 8.8.0(graphql@15.8.0)
graphql: 15.8.0
tslib: 2.5.0
@@ -4967,7 +4993,7 @@ packages:
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@babel/parser': 7.21.2
'@babel/parser': 7.20.15
'@babel/plugin-syntax-import-assertions': 7.20.0(@babel/core@7.18.6)
'@babel/traverse': 7.18.6
'@babel/types': 7.21.2
@@ -5416,7 +5442,7 @@ packages:
engines: {node: ^8.13.0 || >=10.10.0}
dependencies:
'@grpc/proto-loader': 0.6.13
'@types/node': 18.11.10
'@types/node': 17.0.45
dev: false
/@grpc/proto-loader@0.6.13:
@@ -5772,7 +5798,7 @@ packages:
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
dependencies:
'@jest/types': 27.5.1
'@types/node': 18.11.10
'@types/node': 17.0.45
chalk: 4.1.2
jest-message-util: 27.5.1
jest-util: 27.5.1
@@ -5805,7 +5831,7 @@ packages:
'@jest/test-result': 27.5.1
'@jest/transform': 27.5.1
'@jest/types': 27.5.1
'@types/node': 18.11.10
'@types/node': 17.0.45
ansi-escapes: 4.3.2
chalk: 4.1.2
emittery: 0.8.1
@@ -5884,7 +5910,7 @@ packages:
dependencies:
'@jest/fake-timers': 27.5.1
'@jest/types': 27.5.1
'@types/node': 18.11.10
'@types/node': 17.0.45
jest-mock: 27.5.1
dev: true
@@ -5935,7 +5961,7 @@ packages:
dependencies:
'@jest/types': 27.5.1
'@sinonjs/fake-timers': 8.1.0
'@types/node': 18.11.10
'@types/node': 17.0.45
jest-message-util: 27.5.1
jest-mock: 27.5.1
jest-util: 27.5.1
@@ -5988,7 +6014,7 @@ packages:
'@jest/test-result': 27.5.1
'@jest/transform': 27.5.1
'@jest/types': 27.5.1
'@types/node': 18.11.10
'@types/node': 17.0.45
chalk: 4.1.2
collect-v8-coverage: 1.0.1
exit: 0.1.2
@@ -6182,7 +6208,7 @@ packages:
dependencies:
'@types/istanbul-lib-coverage': 2.0.4
'@types/istanbul-reports': 3.0.1
'@types/node': 18.11.10
'@types/node': 17.0.45
'@types/yargs': 16.0.4
chalk: 4.1.2
dev: true
@@ -7274,7 +7300,7 @@ packages:
resolution: {integrity: sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==}
dependencies:
'@babel/parser': 7.21.2
'@babel/types': 7.21.2
'@babel/types': 7.18.7
'@types/babel__generator': 7.6.4
'@types/babel__template': 7.4.1
'@types/babel__traverse': 7.17.1
@@ -7296,7 +7322,7 @@ packages:
/@types/babel__traverse@7.17.1:
resolution: {integrity: sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==}
dependencies:
'@babel/types': 7.21.2
'@babel/types': 7.18.7
dev: true
/@types/bcrypt@5.0.0:
@@ -8500,7 +8526,7 @@ packages:
/@vue/compiler-core@3.2.45:
resolution: {integrity: sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==}
dependencies:
'@babel/parser': 7.21.2
'@babel/parser': 7.18.6
'@vue/shared': 3.2.45
estree-walker: 2.0.2
source-map: 0.6.1
@@ -8534,7 +8560,7 @@ packages:
/@vue/compiler-sfc@3.2.37:
resolution: {integrity: sha512-+7i/2+9LYlpqDv+KTtWhOZH+pa8/HnX/905MdVmAcI/mPQOBwkHHIzrsEsucyOIZQYMkXUiTkmZq5am/NyXKkg==}
dependencies:
'@babel/parser': 7.21.2
'@babel/parser': 7.18.6
'@vue/compiler-core': 3.2.37
'@vue/compiler-dom': 3.2.37
'@vue/compiler-ssr': 3.2.37
@@ -8542,7 +8568,7 @@ packages:
'@vue/shared': 3.2.37
estree-walker: 2.0.2
magic-string: 0.25.9
postcss: 8.4.21
postcss: 8.4.19
source-map: 0.6.1
/@vue/compiler-sfc@3.2.39:
@@ -8657,7 +8683,7 @@ packages:
/@vue/reactivity-transform@3.2.45:
resolution: {integrity: sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==}
dependencies:
'@babel/parser': 7.21.2
'@babel/parser': 7.18.6
'@vue/compiler-core': 3.2.45
'@vue/shared': 3.2.45
estree-walker: 2.0.2
@@ -9070,12 +9096,12 @@ packages:
acorn-walk: 8.2.0
dev: true
/acorn-import-assertions@1.8.0(acorn@8.8.2):
/acorn-import-assertions@1.8.0(acorn@8.8.0):
resolution: {integrity: sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==}
peerDependencies:
acorn: ^8
dependencies:
acorn: 8.8.2
acorn: 8.8.0
/acorn-jsx@5.3.2(acorn@7.4.1):
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
@@ -10582,7 +10608,7 @@ packages:
dependencies:
'@iarna/toml': 2.2.5
/cosmiconfig-typescript-loader@2.0.2(@types/node@18.11.10)(cosmiconfig@7.0.1)(typescript@4.9.4):
/cosmiconfig-typescript-loader@2.0.2(@types/node@17.0.45)(cosmiconfig@7.0.1)(typescript@4.9.4):
resolution: {integrity: sha512-KmE+bMjWMXJbkWCeY4FJX/npHuZPNr9XF9q9CIQ/bpFwi1qHfCmSiKarrCcRa0LO4fWjk93pVoeRtJAkTGcYNw==}
engines: {node: '>=12', npm: '>=6'}
peerDependencies:
@@ -10590,9 +10616,9 @@ packages:
cosmiconfig: '>=7'
typescript: '>=3'
dependencies:
'@types/node': 18.11.10
'@types/node': 17.0.45
cosmiconfig: 7.0.1
ts-node: 10.8.2(@types/node@18.11.10)(typescript@4.9.4)
ts-node: 10.8.2(@types/node@17.0.45)(typescript@4.9.4)
typescript: 4.9.4
transitivePeerDependencies:
- '@swc/core'
@@ -13498,7 +13524,7 @@ packages:
graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
graphql: 15.8.0
tslib: 2.5.0
tslib: 2.4.1
/graphql-tag@2.12.6(graphql@16.6.0):
resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==}
@@ -13507,7 +13533,7 @@ packages:
graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
graphql: 16.6.0
tslib: 2.5.0
tslib: 2.4.1
dev: true
/graphql-ws@5.11.3(graphql@16.6.0):
@@ -14481,7 +14507,7 @@ packages:
engines: {node: '>=8'}
dependencies:
'@babel/core': 7.18.6
'@babel/parser': 7.21.2
'@babel/parser': 7.18.6
'@istanbuljs/schema': 0.1.3
istanbul-lib-coverage: 3.2.0
semver: 6.3.0
@@ -14559,7 +14585,7 @@ packages:
'@jest/environment': 27.5.1
'@jest/test-result': 27.5.1
'@jest/types': 27.5.1
'@types/node': 18.11.10
'@types/node': 17.0.45
chalk: 4.1.2
co: 4.6.0
dedent: 0.7.0
@@ -14827,7 +14853,7 @@ packages:
'@jest/environment': 27.5.1
'@jest/fake-timers': 27.5.1
'@jest/types': 27.5.1
'@types/node': 18.11.10
'@types/node': 17.0.45
jest-mock: 27.5.1
jest-util: 27.5.1
jsdom: 16.7.0
@@ -14845,7 +14871,7 @@ packages:
'@jest/environment': 27.5.1
'@jest/fake-timers': 27.5.1
'@jest/types': 27.5.1
'@types/node': 18.11.10
'@types/node': 17.0.45
jest-mock: 27.5.1
jest-util: 27.5.1
dev: true
@@ -14883,7 +14909,7 @@ packages:
dependencies:
'@jest/types': 27.5.1
'@types/graceful-fs': 4.1.5
'@types/node': 18.11.10
'@types/node': 17.0.45
anymatch: 3.1.2
fb-watchman: 2.0.1
graceful-fs: 4.2.10
@@ -14924,7 +14950,7 @@ packages:
'@jest/source-map': 27.5.1
'@jest/test-result': 27.5.1
'@jest/types': 27.5.1
'@types/node': 18.11.10
'@types/node': 17.0.45
chalk: 4.1.2
co: 4.6.0
expect: 27.5.1
@@ -14984,7 +15010,7 @@ packages:
chalk: 4.1.2
jest-diff: 29.3.1
jest-get-type: 29.2.0
pretty-format: 29.4.1
pretty-format: 29.3.1
dev: true
/jest-matcher-utils@29.4.1:
@@ -15037,7 +15063,7 @@ packages:
chalk: 4.1.2
graceful-fs: 4.2.10
micromatch: 4.0.5
pretty-format: 29.4.1
pretty-format: 29.3.1
slash: 3.0.0
stack-utils: 2.0.5
dev: true
@@ -15073,7 +15099,7 @@ packages:
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
dependencies:
'@jest/types': 27.5.1
'@types/node': 18.11.10
'@types/node': 17.0.45
dev: true
/jest-mock@29.4.1:
@@ -15180,7 +15206,7 @@ packages:
'@jest/test-result': 27.5.1
'@jest/transform': 27.5.1
'@jest/types': 27.5.1
'@types/node': 18.11.10
'@types/node': 17.0.45
chalk: 4.1.2
emittery: 0.8.1
graceful-fs: 4.2.10
@@ -15297,7 +15323,7 @@ packages:
resolution: {integrity: sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
dependencies:
'@types/node': 18.11.10
'@types/node': 17.0.45
graceful-fs: 4.2.10
dev: true
@@ -15309,7 +15335,7 @@ packages:
'@babel/generator': 7.18.7
'@babel/plugin-syntax-typescript': 7.18.6(@babel/core@7.18.6)
'@babel/traverse': 7.18.6
'@babel/types': 7.21.2
'@babel/types': 7.18.7
'@jest/transform': 27.5.1
'@jest/types': 27.5.1
'@types/babel__traverse': 7.17.1
@@ -15340,7 +15366,7 @@ packages:
'@babel/plugin-syntax-jsx': 7.18.6(@babel/core@7.18.6)
'@babel/plugin-syntax-typescript': 7.18.6(@babel/core@7.18.6)
'@babel/traverse': 7.18.6
'@babel/types': 7.21.2
'@babel/types': 7.18.7
'@jest/expect-utils': 29.4.1
'@jest/transform': 29.4.1
'@jest/types': 29.4.1
@@ -15368,7 +15394,7 @@ packages:
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
dependencies:
'@jest/types': 27.5.1
'@types/node': 18.11.10
'@types/node': 17.0.45
chalk: 4.1.2
ci-info: 3.3.2
graceful-fs: 4.2.10
@@ -15441,7 +15467,7 @@ packages:
dependencies:
'@jest/test-result': 27.5.1
'@jest/types': 27.5.1
'@types/node': 18.11.10
'@types/node': 17.0.45
ansi-escapes: 4.3.2
chalk: 4.1.2
jest-util: 27.5.1
@@ -18591,6 +18617,14 @@ packages:
optionalDependencies:
fsevents: 2.3.2
/rollup@3.24.0:
resolution: {integrity: sha512-OgraHOIg2YpHQTjl0/ymWfFNBEyPucB7lmhXrQUh38qNOegxLapSPFs9sNr0qKR75awW41D93XafoR2QfhBdUQ==}
engines: {node: '>=14.18.0', npm: '>=8.0.0'}
hasBin: true
optionalDependencies:
fsevents: 2.3.2
dev: true
/run-async@2.4.1:
resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==}
engines: {node: '>=0.12.0'}
@@ -19934,7 +19968,7 @@ packages:
- '@types/node'
dev: false
/ts-node@10.8.2(@types/node@18.11.10)(typescript@4.9.4):
/ts-node@10.8.2(@types/node@17.0.45)(typescript@4.9.4):
resolution: {integrity: sha512-LYdGnoGddf1D6v8REPtIH+5iq/gTDuZqv2/UJUU7tKjuEU8xVZorBM+buCGNjj+pGEud+sOoM4CX3/YzINpENA==}
hasBin: true
peerDependencies:
@@ -19953,7 +19987,7 @@ packages:
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.3
'@types/node': 18.11.10
'@types/node': 17.0.45
acorn: 8.8.2
acorn-walk: 8.2.0
arg: 4.1.3
@@ -21070,7 +21104,7 @@ packages:
dependencies:
'@types/node': 17.0.45
esbuild: 0.15.15
postcss: 8.4.19
postcss: 8.4.21
resolve: 1.22.1
rollup: 2.79.1
sass: 1.53.0
@@ -21078,6 +21112,40 @@ packages:
optionalDependencies:
fsevents: 2.3.2
/vite@4.0.4(@types/node@17.0.45):
resolution: {integrity: sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
peerDependencies:
'@types/node': '>= 14'
less: '*'
sass: '*'
stylus: '*'
sugarss: '*'
terser: ^5.4.0
peerDependenciesMeta:
'@types/node':
optional: true
less:
optional: true
sass:
optional: true
stylus:
optional: true
sugarss:
optional: true
terser:
optional: true
dependencies:
'@types/node': 17.0.45
esbuild: 0.16.17
postcss: 8.4.21
resolve: 1.22.1
rollup: 3.24.0
optionalDependencies:
fsevents: 2.3.2
dev: true
/vitest@0.29.8(terser@5.14.1):
resolution: {integrity: sha512-JIAVi2GK5cvA6awGpH0HvH/gEG9PZ0a/WoxdiV3PmqK+3CjQMf8c+J/Vhv4mdZ2nRyXFw66sAg6qz7VNkaHfDQ==}
engines: {node: '>=v14.16.0'}
@@ -21669,8 +21737,8 @@ packages:
'@webassemblyjs/ast': 1.11.1
'@webassemblyjs/wasm-edit': 1.11.1
'@webassemblyjs/wasm-parser': 1.11.1
acorn: 8.8.2
acorn-import-assertions: 1.8.0(acorn@8.8.2)
acorn: 8.8.0
acorn-import-assertions: 1.8.0(acorn@8.8.0)
browserslist: 4.21.1
chrome-trace-event: 1.0.3
enhanced-resolve: 5.12.0