diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..5d47c21 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/examples/with-fastify/src/api/users/users.controller.ts b/examples/with-fastify/src/api/users/users.controller.ts index 39558b9..915f23b 100644 --- a/examples/with-fastify/src/api/users/users.controller.ts +++ b/examples/with-fastify/src/api/users/users.controller.ts @@ -34,7 +34,7 @@ export function userController( { schema: userBodySchema }, async (request, reply) => { const { username, age } = request.body - const newUser = service.addUser(username, age) + const newUser = await service.addUser(username, age) if (!newUser) return reply.status(400).send('Username exist') return newUser } diff --git a/examples/with-fastify/src/api/users/users.service.ts b/examples/with-fastify/src/api/users/users.service.ts index af8c4a8..1208c5b 100644 --- a/examples/with-fastify/src/api/users/users.service.ts +++ b/examples/with-fastify/src/api/users/users.service.ts @@ -1,9 +1,9 @@ import { User, Users } from '../../dto/users.dto.js' -import type { Steno } from '@stenodb/fastify' +import type { AsyncProvider } from '@stenodb/fastify' import type { FastifyInstance } from 'fastify' export class UserService { - #users: Steno.NodeProvider + #users: AsyncProvider constructor(private readonly fastify: FastifyInstance) { this.#users = this.fastify.steno.get('users')! diff --git a/examples/with-fastify/src/dto/users.dto.ts b/examples/with-fastify/src/dto/users.dto.ts index e0b051b..42c3a9b 100644 --- a/examples/with-fastify/src/dto/users.dto.ts +++ b/examples/with-fastify/src/dto/users.dto.ts @@ -1,5 +1,5 @@ import { Exclude, Type } from 'class-transformer' -import { IsNumber, IsString, Length } from 'class-validator' +import { IsNumber, IsOptional, IsString, Length } from 'class-validator' import { Post } from './posts.dto.js' export class Users { @@ -13,6 +13,7 @@ export class Users { export class User { @Exclude({ toPlainOnly: true }) + @IsOptional() @IsNumber() userId: number diff --git a/examples/with-fastify/src/index.ts b/examples/with-fastify/src/index.ts index fec67fe..64973d4 100644 --- a/examples/with-fastify/src/index.ts +++ b/examples/with-fastify/src/index.ts @@ -16,11 +16,7 @@ const usersInitialData = new Users( new User(2, 'alice', 23) ) -const usersAdapter = new AsyncAdapter( - 'users', - Users, - usersInitialData -) +const usersAdapter = new AsyncAdapter('users', Users, usersInitialData) fastify.register(FastifySteno, { path: resolve(dirname(fileURLToPath(import.meta.url)), '..', 'db'), diff --git a/examples/with-nest/src/app.service.ts b/examples/with-nest/src/app.service.ts index 75bb6a8..53eac00 100644 --- a/examples/with-nest/src/app.service.ts +++ b/examples/with-nest/src/app.service.ts @@ -1,10 +1,10 @@ import { Injectable, OnModuleInit } from '@nestjs/common' -import { Steno, StenoService } from '@stenodb/nest' +import { AsyncProvider, StenoService } from '@stenodb/nest' import { CreateUserDto, initialUsersData, Users } from './dto/users.dto' @Injectable() export class UsersService implements OnModuleInit { - private usersProvider: Steno.NodeProvider + private usersProvider: AsyncProvider constructor(private readonly stenoService: StenoService) {} diff --git a/examples/with-nest/src/dto/users.dto.ts b/examples/with-nest/src/dto/users.dto.ts index a8ddc73..dd06ca6 100644 --- a/examples/with-nest/src/dto/users.dto.ts +++ b/examples/with-nest/src/dto/users.dto.ts @@ -1,5 +1,12 @@ import { Exclude, Type } from 'class-transformer' -import { IsNumber, IsString, Length, Max, Min } from 'class-validator' +import { + IsNumber, + IsOptional, + IsString, + Length, + Max, + Min +} from 'class-validator' export class Users { @Type(() => CreateUserDto) @@ -11,8 +18,9 @@ export class Users { } export class CreateUserDto { - @IsNumber() @Exclude({ toPlainOnly: true }) + @IsOptional() + @IsNumber() id: number @IsString() diff --git a/examples/with-node/tsconfig.json b/examples/with-node/tsconfig.json index 9d06e0e..8e23fbf 100644 --- a/examples/with-node/tsconfig.json +++ b/examples/with-node/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "@crashmax/tsconfig", "compilerOptions": { + "moduleResolution": "NodeNext", "experimentalDecorators": true, "emitDecoratorMetadata": true, "outDir": "dist" diff --git a/package.json b/package.json index a1aa2f6..7b6b14a 100644 --- a/package.json +++ b/package.json @@ -12,11 +12,13 @@ "dev:examples": "turbo run dev --filter=./examples/*", "build": "turbo run build --filter=./packages/*", "build:examples": "turbo run build --filter=./examples/*", + "test": "turbo run test", "format": "prettier --write --ignore-unknown **" }, "devDependencies": { "@crashmax/prettier-config": "3.0.1", "@crashmax/tsconfig": "1.0.2", + "ava": "5.2.0", "cross-env": "7.0.3", "nodemon": "2.0.20", "ts-node": "10.9.1", diff --git a/packages/browser/package.json b/packages/browser/package.json index 3572b4a..22a5dfa 100644 --- a/packages/browser/package.json +++ b/packages/browser/package.json @@ -1,17 +1,18 @@ { "name": "@stenodb/browser", "description": "✍ Easy to use local JSON database", + "type": "module", "version": "3.4.1", "exports": { ".": { "types": "./dist/index.d.ts", "require": "./dist/index.js", - "default": "./dist/index.mjs" + "default": "./dist/index.js" } }, "types": "./dist/index.d.ts", "main": "./dist/index.js", - "module": "./dist/index.mjs", + "module": "./dist/index.js", "files": [ "dist", "src" @@ -52,6 +53,16 @@ "peerDependencies": { "@stenodb/logger": "workspace:3.4.1" }, + "ava": { + "snapshotDir": "test/snapshots", + "extensions": { + "ts": "module" + }, + "nodeArguments": [ + "--loader=ts-node/esm", + "--no-warnings" + ] + }, "engines": { "node": ">=14.16" } diff --git a/packages/browser/src/adapter/LocalStorage.ts b/packages/browser/src/adapter/LocalStorage.ts index 74fc95b..6161db7 100644 --- a/packages/browser/src/adapter/LocalStorage.ts +++ b/packages/browser/src/adapter/LocalStorage.ts @@ -1,8 +1,8 @@ import { BrowserStorage } from './WebStorage.js' -import type { Steno } from '../types.js' +import type { ClassEntity } from '@stenodb/utils' export class LocalStorage extends BrowserStorage { - constructor(name: string, entity: Steno.Entity, initialData?: T) { + constructor(name: string, entity: ClassEntity, initialData?: T) { super(name, localStorage, entity, initialData) } } diff --git a/packages/browser/src/adapter/SessionStorage.ts b/packages/browser/src/adapter/SessionStorage.ts index 910b746..a3e966b 100644 --- a/packages/browser/src/adapter/SessionStorage.ts +++ b/packages/browser/src/adapter/SessionStorage.ts @@ -1,8 +1,8 @@ import { BrowserStorage } from './WebStorage.js' -import type { Steno } from '../types.js' +import type { ClassEntity } from '@stenodb/utils' export class SessionStorage extends BrowserStorage { - constructor(name: string, entity: Steno.Entity, initialData?: T) { + constructor(name: string, entity: ClassEntity, initialData?: T) { super(name, sessionStorage, entity, initialData) } } diff --git a/packages/browser/src/adapter/WebStorage.ts b/packages/browser/src/adapter/WebStorage.ts index a56ee5e..d0ce574 100644 --- a/packages/browser/src/adapter/WebStorage.ts +++ b/packages/browser/src/adapter/WebStorage.ts @@ -1,6 +1,6 @@ import { dataTransformer, entityTransformer } from '@stenodb/utils' -import type { Steno } from '../types.js' import type { BaseLogger } from '@stenodb/logger' +import type { ClassEntity } from '@stenodb/utils' import type { DataTransformer, EntityTransformer } from '@stenodb/utils' export class BrowserStorage { @@ -17,7 +17,7 @@ export class BrowserStorage { constructor( name: string, storage: Storage, - entity: Steno.Entity, + entity: ClassEntity, initialData?: T ) { this.name = name diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index 6752166..c695ccb 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -1,4 +1,5 @@ export * from './adapter/LocalStorage.js' export * from './adapter/SessionStorage.js' export * from './provider/BrowserProvider.js' +export * from './provider/StorageProvider.js' export * from './types.js' diff --git a/packages/browser/src/provider/BrowserProvider.ts b/packages/browser/src/provider/BrowserProvider.ts index 2a9268b..41cc4b0 100644 --- a/packages/browser/src/provider/BrowserProvider.ts +++ b/packages/browser/src/provider/BrowserProvider.ts @@ -1,20 +1,20 @@ import { StorageProvider } from './StorageProvider.js' -import type { Steno } from '../types.js' +import type { BrowserProviderOptions, BrowserStorageAdapter } from '../types.js' export class BrowserProvider { - #options: Steno.BrowserProviderOptions + #options: BrowserProviderOptions - constructor(options: Steno.BrowserProviderOptions = {}) { + constructor(options: BrowserProviderOptions = {}) { this.#options = options } - private registerAdapterModules(adapter: Steno.BrowserAdapter) { + private registerAdapterModules(adapter: BrowserStorageAdapter): void { if (!this.#options?.logger) return const logger = this.#options.logger(adapter.name) adapter.registerLogger(logger) } - create(adapter: Steno.BrowserAdapter): StorageProvider { + create(adapter: BrowserStorageAdapter): StorageProvider { this.registerAdapterModules(adapter) return new StorageProvider(adapter) } diff --git a/packages/browser/src/provider/StorageProvider.ts b/packages/browser/src/provider/StorageProvider.ts index 2780911..045cac3 100644 --- a/packages/browser/src/provider/StorageProvider.ts +++ b/packages/browser/src/provider/StorageProvider.ts @@ -1,9 +1,9 @@ -import type { Steno } from '../types.js' +import type { BrowserStorageAdapter } from '../types.js' export class StorageProvider { - #adapter: Steno.BrowserAdapter + #adapter: BrowserStorageAdapter - constructor(adapter: Steno.BrowserAdapter) { + constructor(adapter: BrowserStorageAdapter) { this.#adapter = adapter } diff --git a/packages/browser/src/types.ts b/packages/browser/src/types.ts index 0e62e43..722982c 100644 --- a/packages/browser/src/types.ts +++ b/packages/browser/src/types.ts @@ -1,15 +1,9 @@ import type { LocalStorage } from './adapter/LocalStorage.js' import type { SessionStorage } from './adapter/SessionStorage.js' -import type { StorageProvider } from './provider/StorageProvider.js' import type { CreateLogger } from '@stenodb/logger' -import type { ClassEntity } from '@stenodb/utils' -export namespace Steno { - export type Entity = ClassEntity - export type BrowserAdapter = LocalStorage | SessionStorage - export type BrowserProvider = StorageProvider +export type BrowserStorageAdapter = LocalStorage | SessionStorage - export interface BrowserProviderOptions { - logger?: CreateLogger - } +export interface BrowserProviderOptions { + logger?: CreateLogger } diff --git a/packages/fastify/package.json b/packages/fastify/package.json index a7acc7a..74077a0 100644 --- a/packages/fastify/package.json +++ b/packages/fastify/package.json @@ -1,16 +1,17 @@ { "name": "@stenodb/fastify", "version": "3.4.1", + "type": "module", "exports": { ".": { "types": "./dist/index.d.ts", "require": "./dist/index.js", - "default": "./dist/index.mjs" + "default": "./dist/index.js" } }, "types": "./dist/index.d.ts", "main": "./dist/index.js", - "module": "./dist/index.mjs", + "module": "./dist/index.js", "files": [ "dist", "src" @@ -21,6 +22,7 @@ }, "dependencies": { "@stenodb/node": "workspace:3.4.1", + "@stenodb/utils": "workspace:3.4.1", "class-validator-jsonschema": "5.0.0", "fastify-plugin": "4.5.0" }, @@ -32,6 +34,16 @@ "@stenodb/node": "workspace:3.4.1", "fastify": "^4.0.0" }, + "ava": { + "snapshotDir": "test/snapshots", + "extensions": { + "ts": "module" + }, + "nodeArguments": [ + "--loader=ts-node/esm", + "--no-warnings" + ] + }, "engines": { "node": ">=14.16" } diff --git a/packages/fastify/src/index.ts b/packages/fastify/src/index.ts index cb4fb6f..b831d8b 100644 --- a/packages/fastify/src/index.ts +++ b/packages/fastify/src/index.ts @@ -1,13 +1,14 @@ -import { AsyncAdapter, Steno, SyncAdapter } from '@stenodb/node' +import { AsyncAdapter, AsyncProvider } from '@stenodb/node' import fp from 'fastify-plugin' import { StenoPlugin } from './plugin.js' import type { StenoOptions } from './types.js' +import type { ClassEntity } from '@stenodb/utils' const FastifySteno = fp(StenoPlugin.createInstance, { name: '@stenodb/fastify', fastify: '4.x' }) -export { FastifySteno, AsyncAdapter, SyncAdapter } -export type { StenoOptions, Steno } +export { FastifySteno, AsyncAdapter, AsyncProvider } +export type { StenoOptions, ClassEntity } export default StenoPlugin.createInstance diff --git a/packages/fastify/src/plugin.ts b/packages/fastify/src/plugin.ts index 97f045d..0216fbb 100644 --- a/packages/fastify/src/plugin.ts +++ b/packages/fastify/src/plugin.ts @@ -1,20 +1,21 @@ -import { AsyncAdapter, NodeProvider, SyncAdapter } from '@stenodb/node' +import { AsyncAdapter, NodeProvider } from '@stenodb/node' import { targetConstructorToSchema } from 'class-validator-jsonschema' import type { StenoOptions } from './types' -import type { Steno } from '@stenodb/node' +import type { AsyncProvider } from '@stenodb/node' +import type { ClassEntity } from '@stenodb/utils' import type { FastifyInstance } from 'fastify' export class StenoPlugin { #fastify: FastifyInstance #options: StenoOptions - #provider: NodeProvider - #databases: Map> + #db: NodeProvider + #providers: Map> constructor(fastify: FastifyInstance, options: StenoOptions) { this.#fastify = fastify this.#options = options - this.#provider = new NodeProvider(options) - this.#databases = new Map>() + this.#db = new NodeProvider(options) + this.#providers = new Map>() this.#fastify.decorate('steno', { get: this.getDatabase.bind(this) }) } @@ -33,18 +34,17 @@ export class StenoPlugin { this.registerEntities() for (const adapter of this.#options.adapters) { - const db = await this.#provider.create(adapter) + let provider: AsyncProvider - if (adapter instanceof SyncAdapter) { - db.read() - } else if (adapter instanceof AsyncAdapter) { - await db.read() + if (adapter instanceof AsyncAdapter) { + provider = await this.#db.create(adapter) + await provider.read() } else { throw new TypeError('Invalid adapter') } this.addSchema(adapter.entity) - this.#databases.set(adapter.fileName, db) + this.#providers.set(adapter.fileName, provider) } } @@ -55,7 +55,7 @@ export class StenoPlugin { } } - private addSchema(entity: Steno.Entity): void { + private addSchema(entity: ClassEntity): void { if (this.#fastify.getSchema(entity.name)) return const schema = targetConstructorToSchema( entity, @@ -65,9 +65,9 @@ export class StenoPlugin { this.#fastify.addSchema({ ...schema, $id: entity.name }) } - private getDatabase>( + private getDatabase>( name: string - ): Steno.NodeProvider | undefined { - return this.#databases.get(name) + ): AsyncProvider | undefined { + return this.#providers.get(name) } } diff --git a/packages/fastify/src/types.ts b/packages/fastify/src/types.ts index bca63bc..7c07d23 100644 --- a/packages/fastify/src/types.ts +++ b/packages/fastify/src/types.ts @@ -1,16 +1,21 @@ -import type { Steno } from '@stenodb/node' +import type { + AsyncAdapter, + AsyncProvider, + NodeProviderOptions +} from '@stenodb/node' +import type { ClassEntity } from '@stenodb/utils' import type { IOptions } from 'class-validator-jsonschema/build/options' -export interface StenoOptions extends Steno.NodeProviderOptions { - adapters: Steno.NodeAdapter[] - entities?: Steno.Entity[] +export interface StenoOptions extends NodeProviderOptions { + adapters: AsyncAdapter[] + entities?: ClassEntity[] entityOptions?: IOptions } declare module 'fastify' { export interface FastifyInstance { steno: { - get: (name: string) => Steno.NodeProvider | undefined + get: (name: string) => AsyncProvider | undefined } } } diff --git a/packages/lodash/package.json b/packages/lodash/package.json index 38d691e..76f8849 100644 --- a/packages/lodash/package.json +++ b/packages/lodash/package.json @@ -1,11 +1,12 @@ { "name": "@stenodb/lodash", "version": "3.4.1", + "type": "module", "exports": { ".": { "types": "./dist/index.d.ts", "require": "./dist/index.js", - "default": "./dist/index.mjs" + "default": "./dist/index.js" }, "./node": { "types": "./dist/node.d.ts", @@ -20,14 +21,16 @@ }, "types": "./dist/index.d.ts", "main": "./dist/index.js", - "module": "./dist/index.mjs", + "module": "./dist/index.js", "files": [ "dist", "src" ], "scripts": { "dev": "pnpm build --watch src", - "build": "tsup src/index.ts src/node.ts src/browser.ts --format esm,cjs --dts --clean" + "build": "tsup src/index.ts src/node.ts src/browser.ts --format esm,cjs --dts --clean", + "test": "ava", + "test:watch": "ava --watch" }, "dependencies": { "@stenodb/browser": "workspace:3.4.1", @@ -44,6 +47,16 @@ "@types/lodash": "^4.14.191", "lodash": "^4.17.21" }, + "ava": { + "snapshotDir": "test/snapshots", + "extensions": { + "ts": "module" + }, + "nodeArguments": [ + "--loader=ts-node/esm", + "--no-warnings" + ] + }, "engines": { "node": ">=14.16" } diff --git a/packages/lodash/src/browser.ts b/packages/lodash/src/browser.ts index 7895816..a261f17 100644 --- a/packages/lodash/src/browser.ts +++ b/packages/lodash/src/browser.ts @@ -1,11 +1,11 @@ import lodash from 'lodash' -import type { Steno } from '@stenodb/browser' +import type { StorageProvider } from '@stenodb/browser' export class BrowserLodash { - #provider: Steno.BrowserProvider + #provider: StorageProvider #chain: lodash.ExpChain - constructor(provider: Steno.BrowserProvider) { + constructor(provider: StorageProvider) { this.#provider = provider this.#chain = lodash.chain(provider).get('data') } @@ -18,11 +18,23 @@ export class BrowserLodash { return this.#provider.read() } - write(): void { + write(data?: T): void { + if (data) { + this.#provider.data = data + } + this.#provider.write() } - reset(): void { + reset(data?: T): void { + if (data) { + this.#provider.initialData = data + } + this.#provider.reset() } + + exist(): boolean { + return this.#provider.exists() + } } diff --git a/packages/lodash/src/node.ts b/packages/lodash/src/node.ts index 8aa5ce0..e3aaecc 100644 --- a/packages/lodash/src/node.ts +++ b/packages/lodash/src/node.ts @@ -1,11 +1,11 @@ import lodash from 'lodash' -import type { Steno } from '@stenodb/node' +import type { AsyncProvider } from '@stenodb/node' export class NodeLodash { - #provider: Steno.NodeProvider + #provider: AsyncProvider #chain: lodash.ExpChain - constructor(provider: Steno.NodeProvider) { + constructor(provider: AsyncProvider) { this.#provider = provider this.#chain = lodash.chain(provider).get('data') } @@ -18,11 +18,23 @@ export class NodeLodash { return await this.#provider.read() } - async write(): Promise { + async write(data?: T): Promise { + if (data) { + this.#provider.data = data + } + await this.#provider.write() } - async reset(): Promise { + async reset(data?: T): Promise { + if (data) { + this.#provider.initialData = data + } + await this.#provider.reset() } + + async exist(): Promise { + return this.#provider.exists() + } } diff --git a/packages/lodash/test/browser.test.ts b/packages/lodash/test/browser.test.ts new file mode 100644 index 0000000..3018eae --- /dev/null +++ b/packages/lodash/test/browser.test.ts @@ -0,0 +1,51 @@ +import { BrowserProvider, LocalStorage } from '@stenodb/browser' +import test from 'ava' +import { BrowserLodash } from '../src/browser.js' + +const storage = new Map() +const mockStorage = () => ({ + length: 0, + getItem: (key: string): string | null => storage.get(key) ?? null, + setItem: (key: string, value: string) => storage.set(key, value), + removeItem(key: string): void { + storage.delete(key) + }, + clear(): void { + storage.clear() + }, + key(index: number): string | null { + return Object.values(storage.values())[index] ?? null + } +}) + +global.localStorage = mockStorage() +global.sessionStorage = mockStorage() + +class User { + id: number + name: string + + constructor(id: number, name: string) { + this.id = id + this.name = name + } +} + +test('BrowserLodash', (t) => { + const user1 = new User(1, 'John') + const user2 = new User(2, 'Alice') + const adapter = new LocalStorage('users', User, user1) + const provider = new BrowserProvider() + const db = new BrowserLodash(provider.create(adapter)) + + db.read() + t.deepEqual(db.data.value(), user1) + + db.write(user2) + t.deepEqual(db.data.value(), user2) + + db.reset() + t.deepEqual(db.data.value(), user1) + t.is(db.data.get('id').value(), 1) + t.is(db.data.get('name').value(), 'John') +}) diff --git a/packages/lodash/test/node.test.ts b/packages/lodash/test/node.test.ts new file mode 100644 index 0000000..c15d6e6 --- /dev/null +++ b/packages/lodash/test/node.test.ts @@ -0,0 +1,37 @@ +import { dirname, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' +import { AsyncAdapter, NodeProvider } from '@stenodb/node' +import test from 'ava' +import { NodeLodash } from '../src/node.js' + +const provider = new NodeProvider({ + path: resolve(dirname(fileURLToPath(import.meta.url)), '..', 'db') +}) + +class User { + id: number + name: string + + constructor(id: number, name: string) { + this.id = id + this.name = name + } +} + +test('NodeLodash', async (t) => { + const adapter = new AsyncAdapter('users', User) + const db = new NodeLodash(await provider.create(adapter)) + const user1 = new User(1, 'John') + const user2 = new User(2, 'Alice') + + if (await db.exist()) { + await db.write(user1) + } + + t.deepEqual(db.data.value(), user1) + t.is(db.data.get('id').value(), 1) + t.is(db.data.get('name').value(), 'John') + + await db.write(user2) + t.deepEqual(db.data.value(), user2) +}) diff --git a/packages/logger/package.json b/packages/logger/package.json index 26b4b47..bba9df6 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,28 +1,31 @@ { "name": "@stenodb/logger", "version": "3.4.1", + "type": "module", "exports": { ".": { "types": "./dist/index.d.ts", "require": "./dist/index.js", - "default": "./dist/index.mjs" + "default": "./dist/index.js" }, "./rotation": { "types": "./dist/rotation.d.ts", "require": "./dist/rotation.js", - "default": "./dist/rotation.mjs" + "default": "./dist/rotation.js" } }, "types": "./dist/index.d.ts", "main": "./dist/index.js", - "module": "./dist/index.mjs", + "module": "./dist/index.js", "files": [ "dist", "src" ], "scripts": { "dev": "pnpm build --watch src", - "build": "tsup src/index.ts src/rotation.ts --format esm,cjs --dts --clean" + "build": "tsup src/index.ts src/rotation.ts --format esm,cjs --dts --clean", + "test": "ava", + "test:watch": "ava --watch" }, "dependencies": { "rotating-file-stream": "3.0.4", @@ -31,6 +34,16 @@ "devDependencies": { "@types/node": "18.11.19" }, + "ava": { + "snapshotDir": "test/snapshots", + "extensions": { + "ts": "module" + }, + "nodeArguments": [ + "--loader=ts-node/esm", + "--no-warnings" + ] + }, "engines": { "node": ">=14.16" } diff --git a/packages/logger/src/rotation.ts b/packages/logger/src/rotation.ts index 499e7ff..bcfcae1 100644 --- a/packages/logger/src/rotation.ts +++ b/packages/logger/src/rotation.ts @@ -3,10 +3,14 @@ import { BaseLogger, RotationOptions } from './types.js' export function createRotation(options: RotationOptions) { return (logger: BaseLogger) => { - const stream = createStream(options.path, options) + const stream = createStream(options.path + '.log', options) logger.attachTransport((log) => { - stream.write(JSON.stringify(log) + '\n') + const meta = log['_meta'] + const message = `${meta?.date.toISOString()} ${meta?.logLevelName} [${ + meta?.name + }] ${log[0]}` + stream.write(message + '\n') }) } } diff --git a/packages/logger/test/index.test.ts b/packages/logger/test/index.test.ts new file mode 100644 index 0000000..baa45a5 --- /dev/null +++ b/packages/logger/test/index.test.ts @@ -0,0 +1,38 @@ +import { existsSync } from 'node:fs' +import { rm } from 'node:fs/promises' +import { resolve } from 'node:path' +import test from 'ava' +import { Logger } from 'tslog' +import { createLogger } from '../src/logger.js' +import { createRotation } from '../src/rotation.js' + +const logsPath = resolve('logs') + +test.beforeEach(async () => { + if (existsSync(logsPath)) { + await rm(logsPath, { recursive: true }) + } +}) + +test('createLogger', (t) => { + const logger = createLogger({ type: 'pretty' })('test') + t.true(logger instanceof Logger) + t.assert(logger.settings.type, 'pretty') +}) + +test('createRotation', async (t) => { + const rotation = createRotation({ + path: 'logs', + size: '10M', + interval: '1d', + compress: 'gzip' + }) + + const logger = createLogger({ + type: 'hidden', + rotation + })('test-rotation') + + t.true(typeof rotation === 'function') + t.true(logger instanceof Logger) +}) diff --git a/packages/nest/README.md b/packages/nest/README.md index ff6e937..e85fdd7 100644 --- a/packages/nest/README.md +++ b/packages/nest/README.md @@ -21,7 +21,7 @@ pnpm add @stenodb/nest ```ts // users.dto.ts import { Exclude, Type } from 'class-transformer' -import { Length, Max, Min } from 'class-validator' +import { IsOptional, Length, Max, Min } from 'class-validator' export class Users { @Type(() => CreateUserDto) @@ -34,6 +34,7 @@ export class Users { export class CreateUserDto { @Exclude({ toPlainOnly: true }) + @IsOptional() id: number @Length(1, 20) @@ -66,12 +67,12 @@ export class AppModule {} // users.service.ts import { Injectable, OnModuleInit } from '@nestjs/common' -import { Steno, StenoService } from '@stenodb/nest' +import { StenoService, AsyncProvider } from '@stenodb/nest' import { Users, CreateUserDto } from './users.dto' @Injectable() export class UsersService implements OnModuleInit { - private usersProvider: Steno.NodeProvider + private usersProvider: AsyncProvider constructor(private readonly stenoService: StenoService) {} diff --git a/packages/nest/package.json b/packages/nest/package.json index 6b09fdf..cf80cf9 100644 --- a/packages/nest/package.json +++ b/packages/nest/package.json @@ -43,7 +43,8 @@ }, "dependencies": { "@nestjs/common": "9.3.7", - "@stenodb/node": "workspace:3.4.1" + "@stenodb/node": "workspace:3.4.1", + "@stenodb/utils": "workspace:3.4.1" }, "devDependencies": { "@swc/core": "1.3.35", @@ -52,6 +53,16 @@ "peerDependencies": { "@nestjs/common": "^9.0.0" }, + "ava": { + "snapshotDir": "test/snapshots", + "extensions": { + "ts": "commonjs" + }, + "nodeArguments": [ + "--loader=ts-node/register", + "--no-warnings" + ] + }, "engines": { "node": ">=14.16" } diff --git a/packages/nest/src/config.ts b/packages/nest/src/config.ts index e2c80ca..d02cfc5 100644 --- a/packages/nest/src/config.ts +++ b/packages/nest/src/config.ts @@ -1,12 +1,12 @@ import { ConfigurableModuleBuilder } from '@nestjs/common' -import type { Steno } from '@stenodb/node' +import type { NodeProviderOptions } from '@stenodb/node' export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN, OPTIONS_TYPE, ASYNC_OPTIONS_TYPE -} = new ConfigurableModuleBuilder() +} = new ConfigurableModuleBuilder() .setExtras({ isGlobal: false }, (definition, extras) => ({ ...definition, global: extras.isGlobal diff --git a/packages/nest/src/index.ts b/packages/nest/src/index.ts index 3709782..b354772 100644 --- a/packages/nest/src/index.ts +++ b/packages/nest/src/index.ts @@ -1,3 +1,4 @@ export * from './stenodb.module.js' export * from './stenodb.service.js' -export type { Steno } from '@stenodb/node' +export type { SyncProvider, AsyncProvider } from '@stenodb/node' +export type { ClassEntity } from '@stenodb/utils' diff --git a/packages/nest/src/stenodb.service.ts b/packages/nest/src/stenodb.service.ts index d4af3e7..d058839 100644 --- a/packages/nest/src/stenodb.service.ts +++ b/packages/nest/src/stenodb.service.ts @@ -1,7 +1,13 @@ import { Inject, Injectable } from '@nestjs/common' -import { AsyncAdapter, NodeProvider } from '@stenodb/node' +import { + AsyncAdapter, + NodeProvider, + SyncAdapter, + SyncProvider +} from '@stenodb/node' import { MODULE_OPTIONS_TOKEN, OPTIONS_TYPE } from './config.js' -import type { Steno } from '@stenodb/node' +import type { AsyncProvider } from '@stenodb/node' +import type { ClassEntity } from '@stenodb/utils' @Injectable() export class StenoService { @@ -13,10 +19,19 @@ export class StenoService { async create( fileName: string, - entity: Steno.Entity, + entity: ClassEntity, initialData?: T - ): Promise> { + ): Promise> { const adapter = new AsyncAdapter(fileName, entity, initialData) return await this.provider.create(adapter) } + + createSync( + fileName: string, + entity: ClassEntity, + initialData?: T + ): SyncProvider { + const adapter = new SyncAdapter(fileName, entity, initialData) + return this.provider.createSync(adapter) + } } diff --git a/packages/node/package.json b/packages/node/package.json index 83822b6..9381684 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -39,7 +39,9 @@ ], "scripts": { "dev": "pnpm build --watch src", - "build": "tsup src/index.ts --format esm,cjs --dts --clean --target node14" + "build": "tsup src/index.ts --format esm,cjs --dts --clean --target node14", + "test": "ava", + "test:watch": "ava --watch" }, "dependencies": { "@stenodb/logger": "workspace:3.4.1", @@ -47,11 +49,23 @@ "@stenodb/writer": "workspace:3.4.1" }, "devDependencies": { - "@types/node": "18.11.19" + "@types/node": "18.11.19", + "class-transformer": "0.5.1", + "reflect-metadata": "0.1.13" }, "peerDependencies": { "@stenodb/logger": "workspace:3.4.1" }, + "ava": { + "snapshotDir": "test/snapshots", + "extensions": [ + "ts" + ], + "nodeArguments": [ + "--loader=tsx", + "--no-warnings" + ] + }, "engines": { "node": ">=14.16" } diff --git a/packages/node/src/adapter/AsyncAdapter.ts b/packages/node/src/adapter/AsyncAdapter.ts index 9166c5f..adfc6a6 100644 --- a/packages/node/src/adapter/AsyncAdapter.ts +++ b/packages/node/src/adapter/AsyncAdapter.ts @@ -1,9 +1,9 @@ import { readFile } from 'node:fs/promises' import { BaseAdapter } from './BaseAdapter.js' -import type { Steno } from '../types.js' +import type { ClassEntity } from '@stenodb/utils' export class AsyncAdapter extends BaseAdapter { - constructor(fileName: string, entity: Steno.Entity, initialData?: T) { + constructor(fileName: string, entity: ClassEntity, initialData?: T) { super(fileName, entity, initialData) } diff --git a/packages/node/src/adapter/BaseAdapter.ts b/packages/node/src/adapter/BaseAdapter.ts index 5fe8597..dbe9ecb 100644 --- a/packages/node/src/adapter/BaseAdapter.ts +++ b/packages/node/src/adapter/BaseAdapter.ts @@ -1,15 +1,16 @@ +import { extname } from 'node:path' import { BaseLogger } from '@stenodb/logger' import { dataTransformer, entityTransformer } from '@stenodb/utils' import { Writer } from '@stenodb/writer' import type { DirectoryProvider } from '../provider/DirectoryProvider.js' -import type { Steno } from '../types.js' +import type { ClassEntity } from '@stenodb/utils' import type { DataTransformer, EntityTransformer } from '@stenodb/utils' export class BaseAdapter { fileName: string filePath: string - entity: Steno.Entity + entity: ClassEntity entityTransformer: EntityTransformer dataTransformer: DataTransformer @@ -20,7 +21,11 @@ export class BaseAdapter { data: T | null = null initialData: T | null = null - constructor(fileName: string, entity: Steno.Entity, initialData?: T) { + constructor(fileName: string, entity: ClassEntity, initialData?: T) { + if (extname(fileName) !== '') { + throw new Error(`File name must have an extension: ${fileName}`) + } + this.fileName = fileName this.entity = entity this.entityTransformer = entityTransformer(entity) diff --git a/packages/node/src/adapter/SyncAdapter.ts b/packages/node/src/adapter/SyncAdapter.ts index cc30913..6630569 100644 --- a/packages/node/src/adapter/SyncAdapter.ts +++ b/packages/node/src/adapter/SyncAdapter.ts @@ -1,9 +1,9 @@ import { readFileSync } from 'node:fs' import { BaseAdapter } from './BaseAdapter.js' -import type { Steno } from '../types.js' +import type { ClassEntity } from '@stenodb/utils' export class SyncAdapter extends BaseAdapter { - constructor(fileName: string, entity: Steno.Entity, initialData?: T) { + constructor(fileName: string, entity: ClassEntity, initialData?: T) { super(fileName, entity, initialData) } diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 285e51b..f843b4d 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -1,4 +1,6 @@ export * from './adapter/AsyncAdapter.js' export * from './adapter/SyncAdapter.js' +export * from './provider/AsyncProvider.js' +export * from './provider/SyncProvider.js' export * from './provider/NodeProvider.js' export * from './types.js' diff --git a/packages/node/src/provider/DirectoryProvider.ts b/packages/node/src/provider/DirectoryProvider.ts index f858acf..243b299 100644 --- a/packages/node/src/provider/DirectoryProvider.ts +++ b/packages/node/src/provider/DirectoryProvider.ts @@ -11,12 +11,19 @@ export class DirectoryProvider { this.temporaryPath = join(this.databasePath, 'temp') } - async createDatabaseDir(): Promise { - try { - await mkdir(this.temporaryPath, { recursive: true }) - } catch (err) { - if ((err as NodeJS.ErrnoException).code !== 'EEXIST') { - throw err + createDirectory() { + return { + withSync: () => { + mkdir(this.databasePath, { recursive: true }) + }, + withAsync: async () => { + try { + await mkdir(this.temporaryPath, { recursive: true }) + } catch (err) { + if ((err as NodeJS.ErrnoException).code !== 'EEXIST') { + throw err + } + } } } } @@ -29,7 +36,7 @@ export class DirectoryProvider { return join(this.temporaryPath, `${filename}-${Date.now()}.json`) } - writerTemporaryFile(filename: string) { + writerTemporaryFile(filename: string): Writer { const file = this.temporaryFilePath(filename) return new Writer(file) } diff --git a/packages/node/src/provider/NodeProvider.ts b/packages/node/src/provider/NodeProvider.ts index 9d80062..5067e87 100644 --- a/packages/node/src/provider/NodeProvider.ts +++ b/packages/node/src/provider/NodeProvider.ts @@ -1,23 +1,20 @@ -import { AsyncAdapter } from '../adapter/AsyncAdapter.js' -import { SyncAdapter } from '../adapter/SyncAdapter.js' import { AsyncProvider } from './AsyncProvider.js' import { DirectoryProvider } from './DirectoryProvider.js' import { SyncProvider } from './SyncProvider.js' -import type { Steno } from '../types.js' +import type { AsyncAdapter } from '../adapter/AsyncAdapter.js' +import type { SyncAdapter } from '../adapter/SyncAdapter.js' +import type { NodeAdapter, NodeProviderOptions } from '../types.js' export class NodeProvider { #directory: DirectoryProvider - #options: Steno.NodeProviderOptions + #options: NodeProviderOptions - constructor(options: Steno.NodeProviderOptions) { + constructor(options: NodeProviderOptions) { this.#options = options this.#directory = new DirectoryProvider(options.path) } - private async registerAdapterModules( - adapter: Steno.NodeAdapter - ): Promise { - await this.#directory.createDatabaseDir() + private registerAdapterModules(adapter: NodeAdapter): void { adapter.registerDirectory(this.#directory) if (this.#options?.logger) { @@ -26,17 +23,15 @@ export class NodeProvider { } } - async create( - adapter: Steno.NodeAdapter - ): Promise> { - await this.registerAdapterModules(adapter) - - if (adapter instanceof AsyncAdapter) { - return new AsyncProvider(adapter) - } else if (adapter instanceof SyncAdapter) { - return new SyncProvider(adapter) - } + async create(adapter: AsyncAdapter): Promise> { + await this.#directory.createDirectory().withAsync() + this.registerAdapterModules(adapter) + return new AsyncProvider(adapter) + } - throw new Error('Invalid adapter') + createSync(adapter: SyncAdapter): SyncProvider { + this.#directory.createDirectory().withSync() + this.registerAdapterModules(adapter) + return new SyncProvider(adapter) } } diff --git a/packages/node/src/types.ts b/packages/node/src/types.ts index 28a7463..f6bab2c 100644 --- a/packages/node/src/types.ts +++ b/packages/node/src/types.ts @@ -1,17 +1,10 @@ import type { AsyncAdapter } from './adapter/AsyncAdapter.js' import type { SyncAdapter } from './adapter/SyncAdapter.js' -import type { AsyncProvider } from './provider/AsyncProvider.js' -import type { SyncProvider } from './provider/SyncProvider.js' import type { CreateLogger } from '@stenodb/logger' -import type { ClassEntity } from '@stenodb/utils' -export namespace Steno { - export type Entity = ClassEntity - export type NodeAdapter = AsyncAdapter | SyncAdapter - export type NodeProvider = AsyncProvider | SyncProvider +export type NodeAdapter = AsyncAdapter | SyncAdapter - export interface NodeProviderOptions { - path: string - logger?: CreateLogger - } +export interface NodeProviderOptions { + path: string + logger?: CreateLogger } diff --git a/packages/node/test/AsyncAdapter.test.ts b/packages/node/test/AsyncAdapter.test.ts new file mode 100644 index 0000000..c52ecbb --- /dev/null +++ b/packages/node/test/AsyncAdapter.test.ts @@ -0,0 +1,13 @@ +import test from 'ava' +import { AsyncAdapter } from '../src/adapter/AsyncAdapter.js' +import { User, Users } from './fixtures/users.js' + +test('AsyncAdapter', async (t) => { + const initialData = new Users(new User(1, 'John Doe')) + const asyncAdapter = new AsyncAdapter('users', Users, initialData) + + t.is(asyncAdapter.fileName, 'users') + t.is(asyncAdapter.entity, Users) + t.is(asyncAdapter.initialData, initialData) + t.is(asyncAdapter.data, null) +}) diff --git a/packages/node/test/BaseAdapter.test.ts b/packages/node/test/BaseAdapter.test.ts new file mode 100644 index 0000000..da16962 --- /dev/null +++ b/packages/node/test/BaseAdapter.test.ts @@ -0,0 +1,17 @@ +import test from 'ava' +import { BaseAdapter } from '../src/adapter/BaseAdapter.js' +import { User, Users } from './fixtures/users.js' + +test('BaseAdapter', (t) => { + const initialData = new Users(new User(1, 'John Doe')) + const baseAdapter = new BaseAdapter('users', Users, initialData) + + t.is(baseAdapter.fileName, 'users') + t.is(baseAdapter.entity, Users) + t.is(baseAdapter.initialData, initialData) + t.is(baseAdapter.data, null) + + t.throws(() => new BaseAdapter('users.json', Users, initialData), { + instanceOf: Error + }) +}) diff --git a/packages/node/test/DirectoryProvider.test.ts b/packages/node/test/DirectoryProvider.test.ts new file mode 100644 index 0000000..73d6c78 --- /dev/null +++ b/packages/node/test/DirectoryProvider.test.ts @@ -0,0 +1,15 @@ +import { join, resolve } from 'node:path' +import { Writer } from '@stenodb/writer' +import test from 'ava' +import { DirectoryProvider } from '../src/provider/DirectoryProvider.js' + +test('DirectoryProvider', async (t) => { + const path = resolve('db') + const directoryProvider = new DirectoryProvider(path) + await directoryProvider.createDirectory().withAsync() + + t.is(directoryProvider.databasePath, path) + t.is(directoryProvider.temporaryPath, join(path, 'temp')) + t.is(directoryProvider.databaseFilePath('users'), join(path, 'users.json')) + t.true(directoryProvider.writerTemporaryFile('users') instanceof Writer) +}) diff --git a/packages/node/test/NodeProvider.test.ts b/packages/node/test/NodeProvider.test.ts new file mode 100644 index 0000000..b6244a2 --- /dev/null +++ b/packages/node/test/NodeProvider.test.ts @@ -0,0 +1,22 @@ +import { dirname, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' +import testFn from 'ava' +import { AsyncAdapter } from '../src/index.js' +import { NodeProvider } from '../src/provider/NodeProvider.js' +import { User, Users } from './fixtures/users.js' +import type { TestFn } from 'ava' + +const test = testFn as TestFn<{ provider: NodeProvider }> + +test.beforeEach((t) => { + const path = resolve(dirname(fileURLToPath(import.meta.url)), '..', 'db') + t.context = { + provider: new NodeProvider({ path }) + } +}) + +test('NodeProvider', async (t) => { + const adapter = new AsyncAdapter('users', Users) + const db = await t.context.provider.create(adapter) + t.pass() +}) diff --git a/packages/node/test/fixtures/users.ts b/packages/node/test/fixtures/users.ts new file mode 100644 index 0000000..7e5d0fa --- /dev/null +++ b/packages/node/test/fixtures/users.ts @@ -0,0 +1,25 @@ +import 'reflect-metadata' +import { Type } from 'class-transformer' + +export class Users { + @Type(() => User) + users: User[] + + constructor(...users: User[]) { + this.users = users + } +} + +export class User { + id: number + name: string + + constructor(id: number, name: string) { + this.id = id + this.name = name + } + + changeName(name: string): void { + this.name = name + } +} diff --git a/packages/node/tsconfig.json b/packages/node/tsconfig.json index 6a945c6..e6f2224 100644 --- a/packages/node/tsconfig.json +++ b/packages/node/tsconfig.json @@ -1,8 +1,9 @@ { "extends": "@crashmax/tsconfig", "compilerOptions": { - "sourceMap": false, - "outDir": "dist" + "target": "ESNext", + "experimentalDecorators": true, + "emitDecoratorMetadata": true }, "include": [ "src" diff --git a/packages/stenodb/package.json b/packages/stenodb/package.json index fa5587d..6562e6f 100644 --- a/packages/stenodb/package.json +++ b/packages/stenodb/package.json @@ -1,17 +1,18 @@ { "name": "stenodb", "description": "✍ Easy to use local JSON database", + "type": "module", "version": "3.4.1", "exports": { ".": { "types": "./dist/index.d.ts", "require": "./dist/index.js", - "default": "./dist/index.mjs" + "default": "./dist/index.js" } }, "types": "./dist/index.d.ts", "main": "./dist/index.js", - "module": "./dist/index.mjs", + "module": "./dist/index.js", "files": [ "dist", "src" @@ -39,7 +40,9 @@ ], "scripts": { "dev": "pnpm build --watch src", - "build": "tsup src/index.ts --format esm,cjs --dts --clean" + "build": "tsup src/index.ts --format esm,cjs --dts --clean", + "test": "ava", + "test:watch": "ava --watch" }, "dependencies": { "@stenodb/browser": "workspace:3.4.1", @@ -48,6 +51,16 @@ "@stenodb/nest": "workspace:3.4.1", "@stenodb/node": "workspace:3.4.1" }, + "ava": { + "snapshotDir": "test/snapshots", + "extensions": { + "ts": "module" + }, + "nodeArguments": [ + "--loader=ts-node/esm", + "--no-warnings" + ] + }, "engines": { "node": ">=14.16" } diff --git a/packages/stenodb/src/index.ts b/packages/stenodb/src/index.ts index 619edf3..dac214c 100644 --- a/packages/stenodb/src/index.ts +++ b/packages/stenodb/src/index.ts @@ -1,18 +1,5 @@ -export { - LocalStorage, - SessionStorage, - BrowserProvider, - Steno as BrowserStenoTypes -} from '@stenodb/browser' -export { - AsyncAdapter, - SyncAdapter, - NodeProvider, - Steno as NodeStenoTypes -} from '@stenodb/node' -export { - StenoModule, - StenoService, - Steno as NestStenoTypes -} from '@stenodb/nest' +export * from '@stenodb/browser' +export * from '@stenodb/node' +export * from '@stenodb/nest' +export * from '@stenodb/fastify' export * from '@stenodb/lodash' diff --git a/packages/stenodb/test/index.test.ts b/packages/stenodb/test/index.test.ts new file mode 100644 index 0000000..223d770 --- /dev/null +++ b/packages/stenodb/test/index.test.ts @@ -0,0 +1,10 @@ +import test from 'ava' +import * as packages from '../src/index.js' + +test('stenodb exports', async (t) => { + const allExports = [packages] + .reduce((acc, v) => [...acc, ...Object.keys(v)], new Array()) + .filter((name) => name !== 'default') + + t.deepEqual(allExports, [...new Set(allExports)]) +}) diff --git a/packages/stenodb/tsconfig.json b/packages/stenodb/tsconfig.json index 6a945c6..a6534b3 100644 --- a/packages/stenodb/tsconfig.json +++ b/packages/stenodb/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "@crashmax/tsconfig", "compilerOptions": { - "sourceMap": false, + "target": "ESNext", "outDir": "dist" }, "include": [ diff --git a/packages/utils/package.json b/packages/utils/package.json index fd2c971..51c7142 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -17,7 +17,9 @@ ], "scripts": { "dev": "pnpm build --watch src", - "build": "tsup src/index.ts --format esm,cjs --dts --clean" + "build": "tsup src/index.ts --format esm,cjs --dts --clean", + "test": "ava", + "test:watch": "ava --watch" }, "dependencies": { "class-transformer": "0.5.1", @@ -29,6 +31,16 @@ "peerDependencies": { "class-transformer": ">=0.5.0" }, + "ava": { + "snapshotDir": "test/snapshots", + "extensions": [ + "ts" + ], + "nodeArguments": [ + "--loader=tsx", + "--no-warnings" + ] + }, "engines": { "node": ">=14.16" } diff --git a/packages/utils/test/index.test.ts b/packages/utils/test/index.test.ts new file mode 100644 index 0000000..fed8b51 --- /dev/null +++ b/packages/utils/test/index.test.ts @@ -0,0 +1,44 @@ +import test from 'ava' +import { + dataTransformer, + entityTransformer, + getDifferenceData +} from '../src/utils.js' + +class User { + id: number + name: string + + constructor(id: number, name: string) { + this.id = id + this.name = name + } + + changeName(name: string): void { + this.name = name + } +} + +const userData = { id: 1, name: 'John' } +const userJsonData = JSON.stringify(userData) +const userEntityTransformer = entityTransformer(User) + +test('entityTransformer', (t) => { + t.deepEqual(userEntityTransformer(userJsonData), userJsonData) + t.falsy(userEntityTransformer(null)) +}) + +test('dataTransformer', (t) => { + const transformer = dataTransformer(userEntityTransformer) + const user = transformer.toJSON(userJsonData)! + user.changeName('Alice') + t.is(user.id, 1) + t.is(user.name, 'Alice') +}) + +test('getDifferenceData', (t) => { + const newUser = { name: 'Allice', role: 'user' } + const diffData = getDifferenceData(userData, newUser) + t.truthy(diffData) + t.snapshot(JSON.stringify(diffData)) +}) diff --git a/packages/utils/test/snapshots/test/index.test.ts.md b/packages/utils/test/snapshots/test/index.test.ts.md new file mode 100644 index 0000000..816b93e --- /dev/null +++ b/packages/utils/test/snapshots/test/index.test.ts.md @@ -0,0 +1,11 @@ +# Snapshot report for `test/index.test.ts` + +The actual snapshot is saved in `index.test.ts.snap`. + +Generated by [AVA](https://avajs.dev). + +## getDifferenceData + +> Snapshot 1 + + '{"added":[["role","user"]],"removed":[["id",1]],"edited":[["name","John","Allice"]]}' diff --git a/packages/utils/test/snapshots/test/index.test.ts.snap b/packages/utils/test/snapshots/test/index.test.ts.snap new file mode 100644 index 0000000..95a6713 Binary files /dev/null and b/packages/utils/test/snapshots/test/index.test.ts.snap differ diff --git a/packages/writer b/packages/writer index f491423..f175f05 160000 --- a/packages/writer +++ b/packages/writer @@ -1 +1 @@ -Subproject commit f491423c9632dba1a33edd20344fe158279160f3 +Subproject commit f175f05d17093b9b32e55f336ff289c0ff8c35a0 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4e5e68f..eb67aea 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,7 @@ importers: specifiers: '@crashmax/prettier-config': 3.0.1 '@crashmax/tsconfig': 1.0.2 + ava: 5.2.0 cross-env: 7.0.3 nodemon: 2.0.20 ts-node: 10.9.1 @@ -16,9 +17,10 @@ importers: devDependencies: '@crashmax/prettier-config': 3.0.1_za6dmrbiogn3z6m2plsv3qsi6m '@crashmax/tsconfig': 1.0.2 + ava: 5.2.0 cross-env: 7.0.3 nodemon: 2.0.20 - ts-node: 10.9.1_tncu2ai53lzgmizdedur7lbibe + ts-node: 10.9.1_rcvzjt2q3f6gordb34f5djrkie tsup: 6.6.3_6qtx7vkbdhwvdm4crzlegk4mvi tsx: 3.12.3 turbo: 1.8.1 @@ -171,12 +173,14 @@ importers: packages/fastify: specifiers: '@stenodb/node': workspace:3.4.1 + '@stenodb/utils': workspace:3.4.1 '@types/node': 18.11.19 class-validator-jsonschema: 5.0.0 fastify: ^4.13.0 fastify-plugin: 4.5.0 dependencies: '@stenodb/node': link:../node + '@stenodb/utils': link:../utils class-validator-jsonschema: 5.0.0_p4ywi7fdcrugq6nsanv77hac4q fastify-plugin: 4.5.0 devDependencies: @@ -213,11 +217,13 @@ importers: specifiers: '@nestjs/common': 9.3.7 '@stenodb/node': workspace:3.4.1 + '@stenodb/utils': workspace:3.4.1 '@swc/core': 1.3.35 '@types/node': 18.11.19 dependencies: '@nestjs/common': 9.3.7_mnr6j2del53muneqly5h4y27ai '@stenodb/node': link:../node + '@stenodb/utils': link:../utils devDependencies: '@swc/core': 1.3.35 '@types/node': 18.11.19 @@ -228,12 +234,16 @@ importers: '@stenodb/utils': workspace:3.4.1 '@stenodb/writer': workspace:3.4.1 '@types/node': 18.11.19 + class-transformer: 0.5.1 + reflect-metadata: 0.1.13 dependencies: '@stenodb/logger': link:../logger '@stenodb/utils': link:../utils '@stenodb/writer': link:../writer devDependencies: '@types/node': 18.11.19 + class-transformer: 0.5.1 + reflect-metadata: 0.1.13 packages/stenodb: specifiers: @@ -263,14 +273,14 @@ importers: packages/writer: specifiers: '@types/node': 18.13.0 + ava: ^5.2.0 tsup: 6.6.3 tsx: 3.12.3 - uvu: 0.5.6 devDependencies: '@types/node': 18.13.0 + ava: 5.2.0 tsup: 6.6.3 tsx: 3.12.3 - uvu: 0.5.6 packages: @@ -404,11 +414,6 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@babel/compat-data/7.21.0: - resolution: {integrity: sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==} - engines: {node: '>=6.9.0'} - dev: true - /@babel/core/7.20.12: resolution: {integrity: sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==} engines: {node: '>=6.9.0'} @@ -494,9 +499,9 @@ packages: peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/compat-data': 7.21.0 + '@babel/compat-data': 7.20.14 '@babel/core': 7.21.0 - '@babel/helper-validator-option': 7.21.0 + '@babel/helper-validator-option': 7.18.6 browserslist: 4.21.5 lru-cache: 5.1.1 semver: 6.3.0 @@ -603,11 +608,6 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@babel/helper-validator-option/7.21.0: - resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} - engines: {node: '>=6.9.0'} - dev: true - /@babel/helpers/7.20.13: resolution: {integrity: sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg==} engines: {node: '>=6.9.0'} @@ -2117,10 +2117,6 @@ packages: resolution: {integrity: sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==} dev: true - /@types/node/18.14.0: - resolution: {integrity: sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==} - dev: true - /@types/parse-json/4.0.0: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} dev: true @@ -2337,6 +2333,14 @@ packages: hasBin: true dev: true + /aggregate-error/4.0.1: + resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==} + engines: {node: '>=12'} + dependencies: + clean-stack: 4.2.0 + indent-string: 5.0.0 + dev: true + /ajv-formats/2.1.1_ajv@8.11.0: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -2409,6 +2413,11 @@ packages: engines: {node: '>=8'} dev: true + /ansi-regex/6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + /ansi-styles/3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -2427,6 +2436,11 @@ packages: engines: {node: '>=10'} dev: true + /ansi-styles/6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + /any-promise/1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} dev: true @@ -2455,6 +2469,11 @@ packages: sprintf-js: 1.0.3 dev: true + /array-find-index/1.0.2: + resolution: {integrity: sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==} + engines: {node: '>=0.10.0'} + dev: true + /array-flatten/1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} @@ -2463,6 +2482,16 @@ packages: engines: {node: '>=8'} dev: true + /arrgv/1.0.2: + resolution: {integrity: sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==} + engines: {node: '>=8.0.0'} + dev: true + + /arrify/3.0.0: + resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==} + engines: {node: '>=12'} + dev: true + /asap/2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} dev: true @@ -2475,6 +2504,65 @@ packages: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} + /ava/5.2.0: + resolution: {integrity: sha512-W8yxFXJr/P68JP55eMpQIa6AiXhCX3VeuajM8nolyWNExcMDD6rnIWKTjw0B/+GkFHBIaN6Jd0LtcMThcoqVfg==} + engines: {node: '>=14.19 <15 || >=16.15 <17 || >=18'} + hasBin: true + peerDependencies: + '@ava/typescript': '*' + peerDependenciesMeta: + '@ava/typescript': + optional: true + dependencies: + acorn: 8.8.2 + acorn-walk: 8.2.0 + ansi-styles: 6.2.1 + arrgv: 1.0.2 + arrify: 3.0.0 + callsites: 4.0.0 + cbor: 8.1.0 + chalk: 5.2.0 + chokidar: 3.5.3 + chunkd: 2.0.1 + ci-info: 3.7.1 + ci-parallel-vars: 1.0.1 + clean-yaml-object: 0.1.0 + cli-truncate: 3.1.0 + code-excerpt: 4.0.0 + common-path-prefix: 3.0.0 + concordance: 5.0.4 + currently-unhandled: 0.4.1 + debug: 4.3.4 + del: 7.0.0 + emittery: 1.0.1 + figures: 5.0.0 + globby: 13.1.3 + ignore-by-default: 2.1.0 + indent-string: 5.0.0 + is-error: 2.2.2 + is-plain-object: 5.0.0 + is-promise: 4.0.0 + matcher: 5.0.0 + mem: 9.0.2 + ms: 2.1.3 + p-event: 5.0.1 + p-map: 5.5.0 + picomatch: 2.3.1 + pkg-conf: 4.0.0 + plur: 5.1.0 + pretty-ms: 8.0.0 + resolve-cwd: 3.0.0 + slash: 3.0.0 + stack-utils: 2.0.6 + strip-ansi: 7.0.1 + supertap: 3.0.1 + temp-dir: 3.0.0 + write-file-atomic: 5.0.0 + yargs: 17.6.2 + transitivePeerDependencies: + - supports-color + dev: true + /avvio/8.2.1: resolution: {integrity: sha512-TAlMYvOuwGyLK3PfBb5WKBXZmXz2fVCgv23d6zZFdle/q3gPjmxBaeuC0pY0Dzs5PWMSgfqqEZkrye19GlDTgw==} dependencies: @@ -2575,6 +2663,10 @@ packages: readable-stream: 3.6.0 dev: true + /blueimp-md5/2.19.0: + resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==} + dev: true + /body-parser/1.20.1: resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -2683,6 +2775,11 @@ packages: engines: {node: '>=6'} dev: true + /callsites/4.0.0: + resolution: {integrity: sha512-y3jRROutgpKdz5vzEhWM34TidDU8vkJppF8dszITeb1PQmSqV3DTxyV8G/lyO/DNvtE1YTedehmw9MPZsCBHxQ==} + engines: {node: '>=12.20'} + dev: true + /camelcase/5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} @@ -2697,6 +2794,13 @@ packages: resolution: {integrity: sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA==} dev: true + /cbor/8.1.0: + resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==} + engines: {node: '>=12.19'} + dependencies: + nofilter: 3.1.0 + dev: true + /chalk/2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -2721,6 +2825,11 @@ packages: ansi-styles: 4.3.0 supports-color: 7.2.0 + /chalk/5.2.0: + resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + /char-regex/1.0.2: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} @@ -2750,11 +2859,19 @@ packages: engines: {node: '>=6.0'} dev: true + /chunkd/2.0.1: + resolution: {integrity: sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==} + dev: true + /ci-info/3.7.1: resolution: {integrity: sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==} engines: {node: '>=8'} dev: true + /ci-parallel-vars/1.0.1: + resolution: {integrity: sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==} + dev: true + /cjs-module-lexer/1.2.2: resolution: {integrity: sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==} dev: true @@ -2784,6 +2901,18 @@ packages: libphonenumber-js: 1.10.19 validator: 13.9.0 + /clean-stack/4.2.0: + resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==} + engines: {node: '>=12'} + dependencies: + escape-string-regexp: 5.0.0 + dev: true + + /clean-yaml-object/0.1.0: + resolution: {integrity: sha512-3yONmlN9CSAkzNwnRCiJQ7Q2xK5mWuEfL3PuTZcAUzhObbXsfsnMptJzXwz93nc5zn9V9TwCVMmV7w4xsm43dw==} + engines: {node: '>=0.10.0'} + dev: true + /cli-cursor/3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} @@ -2805,6 +2934,14 @@ packages: '@colors/colors': 1.5.0 dev: true + /cli-truncate/3.1.0: + resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + slice-ansi: 5.0.0 + string-width: 5.1.2 + dev: true + /cli-width/3.0.0: resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} engines: {node: '>= 10'} @@ -2829,6 +2966,13 @@ packages: engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} dev: true + /code-excerpt/4.0.0: + resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + convert-to-spaces: 2.0.1 + dev: true + /collect-v8-coverage/1.0.1: resolution: {integrity: sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==} dev: true @@ -2868,6 +3012,10 @@ packages: engines: {node: '>= 6'} dev: true + /common-path-prefix/3.0.0: + resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} + dev: true + /component-emitter/1.3.0: resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} dev: true @@ -2884,6 +3032,20 @@ packages: readable-stream: 2.3.7 typedarray: 0.0.6 + /concordance/5.0.4: + resolution: {integrity: sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==} + engines: {node: '>=10.18.0 <11 || >=12.14.0 <13 || >=14'} + dependencies: + date-time: 3.1.0 + esutils: 2.0.3 + fast-diff: 1.2.0 + js-string-escape: 1.0.1 + lodash: 4.17.21 + md5-hex: 3.0.1 + semver: 7.3.8 + well-known-symbols: 2.0.0 + dev: true + /consola/2.15.3: resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} @@ -2901,6 +3063,11 @@ packages: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} dev: true + /convert-to-spaces/2.0.1: + resolution: {integrity: sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + /cookie-signature/1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} @@ -2954,6 +3121,20 @@ packages: which: 2.0.2 dev: true + /currently-unhandled/0.4.1: + resolution: {integrity: sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==} + engines: {node: '>=0.10.0'} + dependencies: + array-find-index: 1.0.2 + dev: true + + /date-time/3.1.0: + resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==} + engines: {node: '>=6'} + dependencies: + time-zone: 1.0.0 + dev: true + /debug/2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -3002,6 +3183,20 @@ packages: clone: 1.0.4 dev: true + /del/7.0.0: + resolution: {integrity: sha512-tQbV/4u5WVB8HMJr08pgw0b6nG4RGt/tj+7Numvq+zqcvUFeMaIWWOUFltiU+6go8BSO2/ogsB4EasDaj0y68Q==} + engines: {node: '>=14.16'} + dependencies: + globby: 13.1.3 + graceful-fs: 4.2.10 + is-glob: 4.0.3 + is-path-cwd: 3.0.0 + is-path-inside: 4.0.0 + p-map: 5.5.0 + rimraf: 3.0.2 + slash: 4.0.0 + dev: true + /delayed-stream/1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -3011,11 +3206,6 @@ packages: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} - /dequal/2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - dev: true - /destroy/1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -3042,11 +3232,6 @@ packages: engines: {node: '>=0.3.1'} dev: true - /diff/5.1.0: - resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} - engines: {node: '>=0.3.1'} - dev: true - /dir-glob/3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -3054,6 +3239,10 @@ packages: path-type: 4.0.0 dev: true + /eastasianwidth/0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + /ee-first/1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -3066,10 +3255,19 @@ packages: engines: {node: '>=12'} dev: true + /emittery/1.0.1: + resolution: {integrity: sha512-2ID6FdrMD9KDLldGesP6317G78K7km/kMcwItRtVFva7I/cSEOIaLpewaUb+YLXVwdAp3Ctfxh/V5zIl1sj7dQ==} + engines: {node: '>=14.16'} + dev: true + /emoji-regex/8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true + /emoji-regex/9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + /encodeurl/1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} @@ -3386,6 +3584,11 @@ packages: engines: {node: '>=8'} dev: true + /escape-string-regexp/5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: true + /eslint-scope/5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} @@ -3417,6 +3620,11 @@ packages: engines: {node: '>=4.0'} dev: true + /esutils/2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + /etag/1.8.1: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} @@ -3531,6 +3739,10 @@ packages: /fast-deep-equal/3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + /fast-diff/1.2.0: + resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} + dev: true + /fast-glob/3.2.12: resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} engines: {node: '>=8.6.0'} @@ -3614,6 +3826,14 @@ packages: escape-string-regexp: 1.0.5 dev: true + /figures/5.0.0: + resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} + engines: {node: '>=14'} + dependencies: + escape-string-regexp: 5.0.0 + is-unicode-supported: 1.3.0 + dev: true + /fill-range/7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -3651,6 +3871,14 @@ packages: path-exists: 4.0.0 dev: true + /find-up/6.3.0: + resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + dev: true + /fork-ts-checker-webpack-plugin/7.3.0_hhrrucqyg4eysmfpujvov2ym5u: resolution: {integrity: sha512-IN+XTzusCjR5VgntYFgxbxVx3WraPRnKehBFrf00cMSrtUuW9MsG9dhL6MWpY6MkjC3wVwoujfCDgZZCQwbswA==} engines: {node: '>=12.13.0', yarn: '>=1.0.0'} @@ -3827,6 +4055,17 @@ packages: slash: 3.0.0 dev: true + /globby/13.1.3: + resolution: {integrity: sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.2.12 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 4.0.0 + dev: true + /graceful-fs/4.2.10: resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} dev: true @@ -3892,6 +4131,11 @@ packages: resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} dev: true + /ignore-by-default/2.1.0: + resolution: {integrity: sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==} + engines: {node: '>=10 <11 || >=12 <13 || >=14'} + dev: true + /ignore/5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} @@ -3919,6 +4163,11 @@ packages: engines: {node: '>=0.8.19'} dev: true + /indent-string/5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + dev: true + /inflight/1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} dependencies: @@ -3977,6 +4226,11 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} + /irregular-plurals/3.4.0: + resolution: {integrity: sha512-YXxECO/W6N9aMBVKMKKZ8TXESgq7EFrp3emCGGUcrYY1cgJIeZjoB75MTu8qi+NAKntS9NwPU8VdcQ3r6E6aWQ==} + engines: {node: '>=8'} + dev: true + /is-arrayish/0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} dev: true @@ -3994,6 +4248,10 @@ packages: has: 1.0.3 dev: true + /is-error/2.2.2: + resolution: {integrity: sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==} + dev: true + /is-extglob/2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -4004,6 +4262,11 @@ packages: engines: {node: '>=8'} dev: true + /is-fullwidth-code-point/4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + dev: true + /is-generator-fn/2.1.0: resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} engines: {node: '>=6'} @@ -4026,6 +4289,25 @@ packages: engines: {node: '>=0.12.0'} dev: true + /is-path-cwd/3.0.0: + resolution: {integrity: sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /is-path-inside/4.0.0: + resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} + engines: {node: '>=12'} + dev: true + + /is-plain-object/5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + dev: true + + /is-promise/4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + dev: true + /is-stream/2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -4036,6 +4318,11 @@ packages: engines: {node: '>=10'} dev: true + /is-unicode-supported/1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + dev: true + /isarray/1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} @@ -4518,6 +4805,11 @@ packages: engines: {node: '>=10'} dev: true + /js-string-escape/1.0.1: + resolution: {integrity: sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==} + engines: {node: '>= 0.8'} + dev: true + /js-tokens/4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: true @@ -4575,11 +4867,6 @@ packages: engines: {node: '>=6'} dev: true - /kleur/4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - dev: true - /leven/3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -4604,6 +4891,11 @@ packages: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: true + /load-json-file/7.0.1: + resolution: {integrity: sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + /load-tsconfig/0.2.3: resolution: {integrity: sha512-iyT2MXws+dc2Wi6o3grCFtGXpeMvHmJqS27sMPGtV2eUu4PeFnG+33I8BlFK1t1NWMjOpcx9bridn5yxLDX2gQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -4621,6 +4913,13 @@ packages: p-locate: 4.1.0 dev: true + /locate-path/7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-locate: 6.0.0 + dev: true + /lodash.clone/4.5.0: resolution: {integrity: sha512-GhrVeweiTD6uTmmn5hV/lzgCQhccwReIVRLHp7LT4SopOjqEZ5BbX8b5WWEtAKasjmy8hR7ZPwsYlxRCku5odg==} dev: true @@ -4704,10 +5003,39 @@ packages: tmpl: 1.0.5 dev: true + /map-age-cleaner/0.1.3: + resolution: {integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==} + engines: {node: '>=6'} + dependencies: + p-defer: 1.0.0 + dev: true + + /matcher/5.0.0: + resolution: {integrity: sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + escape-string-regexp: 5.0.0 + dev: true + + /md5-hex/3.0.1: + resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==} + engines: {node: '>=8'} + dependencies: + blueimp-md5: 2.19.0 + dev: true + /media-typer/0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} + /mem/9.0.2: + resolution: {integrity: sha512-F2t4YIv9XQUBHt6AOJ0y7lSmP1+cY7Fm1DRh9GClTGzKST7UWLMx6ly9WZdLH/G/ppM5RL4MlQfRT71ri9t19A==} + engines: {node: '>=12.20'} + dependencies: + map-age-cleaner: 0.1.3 + mimic-fn: 4.0.0 + dev: true + /memfs/3.4.13: resolution: {integrity: sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg==} engines: {node: '>= 4.0.0'} @@ -4765,6 +5093,11 @@ packages: engines: {node: '>=6'} dev: true + /mimic-fn/4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: true + /minimatch/3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: @@ -4779,11 +5112,6 @@ packages: dependencies: minimist: 1.2.7 - /mri/1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} - dev: true - /ms/2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -4881,6 +5209,11 @@ packages: undefsafe: 2.0.5 dev: true + /nofilter/3.1.0: + resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==} + engines: {node: '>=12.19'} + dev: true + /nopt/1.0.10: resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} hasBin: true @@ -4962,6 +5295,18 @@ packages: engines: {node: '>=0.10.0'} dev: true + /p-defer/1.0.0: + resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==} + engines: {node: '>=4'} + dev: true + + /p-event/5.0.1: + resolution: {integrity: sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-timeout: 5.1.0 + dev: true + /p-limit/2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -4976,6 +5321,13 @@ packages: yocto-queue: 0.1.0 dev: true + /p-limit/4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + yocto-queue: 1.0.0 + dev: true + /p-locate/4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -4983,6 +5335,25 @@ packages: p-limit: 2.3.0 dev: true + /p-locate/6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-limit: 4.0.0 + dev: true + + /p-map/5.5.0: + resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==} + engines: {node: '>=12'} + dependencies: + aggregate-error: 4.0.1 + dev: true + + /p-timeout/5.1.0: + resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==} + engines: {node: '>=12'} + dev: true + /p-try/2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -5005,6 +5376,11 @@ packages: lines-and-columns: 1.2.4 dev: true + /parse-ms/3.0.0: + resolution: {integrity: sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==} + engines: {node: '>=12'} + dev: true + /parseurl/1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -5014,6 +5390,11 @@ packages: engines: {node: '>=8'} dev: true + /path-exists/5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + /path-is-absolute/1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} @@ -5077,6 +5458,14 @@ packages: engines: {node: '>= 6'} dev: true + /pkg-conf/4.0.0: + resolution: {integrity: sha512-7dmgi4UY4qk+4mj5Cd8v/GExPo0K+SlY+hulOSdfZ/T6jVH6//y7NtzZo5WrfhDBxuQ0jCa7fLZmNaNh7EWL/w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + find-up: 6.3.0 + load-json-file: 7.0.1 + dev: true + /pkg-dir/4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -5084,6 +5473,13 @@ packages: find-up: 4.1.0 dev: true + /plur/5.1.0: + resolution: {integrity: sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + irregular-plurals: 3.4.0 + dev: true + /pluralize/8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} @@ -5118,7 +5514,7 @@ packages: optional: true dependencies: lilconfig: 2.0.6 - ts-node: 10.9.1_tncu2ai53lzgmizdedur7lbibe + ts-node: 10.9.1_rcvzjt2q3f6gordb34f5djrkie yaml: 1.10.2 dev: true @@ -5153,6 +5549,13 @@ packages: react-is: 18.2.0 dev: true + /pretty-ms/8.0.0: + resolution: {integrity: sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==} + engines: {node: '>=14.16'} + dependencies: + parse-ms: 3.0.0 + dev: true + /process-nextick-args/2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -5386,13 +5789,6 @@ packages: dependencies: tslib: 2.5.0 - /sade/1.8.1: - resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} - engines: {node: '>=6'} - dependencies: - mri: 1.2.0 - dev: true - /safe-buffer/5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -5465,6 +5861,13 @@ packages: transitivePeerDependencies: - supports-color + /serialize-error/7.0.1: + resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} + engines: {node: '>=10'} + dependencies: + type-fest: 0.13.1 + dev: true + /serialize-javascript/6.0.1: resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} dependencies: @@ -5537,6 +5940,19 @@ packages: engines: {node: '>=8'} dev: true + /slash/4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + dev: true + + /slice-ansi/5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + dev: true + /sonic-boom/3.2.1: resolution: {integrity: sha512-iITeTHxy3B9FGu8aVdiDXUVAcHMF9Ss0cCsAOo2HfCrmVGT3/DT5oYaeu0M/YKZDlKTvChEyPq0zI9Hf33EX6A==} dependencies: @@ -5623,6 +6039,15 @@ packages: strip-ansi: 6.0.1 dev: true + /string-width/5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.0.1 + dev: true + /string_decoder/1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} dependencies: @@ -5641,6 +6066,13 @@ packages: ansi-regex: 5.0.1 dev: true + /strip-ansi/7.0.1: + resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + /strip-bom/3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -5692,6 +6124,16 @@ packages: - supports-color dev: true + /supertap/3.0.1: + resolution: {integrity: sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + indent-string: 5.0.0 + js-yaml: 3.14.1 + serialize-error: 7.0.1 + strip-ansi: 7.0.1 + dev: true + /supertest/6.3.3: resolution: {integrity: sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==} engines: {node: '>=6.4.0'} @@ -5745,6 +6187,11 @@ packages: engines: {node: '>=6'} dev: true + /temp-dir/3.0.0: + resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} + engines: {node: '>=14.16'} + dev: true + /terminal-link/2.1.1: resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} engines: {node: '>=8'} @@ -5819,6 +6266,11 @@ packages: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: true + /time-zone/1.0.0: + resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==} + engines: {node: '>=4'} + dev: true + /tiny-lru/10.0.1: resolution: {integrity: sha512-Vst+6kEsWvb17Zpz14sRJV/f8bUWKhqm6Dc+v08iShmIJ/WxqWytHzCTd6m88pS33rE2zpX34TRmOpAJPloNCA==} engines: {node: '>=6'} @@ -5955,37 +6407,6 @@ packages: yn: 3.1.1 dev: true - /ts-node/10.9.1_tncu2ai53lzgmizdedur7lbibe: - resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.3 - '@types/node': 18.14.0 - acorn: 8.8.2 - acorn-walk: 8.2.0 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 4.9.5 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true - /tsconfig-paths-webpack-plugin/4.0.0: resolution: {integrity: sha512-fw/7265mIWukrSHd0i+wSwx64kYUSAKPfxRDksjKIYTxSAp9W9/xcZVBF4Kl0eqQd5eBpAQ/oQrc5RyM/0c1GQ==} engines: {node: '>=10.13.0'} @@ -6173,6 +6594,11 @@ packages: engines: {node: '>=4'} dev: true + /type-fest/0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + dev: true + /type-fest/0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} @@ -6241,17 +6667,6 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} - /uvu/0.5.6: - resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} - engines: {node: '>=8'} - hasBin: true - dependencies: - dequal: 2.0.3 - diff: 5.1.0 - kleur: 4.1.5 - sade: 1.8.1 - dev: true - /v8-compile-cache-lib/3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true @@ -6383,6 +6798,11 @@ packages: - uglify-js dev: true + /well-known-symbols/2.0.0: + resolution: {integrity: sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==} + engines: {node: '>=6'} + dev: true + /whatwg-url/5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} dependencies: @@ -6432,6 +6852,14 @@ packages: signal-exit: 3.0.7 dev: true + /write-file-atomic/5.0.0: + resolution: {integrity: sha512-R7NYMnHSlV42K54lwY9lvW6MnSm1HSJqZL3xiSgi9E7//FYaI74r2G0rd+/X6VAMkHEdzxQaU5HUOXWUz5kA/w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + dev: true + /xtend/4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -6485,3 +6913,8 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} dev: true + + /yocto-queue/1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: true diff --git a/turbo.json b/turbo.json index e9ec357..bd16dcc 100644 --- a/turbo.json +++ b/turbo.json @@ -7,6 +7,10 @@ "build": { "outputs": ["dist/**"], "dependsOn": ["^build"] + }, + "test": { + "dependsOn": ["^build"], + "inputs": ["src/**/*.ts"] } } }