diff --git a/.gitignore b/.gitignore index 0501cec..f4cab91 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ pnpm-lock.yaml .DS_Store .log .vscode/ +docs/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..3c8c15a --- /dev/null +++ b/README.md @@ -0,0 +1,198 @@ +# @teacinema/contracts + +npm-пакет с контрактами для межсервисного взаимодействия: gRPC (протобафы) и события (message broker). + +## Установка + +```bash +yarn add @teacinema/contracts +``` + +--- + +## gRPC сервисы + +Для подключения gRPC клиента используй `PROTO_PATHS` и соответствующее имя пакета. + +| Сервис | Пакет proto | Описание | +|---|---|---| +| `AuthService` | `auth.v1` | Аутентификация (OTP, токены, Telegram) | +| `AccountService` | `account.v1` | Управление аккаунтом (email, телефон) | +| `UsersService` | `users.v1` | Профили пользователей | + +### AuthService — `auth.v1` + +| Метод | Запрос | Ответ | Описание | +|---|---|---|---| +| `SendOtp` | `SendOtpRequest` | `SendOtpResponse` | Отправить OTP-код | +| `VerifyOtp` | `VerifyOtpRequest` | `VerifyOtpResponse` | Проверить OTP, получить токены | +| `Refresh` | `RefreshRequest` | `RefreshResponse` | Обновить access/refresh токены | +| `TelegramInit` | `Empty` | `TelegramInitResponse` | Получить ссылку для Telegram-авторизации | +| `TelegramVerify` | `TelegramVerifyRequest` | `TelegramVerifyResponse` | Верифицировать данные от Telegram | +| `TelegramComplete` | `TelegramCompleteRequest` | `TelegramCompleteResponse` | Привязать телефон к Telegram-сессии | +| `TelegramConsume` | `TelegramConsumeRequest` | `TelegramConsumeResponse` | Получить токены из Telegram-сессии | + +### AccountService — `account.v1` + +| Метод | Запрос | Ответ | Описание | +|---|---|---|---| +| `GetAccount` | `GetAccountRequest` | `GetAccountResponse` | Получить данные аккаунта по ID | +| `InitEmailChange` | `InitEmailChangeRequest` | `InitEmailChangeResponse` | Инициировать смену email | +| `ConfirmEmailChange` | `ConfirmEmailChangeRequest` | `ConfirmEmailChangeResponse` | Подтвердить смену email | +| `InitPhoneChange` | `InitPhoneChangeRequest` | `InitPhoneChangeResponse` | Инициировать смену телефона | +| `ConfirmPhoneChange` | `ConfirmPhoneChangeRequest` | `ConfirmPhoneChangeResponse` | Подтвердить смену телефона | + +### UsersService — `users.v1` + +| Метод | Запрос | Ответ | Описание | +|---|---|---|---| +| `GetMe` | `GetMeRequest` | `GetMeResponse` | Получить профиль пользователя по ID | +| `CreateUser` | `CreateUserRequest` | `CreateUserResponse` | Создать нового пользователя | + +--- + +## Использование в NestJS + +### 1. Регистрация gRPC клиента + +```ts +import { ClientsModule, Transport } from '@nestjs/microservices'; +import { PROTO_PATHS } from '@teacinema/contracts'; + +@Module({ + imports: [ + ClientsModule.register([ + { + name: 'AUTH_SERVICE', + transport: Transport.GRPC, + options: { + protoPath: PROTO_PATHS.AUTH, + package: 'auth.v1', + url: 'localhost:5000', + }, + }, + { + name: 'ACCOUNT_SERVICE', + transport: Transport.GRPC, + options: { + protoPath: PROTO_PATHS.ACCOUNT, + package: 'account.v1', + url: 'localhost:5001', + }, + }, + { + name: 'USERS_SERVICE', + transport: Transport.GRPC, + options: { + protoPath: PROTO_PATHS.USERS, + package: 'users.v1', + url: 'localhost:5002', + }, + }, + ]), + ], +}) +export class AppModule {} +``` + +### 2. Использование gRPC клиента + +Типы клиентов генерируются из proto-файлов и находятся в `gen/`: + +```ts +import { Inject, Injectable, OnModuleInit } from '@nestjs/common'; +import { ClientGrpc } from '@nestjs/microservices'; +import { AuthServiceClient } from '@teacinema/contracts/gen/auth'; + +@Injectable() +export class AuthProxy implements OnModuleInit { + private authService: AuthServiceClient; + + constructor(@Inject('AUTH_SERVICE') private client: ClientGrpc) {} + + onModuleInit() { + this.authService = this.client.getService('AuthService'); + } + + sendOtp(identifier: string, type: string) { + return this.authService.sendOtp({ identifier, type }); + } +} +``` + +### 3. Реализация gRPC сервера + +```ts +import { Controller } from '@nestjs/common'; +import { GrpcMethod } from '@nestjs/microservices'; +import { AuthServiceController, AuthServiceControllerMethods } from '@teacinema/contracts/gen/auth'; + +@Controller() +@AuthServiceControllerMethods() +export class AuthController implements AuthServiceController { + @GrpcMethod('AuthService', 'SendOtp') + sendOtp(request: SendOtpRequest): SendOtpResponse { + // ... + } +} +``` + +--- + +## События (Message Broker) + +Интерфейсы событий для типизированного обмена через брокер сообщений (RabbitMQ, Kafka и др.). + +| Интерфейс | Источник | Описание | +|---|---|---| +| `OtpRequestedEvent` | auth-service | Запрос на отправку OTP-кода | +| `EmailChangedEvent` | account-service | Инициация смены email | +| `PhoneChangedEvent` | account-service | Инициация смены телефона | + +### Публикация события + +```ts +import { OtpRequestedEvent } from '@teacinema/contracts'; + +client.emit('auth.otp_requested', { + identifier: '+79001234567', + code: '123456', + type: 'phone', +}); +``` + +### Подписка на событие + +```ts +import { EventPattern } from '@nestjs/microservices'; +import { OtpRequestedEvent } from '@teacinema/contracts'; + +@Controller() +export class NotificationController { + @EventPattern('auth.otp_requested') + handleOtpRequested(data: OtpRequestedEvent) { + // отправить SMS или email с кодом + } +} +``` + +--- + +## Обновление типов из proto + +После изменения `.proto` файлов — пересгенерировать TypeScript типы: + +```bash +yarn generate +``` + +--- + +## Документация + +Сгенерировать HTML-документацию и открыть в браузере: + +```bash +yarn docs +open docs/index.html +``` \ No newline at end of file diff --git a/package.json b/package.json index f947423..6c6a5e9 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Protocol Buffers contracts for microservices", "scripts": { "build": "tsc -p tsconfig.build.json", - "generate": "npx protoc -I ./proto ./proto/*.proto --ts_proto_out=./gen --ts_proto_opt=nestJs=true,package=omit" + "generate": "npx protoc -I ./proto ./proto/*.proto --ts_proto_out=./gen --ts_proto_opt=nestJs=true,package=omit", + "docs": "typedoc" }, "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -24,6 +25,7 @@ }, "devDependencies": { "@types/node": "^25.0.10", + "typedoc": "^0.28.17", "typescript": "^5.9.3" } } diff --git a/src/events/account/email-changed.interface.ts b/src/events/account/email-changed.interface.ts index 9732dfb..1436787 100644 --- a/src/events/account/email-changed.interface.ts +++ b/src/events/account/email-changed.interface.ts @@ -1,4 +1,18 @@ - export interface EmailChangedEvent { +/** + * Событие инициации смены email. Публикуется сервисом аккаунтов — + * подписчик отправляет письмо с кодом подтверждения. + * + * @example + * ```ts + * client.emit('account.email_change_initiated', { + * email: 'user@example.com', + * code: '123456', + * }); + * ``` + */ +export interface EmailChangedEvent { + /** Новый email пользователя */ email: string + /** Код подтверждения */ code: string - } +} diff --git a/src/events/account/phone-changed.interface.ts b/src/events/account/phone-changed.interface.ts index 42a7ba9..7d1d820 100644 --- a/src/events/account/phone-changed.interface.ts +++ b/src/events/account/phone-changed.interface.ts @@ -1,4 +1,18 @@ - export interface PhoneChangedEvent { +/** + * Событие инициации смены номера телефона. Публикуется сервисом аккаунтов — + * подписчик отправляет SMS с кодом подтверждения. + * + * @example + * ```ts + * client.emit('account.phone_change_initiated', { + * phone: '+79001234567', + * code: '123456', + * }); + * ``` + */ +export interface PhoneChangedEvent { + /** Новый номер телефона пользователя */ phone: string + /** Код подтверждения */ code: string - } +} diff --git a/src/events/auth/otp-requested.interface.ts b/src/events/auth/otp-requested.interface.ts index 5ffc8bd..7d612ee 100644 --- a/src/events/auth/otp-requested.interface.ts +++ b/src/events/auth/otp-requested.interface.ts @@ -1,5 +1,27 @@ +/** + * Событие запроса OTP-кода. Публикуется сервисом аутентификации — + * подписчик (например, notification-service) доставляет код пользователю. + * + * @example Публикация события + * ```ts + * client.emit('auth.otp_requested', { + * identifier: '+79001234567', + * code: '123456', + * type: 'phone', + * }); + * ``` + * + * @example Подписка на событие + * ```ts + * @EventPattern('auth.otp_requested') + * handle(data: OtpRequestedEvent) { ... } + * ``` + */ export interface OtpRequestedEvent { + /** Email или номер телефона получателя */ identifier: string + /** OTP-код для отправки */ code: string + /** Тип идентификатора */ type: 'email' | 'phone' } diff --git a/src/proto/paths.ts b/src/proto/paths.ts index f726371..78e5a09 100644 --- a/src/proto/paths.ts +++ b/src/proto/paths.ts @@ -1,7 +1,31 @@ import { join } from 'node:path'; +/** + * Абсолютные пути к `.proto` файлам. + * + * Используются при регистрации gRPC клиентов и серверов в NestJS. + * + * @example Регистрация gRPC клиента + * ```ts + * import { ClientsModule, Transport } from '@nestjs/microservices'; + * import { PROTO_PATHS } from '@teacinema/contracts'; + * + * ClientsModule.register([{ + * name: 'AUTH_SERVICE', + * transport: Transport.GRPC, + * options: { + * protoPath: PROTO_PATHS.AUTH, + * package: 'auth.v1', + * url: 'localhost:5000', + * }, + * }]) + * ``` + */ export const PROTO_PATHS = { + /** Путь к `auth.proto` (пакет `auth.v1`) */ AUTH: join(__dirname, '../../proto/auth.proto'), + /** Путь к `account.proto` (пакет `account.v1`) */ ACCOUNT: join(__dirname, '../../proto/account.proto'), + /** Путь к `users.proto` (пакет `users.v1`) */ USERS: join(__dirname, '../../proto/users.proto'), } as const diff --git a/typedoc.json b/typedoc.json new file mode 100644 index 0000000..81863ad --- /dev/null +++ b/typedoc.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://typedoc.org/schema.json", + "entryPoints": ["src/index.ts"], + "out": "docs", + "name": "@teacinema/contracts", + "readme": "README.md", + "includeVersion": true, + "categorizeByGroup": true, + "tsconfig": "tsconfig.json", + "skipErrorChecking": true +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 58f5d36..3e54f06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,6 +7,17 @@ resolved "https://registry.yarnpkg.com/@bufbuild/protobuf/-/protobuf-2.10.2.tgz#d7c063301f2a33095fc202f06bf3cce0c138dfcd" integrity sha512-uFsRXwIGyu+r6AMdz+XijIIZJYpoWeYzILt5yZ2d3mCjQrWUTVpVD9WL/jZAbvp+Ed04rOhrsk7FiTcEDseB5A== +"@gerrit0/mini-shiki@^3.17.0": + version "3.23.0" + resolved "https://registry.yarnpkg.com/@gerrit0/mini-shiki/-/mini-shiki-3.23.0.tgz#d9414f3080b88303b18f3a311846e37e424d800c" + integrity sha512-bEMORlG0cqdjVyCEuU0cDQbORWX+kYCeo0kV1lbxF5bt4r7SID2l9bqsxJEM0zndaxpOUT7riCyIVEuqq/Ynxg== + dependencies: + "@shikijs/engine-oniguruma" "^3.23.0" + "@shikijs/langs" "^3.23.0" + "@shikijs/themes" "^3.23.0" + "@shikijs/types" "^3.23.0" + "@shikijs/vscode-textmate" "^10.0.2" + "@nestjs/microservices@^11.1.12": version "11.1.12" resolved "https://registry.yarnpkg.com/@nestjs/microservices/-/microservices-11.1.12.tgz#05c497eb5ddcae09ae8ac0d3aa1bcd0b7336816b" @@ -15,6 +26,48 @@ iterare "1.2.1" tslib "2.8.1" +"@shikijs/engine-oniguruma@^3.23.0": + version "3.23.0" + resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz#789421048d66ac1b33613169d6d18b9cc6e340ed" + integrity sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g== + dependencies: + "@shikijs/types" "3.23.0" + "@shikijs/vscode-textmate" "^10.0.2" + +"@shikijs/langs@^3.23.0": + version "3.23.0" + resolved "https://registry.yarnpkg.com/@shikijs/langs/-/langs-3.23.0.tgz#00959d8b16c7f671221ae79b3ad8cde7e6a5c112" + integrity sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg== + dependencies: + "@shikijs/types" "3.23.0" + +"@shikijs/themes@^3.23.0": + version "3.23.0" + resolved "https://registry.yarnpkg.com/@shikijs/themes/-/themes-3.23.0.tgz#fd96ca5ad52639057995bc2093682884e1846f27" + integrity sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA== + dependencies: + "@shikijs/types" "3.23.0" + +"@shikijs/types@3.23.0", "@shikijs/types@^3.23.0": + version "3.23.0" + resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-3.23.0.tgz#d441571a058641926018ae3de99866f39e5bbdf2" + integrity sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ== + dependencies: + "@shikijs/vscode-textmate" "^10.0.2" + "@types/hast" "^3.0.4" + +"@shikijs/vscode-textmate@^10.0.2": + version "10.0.2" + resolved "https://registry.yarnpkg.com/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz#a90ab31d0cc1dfb54c66a69e515bf624fa7b2224" + integrity sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg== + +"@types/hast@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" + integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== + dependencies: + "@types/unist" "*" + "@types/node@^25.0.10": version "25.0.10" resolved "https://registry.yarnpkg.com/@types/node/-/node-25.0.10.tgz#4864459c3c9459376b8b75fd051315071c8213e7" @@ -22,6 +75,28 @@ dependencies: undici-types "~7.16.0" +"@types/unist@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c" + integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + dependencies: + balanced-match "^1.0.0" + case-anything@^2.1.13: version "2.1.13" resolved "https://registry.yarnpkg.com/case-anything/-/case-anything-2.1.13.tgz#0cdc16278cb29a7fcdeb072400da3f342ba329e9" @@ -39,16 +114,62 @@ dprint-node@^1.0.8: dependencies: detect-libc "^1.0.3" +entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + iterare@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/iterare/-/iterare-1.2.1.tgz#139c400ff7363690e33abffa33cbba8920f00042" integrity sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q== +linkify-it@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421" + integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ== + dependencies: + uc.micro "^2.0.0" + +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + +markdown-it@^14.1.0: + version "14.1.1" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.1.tgz#856f90b66fc39ae70affd25c1b18b581d7deee1f" + integrity sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA== + dependencies: + argparse "^2.0.1" + entities "^4.4.0" + linkify-it "^5.0.0" + mdurl "^2.0.0" + punycode.js "^2.3.1" + uc.micro "^2.1.0" + +mdurl@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" + integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w== + +minimatch@^9.0.5: + version "9.0.9" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.9.tgz#9b0cb9fcb78087f6fd7eababe2511c4d3d60574e" + integrity sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== + dependencies: + brace-expansion "^2.0.2" + protoc@33.4.0: version "33.4.0" resolved "https://registry.yarnpkg.com/protoc/-/protoc-33.4.0.tgz#4a288b59f5f50b9a2c4bbf345276357e59dd6f10" integrity sha512-dC1SJKbn4f60onsAMrfiPMygfSz4w/tPGHtPCqMSa5CLfHocJXkHjsvXeuuhjSPAJ8uUc8rfUvs0Hy9nmKIOhA== +punycode.js@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7" + integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA== + rxjs@^7.8.2: version "7.8.2" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" @@ -85,12 +206,33 @@ tslib@2.8.1, tslib@^2.1.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== +typedoc@^0.28.17: + version "0.28.17" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.28.17.tgz#eab7c6649494d0a796e0b2fd2c9a5aea41b0a781" + integrity sha512-ZkJ2G7mZrbxrKxinTQMjFqsCoYY6a5Luwv2GKbTnBCEgV2ihYm5CflA9JnJAwH0pZWavqfYxmDkFHPt4yx2oDQ== + dependencies: + "@gerrit0/mini-shiki" "^3.17.0" + lunr "^2.3.9" + markdown-it "^14.1.0" + minimatch "^9.0.5" + yaml "^2.8.1" + typescript@^5.9.3: version "5.9.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== +uc.micro@^2.0.0, uc.micro@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" + integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== + undici-types@~7.16.0: version "7.16.0" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== + +yaml@^2.8.1: + version "2.8.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.2.tgz#5694f25eca0ce9c3e7a9d9e00ce0ddabbd9e35c5" + integrity sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==