diff --git a/knip.config.ts b/knip.config.ts index 987f469..72795c8 100644 --- a/knip.config.ts +++ b/knip.config.ts @@ -3,7 +3,8 @@ import type { KnipConfig } from 'knip' export default { workspaces: { 'packages/h3': { - ignore: ['**/playground/**'] + ignore: ['**/playground/**'], + ignoreDependencies: ['srvx'] }, 'packages/hono': { ignore: ['**/playground/**'] diff --git a/packages/h3/README.md b/packages/h3/README.md index dadf3ed..cf5e918 100644 --- a/packages/h3/README.md +++ b/packages/h3/README.md @@ -4,26 +4,26 @@ [![npm downloads][npm-downloads-src]][npm-downloads-href] [![CI][ci-src]][ci-href] -Internationalization middleware & utilities for h3 (and therefore also for Nitro, which is using h3) +Internationalization middleware & utilities for h3 (and therefore also for Nitro, which is using H3) > [!NOTE] -> You’re viewing the `srvmid` repository, which is developing for h3 v2. If you want to check h3 v1, please see the [`@intlify/h3` repository](https://github.com/intlify/h3/tree/main) +> You’re viewing the `srvmid` repository, which is developing for H3 v2. If you want to check H3 v1, please see the [`@intlify/h3` repository](https://github.com/intlify/h3/tree/main) ## 🌟 Features +βœ…οΈοΈ  **Internationalization utils:** support [internationalization +utils](https://github.com/intlify/srvmid/blob/main/packages/h3/docs/index.md) via [@intlify/utils](https://github.com/intlify/utils) + βœ…οΈ  **Translation:** Simple API like [vue-i18n](https://vue-i18n.intlify.dev/) βœ…  **Custom locale detector:** You can implement your own locale detector on server-side -βœ…οΈοΈ  **Useful utilities:** support internationalization composables -utilities via [@intlify/utils](https://github.com/intlify/utils) - ## πŸ’Ώ Installation ```sh @@ -40,48 +40,74 @@ pnpm add @intlify/h3 bun add @intlify/h3 ``` -## πŸš€ Usage (h3) +## πŸš€ Usage + +### Detect locale with utils + +Detect locale from `accept-language` header: ```ts -import { createServer } from 'node:http' -import { createApp, createRouter, eventHandler, toNodeListener } from 'h3' -import { - defineI18nMiddleware, - detectLocaleFromAcceptLanguageHeader, - useTranslation -} from '@intlify/h3' - -// define middleware with vue-i18n like options -const middleware = defineI18nMiddleware({ - // detect locale with `accept-language` header - locale: detectLocaleFromAcceptLanguageHeader, - // resource messages - messages: { - en: { - hello: 'Hello {name}!' - }, - ja: { - hello: 'こんにけは、{name}!' - } - } - // something options - // ... +import { H3 } from 'h3' +import { getHeaderLocale } from '@intlify/h3' + +const app = new H3() + +app.get('/', event => { + // detect locale from HTTP header which has `Accept-Language: ja,en-US;q=0.7,en;q=0.3` + const locale = getHeaderLocale(event.req) + return locale.toString() }) +``` -// install middleware with `createApp` option -const app = createApp({ ...middleware }) +Detect locale from URL query: -const router = createRouter() -router.get( - '/', - eventHandler(async event => { - // use `useTranslation` in event handler - const t = await useTranslation(event) - return t('hello', { name: 'h3' }) - }) -) +```ts +import { H3 } from 'h3' +import { getQueryLocale } from '@intlify/h3' + +const app = new H3() + +app.get('/', event => { + // detect locale from query which has 'http://localhost:3000?locale=en' + const locale = getQueryLocale(event.req) + return locale.toString() +}) +``` + +### Translation + +```ts +import { createServer } from 'node:http' +import { H3, toNodeListener } from 'h3' +import { plugin as i18n, detectLocaleFromAcceptLanguageHeader, useTranslation } from '@intlify/h3' + +// install plugin with `H3` constructor +const app = new H3({ + plugins: [ + i18n({ + // detect locale with `accept-language` header + locale: detectLocaleFromAcceptLanguageHeader, + // resource messages + messages: { + en: { + hello: 'Hello {name}!' + }, + ja: { + hello: 'こんにけは、{name}!' + } + } + // something options + // ... + }) + ] +}) + +app.get('/', async event => { + // use `useTranslation` in event handler + const t = await useTranslation(event) + return t('hello', { name: 'h3' }) +}) -app.use(router) createServer(toNodeListener(app)).listen(3000) ``` @@ -120,19 +146,25 @@ You can detect locale with your custom logic from current `H3Event`. example for detecting locale from url query: ```ts -import { defineI18nMiddleware, getQueryLocale } from '@intlify/h3' +import { H3 } from 'h3' +import { plugin as i18n, getQueryLocale } from '@intlify/h3' + import type { H3Event } from 'h3' // define custom locale detector const localeDetector = (event: H3Event): string => { - return getQueryLocale(event).toString() + return getQueryLocale(event.req).toString() } -const middleware = defineI18nMiddleware({ - // set your custom locale detector - locale: localeDetector - // something options - // ... +const app = new H3({ + plugins: [ + i18n({ + // set your custom locale detector + locale: localeDetector + // something options + // ... + }) + ] }) ``` @@ -146,11 +178,13 @@ You can make that function asynchronous. This is useful when loading resources a ```ts -import { defineI18nMiddleware } from '@intlify/h3' -import type { DefineLocaleMessage } from '@intlify/h3' +import { H3 } from 'h3' +import { plugin as i18n, getCookieLocale } from '@intlify/h3' + import type { H3Event } from 'h3' +import type { DefineLocaleMessage, CoreContext } from '@intlify/h3' -const loader = (path: string) => import(path).then(m => m.default || m) +const loader = (path: string) => import(path).then(m => m.default) const messages: Record ReturnType> = { en: () => loader('./locales/en.json'), ja: () => loader('./locales/ja.json') @@ -162,7 +196,7 @@ const localeDetector = async ( i18n: CoreContext ): Promise => { // detect locale - const locale = getCookieLocale(event).toString() + const locale = getCookieLocale(event.req).toString() // resource lazy loading const loader = messages[locale] @@ -174,11 +208,15 @@ const localeDetector = async ( return locale } -const middleware = defineI18nMiddleware({ - // set your custom locale detector - locale: localeDetector - // something options - // ... +const app = new H3({ + plugins: [ + i18n({ + // set your custom locale detector + locale: localeDetector + // something options + // ... + }) + ] }) ``` @@ -191,7 +229,7 @@ const middleware = defineI18nMiddleware({ > We would like to get feedback from you πŸ™‚. > [!NOTE] -> The exeample code is [here](https://github.com/intlify/h3/tree/main/playground/typesafe-schema) +> The example code is [here](https://github.com/intlify/h3/tree/main/playground/typesafe-schema) @@ -209,13 +247,13 @@ your application code: ```ts import { defineI18nMiddleware } from '@intlify/h3' -import { createApp } from 'h3' +import { H3 } from 'h3' import en from './locales/en.ts' // define resource schema, as 'en' is master resource schema type ResourceSchema = typeof en -const middleware = defineI18nMiddleware<[ResourceSchema], 'en' | 'ja'>({ +const i18nMiddleware = defineI18nMiddleware<[ResourceSchema], 'en' | 'ja'>({ messages: { en: { hello: 'Hello, {name}' } } @@ -223,7 +261,10 @@ const middleware = defineI18nMiddleware<[ResourceSchema], 'en' | 'ja'>({ // ... }) -const app = createApp({ ...middleware }) +const app = new H3() +app.use(i18nMiddleware.onRequest) +app.use(i18nMiddleware.onResponse) + // something your implementation code ... // ... ``` @@ -267,7 +308,7 @@ You can completion resources key on translation function with `useTranslation`. ![Key Completion](assets/key-completion.gif) -resource keys completion has twe ways. +resource keys completion has two ways. ### Type parameter for `useTranslation` @@ -283,19 +324,15 @@ You can `useTranslation` set the type parameter to the resource schema you want the part of example: ```ts -const router = createRouter() -router.get( - '/', - eventHandler(async event => { - type ResourceSchema = { - hello: string - } - // set resource schema as type parameter - const t = await useTranslation(event) - // you can completion when you type `t('` - return t('hello', { name: 'h3' }) - }) -) +app.get('/', async event => { + type ResourceSchema = { + hello: string + } + // set resource schema as type parameter + const t = await useTranslation(event) + // you can completion when you type `t('` + return t('hello', { name: 'h3' }) +}) ``` ### global resource schema with `declare module '@intlify/h3'` @@ -323,15 +360,11 @@ declare module '@intlify/h3' { export interface DefineLocaleMessage extends ResourceSchema {} } -const router = createRouter() -router.get( - '/', - eventHandler(async event => { - const t = await useTranslation(event) - // you can completion when you type `t('` - return t('hello', { name: 'h3' }) - }) -) +app.get('/', async event => { + const t = await useTranslation(event) + // you can completion when you type `t('` + return t('hello', { name: 'h3' }) +}) ``` The advantage of this way is that it is not necessary to specify the resource schema in the `useTranslation` type parameter. diff --git a/packages/h3/docs/functions/defineI18nMiddleware.md b/packages/h3/docs/functions/defineI18nMiddleware.md deleted file mode 100644 index 68caed3..0000000 --- a/packages/h3/docs/functions/defineI18nMiddleware.md +++ /dev/null @@ -1,61 +0,0 @@ -[**@intlify/h3**](../index.md) - -*** - -[@intlify/h3](../index.md) / defineI18nMiddleware - -# Function: defineI18nMiddleware() - -```ts -function defineI18nMiddleware(options): I18nMiddleware; -``` - -define i18n middleware for h3 - -## Type Parameters - -| Type Parameter | Default type | -| ------ | ------ | -| `Schema` | `RemoveIndexSignature`\<\{ \[`key`: `string`\]: `LocaleMessageValue`\<`string`\>; `hello`: `string`; `nest`: \{ `foo`: \{ `bar`: `string`; \}; \}; `test`: `string`; \}\> | -| `Locales` | `string` | -| `Message` | `string` | -| `Options` *extends* `CoreOptions`\<`Message`, `SchemaParams`\<`Schema`, `Message`\>, `LocaleParams`\<`Locales`\>, `LocaleParams`\<`Locales`\> *extends* `object` ? `M` : `LocaleParams`\<`Locales`\> *extends* `string` ? `string` & `LocaleParams`\<`Locales`\> : `string`, `LocaleParams`\<`Locales`\> *extends* `object` ? `D` : `LocaleParams`\<`Locales`\> *extends* `string` ? `string` & `LocaleParams`\<`Locales`\> : `string`, `LocaleParams`\<`Locales`\> *extends* `object` ? `N` : `LocaleParams`\<`Locales`\> *extends* `string` ? `string` & `LocaleParams`\<`Locales`\> : `string`, `SchemaParams`\<`Schema`, `Message`\> *extends* `object` ? `M` : `LocaleMessage`\<`string`\>, `SchemaParams`\<`Schema`, `Message`\> *extends* `object` ? `D` : `DateTimeFormat`, `SchemaParams`\<`Schema`, `Message`\> *extends* `object` ? `N` : `NumberFormat`, `LocaleMessages`\<`SchemaParams`\<`Schema`, `Message`\> *extends* `object` ? `M` : `LocaleMessage`\<`string`\>, `LocaleParams`\<`Locales`\> *extends* `object` ? `M` : `LocaleParams`\<`Locales`\> *extends* `string` ? `string` & `LocaleParams`\<`Locales`\> : `string`, `Message`\>, `DateTimeFormats`\<`SchemaParams`\<`Schema`, `Message`\> *extends* `object` ? `D` : `DateTimeFormat`, `LocaleParams`\<`Locales`\> *extends* `object` ? `D` : `LocaleParams`\<`Locales`\> *extends* `string` ? `string` & `LocaleParams`\<`Locales`\> : `string`\>, `NumberFormats`\<`SchemaParams`\<`Schema`, `Message`\> *extends* `object` ? `N` : `NumberFormat`, `LocaleParams`\<`Locales`\> *extends* `object` ? `N` : `LocaleParams`\<`Locales`\> *extends* `string` ? `string` & `LocaleParams`\<`Locales`\> : `string`\>\> | `CoreOptions`\<`Message`, `SchemaParams`\<`Schema`, `Message`\>, `LocaleParams`\<`Locales`\>, `LocaleParams`\<`Locales`\> *extends* `object` ? `M` : `LocaleParams`\<`Locales`\> *extends* `string` ? `string` & `LocaleParams`\<`Locales`\> : `string`, `LocaleParams`\<`Locales`\> *extends* `object` ? `D` : `LocaleParams`\<`Locales`\> *extends* `string` ? `string` & `LocaleParams`\<`Locales`\> : `string`, `LocaleParams`\<`Locales`\> *extends* `object` ? `N` : `LocaleParams`\<`Locales`\> *extends* `string` ? `string` & `LocaleParams`\<`Locales`\> : `string`, `SchemaParams`\<`Schema`, `Message`\> *extends* `object` ? `M` : `LocaleMessage`\<`string`\>, `SchemaParams`\<`Schema`, `Message`\> *extends* `object` ? `D` : `DateTimeFormat`, `SchemaParams`\<`Schema`, `Message`\> *extends* `object` ? `N` : `NumberFormat`, `LocaleMessages`\<`SchemaParams`\<`Schema`, `Message`\> *extends* `object` ? `M` : `LocaleMessage`\<`string`\>, `LocaleParams`\<`Locales`\> *extends* `object` ? `M` : `LocaleParams`\<`Locales`\> *extends* `string` ? `string` & `LocaleParams`\<`Locales`\> : `string`, `Message`\>, `DateTimeFormats`\<`SchemaParams`\<`Schema`, `Message`\> *extends* `object` ? `D` : `DateTimeFormat`, `LocaleParams`\<`Locales`\> *extends* `object` ? `D` : `LocaleParams`\<`Locales`\> *extends* `string` ? `string` & `LocaleParams`\<`Locales`\> : `string`\>, `NumberFormats`\<`SchemaParams`\<`Schema`, `Message`\> *extends* `object` ? `N` : `NumberFormat`, `LocaleParams`\<`Locales`\> *extends* `object` ? `N` : `LocaleParams`\<`Locales`\> *extends* `string` ? `string` & `LocaleParams`\<`Locales`\> : `string`\>\> | - -## Parameters - -| Parameter | Type | Description | -| ------ | ------ | ------ | -| `options` | `Options` | An i18n options like vue-i18n [`createI18n`]([https://vue-i18n.intlify.dev/guide/#javascript](https://vue-i18n.intlify.dev/guide/#javascript)), which are passed to `createCoreContext` of `@intlify/core`, see about details [`CoreOptions` of `@intlify/core`](https://github.com/intlify/vue-i18n-next/blob/6a9947dd3e0fe90de7be9c87ea876b8779998de5/packages/core-base/src/context.ts#L196-L216) | - -## Returns - -[`I18nMiddleware`](../interfaces/I18nMiddleware.md) - -A defined i18n middleware, which is included `onRequest` and `onAfterResponse` options of `createApp` - -## Example - -```js -import { defineI18nMiddleware } from '@intlify/h3' - -const middleware = defineI18nMiddleware({ - messages: { - en: { - hello: 'Hello {name}!', - }, - ja: { - hello: 'こんにけは、{name}!', - }, - }, - // your locale detection logic here - locale: (event) => { - // ... - }, -}) - -const app = createApp({ ...middleware }) -``` - -## Description - -Define the middleware to be specified for h3 [`createApp`]([https://www.jsdocs.io/package/h3#createApp](https://www.jsdocs.io/package/h3#createApp)) diff --git a/packages/h3/docs/functions/detectLocaleFromAcceptLanguageHeader.md b/packages/h3/docs/functions/detectLocaleFromAcceptLanguageHeader.md index 0bd51e5..6fe8c4f 100644 --- a/packages/h3/docs/functions/detectLocaleFromAcceptLanguageHeader.md +++ b/packages/h3/docs/functions/detectLocaleFromAcceptLanguageHeader.md @@ -10,13 +10,13 @@ function detectLocaleFromAcceptLanguageHeader(event): string; ``` -locale detection with `Accept-Language` header +Locale detection with `Accept-Language` header ## Parameters | Parameter | Type | Description | | ------ | ------ | ------ | -| `event` | `H3Event` | A h3 event | +| `event` | `H3Event` | A H3 event | ## Returns @@ -27,10 +27,10 @@ A locale string, which will be detected of **first** from `Accept-Language` head ## Example ```js -import { createApp } from 'h3' -import { defineI18nMiddleware, detectLocaleWithAcceeptLanguageHeader } from '@intlify/h3' +import { H3 } from 'h3' +import { defineI18nMiddleware, detectLocaleFromAcceptLanguageHeader } from '@intlify/h3' -const middleware = defineI18nMiddleware({ +const i18nMiddleware = defineI18nMiddleware({ messages: { en: { hello: 'Hello {name}!', @@ -39,8 +39,10 @@ const middleware = defineI18nMiddleware({ hello: 'こんにけは、{name}!', }, }, - locale: detectLocaleWithAcceeptLanguageHeader + locale: detectLocaleFromAcceptLanguageHeader }) -const app = createApp({ ...middleware }) +const app = new H3() + .use(i18nMiddleware.onRequest) + .use(i18nMiddleware.onResponse) ``` diff --git a/packages/h3/docs/functions/useTranslation.md b/packages/h3/docs/functions/useTranslation.md index c429bb4..da02eab 100644 --- a/packages/h3/docs/functions/useTranslation.md +++ b/packages/h3/docs/functions/useTranslation.md @@ -27,7 +27,7 @@ function useTranslation(event): Promise>>>; ``` -use translation function in event handler +Use translation function in event handler ## Type Parameters @@ -40,7 +40,7 @@ use translation function in event handler | Parameter | Type | Description | | ------ | ------ | ------ | -| `event` | `Event` | A h3 event | +| `event` | `Event` | A H3 event | ## Returns @@ -63,23 +63,16 @@ use translation function in event handler `test`: `string`; \}\>\>\>\> -Return a translation function, which can be translated with i18n resource messages +Return a translation function, which can be translated with internationalization resource messages ## Example ```js -import { createRouter } from 'h3' - -const router = createRouter() -router.get( +app.get( '/', eventHandler(async (event) => { const t = await useTranslation(event) - return t('hello', { name: 'h3' }) + return t('hello', { name: 'H3' }) }), ) ``` - -## Description - -This function must be initialized with defineI18nMiddleware. See about the [defineI18nMiddleware](defineI18nMiddleware.md) diff --git a/packages/h3/docs/index.md b/packages/h3/docs/index.md index afe99a8..1a08d8f 100644 --- a/packages/h3/docs/index.md +++ b/packages/h3/docs/index.md @@ -6,12 +6,17 @@ Internationalization middleware & utilities for h3 +## Variables + +| Variable | Description | +| ------ | ------ | +| [plugin](variables/plugin.md) | Internationalization plugin for H3 | + ## Functions | Function | Description | | ------ | ------ | -| [defineI18nMiddleware](functions/defineI18nMiddleware.md) | define i18n middleware for h3 | -| [detectLocaleFromAcceptLanguageHeader](functions/detectLocaleFromAcceptLanguageHeader.md) | locale detection with `Accept-Language` header | +| [detectLocaleFromAcceptLanguageHeader](functions/detectLocaleFromAcceptLanguageHeader.md) | Locale detection with `Accept-Language` header | | [getCookieLocale](functions/getCookieLocale.md) | get locale from cookie | | [getHeaderLanguage](functions/getHeaderLanguage.md) | get language from header | | [getHeaderLanguages](functions/getHeaderLanguages.md) | get languages from header | @@ -25,17 +30,18 @@ Internationalization middleware & utilities for h3 | [tryHeaderLocales](functions/tryHeaderLocales.md) | try to get locales from header | | [tryPathLocale](functions/tryPathLocale.md) | try to get the locale from the path | | [tryQueryLocale](functions/tryQueryLocale.md) | try to get the locale from the query | -| [useTranslation](functions/useTranslation.md) | use translation function in event handler | +| [useTranslation](functions/useTranslation.md) | Use translation function in event handler | ## Interfaces | Interface | Description | | ------ | ------ | | [DefineLocaleMessage](interfaces/DefineLocaleMessage.md) | The type definition of Locale Message for `@intlify/h3` package | -| [I18nMiddleware](interfaces/I18nMiddleware.md) | i18n middleware for h3 | +| [I18nMiddleware](interfaces/I18nMiddleware.md) | Internationalization middleware for H3 | ## Type Aliases | Type Alias | Description | | ------ | ------ | | [CoreContext](type-aliases/CoreContext.md) | - | +| [I18nPluginOptions](type-aliases/I18nPluginOptions.md) | Internationalization plugin options for H3 | diff --git a/packages/h3/docs/interfaces/DefineLocaleMessage.md b/packages/h3/docs/interfaces/DefineLocaleMessage.md index 64e11e0..2d48217 100644 --- a/packages/h3/docs/interfaces/DefineLocaleMessage.md +++ b/packages/h3/docs/interfaces/DefineLocaleMessage.md @@ -24,10 +24,6 @@ declare module '@intlify/h3' { } ``` -## Description - -The typealias is used to strictly define the type of the Locale message. - ## Extends - `LocaleMessage`\<`string`\>.`ResourceSchema` diff --git a/packages/h3/docs/interfaces/I18nMiddleware.md b/packages/h3/docs/interfaces/I18nMiddleware.md index 8e68bab..790b428 100644 --- a/packages/h3/docs/interfaces/I18nMiddleware.md +++ b/packages/h3/docs/interfaces/I18nMiddleware.md @@ -6,15 +6,11 @@ # Interface: I18nMiddleware -i18n middleware for h3 - -## Description - -The middleware for h3 [`createApp`]([https://www.jsdocs.io/package/h3#createApp](https://www.jsdocs.io/package/h3#createApp)) +Internationalization middleware for H3 ## Properties | Property | Type | Description | | ------ | ------ | ------ | -| `onAfterResponse` | (`event`, `response?`) => `void` \| `Promise`\<`void`\> | `onAfterResponse` option of `createApp` | -| `onRequest` | (`event`) => `void` \| `Promise`\<`void`\> | `onRequest` option of `createApp` | +| `onRequest` | `Middleware` | Request middleware which is defined with [`onRequest`](https://h3.dev/utils/more#onrequesthook) | +| `onResponse` | `Middleware` | Response middleware which is defined with [`onResponse`](https://h3.dev/utils/more#onresponsehook) | diff --git a/packages/h3/docs/type-aliases/I18nPluginOptions.md b/packages/h3/docs/type-aliases/I18nPluginOptions.md new file mode 100644 index 0000000..1777b97 --- /dev/null +++ b/packages/h3/docs/type-aliases/I18nPluginOptions.md @@ -0,0 +1,21 @@ +[**@intlify/h3**](../index.md) + +*** + +[@intlify/h3](../index.md) / I18nPluginOptions + +# Type Alias: I18nPluginOptions\ + +```ts +type I18nPluginOptions = CoreOptions, LocaleParams>; +``` + +Internationalization plugin options for H3 + +## Type Parameters + +| Type Parameter | Default type | Description | +| ------ | ------ | ------ | +| `Schema` | `DefaultLocaleMessageSchema` | Locale message schema type, default is `DefaultLocaleMessageSchema` | +| `Locales` | `string` | Locale type, default is `string` | +| `Message` | `string` | Message type, default is `string` | diff --git a/packages/h3/docs/variables/plugin.md b/packages/h3/docs/variables/plugin.md new file mode 100644 index 0000000..2d370b7 --- /dev/null +++ b/packages/h3/docs/variables/plugin.md @@ -0,0 +1,48 @@ +[**@intlify/h3**](../index.md) + +*** + +[@intlify/h3](../index.md) / plugin + +# Variable: plugin() + +```ts +const plugin: (options) => H3Plugin; +``` + +Internationalization plugin for H3 + +## Parameters + +| Parameter | Type | +| ------ | ------ | +| `options` | [`I18nPluginOptions`](../type-aliases/I18nPluginOptions.md) | + +## Returns + +`H3Plugin` + +## Example + +```ts +import { H3 } from 'h3' +import { plugin as i18n } from '@intlify/h3' + +const app = new H3({ + plugins: [ + i18n({ + messages: { + en: { + hello: 'Hello {name}!', + }, + ja: { + hello: 'こんにけは、{name}!', + }, + }, + // your locale detection logic here + locale: (event) => { + // ... + }, + }) + ] +}) diff --git a/packages/h3/package.json b/packages/h3/package.json index da6a6b6..4fff480 100644 --- a/packages/h3/package.json +++ b/packages/h3/package.json @@ -68,10 +68,9 @@ }, "devDependencies": { "@types/node": "catalog:", - "@types/supertest": "^6.0.3", - "h3": "^1.15.4", + "h3": "^2.0.1-rc.5", "publint": "catalog:", - "supertest": "^7.1.4", + "srvx": "^0.9.6", "tsdown": "catalog:", "typedoc": "catalog:", "typedoc-plugin-markdown": "catalog:", diff --git a/packages/h3/playground/basic/index.ts b/packages/h3/playground/basic/index.ts index 659795d..0b90f54 100644 --- a/packages/h3/playground/basic/index.ts +++ b/packages/h3/playground/basic/index.ts @@ -1,33 +1,35 @@ -import { createServer } from 'node:http' -import { createApp, createRouter, eventHandler, toNodeListener } from 'h3' +import { H3 } from 'h3' +import { serve } from 'srvx' import { - defineI18nMiddleware, detectLocaleFromAcceptLanguageHeader, + plugin as i18n, useTranslation -} from '../../src/index.ts' // `@inlify/h3` +} from '../../src/index.ts' // `@intlify/h3` -const middleware = defineI18nMiddleware({ - locale: detectLocaleFromAcceptLanguageHeader, - messages: { - en: { - hello: 'hello, {name}' - }, - ja: { - hello: 'こんにけは, {name}' - } - } +const app = new H3({ + plugins: [ + i18n({ + locale: detectLocaleFromAcceptLanguageHeader, + messages: { + en: { + hello: 'hello, {name}' + }, + ja: { + hello: 'こんにけは, {name}' + } + } + }) + ] }) -const app = createApp({ ...middleware }) +app.get('/', async event => { + const t = await useTranslation(event) + return t('hello', { name: 'h3' }) +}) -const router = createRouter() -router.get( - '/', - eventHandler(async event => { - const t = await useTranslation(event) - return t('hello', { name: 'h3' }) - }) -) +const server = serve({ + port: 3000, + fetch: app.fetch +}) -app.use(router) -createServer(toNodeListener(app)).listen(3000) +await server.ready() diff --git a/packages/h3/playground/global-schema/index.ts b/packages/h3/playground/global-schema/index.ts index 959e03e..3cff2c3 100644 --- a/packages/h3/playground/global-schema/index.ts +++ b/packages/h3/playground/global-schema/index.ts @@ -1,10 +1,10 @@ -import { createServer } from 'node:http' -import { createApp, createRouter, eventHandler, toNodeListener } from 'h3' +import { H3 } from 'h3' +import { serve } from 'srvx' import { - defineI18nMiddleware, detectLocaleFromAcceptLanguageHeader, + plugin as i18n, useTranslation -} from '../../src/index.ts' // in your project, `import { ... } from '@inlify/h3'` +} from '../../src/index.ts' // in your project, `import { ... } from '@intlify/h3'` import en from './locales/en.ts' import ja from './locales/ja.ts' @@ -17,24 +17,27 @@ declare module '../../src/index.ts' { // please use `declare module '@intlifly/h3'`, if you want to use global resource schema in your project. export interface DefineLocaleMessage extends ResourceSchema {} } -const middleware = defineI18nMiddleware({ - locale: detectLocaleFromAcceptLanguageHeader, - messages: { - en, - ja - } + +const app = new H3({ + plugins: [ + i18n({ + locale: detectLocaleFromAcceptLanguageHeader, + messages: { + en, + ja + } + }) + ] }) -const app = createApp({ ...middleware }) +app.get('/', async event => { + const t = await useTranslation(event) + return t('hello', { name: 'h3' }) +}) -const router = createRouter() -router.get( - '/', - eventHandler(async event => { - const t = await useTranslation(event) - return t('hello', { name: 'h3' }) - }) -) +const server = serve({ + port: 3000, + fetch: app.fetch +}) -app.use(router) -createServer(toNodeListener(app)).listen(3000) +await server.ready() diff --git a/packages/h3/playground/local-schema/index.ts b/packages/h3/playground/local-schema/index.ts index 9a732d5..afbe007 100644 --- a/packages/h3/playground/local-schema/index.ts +++ b/packages/h3/playground/local-schema/index.ts @@ -1,35 +1,37 @@ -import { createApp, createRouter, eventHandler, toNodeListener } from 'h3' -import { createServer } from 'node:http' +import { H3 } from 'h3' +import { serve } from 'srvx' import { - defineI18nMiddleware, detectLocaleFromAcceptLanguageHeader, + plugin as i18n, useTranslation -} from '../../src/index.ts' // in your project, `import { ... } from '@inlify/h3'` +} from '../../src/index.ts' // in your project, `import { ... } from '@intlify/h3'` import en from './locales/en.ts' import ja from './locales/ja.ts' -const middleware = defineI18nMiddleware({ - locale: detectLocaleFromAcceptLanguageHeader, - messages: { - en, - ja - } +const app = new H3({ + plugins: [ + i18n({ + locale: detectLocaleFromAcceptLanguageHeader, + messages: { + en, + ja + } + }) + ] }) -const app = createApp({ ...middleware }) +app.get('/', async event => { + type ResourceSchema = { + hello: string + } + const t = await useTranslation(event) + return t('hello', { name: 'h3' }) +}) -const router = createRouter() -router.get( - '/', - eventHandler(async event => { - type ResourceSchema = { - hello: string - } - const t = await useTranslation(event) - return t('hello', { name: 'h3' }) - }) -) +const server = serve({ + port: 3000, + fetch: app.fetch +}) -app.use(router) -createServer(toNodeListener(app)).listen(3000) +await server.ready() diff --git a/packages/h3/playground/typesafe-schema/index.ts b/packages/h3/playground/typesafe-schema/index.ts index 1df8448..9257ddd 100644 --- a/packages/h3/playground/typesafe-schema/index.ts +++ b/packages/h3/playground/typesafe-schema/index.ts @@ -1,5 +1,5 @@ -// in your project, `import { ... } from '@inlify/h3'` -import { createApp } from 'h3' +// in your project, `import { ... } from '@intlify/h3'` +import { H3 } from 'h3' import { defineI18nMiddleware } from '../../src/index.ts' // define resource schema @@ -10,7 +10,7 @@ type ResourceSchema = { // you can specify resource schema and locales to type parameter. // - first type parameter: resource schema // - second type parameter: locales -const middleware = defineI18nMiddleware<[ResourceSchema], 'en' | 'ja'>({ +const { onRequest, onResponse } = defineI18nMiddleware<[ResourceSchema], 'en' | 'ja'>({ messages: { en: { hello: 'Hello, {name}' }, // you can see the type error, when you will comment out the below `ja` resource @@ -20,7 +20,8 @@ const middleware = defineI18nMiddleware<[ResourceSchema], 'en' | 'ja'>({ // ... }) -// @ts-expect-error -- FIXME -const app = createApp({ ...middleware }) +const app = new H3() +app.use(onRequest) +app.use(onResponse) // something your implementation code ... // ... diff --git a/packages/h3/playground/util-header/index.ts b/packages/h3/playground/util-header/index.ts new file mode 100644 index 0000000..e984ca4 --- /dev/null +++ b/packages/h3/playground/util-header/index.ts @@ -0,0 +1,17 @@ +import { H3 } from 'h3' +import { serve } from 'srvx' +import { getHeaderLocale } from '../../src/index.ts' // `@intlify/h3` + +const app = new H3() + +app.get('/', event => { + const locale = getHeaderLocale(event.req) + return locale.toString() +}) + +const server = serve({ + port: 3000, + fetch: app.fetch +}) + +await server.ready() diff --git a/packages/h3/playground/util-query/index.ts b/packages/h3/playground/util-query/index.ts new file mode 100644 index 0000000..41207c3 --- /dev/null +++ b/packages/h3/playground/util-query/index.ts @@ -0,0 +1,17 @@ +import { H3 } from 'h3' +import { serve } from 'srvx' +import { getQueryLocale } from '../../src/index.ts' // `@intlify/h3` + +const app = new H3() + +app.get('/', event => { + const locale = getQueryLocale(event.req) + return locale.toString() +}) + +const server = serve({ + port: 3000, + fetch: app.fetch +}) + +await server.ready() diff --git a/packages/h3/spec/e2e.spec.ts b/packages/h3/spec/e2e.spec.ts index 389cab1..8b2658c 100644 --- a/packages/h3/spec/e2e.spec.ts +++ b/packages/h3/spec/e2e.spec.ts @@ -1,6 +1,6 @@ import { exec, spawn } from 'node:child_process' import path from 'node:path' -import { afterAll, expect, test } from 'vitest' +import { afterEach, describe, expect, test } from 'vitest' import type { ExecOptions } from 'node:child_process' @@ -24,16 +24,36 @@ const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) let serve: ReturnType | null = null -afterAll(async () => { +afterEach(async () => { serve?.kill() }) -test('e2e', async () => { - const target = path.resolve(import.meta.dirname, '../playground/basic/index.ts') - serve = spawn('pnpx', ['tsx', target]) - await delay(3000) // wait for server to start - const stdout = await runCommand( - `curl -H 'Accept-Language: ja,en-US;q=0.7,en;q=0.3' http://localhost:3000` - ) - expect(stdout).toContain(`こんにけは, h3`) +describe('e2e', () => { + test('util-header', async () => { + const target = path.resolve(import.meta.dirname, '../playground/util-header/index.ts') + serve = spawn('pnpx', ['tsx', target]) + await delay(2000) // wait for server to start + const stdout = await runCommand( + `curl -H 'Accept-Language: ja,en-US;q=0.7,en;q=0.3' http://localhost:3000` + ) + expect(stdout).toContain(`ja`) + }) + + test('util-query', async () => { + const target = path.resolve(import.meta.dirname, '../playground/util-query/index.ts') + serve = spawn('pnpx', ['tsx', target]) + await delay(2000) // wait for server to start + const stdout = await runCommand(`curl http://localhost:3000?locale=en`) + expect(stdout).toContain(`en`) + }) + + test('translation', async () => { + const target = path.resolve(import.meta.dirname, '../playground/basic/index.ts') + serve = spawn('pnpx', ['tsx', target]) + await delay(2000) // wait for server to start + const stdout = await runCommand( + `curl -H 'Accept-Language: ja,en-US;q=0.7,en;q=0.3' http://localhost:3000` + ) + expect(stdout).toContain(`こんにけは, h3`) + }) }) diff --git a/packages/h3/spec/integration.spec.ts b/packages/h3/spec/integration.spec.ts index 43695fc..0b7c214 100644 --- a/packages/h3/spec/integration.spec.ts +++ b/packages/h3/spec/integration.spec.ts @@ -1,41 +1,41 @@ -import { getQueryLocale } from '@intlify/utils/h3' -import { createApp, eventHandler, toNodeListener } from 'h3' -import supertest from 'supertest' +import { eventHandler, H3 } from 'h3' import { afterEach, describe, expect, test, vi } from 'vitest' import { - defineI18nMiddleware, detectLocaleFromAcceptLanguageHeader, + getQueryLocale, + plugin as i18n, useTranslation } from '../src/index.ts' import type { CoreContext } from '@intlify/core' -import type { App, H3Event } from 'h3' +import type { H3Event } from 'h3' import type { DefineLocaleMessage } from '../src/index.ts' -let app: App -let request: ReturnType +let app: H3 afterEach(() => { vi.resetAllMocks() }) test('translation', async () => { - const middleware = defineI18nMiddleware({ - locale: detectLocaleFromAcceptLanguageHeader, - messages: { - en: { - hello: 'hello, {name}' - }, - ja: { - hello: 'こんにけは, {name}' - } - } + app = new H3({ + plugins: [ + i18n({ + locale: detectLocaleFromAcceptLanguageHeader, + messages: { + en: { + hello: 'hello, {name}' + }, + ja: { + hello: 'こんにけは, {name}' + } + } + }) + ] }) - app = createApp({ ...middleware }) - request = supertest(toNodeListener(app)) - app.use( + app.get( '/', eventHandler(async event => { const t = await useTranslation(event) @@ -43,32 +43,39 @@ test('translation', async () => { }) ) - const res = await request.get('/').set('accept-language', 'en;q=0.9,ja;q=0.8') - expect(res.body).toEqual({ message: 'hello, h3' }) + const response = await app.fetch( + new Request('http://localhost/', { + headers: { 'accept-language': 'en;q=0.9,ja;q=0.8' } + }) + ) + const body = await response.json() + expect(body).toEqual({ message: 'hello, h3' }) }) describe('custom locale detection', () => { test('basic', async () => { // define custom locale detector const localeDetector = (event: H3Event): string => { - return getQueryLocale(event).toString() + return getQueryLocale(event.req).toString() } - const middleware = defineI18nMiddleware({ - locale: localeDetector, - messages: { - en: { - hello: 'hello, {name}' - }, - ja: { - hello: 'こんにけは, {name}' - } - } + app = new H3({ + plugins: [ + i18n({ + locale: localeDetector, + messages: { + en: { + hello: 'hello, {name}' + }, + ja: { + hello: 'こんにけは, {name}' + } + } + }) + ] }) - app = createApp({ ...middleware }) - request = supertest(toNodeListener(app)) - app.use( + app.get( '/', eventHandler(async event => { const t = await useTranslation(event) @@ -76,8 +83,9 @@ describe('custom locale detection', () => { }) ) - const res = await request.get('/?locale=ja') - expect(res.body).toEqual({ message: 'こんにけは, h3' }) + const response = await app.fetch(new Request('http://localhost/?locale=ja')) + const body = await response.json() + expect(body).toEqual({ message: 'こんにけは, h3' }) }) test('async', async () => { @@ -94,7 +102,7 @@ describe('custom locale detection', () => { event: H3Event, i18n: CoreContext ) => { - const locale = getQueryLocale(event).toString() + const locale = getQueryLocale(event.req).toString() await sleep(100) const loader = messages[locale] if (loader && !i18n.messages[locale]) { @@ -104,18 +112,23 @@ describe('custom locale detection', () => { return locale } - const middleware = defineI18nMiddleware({ - locale: localeDetector, - messages: { - en: { - hello: 'hello, {name}' - } - } + app = new H3({ + plugins: [ + i18n({ + locale: localeDetector, + messages: { + en: { + hello: 'hello, {name}' + }, + ja: { + hello: 'こんにけは, {name}' + } + } + }) + ] }) - app = createApp({ ...middleware }) - request = supertest(toNodeListener(app)) - app.use( + app.get( '/', eventHandler(async event => { const t = await useTranslation(event) @@ -132,8 +145,9 @@ describe('custom locale detection', () => { } } for (const locale of ['en', 'ja']) { - const res = await request.get(`/?locale=${locale}`) - expect(res.body).toEqual(translated[locale]) + const response = await app.fetch(new Request(`http://localhost/?locale=${locale}`)) + const body = await response.json() + expect(body).toEqual(translated[locale]) } }) test('async parallel', async () => { @@ -150,7 +164,7 @@ describe('custom locale detection', () => { event: H3Event, i18n: CoreContext ) => { - const locale = getQueryLocale(event).toString() + const locale = getQueryLocale(event.req).toString() await sleep(100) const loader = messages[locale] if (loader && !i18n.messages[locale]) { @@ -160,16 +174,18 @@ describe('custom locale detection', () => { return locale } - const middleware = defineI18nMiddleware({ - locale: localeDetector, - messages: { - en: { - hello: 'hello, {name}' - } - } + app = new H3({ + plugins: [ + i18n({ + locale: localeDetector, + messages: { + en: { + hello: 'hello, {name}' + } + } + }) + ] }) - app = createApp({ ...middleware }) - request = supertest(toNodeListener(app)) app.use( '/', @@ -192,7 +208,10 @@ describe('custom locale detection', () => { // request in parallel const resList = await Promise.all( ['en', 'ja'].map(locale => - request.get(`/?locale=${locale}`).then((res: { body: string }) => res.body) + app + .fetch(new Request(`http://localhost/?locale=${locale}`)) + // @ts-ignore + .then(res => res.json()) ) ) expect(resList).toEqual([translated['en'], translated['ja']]) diff --git a/packages/h3/src/index.test-d.ts b/packages/h3/src/index.test-d.ts index 8f5d5c4..2a431ee 100644 --- a/packages/h3/src/index.test-d.ts +++ b/packages/h3/src/index.test-d.ts @@ -33,11 +33,6 @@ test('defineI18nMiddleware', () => { test('translation function', async () => { const eventMock = { - node: { - req: { - method: 'GET' - } - }, context: {} } as H3Event @@ -51,7 +46,7 @@ test('translation function', async () => { } const t = await useTranslation(eventMock) - expectTypeOf(t('test')).toMatchTypeOf() - expectTypeOf(t('foo')).toMatchTypeOf() - expectTypeOf(t('bar.buz.baz')).toMatchTypeOf() + expectTypeOf(t('test')).toExtend() + expectTypeOf(t('foo')).toExtend() + expectTypeOf(t('bar.buz.baz')).toExtend() }) diff --git a/packages/h3/src/index.test.ts b/packages/h3/src/index.test.ts index 759e531..481390d 100644 --- a/packages/h3/src/index.test.ts +++ b/packages/h3/src/index.test.ts @@ -1,5 +1,6 @@ import { createCoreContext } from '@intlify/core' import { describe, expect, test } from 'vitest' +import { SYMBOL_I18N, SYMBOL_I18N_LOCALE } from './symbols.ts' import { defineI18nMiddleware, @@ -12,19 +13,9 @@ import type { H3Event } from 'h3' test('detectLocaleFromAcceptLanguageHeader', () => { const eventMock = { - web: { - request: { - headers: { - get: _name => (_name === 'accept-language' ? 'en-US,en;q=0.9,ja;q=0.8' : '') - } - } - }, - node: { - req: { - method: 'GET', - headers: { - 'accept-language': 'en-US,en;q=0.9,ja;q=0.8' - } + req: { + headers: { + get: _name => (_name === 'accept-language' ? 'en-US,en;q=0.9,ja;q=0.8' : '') } } } as H3Event @@ -44,7 +35,7 @@ test('defineI18nMiddleware', () => { } }) expect(middleware.onRequest).toBeDefined() - expect(middleware.onAfterResponse).toBeDefined() + expect(middleware.onResponse).toBeDefined() }) describe('useTranslation', () => { @@ -64,31 +55,20 @@ describe('useTranslation', () => { } }) const eventMock = { - web: { - request: { - headers: { - get: _name => (_name === 'accept-language' ? 'ja;q=0.9,en;q=0.8' : '') - } - } - }, - node: { - req: { - method: 'GET', - headers: { - 'accept-language': 'ja,en' - } + req: { + headers: { + get: _name => (_name === 'accept-language' ? 'ja;q=0.9,en;q=0.8' : '') } }, context: { - i18n: context as CoreContext + [SYMBOL_I18N]: context as CoreContext } } as H3Event const locale = context.locale as unknown const bindLocaleDetector = (locale as LocaleDetector).bind(null, eventMock) // @ts-ignore ignore type error because this is test context.locale = bindLocaleDetector - // @ts-ignore ignore type error because this is test - eventMock.context._i18nLocale = bindLocaleDetector + eventMock.context[SYMBOL_I18N_LOCALE] = bindLocaleDetector // test `useTranslation` const t = await useTranslation(eventMock) @@ -97,12 +77,9 @@ describe('useTranslation', () => { test('not initialize context', async () => { const eventMock = { - node: { - req: { - method: 'GET', - headers: { - 'accept-language': 'ja,en' - } + req: { + headers: { + get: _name => (_name === 'accept-language' ? 'ja,en' : '') } }, context: {} diff --git a/packages/h3/src/index.ts b/packages/h3/src/index.ts index 27e538b..0bd7f67 100644 --- a/packages/h3/src/index.ts +++ b/packages/h3/src/index.ts @@ -17,7 +17,8 @@ import { parseTranslateArgs } from '@intlify/core' import { getHeaderLocale } from '@intlify/utils' -import { toWebRequest } from 'h3' +import { definePlugin, onRequest, onResponse } from 'h3' +import { SYMBOL_I18N, SYMBOL_I18N_LOCALE } from './symbols.ts' export { getCookieLocale, @@ -52,12 +53,12 @@ import type { SchemaParams, TranslateOptions } from '@intlify/core' -import type { AppOptions, H3Event } from 'h3' +import type { H3Event, Middleware } from 'h3' declare module 'h3' { interface H3EventContext { - i18n?: CoreContext - _i18nLocale?: LocaleDetector + [SYMBOL_I18N]?: CoreContext + [SYMBOL_I18N_LOCALE]?: LocaleDetector } } @@ -68,31 +69,79 @@ type DefaultLocaleMessageSchema< > = IsEmptyObject extends true ? LocaleMessage : Schema /** - * i18n middleware for h3 - * - * @description - * The middleware for h3 [`createApp`]({@link https://www.jsdocs.io/package/h3#createApp}) + * Internationalization middleware for H3 */ export interface I18nMiddleware { /** - * `onRequest` option of `createApp` + * Request middleware which is defined with [`onRequest`](https://h3.dev/utils/more#onrequesthook) */ - onRequest: NonNullable + onRequest: Middleware /** - * `onAfterResponse` option of `createApp` + * Response middleware which is defined with [`onResponse`](https://h3.dev/utils/more#onresponsehook) */ - onAfterResponse: NonNullable + onResponse: Middleware } /** - * define i18n middleware for h3 + * Internationalization plugin options for H3 + * + * @typeParam Schema - Locale message schema type, default is {@linkcode DefaultLocaleMessageSchema} + * @typeParam Locales - Locale type, default is `string` + * @typeParam Message - Message type, default is `string` + */ +export type I18nPluginOptions< + Schema = DefaultLocaleMessageSchema, + Locales = string, + Message = string +> = CoreOptions, LocaleParams> + +/** + * Internationalization plugin for H3 + * + * @example + * ```ts + * import { H3 } from 'h3' + * import { plugin as i18n } from '@intlify/h3' + * + * const app = new H3({ + * plugins: [ + * i18n({ + * messages: { + * en: { + * hello: 'Hello {name}!', + * }, + * ja: { + * hello: 'こんにけは、{name}!', + * }, + * }, + * // your locale detection logic here + * locale: (event) => { + * // ... + * }, + * }) + * ] + * }) + */ +export const plugin = definePlugin((h3, options) => { + const { onRequest, onResponse } = defineI18nMiddleware(options) + h3.use(onRequest) + h3.use(onResponse) +}) + +/** + * Define internationalization middleware for H3 + * + * Define the middleware to be specified the bellows: + * + * - [`H3.use`]({@link https://h3.dev/guide/api/h3#h3use}) * * @example * * ```js + * import { H3 } from 'h3' * import { defineI18nMiddleware } from '@intlify/h3' * - * const middleware = defineI18nMiddleware({ + * const i18nMiddleware = defineI18nMiddleware({ * messages: { * en: { * hello: 'Hello {name}!', @@ -107,15 +156,16 @@ export interface I18nMiddleware { * }, * }) * - * const app = createApp({ ...middleware }) + * const app = new H3() + * .use(i18nMiddleware.onRequest) // register `onRequest` hook before your application middlewares + * .use(i18nMiddleware.onResponse) // register `onResponse` hook before your application middlewares * ``` * - * @description - * Define the middleware to be specified for h3 [`createApp`]({@link https://www.jsdocs.io/package/h3#createApp}) + * @param options - An `i18n` options like vue-i18n [`createI18n`]({@link https://vue-i18n.intlify.dev/guide/#javascript}), which are passed to `createCoreContext` of `@intlify/core`, see about details [`CoreOptions` of `@intlify/core`](https://github.com/intlify/vue-i18n-next/blob/6a9947dd3e0fe90de7be9c87ea876b8779998de5/packages/core-base/src/context.ts#L196-L216) * - * @param options - An i18n options like vue-i18n [`createI18n`]({@link https://vue-i18n.intlify.dev/guide/#javascript}), which are passed to `createCoreContext` of `@intlify/core`, see about details [`CoreOptions` of `@intlify/core`](https://github.com/intlify/vue-i18n-next/blob/6a9947dd3e0fe90de7be9c87ea876b8779998de5/packages/core-base/src/context.ts#L196-L216) + * @returns A defined internationalization middleware, which is included `onRequest` and `onResponse` options of `H3` * - * @returns A defined i18n middleware, which is included `onRequest` and `onAfterResponse` options of `createApp` + * @internal */ export function defineI18nMiddleware< Schema = DefaultLocaleMessageSchema, @@ -133,7 +183,7 @@ export function defineI18nMiddleware< let staticLocaleDetector: LocaleDetector | null = null if (typeof orgLocale === 'string') { console.warn( - `defineI18nMiddleware 'locale' option is static ${orgLocale} locale! you should specify dynamic locale detector function.` + `'locale' option is static ${orgLocale} locale! you should specify dynamic locale detector function.` ) staticLocaleDetector = () => orgLocale } @@ -147,27 +197,28 @@ export function defineI18nMiddleware< } return { - onRequest(event: H3Event) { - event.context._i18nLocale = getLocaleDetector(event, i18n as CoreContext) - i18n.locale = event.context._i18nLocale - event.context.i18n = i18n as CoreContext - }, - onAfterResponse(event: H3Event) { + onRequest: onRequest(event => { + event.context[SYMBOL_I18N_LOCALE] = getLocaleDetector(event, i18n as CoreContext) + i18n.locale = event.context[SYMBOL_I18N_LOCALE] + event.context[SYMBOL_I18N] = i18n as CoreContext + }), + onResponse: onResponse((_, event) => { i18n.locale = orgLocale - delete event.context.i18n - } + delete event.context[SYMBOL_I18N] + delete event.context[SYMBOL_I18N_LOCALE] + }) } } /** - * locale detection with `Accept-Language` header + * Locale detection with `Accept-Language` header * * @example * ```js - * import { createApp } from 'h3' - * import { defineI18nMiddleware, detectLocaleWithAcceeptLanguageHeader } from '@intlify/h3' + * import { H3 } from 'h3' + * import { defineI18nMiddleware, detectLocaleFromAcceptLanguageHeader } from '@intlify/h3' * - * const middleware = defineI18nMiddleware({ + * const i18nMiddleware = defineI18nMiddleware({ * messages: { * en: { * hello: 'Hello {name}!', @@ -176,18 +227,20 @@ export function defineI18nMiddleware< * hello: 'こんにけは、{name}!', * }, * }, - * locale: detectLocaleWithAcceeptLanguageHeader + * locale: detectLocaleFromAcceptLanguageHeader * }) * - * const app = createApp({ ...middleware }) + * const app = new H3() + * .use(i18nMiddleware.onRequest) + * .use(i18nMiddleware.onResponse) * ``` * - * @param event - A h3 event + * @param event - A H3 event * * @returns A locale string, which will be detected of **first** from `Accept-Language` header */ export const detectLocaleFromAcceptLanguageHeader = (event: H3Event): Locale => - getHeaderLocale(toWebRequest(event)).toString() + getHeaderLocale(event.req).toString() /** * The type definition of Locale Message for `@intlify/h3` package @@ -206,9 +259,6 @@ export const detectLocaleFromAcceptLanguageHeader = (event: H3Event): Locale => * } * } * ``` - * - * @description - * The typealias is used to strictly define the type of the Locale message. */ export interface DefineLocaleMessage extends LocaleMessage {} @@ -331,52 +381,45 @@ interface TranslationFunction< } /** - * use translation function in event handler + * Use translation function in event handler * * @example * ```js - * import { createRouter } from 'h3' - * - * const router = createRouter() - * router.get( + * app.get( * '/', * eventHandler(async (event) => { * const t = await useTranslation(event) - * return t('hello', { name: 'h3' }) + * return t('hello', { name: 'H3' }) * }), * ) * ``` * - * @description - * This function must be initialized with defineI18nMiddleware. See about the {@link defineI18nMiddleware} + * @param event - A H3 event * - * @param event - A h3 event - * - * @returns Return a translation function, which can be translated with i18n resource messages + * @returns Return a translation function, which can be translated with internationalization resource messages */ export async function useTranslation< Schema extends Record = {}, // eslint-disable-line @typescript-eslint/no-explicit-any -- NOTE(kazupon): generic type Event extends H3Event = H3Event >(event: Event): Promise> { - if (event.context.i18n == null) { + if (event.context[SYMBOL_I18N] == null) { throw new Error( - 'middleware not initialized, please setup `onRequest` and `onAfterResponse` options of `createApp` with the middleware obtained with `defineI18nMiddleware`' + 'middleware not initialized, please setup `onRequest` and `onResponse` options of `H3` with the middleware obtained with `defineI18nMiddleware`' ) } - const localeDetector = event.context._i18nLocale as unknown as LocaleDetector - let locale: string - if (localeDetector.constructor.name === 'AsyncFunction') { - locale = await localeDetector(event) - event.context.i18n.locale = locale - } + const localeDetector = event.context[SYMBOL_I18N_LOCALE] as unknown as LocaleDetector + // Always await detector call - works for both sync and async detectors + // (awaiting a non-promise value returns it immediately) + const locale = await localeDetector(event) + event.context[SYMBOL_I18N].locale = locale function translate(key: string, ...args: unknown[]): string { const [_, options] = parseTranslateArgs(key, ...args) const [arg2] = args const result = Reflect.apply(_translate, null, [ - event.context.i18n!, + event.context[SYMBOL_I18N]!, key, arg2, { diff --git a/packages/h3/src/symbols.ts b/packages/h3/src/symbols.ts new file mode 100644 index 0000000..8ee4ea9 --- /dev/null +++ b/packages/h3/src/symbols.ts @@ -0,0 +1,11 @@ +/** + * defined symbols + */ + +/** + * @author kazuya kawaguchi (a.k.a. kazupon) + * @license MIT + */ + +export const SYMBOL_I18N = Symbol('__INTLIFY_H3_I18N__') +export const SYMBOL_I18N_LOCALE = Symbol('__INTLIFY_H3_I18N_LOCALE__') diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ff0d909..81e8c2f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,7 +40,7 @@ importers: version: 7.5.1 '@kazupon/eslint-config': specifier: ^0.37.2 - version: 0.37.2(9fb9aa33925b3b1b8114a6d4e3a9e8c6) + version: 0.37.2(ddc9953ef2070f6f9d2fd84915400355) '@kazupon/prettier-config': specifier: ^0.1.1 version: 0.1.1 @@ -52,10 +52,10 @@ importers: version: 7.0.0-dev.20251108.1 '@vitest/coverage-v8': specifier: 4.0.8 - version: 4.0.8(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1)) + version: 4.0.8(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(tsx@4.20.6)(yaml@2.8.1)) '@vitest/eslint-plugin': specifier: ^1.4.2 - version: 1.4.2(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1)) + version: 1.4.2(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(tsx@4.20.6)(yaml@2.8.1)) bumpp: specifier: ^10.3.1 version: 10.3.1(magicast@0.5.1) @@ -118,10 +118,10 @@ importers: version: 8.46.4(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) vitest: specifier: ^4.0.0 - version: 4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1) + version: 4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(tsx@4.20.6)(yaml@2.8.1) vitest-environment-miniflare: specifier: ^2.14.1 - version: 2.14.4(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1)) + version: 2.14.4(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(tsx@4.20.6)(yaml@2.8.1)) packages/h3: dependencies: @@ -135,18 +135,15 @@ importers: '@types/node': specifier: 'catalog:' version: 24.10.1 - '@types/supertest': - specifier: ^6.0.3 - version: 6.0.3 h3: - specifier: ^1.15.4 - version: 1.15.4 + specifier: ^2.0.1-rc.5 + version: 2.0.1-rc.5 publint: specifier: 'catalog:' version: 0.3.15 - supertest: - specifier: ^7.1.4 - version: 7.1.4 + srvx: + specifier: ^0.9.6 + version: 0.9.6 tsdown: specifier: 'catalog:' version: 0.16.4(@typescript/native-preview@7.0.0-dev.20251108.1)(ms@2.1.3)(oxc-resolver@11.13.2)(publint@0.3.15)(synckit@0.11.11)(typescript@5.9.3) @@ -809,6 +806,41 @@ packages: cpu: [x64] os: [win32] + '@inquirer/ansi@1.0.2': + resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} + engines: {node: '>=18'} + + '@inquirer/confirm@5.1.21': + resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/core@10.3.2': + resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} + engines: {node: '>=18'} + + '@inquirer/type@3.0.10': + resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + '@intlify/core-base@11.1.12': resolution: {integrity: sha512-whh0trqRsSqVLNEUCwU59pyJZYpU8AmSWl8M3Jz2Mv5ESPP6kFh4juas2NpZ1iCvy7GlNRffUD1xr84gceimjg==} engines: {node: '>= 16'} @@ -1041,16 +1073,16 @@ packages: engines: {node: '>=16.13'} deprecated: Miniflare v2 is no longer supported. Please upgrade to Miniflare v4 + '@mswjs/interceptors@0.40.0': + resolution: {integrity: sha512-EFd6cVbHsgLa6wa4RljGj6Wk75qoHxUSyc5asLyyPSyuhIcdS2Q3Phw6ImS1q+CkALthJRShiYfKANcQMuMqsQ==} + engines: {node: '>=18'} + '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} '@napi-rs/wasm-runtime@1.0.7': resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} - '@noble/hashes@1.8.0': - resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} - engines: {node: ^14.21.3 || >=16} - '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1063,6 +1095,15 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@open-draft/deferred-promise@2.2.0': + resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} + + '@open-draft/logger@0.3.0': + resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} + + '@open-draft/until@2.1.0': + resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} + '@oxc-project/runtime@0.97.0': resolution: {integrity: sha512-yH0zw7z+jEws4dZ4IUKoix5Lh3yhqIJWF9Dc8PWvhpo7U7O+lJrv7ZZL4BeRO0la8LBQFwcCewtLBnVV7hPe/w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1176,9 +1217,6 @@ packages: cpu: [x64] os: [win32] - '@paralleldrive/cuid2@2.3.1': - resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==} - '@pkgr/core@0.2.9': resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} @@ -1531,9 +1569,6 @@ packages: '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} - '@types/cookiejar@2.1.5': - resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} - '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -1558,9 +1593,6 @@ packages: '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - '@types/methods@1.1.4': - resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} - '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} @@ -1570,11 +1602,8 @@ packages: '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - '@types/superagent@8.1.9': - resolution: {integrity: sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==} - - '@types/supertest@6.0.3': - resolution: {integrity: sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==} + '@types/statuses@2.0.6': + resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==} '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -1857,6 +1886,10 @@ packages: resolution: {integrity: sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==} engines: {node: '>=18'} + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + ansi-regex@6.2.2: resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} @@ -1910,9 +1943,6 @@ packages: as-table@1.0.55: resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} - asap@2.0.6: - resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -1928,9 +1958,6 @@ packages: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -2047,6 +2074,14 @@ packages: resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==} engines: {node: '>=20'} + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -2064,10 +2099,6 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - commander@14.0.2: resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} engines: {node: '>=20'} @@ -2080,9 +2111,6 @@ packages: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} - component-emitter@1.3.1: - resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} - concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -2093,15 +2121,13 @@ packages: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} - cookie-es@1.2.2: - resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==} - cookie@0.7.2: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} - cookiejar@2.1.4: - resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} + cookie@1.0.2: + resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + engines: {node: '>=18'} core-js-compat@3.46.0: resolution: {integrity: sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==} @@ -2110,9 +2136,6 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - crossws@0.3.5: - resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} - data-uri-to-buffer@2.0.2: resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} @@ -2162,10 +2185,6 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -2180,9 +2199,6 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} - dezalgo@1.0.4: - resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} - diff-sequences@27.5.1: resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -2230,6 +2246,9 @@ packages: emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + empathic@2.0.0: resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} engines: {node: '>=14'} @@ -2531,9 +2550,6 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-safe-stringify@2.1.1: - resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} @@ -2579,10 +2595,6 @@ packages: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} - form-data@4.0.4: - resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} - engines: {node: '>= 6'} - format@0.2.2: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} @@ -2592,10 +2604,6 @@ packages: engines: {node: '>=18.3.0'} hasBin: true - formidable@3.5.4: - resolution: {integrity: sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==} - engines: {node: '>=14.0.0'} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -2615,6 +2623,10 @@ packages: resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} engines: {node: '>= 0.4'} + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.4.0: resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} engines: {node: '>=18'} @@ -2681,8 +2693,18 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - h3@1.15.4: - resolution: {integrity: sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==} + graphql@16.12.0: + resolution: {integrity: sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + + h3@2.0.1-rc.5: + resolution: {integrity: sha512-qkohAzCab0nLzXNm78tBjZDvtKMTmtygS8BJLT3VPczAQofdqlFXDPkXdLMJN4r05+xqneG8snZJ0HgkERCZTg==} + engines: {node: '>=20.11.1'} + peerDependencies: + crossws: ^0.4.1 + peerDependenciesMeta: + crossws: + optional: true has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} @@ -2711,6 +2733,9 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + headers-polyfill@4.0.3: + resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==} + hono@3.12.12: resolution: {integrity: sha512-5IAMJOXfpA5nT+K0MNjClchzz0IhBHs2Szl7WFAhrFOsbtQsYmNynFyJRg/a3IPsmCfxcrf8txUGiNShXpK5Rg==} engines: {node: '>=16.0.0'} @@ -2766,9 +2791,6 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - iron-webcrypto@1.2.1: - resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} - is-array-buffer@3.0.5: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} @@ -2819,6 +2841,10 @@ packages: resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} engines: {node: '>= 0.4'} + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + is-fullwidth-code-point@5.1.0: resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} engines: {node: '>=18'} @@ -2839,6 +2865,9 @@ packages: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} + is-node-process@1.2.0: + resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} + is-number-object@1.1.1: resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} @@ -3093,10 +3122,6 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} @@ -3191,19 +3216,6 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - - mime@2.6.0: - resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} - engines: {node: '>=4.0.0'} - hasBin: true - mime@3.0.0: resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} engines: {node: '>=10.0.0'} @@ -3239,10 +3251,24 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + msw@2.12.1: + resolution: {integrity: sha512-arzsi9IZjjByiEw21gSUP82qHM8zkV69nNpWV6W4z72KiLvsDWoOp678ORV6cNfU/JGhlX0SsnD4oXo9gI6I2A==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + typescript: '>= 4.8.x' + peerDependenciesMeta: + typescript: + optional: true + mustache@4.2.0: resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} hasBin: true + mute-stream@2.0.0: + resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} + engines: {node: ^18.17.0 || >=20.5.0} + nano-spawn@2.0.0: resolution: {integrity: sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==} engines: {node: '>=20.17'} @@ -3263,9 +3289,6 @@ packages: node-fetch-native@1.6.7: resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} - node-mock-http@1.0.3: - resolution: {integrity: sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog==} - node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} @@ -3323,9 +3346,6 @@ packages: ohash@2.0.11: resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - onetime@6.0.0: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} @@ -3338,6 +3358,9 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} + outvariant@1.4.3: + resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} + own-keys@1.0.1: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} @@ -3453,19 +3476,12 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - qs@6.14.0: - resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} - engines: {node: '>=0.6'} - quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - radix3@1.1.2: - resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} - rc9@2.1.2: resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} @@ -3505,6 +3521,10 @@ packages: resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} hasBin: true + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + reserved-identifiers@1.2.0: resolution: {integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==} engines: {node: '>=18'} @@ -3525,6 +3545,9 @@ packages: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} + rettime@0.7.0: + resolution: {integrity: sha512-LPRKoHnLKd/r3dVxcwO7vhCW+orkOGj9ViueosEBK6ie89CijnfRlhaDhHq/3Hxu4CkWQtxwlBG0mzTQY6uQjw==} + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -3576,6 +3599,9 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rou3@0.7.10: + resolution: {integrity: sha512-aoFj6f7MJZ5muJ+Of79nrhs9N3oLGqi2VEMe94Zbkjb6Wupha46EuoYgpWSOZlXww3bbd8ojgXTAA2mzimX5Ww==} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -3699,6 +3725,11 @@ packages: spdx-license-ids@3.0.22: resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} + srvx@0.9.6: + resolution: {integrity: sha512-5L4rT6qQqqb+xcoDoklUgCNdmzqJ6vbcDRwPVGRXewF55IJH0pqh0lQlrJ266ZWTKJ4mfeioqHQJeAYesS+RrQ==} + engines: {node: '>=20.16.0'} + hasBin: true + stable-hash-x@0.2.0: resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==} engines: {node: '>=12.0.0'} @@ -3709,6 +3740,10 @@ packages: stacktracey@2.1.8: resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} @@ -3724,10 +3759,17 @@ packages: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} + strict-event-emitter@0.5.1: + resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + string-width@7.2.0: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} @@ -3748,6 +3790,10 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + strip-ansi@7.1.2: resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} engines: {node: '>=12'} @@ -3772,14 +3818,6 @@ packages: resolution: {integrity: sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g==} engines: {node: '>=14.16'} - superagent@10.2.3: - resolution: {integrity: sha512-y/hkYGeXAj7wUMjxRbB21g/l6aAEituGXM9Rwl4o20+SX3e8YOSV6BxFXl+dL3Uk0mjSL3kCbNkwURm8/gEDig==} - engines: {node: '>=14.18.0'} - - supertest@7.1.4: - resolution: {integrity: sha512-tjLPs7dVyqgItVFirHYqe2T+MfWc2VOBQ8QFKKbWTA3PU7liZR8zoSpAi/C1k1ilm9RsXIKYf197oap9wXGVYg==} - engines: {node: '>=14.18.0'} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -3814,6 +3852,13 @@ packages: resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} engines: {node: '>=14.0.0'} + tldts-core@7.0.17: + resolution: {integrity: sha512-DieYoGrP78PWKsrXr8MZwtQ7GLCUeLxihtjC1jZsW1DnvSMdKPitJSe8OSYDM2u5H6g3kWJZpePqkp43TfLh0g==} + + tldts@7.0.17: + resolution: {integrity: sha512-Y1KQBgDd/NUc+LfOtKS6mNsC9CCaH+m2P1RoIZy7RAPo3C3/t8X45+zgut31cRZtZ3xKPjfn3TkGTrctC2TQIQ==} + hasBin: true + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -3822,6 +3867,10 @@ packages: resolution: {integrity: sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw==} engines: {node: '>=20'} + tough-cookie@6.0.0: + resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==} + engines: {node: '>=16'} + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -3958,9 +4007,6 @@ packages: unconfig@7.4.1: resolution: {integrity: sha512-uyQ7LElcGizrOGZyIq9KU+xkuEjcRf9IpmDTkCSYv5mEeZzrXSj6rb51C0L+WTedsmAoVxW9WKrLWhSwebIM9Q==} - uncrypto@0.1.3: - resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} - undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} @@ -4007,6 +4053,9 @@ packages: synckit: optional: true + until-async@3.0.2: + resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==} + update-browserslist-db@1.1.4: resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} hasBin: true @@ -4156,13 +4205,18 @@ packages: '@cloudflare/workers-types': optional: true + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + wrap-ansi@9.0.2: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.18.0: resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} engines: {node: '>=10.0.0'} @@ -4187,6 +4241,10 @@ packages: utf-8-validate: optional: true + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + yaml-eslint-parser@1.3.0: resolution: {integrity: sha512-E/+VitOorXSLiAqtTd7Yqax0/pAS3xaYMP+AUUJGOK1OZG3rhcj9fcJOM5HJ2VrP1FrStVCWr1muTfQCdj4tAA==} engines: {node: ^14.17.0 || >=16.0.0} @@ -4196,10 +4254,22 @@ packages: engines: {node: '>= 14.6'} hasBin: true + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + yoctocolors-cjs@2.1.3: + resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} + engines: {node: '>=18'} + youch@3.3.4: resolution: {integrity: sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==} @@ -4645,6 +4715,39 @@ snapshots: '@img/sharp-win32-x64@0.33.5': optional: true + '@inquirer/ansi@1.0.2': + optional: true + + '@inquirer/confirm@5.1.21(@types/node@24.10.1)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@24.10.1) + '@inquirer/type': 3.0.10(@types/node@24.10.1) + optionalDependencies: + '@types/node': 24.10.1 + optional: true + + '@inquirer/core@10.3.2(@types/node@24.10.1)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@24.10.1) + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 24.10.1 + optional: true + + '@inquirer/figures@1.0.15': + optional: true + + '@inquirer/type@3.0.10(@types/node@24.10.1)': + optionalDependencies: + '@types/node': 24.10.1 + optional: true + '@intlify/core-base@11.1.12': dependencies: '@intlify/message-compiler': 11.1.12 @@ -4683,7 +4786,7 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@kazupon/eslint-config@0.37.2(9fb9aa33925b3b1b8114a6d4e3a9e8c6)': + '@kazupon/eslint-config@0.37.2(ddc9953ef2070f6f9d2fd84915400355)': dependencies: '@eslint-community/eslint-plugin-eslint-comments': 4.5.0(eslint@9.39.1(jiti@2.6.1)) '@eslint/js': 9.39.1 @@ -4696,7 +4799,7 @@ snapshots: globals: 16.5.0 optionalDependencies: '@eslint/markdown': 7.5.1 - '@vitest/eslint-plugin': 1.4.2(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1)) + '@vitest/eslint-plugin': 1.4.2(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(tsx@4.20.6)(yaml@2.8.1)) eslint-config-prettier: 10.1.8(eslint@9.39.1(jiti@2.6.1)) eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.4(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.39.1(jiti@2.6.1)) @@ -4862,6 +4965,16 @@ snapshots: - bufferutil - utf-8-validate + '@mswjs/interceptors@0.40.0': + dependencies: + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/logger': 0.3.0 + '@open-draft/until': 2.1.0 + is-node-process: 1.2.0 + outvariant: 1.4.3 + strict-event-emitter: 0.5.1 + optional: true + '@napi-rs/wasm-runtime@0.2.12': dependencies: '@emnapi/core': 1.7.0 @@ -4876,8 +4989,6 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@noble/hashes@1.8.0': {} - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -4890,6 +5001,18 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 + '@open-draft/deferred-promise@2.2.0': + optional: true + + '@open-draft/logger@0.3.0': + dependencies: + is-node-process: 1.2.0 + outvariant: 1.4.3 + optional: true + + '@open-draft/until@2.1.0': + optional: true + '@oxc-project/runtime@0.97.0': {} '@oxc-project/types@0.95.0': {} @@ -4955,10 +5078,6 @@ snapshots: '@oxc-resolver/binding-win32-x64-msvc@11.13.2': optional: true - '@paralleldrive/cuid2@2.3.1': - dependencies: - '@noble/hashes': 1.8.0 - '@pkgr/core@0.2.9': {} '@publint/pack@0.1.2': {} @@ -5177,8 +5296,6 @@ snapshots: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 - '@types/cookiejar@2.1.5': {} - '@types/debug@4.1.12': dependencies: '@types/ms': 2.1.0 @@ -5201,8 +5318,6 @@ snapshots: dependencies: '@types/unist': 3.0.3 - '@types/methods@1.1.4': {} - '@types/ms@2.1.0': {} '@types/node@24.10.1': @@ -5211,17 +5326,8 @@ snapshots: '@types/normalize-package-data@2.4.4': {} - '@types/superagent@8.1.9': - dependencies: - '@types/cookiejar': 2.1.5 - '@types/methods': 1.1.4 - '@types/node': 24.10.1 - form-data: 4.0.4 - - '@types/supertest@6.0.3': - dependencies: - '@types/methods': 1.1.4 - '@types/superagent': 8.1.9 + '@types/statuses@2.0.6': + optional: true '@types/unist@3.0.3': {} @@ -5408,7 +5514,7 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - '@vitest/coverage-v8@4.0.8(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1))': + '@vitest/coverage-v8@4.0.8(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.0.8 @@ -5421,18 +5527,18 @@ snapshots: magicast: 0.5.1 std-env: 3.10.0 tinyrainbow: 3.0.3 - vitest: 4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1) + vitest: 4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - supports-color - '@vitest/eslint-plugin@1.4.2(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1))': + '@vitest/eslint-plugin@1.4.2(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@typescript-eslint/scope-manager': 8.46.4 '@typescript-eslint/utils': 8.46.4(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) eslint: 9.39.1(jiti@2.6.1) optionalDependencies: typescript: 5.9.3 - vitest: 4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1) + vitest: 4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -5445,12 +5551,13 @@ snapshots: chai: 6.2.1 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.8(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1))': + '@vitest/mocker@4.0.8(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@vitest/spy': 4.0.8 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: + msw: 2.12.1(@types/node@24.10.1)(typescript@5.9.3) vite: 7.2.2(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1) '@vitest/pretty-format@4.0.8': @@ -5496,6 +5603,9 @@ snapshots: dependencies: environment: 1.1.0 + ansi-regex@5.0.1: + optional: true + ansi-regex@6.2.2: {} ansi-styles@4.3.0: @@ -5566,8 +5676,6 @@ snapshots: dependencies: printable-characters: 1.0.42 - asap@2.0.6: {} - assertion-error@2.0.1: {} ast-kit@2.2.0: @@ -5583,8 +5691,6 @@ snapshots: async-function@1.0.0: {} - asynckit@0.4.0: {} - available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -5718,6 +5824,16 @@ snapshots: slice-ansi: 7.1.2 string-width: 8.1.0 + cli-width@4.1.0: + optional: true + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + optional: true + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -5738,29 +5854,22 @@ snapshots: colorette@2.0.20: {} - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 - commander@14.0.2: {} commander@8.3.0: {} comment-parser@1.4.1: {} - component-emitter@1.3.1: {} - concat-map@0.0.1: {} confbox@0.2.2: {} consola@3.4.2: {} - cookie-es@1.2.2: {} - cookie@0.7.2: {} - cookiejar@2.1.4: {} + cookie@1.0.2: + optional: true core-js-compat@3.46.0: dependencies: @@ -5772,10 +5881,6 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - crossws@0.3.5: - dependencies: - uncrypto: 0.1.3 - data-uri-to-buffer@2.0.2: {} data-view-buffer@1.0.2: @@ -5824,8 +5929,6 @@ snapshots: defu@6.1.4: {} - delayed-stream@1.0.0: {} - dequal@2.0.3: {} destr@2.0.5: {} @@ -5837,11 +5940,6 @@ snapshots: dependencies: dequal: 2.0.3 - dezalgo@1.0.4: - dependencies: - asap: 2.0.6 - wrappy: 1.0.2 - diff-sequences@27.5.1: {} diff-sequences@29.6.3: {} @@ -5872,6 +5970,9 @@ snapshots: emoji-regex@10.6.0: {} + emoji-regex@8.0.0: + optional: true + empathic@2.0.0: {} enhanced-resolve@5.18.3: @@ -6353,8 +6454,6 @@ snapshots: fast-levenshtein@2.0.6: {} - fast-safe-stringify@2.1.1: {} - fastq@1.19.1: dependencies: reusify: 1.1.0 @@ -6397,26 +6496,12 @@ snapshots: dependencies: is-callable: 1.2.7 - form-data@4.0.4: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - es-set-tostringtag: 2.1.0 - hasown: 2.0.2 - mime-types: 2.1.35 - format@0.2.2: {} formatly@0.3.0: dependencies: fd-package-json: 2.0.0 - formidable@3.5.4: - dependencies: - '@paralleldrive/cuid2': 2.3.1 - dezalgo: 1.0.4 - once: 1.4.0 - fsevents@2.3.3: optional: true @@ -6435,6 +6520,9 @@ snapshots: generator-function@2.0.1: {} + get-caller-file@2.0.5: + optional: true + get-east-asian-width@1.4.0: {} get-intrinsic@1.3.0: @@ -6508,17 +6596,13 @@ snapshots: graphemer@1.4.0: {} - h3@1.15.4: + graphql@16.12.0: + optional: true + + h3@2.0.1-rc.5: dependencies: - cookie-es: 1.2.2 - crossws: 0.3.5 - defu: 6.1.4 - destr: 2.0.5 - iron-webcrypto: 1.2.1 - node-mock-http: 1.0.3 - radix3: 1.1.2 - ufo: 1.6.1 - uncrypto: 0.1.3 + rou3: 0.7.10 + srvx: 0.9.6 has-bigints@1.1.0: {} @@ -6542,6 +6626,9 @@ snapshots: dependencies: function-bind: 1.1.2 + headers-polyfill@4.0.3: + optional: true + hono@3.12.12: {} hookable@5.5.3: {} @@ -6581,8 +6668,6 @@ snapshots: hasown: 2.0.2 side-channel: 1.1.0 - iron-webcrypto@1.2.1: {} - is-array-buffer@3.0.5: dependencies: call-bind: 1.0.8 @@ -6640,6 +6725,9 @@ snapshots: dependencies: call-bound: 1.0.4 + is-fullwidth-code-point@3.0.0: + optional: true + is-fullwidth-code-point@5.1.0: dependencies: get-east-asian-width: 1.4.0 @@ -6660,6 +6748,9 @@ snapshots: is-negative-zero@2.0.3: {} + is-node-process@1.2.0: + optional: true + is-number-object@1.1.1: dependencies: call-bound: 1.0.4 @@ -7009,8 +7100,6 @@ snapshots: merge2@1.4.1: {} - methods@1.1.2: {} - micromark-core-commonmark@2.0.3: dependencies: decode-named-character-reference: 1.2.0 @@ -7224,14 +7313,6 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - - mime@2.6.0: {} - mime@3.0.0: {} mimic-fn@4.0.0: {} @@ -7269,8 +7350,37 @@ snapshots: ms@2.1.3: {} + msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3): + dependencies: + '@inquirer/confirm': 5.1.21(@types/node@24.10.1) + '@mswjs/interceptors': 0.40.0 + '@open-draft/deferred-promise': 2.2.0 + '@types/statuses': 2.0.6 + cookie: 1.0.2 + graphql: 16.12.0 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 + picocolors: 1.1.1 + rettime: 0.7.0 + statuses: 2.0.2 + strict-event-emitter: 0.5.1 + tough-cookie: 6.0.0 + type-fest: 4.41.0 + until-async: 3.0.2 + yargs: 17.7.2 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@types/node' + optional: true + mustache@4.2.0: {} + mute-stream@2.0.0: + optional: true + nano-spawn@2.0.0: {} nanoid@3.3.11: {} @@ -7281,8 +7391,6 @@ snapshots: node-fetch-native@1.6.7: {} - node-mock-http@1.0.3: {} - node-releases@2.0.27: {} normalize-package-data@6.0.2: @@ -7351,10 +7459,6 @@ snapshots: ohash@2.0.11: {} - once@1.4.0: - dependencies: - wrappy: 1.0.2 - onetime@6.0.0: dependencies: mimic-fn: 4.0.0 @@ -7372,6 +7476,9 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 + outvariant@1.4.3: + optional: true + own-keys@1.0.1: dependencies: get-intrinsic: 1.3.0 @@ -7483,16 +7590,10 @@ snapshots: punycode@2.3.1: {} - qs@6.14.0: - dependencies: - side-channel: 1.1.0 - quansync@0.2.11: {} queue-microtask@1.2.3: {} - radix3@1.1.2: {} - rc9@2.1.2: dependencies: defu: 6.1.4 @@ -7549,6 +7650,9 @@ snapshots: dependencies: jsesc: 3.0.2 + require-directory@2.1.1: + optional: true + reserved-identifiers@1.2.0: {} resolve-from@4.0.0: {} @@ -7566,6 +7670,9 @@ snapshots: onetime: 7.0.0 signal-exit: 4.1.0 + rettime@0.7.0: + optional: true + reusify@1.1.0: {} rfdc@1.4.1: {} @@ -7690,6 +7797,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.53.2 fsevents: 2.3.3 + rou3@0.7.10: {} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -7855,6 +7964,8 @@ snapshots: spdx-license-ids@3.0.22: {} + srvx@0.9.6: {} + stable-hash-x@0.2.0: {} stackback@0.0.2: {} @@ -7864,6 +7975,9 @@ snapshots: as-table: 1.0.55 get-source: 2.0.12 + statuses@2.0.2: + optional: true + std-env@3.10.0: {} stop-iteration-iterator@1.1.0: @@ -7875,8 +7989,18 @@ snapshots: streamsearch@1.1.0: {} + strict-event-emitter@0.5.1: + optional: true + string-argv@0.3.2: {} + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + optional: true + string-width@7.2.0: dependencies: emoji-regex: 10.6.0 @@ -7911,6 +8035,11 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + optional: true + strip-ansi@7.1.2: dependencies: ansi-regex: 6.2.2 @@ -7925,27 +8054,6 @@ snapshots: strip-json-comments@5.0.2: {} - superagent@10.2.3: - dependencies: - component-emitter: 1.3.1 - cookiejar: 2.1.4 - debug: 4.4.3 - fast-safe-stringify: 2.1.1 - form-data: 4.0.4 - formidable: 3.5.4 - methods: 1.1.2 - mime: 2.6.0 - qs: 6.14.0 - transitivePeerDependencies: - - supports-color - - supertest@7.1.4: - dependencies: - methods: 1.1.2 - superagent: 10.2.3 - transitivePeerDependencies: - - supports-color - supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -7971,6 +8079,14 @@ snapshots: tinyrainbow@3.0.3: {} + tldts-core@7.0.17: + optional: true + + tldts@7.0.17: + dependencies: + tldts-core: 7.0.17 + optional: true + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -7980,6 +8096,11 @@ snapshots: '@sindresorhus/base62': 1.0.0 reserved-identifiers: 1.2.0 + tough-cookie@6.0.0: + dependencies: + tldts: 7.0.17 + optional: true + tree-kill@1.2.2: {} ts-api-utils@2.1.0(typescript@5.9.3): @@ -8149,8 +8270,6 @@ snapshots: quansync: 0.2.11 unconfig-core: 7.4.1 - uncrypto@0.1.3: {} - undici-types@7.16.0: {} undici@5.28.4: @@ -8226,6 +8345,9 @@ snapshots: optionalDependencies: synckit: 0.11.11 + until-async@3.0.2: + optional: true + update-browserslist-db@1.1.4(browserslist@4.28.0): dependencies: browserslist: 4.28.0 @@ -8262,22 +8384,22 @@ snapshots: tsx: 4.20.6 yaml: 2.8.1 - vitest-environment-miniflare@2.14.4(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1)): + vitest-environment-miniflare@2.14.4(vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(tsx@4.20.6)(yaml@2.8.1)): dependencies: '@miniflare/queues': 2.14.4 '@miniflare/runner-vm': 2.14.4 '@miniflare/shared': 2.14.4 '@miniflare/shared-test-environment': 2.14.4 undici: 5.28.4 - vitest: 4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1) + vitest: 4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: - bufferutil - utf-8-validate - vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1): + vitest@4.0.8(@types/debug@4.1.12)(@types/node@24.10.1)(jiti@2.6.1)(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(tsx@4.20.6)(yaml@2.8.1): dependencies: '@vitest/expect': 4.0.8 - '@vitest/mocker': 4.0.8(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1)) + '@vitest/mocker': 4.0.8(msw@2.12.1(@types/node@24.10.1)(typescript@5.9.3))(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.20.6)(yaml@2.8.1)) '@vitest/pretty-format': 4.0.8 '@vitest/runner': 4.0.8 '@vitest/snapshot': 4.0.8 @@ -8395,18 +8517,33 @@ snapshots: - bufferutil - utf-8-validate + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + optional: true + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + optional: true + wrap-ansi@9.0.2: dependencies: ansi-styles: 6.2.3 string-width: 7.2.0 strip-ansi: 7.1.2 - wrappy@1.0.2: {} - ws@8.18.0: {} ws@8.18.3: {} + y18n@5.0.8: + optional: true + yaml-eslint-parser@1.3.0: dependencies: eslint-visitor-keys: 3.4.3 @@ -8414,8 +8551,25 @@ snapshots: yaml@2.8.1: {} + yargs-parser@21.1.1: + optional: true + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + optional: true + yocto-queue@0.1.0: {} + yoctocolors-cjs@2.1.3: + optional: true + youch@3.3.4: dependencies: cookie: 0.7.2 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 29e4c0d..d162d9c 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,13 +2,13 @@ packages: - packages/* catalog: + '@intlify/utils': ^1.0.1 '@types/node': ^24.10.0 + publint: ^0.3.15 + tsdown: ^0.16.4 typedoc: ^0.28.14 typedoc-plugin-markdown: ^4.9.0 typescript: ^5.9.3 - tsdown: ^0.16.4 - publint: ^0.3.15 - '@intlify/utils': ^1.0.1 minimumReleaseAge: 1440 @@ -18,6 +18,7 @@ minimumReleaseAgeExclude: onlyBuiltDependencies: - deno - esbuild + - msw - sharp - unrs-resolver - workerd