diff --git a/.chronus/changes/http-server-javascript-2024-6-5-12-35-40.md b/.chronus/changes/http-server-javascript-2024-6-5-12-35-40.md new file mode 100644 index 0000000000..e95ee443b8 --- /dev/null +++ b/.chronus/changes/http-server-javascript-2024-6-5-12-35-40.md @@ -0,0 +1,7 @@ +--- +changeKind: internal +packages: + - "@typespec/http-server-javascript" +--- + +Added the experimental HTTP server generator for JavaScript. diff --git a/cspell.yaml b/cspell.yaml index 23349c1b5a..acb9c4b911 100644 --- a/cspell.yaml +++ b/cspell.yaml @@ -12,6 +12,7 @@ words: - azsdkengsys - azurecr - azuresdk + - bifilter - blockful - blockless - cadl @@ -28,6 +29,7 @@ words: - CRUDL - dbaeumer - debouncer + - destructures - devdiv - Diagnoser - dogfood @@ -84,6 +86,7 @@ words: - protoc - psscriptanalyzer - pwsh + - recase - regen - respecify - rpaas @@ -109,11 +112,14 @@ words: - uitestresults - unassignable - Uncapitalize + - undifferentiable - uncollapsed - uninstantiated - unioned + - unparented - unprefixed - unprojected + - unrepresentable - unsourced - unversioned - VITE diff --git a/docs/libraries/http-server-javascript/reference/emitter.md b/docs/libraries/http-server-javascript/reference/emitter.md new file mode 100644 index 0000000000..48a590d5ef --- /dev/null +++ b/docs/libraries/http-server-javascript/reference/emitter.md @@ -0,0 +1,36 @@ +--- +title: "Emitter usage" +toc_min_heading_level: 2 +toc_max_heading_level: 3 +--- + +# Emitter + +## Usage + +1. Via the command line + +```bash +tsp compile . --emit=@typespec/http-server-javascript +``` + +2. Via the config + +```yaml +emit: + - "@typespec/http-server-javascript" +``` + +## Emitter options + +### `features` + +**Type:** `object` + +### `omit-unreachable-types` + +**Type:** `boolean` + +### `no-format` + +**Type:** `boolean` diff --git a/docs/libraries/http-server-javascript/reference/index.mdx b/docs/libraries/http-server-javascript/reference/index.mdx new file mode 100644 index 0000000000..f49d39fb19 --- /dev/null +++ b/docs/libraries/http-server-javascript/reference/index.mdx @@ -0,0 +1,36 @@ +--- +title: Overview +sidebar_position: 0 +toc_min_heading_level: 2 +toc_max_heading_level: 3 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Overview + +TypeSpec HTTP server code generator for JavaScript + +## Install + + + + +```bash +npm install @typespec/http-server-javascript +``` + + + + +```bash +npm install --save-peer @typespec/http-server-javascript +``` + + + + +## Emitter usage + +[See documentation](./emitter.md) diff --git a/packages/http-server-javascript/LICENSE b/packages/http-server-javascript/LICENSE new file mode 100644 index 0000000000..21071075c2 --- /dev/null +++ b/packages/http-server-javascript/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/packages/http-server-javascript/README.md b/packages/http-server-javascript/README.md new file mode 100644 index 0000000000..e36a1ac1d1 --- /dev/null +++ b/packages/http-server-javascript/README.md @@ -0,0 +1,183 @@ +# @typespec/http-server-javascript + +:warning: **This package is highly experimental and may be subject to breaking changes and bugs.** Please expect that your code may need to be updated as this package evolves, and please report any issues you encounter. + +TypeSpec HTTP server code generator for JavaScript and TypeScript. + +This package generates an implementation of an HTTP server layer for a TypeSpec API. It supports binding directly to a +Node.js HTTP server or Express.js application. + +## Install + +```bash +npm install @typespec/http-server-javascript +``` + +## Emitter + +### Usage + +1. Via the command line + +```bash +tsp compile . --emit=@typespec/http-server-javascript +``` + +2. Via the config + +```yaml +emit: + - "@typespec/http-server-javascript" +``` + +### Emitter options + +#### `express` + +**Type:** `boolean` + +If set to `true`, the emitter will generate a router that exposes an Express.js middleware function in addition to the +ordinary Node.js HTTP server router. + +If this option is not set to `true`, the `expressMiddleware` property will not be present on the generated router. + +#### `omit-unreachable-types` + +**Type:** `boolean` + +By default, the emitter will create interfaces that represent all models in the service namespace. If this option is set +to `true`, the emitter will only emit those types that are reachable from an HTTP operation. + +#### `no-format` + +**Type:** `boolean` + +If set to `true`, the emitter will not format the generated code using Prettier. + +## Functionality and generated code + +The emitter generates a few major components: + +### Router + +The highest-level component that your code interacts with directly is the router implementation. +`@typespec/http-server-javascript` generates a static router that you can bind to an implementation of an HTTP server. + +The router is generated in the `http/router.js` module within the output directory. Each service will have its own +router implementation named after the service. For example, given a service namespace named `Todo`, the router module +will export a function `createTodoRouter`. This function creates an instance of a router that dispatches methods within +the `Todo` service. + +```ts +import { createTodoRouter } from "../tsp-output/@typespec/http-server-javascript/http/router.js"; + +const router = createTodoRouter(users, todoItems, attachments); +``` + +As arguments, the `createTodoRouter` function expects implementations of the underlying service interfaces. These +interfaces are explained further in the next section. + +Once the router is created, it is bound to an instance of the HTTP server. The router's `dispatch` method implements the +Node.js event handler signature for the `request` event on a Node.js HTTP server. + +```ts +const server = http.createServer(); + +server.on("request", router.dispatch); + +server.listen(8080, () => { + console.log("Server listening on http://localhost:8080"); +}); +``` + +Alternatively, the router can be used with Express.js instead of the Node.js HTTP server directly. If the `express` +feature is enabled in the emitter options, the router will expose an `expressMiddleware` property that implements the +Express.js middleware interface. + +```ts +import express from "express"; + +const app = express(); + +app.use(router.expressMiddleware); + +app.listen(8080, () => { + console.log("Server listening on http://localhost:8080"); +}); +``` + +### Service interfaces + +The emitter generates interfaces for each collection of service methods that exists in the service namespace. +Implementations of these interfaces are required to instantiate the router. When the router processes an HTTP request, +it will call the appropriate method on the service implementation after determining the route and method. + +For example, given the following TypeSpec namespace `Users` within the `Todo` service: + +```tsp +namespace Users { + @route("/users") + @post + op create( + user: User, + ): WithStandardErrors; +} +``` + +The emitter will generate a corresponding interface `Users` within the module `models/all/todo/index.js` in the output +directory. + +```ts +/** An interface representing the operations defined in the 'Todo.Users' namespace. */ +export interface Users { + create( + ctx: Context, + user: User + ): Promise< + | UserCreatedResponse + | UserExistsResponse + | InvalidUserResponse + | Standard4XxResponse + | Standard5XxResponse + >; +} +``` + +An object implementing this `Users` interface must be passed to the router when it is created. The `Context` type +parameter represents the underlying protocol or framework-specific context that the service implementation may inspect. +If you need to access the HTTP request or response objects directly in the implementation of the service methods, you +must use the `HttpContext` type as the `Context` argument when implementing the service interface. Otherwise, it is safe +to use the default `unknown` argument. + +```ts +import { HttpContext } from "../tsp-output/@typespec/http-server-javascript/helpers/router.js"; +import { Users } from "../tsp-output/@typespec/http-server-javascript/models/all/todo/index.js"; + +export const users: Users = { + async create(ctx, user) { + // Implementation + }, +}; +``` + +### Models + +The emitter generates TypeScript interfaces that represent the model types used in the service operations. This allows +the service implementation to interact with the data structures carried over the HTTP protocol in a type-safe manner. + +### Operation functions + +While your code should never need to interact with these functions directly, the emitter generates a function per HTTP +operation that handles the parsing and validation of the request contents. This allows the service implementation to be +written in terms of ordinary TypeScript types and values rather than raw HTTP request and response objects. In general: + +- The Node.js HTTP server or Express.js application (your code) calls the router (generated code), which determines + which service operation function (generated code) to call based on the route, method, and other HTTP metadata in the + case of shared routes. +- The operation function (generated code) deserializes the request body, query parameters, and headers into TypeScript + types, and may perform request validation. +- The operation function (generated code) calls the service implementation (your code) with the deserialized request + data. +- The service implementation (your code) returns a result or throws an error. +- The operation function (generated code) responds to the HTTP request on your behalf, converting the result or error + into HTTP response data. diff --git a/packages/http-server-javascript/build-helpers.ts b/packages/http-server-javascript/build-helpers.ts new file mode 100644 index 0000000000..2f8c618e51 --- /dev/null +++ b/packages/http-server-javascript/build-helpers.ts @@ -0,0 +1,170 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/* eslint no-console: "off" */ + +import fs from "node:fs/promises"; +import path from "node:path"; + +const HELPER_DECLARATION_PATH = path.resolve("generated-defs", "helpers"); +const HELPER_SRC_PATH = path.resolve("src", "helpers"); + +console.log("Building JS server generator helpers."); + +async function* visitAllFiles(base: string): AsyncIterable { + const contents = await fs.readdir(base, { withFileTypes: true }); + + for (const entry of contents) { + if (entry.isDirectory()) { + yield* visitAllFiles(path.join(base, entry.name)); + } else if (entry.isFile()) { + yield path.join(base, entry.name); + } + } +} + +async function main() { + const allFiles: string[] = []; + const indices = new Map(); + + const ctxPath = path.resolve("src", "ctx.js"); + + await fs.rm(HELPER_DECLARATION_PATH, { recursive: true, force: true }); + + function addIndex(dir: string, file: string) { + const index = indices.get(dir); + + if (index) { + index.push(file); + } else { + indices.set(dir, [file]); + } + } + + for await (const file of visitAllFiles(HELPER_SRC_PATH)) { + allFiles.push(file); + addIndex(path.dirname(file), file); + } + + for (const file of allFiles) { + if (!file.endsWith(".ts")) { + continue; + } + + const relativePath = path.relative(HELPER_SRC_PATH, file); + + console.log("Building helper:", relativePath); + + const targetPath = path.resolve(HELPER_DECLARATION_PATH, relativePath); + + const targetDir = path.dirname(targetPath); + const targetFileBase = path.basename(targetPath, ".ts"); + const isIndex = targetFileBase === "index"; + const targetBase = isIndex ? path.basename(targetDir) : targetFileBase; + await fs.mkdir(targetDir, { recursive: true }); + + const childModules = isIndex ? indices.get(path.dirname(file)) : []; + + if (isIndex) { + indices.delete(path.dirname(file)); + } + + const contents = await fs.readFile(file, "utf-8"); + + let childModuleLines = + childModules + ?.filter((m) => path.basename(m, ".ts") !== "index") + .map((child) => { + const childBase = path.basename(child, ".ts"); + return ` await import("./${childBase}.js").then((m) => m.createModule(module));`; + }) ?? []; + + if (childModuleLines.length > 0) { + childModuleLines = [" // Child modules", ...childModuleLines, ""]; + } + + const transformed = [ + "// Copyright (c) Microsoft Corporation", + "// Licensed under the MIT license.", + "", + `import { Module } from "${path.relative(targetDir, ctxPath).replace(/\\/g, "/")}";`, + "", + "export let module: Module = undefined as any;", + "", + "// prettier-ignore", + "const lines = [", + ...contents.split(/\r?\n/).map((line) => " " + JSON.stringify(line) + ","), + "];", + "", + "export async function createModule(parent: Module): Promise {", + " if (module) return module;", + "", + " module = {", + ` name: ${JSON.stringify(targetBase)},`, + ` cursor: parent.cursor.enter(${JSON.stringify(targetBase)}),`, + " imports: [],", + " declarations: [],", + " };", + "", + ...childModuleLines, + " module.declarations.push(lines);", + "", + " parent.declarations.push(module);", + "", + " return module;", + "}", + "", + ].join("\n"); + + await fs.writeFile(targetPath, transformed); + } + + console.log("Building index files."); + + for (const [dir, files] of indices.entries()) { + console.log("Building index:", dir); + + const relativePath = path.relative(HELPER_SRC_PATH, dir); + + const targetPath = path.resolve(HELPER_DECLARATION_PATH, relativePath, "index.ts"); + + const children = files.map((file) => { + return ` await import("./${path.basename(file, ".ts")}.js").then((m) => m.createModule(module));`; + }); + + const transformed = [ + "// Copyright (c) Microsoft Corporation", + "// Licensed under the MIT license.", + "", + `import { Module } from "${path.relative(path.dirname(targetPath), ctxPath).replace(/\\/g, "/")}";`, + "", + "export let module: Module = undefined as any;", + "", + "export async function createModule(parent: Module): Promise {", + " if (module) return module;", + "", + " module = {", + ` name: ${JSON.stringify(path.basename(dir))},`, + ` cursor: parent.cursor.enter(${JSON.stringify(path.basename(dir))}),`, + " imports: [],", + " declarations: [],", + " };", + "", + " // Child modules", + ...children, + "", + " parent.declarations.push(module);", + "", + " return module;", + "}", + "", + ].join("\n"); + + await fs.writeFile(targetPath, transformed); + } +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/packages/http-server-javascript/generated-defs/helpers/index.ts b/packages/http-server-javascript/generated-defs/helpers/index.ts new file mode 100644 index 0000000000..3876a28a17 --- /dev/null +++ b/packages/http-server-javascript/generated-defs/helpers/index.ts @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { Module } from "../../src/ctx.js"; + +export let module: Module = undefined as any; + +export async function createModule(parent: Module): Promise { + if (module) return module; + + module = { + name: "helpers", + cursor: parent.cursor.enter("helpers"), + imports: [], + declarations: [], + }; + + // Child modules + await import("./router.js").then((m) => m.createModule(module)); + + parent.declarations.push(module); + + return module; +} diff --git a/packages/http-server-javascript/generated-defs/helpers/router.ts b/packages/http-server-javascript/generated-defs/helpers/router.ts new file mode 100644 index 0000000000..d49c08bdbe --- /dev/null +++ b/packages/http-server-javascript/generated-defs/helpers/router.ts @@ -0,0 +1,271 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { Module } from "../../src/ctx.js"; + +export let module: Module = undefined as any; + +// prettier-ignore +const lines = [ + "// Copyright (c) Microsoft Corporation", + "// Licensed under the MIT license.", + "", + "import type * as http from \"node:http\";", + "", + "/** A policy that can be applied to a route or a set of routes. */", + "export interface Policy {", + " /** Optional policy name. */", + " name?: string;", + "", + " /**", + " * Applies the policy to the request.", + " *", + " * Policies _MUST_ call `next()` to pass the request to the next policy _OR_ call `response.end()` to terminate,", + " * and _MUST NOT_ do both.", + " *", + " * If the policy passes a `request` object to `next()`, that request object will be used instead of the original", + " * request object for the remainder of the policy chain. If the policy does _not_ pass a request object to `next()`,", + " * the same object that was passed to this policy will be forwarded to the next policy automatically.", + " *", + " * @param request - The incoming HTTP request.", + " * @param response - The outgoing HTTP response.", + " * @param next - Calls the next policy in the chain.", + " */", + " (", + " request: http.IncomingMessage,", + " response: http.ServerResponse,", + " next: (request?: http.IncomingMessage) => void", + " ): void;", + "}", + "", + "/**", + " * Create a function from a chain of policies.", + " *", + " * This returns a single function that will apply the policy chain and eventually call the provided `next()` function.", + " *", + " * @param name - The name to give to the policy chain function.", + " * @param policies - The policies to apply to the request.", + " * @param out - The function to call after the policies have been applied.", + " */", + "export function createPolicyChain<", + " Out extends (", + " ctx: HttpContext,", + " request: http.IncomingMessage,", + " response: http.ServerResponse,", + " ...rest: any[]", + " ) => void,", + ">(name: string, policies: Policy[], out: Out): Out {", + " let outParams: any[];", + " if (policies.length === 0) {", + " return out;", + " }", + "", + " function applyPolicy(", + " ctx: HttpContext,", + " request: http.IncomingMessage,", + " response: http.ServerResponse,", + " index: number", + " ) {", + " if (index >= policies.length) {", + " return out(ctx, request, response, ...outParams);", + " }", + "", + " policies[index](request, response, function nextPolicy(nextRequest) {", + " applyPolicy(ctx, nextRequest ?? request, response, index + 1);", + " });", + " }", + "", + " return {", + " [name](", + " ctx: HttpContext,", + " request: http.IncomingMessage,", + " response: http.ServerResponse,", + " ...params: any[]", + " ) {", + " outParams = params;", + " applyPolicy(ctx, request, response, 0);", + " },", + " }[name] as Out;", + "}", + "", + "/**", + " * The type of an error encountered during request validation.", + " */", + "export type ValidationError = string;", + "", + "/**", + " * An object specifying the policies for a given route configuration.", + " */", + "export type RoutePolicies = {", + " [Interface in keyof RouteConfig]?: {", + " before?: Policy[];", + " after?: Policy[];", + " methodPolicies?: {", + " [Method in keyof RouteConfig[Interface]]?: Policy[];", + " };", + " };", + "};", + "", + "/**", + " * Create a policy chain for a given route.", + " *", + " * This function calls `createPolicyChain` internally and orders the policies based on the route configuration.", + " *", + " * Interface-level `before` policies run first, then method-level policies, then Interface-level `after` policies.", + " *", + " * @param name - The name to give to the policy chain function.", + " * @param routePolicies - The policies to apply to the routes (part of the route configuration).", + " * @param interfaceName - The name of the interface that the route belongs to.", + " * @param methodName - The name of the method that the route corresponds to.", + " * @param out - The function to call after the policies have been applied.", + " */", + "export function createPolicyChainForRoute<", + " RouteConfig extends { [k: string]: object },", + " InterfaceName extends keyof RouteConfig,", + " Out extends (", + " ctx: HttpContext,", + " request: http.IncomingMessage,", + " response: http.ServerResponse,", + " ...rest: any[]", + " ) => void,", + ">(", + " name: string,", + " routePolicies: RoutePolicies,", + " interfaceName: InterfaceName,", + " methodName: keyof RouteConfig[InterfaceName],", + " out: Out", + "): Out {", + " return createPolicyChain(", + " name,", + " [", + " ...(routePolicies[interfaceName]?.before ?? []),", + " ...(routePolicies[interfaceName]?.methodPolicies?.[methodName] ?? []),", + " ...(routePolicies[interfaceName]?.after ?? []),", + " ],", + " out", + " );", + "}", + "", + "/**", + " * Options for configuring a router with additional functionality.", + " */", + "export interface RouterOptions<", + " RouteConfig extends { [k: string]: object } = { [k: string]: object },", + "> {", + " /**", + " * The base path of the router.", + " *", + " * This should include any leading slashes, but not a trailing slash, and should not include any component", + " * of the URL authority (e.g. the scheme, host, or port).", + " *", + " * Defaults to \"\".", + " */", + " basePath?: string;", + "", + " /**", + " * A list of policies to apply to all routes _before_ routing.", + " *", + " * Policies are applied in the order they are listed.", + " *", + " * By default, the policy list is empty.", + " *", + " * Policies _MUST_ call `next()` to pass the request to the next policy _OR_ call `response.end()` to terminate", + " * the response and _MUST NOT_ do both.", + " */", + " policies?: Policy[];", + "", + " /**", + " * A record of policies that apply to specific routes.", + " *", + " * The policies are provided as a nested record where the keys are the business-logic interface names, and the values", + " * are records of the method names in the given interface and the policies that apply to them.", + " *", + " * By default, no additional policies are applied to the routes.", + " *", + " * Policies _MUST_ call `next()` to pass the request to the next policy _OR_ call `response.end()` to terminate", + " * the response and _MUST NOT_ do both.", + " */", + " routePolicies?: RoutePolicies;", + "", + " /**", + " * A handler for requests that do not match any known route and method.", + " *", + " * If this handler is not provided, a 404 Not Found response with a text body will be returned.", + " *", + " * You _MUST_ call `response.end()` to terminate the response.", + " *", + " * This handler is unreachable when using the Express middleware, as it will forward non-matching requests to the", + " * next middleware layer in the stack.", + " *", + " * @param request - The incoming HTTP request.", + " * @param response - The outgoing HTTP response.", + " */", + " onRequestNotFound?: (request: http.IncomingMessage, response: http.ServerResponse) => void;", + "", + " /**", + " * A handler for requests that fail to validate inputs.", + " *", + " * If this handler is not provided, a 400 Bad Request response with a JSON body containing some basic information", + " * about the error will be returned to the client.", + " *", + " * You _MUST_ call `response.end()` to terminate the response.", + " *", + " * @param request - The incoming HTTP request.", + " * @param response - The outgoing HTTP response.", + " * @param route - The route that was matched.", + " * @param error - The validation error that was thrown.", + " */", + " onInvalidRequest?: (", + " request: http.IncomingMessage,", + " response: http.ServerResponse,", + " route: string,", + " error: ValidationError", + " ) => void;", + "", + " /**", + " * A handler for requests that throw an error during processing.", + " *", + " * If this handler is not provided, a 500 Internal Server Error response with a text body and no error details will be", + " * returned to the client.", + " *", + " * You _MUST_ call `response.end()` to terminate the response.", + " *", + " * If this handler itself throws an Error, the router will respond with a 500 Internal Server Error", + " *", + " * @param error - The error that was thrown.", + " * @param request - The incoming HTTP request.", + " * @param response - The outgoing HTTP response.", + " */", + " onInternalError?(", + " error: unknown,", + " request: http.IncomingMessage,", + " response: http.ServerResponse", + " ): void;", + "}", + "", + "/** Context information for operations carried over the HTTP protocol. */", + "export interface HttpContext {", + " /** The incoming request to the server. */", + " request: http.IncomingMessage;", + " /** The outgoing response object. */", + " response: http.ServerResponse;", + "}", + "", +]; + +export async function createModule(parent: Module): Promise { + if (module) return module; + + module = { + name: "router", + cursor: parent.cursor.enter("router"), + imports: [], + declarations: [], + }; + + module.declarations.push(lines); + + parent.declarations.push(module); + + return module; +} diff --git a/packages/http-server-javascript/package.json b/packages/http-server-javascript/package.json new file mode 100644 index 0000000000..c626134f1b --- /dev/null +++ b/packages/http-server-javascript/package.json @@ -0,0 +1,55 @@ +{ + "name": "@typespec/http-server-javascript", + "version": "0.58.0-alpha.1", + "author": "Microsoft Corporation", + "description": "TypeSpec HTTP server code generator for JavaScript", + "homepage": "https://github.com/microsoft/typespec", + "readme": "https://github.com/microsoft/typespec/blob/main/packages/http-server-javascript/README.md", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/microsoft/typespec.git" + }, + "bugs": { + "url": "https://github.com/microsoft/typespec/issues" + }, + "keywords": [ + "typespec", + "http", + "server", + "javascript", + "typescript" + ], + "type": "module", + "main": "dist/src/index.js", + "exports": { + ".": "./dist/src/index.js", + "./testing": "./dist/src/testing/index.js" + }, + "scripts": { + "clean": "rimraf ./dist ./temp", + "build": "npm run build:helpers && npm run build:src", + "build:src": "tsc -p ./tsconfig.json", + "build:helpers": "tsx ./build-helpers.ts", + "watch": "tsc -p . --watch", + "test": "echo No tests specified", + "test:ci": "echo No tests specified", + "lint": "eslint . --max-warnings=0", + "lint:fix": "eslint . --fix", + "regen-docs": "echo Doc generation disabled for this package." + }, + "peerDependencies": { + "@typespec/compiler": "workspace:~", + "@typespec/http": "workspace:~" + }, + "dependencies": { + "prettier": "~3.3.2" + }, + "devDependencies": { + "@types/node": "~18.11.19", + "@typespec/compiler": "workspace:~", + "@typespec/http": "workspace:~", + "typescript": "~5.5.3", + "tsx": "^4.16.0" + } +} diff --git a/packages/http-server-javascript/src/common/declaration.ts b/packages/http-server-javascript/src/common/declaration.ts new file mode 100644 index 0000000000..23d0adec83 --- /dev/null +++ b/packages/http-server-javascript/src/common/declaration.ts @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { DeclarationType, JsContext, Module } from "../ctx.js"; +import { emitEnum } from "./enum.js"; +import { emitInterface } from "./interface.js"; +import { emitModel } from "./model.js"; +import { emitScalar } from "./scalar.js"; +import { emitUnion } from "./union.js"; + +/** + * Emit a declaration for a module based on its type. + * + * The altName is optional and is only used for unnamed models and unions. + * + * @param ctx - The emitter context. + * @param type - The type to emit. + * @param module - The module that this declaration is written into. + * @param altName - An alternative name to use for the declaration if it is not named. + */ +export function* emitDeclaration( + ctx: JsContext, + type: DeclarationType, + module: Module, + altName?: string +): Iterable { + switch (type.kind) { + case "Model": { + yield* emitModel(ctx, type, module, altName); + break; + } + case "Enum": { + yield* emitEnum(ctx, type); + break; + } + case "Union": { + yield* emitUnion(ctx, type, module, altName); + break; + } + case "Interface": { + yield* emitInterface(ctx, type, module); + break; + } + case "Scalar": { + yield emitScalar(ctx, type); + break; + } + default: { + throw new Error(`UNREACHABLE: Unhandled type kind: ${(type satisfies never as any).kind}`); + } + } +} diff --git a/packages/http-server-javascript/src/common/documentation.ts b/packages/http-server-javascript/src/common/documentation.ts new file mode 100644 index 0000000000..ee1bf08810 --- /dev/null +++ b/packages/http-server-javascript/src/common/documentation.ts @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { Type, getDoc } from "@typespec/compiler"; +import { JsContext } from "../ctx.js"; +import { indent } from "../util/iter.js"; + +/** + * Emit the documentation for a type in JSDoc format. + * + * This assumes that the documentation may include Markdown formatting. + * + * @param ctx - The emitter context. + * @param type - The type to emit documentation for. + */ +export function* emitDocumentation(ctx: JsContext, type: Type): Iterable { + const doc = getDoc(ctx.program, type); + + if (doc === undefined) return; + + yield `/**`; + + yield* indent(doc.trim().split(/\r?\n/g), " * "); + + yield ` */`; +} diff --git a/packages/http-server-javascript/src/common/enum.ts b/packages/http-server-javascript/src/common/enum.ts new file mode 100644 index 0000000000..97d252bee9 --- /dev/null +++ b/packages/http-server-javascript/src/common/enum.ts @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { Enum } from "@typespec/compiler"; +import { JsContext } from "../ctx.js"; +import { parseCase } from "../util/case.js"; +import { emitDocumentation } from "./documentation.js"; + +/** + * Emit an enum declaration. + * + * @param ctx - The emitter context. + * @param enum_ - The enum to emit. + */ +export function* emitEnum(ctx: JsContext, enum_: Enum): Iterable { + yield* emitDocumentation(ctx, enum_); + + const name = parseCase(enum_.name); + + yield `export enum ${name.pascalCase} {`; + + for (const member of enum_.members.values()) { + yield ` ${member.name} = ${member.value},`; + } + + yield `}`; +} diff --git a/packages/http-server-javascript/src/common/interface.ts b/packages/http-server-javascript/src/common/interface.ts new file mode 100644 index 0000000000..92fe38fd28 --- /dev/null +++ b/packages/http-server-javascript/src/common/interface.ts @@ -0,0 +1,262 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { Interface, Operation, Type, UnionVariant, isErrorModel } from "@typespec/compiler"; +import { JsContext, Module, PathCursor } from "../ctx.js"; +import { parseCase } from "../util/case.js"; +import { getAllProperties } from "../util/extends.js"; +import { bifilter, indent } from "../util/iter.js"; +import { emitDocumentation } from "./documentation.js"; +import { emitTypeReference, isValueLiteralType } from "./reference.js"; +import { emitUnionType } from "./union.js"; + +/** + * Emit an interface declaration. + * + * @param ctx - The emitter context. + * @param iface - The interface to emit. + * @param module - The module that this interface is written into. + */ +export function* emitInterface(ctx: JsContext, iface: Interface, module: Module): Iterable { + const name = parseCase(iface.name).pascalCase; + + yield* emitDocumentation(ctx, iface); + yield `export interface ${name} {`; + yield* indent(emitOperationGroup(ctx, iface.operations.values(), module)); + yield "}"; + yield ""; +} + +/** + * Emit a list of operation signatures. + * + * @param ctx - The emitter context. + * @param operations - The operations to emit. + * @param module - The module that the operations are written into. + */ +export function* emitOperationGroup( + ctx: JsContext, + operations: Iterable, + module: Module +): Iterable { + for (const op of operations) { + yield* emitOperation(ctx, op, module); + yield ""; + } +} + +/** + * Emit a single operation signature. + * + * @param ctx - The emitter context. + * @param op - The operation to emit. + * @param module - The module that the operation is written into. + */ +export function* emitOperation(ctx: JsContext, op: Operation, module: Module): Iterable { + const opNameCase = parseCase(op.name); + + const opName = opNameCase.camelCase; + + const hasOptions = getAllProperties(op.parameters).some((p) => p.optional); + + const returnTypeReference = emitTypeReference(ctx, op.returnType, op, module, { + altName: opNameCase.pascalCase + "Result", + }); + + const returnType = `Promise<${returnTypeReference}>`; + + const params: string[] = []; + + for (const param of getAllProperties(op.parameters)) { + // If the type is a value literal, then we consider it a _setting_ and not a parameter. + // This allows us to exclude metadata parameters (such as contentType) from the generated interface. + if (param.optional || isValueLiteralType(param.type)) continue; + + const paramNameCase = parseCase(param.name); + const paramName = paramNameCase.camelCase; + + const outputTypeReference = emitTypeReference(ctx, param.type, param, module, { + altName: opNameCase.pascalCase + paramNameCase.pascalCase, + }); + + params.push(`${paramName}: ${outputTypeReference}`); + } + + const paramsDeclarationLine = params.join(", "); + + yield* emitDocumentation(ctx, op); + + if (hasOptions) { + const optionsTypeName = opNameCase.pascalCase + "Options"; + + emitOptionsType(ctx, op, module, optionsTypeName); + + const paramsFragment = params.length > 0 ? `${paramsDeclarationLine}, ` : ""; + + // prettier-ignore + yield `${opName}(ctx: Context, ${paramsFragment}options?: ${optionsTypeName}): ${returnType};`; + yield ""; + } else { + // prettier-ignore + yield `${opName}(ctx: Context, ${paramsDeclarationLine}): ${returnType};`; + yield ""; + } +} + +/** + * Emit a declaration for an options type including the optional parameters of an operation. + * + * @param ctx - The emitter context. + * @param operation - The operation to emit the options type for. + * @param module - The module that the options type is written into. + * @param optionsTypeName - The name of the options type. + */ +export function emitOptionsType( + ctx: JsContext, + operation: Operation, + module: Module, + optionsTypeName: string +) { + module.imports.push({ + binder: [optionsTypeName], + from: ctx.syntheticModule, + }); + + const options = [...operation.parameters.properties.values()].filter((p) => p.optional); + + ctx.syntheticModule.declarations.push([ + `export interface ${optionsTypeName} {`, + ...options.flatMap((p) => [ + ` ${parseCase(p.name).camelCase}?: ${emitTypeReference(ctx, p.type, p, module, { + altName: optionsTypeName + parseCase(p.name).pascalCase, + })};`, + ]), + "}", + "", + ]); +} + +export interface SplitReturnTypeCommon { + typeReference: string; + target: Type | [PathCursor, string] | undefined; +} + +export interface OrdinarySplitReturnType extends SplitReturnTypeCommon { + kind: "ordinary"; +} + +export interface UnionSplitReturnType extends SplitReturnTypeCommon { + kind: "union"; + variants: UnionVariant[]; +} + +export type SplitReturnType = OrdinarySplitReturnType | UnionSplitReturnType; + +const DEFAULT_NO_VARIANT_RETURN_TYPE = "never"; +const DEFAULT_NO_VARIANT_SPLIT: SplitReturnType = { + kind: "ordinary", + typeReference: DEFAULT_NO_VARIANT_RETURN_TYPE, + target: undefined, +}; + +export function isInfallible(split: SplitReturnType): boolean { + return ( + (split.kind === "ordinary" && split.typeReference === "never") || + (split.kind === "union" && split.variants.length === 0) + ); +} + +export function splitReturnType( + ctx: JsContext, + type: Type, + module: Module, + altBaseName: string +): [SplitReturnType, SplitReturnType] { + const successAltName = altBaseName + "Response"; + const errorAltName = altBaseName + "ErrorResponse"; + + if (type.kind === "Union") { + const [successVariants, errorVariants] = bifilter( + type.variants.values(), + (v) => !isErrorModel(ctx.program, v.type) + ); + + const successTypeReference = + successVariants.length === 0 + ? DEFAULT_NO_VARIANT_RETURN_TYPE + : successVariants.length === 1 + ? emitTypeReference(ctx, successVariants[0].type, successVariants[0], module, { + altName: successAltName, + }) + : emitUnionType(ctx, successVariants, module); + + const errorTypeReference = + errorVariants.length === 0 + ? DEFAULT_NO_VARIANT_RETURN_TYPE + : errorVariants.length === 1 + ? emitTypeReference(ctx, errorVariants[0].type, errorVariants[0], module, { + altName: errorAltName, + }) + : emitUnionType(ctx, errorVariants, module); + + const successSplit: SplitReturnType = + successVariants.length > 1 + ? { + kind: "union", + variants: successVariants, + typeReference: successTypeReference, + target: undefined, + } + : { + kind: "ordinary", + typeReference: successTypeReference, + target: successVariants[0]?.type, + }; + + const errorSplit: SplitReturnType = + errorVariants.length > 1 + ? { + kind: "union", + variants: errorVariants, + typeReference: errorTypeReference, + // target: module.cursor.resolveRelativeItemPath(errorTypeReference), + target: undefined, + } + : { + kind: "ordinary", + typeReference: errorTypeReference, + target: errorVariants[0]?.type, + }; + + return [successSplit, errorSplit]; + } else { + // No splitting, just figure out if the type is an error type or not and make the other infallible. + + if (isErrorModel(ctx.program, type)) { + const typeReference = emitTypeReference(ctx, type, type, module, { + altName: altBaseName + "ErrorResponse", + }); + + return [ + DEFAULT_NO_VARIANT_SPLIT, + { + kind: "ordinary", + typeReference, + target: type, + }, + ]; + } else { + const typeReference = emitTypeReference(ctx, type, type, module, { + altName: altBaseName + "SuccessResponse", + }); + return [ + { + kind: "ordinary", + typeReference, + target: type, + }, + DEFAULT_NO_VARIANT_SPLIT, + ]; + } + } +} diff --git a/packages/http-server-javascript/src/common/model.ts b/packages/http-server-javascript/src/common/model.ts new file mode 100644 index 0000000000..f5123afdeb --- /dev/null +++ b/packages/http-server-javascript/src/common/model.ts @@ -0,0 +1,137 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { + Model, + getFriendlyName, + isTemplateDeclaration, + isTemplateInstance, +} from "@typespec/compiler"; +import { JsContext, Module } from "../ctx.js"; +import { parseCase } from "../util/case.js"; +import { indent } from "../util/iter.js"; +import { KEYWORDS } from "../util/keywords.js"; +import { getFullyQualifiedTypeName } from "../util/name.js"; +import { asArrayType, getArrayElementName, getRecordValueName } from "../util/pluralism.js"; +import { emitDocumentation } from "./documentation.js"; +import { emitTypeReference } from "./reference.js"; + +/** + * Emit a model declaration. + * + * @param ctx - The emitter context. + * @param model - The model to emit. + * @param module - The module that this model is written into. + * @param altName - An alternative name to use for the model if it is not named. + */ +export function* emitModel( + ctx: JsContext, + model: Model, + module: Module, + altName?: string +): Iterable { + const isTemplate = isTemplateInstance(model); + const friendlyName = getFriendlyName(ctx.program, model); + + if (isTemplateDeclaration(model)) { + return; + } + + const modelNameCase = parseCase( + friendlyName + ? friendlyName + : isTemplate + ? model.templateMapper!.args.map((a) => ("name" in a ? String(a.name) : "")).join("_") + + model.name + : model.name + ); + + if (model.name === "" && !altName) { + throw new Error("UNREACHABLE: Anonymous model with no altName"); + } + + yield* emitDocumentation(ctx, model); + + const ifaceName = model.name === "" ? altName! : modelNameCase.pascalCase; + + const extendsClause = model.baseModel + ? `extends ${emitTypeReference(ctx, model.baseModel, model, module)} ` + : ""; + + yield `export interface ${ifaceName} ${extendsClause}{`; + + for (const field of model.properties.values()) { + const nameCase = parseCase(field.name); + const basicName = nameCase.camelCase; + + const typeReference = emitTypeReference(ctx, field.type, field, module, { + altName: modelNameCase.pascalCase + nameCase.pascalCase, + }); + + const name = KEYWORDS.has(basicName) ? `_${basicName}` : basicName; + + yield* indent(emitDocumentation(ctx, field)); + + const questionMark = field.optional ? "?" : ""; + + yield ` ${name}${questionMark}: ${typeReference};`; + yield ""; + } + + yield "}"; + yield ""; +} + +export function emitModelLiteral(ctx: JsContext, model: Model, module: Module): string { + const properties = [...model.properties.values()].map((prop) => { + const nameCase = parseCase(prop.name); + const questionMark = prop.optional ? "?" : ""; + + const name = KEYWORDS.has(nameCase.camelCase) ? `_${nameCase.camelCase}` : nameCase.camelCase; + + return `${name}${questionMark}: ${emitTypeReference(ctx, prop.type, prop, module)}`; + }); + + return `{ ${properties.join("; ")} }`; +} + +/** + * Determines whether a model is an instance of a well-known model, such as TypeSpec.Record or TypeSpec.Array. + */ +export function isWellKnownModel(ctx: JsContext, type: Model): boolean { + const fullName = getFullyQualifiedTypeName(type); + return fullName === "TypeSpec.Record" || fullName === "TypeSpec.Array"; +} + +/** + * Emits a well-known model, such as TypeSpec.Record or TypeSpec.Array. + * + * @param ctx - The emitter context. + * @param type - The model to emit. + * @param module - The module that this model is written into. + * @param preferredAlternativeName - An alternative name to use for the model if it is not named. + */ +export function emitWellKnownModel( + ctx: JsContext, + type: Model, + module: Module, + preferredAlternativeName?: string +): string { + const arg = type.indexer!.value; + switch (type.name) { + case "Record": { + return `{ [k: string]: ${emitTypeReference(ctx, arg, type, module, { + altName: preferredAlternativeName && getRecordValueName(preferredAlternativeName), + })} }`; + } + case "Array": { + return asArrayType( + emitTypeReference(ctx, arg, type, module, { + altName: preferredAlternativeName && getArrayElementName(preferredAlternativeName), + }) + ); + } + default: + throw new Error(`UNREACHABLE: ${type.name}`); + } +} diff --git a/packages/http-server-javascript/src/common/namespace.ts b/packages/http-server-javascript/src/common/namespace.ts new file mode 100644 index 0000000000..147689af86 --- /dev/null +++ b/packages/http-server-javascript/src/common/namespace.ts @@ -0,0 +1,243 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { Namespace, getNamespaceFullName } from "@typespec/compiler"; +import { + DeclarationType, + JsContext, + Module, + ModuleBodyDeclaration, + createModule, + isModule, +} from "../ctx.js"; +import { parseCase } from "../util/case.js"; +import { UnimplementedError } from "../util/error.js"; +import { cat, indent, isIterable } from "../util/iter.js"; +import { OnceQueue } from "../util/once-queue.js"; +import { emitOperationGroup } from "./interface.js"; + +/** + * Enqueue all declarations in the namespace to be included in the emit, recursively. + * + * @param ctx - The emitter context. + * @param namespace - The root namespace to begin traversing. + */ +export function visitAllTypes(ctx: JsContext, namespace: Namespace) { + const { enums, interfaces, models, unions, namespaces, scalars, operations } = namespace; + + for (const type of cat( + enums.values(), + interfaces.values(), + models.values(), + unions.values(), + scalars.values() + )) { + ctx.typeQueue.add(type); + } + + for (const ns of namespaces.values()) { + visitAllTypes(ctx, ns); + } + + if (operations.size > 0) { + // If the operation has any floating operations in it, we will synthesize an interface for them in the parent module. + // This requires some special handling by other parts of the emitter to ensure that the interface for a namespace's + // own operations is properly imported. + if (!namespace.namespace) { + throw new UnimplementedError("no parent namespace in visitAllTypes"); + } + + const parentModule = createOrGetModuleForNamespace(ctx, namespace.namespace); + + parentModule.declarations.push([ + // prettier-ignore + `/** An interface representing the operations defined in the '${getNamespaceFullName(namespace)}' namespace. */`, + `export interface ${parseCase(namespace.name).pascalCase} {`, + ...indent(emitOperationGroup(ctx, operations.values(), parentModule)), + "}", + ]); + } +} + +/** + * Create a module for a namespace, or get an existing module if one has already been created. + * + * @param ctx - The emitter context. + * @param namespace - The namespace to create a module for. + * @returns the module for the namespace. + */ +export function createOrGetModuleForNamespace( + ctx: JsContext, + namespace: Namespace, + root: Module = ctx.globalNamespaceModule +): Module { + if (ctx.namespaceModules.has(namespace)) { + return ctx.namespaceModules.get(namespace)!; + } + + if (!namespace.namespace) { + throw new Error("UNREACHABLE: no parent namespace in createOrGetModuleForNamespace"); + } + + const parent = + namespace.namespace === ctx.globalNamespace + ? root + : createOrGetModuleForNamespace(ctx, namespace.namespace); + const name = namespace.name === "TypeSpec" ? "typespec" : parseCase(namespace.name).kebabCase; + + const module: Module = createModule(name, parent, namespace); + + ctx.namespaceModules.set(namespace, module); + + return module; +} + +/** + * Get a reference to the interface representing the namespace's floating operations. + * + * This does not check that such an interface actually exists, so it should only be called in situations where it is + * known to exist (for example, if an operation comes from the namespace). + * + * @param ctx - The emitter context. + * @param namespace - The namespace to get the interface reference for. + * @param module - The module the the reference will be written to. + */ +export function emitNamespaceInterfaceReference( + ctx: JsContext, + namespace: Namespace, + module: Module +): string { + if (!namespace.namespace) { + throw new Error("UNREACHABLE: no parent namespace in emitNamespaceInterfaceReference"); + } + + const namespaceName = parseCase(namespace.name).pascalCase; + + module.imports.push({ + binder: [namespaceName], + from: createOrGetModuleForNamespace(ctx, namespace.namespace), + }); + + return namespaceName; +} + +/** + * Emits a single declaration within a module. If the declaration is a module, it is enqueued for later processing. + * + * @param ctx - The emitter context. + * @param decl - The declaration to emit. + * @param queue - The queue to add the declaration to if it is a module. + */ +function* emitModuleBodyDeclaration( + ctx: JsContext, + decl: ModuleBodyDeclaration, + queue: OnceQueue +): Iterable { + if (isIterable(decl)) { + yield* decl; + } else if (typeof decl === "string") { + yield* decl.split(/\r?\n/); + } else { + if (decl.declarations.length > 0) { + queue.add(decl); + } + } +} + +/** + * Gets a file path from a given module to another module. + */ +function computeRelativeFilePath(from: Module, to: Module): string { + const fromIsIndex = from.declarations.some((d) => isModule(d)); + const toIsIndex = to.declarations.some((d) => isModule(d)); + + const relativePath = (fromIsIndex ? from.cursor : from.cursor.parent!).relativePath(to.cursor); + + if (relativePath.length === 0 && !toIsIndex) + throw new Error("UNREACHABLE: relativePath returned no fragments"); + + if (relativePath.length === 0) return "./index.js"; + + const prefix = relativePath[0] === ".." ? "" : "./"; + + const suffix = toIsIndex ? "/index.js" : ".js"; + + return prefix + relativePath.join("/") + suffix; +} + +/** + * Deduplicates, consolidates, and writes the import statements for a module. + */ +function* writeImportsNormalized(ctx: JsContext, module: Module): Iterable { + const allTargets = new Set(); + const importMap = new Map>(); + const starAsMap = new Map(); + const extraStarAs: [string, string][] = []; + + for (const _import of module.imports) { + // check for same module and continue + if (_import.from === module) continue; + + const target = + typeof _import.from === "string" + ? _import.from + : computeRelativeFilePath(module, _import.from); + + allTargets.add(target); + + if (typeof _import.binder === "string") { + if (starAsMap.has(target)) { + extraStarAs.push([_import.binder, target]); + } else { + starAsMap.set(target, _import.binder); + } + } else { + const binders = importMap.get(target) ?? new Set(); + for (const binder of _import.binder) { + binders.add(binder); + } + importMap.set(target, binders); + } + } + + for (const target of allTargets) { + const binders = importMap.get(target); + const starAs = starAsMap.get(target); + + if (binders && starAs) { + yield `import ${starAs}, { ${[...binders].join(", ")} } from "${target}";`; + } else if (binders) { + yield `import { ${[...binders].join(", ")} } from "${target}";`; + } else if (starAs) { + yield `import ${starAs} from "${target}";`; + } + + yield ""; + } + + for (const [binder, target] of extraStarAs) { + yield `import ${binder} from "${target}";`; + } +} + +/** + * Emits the body of a module file. + * + * @param ctx - The emitter context. + * @param module - The module to emit. + * @param queue - The queue to add any submodules to for later processing. + */ +export function* emitModuleBody( + ctx: JsContext, + module: Module, + queue: OnceQueue +): Iterable { + yield* writeImportsNormalized(ctx, module); + + if (module.imports.length > 0) yield ""; + + for (const decl of module.declarations) { + yield* emitModuleBodyDeclaration(ctx, decl, queue); + yield ""; + } +} diff --git a/packages/http-server-javascript/src/common/reference.ts b/packages/http-server-javascript/src/common/reference.ts new file mode 100644 index 0000000000..7feeb3d69c --- /dev/null +++ b/packages/http-server-javascript/src/common/reference.ts @@ -0,0 +1,319 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { + DiagnosticTarget, + IntrinsicType, + LiteralType, + Namespace, + NoTarget, + Type, + compilerAssert, + getEffectiveModelType, + getFriendlyName, + isArrayModelType, +} from "@typespec/compiler"; +import { JsContext, Module, isImportableType } from "../ctx.js"; +import { reportDiagnostic } from "../lib.js"; +import { parseCase } from "../util/case.js"; +import { asArrayType, getArrayElementName } from "../util/pluralism.js"; +import { emitModelLiteral, emitWellKnownModel, isWellKnownModel } from "./model.js"; +import { createOrGetModuleForNamespace } from "./namespace.js"; +import { getJsScalar } from "./scalar.js"; +import { emitUnionType } from "./union.js"; + +export type NamespacedType = Extract; + +/** + * Options for emitting a type reference. + */ +export interface EmitTypeReferenceOptions { + /** + * An optional alternative name to use for the type if it is not named. + */ + altName?: string; + + /** + * Require a declaration for types that may be represented anonymously. + */ + requireDeclaration?: boolean; +} + +/** + * Emits a reference to a host type. + * + * This function will automatically ensure that the referenced type is included in the emit graph, and will import the + * type into the current module if necessary. + * + * Optionally, a `preferredAlternativeName` may be supplied. This alternative name will be used if a declaration is + * required, but the type is anonymous. The alternative name can only be set once. If two callers provide different + * alternative names for the same anonymous type, the first one is used in all cases. If a declaration _is_ required, + * and no alternative name is supplied (or has been supplied in a prior call to `emitTypeReference`), this function will + * throw an error. Callers must be sure to provide an alternative name if the type _may_ have an unknown name. However, + * callers may know that they have previously emitted a reference to the type and provided an alternative name in that + * call, in which case the alternative name may be safely omitted. + * + * @param ctx - The emitter context. + * @param type - The type to emit a reference to. + * @param position - The syntactic position of the reference, for diagnostics. + * @param module - The module that the reference is being emitted into. + * @param preferredAlternativeName - An optional alternative name to use for the type if it is not named. + * @returns a string containing a reference to the TypeScript type that represents the given TypeSpec type. + */ +export function emitTypeReference( + ctx: JsContext, + type: Type, + position: DiagnosticTarget | typeof NoTarget, + module: Module, + options: EmitTypeReferenceOptions = {} +): string { + switch (type.kind) { + case "Scalar": + // Get the scalar and return it directly, as it is a primitive. + return getJsScalar(ctx.program, type, position); + case "Model": { + // First handle arrays. + if (isArrayModelType(ctx.program, type)) { + const argumentType = type.indexer.value; + + const argTypeReference = emitTypeReference(ctx, argumentType, position, module, { + altName: options.altName && getArrayElementName(options.altName), + }); + + if (isImportableType(ctx, argumentType) && argumentType.namespace) { + module.imports.push({ + binder: [argTypeReference], + from: createOrGetModuleForNamespace(ctx, argumentType.namespace), + }); + } + + return asArrayType(argTypeReference); + } + + // Now other well-known models. + if (isWellKnownModel(ctx, type)) { + return emitWellKnownModel(ctx, type, module, options.altName); + } + + // Try to reduce the model to an effective model if possible. + const effectiveModel = getEffectiveModelType(ctx.program, type); + + if (effectiveModel.name === "") { + // We might have seen the model before and synthesized a declaration for it already. + if (ctx.syntheticNames.has(effectiveModel)) { + const name = ctx.syntheticNames.get(effectiveModel)!; + module.imports.push({ + binder: [name], + from: ctx.syntheticModule, + }); + return name; + } + + // Require preferredAlternativeName at this point, as we have an anonymous model that we have not visited. + if (!options.altName) { + return emitModelLiteral(ctx, effectiveModel, module); + } + + // Anonymous model, synthesize a new model with the preferredName + ctx.synthetics.push({ + kind: "anonymous", + name: options.altName, + underlying: effectiveModel, + }); + + module.imports.push({ + binder: [options.altName], + from: ctx.syntheticModule, + }); + + ctx.syntheticNames.set(effectiveModel, options.altName); + + return options.altName; + } else { + // The effective model is good for a declaration, so enqueue it. + ctx.typeQueue.add(effectiveModel); + } + + const friendlyName = getFriendlyName(ctx.program, effectiveModel); + + // The model may be a template instance, so we generate a name for it. + const templatedName = parseCase( + friendlyName + ? friendlyName + : effectiveModel.templateMapper + ? effectiveModel + .templateMapper!.args.map((a) => ("name" in a ? String(a.name) : "")) + .join("_") + effectiveModel.name + : effectiveModel.name + ); + + if (!effectiveModel.namespace) { + throw new Error("UNREACHABLE: no parent namespace of named model in emitTypeReference"); + } + + const parentModule = createOrGetModuleForNamespace(ctx, effectiveModel.namespace); + + module.imports.push({ + binder: [templatedName.pascalCase], + from: parentModule, + }); + + return templatedName.pascalCase; + } + case "Union": { + if (type.variants.size === 0) return "never"; + else if (type.variants.size === 1) + return emitTypeReference(ctx, [...type.variants.values()][0], position, module, options); + + if (options.requireDeclaration) { + if (type.name) { + const nameCase = parseCase(type.name); + + ctx.typeQueue.add(type); + + module.imports.push({ + binder: [nameCase.pascalCase], + from: createOrGetModuleForNamespace(ctx, type.namespace!), + }); + + return type.name; + } else { + const existingSyntheticName = ctx.syntheticNames.get(type); + + if (existingSyntheticName) { + module.imports.push({ + binder: [existingSyntheticName], + from: ctx.syntheticModule, + }); + + return existingSyntheticName; + } else { + const altName = options.altName; + + if (!altName) { + throw new Error("UNREACHABLE: anonymous union without preferredAlternativeName"); + } + + ctx.synthetics.push({ + kind: "anonymous", + name: altName, + underlying: type, + }); + + module.imports.push({ + binder: [altName], + from: ctx.syntheticModule, + }); + + ctx.syntheticNames.set(type, altName); + + return altName; + } + } + } else { + return emitUnionType(ctx, [...type.variants.values()], module); + } + } + case "Enum": { + ctx.typeQueue.add(type); + + const name = parseCase(type.name).pascalCase; + + module.imports.push({ + binder: [name], + from: createOrGetModuleForNamespace(ctx, type.namespace!), + }); + + return name; + } + case "String": + return escapeUnsafeChars(JSON.stringify(type.value)); + case "Number": + case "Boolean": + return String(type.value); + case "Intrinsic": + switch (type.name) { + case "never": + return "never"; + case "null": + return "null"; + case "void": + // It's a bit strange to have a void property, but it's possible, and TypeScript allows it. Void is simply + // only assignable from undefined or void itself. + return "void"; + case "ErrorType": + compilerAssert( + false, + "ErrorType should not be encountered in emitTypeReference", + position === NoTarget ? type : position + ); + return "unknown"; + case "unknown": + return "unknown"; + default: + reportDiagnostic(ctx.program, { + code: "unrecognized-intrinsic", + format: { name: (type satisfies never as IntrinsicType).name }, + target: position, + }); + return "unknown"; + } + case "Interface": { + if (type.namespace === undefined) { + throw new Error("UNREACHABLE: unparented interface"); + } + + const typeName = parseCase(type.name).pascalCase; + + ctx.typeQueue.add(type); + + const parentModule = createOrGetModuleForNamespace(ctx, type.namespace); + + module.imports.push({ + binder: [typeName], + from: parentModule, + }); + + return typeName; + } + case "ModelProperty": { + // Forward to underlying type. + return emitTypeReference(ctx, type.type, position, module, options); + } + default: + throw new Error(`UNREACHABLE: ${type.kind}`); + } +} +const UNSAFE_CHAR_MAP: { [k: string]: string } = { + "<": "\\u003C", + ">": "\\u003E", + "/": "\\u002F", + "\\": "\\\\", + "\b": "\\b", + "\f": "\\f", + "\n": "\\n", + "\r": "\\r", + "\t": "\\t", + "\0": "\\0", + "\u2028": "\\u2028", + "\u2029": "\\u2029", +}; + +export function escapeUnsafeChars(s: string) { + return s.replace(/[<>/\\\b\f\n\r\t\0\u2028\u2029]/g, (x) => UNSAFE_CHAR_MAP[x]); +} + +export type JsTypeSpecLiteralType = LiteralType | (IntrinsicType & { name: "null" }); + +export function isValueLiteralType(t: Type): t is JsTypeSpecLiteralType { + switch (t.kind) { + case "String": + case "Number": + case "Boolean": + return true; + case "Intrinsic": + return t.name === "null"; + default: + return false; + } +} diff --git a/packages/http-server-javascript/src/common/scalar.ts b/packages/http-server-javascript/src/common/scalar.ts new file mode 100644 index 0000000000..bdf728414a --- /dev/null +++ b/packages/http-server-javascript/src/common/scalar.ts @@ -0,0 +1,149 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { DiagnosticTarget, NoTarget, Program, Scalar, formatDiagnostic } from "@typespec/compiler"; +import { JsContext } from "../ctx.js"; +import { reportDiagnostic } from "../lib.js"; +import { parseCase } from "../util/case.js"; +import { UnimplementedError } from "../util/error.js"; +import { getFullyQualifiedTypeName } from "../util/name.js"; + +/** + * Emits a declaration for a scalar type. + * + * This is rare in TypeScript, as the scalar will ordinarily be used inline, but may be desirable in some cases. + * + * @param ctx - The emitter context. + * @param scalar - The scalar to emit. + * @returns a string that declares an alias to the scalar type in TypeScript. + */ +export function emitScalar(ctx: JsContext, scalar: Scalar): string { + const jsScalar = getJsScalar(ctx.program, scalar, scalar.node.id); + + const name = parseCase(scalar.name).pascalCase; + + return `type ${name} = ${jsScalar};`; +} + +/** + * Get the string parsing template for a given scalar. + * + * It is common that a scalar type is encoded as a string. For example, in HTTP path parameters or query parameters + * where the value may be an integer, but the APIs expose it as a string. In such cases the parse template may be + * used to coerce the string value to the correct scalar type. + * + * The result of this function contains the string "{}" exactly once, which should be replaced with the text of an + * expression evaluating to the string representation of the scalar. + * + * For example, scalars that are represented by JS `number` are parsed with the template `Number({})`, which will + * convert the string to a number. + * + * @param ctx - The emitter context. + * @param scalar - The scalar to parse from a string + * @returns a template expression string that can be used to parse a string into the scalar type. + */ +export function parseTemplateForScalar(ctx: JsContext, scalar: Scalar): string { + const jsScalar = getJsScalar(ctx.program, scalar, scalar); + + switch (jsScalar) { + case "string": + return "{}"; + case "number": + return "Number({})"; + case "bigint": + return "BigInt({})"; + default: + throw new UnimplementedError(`parse template for scalar '${jsScalar}'`); + } +} + +const __JS_SCALARS_MAP = new Map>(); + +function getScalarsMap(program: Program): Map { + let scalars = __JS_SCALARS_MAP.get(program); + + if (scalars === undefined) { + scalars = createScalarsMap(program); + __JS_SCALARS_MAP.set(program, scalars); + } + + return scalars; +} + +function createScalarsMap(program: Program): Map { + const entries = [ + [program.resolveTypeReference("TypeSpec.bytes"), "Uint8Array"], + [program.resolveTypeReference("TypeSpec.boolean"), "boolean"], + [program.resolveTypeReference("TypeSpec.string"), "string"], + [program.resolveTypeReference("TypeSpec.float32"), "number"], + [program.resolveTypeReference("TypeSpec.float64"), "number"], + + [program.resolveTypeReference("TypeSpec.uint32"), "number"], + [program.resolveTypeReference("TypeSpec.uint16"), "number"], + [program.resolveTypeReference("TypeSpec.uint8"), "number"], + [program.resolveTypeReference("TypeSpec.int32"), "number"], + [program.resolveTypeReference("TypeSpec.int16"), "number"], + [program.resolveTypeReference("TypeSpec.int8"), "number"], + + [program.resolveTypeReference("TypeSpec.safeint"), "number"], + [program.resolveTypeReference("TypeSpec.integer"), "bigint"], + [program.resolveTypeReference("TypeSpec.plainDate"), "Date"], + [program.resolveTypeReference("TypeSpec.plainTime"), "Date"], + [program.resolveTypeReference("TypeSpec.utcDateTime"), "Date"], + ] as const; + + for (const [[type, diagnostics]] of entries) { + if (!type) { + const diagnosticString = diagnostics.map(formatDiagnostic).join("\n"); + throw new Error(`failed to construct TypeSpec -> JavaScript scalar map: ${diagnosticString}`); + } else if (type.kind !== "Scalar") { + throw new Error( + `type ${(type as any).name ?? ""} is a '${type.kind}', expected 'scalar'` + ); + } + } + + return new Map(entries.map(([[type], scalar]) => [type! as Scalar, scalar])); +} + +/** + * Gets a TypeScript type that can represent a given TypeSpec scalar. + * + * Scalar recognition is recursive. If a scalar is not recognized, we will treat it as its parent scalar and try again. + * + * If no scalar in the chain is recognized, it will be treated as `unknown` and a warning will be issued. + * + * @param program - The program that contains the scalar + * @param scalar - The scalar to get the TypeScript type for + * @param diagnosticTarget - Where to report a diagnostic if the scalar is not recognized. + * @returns a string containing a TypeScript type that can represent the scalar + */ +export function getJsScalar( + program: Program, + scalar: Scalar, + diagnosticTarget: DiagnosticTarget | typeof NoTarget +): string { + const scalars = getScalarsMap(program); + + let _scalar: Scalar | undefined = scalar; + + while (_scalar !== undefined) { + const jsScalar = scalars.get(_scalar); + + if (jsScalar !== undefined) { + return jsScalar; + } + + _scalar = _scalar.baseScalar; + } + + reportDiagnostic(program, { + code: "unrecognized-scalar", + target: diagnosticTarget, + format: { + scalar: getFullyQualifiedTypeName(scalar), + }, + }); + + return "unknown"; +} diff --git a/packages/http-server-javascript/src/common/serialization/index.ts b/packages/http-server-javascript/src/common/serialization/index.ts new file mode 100644 index 0000000000..7c95cdc554 --- /dev/null +++ b/packages/http-server-javascript/src/common/serialization/index.ts @@ -0,0 +1,124 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { Model, NoTarget, Scalar, Type, Union } from "@typespec/compiler"; +import { JsContext, Module, completePendingDeclarations } from "../../ctx.js"; +import { UnimplementedError } from "../../util/error.js"; +import { indent } from "../../util/iter.js"; +import { createOrGetModuleForNamespace } from "../namespace.js"; +import { emitTypeReference } from "../reference.js"; +import { emitJsonSerialization, requiresJsonSerialization } from "./json.js"; + +export type SerializableType = Model | Scalar | Union; + +export function isSerializableType(t: Type): t is SerializableType { + return t.kind === "Model" || t.kind === "Scalar" || t.kind === "Union"; +} + +export type SerializationContentType = "application/json"; + +const _SERIALIZATIONS_MAP = new WeakMap>(); + +export function requireSerialization( + ctx: JsContext, + type: Type, + contentType: SerializationContentType +): void { + if (!isSerializableType(type)) { + throw new UnimplementedError(`no implementation of JSON serialization for type '${type.kind}'`); + } + + let serializationsForType = _SERIALIZATIONS_MAP.get(type); + + if (!serializationsForType) { + serializationsForType = new Set(); + _SERIALIZATIONS_MAP.set(type, serializationsForType); + } + + serializationsForType.add(contentType); + + ctx.serializations.add(type); +} + +export interface SerializationContext extends JsContext {} + +export function emitSerialization(ctx: JsContext): void { + completePendingDeclarations(ctx); + + const serializationContext: SerializationContext = { + ...ctx, + }; + + while (!ctx.serializations.isEmpty()) { + const type = ctx.serializations.take()!; + + const serializations = _SERIALIZATIONS_MAP.get(type)!; + + const requiredSerializations = new Set( + [...serializations].filter((serialization) => + isSerializationRequired(ctx, type, serialization) + ) + ); + + if (requiredSerializations.size > 0) { + emitSerializationsForType(serializationContext, type, serializations); + } + } +} + +export function isSerializationRequired( + ctx: JsContext, + type: Type, + serialization: SerializationContentType +): boolean { + switch (serialization) { + case "application/json": { + return requiresJsonSerialization(ctx, type); + } + default: + throw new Error(`Unreachable: serialization content type ${serialization satisfies never}`); + } +} + +function emitSerializationsForType( + ctx: SerializationContext, + type: SerializableType, + serializations: Set +): void { + const isSynthetic = ctx.syntheticNames.has(type) || !type.namespace; + + const module = isSynthetic + ? ctx.syntheticModule + : createOrGetModuleForNamespace(ctx, type.namespace!); + + const typeName = emitTypeReference(ctx, type, NoTarget, module); + + const serializationCode = [`export const ${typeName} = {`]; + + for (const serialization of serializations) { + serializationCode.push( + ...indent(emitSerializationForType(ctx, type, serialization, module, typeName)) + ); + } + + serializationCode.push("} as const;"); + + module.declarations.push(serializationCode); +} + +function* emitSerializationForType( + ctx: SerializationContext, + type: SerializableType, + contentType: SerializationContentType, + module: Module, + typeName: string +): Iterable { + switch (contentType) { + case "application/json": { + yield* emitJsonSerialization(ctx, type, module, typeName); + break; + } + default: + throw new Error(`Unreachable: serialization content type ${contentType satisfies never}`); + } +} diff --git a/packages/http-server-javascript/src/common/serialization/json.ts b/packages/http-server-javascript/src/common/serialization/json.ts new file mode 100644 index 0000000000..ee50a22255 --- /dev/null +++ b/packages/http-server-javascript/src/common/serialization/json.ts @@ -0,0 +1,420 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { + BooleanLiteral, + IntrinsicType, + ModelProperty, + NoTarget, + NumericLiteral, + StringLiteral, + Type, + compilerAssert, + getEncode, + getProjectedName, + isArrayModelType, + isRecordModelType, + resolveEncodedName, +} from "@typespec/compiler"; +import { getHeaderFieldOptions, getPathParamOptions, getQueryParamOptions } from "@typespec/http"; +import { JsContext, Module } from "../../ctx.js"; +import { parseCase } from "../../util/case.js"; +import { differentiateUnion, writeCodeTree } from "../../util/differentiate.js"; +import { UnimplementedError } from "../../util/error.js"; +import { indent } from "../../util/iter.js"; +import { emitTypeReference, escapeUnsafeChars } from "../reference.js"; +import { SerializableType, SerializationContext, requireSerialization } from "./index.js"; + +/** + * Memoization cache for requiresJsonSerialization. + */ +const _REQUIRES_JSON_SERIALIZATION = new WeakMap(); + +export function requiresJsonSerialization(ctx: JsContext, type: Type): boolean { + if (!isSerializable(type)) return false; + + if (_REQUIRES_JSON_SERIALIZATION.has(type)) { + return _REQUIRES_JSON_SERIALIZATION.get(type)!; + } + + // Assume the type is serializable until proven otherwise, in case this model is encountered recursively. + // This isn't an exactly correct algorithm, but in the recursive case it will at least produce something that + // is correct. + _REQUIRES_JSON_SERIALIZATION.set(type, true); + + let requiresSerialization: boolean; + + switch (type.kind) { + case "Model": { + requiresSerialization = [...type.properties.values()].some((property) => + propertyRequiresJsonSerialization(ctx, property) + ); + break; + } + case "Scalar": { + requiresSerialization = getEncode(ctx.program, type) !== undefined; + break; + } + case "Union": { + requiresSerialization = [...type.variants.values()].some((variant) => + requiresJsonSerialization(ctx, variant) + ); + break; + } + case "ModelProperty": + requiresSerialization = requiresJsonSerialization(ctx, type.type); + break; + } + + _REQUIRES_JSON_SERIALIZATION.set(type, requiresSerialization); + + return requiresSerialization; +} + +function propertyRequiresJsonSerialization(ctx: JsContext, property: ModelProperty): boolean { + return !!( + isHttpMetadata(ctx, property) || + getEncode(ctx.program, property) || + resolveEncodedName(ctx.program, property, "application/json") !== property.name || + getProjectedName(ctx.program, property, "json") || + (isSerializable(property.type) && requiresJsonSerialization(ctx, property.type)) + ); +} + +function isHttpMetadata(ctx: JsContext, property: ModelProperty): boolean { + return ( + getQueryParamOptions(ctx.program, property) !== undefined || + getHeaderFieldOptions(ctx.program, property) !== undefined || + getPathParamOptions(ctx.program, property) !== undefined + ); +} + +function isSerializable(type: Type): type is SerializableType | ModelProperty { + return ( + type.kind === "Model" || + type.kind === "Scalar" || + type.kind === "Union" || + type.kind === "ModelProperty" + ); +} + +export function* emitJsonSerialization( + ctx: SerializationContext, + type: SerializableType, + module: Module, + typeName: string +): Iterable { + yield `toJsonObject(input: ${typeName}): object {`; + yield* indent(emitToJson(ctx, type, module)); + yield `},`; + + yield `fromJsonObject(input: object): ${typeName} {`; + yield* indent(emitFromJson(ctx, type, module)); + yield `},`; +} + +function* emitToJson( + ctx: SerializationContext, + type: SerializableType, + module: Module +): Iterable { + switch (type.kind) { + case "Model": { + yield `return {`; + + for (const property of type.properties.values()) { + const encodedName = + getProjectedName(ctx.program, property, "json") ?? + resolveEncodedName(ctx.program, property, "application/json") ?? + property.name; + + const expr = transposeExpressionToJson( + ctx, + property.type, + `input.${property.name}`, + module + ); + + yield ` ${encodedName}: ${expr},`; + } + + yield `};`; + + return; + } + case "Scalar": { + yield `throw new Error("Unimplemented: scalar JSON serialization");`; + return; + } + case "Union": { + const codeTree = differentiateUnion(ctx, type); + + yield* writeCodeTree(ctx, codeTree, { + subject: "input", + referenceModelProperty(p) { + return "input." + parseCase(p.name).camelCase; + }, + renderResult(type) { + return [`return ${transposeExpressionToJson(ctx, type, "input", module)};`]; + }, + }); + + return; + } + } +} + +function transposeExpressionToJson( + ctx: SerializationContext, + type: Type, + expr: string, + module: Module +): string { + switch (type.kind) { + case "Model": { + if (isArrayModelType(ctx.program, type)) { + const argumentType = type.indexer.value; + + if (requiresJsonSerialization(ctx, argumentType)) { + return `${expr}.map((item) => ${transposeExpressionToJson(ctx, argumentType, "item", module)})`; + } else { + return expr; + } + } else if (isRecordModelType(ctx.program, type)) { + const argumentType = type.indexer.value; + + if (requiresJsonSerialization(ctx, argumentType)) { + return `Object.fromEntries(Object.entries(${expr}).map(([key, value]) => [String(key), ${transposeExpressionToJson( + ctx, + argumentType, + "value", + module + )}]))`; + } else { + return expr; + } + } else if (!requiresJsonSerialization(ctx, type)) { + return expr; + } else { + requireSerialization(ctx, type, "application/json"); + const typeReference = emitTypeReference(ctx, type, NoTarget, module); + + return `${typeReference}.toJsonObject(${expr})`; + } + } + case "Scalar": + return expr; + case "Union": + if (!requiresJsonSerialization(ctx, type)) { + return expr; + } else { + requireSerialization(ctx, type, "application/json"); + const typeReference = emitTypeReference(ctx, type, NoTarget, module, { + altName: "WeirdUnion", + requireDeclaration: true, + }); + + return `${typeReference}.toJsonObject(${expr})`; + } + case "ModelProperty": + return transposeExpressionToJson(ctx, type.type, expr, module); + case "Intrinsic": + switch (type.name) { + case "void": + return "undefined"; + case "null": + return "null"; + case "ErrorType": + compilerAssert(false, "Encountered ErrorType in JSON serialization", type); + return expr; + case "never": + case "unknown": + default: + // Unhandled intrinsics will have been caught during type construction. We'll ignore this and + // just return the expr as-is. + return expr; + } + case "String": + case "Number": + case "Boolean": + return literalToExpr(type); + case "Interface": + case "Enum": + case "EnumMember": + case "TemplateParameter": + case "Namespace": + case "Operation": + case "StringTemplate": + case "StringTemplateSpan": + case "Tuple": + case "UnionVariant": + case "Function": + case "Decorator": + case "FunctionParameter": + case "Object": + case "Projection": + case "ScalarConstructor": + default: + throw new UnimplementedError(`transformJsonExprForType: ${type.kind}`); + } +} + +function literalToExpr(type: StringLiteral | BooleanLiteral | NumericLiteral): string { + switch (type.kind) { + case "String": + return escapeUnsafeChars(JSON.stringify(type.value)); + case "Number": + case "Boolean": + return String(type.value); + } +} + +function* emitFromJson( + ctx: SerializationContext, + type: SerializableType, + module: Module +): Iterable { + switch (type.kind) { + case "Model": { + yield `return {`; + + for (const property of type.properties.values()) { + const encodedName = + getProjectedName(ctx.program, property, "json") ?? + resolveEncodedName(ctx.program, property, "application/json") ?? + property.name; + + const expr = transposeExpressionFromJson( + ctx, + property.type, + `input["${encodedName}"]`, + module + ); + + yield ` ${property.name}: ${expr},`; + } + + yield "};"; + + return; + } + case "Scalar": { + yield `throw new Error("Unimplemented: scalar JSON serialization");`; + return; + } + case "Union": { + const codeTree = differentiateUnion(ctx, type); + + yield* writeCodeTree(ctx, codeTree, { + subject: "input", + referenceModelProperty(p) { + const jsonName = + getProjectedName(ctx.program, p, "json") ?? + resolveEncodedName(ctx.program, p, "application/json") ?? + p.name; + return "input[" + JSON.stringify(jsonName) + "]"; + }, + renderResult(type) { + return [`return ${transposeExpressionFromJson(ctx, type, "input", module)};`]; + }, + }); + + return; + } + } +} + +function transposeExpressionFromJson( + ctx: SerializationContext, + type: Type, + expr: string, + module: Module +): string { + switch (type.kind) { + case "Model": { + if (isArrayModelType(ctx.program, type)) { + const argumentType = type.indexer.value; + + if (requiresJsonSerialization(ctx, argumentType)) { + return `${expr}.map((item) => ${transposeExpressionFromJson(ctx, argumentType, "item", module)})`; + } else { + return expr; + } + } else if (isRecordModelType(ctx.program, type)) { + const argumentType = type.indexer.value; + + if (requiresJsonSerialization(ctx, argumentType)) { + return `Object.fromEntries(Object.entries(${expr}).map(([key, value]) => [key, ${transposeExpressionFromJson( + ctx, + argumentType, + "value", + module + )}]))`; + } else { + return expr; + } + } else if (!requiresJsonSerialization(ctx, type)) { + return `${expr} as ${emitTypeReference(ctx, type, NoTarget, module)}`; + } else { + requireSerialization(ctx, type, "application/json"); + const typeReference = emitTypeReference(ctx, type, NoTarget, module); + + return `${typeReference}.fromJsonObject(${expr})`; + } + } + case "Scalar": + return expr; + case "Union": + if (!requiresJsonSerialization(ctx, type)) { + return expr; + } else { + requireSerialization(ctx, type, "application/json"); + const typeReference = emitTypeReference(ctx, type, NoTarget, module, { + altName: "WeirdUnion", + requireDeclaration: true, + }); + + return `${typeReference}.fromJsonObject(${expr})`; + } + case "ModelProperty": + return transposeExpressionFromJson(ctx, type.type, expr, module); + case "Intrinsic": + switch (type.name) { + case "ErrorType": + throw new Error("UNREACHABLE: ErrorType in JSON deserialization"); + case "void": + return "undefined"; + case "null": + return "null"; + case "never": + case "unknown": + return expr; + default: + throw new Error( + `Unreachable: intrinsic type ${(type satisfies never as IntrinsicType).name}` + ); + } + case "String": + case "Number": + case "Boolean": + return literalToExpr(type); + case "Interface": + case "Enum": + case "EnumMember": + case "TemplateParameter": + case "Namespace": + case "Operation": + case "StringTemplate": + case "StringTemplateSpan": + case "Tuple": + case "UnionVariant": + case "Function": + case "Decorator": + case "FunctionParameter": + case "Object": + case "Projection": + case "ScalarConstructor": + default: + throw new UnimplementedError(`transformJsonExprForType: ${type.kind}`); + } +} diff --git a/packages/http-server-javascript/src/common/union.ts b/packages/http-server-javascript/src/common/union.ts new file mode 100644 index 0000000000..1be1c97727 --- /dev/null +++ b/packages/http-server-javascript/src/common/union.ts @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { Union, UnionVariant } from "@typespec/compiler"; +import { JsContext, Module, PartialUnionSynthetic } from "../ctx.js"; +import { parseCase } from "../util/case.js"; +import { emitDocumentation } from "./documentation.js"; +import { emitTypeReference } from "./reference.js"; + +/** + * Emit an inline union type. This will automatically import any referenced types that are part of the union. + * + * @param ctx - The emitter context. + * @param variants - The variants of the union. + * @param module - The module that this union is written into. + * @returns a string that can be used as a type reference + */ +export function emitUnionType(ctx: JsContext, variants: UnionVariant[], module: Module): string { + // Treat empty unions as never so that we always return a good type reference here. + if (variants.length === 0) return "never"; + + const variantTypes: string[] = []; + + for (const [_, v] of variants.entries()) { + const name = emitTypeReference(ctx, v.type, v, module); + + variantTypes.push(name); + + // if (isImportableType(ctx, v.type)) { + // module.imports.push({ + // binder: [name], + // from: createOrGetModuleForNamespace(ctx, v.type.namespace!), + // }); + // } + } + + return variantTypes.join(" | "); +} + +/** + * Emits a union type declaration as an alias. + * + * This is rare in TypeScript, but may occur in some niche cases where an alias is desirable. + * + * @param ctx - The emitter context. + * @param union - The union to emit. + * @param module - The module that this union declaration is written into. + * @param altName - An alternative name to use for the union if it is not named. + */ +export function* emitUnion( + ctx: JsContext, + union: Union | PartialUnionSynthetic, + module: Module, + altName?: string +): Iterable { + const name = union.name ? parseCase(union.name).pascalCase : altName; + const isPartialSynthetic = union.kind === "partialUnion"; + + if (name === undefined) { + throw new Error("Internal Error: Union name is undefined"); + } + + if (!isPartialSynthetic) yield* emitDocumentation(ctx, union); + + const variants = isPartialSynthetic + ? union.variants.map((v) => [v.name, v] as const) + : union.variants.entries(); + + const variantTypes = [...variants].map(([_, v]) => + emitTypeReference(ctx, v.type, v, module, { + altName: name + parseCase(String(v.name)).pascalCase, + }) + ); + + yield `export type ${name} = ${variantTypes.join(" | ")};`; +} diff --git a/packages/http-server-javascript/src/ctx.ts b/packages/http-server-javascript/src/ctx.ts new file mode 100644 index 0000000000..02ab155923 --- /dev/null +++ b/packages/http-server-javascript/src/ctx.ts @@ -0,0 +1,386 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { + Enum, + Interface, + Model, + Namespace, + Program, + Scalar, + Service, + Type, + Union, + UnionVariant, + compilerAssert, + isArrayModelType, + isRecordModelType, +} from "@typespec/compiler"; +import { emitDeclaration } from "./common/declaration.js"; +import { createOrGetModuleForNamespace } from "./common/namespace.js"; +import { SerializableType } from "./common/serialization/index.js"; +import { emitUnion } from "./common/union.js"; +import { JsEmitterOptions } from "./lib.js"; +import { OnceQueue } from "./util/once-queue.js"; + +export type DeclarationType = Model | Enum | Union | Interface | Scalar; + +/** + * Determines whether or not a type is importable into a JavaScript module. + * + * i.e. whether or not it is declared as a named symbol within the module. + * + * In TypeScript, unions are rendered inline, so they are not ordinarily + * considered importable. + * + * @param ctx - The JS emitter context. + * @param t - the type to test + * @returns `true` if the type is an importable declaration, `false` otherwise. + */ +export function isImportableType(ctx: JsContext, t: Type): t is DeclarationType { + return ( + (t.kind === "Model" && + !isArrayModelType(ctx.program, t) && + !isRecordModelType(ctx.program, t)) || + t.kind === "Enum" || + t.kind === "Interface" + ); +} + +/** + * Stores stateful information consumed and modified by the JavaScript server + * emitter. + */ +export interface JsContext { + /** + * The TypeSpec Program that this emitter instance operates over. + */ + program: Program; + + /** + * The emitter options. + */ + options: JsEmitterOptions; + + /** + * The global (root) namespace of the program. + */ + globalNamespace: Namespace; + + /** + * The service definition to use for emit. + */ + service: Service; + + /** + * A queue of all types to be included in the emit tree. This queue + * automatically deduplicates types, so if a type is added multiple times it + * will only be visited once. + */ + typeQueue: OnceQueue; + /** + * A list of synthetic types (anonymous types that are given names) that are + * included in the emit tree. + */ + synthetics: Synthetic[]; + /** + * A cache of names given to synthetic types. These names may be used to avoid + * emitting the same synthetic type multiple times. + */ + syntheticNames: Map; + + /** + * The root module for the emit tree. + */ + rootModule: Module; + + /** + * A map relating each namespace to the module that contains its declarations. + * + * @see createOrGetModuleForNamespace + */ + namespaceModules: Map; + /** + * The module that contains all synthetic types. + */ + syntheticModule: Module; + /** + * The root module for all named declarations of types referenced by the program. + */ + modelsModule: Module; + /** + * The module within `models` that maps to the global namespace. + */ + globalNamespaceModule: Module; + + /** + * A map of all types that require serialization code to the formats they require. + */ + serializations: OnceQueue; +} + +/** + * A synthetic type that is not directly represented with a name in the TypeSpec program. + */ +export type Synthetic = AnonymousSynthetic | PartialUnionSynthetic; + +/** + * An ordinary, anonymous type that is given a name. + */ +export interface AnonymousSynthetic { + kind: "anonymous"; + name: string; + underlying: DeclarationType; +} + +/** + * A partial union with a name for the given variants. + */ +export interface PartialUnionSynthetic { + kind: "partialUnion"; + name: string; + variants: UnionVariant[]; +} + +/** + * Adds all pending declarations from the type queue to the module tree. + * + * The JavaScript emitter is lazy, and sometimes emitter components may visit + * types that are not yet declared. This function ensures that all types + * reachable from existing declarations are complete. + * + * @param ctx - The JavaScript emitter context. + */ +export function completePendingDeclarations(ctx: JsContext): void { + // Add all pending declarations to the module tree. + while (!ctx.typeQueue.isEmpty() || ctx.synthetics.length > 0) { + while (!ctx.typeQueue.isEmpty()) { + const type = ctx.typeQueue.take()!; + + compilerAssert(type.namespace !== undefined, "no namespace for declaration type", type); + + const module = createOrGetModuleForNamespace(ctx, type.namespace); + + module.declarations.push([...emitDeclaration(ctx, type, module)]); + } + + while (ctx.synthetics.length > 0) { + const synthetic = ctx.synthetics.shift()!; + + switch (synthetic.kind) { + case "anonymous": { + ctx.syntheticModule.declarations.push([ + ...emitDeclaration(ctx, synthetic.underlying, ctx.syntheticModule, synthetic.name), + ]); + break; + } + case "partialUnion": { + ctx.syntheticModule.declarations.push([ + ...emitUnion(ctx, synthetic, ctx.syntheticModule, synthetic.name), + ]); + break; + } + } + } + } +} + +// #region Module + +/** + * A declaration within a module. This may be a string (i.e. a line), an array of + * strings (emitted as multiple lines), or another module (emitted as a nested module). + */ +export type ModuleBodyDeclaration = string[] | string | Module; + +/** + * A type-guard that checks whether or not a given value is a module. + * @returns `true` if the value is a module, `false` otherwise. + */ +export function isModule(value: unknown): value is Module { + return ( + typeof value === "object" && + value !== null && + "declarations" in value && + Array.isArray(value.declarations) + ); +} + +/** + * Creates a new module with the given name and attaches it to the parent module. + * + * Optionally, a namespace may be associated with the module. This namespace is + * _NOT_ stored in the context (this function does not use the JsContext), and + * is only stored as metadata within the module. To associate a module with a + * namespace inside the context, use `createOrGetModuleForNamespace`. + * + * The module is automatically declared as a declaration within its parent + * module. + * + * @param name - The name of the module. + * @param parent - The parent module to attach the new module to. + * @param namespace - an optional TypeSpec Namespace to associate with the module + * @returns the newly created module + */ +export function createModule(name: string, parent: Module, namespace?: Namespace): Module { + const self = { + name, + cursor: parent.cursor.enter(name), + namespace, + + imports: [], + declarations: [], + }; + + parent.declarations.push(self); + + return self; +} + +/** + * The type of a binding for an import statement. Either: + * + * - A string beginning with `* as` followed by the name of the binding, which + * imports all exports from the module as a single object. + * - An array of strings, each of which is a named import from the module. + */ +export type ImportBinder = `* as ${string}` | string[]; + +/** + * An object representing a ECMAScript module import declaration. + */ +export interface Import { + /** + * The binder to define the import as. + */ + binder: ImportBinder; + /** + * Where to import from. This is either a literal string (which will be used verbatim), or Module object, which will + * be resolved to a relative file path. + */ + from: Module | string; +} + +/** + * An output module within the module tree. + */ +export interface Module { + /** + * The name of the module, which should be suitable for use as the basename of + * a file and as an identifier. + */ + name: string; + /** + * The cursor for the module, which assists navigation and relative path + * computation between modules. + */ + readonly cursor: PathCursor; + + /** + * An optional namespace for the module. This is not used by the code writer, + * but is used to track dependencies between TypeSpec namespaces and create + * imports between them. + */ + namespace?: Namespace; + + /** + * A list of imports that the module requires. + */ + imports: Import[]; + + /** + * A list of declarations within the module. + */ + declarations: ModuleBodyDeclaration[]; +} + +// #endregion + +/** + * A cursor that assists in navigating the module tree and computing relative + * paths between modules. + */ +export interface PathCursor { + /** + * The path to this cursor. This is an array of strings that represents the + * path from the root module to another module. + */ + readonly path: string[]; + + /** + * The parent cursor of this cursor (equivalent to moving up one level in the + * module tree). If this cursor is the root cursor, this property is `undefined`. + */ + readonly parent: PathCursor | undefined; + + /** + * Returns a new cursor that includes the given path components appended to + * this cursor's path. + * + * @param path - the path to append to this cursor + */ + enter(...path: string[]): PathCursor; + + /** + * Computes a relative path from this cursor to another cursor, using the string `up` + * to navigate upwards one level in the path. This is similar to `path.relative` when + * working with file paths, but operates over PathCursor objects. + * + * @param to - the cursor to compute the path to + * @param up - the string to use to move up a level in the path (defaults to "..") + */ + relativePath(to: PathCursor, up?: string): string[]; +} + +/** + * Create a new cursor with the given path. + * + * @param base - the base path of this cursor + * @returns + */ +export function createPathCursor(...base: string[]): PathCursor { + const self: PathCursor = { + path: base, + + get parent() { + return self.path.length === 0 ? undefined : createPathCursor(...self.path.slice(0, -1)); + }, + + enter(...path: string[]) { + return createPathCursor(...self.path, ...path); + }, + + relativePath(to: PathCursor, up: string = ".."): string[] { + const commonPrefix = getCommonPrefix(self.path, to.path); + + const outputPath = []; + + for (let i = 0; i < self.path.length - commonPrefix.length; i++) { + outputPath.push(up); + } + + outputPath.push(...to.path.slice(commonPrefix.length)); + + return outputPath; + }, + }; + + return self; +} + +/** + * Compute the common prefix of two paths. + */ +function getCommonPrefix(a: string[], b: string[]): string[] { + const prefix = []; + + for (let i = 0; i < Math.min(a.length, b.length); i++) { + if (a[i] !== b[i]) { + break; + } + + prefix.push(a[i]); + } + + return prefix; +} diff --git a/packages/http-server-javascript/src/helpers/router.ts b/packages/http-server-javascript/src/helpers/router.ts new file mode 100644 index 0000000000..84a4c2ab44 --- /dev/null +++ b/packages/http-server-javascript/src/helpers/router.ts @@ -0,0 +1,243 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import type * as http from "node:http"; + +/** A policy that can be applied to a route or a set of routes. */ +export interface Policy { + /** Optional policy name. */ + name?: string; + + /** + * Applies the policy to the request. + * + * Policies _MUST_ call `next()` to pass the request to the next policy _OR_ call `response.end()` to terminate, + * and _MUST NOT_ do both. + * + * If the policy passes a `request` object to `next()`, that request object will be used instead of the original + * request object for the remainder of the policy chain. If the policy does _not_ pass a request object to `next()`, + * the same object that was passed to this policy will be forwarded to the next policy automatically. + * + * @param request - The incoming HTTP request. + * @param response - The outgoing HTTP response. + * @param next - Calls the next policy in the chain. + */ + ( + request: http.IncomingMessage, + response: http.ServerResponse, + next: (request?: http.IncomingMessage) => void + ): void; +} + +/** + * Create a function from a chain of policies. + * + * This returns a single function that will apply the policy chain and eventually call the provided `next()` function. + * + * @param name - The name to give to the policy chain function. + * @param policies - The policies to apply to the request. + * @param out - The function to call after the policies have been applied. + */ +export function createPolicyChain< + Out extends ( + ctx: HttpContext, + request: http.IncomingMessage, + response: http.ServerResponse, + ...rest: any[] + ) => void, +>(name: string, policies: Policy[], out: Out): Out { + let outParams: any[]; + if (policies.length === 0) { + return out; + } + + function applyPolicy( + ctx: HttpContext, + request: http.IncomingMessage, + response: http.ServerResponse, + index: number + ) { + if (index >= policies.length) { + return out(ctx, request, response, ...outParams); + } + + policies[index](request, response, function nextPolicy(nextRequest) { + applyPolicy(ctx, nextRequest ?? request, response, index + 1); + }); + } + + return { + [name]( + ctx: HttpContext, + request: http.IncomingMessage, + response: http.ServerResponse, + ...params: any[] + ) { + outParams = params; + applyPolicy(ctx, request, response, 0); + }, + }[name] as Out; +} + +/** + * The type of an error encountered during request validation. + */ +export type ValidationError = string; + +/** + * An object specifying the policies for a given route configuration. + */ +export type RoutePolicies = { + [Interface in keyof RouteConfig]?: { + before?: Policy[]; + after?: Policy[]; + methodPolicies?: { + [Method in keyof RouteConfig[Interface]]?: Policy[]; + }; + }; +}; + +/** + * Create a policy chain for a given route. + * + * This function calls `createPolicyChain` internally and orders the policies based on the route configuration. + * + * Interface-level `before` policies run first, then method-level policies, then Interface-level `after` policies. + * + * @param name - The name to give to the policy chain function. + * @param routePolicies - The policies to apply to the routes (part of the route configuration). + * @param interfaceName - The name of the interface that the route belongs to. + * @param methodName - The name of the method that the route corresponds to. + * @param out - The function to call after the policies have been applied. + */ +export function createPolicyChainForRoute< + RouteConfig extends { [k: string]: object }, + InterfaceName extends keyof RouteConfig, + Out extends ( + ctx: HttpContext, + request: http.IncomingMessage, + response: http.ServerResponse, + ...rest: any[] + ) => void, +>( + name: string, + routePolicies: RoutePolicies, + interfaceName: InterfaceName, + methodName: keyof RouteConfig[InterfaceName], + out: Out +): Out { + return createPolicyChain( + name, + [ + ...(routePolicies[interfaceName]?.before ?? []), + ...(routePolicies[interfaceName]?.methodPolicies?.[methodName] ?? []), + ...(routePolicies[interfaceName]?.after ?? []), + ], + out + ); +} + +/** + * Options for configuring a router with additional functionality. + */ +export interface RouterOptions< + RouteConfig extends { [k: string]: object } = { [k: string]: object }, +> { + /** + * The base path of the router. + * + * This should include any leading slashes, but not a trailing slash, and should not include any component + * of the URL authority (e.g. the scheme, host, or port). + * + * Defaults to "". + */ + basePath?: string; + + /** + * A list of policies to apply to all routes _before_ routing. + * + * Policies are applied in the order they are listed. + * + * By default, the policy list is empty. + * + * Policies _MUST_ call `next()` to pass the request to the next policy _OR_ call `response.end()` to terminate + * the response and _MUST NOT_ do both. + */ + policies?: Policy[]; + + /** + * A record of policies that apply to specific routes. + * + * The policies are provided as a nested record where the keys are the business-logic interface names, and the values + * are records of the method names in the given interface and the policies that apply to them. + * + * By default, no additional policies are applied to the routes. + * + * Policies _MUST_ call `next()` to pass the request to the next policy _OR_ call `response.end()` to terminate + * the response and _MUST NOT_ do both. + */ + routePolicies?: RoutePolicies; + + /** + * A handler for requests that do not match any known route and method. + * + * If this handler is not provided, a 404 Not Found response with a text body will be returned. + * + * You _MUST_ call `response.end()` to terminate the response. + * + * This handler is unreachable when using the Express middleware, as it will forward non-matching requests to the + * next middleware layer in the stack. + * + * @param request - The incoming HTTP request. + * @param response - The outgoing HTTP response. + */ + onRequestNotFound?: (request: http.IncomingMessage, response: http.ServerResponse) => void; + + /** + * A handler for requests that fail to validate inputs. + * + * If this handler is not provided, a 400 Bad Request response with a JSON body containing some basic information + * about the error will be returned to the client. + * + * You _MUST_ call `response.end()` to terminate the response. + * + * @param request - The incoming HTTP request. + * @param response - The outgoing HTTP response. + * @param route - The route that was matched. + * @param error - The validation error that was thrown. + */ + onInvalidRequest?: ( + request: http.IncomingMessage, + response: http.ServerResponse, + route: string, + error: ValidationError + ) => void; + + /** + * A handler for requests that throw an error during processing. + * + * If this handler is not provided, a 500 Internal Server Error response with a text body and no error details will be + * returned to the client. + * + * You _MUST_ call `response.end()` to terminate the response. + * + * If this handler itself throws an Error, the router will respond with a 500 Internal Server Error + * + * @param error - The error that was thrown. + * @param request - The incoming HTTP request. + * @param response - The outgoing HTTP response. + */ + onInternalError?( + error: unknown, + request: http.IncomingMessage, + response: http.ServerResponse + ): void; +} + +/** Context information for operations carried over the HTTP protocol. */ +export interface HttpContext { + /** The incoming request to the server. */ + request: http.IncomingMessage; + /** The outgoing response object. */ + response: http.ServerResponse; +} diff --git a/packages/http-server-javascript/src/http/index.ts b/packages/http-server-javascript/src/http/index.ts new file mode 100644 index 0000000000..7b4b7f4e2e --- /dev/null +++ b/packages/http-server-javascript/src/http/index.ts @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { NoTarget } from "@typespec/compiler"; +import { HttpServer, HttpService, getHttpService, getServers } from "@typespec/http"; +import { JsContext, Module, createModule } from "../ctx.js"; +import { reportDiagnostic } from "../lib.js"; +import { emitRawServer } from "./server/index.js"; +import { emitRouter } from "./server/router.js"; + +/** + * Additional context items used by the HTTP emitter. + */ +export interface HttpContext extends JsContext { + /** + * The HTTP-level representation of the service. + */ + httpService: HttpService; + /** + * The root module for HTTP-specific code. + */ + httpModule: Module; + /** + * The server definitions of the service (\@server decorator) + */ + servers: HttpServer[]; +} + +/** + * Emits bindings for the service to be carried over the HTTP protocol. + */ +export async function emitHttp(ctx: JsContext) { + const [httpService, diagnostics] = getHttpService(ctx.program, ctx.service.type); + + const diagnosticsAreError = diagnostics.some((d) => d.severity === "error"); + + if (diagnosticsAreError) { + reportDiagnostic(ctx.program, { + code: "http-emit-disabled", + target: NoTarget, + messageId: "default", + }); + return; + } + + const servers = getServers(ctx.program, ctx.service.type) ?? []; + + const httpModule = createModule("http", ctx.rootModule); + + const httpContext: HttpContext = { + ...ctx, + httpService, + httpModule, + servers, + }; + + const operationsModule = createModule("operations", httpModule); + + const serverRawModule = emitRawServer(httpContext, operationsModule); + emitRouter(httpContext, httpService, serverRawModule); +} diff --git a/packages/http-server-javascript/src/http/server/index.ts b/packages/http-server-javascript/src/http/server/index.ts new file mode 100644 index 0000000000..82a6de82ee --- /dev/null +++ b/packages/http-server-javascript/src/http/server/index.ts @@ -0,0 +1,434 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { ModelProperty, Type } from "@typespec/compiler"; +import { + HttpOperation, + HttpOperationParameter, + getHeaderFieldName, + isBody, + isHeader, + isStatusCode, +} from "@typespec/http"; +import { createOrGetModuleForNamespace } from "../../common/namespace.js"; +import { emitTypeReference, isValueLiteralType } from "../../common/reference.js"; +import { parseTemplateForScalar } from "../../common/scalar.js"; +import { + SerializableType, + isSerializationRequired, + requireSerialization, +} from "../../common/serialization/index.js"; +import { Module, completePendingDeclarations, createModule } from "../../ctx.js"; +import { parseCase } from "../../util/case.js"; +import { UnimplementedError } from "../../util/error.js"; +import { getAllProperties } from "../../util/extends.js"; +import { bifilter, indent } from "../../util/iter.js"; +import { keywordSafe } from "../../util/keywords.js"; +import { HttpContext } from "../index.js"; + +import { module as routerHelpers } from "../../../generated-defs/helpers/router.js"; +import { differentiateUnion, writeCodeTree } from "../../util/differentiate.js"; + +const DEFAULT_CONTENT_TYPE = "application/json"; + +/** + * Emits raw operations for handling incoming server requests. + * + * @param ctx - The HTTP emitter context. + * @param operationsModule - The module to emit the operations into. + * @returns the module containing the raw server operations. + */ +export function emitRawServer(ctx: HttpContext, operationsModule: Module): Module { + const serverRawModule = createModule("server-raw", operationsModule); + + serverRawModule.imports.push({ + binder: "* as http", + from: "node:http", + }); + + serverRawModule.imports.push({ + binder: ["HttpContext"], + from: routerHelpers, + }); + + for (const operation of ctx.httpService.operations) { + serverRawModule.declarations.push([...emitRawServerOperation(ctx, operation, serverRawModule)]); + } + + return serverRawModule; +} + +/** + * Emit a raw operation handler for a specific operation. + * @param ctx - The HTTP emitter context. + * @param operation - The operation to create a handler for. + * @param module - The module that the handler will be written to. + */ +function* emitRawServerOperation( + ctx: HttpContext, + operation: HttpOperation, + module: Module +): Iterable { + const op = operation.operation; + const operationNameCase = parseCase(op.name); + + const container = op.interface ?? op.namespace!; + const containerNameCase = parseCase(container.name); + + module.imports.push({ + binder: [containerNameCase.pascalCase], + from: createOrGetModuleForNamespace(ctx, container.namespace!), + }); + + completePendingDeclarations(ctx); + + const pathParameters = operation.parameters.parameters.filter(function isPathParameter(param) { + return param.type === "path"; + }) as Extract[]; + + const functionName = keywordSafe(containerNameCase.snakeCase + "_" + operationNameCase.snakeCase); + + yield `export async function ${functionName}(`; + yield ` ctx: HttpContext,`; + yield ` request: http.IncomingMessage,`; + yield ` response: http.ServerResponse,`; + yield ` operations: ${containerNameCase.pascalCase},`; + + for (const pathParam of pathParameters) { + yield ` ${parseCase(pathParam.param.name).camelCase}: string,`; + } + + yield "): Promise {"; + + const [_, parameters] = bifilter(op.parameters.properties.values(), (param) => + isValueLiteralType(param.type) + ); + + const queryParams: Extract[] = []; + + const parsedParams = new Set(); + + for (const parameter of operation.parameters.parameters) { + const resolvedParameter = + parameter.param.type.kind === "ModelProperty" ? parameter.param.type : parameter.param; + switch (parameter.type) { + case "header": + yield* indent(emitHeaderParamBinding(ctx, parameter)); + break; + case "query": + queryParams.push(parameter); + parsedParams.add(resolvedParameter); + break; + case "path": + // Already handled above. + parsedParams.add(resolvedParameter); + break; + default: + throw new Error( + `UNREACHABLE: parameter type ${ + (parameter satisfies never as HttpOperationParameter).type + }` + ); + } + } + + if (queryParams.length > 0) { + yield ` const __query_params = new URLSearchParams(request.url!.split("?", 1)[1] ?? "");`; + yield ""; + } + + for (const qp of queryParams) { + yield* indent(emitQueryParamBinding(ctx, qp)); + } + + const bodyFields = new Map( + operation.parameters.body && operation.parameters.body.type.kind === "Model" + ? getAllProperties(operation.parameters.body.type).map((p) => [p.name, p.type] as const) + : [] + ); + + let bodyName: string | undefined = undefined; + + if (operation.parameters.body) { + const body = operation.parameters.body; + + if (body.contentTypes.length > 1) { + throw new UnimplementedError("dynamic request content type"); + } + + const contentType = body.contentTypes[0] ?? DEFAULT_CONTENT_TYPE; + + const defaultBodyTypeName = operationNameCase.pascalCase + "RequestBody"; + + if (body.bodyKind === "multipart") { + throw new UnimplementedError(`new form of multipart requests`); + } + + const bodyNameCase = parseCase(body.property?.name ?? defaultBodyTypeName); + + const bodyTypeName = emitTypeReference( + ctx, + body.type, + body.property?.type ?? operation.operation.node, + module, + { altName: defaultBodyTypeName } + ); + + bodyName = bodyNameCase.camelCase; + + yield ` if (!request.headers["content-type"]?.startsWith(${JSON.stringify(contentType)})) {`; + yield ` throw new Error(\`Invalid Request: expected content-type '${contentType}' but got '\${request.headers["content-type"]?.split(";", 2)[0]}'.\`)`; + yield " }"; + yield ""; + + switch (contentType) { + case "application/merge-patch+json": + case "application/json": { + requireSerialization(ctx, body.type as SerializableType, "application/json"); + yield ` const ${bodyName} = await new Promise(function parse${bodyNameCase.pascalCase}(resolve, reject) {`; + yield ` const chunks: Array = [];`; + yield ` request.on("data", function appendChunk(chunk) { chunks.push(chunk); });`; + yield ` request.on("end", function finalize() {`; + yield ` resolve(JSON.parse(Buffer.concat(chunks).toString()));`; + yield ` });`; + yield ` }) as ${bodyTypeName};`; + yield ""; + + break; + } + case "multipart/form-data": + yield `const ${bodyName} = await new Promise(function parse${bodyNameCase.pascalCase}MultipartRequest(resolve, reject) {`; + yield ` const boundary = request.headers["content-type"]?.split(";").find((s) => s.includes("boundary="))?.split("=", 2)[1];`; + yield ` if (!boundary) {`; + yield ` return reject("Invalid request: missing boundary in content-type.");`; + yield ` }`; + yield ""; + yield ` const chunks: Array = [];`; + yield ` request.on("data", function appendChunk(chunk) { chunks.push(chunk); });`; + yield ` request.on("end", function finalize() {`; + yield ` const text = Buffer.concat(chunks).toString();`; + yield ` const parts = text.split(boundary).slice(1, -1);`; + yield ` const fields: { [k: string]: any } = {};`; + yield ""; + yield ` for (const part of parts) {`; + yield ` const [headerText, body] = part.split("\\r\\n\\r\\n", 2);`; + yield " const headers = Object.fromEntries("; + yield ` headerText.split("\\r\\n").map((line) => line.split(": ", 2))`; + yield " ) as { [k: string]: string };"; + yield ` const name = headers["Content-Disposition"].split("name=\\"")[1].split("\\"")[0];`; + yield ` const contentType = headers["Content-Type"] ?? "text/plain";`; + yield ""; + yield ` switch (contentType) {`; + yield ` case "application/json":`; + yield ` fields[name] = JSON.parse(body);`; + yield ` break;`; + yield ` case "application/octet-stream":`; + yield ` fields[name] = Buffer.from(body, "utf-8");`; + yield ` break;`; + yield ` default:`; + yield ` fields[name] = body;`; + yield ` }`; + yield ` }`; + yield ""; + yield ` resolve(fields as ${bodyTypeName});`; + yield ` });`; + yield `}) as ${bodyTypeName};`; + break; + default: + throw new UnimplementedError(`request deserialization for content-type: '${contentType}'`); + } + + yield ""; + } + + let hasOptions = false; + const optionalParams = new Map(); + + const requiredParams = []; + + for (const param of parameters) { + let paramBaseExpression; + const paramNameCase = parseCase(param.name); + const isBodyField = bodyFields.has(param.name) && bodyFields.get(param.name) === param.type; + if (isBodyField) { + paramBaseExpression = `${bodyName}.${paramNameCase.camelCase}`; + } else { + const resolvedParameter = param.type.kind === "ModelProperty" ? param.type : param; + + paramBaseExpression = + resolvedParameter.type.kind === "Scalar" && parsedParams.has(resolvedParameter) + ? parseTemplateForScalar(ctx, resolvedParameter.type).replace( + "{}", + paramNameCase.camelCase + ) + : paramNameCase.camelCase; + } + + if (param.optional) { + hasOptions = true; + optionalParams.set(paramNameCase.camelCase, paramBaseExpression); + } else { + requiredParams.push(paramBaseExpression); + } + } + + const paramLines = requiredParams.map((p) => `${p},`); + + if (hasOptions) { + paramLines.push( + `{ ${[...optionalParams.entries()].map(([name, expr]) => `${name}: ${expr},`)} }` + ); + } + + yield ` const result = await operations.${operationNameCase.camelCase}(ctx, `; + yield* indent(indent(paramLines)); + yield ` );`, yield ""; + + yield* indent(emitResultProcessing(ctx, op.returnType, module)); + + yield "}"; + + yield ""; +} + +/** + * Emit the result-processing code for an operation. + * + * This code handles writing the result of calling the business logic layer to the HTTP response object. + * + * @param ctx - The HTTP emitter context. + * @param t - The return type of the operation. + * @param module - The module that the result processing code will be written to. + */ +function* emitResultProcessing(ctx: HttpContext, t: Type, module: Module): Iterable { + if (t.kind !== "Union") { + // Single target type + yield* emitResultProcessingForType(ctx, t, module); + } else { + const codeTree = differentiateUnion(ctx, t); + + yield* writeCodeTree(ctx, codeTree, { + subject: "result", + referenceModelProperty(p) { + return "result." + parseCase(p.name).camelCase; + }, + // We mapped the output directly in the code tree input, so we can just return it. + renderResult: (t) => emitResultProcessingForType(ctx, t, module), + }); + } +} + +/** + * Emit the result-processing code for a single response type. + * + * @param ctx - The HTTP emitter context. + * @param target - The target type to emit processing code for. + * @param module - The module that the result processing code will be written to. + */ +function* emitResultProcessingForType( + ctx: HttpContext, + target: Type, + module: Module +): Iterable { + if (target.kind !== "Model") { + throw new UnimplementedError(`result processing for type kind '${target.kind}'`); + } + + const body = [...target.properties.values()].find((p) => isBody(ctx.program, p)); + + for (const property of target.properties.values()) { + if (isHeader(ctx.program, property)) { + const headerName = getHeaderFieldName(ctx.program, property); + yield `response.setHeader(${JSON.stringify(headerName.toLowerCase())}, result.${parseCase(property.name).camelCase});`; + if (!body) yield `delete (result as any).${parseCase(property.name).camelCase};`; + } else if (isStatusCode(ctx.program, property)) { + yield `response.statusCode = result.${parseCase(property.name).camelCase};`; + if (!body) yield `delete (result as any).${parseCase(property.name).camelCase};`; + } + } + + const allMetadataIsRemoved = + !body && + [...target.properties.values()].every((p) => { + return isHeader(ctx.program, p) || isStatusCode(ctx.program, p); + }); + + if (body) { + const bodyCase = parseCase(body.name); + const serializationRequired = isSerializationRequired(ctx, body.type, "application/json"); + requireSerialization(ctx, body.type, "application/json"); + if (serializationRequired) { + const typeReference = emitTypeReference(ctx, body.type, body, module, { + requireDeclaration: true, + }); + yield `response.end(JSON.stringify(${typeReference}.toJsonObject(result.${bodyCase.camelCase})))`; + } else { + yield `response.end(JSON.stringify(result.${bodyCase.camelCase}));`; + } + } else { + if (allMetadataIsRemoved) { + yield `response.end();`; + } else { + const serializationRequired = isSerializationRequired(ctx, target, "application/json"); + requireSerialization(ctx, target, "application/json"); + if (serializationRequired) { + const typeReference = emitTypeReference(ctx, target, target, module, { + requireDeclaration: true, + }); + yield `response.end(JSON.stringify(${typeReference}.toJsonObject(result as ${typeReference})));`; + } else { + yield `response.end(JSON.stringify(result));`; + } + } + } +} + +/** + * Emit code that binds a given header parameter to a variable. + * + * If the parameter is not optional, this will also emit a test to ensure that the parameter is present. + * + * @param ctx - The HTTP emitter context. + * @param parameter - The header parameter to bind. + */ +function* emitHeaderParamBinding( + ctx: HttpContext, + parameter: Extract +): Iterable { + const nameCase = parseCase(parameter.param.name); + + yield `const ${nameCase.camelCase} = request.headers[${JSON.stringify(parameter.name)}];`; + + if (!parameter.param.optional) { + yield `if (${nameCase.camelCase} === undefined) {`; + // prettier-ignore + yield ` throw new Error("Invalid request: missing required header '${parameter.name}'.");`; + yield "}"; + yield ""; + } +} + +/** + * Emit code that binds a given query parameter to a variable. + * + * If the parameter is not optional, this will also emit a test to ensure that the parameter is present. + * + * @param ctx - The HTTP emitter context + * @param parameter - The query parameter to bind + */ +function* emitQueryParamBinding( + ctx: HttpContext, + parameter: Extract +): Iterable { + const nameCase = parseCase(parameter.param.name); + + yield `const ${nameCase.camelCase} = __query_params.get(${JSON.stringify(parameter.name)});`; + + if (!parameter.param.optional) { + yield `if (${nameCase.camelCase} === null) {`; + // prettier-ignore + yield ` throw new Error("Invalid request: missing required query parameter '${parameter.name}'.");`; + yield "}"; + yield ""; + } +} diff --git a/packages/http-server-javascript/src/http/server/router.ts b/packages/http-server-javascript/src/http/server/router.ts new file mode 100644 index 0000000000..6fa8b92e76 --- /dev/null +++ b/packages/http-server-javascript/src/http/server/router.ts @@ -0,0 +1,632 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { Operation, Type } from "@typespec/compiler"; +import { + HttpOperation, + HttpService, + HttpVerb, + OperationContainer, + getHttpOperation, +} from "@typespec/http"; +import { + createOrGetModuleForNamespace, + emitNamespaceInterfaceReference, +} from "../../common/namespace.js"; +import { emitTypeReference } from "../../common/reference.js"; +import { Module, createModule } from "../../ctx.js"; +import { ReCase, parseCase } from "../../util/case.js"; +import { bifilter, indent } from "../../util/iter.js"; +import { keywordSafe } from "../../util/keywords.js"; +import { HttpContext } from "../index.js"; + +import { module as routerHelper } from "../../../generated-defs/helpers/router.js"; +import { reportDiagnostic } from "../../lib.js"; +import { UnimplementedError } from "../../util/error.js"; + +/** + * Emit a router for the HTTP operations defined in a given service. + * + * The generated router will use optimal prefix matching to dispatch requests to the appropriate underlying + * implementation using the raw server. + * + * @param ctx - The emitter context. + * @param service - The HTTP service to emit a router for. + * @param serverRawModule - The module that contains the raw server implementation. + */ +export function emitRouter(ctx: HttpContext, service: HttpService, serverRawModule: Module) { + const routerModule = createModule("router", ctx.httpModule); + + const routeTree = createRouteTree(ctx, service); + + routerModule.imports.push({ + binder: "* as http", + from: "node:http", + }); + + routerModule.imports.push({ + binder: "* as serverRaw", + from: serverRawModule, + }); + + routerModule.declarations.push([...emitRouterDefinition(ctx, service, routeTree, routerModule)]); +} + +/** + * Writes the code for a router of a given service. + * + * @param ctx - The emitter context. + * @param service - The HTTP service to emit a router for. + * @param routeTree - The service's route tree. + * @param module - The module we're writing to. + */ +function* emitRouterDefinition( + ctx: HttpContext, + service: HttpService, + routeTree: RouteTree, + module: Module +): Iterable { + const routerName = parseCase(service.namespace.name).pascalCase + "Router"; + + const uniqueContainers = new Set(service.operations.map((operation) => operation.container)); + + const backends = new Map(); + + for (const container of uniqueContainers) { + const param = parseCase(container.name); + + const traitConstraint = + container.kind === "Namespace" + ? emitNamespaceInterfaceReference(ctx, container, module) + : emitTypeReference(ctx, container, container, module); + + module.imports.push({ + binder: [param.pascalCase], + from: createOrGetModuleForNamespace(ctx, container.namespace!), + }); + + backends.set(container, [param, traitConstraint]); + } + + module.imports.push({ + binder: ["RouterOptions", "createPolicyChain", "createPolicyChainForRoute", "HttpContext"], + from: routerHelper, + }); + + yield `export interface ${routerName} {`; + yield ` /**`; + yield ` * Dispatches the request to the appropriate service based on the request path.`; + yield ` *`; + yield ` * This member function may be used directly as a handler for a Node HTTP server.`; + yield ` *`; + yield ` * @param request - The incoming HTTP request.`; + yield ` * @param response - The outgoing HTTP response.`; + yield ` */`; + yield ` dispatch(request: http.IncomingMessage, response: http.ServerResponse): void;`; + + if (ctx.options.express) { + yield ""; + yield ` /**`; + yield ` * An Express middleware function that dispatches the request to the appropriate service based on the request path.`; + yield ` *`; + yield ` * This member function may be used directly as an application-level middleware function in an Express app.`; + yield ` *`; + yield ` * If the router does not match a route, it will call the \`next\` middleware registered with the application,`; + yield ` * so it is sensible to insert this middleware at the beginning of the middleware stack.`; + yield ` *`; + yield ` * @param req - The incoming HTTP request.`; + yield ` * @param res - The outgoing HTTP response.`; + yield ` * @param next - The next middleware function in the stack.`; + yield ` */`; + yield ` expressMiddleware(req: http.IncomingMessage, res: http.ServerResponse, next: () => void): void;`; + } + + yield "}"; + yield ""; + + yield `export function create${routerName}(`; + + for (const [param] of backends.values()) { + yield ` ${param.camelCase}: ${param.pascalCase},`; + } + + yield ` options: RouterOptions<{`; + for (const [param] of backends.values()) { + yield ` ${param.camelCase}: ${param.pascalCase},`; + } + yield ` }> = {}`; + yield `): ${routerName} {`; + + // Router error case handlers + yield ` const onRouteNotFound = options.onRequestNotFound ?? ((request, response) => {`; + yield ` response.statusCode = 404;`; + yield ` response.setHeader("Content-Type", "text/plain");`; + yield ` response.end("Not Found");`; + yield ` });`; + yield ""; + yield ` const onInvalidRequest = options.onInvalidRequest ?? ((request, response, route, error) => {`; + yield ` response.statusCode = 400;`; + yield ` response.setHeader("Content-Type", "application/json");`; + yield ` response.end(JSON.stringify({ error }));`; + yield ` });`; + yield ""; + yield ` const onInternalError = options.onInternalError ?? ((error, request, response) => {`; + yield ` response.statusCode = 500;`; + yield ` response.setHeader("Content-Type", "text/plain");`; + yield ` response.end("Internal server error.");`; + yield ` });`; + yield ""; + yield ` const routePolicies = options.routePolicies ?? {};`; + yield ""; + yield ` const routeHandlers = {`; + + // Policy chains for each operation + for (const operation of service.operations) { + const operationName = parseCase(operation.operation.name); + const containerName = parseCase(operation.container.name); + + yield ` ${containerName.snakeCase}_${operationName.snakeCase}: createPolicyChainForRoute(`; + yield ` "${containerName.camelCase + operationName.pascalCase + "Dispatch"}",`; + yield ` routePolicies,`; + yield ` "${containerName.camelCase}",`; + yield ` "${operationName.camelCase}",`; + yield ` serverRaw.${containerName.snakeCase}_${operationName.snakeCase},`; + yield ` ),`; + } + + yield ` } as const;`; + yield ""; + + // Core routing function definition + yield ` const dispatch = createPolicyChain("${routerName}Dispatch", options.policies ?? [], async function(ctx, request, response, onRouteNotFound) {`; + yield ` const url = new URL(request.url!, \`http://\${request.headers.host}\`);`; + yield ` let path = url.pathname;`; + yield ""; + + yield* indent(indent(emitRouteHandler(ctx, routeTree, backends, module))); + + yield ""; + + yield ` return onRouteNotFound(request, response);`; + yield ` });`; + yield ""; + yield ` return {`; + yield ` dispatch(request, response) { return dispatch({ request, response }, request, response, onRouteNotFound).catch((e) => onInternalError(e, request, response)); },`; + + if (ctx.options.express) { + yield ` expressMiddleware: function (request, response, next) { void dispatch({ request, response }, request, response, function () { next(); }).catch((e) => onInternalError(e, request, response)); },`; + } + + yield " }"; + yield "}"; +} + +/** + * Writes handling code for a single route tree node. + * + * @param ctx - The emitter context. + * @param routeTree - The route tree node to write handling code for. + * @param backends - The map of backends for operations. + * @param module - The module we're writing to. + */ +function* emitRouteHandler( + ctx: HttpContext, + routeTree: RouteTree, + backends: Map, + module: Module +): Iterable { + const mustTerminate = routeTree.edges.length === 0 && !routeTree.bind; + + yield `if (path.length === 0) {`; + if (routeTree.operations.size > 0) { + yield* indent(emitRouteOperationDispatch(ctx, routeTree.operations, backends)); + } else { + // Not found + yield ` return onRouteNotFound(request, response);`; + } + yield `}`; + + if (mustTerminate) { + // Not found + yield "else {"; + yield ` return onRouteNotFound(request, response);`; + yield `}`; + return; + } + + for (const [edge, nextTree] of routeTree.edges) { + const edgePattern = edge.length === 1 ? `'${edge}'` : JSON.stringify(edge); + yield `else if (path.startsWith(${edgePattern})) {`; + yield ` path = path.slice(${edge.length});`; + yield* indent(emitRouteHandler(ctx, nextTree, backends, module)); + yield "}"; + } + + if (routeTree.bind) { + const [parameterSet, nextTree] = routeTree.bind; + const parameters = [...parameterSet]; + + yield `else {`; + const paramName = parameters.length === 1 ? parameters[0] : "param"; + yield ` const [${paramName}, rest] = path.split("/", 1);`; + yield ` path = rest ?? "";`; + if (parameters.length !== 1) { + for (const p of parameters) { + yield ` const ${parseCase(p).camelCase} = param;`; + } + } + yield* indent(emitRouteHandler(ctx, nextTree, backends, module)); + + yield `}`; + } +} + +/** + * Writes the dispatch code for a specific set of operations mapped to the same route. + * + * @param ctx - The emitter context. + * @param operations - The operations mapped to the route. + * @param backends - The map of backends for operations. + */ +function* emitRouteOperationDispatch( + ctx: HttpContext, + operations: Map, + backends: Map +): Iterable { + yield `switch (request.method) {`; + for (const [verb, operationList] of operations.entries()) { + if (operationList.length === 1) { + const operation = operationList[0]; + const [backend] = backends.get(operation.container)!; + const operationName = keywordSafe( + backend.snakeCase + "_" + parseCase(operation.operation.name).snakeCase + ); + + const backendMemberName = backend.camelCase; + + const parameters = + operation.parameters.length > 0 + ? ", " + operation.parameters.map((param) => parseCase(param.name).camelCase).join(", ") + : ""; + + yield ` case ${JSON.stringify(verb.toUpperCase())}:`; + yield ` return routeHandlers.${operationName}(ctx, request, response, ${backendMemberName}${parameters});`; + } else { + // Shared route + const route = getHttpOperation(ctx.program, operationList[0].operation)[0].path; + yield ` case ${JSON.stringify(verb.toUpperCase())}:`; + yield* indent( + indent(emitRouteOperationDispatchMultiple(ctx, operationList, route, backends)) + ); + } + } + + yield ` default:`; + yield ` return onRouteNotFound(request, response);`; + + yield "}"; +} + +/** + * Writes the dispatch code for a specific set of operations mapped to the same route. + * + * @param ctx - The emitter context. + * @param operations - The operations mapped to the route. + * @param backends - The map of backends for operations. + */ +function* emitRouteOperationDispatchMultiple( + ctx: HttpContext, + operations: RouteOperation[], + route: string, + backends: Map +): Iterable { + const usedContentTypes = new Set(); + const contentTypeMap = new Map(); + + for (const operation of operations) { + const [httpOperation] = getHttpOperation(ctx.program, operation.operation); + const operationContentType = httpOperation.parameters.parameters.find( + (param) => param.type === "header" && param.name.toLowerCase() === "content-type" + )?.param.type; + + if (!operationContentType || operationContentType.kind !== "String") { + throw new UnimplementedError( + "Only string content-types are supported for route differentiation." + ); + } + + if (usedContentTypes.has(operationContentType.value)) { + reportDiagnostic(ctx.program, { + code: "undifferentiable-route", + target: httpOperation.operation, + }); + } + + usedContentTypes.add(operationContentType.value); + + contentTypeMap.set(operation, operationContentType.value); + } + + yield `const contentType = request.headers["content-type"];`; + yield `switch (contentType) {`; + + for (const [operation, contentType] of contentTypeMap.entries()) { + const [backend] = backends.get(operation.container)!; + const operationName = keywordSafe( + backend.snakeCase + "_" + parseCase(operation.operation.name).snakeCase + ); + + const backendMemberName = backend.camelCase; + + const parameters = + operation.parameters.length > 0 + ? ", " + operation.parameters.map((param) => parseCase(param.name).camelCase).join(", ") + : ""; + + yield ` case ${JSON.stringify(contentType)}:`; + yield ` return routeHandlers.${operationName}(ctx, request, response, ${backendMemberName}${parameters});`; + } + + yield ` default:`; + yield ` return onInvalidRequest(request, response, ${JSON.stringify(route)}, \`No operation in route '${route}' matched content-type "\${contentType}"\`);`; + yield "}"; +} + +/** + * A tree of routes in an HTTP router domain. + */ +interface RouteTree { + /** + * A list of operations that can be dispatched at this node. + */ + operations: Map; + /** + * A set of parameters that are bound in this position before proceeding along the subsequent tree. + */ + bind?: [Set, RouteTree]; + /** + * A list of static edges that can be taken from this node. + */ + edges: RouteTreeEdge[]; +} + +/** + * An edge in the route tree. The edge contains a literal string prefix that must match before the next node is visited. + */ +type RouteTreeEdge = readonly [string, RouteTree]; + +/** + * An operation that may be dispatched at a given tree node. + */ +interface RouteOperation { + /** + * The HTTP operation corresponding to this route operation. + */ + operation: Operation; + /** + * The operation's container. + */ + container: OperationContainer; + /** + * The path parameters that the route template for this operation binds. + */ + parameters: RouteParameter[]; + /** + * The HTTP verb (GET, PUT, etc.) that this operation requires. + */ + verb: HttpVerb; +} + +/** + * A single route split into segments of strings and parameters. + */ +interface Route extends RouteOperation { + segments: RouteSegment[]; +} + +/** + * A segment of a single route. + */ +type RouteSegment = string | RouteParameter; + +/** + * A parameter in the route segment with its expected type. + */ +interface RouteParameter { + name: string; + type: Type; +} + +/** + * Create a route tree for a given service. + */ +function createRouteTree(ctx: HttpContext, service: HttpService): RouteTree { + // First get the Route for each operation in the service. + const routes = service.operations.map(function (operation) { + const segments = getRouteSegments(ctx, operation); + return { + operation: operation.operation, + container: operation.container, + verb: operation.verb, + parameters: segments.filter((segment) => typeof segment !== "string"), + segments, + } as Route; + }); + + // Build the tree by iteratively removing common prefixes from the text segments. + + const tree = intoRouteTree(routes); + + return tree; +} + +/** + * Build a route tree from a list of routes. + * + * This iteratively removes common segments from the routes and then for all routes matching a given common prefix, + * builds a nested tree from their subsequent segments. + * + * @param routes - the routes to build the tree from + */ +function intoRouteTree(routes: Route[]): RouteTree { + const [operations, rest] = bifilter(routes, (route) => route.segments.length === 0); + const [literal, parameterized] = bifilter( + rest, + (route) => typeof route.segments[0]! === "string" + ); + + const edgeMap = new Map(); + + // Group the routes by common prefix + + outer: for (const literalRoute of literal) { + const segment = literalRoute.segments[0] as string; + + for (const edge of [...edgeMap.keys()]) { + const prefix = commonPrefix(segment, edge); + + if (prefix.length > 0) { + const existing = edgeMap.get(edge)!; + edgeMap.delete(edge); + edgeMap.set(prefix, [...existing, literalRoute]); + continue outer; + } + } + + edgeMap.set(segment, [literalRoute]); + } + + const edges = [...edgeMap.entries()].map( + ([edge, routes]) => + [ + edge, + intoRouteTree( + routes.map(function removePrefix(route) { + const [prefix, ...rest] = route.segments as [string, ...RouteSegment[]]; + + if (prefix === edge) { + return { ...route, segments: rest }; + } else { + return { + ...route, + segments: [prefix.substring(edge.length), ...rest], + }; + } + }) + ), + ] as const + ); + + let bind: [Set, RouteTree] | undefined; + + if (parameterized.length > 0) { + const parameters = new Set(); + const nextRoutes: Route[] = []; + for (const parameterizedRoute of parameterized) { + const [{ name }, ...rest] = parameterizedRoute.segments as [ + RouteParameter, + ...RouteSegment[], + ]; + + parameters.add(name); + nextRoutes.push({ ...parameterizedRoute, segments: rest }); + } + + bind = [parameters, intoRouteTree(nextRoutes)]; + } + + const operationMap = new Map(); + + for (const operation of operations) { + let operations = operationMap.get(operation.verb); + if (!operations) { + operations = []; + operationMap.set(operation.verb, operations); + } + + operations.push(operation); + } + + return { + operations: operationMap, + bind, + edges, + }; + + function commonPrefix(a: string, b: string): string { + let i = 0; + while (i < a.length && i < b.length && a[i] === b[i]) { + i++; + } + return a.substring(0, i); + } +} + +function getRouteSegments(ctx: HttpContext, operation: HttpOperation): RouteSegment[] { + // Parse the route template into segments of "prefixes" (i.e. literal strings) + // and parameters (names enclosed in curly braces). The "/" character does not + // actually matter for this. We just want to know what the segments of the route + // are. + // + // Examples: + // "" => [] + // "/users" => ["/users"] + // "/users/{userId}" => ["/users/", {name: "userId"}] + // "/users/{userId}/posts/{postId}" => ["/users/", {name: "userId"}, "/posts/", {name: "postId"}] + + const segments: RouteSegment[] = []; + + const parameterTypeMap = new Map( + [...operation.parameters.parameters.values()].map( + (p) => + [ + p.param.name, + p.param.type.kind === "ModelProperty" ? p.param.type.type : p.param.type, + ] as const + ) + ); + + let remainingTemplate = operation.path; + + while (remainingTemplate.length > 0) { + // Scan for next `{` character + const openBraceIndex = remainingTemplate.indexOf("{"); + + if (openBraceIndex === -1) { + // No more parameters, just add the remaining string as a segment + segments.push(remainingTemplate); + break; + } + + // Add the prefix before the parameter, if there is one + if (openBraceIndex > 0) { + segments.push(remainingTemplate.substring(0, openBraceIndex)); + } + + // Scan for next `}` character + const closeBraceIndex = remainingTemplate.indexOf("}", openBraceIndex); + + if (closeBraceIndex === -1) { + // This is an error in the HTTP layer, so we'll just treat it as if the parameter ends here + // and captures the rest of the string as its name. + segments.push({ + name: remainingTemplate.substring(openBraceIndex + 1), + type: undefined as any, + }); + break; + } + + // Extract the parameter name + const parameterName = remainingTemplate.substring(openBraceIndex + 1, closeBraceIndex); + + segments.push({ + name: parameterName, + type: parameterTypeMap.get(parameterName)!, + }); + + // Move to the next segment + remainingTemplate = remainingTemplate.substring(closeBraceIndex + 1); + } + + return segments; +} diff --git a/packages/http-server-javascript/src/index.ts b/packages/http-server-javascript/src/index.ts new file mode 100644 index 0000000000..7d91eaa6cc --- /dev/null +++ b/packages/http-server-javascript/src/index.ts @@ -0,0 +1,116 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { EmitContext, NoTarget, listServices } from "@typespec/compiler"; +import { visitAllTypes } from "./common/namespace.js"; +import { JsContext, Module, createModule, createPathCursor } from "./ctx.js"; +import { JsEmitterOptions, reportDiagnostic } from "./lib.js"; +import { parseCase } from "./util/case.js"; +import { UnimplementedError } from "./util/error.js"; +import { createOnceQueue } from "./util/once-queue.js"; +import { writeModuleTree } from "./write.js"; + +import { createModule as initializeHelperModule } from "../generated-defs/helpers/index.js"; + +// #region features + +import { emitSerialization } from "./common/serialization/index.js"; +import { emitHttp } from "./http/index.js"; + +// #endregion + +export { $lib } from "./lib.js"; + +export async function $onEmit(context: EmitContext) { + const services = listServices(context.program); + + if (services.length === 0) { + reportDiagnostic(context.program, { + code: "no-services-in-program", + target: NoTarget, + messageId: "default", + }); + return; + } else if (services.length > 1) { + throw new UnimplementedError("multiple service definitions per program."); + } + + const [service] = services; + + const serviceModuleName = parseCase(service.type.name).snakeCase; + + const rootCursor = createPathCursor(); + + const globalNamespace = context.program.getGlobalNamespaceType(); + + // Root module for emit. + const rootModule: Module = { + name: serviceModuleName, + cursor: rootCursor, + + imports: [], + declarations: [], + }; + + // This has the side effect of setting the `module` property of all helpers. + // Don't do anything with the emitter code before this is called. + await initializeHelperModule(rootModule); + + // Module for all models, including synthetic and all. + const modelsModule: Module = createModule("models", rootModule); + + // Module for all types in all namespaces. + const allModule: Module = createModule("all", modelsModule, globalNamespace); + + // Module for all synthetic (named ad-hoc) types. + const syntheticModule: Module = createModule("synthetic", modelsModule); + + const jsCtx: JsContext = { + program: context.program, + options: context.options, + globalNamespace, + service, + + typeQueue: createOnceQueue(), + synthetics: [], + syntheticNames: new Map(), + + rootModule, + namespaceModules: new Map([[globalNamespace, allModule]]), + syntheticModule, + modelsModule, + globalNamespaceModule: allModule, + + serializations: createOnceQueue(), + }; + + await emitHttp(jsCtx); + + if (!context.options["omit-unreachable-types"]) { + // Visit everything in the service namespace to ensure we emit a full `models` module and not just the subparts that + // are reachable from the service impl. + + visitAllTypes(jsCtx, service.type); + } + + // Emit serialization code for all required types. + emitSerialization(jsCtx); + + if (!context.program.compilerOptions.noEmit) { + try { + const stat = await context.program.host.stat(context.emitterOutputDir); + if (stat.isDirectory()) { + await context.program.host.rm(context.emitterOutputDir, { + recursive: true, + }); + } + } catch {} + + await writeModuleTree( + jsCtx, + context.emitterOutputDir, + rootModule, + !context.options["no-format"] + ); + } +} diff --git a/packages/http-server-javascript/src/lib.ts b/packages/http-server-javascript/src/lib.ts new file mode 100644 index 0000000000..77deeedae5 --- /dev/null +++ b/packages/http-server-javascript/src/lib.ts @@ -0,0 +1,109 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { JSONSchemaType, createTypeSpecLibrary, paramMessage } from "@typespec/compiler"; + +export interface JsEmitterOptions { + express?: boolean; + "omit-unreachable-types": boolean; + "no-format": boolean; +} + +const EmitterOptionsSchema: JSONSchemaType = { + type: "object", + additionalProperties: false, + properties: { + express: { type: "boolean", nullable: true, default: false }, + "omit-unreachable-types": { + type: "boolean", + default: false, + }, + "no-format": { + type: "boolean", + default: false, + }, + }, + required: [], +}; + +export const $lib = createTypeSpecLibrary({ + name: "tsp-js", + requireImports: [], + emitter: { + options: EmitterOptionsSchema, + }, + diagnostics: { + "unrecognized-intrinsic": { + severity: "warning", + messages: { + default: paramMessage`unrecognized intrinsic '${"intrinsic"}' is treated as 'unknown'`, + }, + }, + "unrecognized-scalar": { + severity: "warning", + messages: { + default: paramMessage`unrecognized scalar '${"scalar"}' is treated as 'unknown'`, + }, + }, + "unrecognized-encoding": { + severity: "error", + messages: { + default: paramMessage`unrecognized encoding '${"encoding"}' for type '${"type"}'`, + }, + }, + "http-emit-disabled": { + severity: "warning", + messages: { + default: "HTTP emit is disabled because the HTTP library returned errors.", + }, + }, + "no-services-in-program": { + severity: "warning", + messages: { + default: "No services found in program.", + }, + }, + "undifferentiable-route": { + severity: "error", + messages: { + default: "Shared route cannot be differentiated from other routes.", + }, + }, + "undifferentiable-scalar": { + severity: "error", + messages: { + default: paramMessage`Scalar type cannot be differentiated from other scalar type '${"competitor"}'.`, + }, + }, + "undifferentiable-model": { + severity: "error", + messages: { + default: + "Model type does not have enough unique properties to be differentiated from other models in some contexts.", + }, + }, + "unrepresentable-numeric-constant": { + severity: "error", + messages: { + default: "JavaScript cannot accurately represent this numeric constant.", + }, + }, + "undifferentiable-union-variant": { + severity: "error", + messages: { + default: + "Union variant cannot be differentiated from other variants of the union an an ambiguous context.", + }, + }, + "name-conflict": { + severity: "error", + messages: { + default: paramMessage`Name ${"name"} conflicts with a prior declaration and must be unique.`, + }, + }, + }, +}); + +const { reportDiagnostic } = $lib; + +export { reportDiagnostic }; diff --git a/packages/http-server-javascript/src/testing/index.ts b/packages/http-server-javascript/src/testing/index.ts new file mode 100644 index 0000000000..822fdff96c --- /dev/null +++ b/packages/http-server-javascript/src/testing/index.ts @@ -0,0 +1,10 @@ +import { + TypeSpecTestLibrary, + createTestLibrary, + findTestPackageRoot, +} from "@typespec/compiler/testing"; + +export const HttpServerJavaScriptTestLibrary: TypeSpecTestLibrary = createTestLibrary({ + name: "@typespec/http-server-javascript", + packageRoot: await findTestPackageRoot(import.meta.url), +}); diff --git a/packages/http-server-javascript/src/util/case.ts b/packages/http-server-javascript/src/util/case.ts new file mode 100644 index 0000000000..1935885cdf --- /dev/null +++ b/packages/http-server-javascript/src/util/case.ts @@ -0,0 +1,155 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +/** + * Destructures a name into its components. + * + * The following case conventions are supported: + * - PascalCase (["pascal", "case"]) + * - camelCase (["camel", "case"]) + * - snake_case (["snake", "case"]) + * - kebab-case (["kebab", "case"]) + * - dot.separated (["dot", "separated"]) + * - path/separated (["path", "separated"]) + * - double::colon::separated (["double", "colon", "separated"]) + * - space separated (["space", "separated"]) + * + * - AND any combination of the above, or any other separators or combination of separators. + * + * @param name - a name in any case + */ +export function parseCase(name: string): ReCase { + const components: string[] = []; + + let currentComponent = ""; + let inAcronym = false; + + for (let i = 0; i < name.length; i++) { + const char = name[i]; + + // cSpell:ignore presponse + // Special case acronym handling. We want to treat acronyms as a single component, + // but we also want the last capitalized letter in an all caps sequence to start a new + // component if the next letter is lower case. + // For example : "HTTPResponse" => ["http", "response"] + // : "OpenAIContext" => ["open", "ai", "context"] + // but : "HTTPresponse" (wrong) => ["htt", "presponse"] + // however : "HTTP_response" (okay I guess) => ["http", "response"] + + // If the character is a separator or an upper case character, we push the current component and start a new one. + if (char === char.toUpperCase() && !/[0-9]/.test(char)) { + // If we're in an acronym, we need to check if the next character is lower case. + // If it is, then this is the start of a new component. + const acronymRestart = + inAcronym && /[A-Z]/.test(char) && i + 1 < name.length && /[^A-Z]/.test(name[i + 1]); + + if (currentComponent.length > 0 && (acronymRestart || !inAcronym)) { + components.push(currentComponent.trim()); + currentComponent = ""; + } + } + + if (![":", "_", "-", ".", "/"].includes(char) && !/\s/.test(char)) { + currentComponent += char.toLowerCase(); + } + + inAcronym = /[A-Z]/.test(char); + } + + if (currentComponent.length > 0) { + components.push(currentComponent); + } + + return recase(components); +} + +/** + * An object allowing a name to be converted into various case conventions. + */ +export interface ReCase extends ReCaseUpper { + /** + * The components of the name with the first letter of each component capitalized and joined by an empty string. + */ + readonly pascalCase: string; + /** + * The components of the name with the first letter of the second and all subsequent components capitalized and joined + * by an empty string. + */ + readonly camelCase: string; + + /** + * Convert the components of the name into all uppercase letters. + */ + readonly upper: ReCaseUpper; +} + +interface ReCaseUpper { + /** + * The components of the name. + */ + readonly components: readonly string[]; + + /** + * The components of the name joined by underscores. + */ + readonly snakeCase: string; + /** + * The components of the name joined by hyphens. + */ + readonly kebabCase: string; + /** + * The components of the name joined by periods. + */ + readonly dotCase: string; + /** + * The components of the name joined by slashes. + * + * This uses forward slashes in the unix convention. + */ + readonly pathCase: string; + + /** + * Join the components with any given string. + * + * @param separator - the separator to join the components with + */ + join(separator: string): string; +} + +function recase(components: readonly string[]): ReCase { + return Object.freeze({ + components, + get pascalCase() { + return components + .map((component) => component[0].toUpperCase() + component.slice(1)) + .join(""); + }, + get camelCase() { + return components + .map((component, index) => + index === 0 ? component : component[0].toUpperCase() + component.slice(1) + ) + .join(""); + }, + get snakeCase() { + return components.join("_"); + }, + get kebabCase() { + return components.join("-"); + }, + get dotCase() { + return components.join("."); + }, + get pathCase() { + return components.join("/"); + }, + + get upper() { + return recase(components.map((component) => component.toUpperCase())); + }, + + join(separator: string) { + return components.join(separator); + }, + }); +} diff --git a/packages/http-server-javascript/src/util/differentiate.ts b/packages/http-server-javascript/src/util/differentiate.ts new file mode 100644 index 0000000000..28f18f09f5 --- /dev/null +++ b/packages/http-server-javascript/src/util/differentiate.ts @@ -0,0 +1,895 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { + BooleanLiteral, + EnumMember, + Model, + ModelProperty, + NumericLiteral, + Scalar, + StringLiteral, + Type, + Union, + getDiscriminator, + getMaxValue, + getMinValue, +} from "@typespec/compiler"; +import { getJsScalar } from "../common/scalar.js"; +import { JsContext } from "../ctx.js"; +import { reportDiagnostic } from "../lib.js"; +import { parseCase } from "./case.js"; +import { UnimplementedError, UnreachableError } from "./error.js"; +import { getAllProperties } from "./extends.js"; +import { categorize, indent } from "./iter.js"; + +/** + * A tree structure representing a body of TypeScript code. + */ +export type CodeTree = Result | IfChain | Switch | Verbatim; + +export type JsLiteralType = StringLiteral | BooleanLiteral | NumericLiteral | EnumMember; + +/** + * A TypeSpec type that is precise, i.e. the type of a single value. + */ +export type PreciseType = Scalar | Model | JsLiteralType; + +/** + * Determines if `t` is a precise type. + * @param t - the type to test + * @returns true if `t` is precise, false otherwise. + */ +export function isPreciseType(t: Type): t is PreciseType { + return ( + t.kind === "Scalar" || + t.kind === "Model" || + t.kind === "Boolean" || + t.kind === "Number" || + t.kind === "String" + ); +} + +/** + * An if-chain structure in the CodeTree DSL. This represents a cascading series of if-else-if statements with an optional + * final `else` branch. + */ +export interface IfChain { + kind: "if-chain"; + branches: IfBranch[]; + else?: CodeTree; +} + +/** + * A branch in an if-chain. + */ +export interface IfBranch { + /** + * A condition to test for this branch. + */ + condition: Expression; + /** + * The body of this branch, to be executed if the condition is true. + */ + body: CodeTree; +} + +/** + * A node in the code tree indicating that a precise type has been determined. + */ +export interface Result { + kind: "result"; + type: PreciseType; +} + +/** + * A switch structure in the CodeTree DSL. + */ +export interface Switch { + kind: "switch"; + /** + * The expression to switch on. + */ + condition: Expression; + /** + * The cases to test for. + */ + cases: SwitchCase[]; + /** + * The default case, if any. + */ + default?: CodeTree; +} + +/** + * A verbatim code block. + */ +export interface Verbatim { + kind: "verbatim"; + body: Iterable; +} + +/** + * A case in a switch statement. + */ +export interface SwitchCase { + /** + * The value to test for in this case. + */ + value: Expression; + /** + * The body of this case. + */ + body: CodeTree; +} + +/** + * An expression in the CodeTree DSL. + */ +export type Expression = + | BinaryOp + | UnaryOp + | TypeOf + | Literal + | VerbatimExpression + | SubjectReference + | ModelPropertyReference + | InRange; + +/** + * A binary operation. + */ +export interface BinaryOp { + kind: "binary-op"; + /** + * The operator to apply. This operation may be sensitive to the order of the left and right expressions. + */ + operator: + | "===" + | "!==" + | "<" + | "<=" + | ">" + | ">=" + | "+" + | "-" + | "*" + | "/" + | "%" + | "&&" + | "||" + | "instanceof" + | "in"; + /** + * The left-hand-side operand. + */ + left: Expression; + /** + * The right-hand-side operand. + */ + right: Expression; +} + +/** + * A unary operation. + */ +export interface UnaryOp { + kind: "unary-op"; + /** + * The operator to apply. + */ + operator: "!" | "-"; + /** + * The operand to apply the operator to. + */ + operand: Expression; +} + +/** + * A type-of operation. + */ +export interface TypeOf { + kind: "typeof"; + /** + * The operand to apply the `typeof` operator to. + */ + operand: Expression; +} + +/** + * A literal JavaScript value. The value will be converted to the text of an expression that will yield the same value. + */ +export interface Literal { + kind: "literal"; + /** + * The value of the literal. + */ + value: LiteralValue; +} + +/** + * A verbatim expression, written as-is with no modification. + */ +export interface VerbatimExpression { + kind: "verbatim"; + /** + * The exact text of the expression. + */ + text: string; +} + +/** + * A reference to the "subject" of the code tree. + * + * The "subject" is a special expression denoting an input value. + */ +export interface SubjectReference { + kind: "subject"; +} + +/** + * A reference to a model property. Model property references are rendered by the `referenceModelProperty` function in the + * options given to `writeCodeTree`, allowing the caller to define how model properties are stored. + */ +export interface ModelPropertyReference { + kind: "model-property"; + property: ModelProperty; +} + +/** + * A check to see if a value is in an integer range. + */ +export interface InRange { + kind: "in-range"; + /** + * The expression to check. + */ + expr: Expression; + /** + * The range to check against. + */ + range: IntegerRange; +} + +/** + * A literal value that can be used in a JavaScript expression. + */ +export type LiteralValue = string | number | boolean | bigint; + +function isLiteralValueType(type: Type): type is JsLiteralType { + return ( + type.kind === "Boolean" || + type.kind === "Number" || + type.kind === "String" || + type.kind === "EnumMember" + ); +} + +const PROPERTY_ID = (prop: ModelProperty) => parseCase(prop.name).camelCase; + +/** + * Differentiates the variants of a union type. This function returns a CodeTree that will test an input "subject" and + * determine which of the cases it matches. + * + * Compared to `differentiateTypes`, this function is specialized for union types, and will consider union + * discriminators first, then delegate to `differentiateTypes` for the remaining cases. + * + * @param ctx + * @param type + */ +export function differentiateUnion( + ctx: JsContext, + union: Union, + renderPropertyName: (prop: ModelProperty) => string = PROPERTY_ID +): CodeTree { + const discriminator = getDiscriminator(ctx.program, union)?.propertyName; + const variants = [...union.variants.values()]; + + if (!discriminator) { + const cases = new Set(); + + for (const variant of variants) { + if (!isPreciseType(variant.type)) { + reportDiagnostic(ctx.program, { + code: "undifferentiable-union-variant", + target: variant, + }); + } else { + cases.add(variant.type); + } + } + + return differentiateTypes(ctx, cases, PROPERTY_ID); + } else { + const property = (variants[0].type as Model).properties.get(discriminator)!; + + return { + kind: "switch", + condition: { + kind: "model-property", + property, + }, + cases: variants.map((v) => { + const discriminatorPropertyType = (v.type as Model).properties.get(discriminator)!.type as + | JsLiteralType + | EnumMember; + + return { + value: { kind: "literal", value: getJsValue(ctx, discriminatorPropertyType) }, + body: { kind: "result", type: v.type }, + } as SwitchCase; + }), + default: { + kind: "verbatim", + body: [ + 'throw new Error("Unreachable: discriminator did not match any known value or was not present.");', + ], + }, + }; + } +} + +/** + * Differentiates a set of input types. This function returns a CodeTree that will test an input "subject" and determine + * which of the cases it matches, executing the corresponding code block. + * + * @param ctx - The emitter context. + * @param cases - A map of cases to differentiate to their respective code blocks. + * @returns a CodeTree to use with `writeCodeTree` + */ +export function differentiateTypes( + ctx: JsContext, + cases: Set, + renderPropertyName: (prop: ModelProperty) => string = PROPERTY_ID +): CodeTree { + if (cases.size === 0) { + return { + kind: "verbatim", + body: [ + 'throw new Error("Unreachable: encountered a value in differentiation where no variants exist.");', + ], + }; + } + + const categories = categorize(cases.keys(), (type) => type.kind); + + const literals = [ + ...(categories.Boolean ?? []), + ...(categories.Number ?? []), + ...(categories.String ?? []), + ] as JsLiteralType[]; + const models = (categories.Model as Model[]) ?? []; + const scalars = (categories.Scalar as Scalar[]) ?? []; + + if (literals.length + scalars.length === 0) { + return differentiateModelTypes(ctx, select(models, cases)); + } else { + const branches: IfBranch[] = []; + for (const literal of literals) { + branches.push({ + condition: { + kind: "binary-op", + operator: "===", + left: { kind: "subject" }, + right: { kind: "literal", value: getJsValue(ctx, literal) }, + }, + body: { + kind: "result", + type: literal, + }, + }); + } + + const scalarRepresentations = new Map(); + + for (const scalar of scalars) { + const jsScalar = getJsScalar(ctx.program, scalar, scalar); + + if (scalarRepresentations.has(jsScalar)) { + reportDiagnostic(ctx.program, { + code: "undifferentiable-scalar", + target: scalar, + format: { + competitor: scalarRepresentations.get(jsScalar)!.name, + }, + }); + continue; + } + + let test: Expression; + + switch (jsScalar) { + case "Uint8Array": + test = { + kind: "binary-op", + operator: "instanceof", + left: { kind: "subject" }, + right: { kind: "verbatim", text: "Uint8Array" }, + }; + break; + case "number": + test = { + kind: "binary-op", + operator: "===", + left: { kind: "typeof", operand: { kind: "subject" } }, + right: { kind: "literal", value: "number" }, + }; + break; + case "bigint": + test = { + kind: "binary-op", + operator: "===", + left: { kind: "typeof", operand: { kind: "subject" } }, + right: { kind: "literal", value: "bigint" }, + }; + break; + case "string": + test = { + kind: "binary-op", + operator: "===", + left: { kind: "typeof", operand: { kind: "subject" } }, + right: { kind: "literal", value: "string" }, + }; + break; + case "boolean": + test = { + kind: "binary-op", + operator: "===", + left: { kind: "typeof", operand: { kind: "subject" } }, + right: { kind: "literal", value: "boolean" }, + }; + break; + case "Date": + test = { + kind: "binary-op", + operator: "instanceof", + left: { kind: "subject" }, + right: { kind: "verbatim", text: "Date" }, + }; + break; + default: + throw new UnimplementedError( + `scalar differentiation for unknown JS Scalar '${jsScalar}'.` + ); + } + + branches.push({ + condition: test, + body: { + kind: "result", + type: scalar, + }, + }); + } + + return { + kind: "if-chain", + branches, + else: models.length > 0 ? differentiateModelTypes(ctx, select(models, cases)) : undefined, + }; + } + + /** + * Select a subset of keys from a map. + * + * @param keys - The keys to select. + * @param map - The map to select from. + * @returns a map containing only those keys of the original map that were also in the `keys` iterable. + */ + function select(keys: Iterable, set: Set): Set { + const result = new Set(); + for (const key of keys) { + if (set.has(key)) result.add(key); + } + return result; + } +} + +/** + * Gets a JavaScript literal value for a given LiteralType. + */ +function getJsValue(ctx: JsContext, literal: JsLiteralType | EnumMember): LiteralValue { + switch (literal.kind) { + case "Boolean": + return literal.value; + case "Number": { + const asNumber = literal.numericValue.asNumber(); + + if (asNumber) return asNumber; + + const asBigInt = literal.numericValue.asBigInt(); + + if (asBigInt) return asBigInt; + + reportDiagnostic(ctx.program, { + code: "unrepresentable-numeric-constant", + target: literal, + }); + return 0; + } + case "String": + return literal.value; + case "EnumMember": + return literal.value ?? literal.name; + default: + throw new UnreachableError( + "getJsValue for " + (literal satisfies never as JsLiteralType).kind, + { literal } + ); + } +} + +/** + * An integer range, inclusive. + */ +type IntegerRange = [number, number]; + +function getIntegerRange(ctx: JsContext, property: ModelProperty): IntegerRange | false { + if ( + property.type.kind === "Scalar" && + getJsScalar(ctx.program, property.type, property) === "number" + ) { + const minValue = getMinValue(ctx.program, property); + const maxValue = getMaxValue(ctx.program, property); + + if (minValue !== undefined && maxValue !== undefined) { + return [minValue, maxValue]; + } + } + + return false; +} + +function overlaps(range: IntegerRange, other: IntegerRange): boolean { + return range[0] <= other[1] && range[1] >= other[0]; +} + +/** + * Differentiate a set of model types based on their properties. This function returns a CodeTree that will test an input + * "subject" and determine which of the cases it matches, executing the corresponding code block. + * + * @param ctx - The emitter context. + * @param models - A map of models to differentiate to their respective code blocks. + * @param renderPropertyName - A function that converts a model property reference over the subject to a string. + * @returns a CodeTree to use with `writeCodeTree` + */ +export function differentiateModelTypes( + ctx: JsContext, + models: Set, + renderPropertyName: (prop: ModelProperty) => string = PROPERTY_ID +): CodeTree { + // Horrible n^2 operation to get the unique properties of all models in the map, but hopefully n is small, so it should + // be okay until you have a lot of models to differentiate. + + type PropertyName = string; + type RenderedPropertyName = string & { __brand: "RenderedPropertyName" }; + + const uniqueProps = new Map>(); + + // Map of property names to maps of literal values that identify a model. + const propertyLiterals = new Map>(); + // Map of models to properties with values that can uniquely identify it + const uniqueLiterals = new Map>(); + + const propertyRanges = new Map>(); + const uniqueRanges = new Map>(); + + for (const model of models) { + const props = new Set(); + + for (const prop of getAllProperties(model)) { + // Don't consider optional properties for differentiation. + if (prop.optional) continue; + + const renderedPropName = renderPropertyName(prop) as RenderedPropertyName; + + // CASE - literal value + + if (isLiteralValueType(prop.type)) { + let literals = propertyLiterals.get(renderedPropName); + if (!literals) { + literals = new Map(); + propertyLiterals.set(renderedPropName, literals); + } + + const value = getJsValue(ctx, prop.type); + + const other = literals.get(value); + + if (other) { + // Literal already used. Leave the literal in the propertyLiterals map to prevent future collisions, + // but remove the model from the uniqueLiterals map. + uniqueLiterals.get(other)?.delete(renderedPropName); + } else { + // Literal is available. Add the model to the uniqueLiterals map and set this value. + literals.set(value, model); + let modelsUniqueLiterals = uniqueLiterals.get(model); + if (!modelsUniqueLiterals) { + modelsUniqueLiterals = new Set(); + uniqueLiterals.set(model, modelsUniqueLiterals); + } + modelsUniqueLiterals.add(renderedPropName); + } + } + + // CASE - unique range + + const range = getIntegerRange(ctx, prop); + if (range) { + let ranges = propertyRanges.get(renderedPropName); + if (!ranges) { + ranges = new Map(); + propertyRanges.set(renderedPropName, ranges); + } + + const overlappingRanges = [...ranges.entries()].filter(([r]) => overlaps(r, range)); + + if (overlappingRanges.length > 0) { + // Overlapping range found. Remove the model from the uniqueRanges map. + for (const [, other] of overlappingRanges) { + uniqueRanges.get(other)?.delete(renderedPropName); + } + } else { + // No overlapping range found. Add the model to the uniqueRanges map and set this range. + ranges.set(range, model); + let modelsUniqueRanges = uniqueRanges.get(model); + if (!modelsUniqueRanges) { + modelsUniqueRanges = new Set(); + uniqueRanges.set(model, modelsUniqueRanges); + } + modelsUniqueRanges.add(renderedPropName); + } + } + + // CASE - unique property + + let valid = true; + for (const [, other] of uniqueProps) { + if ( + other.has(prop.name) || + (isLiteralValueType(prop.type) && + propertyLiterals + .get(renderedPropName) + ?.has(getJsValue(ctx, prop.type as JsLiteralType))) + ) { + valid = false; + other.delete(prop.name); + } + } + + if (valid) { + props.add(prop.name); + } + } + + uniqueProps.set(model, props); + } + + const branches: IfBranch[] = []; + + let defaultCase: Model | undefined = undefined; + + for (const [model, unique] of uniqueProps) { + const literals = uniqueLiterals.get(model); + const ranges = uniqueRanges.get(model); + if (unique.size === 0 && (!literals || literals.size === 0) && (!ranges || ranges.size === 0)) { + if (defaultCase) { + reportDiagnostic(ctx.program, { + code: "undifferentiable-model", + target: model, + }); + return { + kind: "result", + type: defaultCase, + }; + } else { + // Allow a single default case. This covers more APIs that have a single model that is not differentiated by a + // unique property, in which case we can make it the `else` case. + defaultCase = model; + continue; + } + } + + if (literals && literals.size > 0) { + // A literal property value exists that can differentiate this model. + const firstUniqueLiteral = literals.values().next().value as RenderedPropertyName; + + const property = [...model.properties.values()].find( + (p) => (renderPropertyName(p) as RenderedPropertyName) === firstUniqueLiteral + )!; + + branches.push({ + condition: { + kind: "binary-op", + left: { kind: "model-property", property }, + operator: "===", + right: { + kind: "literal", + value: getJsValue(ctx, property.type as JsLiteralType), + }, + }, + body: { kind: "result", type: model }, + }); + } else if (ranges && ranges.size > 0) { + // A range property value exists that can differentiate this model. + const firstUniqueRange = ranges.values().next().value as RenderedPropertyName; + + const property = [...model.properties.values()].find( + (p) => renderPropertyName(p) === firstUniqueRange + )!; + + const range = [...propertyRanges.get(firstUniqueRange)!.entries()].find( + ([range, candidate]) => candidate === model + )![0]; + + branches.push({ + condition: { + kind: "in-range", + expr: { kind: "model-property", property }, + range, + }, + body: { kind: "result", type: model }, + }); + } else { + const firstUniqueProp = unique.values().next().value as PropertyName; + + branches.push({ + condition: { + kind: "binary-op", + left: { kind: "literal", value: firstUniqueProp }, + operator: "in", + right: { kind: "subject" }, + }, + body: { kind: "result", type: model }, + }); + } + } + + return { + kind: "if-chain", + branches, + else: defaultCase + ? { + kind: "result", + type: defaultCase, + } + : undefined, + }; +} + +/** + * Options for the `writeCodeTree` function. + */ +export interface CodeTreeOptions { + /** + * The subject expression to use in the code tree. + * + * This text is used whenever a `SubjectReference` is encountered in the code tree, allowing the caller to specify + * how the subject is stored and referenced. + */ + subject: string; + + /** + * A function that converts a model property to a string reference. + * + * This function is used whenever a `ModelPropertyReference` is encountered in the code tree, allowing the caller to + * specify how model properties are stored and referenced. + */ + referenceModelProperty: (p: ModelProperty) => string; + + /** + * Renders a result when encountered in the code tree. + */ + renderResult: (type: Type) => Iterable; +} + +/** + * Writes a code tree to text, given a set of options. + * + * @param ctx - The emitter context. + * @param tree - The code tree to write. + * @param options - The options to use when writing the code tree. + */ +export function* writeCodeTree( + ctx: JsContext, + tree: CodeTree, + options: CodeTreeOptions +): Iterable { + switch (tree.kind) { + case "result": + yield* options.renderResult(tree.type); + break; + case "if-chain": { + let first = true; + for (const branch of tree.branches) { + const condition = writeExpression(ctx, branch.condition, options); + if (first) { + first = false; + yield `if (${condition}) {`; + } else { + yield `} else if (${condition}) {`; + } + yield* indent(writeCodeTree(ctx, branch.body, options)); + } + if (tree.else) { + yield "} else {"; + yield* indent(writeCodeTree(ctx, tree.else, options)); + } + yield "}"; + break; + } + case "switch": { + yield `switch (${writeExpression(ctx, tree.condition, options)}) {`; + for (const _case of tree.cases) { + yield ` case ${writeExpression(ctx, _case.value, options)}: {`; + yield* indent(indent(writeCodeTree(ctx, _case.body, options))); + yield " }"; + } + if (tree.default) { + yield " default: {"; + yield* indent(indent(writeCodeTree(ctx, tree.default, options))); + yield " }"; + } + yield "}"; + break; + } + case "verbatim": + yield* tree.body; + break; + default: + throw new UnreachableError("writeCodeTree for " + (tree satisfies never as CodeTree).kind, { + tree, + }); + } +} + +function writeExpression(ctx: JsContext, expression: Expression, options: CodeTreeOptions): string { + switch (expression.kind) { + case "binary-op": + return `(${writeExpression(ctx, expression.left, options)}) ${expression.operator} (${writeExpression( + ctx, + expression.right, + options + )})`; + case "unary-op": + return `${expression.operator}(${writeExpression(ctx, expression.operand, options)})`; + case "typeof": + return `typeof (${writeExpression(ctx, expression.operand, options)})`; + case "literal": + switch (typeof expression.value) { + case "string": + return JSON.stringify(expression.value); + case "number": + case "bigint": + return String(expression.value); + case "boolean": + return expression.value ? "true" : "false"; + default: + throw new UnreachableError( + `writeExpression for literal value type '${typeof expression.value}'` + ); + } + case "in-range": { + const { + expr, + range: [min, max], + } = expression; + const exprText = writeExpression(ctx, expr, options); + + return `(${exprText} >= ${min} && ${exprText} <= ${max})`; + } + case "verbatim": + return expression.text; + case "subject": + return options.subject; + case "model-property": + return options.referenceModelProperty(expression.property); + default: + throw new UnreachableError( + "writeExpression for " + (expression satisfies never as Expression).kind, + { + expression, + } + ); + } +} diff --git a/packages/http-server-javascript/src/util/error.ts b/packages/http-server-javascript/src/util/error.ts new file mode 100644 index 0000000000..89997fc61e --- /dev/null +++ b/packages/http-server-javascript/src/util/error.ts @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +/** + * A utility error for unimplemented functionality. + */ +export class UnimplementedError extends Error { + constructor(message: string) { + super(`Unimplemented: ${message}`); + } +} + +/** + * A utility error for unreachable code paths. + */ +export class UnreachableError extends Error { + constructor(message: string, values?: Record) { + let fullMessage = `Unreachable: ${message}`; + + if (values) { + fullMessage += `\nObserved values: ${Object.entries(values) + .map(([k, v]) => ` ${k}: ${String(v)}`) + .join(",\n")}`; + } + + super(fullMessage); + } +} diff --git a/packages/http-server-javascript/src/util/extends.ts b/packages/http-server-javascript/src/util/extends.ts new file mode 100644 index 0000000000..c16de2c1fb --- /dev/null +++ b/packages/http-server-javascript/src/util/extends.ts @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { Interface, Model, ModelProperty, Operation } from "@typespec/compiler"; + +/** + * Recursively collects all properties of a model, including inherited properties. + */ +export function getAllProperties(model: Model, visited: Set = new Set()): ModelProperty[] { + if (visited.has(model)) return []; + + visited.add(model); + + const properties = [...model.properties.values()]; + + if (model.baseModel) { + properties.push(...getAllProperties(model.baseModel, visited)); + } + + return properties; +} + +/** + * Recursively collects all operations in an interface, including those inherited from source interfaces. + */ +export function getAllOperations( + iface: Interface, + visited: Set = new Set() +): Operation[] { + if (visited.has(iface)) return []; + + visited.add(iface); + + const operations = [...iface.operations.values()]; + + if (iface.sourceInterfaces) { + for (const source of iface.sourceInterfaces) { + operations.push(...getAllOperations(source, visited)); + } + } + + return operations; +} diff --git a/packages/http-server-javascript/src/util/iter.ts b/packages/http-server-javascript/src/util/iter.ts new file mode 100644 index 0000000000..ef44fd3b02 --- /dev/null +++ b/packages/http-server-javascript/src/util/iter.ts @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +/** + * Returns true if a value implements the ECMAScript Iterable interface. + */ +export function isIterable(value: unknown): value is object & Iterable { + return ( + typeof value === "object" && + value !== null && + Symbol.iterator in value && + typeof (value as Iterable)[Symbol.iterator] === "function" + ); +} + +/** + * Concatenate multiple iterables into a single iterable. + */ +export function* cat(...iterables: Iterable[]): Iterable { + for (const iterable of iterables) { + yield* iterable; + } +} + +/** + * Filter and collect an iterable into multiple groups based on a categorization function. + * + * The categorization function returns a string key for each value, and the values are returned in an object where each + * key is a category returned by the categorization function and the value is an array of values in that category. + * + * @param values - an iterable of values to categorize + * @param categorize - a categorization function that returns a string key for each value + * @returns an object where each key is a category and the value is an array of values in that category + */ + +export function categorize( + values: Iterable, + categorize: (o: T) => K +): Partial> { + const result: Record = {} as any; + + for (const value of values) { + (result[categorize(value)] ??= []).push(value); + } + + return result; +} + +/** + * Filter and collect an iterable into two categorizations based on a predicate function. + * + * Items for which the predicate returns true will be returned in the first array. + * Items for which the predicate returns false will be returned in the second array. + * + * @param values - an iterable of values to filter + * @param predicate - a predicate function that decides whether a value should be included in the first or second array + * + * @returns a tuple of two arrays of values filtered by the predicate + */ +export function bifilter(values: Iterable, predicate: (o: T) => boolean): [T[], T[]] { + const pass: T[] = []; + const fail: T[] = []; + + for (const value of values) { + if (predicate(value)) { + pass.push(value); + } else { + fail.push(value); + } + } + + return [pass, fail]; +} + +/** + * Prepends a string `indentation` to each value in `values`. + * + * @param values - an iterable of strings to indent + * @param indentation - the string to prepend to the beginning of each value + */ +export function* indent(values: Iterable, indentation: string = " "): Iterable { + for (const value of values) { + yield indentation + value; + } +} diff --git a/packages/http-server-javascript/src/util/keywords.ts b/packages/http-server-javascript/src/util/keywords.ts new file mode 100644 index 0000000000..5030e89cc0 --- /dev/null +++ b/packages/http-server-javascript/src/util/keywords.ts @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +const KEYWORDS_CONTEXTUAL = [ + "any", + "boolean", + "constructor", + "declare", + "get", + "module", + "require", + "number", + "set", + "string", +]; + +const KEYWORDS_STRICT = [ + "as", + "implements", + "interface", + "let", + "package", + "private", + "protected", + "public", + "static", + "yield", + "symbol", + "type", + "from", + "of", +]; + +const KEYWORDS_RESERVED = [ + "break", + "case", + "catch", + "class", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "else", + "enum", + "export", + "extends", + "false", + "finally", + "for", + "function", + "if", + "import", + "in", + "instanceof", + "new", + "null", + "return", + "super", + "switch", + "this", + "throw", + "true", + "try", + "typeof", + "var", + "void", + "while", + "with", + + "namespace", + "async", + "await", + "module", + "delete", +]; + +/** + * A set of reserved keywords that should not be used as identifiers. + */ +export const KEYWORDS = new Set([...KEYWORDS_STRICT, ...KEYWORDS_RESERVED, ...KEYWORDS_CONTEXTUAL]); + +/** + * Makes a name safe to use as an identifier by prefixing it with an underscore + * if it would conflict with a keyword. + */ +export function keywordSafe(name: string): string { + return KEYWORDS.has(name) ? `_${name}` : name; +} diff --git a/packages/http-server-javascript/src/util/name.ts b/packages/http-server-javascript/src/util/name.ts new file mode 100644 index 0000000000..f1077a92bd --- /dev/null +++ b/packages/http-server-javascript/src/util/name.ts @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { Namespace, Type } from "@typespec/compiler"; + +/** + * A TypeSpec type that may be attached to a namespace. + */ +export type NamespacedType = Extract; + +/** + * Computes the fully-qualified name of a TypeSpec type, i.e. `TypeSpec.boolean` for the built-in `boolean` scalar. + */ +export function getFullyQualifiedTypeName(type: NamespacedType): string { + const name = type.name ?? ""; + if (type.namespace) { + return getFullyQualifiedNamespacePath(type.namespace).join(".") + "." + name; + } else { + return name; + } +} + +function getFullyQualifiedNamespacePath(ns: Namespace): string[] { + if (ns.namespace) { + const innerPath = getFullyQualifiedNamespacePath(ns.namespace); + innerPath.push(ns.name); + return innerPath; + } else { + return [ns.name]; + } +} diff --git a/packages/http-server-javascript/src/util/once-queue.ts b/packages/http-server-javascript/src/util/once-queue.ts new file mode 100644 index 0000000000..b29ac793b3 --- /dev/null +++ b/packages/http-server-javascript/src/util/once-queue.ts @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +/** + * A deduplicating queue that only allows elements to be enqueued once. + * + * This uses a Set to track visited elements. + */ +export interface OnceQueue { + /** + * Enqueue a value if it has not been enqueued before. + */ + add(value: T): void; + /** + * Dequeue the next value. + */ + take(): T | undefined; + /** + * Check if the queue is empty. + */ + isEmpty(): boolean; +} + +/** + * Creates a new OnceQueue with the given initial values. + */ +export function createOnceQueue(...initialValues: T[]): OnceQueue { + const visited = new Set(); + const queue = [] as T[]; + let idx = 0; + const oncequeue: OnceQueue = { + add(value: T): void { + if (!visited.has(value)) { + visited.add(value); + queue.push(value); + } + }, + take(): T | undefined { + if (idx < queue.length) { + return queue[idx++]; + } else { + return undefined; + } + }, + isEmpty(): boolean { + return idx >= queue.length; + }, + }; + + for (const value of initialValues) { + oncequeue.add(value); + } + + return oncequeue; +} diff --git a/packages/http-server-javascript/src/util/pluralism.ts b/packages/http-server-javascript/src/util/pluralism.ts new file mode 100644 index 0000000000..aa8662f6fc --- /dev/null +++ b/packages/http-server-javascript/src/util/pluralism.ts @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +/** + * Provides an alternative name for anonymous TypeSpec.Array elements. + * @param typeName + * @returns + */ +export function getArrayElementName(typeName: string): string { + return typeName + "Element"; +} + +/** + * Provides an alternative name for anonymous TypeSpec.Record values. + * @param typeName + * @returns + */ +export function getRecordValueName(typeName: string): string { + return typeName + "Value"; +} + +/** + * Produces the name of an array type for a given base type. + * + * If the type name is a simple identifier, this will use the `[]` syntax, + * otherwise it will use the `Array<>` type constructor. + * + * @param typeName - the base type to make an array of + * @returns a good representation of an array of the base type + */ +export function asArrayType(typeName: string): string { + if (/^[a-zA-Z_]+$/.test(typeName)) { + return typeName + "[]"; + } else { + return `Array<${typeName}>`; + } +} diff --git a/packages/http-server-javascript/src/util/scope.ts b/packages/http-server-javascript/src/util/scope.ts new file mode 100644 index 0000000000..8443930a7c --- /dev/null +++ b/packages/http-server-javascript/src/util/scope.ts @@ -0,0 +1,211 @@ +import { DiagnosticTarget, NoTarget } from "@typespec/compiler"; +import { JsContext } from "../ctx.js"; +import { reportDiagnostic } from "../lib.js"; +import { UnreachableError } from "./error.js"; + +/** + * A conceptual lexical scope. + */ +export interface Scope { + /** + * Declare a name in the scope, applying the appropriate resolution strategy if necessary. + * + * @param primaryName - the primary name we want to declare in this scope + * @param options - options for the declaration + * @returns the name that was finally declared in the scope + */ + declare(primaryName: string, options?: DeclarationOptions): string; + + /** + * Determines whether or not a given name is declared in the scope. + * + * @param name - the name to check for declaration + */ + isDeclared(name: string): boolean; +} + +export interface DeclarationOptions { + /** + * The source of the declaration, to be used when raising diagnostics. + * + * Default: NoTarget + */ + source?: DiagnosticTarget | typeof NoTarget; + /** + * The resolution strategy to use if the declared name conflicts with an already declared name. + * + * Default: "shadow" + */ + resolutionStrategy?: ResolutionStrategy; +} + +const DEFAULT_DECLARATION_OPTIONS: Required = { + source: NoTarget, + resolutionStrategy: "shadow", +}; + +/** + * A strategy to use when attempting to resolve naming conflicts. This can be one of the following types: + * + * - `none`: no attempt will be made to resolve the naming conflict. + * - `shadow`: if the scope does not directly declare the name, this declaration will shadow it. + * - `prefix`: if the name is already declared, a prefix will be added to the name to resolve the conflict. + * - `alt-name`: if the name is already declared, an alternative name will be used to resolve the conflict. + */ +export type ResolutionStrategy = PrefixResolution | AltNameResolution | "shadow" | "none"; + +/** + * A resolution strategy that prepends a prefix. + */ +export interface PrefixResolution { + kind: "prefix"; + /** + * The prefix to append to the name. + * + * Default: "_". + */ + prefix?: string; + /** + * Whether or not to repeat the prefix until the conflict is resolved. + */ + repeated?: boolean; + /** + * Whether or not the name should shadow existing declarations. + * + * This setting applies to the primary name as well, so if the primary name is not own-declared in the scope, no + * prefix will be added. + */ + shadow?: boolean; +} + +/** + * A resolution strategy that attempts to use an alternative name to resolve conflicts. + */ +export interface AltNameResolution { + kind: "alt-name"; + /** + * The alternative name for this declaration. + */ + altName: string; +} + +const NO_PARENT: Scope = { + declare() { + throw new UnreachableError("Cannot declare in the no-parent scope"); + }, + isDeclared() { + return false; + }, +}; + +/** + * Create a new scope. + * + * @param ctx - the JS emitter context. + * @param parent - an optional parent scope for this scope. It will consider declarations in the parent scope for some conflicts. + */ +export function createScope(ctx: JsContext, parent: Scope = NO_PARENT): Scope { + const ownDeclarations: Set = new Set(); + const self: Scope = { + declare(primaryName, options = {}) { + const { source: target, resolutionStrategy } = { ...DEFAULT_DECLARATION_OPTIONS, ...options }; + + if (!self.isDeclared(primaryName)) { + ownDeclarations.add(primaryName); + return primaryName; + } + + // Apply resolution strategy + const resolutionStrategyName = + typeof resolutionStrategy === "string" ? resolutionStrategy : resolutionStrategy.kind; + + switch (resolutionStrategyName) { + case "none": + // Report diagnostic and return the name as is. + reportDiagnostic(ctx.program, { + code: "name-conflict", + format: { + name: primaryName, + }, + target, + }); + return primaryName; + case "shadow": + // Check to make sure this name isn't an own-declaration, and if not allow it, otherwise raise a diagnostic. + if (!ownDeclarations.has(primaryName)) { + ownDeclarations.add(primaryName); + return primaryName; + } else { + reportDiagnostic(ctx.program, { + code: "name-conflict", + format: { + name: primaryName, + }, + target, + }); + return primaryName; + } + case "prefix": { + const { + prefix = "_", + repeated = false, + shadow = true, + } = resolutionStrategy as PrefixResolution; + let name = primaryName; + + const isDeclared = shadow ? (name: string) => ownDeclarations.has(name) : self.isDeclared; + + while (isDeclared(name)) { + name = prefix + name; + + if (!repeated) break; + } + + if (isDeclared(name)) { + // We were not able to resolve the conflict with this strategy, so raise a diagnostic. + reportDiagnostic(ctx.program, { + code: "name-conflict", + format: { + name: name, + }, + target, + }); + + return name; + } + + ownDeclarations.add(name); + return name; + } + case "alt-name": { + const { altName } = resolutionStrategy as AltNameResolution; + + if (!self.isDeclared(altName)) { + ownDeclarations.add(altName); + return altName; + } + + // We were not able to resolve the conflict with this strategy, so raise a diagnostic. + reportDiagnostic(ctx.program, { + code: "name-conflict", + format: { + name: altName, + }, + target, + }); + + return altName; + } + default: + throw new UnreachableError(`Unknown resolution strategy: ${resolutionStrategy}`, { + resolutionStrategyName, + }); + } + }, + isDeclared(name) { + return ownDeclarations.has(name) || parent.isDeclared(name); + }, + }; + + return self; +} diff --git a/packages/http-server-javascript/src/write.ts b/packages/http-server-javascript/src/write.ts new file mode 100644 index 0000000000..da3f770d3f --- /dev/null +++ b/packages/http-server-javascript/src/write.ts @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +import { resolvePath } from "@typespec/compiler"; +import { JsContext, Module, isModule } from "./ctx.js"; + +import { emitModuleBody } from "./common/namespace.js"; +import { OnceQueue, createOnceQueue } from "./util/once-queue.js"; + +import * as prettier from "prettier"; + +import { EOL } from "os"; +import path from "path"; +import { bifilter } from "./util/iter.js"; + +/** + * Writes the tree of modules to the output directory. + * + * @param ctx - The emitter context. + * @param baseOutputPath - The base output directory to write the module tree to. + * @param rootModule - The root module to begin emitting from. + * @param format - Whether to format the output using Prettier. + */ +export async function writeModuleTree( + ctx: JsContext, + baseOutputPath: string, + rootModule: Module, + format: boolean +): Promise { + const queue = createOnceQueue(rootModule); + + while (!queue.isEmpty()) { + const module = queue.take()!; + await writeModuleFile(ctx, baseOutputPath, module, queue, format); + } +} + +/** + * Write a single module file to the output directory. + * + * @param ctx - The emitter context. + * @param baseOutputPath - The base output directory to write the module tree to. + * @param module - The module to write. + * @param queue - The queue of modules to write. + * @param format - Whether to format the output using Prettier. + */ +async function writeModuleFile( + ctx: JsContext, + baseOutputPath: string, + module: Module, + queue: OnceQueue, + format: boolean +): Promise { + const moduleText = [ + "// Generated by Microsoft TypeSpec", + "", + ...emitModuleBody(ctx, module, queue), + ]; + + const [declaredModules, declaredText] = bifilter(module.declarations, isModule); + + if (declaredText.length === 0) { + // Early exit to avoid writing an empty module. + return; + } + + const isIndex = module.cursor.path.length === 0 || declaredModules.length > 0; + + const moduleRelativePath = + module.cursor.path.length > 0 + ? module.cursor.path.join("/") + (isIndex ? "/index.ts" : ".ts") + : "index.ts"; + + const modulePath = resolvePath(baseOutputPath, moduleRelativePath); + + const text = format + ? await prettier.format(moduleText.join(EOL), { + parser: "typescript", + }) + : moduleText.join(EOL); + + await ctx.program.host.mkdirp(path.dirname(modulePath)); + await ctx.program.host.writeFile(modulePath, text); +} diff --git a/packages/http-server-javascript/tsconfig.json b/packages/http-server-javascript/tsconfig.json new file mode 100644 index 0000000000..d086cc7948 --- /dev/null +++ b/packages/http-server-javascript/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base.json", + "references": [{ "path": "../compiler/tsconfig.json" }], + "compilerOptions": { + "outDir": "dist", + "rootDir": ".", + "tsBuildInfoFile": "temp/tsconfig.tsbuildinfo" + }, + "include": ["src/**/*.ts", "generated-defs/**/*.ts"] +} diff --git a/packages/samples/package.json b/packages/samples/package.json index 7861549ecb..e27b3b1c6c 100644 --- a/packages/samples/package.json +++ b/packages/samples/package.json @@ -47,6 +47,7 @@ "@typespec/compiler": "workspace:~", "@typespec/html-program-viewer": "workspace:~", "@typespec/http": "workspace:~", + "@typespec/http-server-javascript": "workspace:~", "@typespec/json-schema": "workspace:~", "@typespec/openapi": "workspace:~", "@typespec/openapi3": "workspace:~", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e6e9407659..91b2587dd3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,7 +43,7 @@ importers: version: 7.15.0(eslint@8.57.0)(typescript@5.5.3) '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) c8: specifier: ^10.1.2 version: 10.1.2 @@ -58,7 +58,7 @@ importers: version: 3.0.0(eslint@8.57.0)(typescript@5.5.3) eslint-plugin-import: specifier: ^2.29.1 - version: 2.29.1(@typescript-eslint/parser@7.15.0)(eslint@8.57.0) + version: 2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0) eslint-plugin-react-hooks: specifier: ^4.6.2 version: 4.6.2(eslint@8.57.0) @@ -67,7 +67,7 @@ importers: version: 54.0.0(eslint@8.57.0) eslint-plugin-vitest: specifier: ^0.5.4 - version: 0.5.4(eslint@8.57.0)(typescript@5.5.3)(vitest@1.6.0) + version: 0.5.4(eslint@8.57.0)(typescript@5.5.3)(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) picocolors: specifier: ~1.0.1 version: 1.0.1 @@ -94,7 +94,7 @@ importers: version: 7.15.0(eslint@8.57.0)(typescript@5.5.3) vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) yaml: specifier: ~2.4.5 version: 2.4.5 @@ -111,7 +111,7 @@ importers: version: link:../compiler '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -126,7 +126,7 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/bundle-uploader: dependencies: @@ -160,7 +160,7 @@ importers: version: 7.5.8 '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -175,7 +175,7 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/bundler: dependencies: @@ -218,7 +218,7 @@ importers: version: 17.0.32 '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -233,10 +233,10 @@ importers: version: 5.5.3 vite: specifier: ^5.3.2 - version: 5.3.3(@types/node@18.11.19) + version: 5.3.3(@types/node@18.11.19)(terser@5.30.0) vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/compiler: dependencies: @@ -303,7 +303,7 @@ importers: version: link:../internal-build-utils '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -324,13 +324,13 @@ importers: version: link:../tmlanguage-generator ts-node: specifier: ~10.9.2 - version: 10.9.2(@types/node@18.11.19)(typescript@5.5.3) + version: 10.9.2(@swc/core@1.6.7)(@types/node@18.11.19)(typescript@5.5.3) typescript: specifier: ~5.5.3 version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) vscode-oniguruma: specifier: ~2.0.1 version: 2.0.1 @@ -358,7 +358,7 @@ importers: version: 7.15.0 '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -376,19 +376,19 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/html-program-viewer: dependencies: '@fluentui/react-components': specifier: ~9.54.2 - version: 9.54.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + version: 9.54.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': specifier: ^2.0.247 version: 2.0.247(react@18.3.1) '@fluentui/react-list-preview': specifier: ^0.2.8 - version: 0.2.8(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + version: 0.2.8(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) react: specifier: ~18.3.1 version: 18.3.1 @@ -397,7 +397,7 @@ importers: version: 18.3.1(react@18.3.1) react-hotkeys-hook: specifier: ^4.5.0 - version: 4.5.0(react-dom@18.3.1)(react@18.3.1) + version: 4.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@babel/core': specifier: ^7.24.7 @@ -407,10 +407,10 @@ importers: version: 10.2.0 '@testing-library/jest-dom': specifier: ^6.4.6 - version: 6.4.6(vitest@1.6.0) + version: 6.4.6(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@testing-library/react': specifier: ^16.0.0 - version: 16.0.0(@testing-library/dom@10.2.0)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + version: 16.0.0(@testing-library/dom@10.2.0)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/node': specifier: ~18.11.19 version: 18.11.19 @@ -428,10 +428,10 @@ importers: version: link:../react-components '@vitejs/plugin-react': specifier: ~4.3.1 - version: 4.3.1(vite@5.3.3) + version: 4.3.1(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -446,16 +446,16 @@ importers: version: 5.5.3 vite: specifier: ^5.3.2 - version: 5.3.3(@types/node@18.11.19) + version: 5.3.3(@types/node@18.11.19)(terser@5.30.0) vite-plugin-checker: specifier: ^0.7.0 - version: 0.7.0(eslint@8.57.0)(typescript@5.5.3)(vite@5.3.3) + version: 0.7.0(eslint@8.57.0)(optionator@0.9.3)(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) vite-plugin-dts: specifier: ^3.9.1 - version: 3.9.1(@types/node@18.11.19)(typescript@5.5.3)(vite@5.3.3) + version: 3.9.1(@types/node@18.11.19)(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/http: devDependencies: @@ -473,7 +473,7 @@ importers: version: link:../tspd '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -488,7 +488,29 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) + + packages/http-server-javascript: + dependencies: + prettier: + specifier: ~3.3.2 + version: 3.3.2 + devDependencies: + '@types/node': + specifier: ~18.11.19 + version: 18.11.19 + '@typespec/compiler': + specifier: workspace:~ + version: link:../compiler + '@typespec/http': + specifier: workspace:~ + version: link:../http + tsx: + specifier: ^4.16.0 + version: 4.16.2 + typescript: + specifier: ~5.5.3 + version: 5.5.3 packages/internal-build-utils: dependencies: @@ -519,7 +541,7 @@ importers: version: 17.0.32 '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -537,7 +559,7 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/json-schema: dependencies: @@ -562,7 +584,7 @@ importers: version: link:../tspd '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -583,7 +605,7 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/library-linter: devDependencies: @@ -595,7 +617,7 @@ importers: version: link:../compiler '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -610,7 +632,7 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/monarch: dependencies: @@ -623,7 +645,7 @@ importers: version: 18.11.19 '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -641,7 +663,7 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/openapi: devDependencies: @@ -665,7 +687,7 @@ importers: version: link:../tspd '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -680,7 +702,7 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/openapi3: dependencies: @@ -720,7 +742,7 @@ importers: version: link:../versioning '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -738,13 +760,13 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/playground: dependencies: '@fluentui/react-components': specifier: ~9.54.2 - version: 9.54.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + version: 9.54.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': specifier: ^2.0.247 version: 2.0.247(react@18.3.1) @@ -817,16 +839,16 @@ importers: version: 8.1.11 '@storybook/cli': specifier: ^8.1.11 - version: 8.1.11(react-dom@18.3.1)(react@18.3.1) + version: 8.1.11(@babel/preset-env@7.24.5(@babel/core@7.24.7))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/react': specifier: ^8.1.11 - version: 8.1.11(prettier@3.3.2)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) + version: 8.1.11(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@storybook/react-vite': specifier: ^8.1.11 - version: 8.1.11(prettier@3.3.2)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)(vite@5.3.3) + version: 8.1.11(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) '@storybook/test': specifier: ^8.1.11 - version: 8.1.11(vitest@1.6.0) + version: 8.1.11(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@storybook/types': specifier: ^8.1.11 version: 8.1.11 @@ -850,7 +872,7 @@ importers: version: link:../react-components '@vitejs/plugin-react': specifier: ~4.3.1 - version: 4.3.1(vite@5.3.3) + version: 4.3.1(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) c8: specifier: ^10.1.2 version: 10.1.2 @@ -868,19 +890,19 @@ importers: version: 5.5.3 vite: specifier: ^5.3.2 - version: 5.3.3(@types/node@18.11.19) + version: 5.3.3(@types/node@18.11.19)(terser@5.30.0) vite-plugin-checker: specifier: ^0.7.0 - version: 0.7.0(eslint@8.57.0)(typescript@5.5.3)(vite@5.3.3) + version: 0.7.0(eslint@8.57.0)(optionator@0.9.3)(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) vite-plugin-dts: specifier: ^3.9.1 - version: 3.9.1(@types/node@18.11.19)(typescript@5.5.3)(vite@5.3.3) + version: 3.9.1(@types/node@18.11.19)(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) packages/playground-website: dependencies: '@fluentui/react-components': specifier: ~9.54.2 - version: 9.54.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + version: 9.54.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': specifier: ^2.0.247 version: 2.0.247(react@18.3.1) @@ -947,10 +969,10 @@ importers: version: 3.52.4 '@vitejs/plugin-react': specifier: ~4.3.1 - version: 4.3.1(vite@5.3.3) + version: 4.3.1(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -965,19 +987,19 @@ importers: version: 5.0.7 rollup-plugin-visualizer: specifier: ~5.12.0 - version: 5.12.0 + version: 5.12.0(rollup@4.18.0) typescript: specifier: ~5.5.3 version: 5.5.3 vite: specifier: ^5.3.2 - version: 5.3.3(@types/node@18.11.19) + version: 5.3.3(@types/node@18.11.19)(terser@5.30.0) vite-plugin-dts: specifier: ^3.9.1 - version: 3.9.1(@types/node@18.11.19)(typescript@5.5.3)(vite@5.3.3) + version: 3.9.1(@types/node@18.11.19)(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/prettier-plugin-typespec: dependencies: @@ -1008,7 +1030,7 @@ importers: version: 4.18.0 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/protobuf: devDependencies: @@ -1026,7 +1048,7 @@ importers: version: link:../tspd '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -1044,13 +1066,13 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/react-components: dependencies: '@fluentui/react-components': specifier: ~9.54.2 - version: 9.54.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + version: 9.54.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': specifier: ^2.0.247 version: 2.0.247(react@18.3.1) @@ -1069,10 +1091,10 @@ importers: version: 10.2.0 '@testing-library/jest-dom': specifier: ^6.4.6 - version: 6.4.6(vitest@1.6.0) + version: 6.4.6(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@testing-library/react': specifier: ^16.0.0 - version: 16.0.0(@testing-library/dom@10.2.0)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + version: 16.0.0(@testing-library/dom@10.2.0)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/node': specifier: ~18.11.19 version: 18.11.19 @@ -1084,10 +1106,10 @@ importers: version: 18.3.0 '@vitejs/plugin-react': specifier: ~4.3.1 - version: 4.3.1(vite@5.3.3) + version: 4.3.1(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -1102,16 +1124,16 @@ importers: version: 5.5.3 vite: specifier: ^5.3.2 - version: 5.3.3(@types/node@18.11.19) + version: 5.3.3(@types/node@18.11.19)(terser@5.30.0) vite-plugin-checker: specifier: ^0.7.0 - version: 0.7.0(eslint@8.57.0)(typescript@5.5.3)(vite@5.3.3) + version: 0.7.0(eslint@8.57.0)(optionator@0.9.3)(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) vite-plugin-dts: specifier: ^3.9.1 - version: 3.9.1(@types/node@18.11.19)(typescript@5.5.3)(vite@5.3.3) + version: 3.9.1(@types/node@18.11.19)(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/rest: devDependencies: @@ -1132,7 +1154,7 @@ importers: version: link:../tspd '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -1147,7 +1169,7 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/samples: dependencies: @@ -1163,6 +1185,9 @@ importers: '@typespec/http': specifier: workspace:~ version: link:../http + '@typespec/http-server-javascript': + specifier: workspace:~ + version: link:../http-server-javascript '@typespec/json-schema': specifier: workspace:~ version: link:../json-schema @@ -1187,7 +1212,7 @@ importers: version: link:../internal-build-utils '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -1205,7 +1230,7 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/spec: devDependencies: @@ -1270,7 +1295,7 @@ importers: version: link:../prettier-plugin-typespec '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -1288,13 +1313,13 @@ importers: version: 0.26.3(typescript@5.5.3) typedoc-plugin-markdown: specifier: ^4.1.1 - version: 4.1.1(typedoc@0.26.3) + version: 4.1.1(typedoc@0.26.3(typescript@5.5.3)) typescript: specifier: ~5.5.3 version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/typespec-vs: devDependencies: @@ -1315,7 +1340,7 @@ importers: version: 15.2.3(rollup@4.18.0) '@rollup/plugin-typescript': specifier: ~11.1.6 - version: 11.1.6(rollup@4.18.0)(typescript@5.5.3) + version: 11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.5.3) '@types/node': specifier: ~18.11.19 version: 18.11.19 @@ -1330,7 +1355,7 @@ importers: version: link:../internal-build-utils '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -1351,7 +1376,7 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) vscode-languageclient: specifier: ~9.0.1 version: 9.0.1 @@ -1372,7 +1397,7 @@ importers: version: link:../tspd '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -1387,31 +1412,31 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages/website: dependencies: '@docusaurus/core': specifier: ^3.4.0 - version: 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) + version: 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) '@docusaurus/plugin-content-docs': specifier: ~3.4.0 - version: 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) + version: 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) '@docusaurus/preset-classic': specifier: ^3.4.0 - version: 3.4.0(@algolia/client-search@4.23.2)(@swc/core@1.6.7)(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(search-insights@2.13.0)(typescript@5.5.3) + version: 3.4.0(@algolia/client-search@4.23.2)(@swc/core@1.6.7(@swc/helpers@0.5.8))(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)(typescript@5.5.3)(vue-template-compiler@2.7.16) '@docusaurus/theme-classic': specifier: ~3.4.0 - version: 3.4.0(@swc/core@1.6.7)(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) + version: 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) '@docusaurus/theme-common': specifier: ~3.4.0 - version: 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) + version: 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) '@docusaurus/theme-mermaid': specifier: ^3.4.0 - version: 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) + version: 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) '@fluentui/react-components': specifier: ~9.54.2 - version: 9.54.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + version: 9.54.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': specifier: ^2.0.247 version: 2.0.247(react@18.3.1) @@ -1442,16 +1467,16 @@ importers: devDependencies: '@docusaurus/module-type-aliases': specifier: ^3.4.0 - version: 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) + version: 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/tsconfig': specifier: ^3.4.0 version: 3.4.0 '@docusaurus/types': specifier: ^3.4.0 - version: 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) + version: 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/core': specifier: ^1.6.6 - version: 1.6.7 + version: 1.6.7(@swc/helpers@0.5.8) '@types/node': specifier: ~18.11.19 version: 18.11.19 @@ -1502,13 +1527,13 @@ importers: version: 16.4.5 file-loader: specifier: ~6.2.0 - version: 6.2.0(webpack@5.91.0) + version: 6.2.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) mermaid: specifier: ~10.9.1 version: 10.9.1 monaco-editor-webpack-plugin: specifier: ~7.1.0 - version: 7.1.0(monaco-editor@0.46.0)(webpack@5.91.0) + version: 7.1.0(monaco-editor@0.46.0)(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) playwright: specifier: ^1.45.0 version: 1.45.1 @@ -1517,13 +1542,13 @@ importers: version: 1.9.0 raw-loader: specifier: ~4.0.2 - version: 4.0.2(webpack@5.91.0) + version: 4.0.2(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) rimraf: specifier: ~5.0.7 version: 5.0.7 swc-loader: specifier: ^0.2.6 - version: 0.2.6(@swc/core@1.6.7)(webpack@5.91.0) + version: 0.2.6(@swc/core@1.6.7(@swc/helpers@0.5.8))(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) typescript: specifier: ~5.5.3 version: 5.5.3 @@ -1544,7 +1569,7 @@ importers: version: link:../tspd '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0) + version: 1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@vitest/ui': specifier: ^1.6.0 version: 1.6.0(vitest@1.6.0) @@ -1559,7 +1584,7 @@ importers: version: 5.5.3 vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + version: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) packages: @@ -10495,9 +10520,6 @@ packages: resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} engines: {node: '>=10'} - scheduler@0.23.0: - resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} - scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} @@ -13356,20 +13378,21 @@ snapshots: '@docsearch/css@3.6.0': {} - '@docsearch/react@3.6.0(@algolia/client-search@4.23.2)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(search-insights@2.13.0)': + '@docsearch/react@3.6.0(@algolia/client-search@4.23.2)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)': dependencies: '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.23.2)(algoliasearch@4.23.2)(search-insights@2.13.0) '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.23.2)(algoliasearch@4.23.2) '@docsearch/css': 3.6.0 - '@types/react': 18.3.3 algoliasearch: 4.23.2 + optionalDependencies: + '@types/react': 18.3.3 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) search-insights: 2.13.0 transitivePeerDependencies: - '@algolia/client-search' - '@docusaurus/core@3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@docusaurus/core@3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16)': dependencies: '@babel/core': 7.24.7 '@babel/generator': 7.24.5 @@ -13383,12 +13406,12 @@ snapshots: '@babel/traverse': 7.24.5 '@docusaurus/cssnano-preset': 3.4.0 '@docusaurus/logger': 3.4.0 - '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) - '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) + '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) + '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) autoprefixer: 10.4.19(postcss@8.4.38) - babel-loader: 9.1.3(@babel/core@7.24.7)(webpack@5.91.0) + babel-loader: 9.1.3(@babel/core@7.24.7)(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) babel-plugin-dynamic-import-node: 2.3.3 boxen: 6.2.1 chalk: 4.1.2 @@ -13397,50 +13420,50 @@ snapshots: cli-table3: 0.6.4 combine-promises: 1.2.0 commander: 5.1.0 - copy-webpack-plugin: 11.0.0(webpack@5.91.0) + copy-webpack-plugin: 11.0.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) core-js: 3.36.1 - css-loader: 6.10.0(webpack@5.91.0) - css-minimizer-webpack-plugin: 5.0.1(clean-css@5.3.3)(webpack@5.91.0) + css-loader: 6.10.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) + css-minimizer-webpack-plugin: 5.0.1(clean-css@5.3.3)(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) cssnano: 6.1.2(postcss@8.4.38) del: 6.1.1 detect-port: 1.5.1 escape-html: 1.0.3 eta: 2.2.0 eval: 0.1.8 - file-loader: 6.2.0(webpack@5.91.0) + file-loader: 6.2.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) fs-extra: 11.2.0 html-minifier-terser: 7.2.0 html-tags: 3.3.1 - html-webpack-plugin: 5.6.0(webpack@5.91.0) + html-webpack-plugin: 5.6.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) leven: 3.1.0 lodash: 4.17.21 - mini-css-extract-plugin: 2.8.1(webpack@5.91.0) + mini-css-extract-plugin: 2.8.1(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) p-map: 4.0.0 postcss: 8.4.38 - postcss-loader: 7.3.4(postcss@8.4.38)(typescript@5.5.3)(webpack@5.91.0) + postcss-loader: 7.3.4(postcss@8.4.38)(typescript@5.5.3)(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) prompts: 2.4.2 react: 18.3.1 - react-dev-utils: 12.0.1(eslint@8.57.0)(typescript@5.5.3)(webpack@5.91.0) + react-dev-utils: 12.0.1(eslint@8.57.0)(typescript@5.5.3)(vue-template-compiler@2.7.16)(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) react-dom: 18.3.1(react@18.3.1) - react-helmet-async: 1.3.0(react-dom@18.3.1)(react@18.3.1) + react-helmet-async: 1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-loadable: '@docusaurus/react-loadable@6.0.0(react@18.3.1)' - react-loadable-ssr-addon-v5-slorber: 1.0.1(@docusaurus/react-loadable@6.0.0)(webpack@5.91.0) + react-loadable-ssr-addon-v5-slorber: 1.0.1(@docusaurus/react-loadable@6.0.0(react@18.3.1))(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) react-router: 5.3.4(react@18.3.1) - react-router-config: 5.1.1(react-router@5.3.4)(react@18.3.1) + react-router-config: 5.1.1(react-router@5.3.4(react@18.3.1))(react@18.3.1) react-router-dom: 5.3.4(react@18.3.1) rtl-detect: 1.1.2 semver: 7.6.2 serve-handler: 6.1.5 shelljs: 0.8.5 - terser-webpack-plugin: 5.3.10(@swc/core@1.6.7)(webpack@5.91.0) + terser-webpack-plugin: 5.3.10(@swc/core@1.6.7(@swc/helpers@0.5.8))(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) tslib: 2.6.2 update-notifier: 6.0.2 - url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.91.0) - webpack: 5.91.0(@swc/core@1.6.7) + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))))(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) webpack-bundle-analyzer: 4.10.1 - webpack-dev-server: 4.15.2(webpack@5.91.0) + webpack-dev-server: 4.15.2(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) webpack-merge: 5.10.0 - webpackbar: 5.0.2(webpack@5.91.0) + webpackbar: 5.0.2(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) transitivePeerDependencies: - '@docusaurus/types' - '@parcel/css' @@ -13472,16 +13495,16 @@ snapshots: chalk: 4.1.2 tslib: 2.6.2 - '@docusaurus/mdx-loader@3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@docusaurus/mdx-loader@3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: '@docusaurus/logger': 3.4.0 - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) '@mdx-js/mdx': 3.0.1 '@slorber/remark-comment': 1.0.0 escape-html: 1.0.3 estree-util-value-to-estree: 3.0.1 - file-loader: 6.2.0(webpack@5.91.0) + file-loader: 6.2.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) fs-extra: 11.2.0 image-size: 1.1.1 mdast-util-mdx: 3.0.0 @@ -13497,9 +13520,9 @@ snapshots: tslib: 2.6.2 unified: 11.0.4 unist-util-visit: 5.0.0 - url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.91.0) + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))))(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) vfile: 6.0.1 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) transitivePeerDependencies: - '@docusaurus/types' - '@swc/core' @@ -13509,16 +13532,16 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/module-type-aliases@3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1)': + '@docusaurus/module-type-aliases@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/history': 4.7.11 '@types/react': 18.3.3 '@types/react-router-config': 5.0.11 '@types/react-router-dom': 5.3.3 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-helmet-async: 2.0.4(react-dom@18.3.1)(react@18.3.1) + react-helmet-async: 2.0.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-loadable: '@docusaurus/react-loadable@6.0.0(react@18.3.1)' transitivePeerDependencies: - '@swc/core' @@ -13527,15 +13550,15 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/plugin-content-blog@3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@docusaurus/plugin-content-blog@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) '@docusaurus/logger': 3.4.0 - '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) - '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) + '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) + '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) cheerio: 1.0.0-rc.12 feed: 4.2.2 fs-extra: 11.2.0 @@ -13547,7 +13570,7 @@ snapshots: tslib: 2.6.2 unist-util-visit: 5.0.0 utility-types: 3.11.0 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) transitivePeerDependencies: - '@parcel/css' - '@rspack/core' @@ -13566,16 +13589,16 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-content-docs@3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@docusaurus/plugin-content-docs@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) '@docusaurus/logger': 3.4.0 - '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/module-type-aliases': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) - '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) + '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/module-type-aliases': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) + '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) '@types/react-router-config': 5.0.11 combine-promises: 1.2.0 fs-extra: 11.2.0 @@ -13585,7 +13608,7 @@ snapshots: react-dom: 18.3.1(react@18.3.1) tslib: 2.6.2 utility-types: 3.11.0 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) transitivePeerDependencies: - '@parcel/css' - '@rspack/core' @@ -13604,18 +13627,18 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-content-pages@3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@docusaurus/plugin-content-pages@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) fs-extra: 11.2.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tslib: 2.6.2 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) transitivePeerDependencies: - '@parcel/css' - '@rspack/core' @@ -13634,11 +13657,11 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-debug@3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@docusaurus/plugin-debug@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) fs-extra: 11.2.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -13662,11 +13685,11 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-google-analytics@3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@docusaurus/plugin-google-analytics@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tslib: 2.6.2 @@ -13688,11 +13711,11 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-google-gtag@3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@docusaurus/plugin-google-gtag@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) '@types/gtag.js': 0.0.12 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -13715,11 +13738,11 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-google-tag-manager@3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@docusaurus/plugin-google-tag-manager@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tslib: 2.6.2 @@ -13741,14 +13764,14 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-sitemap@3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@docusaurus/plugin-sitemap@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) '@docusaurus/logger': 3.4.0 - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) - '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) + '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) fs-extra: 11.2.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -13772,21 +13795,21 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/preset-classic@3.4.0(@algolia/client-search@4.23.2)(@swc/core@1.6.7)(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(search-insights@2.13.0)(typescript@5.5.3)': - dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/plugin-content-blog': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/plugin-content-docs': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/plugin-content-pages': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/plugin-debug': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/plugin-google-analytics': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/plugin-google-gtag': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/plugin-google-tag-manager': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/plugin-sitemap': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/theme-classic': 3.4.0(@swc/core@1.6.7)(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/theme-search-algolia': 3.4.0(@algolia/client-search@4.23.2)(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(search-insights@2.13.0)(typescript@5.5.3) - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) + '@docusaurus/preset-classic@3.4.0(@algolia/client-search@4.23.2)(@swc/core@1.6.7(@swc/helpers@0.5.8))(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)(typescript@5.5.3)(vue-template-compiler@2.7.16)': + dependencies: + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/plugin-content-blog': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/plugin-content-docs': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/plugin-content-pages': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/plugin-debug': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/plugin-google-analytics': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/plugin-google-gtag': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/plugin-google-tag-manager': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/plugin-sitemap': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/theme-classic': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/theme-search-algolia': 3.4.0(@algolia/client-search@4.23.2)(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: @@ -13815,20 +13838,20 @@ snapshots: '@types/react': 18.3.3 react: 18.3.1 - '@docusaurus/theme-classic@3.4.0(@swc/core@1.6.7)(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@docusaurus/theme-classic@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/module-type-aliases': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/plugin-content-blog': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/plugin-content-docs': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/plugin-content-pages': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/module-type-aliases': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/plugin-content-blog': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/plugin-content-docs': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/plugin-content-pages': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) '@docusaurus/theme-translations': 3.4.0 - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) - '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) + '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) '@mdx-js/react': 3.0.1(@types/react@18.3.3)(react@18.3.1) clsx: 2.1.1 copy-text-to-clipboard: 3.2.0 @@ -13863,15 +13886,15 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/theme-common@3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@docusaurus/theme-common@3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16)': dependencies: - '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/module-type-aliases': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/plugin-content-blog': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/plugin-content-docs': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/plugin-content-pages': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) - '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0) + '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/module-type-aliases': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/plugin-content-blog': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/plugin-content-docs': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/plugin-content-pages': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) + '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) '@types/history': 4.7.11 '@types/react': 18.3.3 '@types/react-router-config': 5.0.11 @@ -13901,13 +13924,13 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/theme-mermaid@3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@docusaurus/theme-mermaid@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/module-type-aliases': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/module-type-aliases': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) mermaid: 10.9.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -13930,16 +13953,16 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/theme-search-algolia@3.4.0(@algolia/client-search@4.23.2)(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(search-insights@2.13.0)(typescript@5.5.3)': + '@docusaurus/theme-search-algolia@3.4.0(@algolia/client-search@4.23.2)(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)(typescript@5.5.3)(vue-template-compiler@2.7.16)': dependencies: - '@docsearch/react': 3.6.0(@algolia/client-search@4.23.2)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(search-insights@2.13.0) - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) + '@docsearch/react': 3.6.0(@algolia/client-search@4.23.2)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) '@docusaurus/logger': 3.4.0 - '@docusaurus/plugin-content-docs': 3.4.0(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) - '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(eslint@8.57.0)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) + '@docusaurus/plugin-content-docs': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) + '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)(vue-template-compiler@2.7.16) '@docusaurus/theme-translations': 3.4.0 - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) algoliasearch: 4.23.2 algoliasearch-helper: 3.16.3(algoliasearch@4.23.2) clsx: 2.1.1 @@ -13979,7 +14002,7 @@ snapshots: '@docusaurus/tsconfig@3.4.0': {} - '@docusaurus/types@3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1)': + '@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@mdx-js/mdx': 3.0.1 '@types/history': 4.7.11 @@ -13988,9 +14011,9 @@ snapshots: joi: 17.12.2 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-helmet-async: 1.3.0(react-dom@18.3.1)(react@18.3.1) + react-helmet-async: 1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) utility-types: 3.11.0 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) webpack-merge: 5.10.0 transitivePeerDependencies: - '@swc/core' @@ -13999,16 +14022,17 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/utils-common@3.4.0(@docusaurus/types@3.4.0)': + '@docusaurus/utils-common@3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))': dependencies: - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) tslib: 2.6.2 + optionalDependencies: + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation@3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3)': + '@docusaurus/utils-validation@3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3)': dependencies: '@docusaurus/logger': 3.4.0 - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3) - '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3) + '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) fs-extra: 11.2.0 joi: 17.12.2 js-yaml: 4.1.0 @@ -14023,14 +14047,13 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/utils@3.4.0(@docusaurus/types@3.4.0)(@swc/core@1.6.7)(typescript@5.5.3)': + '@docusaurus/utils@3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@swc/core@1.6.7(@swc/helpers@0.5.8))(typescript@5.5.3)': dependencies: '@docusaurus/logger': 3.4.0 - '@docusaurus/types': 3.4.0(@swc/core@1.6.7)(react-dom@18.3.1)(react@18.3.1) - '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0) + '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) '@svgr/webpack': 8.1.0(typescript@5.5.3) escape-string-regexp: 4.0.0 - file-loader: 6.2.0(webpack@5.91.0) + file-loader: 6.2.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) fs-extra: 11.2.0 github-slugger: 1.5.0 globby: 11.1.0 @@ -14043,9 +14066,11 @@ snapshots: resolve-pathname: 3.0.0 shelljs: 0.8.5 tslib: 2.6.2 - url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.91.0) + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))))(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) utility-types: 3.11.0 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) + optionalDependencies: + '@docusaurus/types': 3.4.0(@swc/core@1.6.7(@swc/helpers@0.5.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) transitivePeerDependencies: - '@swc/core' - esbuild @@ -14284,14 +14309,14 @@ snapshots: dependencies: '@swc/helpers': 0.5.8 - '@fluentui/react-accordion@9.4.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-accordion@9.4.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14303,13 +14328,13 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-alert@9.0.0-beta.124(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-alert@9.0.0-beta.124(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-avatar': 9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-avatar': 9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14321,12 +14346,12 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-aria@9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-aria@9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/keyboard-keys': 9.0.7 '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@swc/helpers': 0.5.8 '@types/react': 18.3.3 @@ -14334,17 +14359,17 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-avatar@9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-avatar@9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-badge': 9.2.39(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-badge': 9.2.39(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-popover': 9.9.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-popover': 9.9.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 - '@fluentui/react-tooltip': 9.4.32(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tooltip': 9.4.32(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) '@swc/helpers': 0.5.8 @@ -14355,7 +14380,7 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-badge@9.2.39(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-badge@9.2.39(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) @@ -14369,15 +14394,15 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-breadcrumb@9.0.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-breadcrumb@9.0.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-link': 9.2.26(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-link': 9.2.26(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14387,14 +14412,14 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-button@9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-button@9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/keyboard-keys': 9.0.7 - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14404,11 +14429,11 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-card@9.0.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-card@9.0.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/keyboard-keys': 9.0.7 '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14418,14 +14443,14 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-checkbox@9.2.28(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-checkbox@9.2.28(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-field': 9.1.67(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-field': 9.1.67(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.39(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-label': 9.1.71(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-label': 9.1.71(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.21.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.21.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.10(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14437,14 +14462,14 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-checkbox@9.2.30(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-checkbox@9.2.30(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14456,18 +14481,18 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-combobox@9.12.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-combobox@9.12.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/keyboard-keys': 9.0.7 - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-positioning': 9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-positioning': 9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14479,64 +14504,64 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-components@9.54.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': - dependencies: - '@fluentui/react-accordion': 9.4.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-alert': 9.0.0-beta.124(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-avatar': 9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-badge': 9.2.39(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-breadcrumb': 9.0.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-card': 9.0.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-checkbox': 9.2.30(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-combobox': 9.12.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-dialog': 9.11.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-divider': 9.2.71(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-drawer': 9.5.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-image': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-infobutton': 9.0.0-beta.102(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-infolabel': 9.0.38(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-input': 9.4.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-link': 9.2.26(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-menu': 9.14.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-message-bar': 9.2.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-motion': 9.2.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-overflow': 9.1.23(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-persona': 9.2.90(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-popover': 9.9.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-positioning': 9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-progress': 9.1.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-provider': 9.16.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-radio': 9.2.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-rating': 9.0.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-search': 9.0.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-select': 9.1.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-components@9.54.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': + dependencies: + '@fluentui/react-accordion': 9.4.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-alert': 9.0.0-beta.124(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-avatar': 9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-badge': 9.2.39(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-breadcrumb': 9.0.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-card': 9.0.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-checkbox': 9.2.30(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-combobox': 9.12.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-dialog': 9.11.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-divider': 9.2.71(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-drawer': 9.5.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-image': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-infobutton': 9.0.0-beta.102(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-infolabel': 9.0.38(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-input': 9.4.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-link': 9.2.26(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-menu': 9.14.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-message-bar': 9.2.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-motion': 9.2.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-overflow': 9.1.23(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-persona': 9.2.90(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-popover': 9.9.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-positioning': 9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-progress': 9.1.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-provider': 9.16.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-radio': 9.2.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-rating': 9.0.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-search': 9.0.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-select': 9.1.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-skeleton': 9.1.8(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-slider': 9.1.87(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-spinbutton': 9.2.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-spinner': 9.4.10(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-swatch-picker': 9.1.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-switch': 9.1.87(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-table': 9.15.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-tabs': 9.4.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-tag-picker': 9.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-tags': 9.3.10(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-teaching-popover': 9.1.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-text': 9.4.21(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-textarea': 9.3.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-skeleton': 9.1.8(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-slider': 9.1.87(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-spinbutton': 9.2.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-spinner': 9.4.10(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-swatch-picker': 9.1.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-switch': 9.1.87(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-table': 9.15.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-tabs': 9.4.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-tag-picker': 9.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-tags': 9.3.10(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-teaching-popover': 9.1.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-text': 9.4.21(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-textarea': 9.3.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-theme': 9.1.17 - '@fluentui/react-toast': 9.3.48(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-toolbar': 9.1.88(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-tooltip': 9.4.32(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-tree': 9.7.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-toast': 9.3.48(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-toolbar': 9.1.88(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-tooltip': 9.4.32(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-tree': 9.7.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-virtualizer': 9.0.0-alpha.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-virtualizer': 9.0.0-alpha.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) '@swc/helpers': 0.5.8 '@types/react': 18.3.3 @@ -14546,7 +14571,7 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-context-selector@9.1.61(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-context-selector@9.1.61(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/react-utilities': 9.18.10(@types/react@18.3.3)(react@18.3.1) '@swc/helpers': 0.5.8 @@ -14554,9 +14579,9 @@ snapshots: '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - scheduler: 0.23.0 + scheduler: 0.23.2 - '@fluentui/react-context-selector@9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-context-selector@9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@swc/helpers': 0.5.8 @@ -14564,19 +14589,19 @@ snapshots: '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - scheduler: 0.23.0 + scheduler: 0.23.2 - '@fluentui/react-dialog@9.11.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-dialog@9.11.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/keyboard-keys': 9.0.7 - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-motion': 9.2.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-motion': 9.2.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14588,7 +14613,7 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-divider@9.2.71(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-divider@9.2.71(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) @@ -14601,13 +14626,13 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-drawer@9.5.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-drawer@9.5.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-dialog': 9.11.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-dialog': 9.11.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-motion-preview': 0.5.23(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-motion-preview': 0.5.23(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14619,12 +14644,12 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-field@9.1.67(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-field@9.1.67(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14636,12 +14661,12 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-field@9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-field@9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14659,7 +14684,7 @@ snapshots: react: 18.3.1 tslib: 2.6.2 - '@fluentui/react-image@9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-image@9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) @@ -14672,13 +14697,13 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-infobutton@9.0.0-beta.102(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-infobutton@9.0.0-beta.102(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-popover': 9.9.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-popover': 9.9.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14690,13 +14715,13 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-infolabel@9.0.38(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-infolabel@9.0.38(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-popover': 9.9.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-popover': 9.9.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14708,9 +14733,9 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-input@9.4.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-input@9.4.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-theme': 9.1.17 @@ -14740,7 +14765,7 @@ snapshots: react: 18.3.1 react-is: 17.0.2 - '@fluentui/react-label@9.1.71(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-label@9.1.71(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) @@ -14753,7 +14778,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-label@9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-label@9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) @@ -14766,12 +14791,12 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-link@9.2.26(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-link@9.2.26(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/keyboard-keys': 9.0.7 '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14781,14 +14806,14 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-list-preview@0.2.8(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-list-preview@0.2.8(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/keyboard-keys': 9.0.7 - '@fluentui/react-checkbox': 9.2.28(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-context-selector': 9.1.61(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-checkbox': 9.2.28(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-context-selector': 9.1.61(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-jsx-runtime': 9.0.39(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.21.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.21.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.10(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14800,17 +14825,17 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-menu@9.14.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-menu@9.14.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/keyboard-keys': 9.0.7 - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-positioning': 9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-positioning': 9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14822,9 +14847,9 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-message-bar@9.2.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-message-bar@9.2.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) @@ -14836,9 +14861,9 @@ snapshots: '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-transition-group: 4.4.5(react-dom@18.3.1)(react@18.3.1) + react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@fluentui/react-motion-preview@0.5.23(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-motion-preview@0.5.23(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) @@ -14851,7 +14876,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-motion@9.2.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-motion@9.2.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) @@ -14862,10 +14887,10 @@ snapshots: react-dom: 18.3.1(react@18.3.1) react-is: 17.0.2 - '@fluentui/react-overflow@9.1.23(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-overflow@9.1.23(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/priority-overflow': 9.1.13 - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14877,10 +14902,10 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-persona@9.2.90(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-persona@9.2.90(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-avatar': 9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-badge': 9.2.39(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-avatar': 9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-badge': 9.2.39(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-theme': 9.1.17 @@ -14894,16 +14919,16 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-popover@9.9.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-popover@9.9.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/keyboard-keys': 9.0.7 - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-positioning': 9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-positioning': 9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14915,10 +14940,10 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-portal@9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-portal@9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) '@swc/helpers': 0.5.8 @@ -14926,9 +14951,9 @@ snapshots: '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - use-disposable: 1.0.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + use-disposable: 1.0.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@fluentui/react-positioning@9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-positioning@9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@floating-ui/devtools': 0.2.1(@floating-ui/dom@1.6.3) '@floating-ui/dom': 1.6.3 @@ -14942,9 +14967,9 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-progress@9.1.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-progress@9.1.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-theme': 9.1.17 @@ -14958,12 +14983,12 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-provider@9.16.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-provider@9.16.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/core': 1.16.0 @@ -14974,13 +14999,13 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-radio@9.2.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-radio@9.2.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -14992,11 +15017,11 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-rating@9.0.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-rating@9.0.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -15006,10 +15031,10 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-search@9.0.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-search@9.0.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/react-icons': 2.0.247(react@18.3.1) - '@fluentui/react-input': 9.4.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-input': 9.4.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) @@ -15022,9 +15047,9 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-select@9.1.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-select@9.1.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) @@ -15046,9 +15071,9 @@ snapshots: '@types/react': 18.3.3 react: 18.3.1 - '@fluentui/react-skeleton@9.1.8(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-skeleton@9.1.8(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-theme': 9.1.17 @@ -15062,12 +15087,12 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-slider@9.1.87(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-slider@9.1.87(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -15079,10 +15104,10 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-spinbutton@9.2.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-spinbutton@9.2.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/keyboard-keys': 9.0.7 - '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) @@ -15097,10 +15122,10 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-spinner@9.4.10(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-spinner@9.4.10(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) @@ -15111,13 +15136,13 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-swatch-picker@9.1.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-swatch-picker@9.1.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -15129,14 +15154,14 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-switch@9.1.87(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-switch@9.1.87(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-label': 9.1.72(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -15148,18 +15173,18 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-table@9.15.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-table@9.15.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/keyboard-keys': 9.0.7 - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-avatar': 9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-checkbox': 9.2.30(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-avatar': 9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-checkbox': 9.2.30(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-radio': 9.2.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-radio': 9.2.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -15171,12 +15196,12 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-tabs@9.4.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-tabs@9.4.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -15188,7 +15213,7 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-tabster@9.21.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-tabster@9.21.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-theme': 9.1.17 @@ -15202,7 +15227,7 @@ snapshots: react-dom: 18.3.1(react@18.3.1) tabster: 7.3.0 - '@fluentui/react-tabster@9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-tabster@9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-theme': 9.1.17 @@ -15216,20 +15241,20 @@ snapshots: react-dom: 18.3.1(react@18.3.1) tabster: 8.0.0 - '@fluentui/react-tag-picker@9.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-tag-picker@9.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/keyboard-keys': 9.0.7 - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-combobox': 9.12.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-combobox': 9.12.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-positioning': 9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-positioning': 9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-tags': 9.3.10(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-tags': 9.3.10(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -15241,15 +15266,15 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-tags@9.3.10(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-tags@9.3.10(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/keyboard-keys': 9.0.7 - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-avatar': 9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-avatar': 9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -15261,16 +15286,16 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-teaching-popover@9.1.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-teaching-popover@9.1.9(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-popover': 9.9.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-popover': 9.9.13(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -15283,7 +15308,7 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-text@9.4.21(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-text@9.4.21(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) @@ -15296,9 +15321,9 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-textarea@9.3.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-textarea@9.3.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-field': 9.1.69(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-theme': 9.1.17 @@ -15317,16 +15342,16 @@ snapshots: '@fluentui/tokens': 1.0.0-alpha.14 '@swc/helpers': 0.5.8 - '@fluentui/react-toast@9.3.48(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-toast@9.3.48(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/keyboard-keys': 9.0.7 - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-motion': 9.2.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-motion': 9.2.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -15336,15 +15361,15 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-toolbar@9.1.88(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-toolbar@9.1.88(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: - '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-divider': 9.2.71(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-divider': 9.2.71(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-radio': 9.2.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-radio': 9.2.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -15356,14 +15381,14 @@ snapshots: transitivePeerDependencies: - scheduler - '@fluentui/react-tooltip@9.4.32(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-tooltip@9.4.32(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/keyboard-keys': 9.0.7 '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-positioning': 9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-portal': 9.4.29(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-positioning': 9.15.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -15373,19 +15398,19 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@fluentui/react-tree@9.7.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0)': + '@fluentui/react-tree@9.7.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)': dependencies: '@fluentui/keyboard-keys': 9.0.7 - '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-avatar': 9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@fluentui/react-checkbox': 9.2.30(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) - '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-aria': 9.13.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-avatar': 9.6.31(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-button': 9.3.85(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@fluentui/react-checkbox': 9.2.30(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) + '@fluentui/react-context-selector': 9.1.63(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-icons': 2.0.247(react@18.3.1) '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-radio': 9.2.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)(scheduler@0.23.0) + '@fluentui/react-radio': 9.2.25(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) - '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) + '@fluentui/react-tabster': 9.22.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@fluentui/react-theme': 9.1.17 '@fluentui/react-utilities': 9.18.11(@types/react@18.3.3)(react@18.3.1) '@griffel/react': 1.5.22(react@18.3.1) @@ -15413,7 +15438,7 @@ snapshots: '@types/react': 18.3.3 react: 18.3.1 - '@fluentui/react-virtualizer@9.0.0-alpha.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@fluentui/react-virtualizer@9.0.0-alpha.80(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@fluentui/react-jsx-runtime': 9.0.40(@types/react@18.3.3)(react@18.3.1) '@fluentui/react-shared-contexts': 9.19.0(@types/react@18.3.3)(react@18.3.1) @@ -15494,14 +15519,15 @@ snapshots: '@types/yargs': 17.0.32 chalk: 4.1.2 - '@joshwooding/vite-plugin-react-docgen-typescript@0.3.1(typescript@5.5.3)(vite@5.3.3)': + '@joshwooding/vite-plugin-react-docgen-typescript@0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0))': dependencies: glob: 7.2.3 glob-promise: 4.2.2(glob@7.2.3) magic-string: 0.27.0 react-docgen-typescript: 2.2.2(typescript@5.5.3) + vite: 5.3.3(@types/node@18.11.19)(terser@5.30.0) + optionalDependencies: typescript: 5.5.3 - vite: 5.3.3(@types/node@18.11.19) '@jridgewell/gen-mapping@0.3.5': dependencies: @@ -16189,8 +16215,9 @@ snapshots: '@rollup/plugin-alias@5.1.0(rollup@4.18.0)': dependencies: - rollup: 4.18.0 slash: 4.0.0 + optionalDependencies: + rollup: 4.18.0 '@rollup/plugin-commonjs@26.0.1(rollup@4.18.0)': dependencies: @@ -16200,17 +16227,20 @@ snapshots: glob: 10.4.2 is-reference: 1.2.1 magic-string: 0.30.8 + optionalDependencies: rollup: 4.18.0 '@rollup/plugin-json@6.1.0(rollup@4.18.0)': dependencies: '@rollup/pluginutils': 5.1.0(rollup@4.18.0) + optionalDependencies: rollup: 4.18.0 '@rollup/plugin-multi-entry@6.0.1(rollup@4.18.0)': dependencies: '@rollup/plugin-virtual': 3.0.2(rollup@4.18.0) matched: 5.0.1 + optionalDependencies: rollup: 4.18.0 '@rollup/plugin-node-resolve@15.2.3(rollup@4.18.0)': @@ -16221,23 +16251,27 @@ snapshots: is-builtin-module: 3.2.1 is-module: 1.0.0 resolve: 1.22.8 + optionalDependencies: rollup: 4.18.0 '@rollup/plugin-replace@5.0.7(rollup@4.18.0)': dependencies: '@rollup/pluginutils': 5.1.0(rollup@4.18.0) magic-string: 0.30.8 + optionalDependencies: rollup: 4.18.0 - '@rollup/plugin-typescript@11.1.6(rollup@4.18.0)(typescript@5.5.3)': + '@rollup/plugin-typescript@11.1.6(rollup@4.18.0)(tslib@2.6.2)(typescript@5.5.3)': dependencies: '@rollup/pluginutils': 5.1.0(rollup@4.18.0) resolve: 1.22.8 - rollup: 4.18.0 typescript: 5.5.3 + optionalDependencies: + rollup: 4.18.0 + tslib: 2.6.2 '@rollup/plugin-virtual@3.0.2(rollup@4.18.0)': - dependencies: + optionalDependencies: rollup: 4.18.0 '@rollup/pluginutils@5.1.0(rollup@4.18.0)': @@ -16245,6 +16279,7 @@ snapshots: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 + optionalDependencies: rollup: 4.18.0 '@rollup/rollup-android-arm-eabi@4.18.0': @@ -16297,13 +16332,14 @@ snapshots: '@rushstack/node-core-library@4.0.2(@types/node@18.11.19)': dependencies: - '@types/node': 18.11.19 fs-extra: 7.0.1 import-lazy: 4.0.0 jju: 1.4.0 resolve: 1.22.8 semver: 7.5.4 z-schema: 5.0.5 + optionalDependencies: + '@types/node': 18.11.19 '@rushstack/rig-package@0.5.2': dependencies: @@ -16313,8 +16349,9 @@ snapshots: '@rushstack/terminal@0.10.0(@types/node@18.11.19)': dependencies: '@rushstack/node-core-library': 4.0.2(@types/node@18.11.19) - '@types/node': 18.11.19 supports-color: 8.1.1 + optionalDependencies: + '@types/node': 18.11.19 '@rushstack/ts-command-line@4.19.1(@types/node@18.11.19)': dependencies: @@ -16388,10 +16425,10 @@ snapshots: polished: 4.3.1 uuid: 9.0.1 - '@storybook/builder-manager@8.1.11(prettier@3.3.2)': + '@storybook/builder-manager@8.1.11(encoding@0.1.13)(prettier@3.3.2)': dependencies: '@fal-works/esbuild-plugin-global-externals': 2.1.2 - '@storybook/core-common': 8.1.11(prettier@3.3.2) + '@storybook/core-common': 8.1.11(encoding@0.1.13)(prettier@3.3.2) '@storybook/manager': 8.1.11 '@storybook/node-logger': 8.1.11 '@types/ejs': 3.1.5 @@ -16409,11 +16446,11 @@ snapshots: - prettier - supports-color - '@storybook/builder-vite@8.1.11(prettier@3.3.2)(typescript@5.5.3)(vite@5.3.3)': + '@storybook/builder-vite@8.1.11(encoding@0.1.13)(prettier@3.3.2)(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0))': dependencies: '@storybook/channels': 8.1.11 '@storybook/client-logger': 8.1.11 - '@storybook/core-common': 8.1.11(prettier@3.3.2) + '@storybook/core-common': 8.1.11(encoding@0.1.13)(prettier@3.3.2) '@storybook/core-events': 8.1.11 '@storybook/csf-plugin': 8.1.11 '@storybook/node-logger': 8.1.11 @@ -16428,8 +16465,9 @@ snapshots: fs-extra: 11.2.0 magic-string: 0.30.8 ts-dedent: 2.2.0 + vite: 5.3.3(@types/node@18.11.19)(terser@5.30.0) + optionalDependencies: typescript: 5.5.3 - vite: 5.3.3(@types/node@18.11.19) transitivePeerDependencies: - encoding - prettier @@ -16443,18 +16481,18 @@ snapshots: telejson: 7.2.0 tiny-invariant: 1.3.3 - '@storybook/cli@8.1.11(react-dom@18.3.1)(react@18.3.1)': + '@storybook/cli@8.1.11(@babel/preset-env@7.24.5(@babel/core@7.24.7))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/core': 7.24.7 '@babel/types': 7.24.5 '@ndelangen/get-tarball': 3.0.9 '@storybook/codemod': 8.1.11 - '@storybook/core-common': 8.1.11(prettier@3.3.2) + '@storybook/core-common': 8.1.11(encoding@0.1.13)(prettier@3.3.2) '@storybook/core-events': 8.1.11 - '@storybook/core-server': 8.1.11(prettier@3.3.2)(react-dom@18.3.1)(react@18.3.1) + '@storybook/core-server': 8.1.11(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/csf-tools': 8.1.11 '@storybook/node-logger': 8.1.11 - '@storybook/telemetry': 8.1.11(prettier@3.3.2) + '@storybook/telemetry': 8.1.11(encoding@0.1.13)(prettier@3.3.2) '@storybook/types': 8.1.11 '@types/semver': 7.5.8 '@yarnpkg/fslib': 2.10.3 @@ -16470,7 +16508,7 @@ snapshots: get-npm-tarball-url: 2.1.0 giget: 1.2.3 globby: 14.0.2 - jscodeshift: 0.15.2(@babel/preset-env@7.24.5) + jscodeshift: 0.15.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)) leven: 3.1.0 ora: 5.4.1 prettier: 3.3.2 @@ -16506,7 +16544,7 @@ snapshots: '@types/cross-spawn': 6.0.6 cross-spawn: 7.0.3 globby: 14.0.2 - jscodeshift: 0.15.2(@babel/preset-env@7.24.5) + jscodeshift: 0.15.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)) lodash: 4.17.21 prettier: 3.3.2 recast: 0.23.7 @@ -16514,7 +16552,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@storybook/core-common@8.1.11(prettier@3.3.2)': + '@storybook/core-common@8.1.11(encoding@0.1.13)(prettier@3.3.2)': dependencies: '@storybook/core-events': 8.1.11 '@storybook/csf-tools': 8.1.11 @@ -16534,10 +16572,9 @@ snapshots: glob: 10.3.12 handlebars: 4.7.8 lazy-universal-dotenv: 4.0.0 - node-fetch: 2.7.0 + node-fetch: 2.7.0(encoding@0.1.13) picomatch: 2.3.1 pkg-dir: 5.0.0 - prettier: 3.3.2 prettier-fallback: prettier@3.3.2 pretty-hrtime: 1.0.3 resolve-from: 5.0.0 @@ -16546,6 +16583,8 @@ snapshots: tiny-invariant: 1.3.3 ts-dedent: 2.2.0 util: 0.12.5 + optionalDependencies: + prettier: 3.3.2 transitivePeerDependencies: - encoding - supports-color @@ -16555,25 +16594,25 @@ snapshots: '@storybook/csf': 0.1.7 ts-dedent: 2.2.0 - '@storybook/core-server@8.1.11(prettier@3.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@storybook/core-server@8.1.11(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@aw-web-design/x-default-browser': 1.4.126 '@babel/core': 7.24.7 '@babel/parser': 7.24.7 '@discoveryjs/json-ext': 0.5.7 - '@storybook/builder-manager': 8.1.11(prettier@3.3.2) + '@storybook/builder-manager': 8.1.11(encoding@0.1.13)(prettier@3.3.2) '@storybook/channels': 8.1.11 - '@storybook/core-common': 8.1.11(prettier@3.3.2) + '@storybook/core-common': 8.1.11(encoding@0.1.13)(prettier@3.3.2) '@storybook/core-events': 8.1.11 '@storybook/csf': 0.1.7 '@storybook/csf-tools': 8.1.11 '@storybook/docs-mdx': 3.1.0-next.0 '@storybook/global': 5.0.0 '@storybook/manager': 8.1.11 - '@storybook/manager-api': 8.1.11(react-dom@18.3.1)(react@18.3.1) + '@storybook/manager-api': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/node-logger': 8.1.11 '@storybook/preview-api': 8.1.11 - '@storybook/telemetry': 8.1.11(prettier@3.3.2) + '@storybook/telemetry': 8.1.11(encoding@0.1.13)(prettier@3.3.2) '@storybook/types': 8.1.11 '@types/detect-port': 1.3.5 '@types/diff': 5.2.1 @@ -16638,9 +16677,9 @@ snapshots: '@storybook/docs-mdx@3.1.0-next.0': {} - '@storybook/docs-tools@8.1.11(prettier@3.3.2)': + '@storybook/docs-tools@8.1.11(encoding@0.1.13)(prettier@3.3.2)': dependencies: - '@storybook/core-common': 8.1.11(prettier@3.3.2) + '@storybook/core-common': 8.1.11(encoding@0.1.13)(prettier@3.3.2) '@storybook/core-events': 8.1.11 '@storybook/preview-api': 8.1.11 '@storybook/types': 8.1.11 @@ -16655,7 +16694,7 @@ snapshots: '@storybook/global@5.0.0': {} - '@storybook/icons@1.2.9(react-dom@18.3.1)(react@18.3.1)': + '@storybook/icons@1.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -16670,16 +16709,16 @@ snapshots: '@vitest/utils': 1.6.0 util: 0.12.5 - '@storybook/manager-api@8.1.11(react-dom@18.3.1)(react@18.3.1)': + '@storybook/manager-api@8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@storybook/channels': 8.1.11 '@storybook/client-logger': 8.1.11 '@storybook/core-events': 8.1.11 '@storybook/csf': 0.1.7 '@storybook/global': 5.0.0 - '@storybook/icons': 1.2.9(react-dom@18.3.1)(react@18.3.1) + '@storybook/icons': 1.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/router': 8.1.11 - '@storybook/theming': 8.1.11(react-dom@18.3.1)(react@18.3.1) + '@storybook/theming': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/types': 8.1.11 dequal: 2.0.3 lodash: 4.17.21 @@ -16714,18 +16753,18 @@ snapshots: '@storybook/preview@8.1.11': {} - '@storybook/react-dom-shim@8.1.11(react-dom@18.3.1)(react@18.3.1)': + '@storybook/react-dom-shim@8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/react-vite@8.1.11(prettier@3.3.2)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)(vite@5.3.3)': + '@storybook/react-vite@8.1.11(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0))': dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.1(typescript@5.5.3)(vite@5.3.3) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) '@rollup/pluginutils': 5.1.0(rollup@4.18.0) - '@storybook/builder-vite': 8.1.11(prettier@3.3.2)(typescript@5.5.3)(vite@5.3.3) + '@storybook/builder-vite': 8.1.11(encoding@0.1.13)(prettier@3.3.2)(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)) '@storybook/node-logger': 8.1.11 - '@storybook/react': 8.1.11(prettier@3.3.2)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3) + '@storybook/react': 8.1.11(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@storybook/types': 8.1.11 find-up: 5.0.0 magic-string: 0.30.8 @@ -16734,7 +16773,7 @@ snapshots: react-dom: 18.3.1(react@18.3.1) resolve: 1.22.8 tsconfig-paths: 4.2.0 - vite: 5.3.3(@types/node@18.11.19) + vite: 5.3.3(@types/node@18.11.19)(terser@5.30.0) transitivePeerDependencies: - '@preact/preset-vite' - encoding @@ -16744,13 +16783,13 @@ snapshots: - typescript - vite-plugin-glimmerx - '@storybook/react@8.1.11(prettier@3.3.2)(react-dom@18.3.1)(react@18.3.1)(typescript@5.5.3)': + '@storybook/react@8.1.11(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: '@storybook/client-logger': 8.1.11 - '@storybook/docs-tools': 8.1.11(prettier@3.3.2) + '@storybook/docs-tools': 8.1.11(encoding@0.1.13)(prettier@3.3.2) '@storybook/global': 5.0.0 '@storybook/preview-api': 8.1.11 - '@storybook/react-dom-shim': 8.1.11(react-dom@18.3.1)(react@18.3.1) + '@storybook/react-dom-shim': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/types': 8.1.11 '@types/escodegen': 0.0.6 '@types/estree': 0.0.51 @@ -16764,12 +16803,13 @@ snapshots: prop-types: 15.8.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-element-to-jsx-string: 15.0.0(react-dom@18.3.1)(react@18.3.1) + react-element-to-jsx-string: 15.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) semver: 7.6.2 ts-dedent: 2.2.0 type-fest: 2.19.0 - typescript: 5.5.3 util-deprecate: 1.0.2 + optionalDependencies: + typescript: 5.5.3 transitivePeerDependencies: - encoding - prettier @@ -16781,10 +16821,10 @@ snapshots: memoizerific: 1.11.3 qs: 6.12.0 - '@storybook/telemetry@8.1.11(prettier@3.3.2)': + '@storybook/telemetry@8.1.11(encoding@0.1.13)(prettier@3.3.2)': dependencies: '@storybook/client-logger': 8.1.11 - '@storybook/core-common': 8.1.11(prettier@3.3.2) + '@storybook/core-common': 8.1.11(encoding@0.1.13)(prettier@3.3.2) '@storybook/csf-tools': 8.1.11 chalk: 4.1.2 detect-package-manager: 2.0.1 @@ -16796,14 +16836,14 @@ snapshots: - prettier - supports-color - '@storybook/test@8.1.11(vitest@1.6.0)': + '@storybook/test@8.1.11(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0))': dependencies: '@storybook/client-logger': 8.1.11 '@storybook/core-events': 8.1.11 '@storybook/instrumenter': 8.1.11 '@storybook/preview-api': 8.1.11 '@testing-library/dom': 10.1.0 - '@testing-library/jest-dom': 6.4.5(vitest@1.6.0) + '@testing-library/jest-dom': 6.4.5(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)) '@testing-library/user-event': 14.5.2(@testing-library/dom@10.1.0) '@vitest/expect': 1.6.0 '@vitest/spy': 1.6.0 @@ -16815,12 +16855,13 @@ snapshots: - jest - vitest - '@storybook/theming@8.1.11(react-dom@18.3.1)(react@18.3.1)': + '@storybook/theming@8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.3.1) '@storybook/client-logger': 8.1.11 '@storybook/global': 5.0.0 memoizerific: 1.11.3 + optionalDependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -16890,7 +16931,7 @@ snapshots: '@babel/types': 7.24.7 entities: 4.5.0 - '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0)': + '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.5.3))': dependencies: '@babel/core': 7.24.7 '@svgr/babel-preset': 8.1.0(@babel/core@7.24.7) @@ -16900,7 +16941,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0)(typescript@5.5.3)': + '@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0(typescript@5.5.3))(typescript@5.5.3)': dependencies: '@svgr/core': 8.1.0(typescript@5.5.3) cosmiconfig: 8.3.6(typescript@5.5.3) @@ -16917,8 +16958,8 @@ snapshots: '@babel/preset-react': 7.24.1(@babel/core@7.24.7) '@babel/preset-typescript': 7.24.1(@babel/core@7.24.7) '@svgr/core': 8.1.0(typescript@5.5.3) - '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0) - '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0)(typescript@5.5.3) + '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.5.3)) + '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.5.3))(typescript@5.5.3) transitivePeerDependencies: - supports-color - typescript @@ -16953,7 +16994,7 @@ snapshots: '@swc/core-win32-x64-msvc@1.6.7': optional: true - '@swc/core@1.6.7': + '@swc/core@1.6.7(@swc/helpers@0.5.8)': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.9 @@ -16968,6 +17009,7 @@ snapshots: '@swc/core-win32-arm64-msvc': 1.6.7 '@swc/core-win32-ia32-msvc': 1.6.7 '@swc/core-win32-x64-msvc': 1.6.7 + '@swc/helpers': 0.5.8 '@swc/counter@0.1.3': {} @@ -17005,7 +17047,7 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.4.5(vitest@1.6.0)': + '@testing-library/jest-dom@6.4.5(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0))': dependencies: '@adobe/css-tools': 4.4.0 '@babel/runtime': 7.24.1 @@ -17015,9 +17057,10 @@ snapshots: dom-accessibility-api: 0.6.3 lodash: 4.17.21 redent: 3.0.0 - vitest: 1.6.0(@types/node@18.11.19) + optionalDependencies: + vitest: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) - '@testing-library/jest-dom@6.4.6(vitest@1.6.0)': + '@testing-library/jest-dom@6.4.6(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0))': dependencies: '@adobe/css-tools': 4.4.0 '@babel/runtime': 7.24.1 @@ -17027,16 +17070,18 @@ snapshots: dom-accessibility-api: 0.6.3 lodash: 4.17.21 redent: 3.0.0 - vitest: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + optionalDependencies: + vitest: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) - '@testing-library/react@16.0.0(@testing-library/dom@10.2.0)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1)': + '@testing-library/react@16.0.0(@testing-library/dom@10.2.0)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.1 '@testing-library/dom': 10.2.0 - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.3 + '@types/react-dom': 18.3.0 '@testing-library/user-event@14.5.2(@testing-library/dom@10.1.0)': dependencies: @@ -17354,7 +17399,7 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.15.0)(eslint@8.57.0)(typescript@5.5.3)': + '@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)': dependencies: '@eslint-community/regexpp': 4.10.0 '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.5.3) @@ -17367,6 +17412,7 @@ snapshots: ignore: 5.3.1 natural-compare: 1.4.0 ts-api-utils: 1.3.0(typescript@5.5.3) + optionalDependencies: typescript: 5.5.3 transitivePeerDependencies: - supports-color @@ -17379,6 +17425,7 @@ snapshots: '@typescript-eslint/visitor-keys': 7.15.0 debug: 4.3.4 eslint: 8.57.0 + optionalDependencies: typescript: 5.5.3 transitivePeerDependencies: - supports-color @@ -17409,6 +17456,7 @@ snapshots: debug: 4.3.4 eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.5.3) + optionalDependencies: typescript: 5.5.3 transitivePeerDependencies: - supports-color @@ -17425,6 +17473,7 @@ snapshots: minimatch: 9.0.5 semver: 7.6.2 ts-api-utils: 1.3.0(typescript@5.5.3) + optionalDependencies: typescript: 5.5.3 transitivePeerDependencies: - supports-color @@ -17447,18 +17496,18 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-react@4.3.1(vite@5.3.3)': + '@vitejs/plugin-react@4.3.1(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0))': dependencies: '@babel/core': 7.24.7 '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.24.7) '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.7) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 5.3.3(@types/node@18.11.19) + vite: 5.3.3(@types/node@18.11.19)(terser@5.30.0) transitivePeerDependencies: - supports-color - '@vitest/coverage-v8@1.6.0(vitest@1.6.0)': + '@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 0.2.3 @@ -17473,7 +17522,7 @@ snapshots: std-env: 3.7.0 strip-literal: 2.1.0 test-exclude: 6.0.0 - vitest: 1.6.0(@types/node@18.11.19) + vitest: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) transitivePeerDependencies: - supports-color @@ -17508,7 +17557,7 @@ snapshots: pathe: 1.1.2 picocolors: 1.0.1 sirv: 2.0.4 - vitest: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3) + vitest: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) '@vitest/utils@1.6.0': dependencies: @@ -17635,8 +17684,9 @@ snapshots: minimatch: 9.0.5 muggle-string: 0.3.1 path-browserify: 1.0.1 - typescript: 5.5.3 vue-template-compiler: 2.7.16 + optionalDependencies: + typescript: 5.5.3 '@vue/shared@3.4.27': {} @@ -17804,15 +17854,15 @@ snapshots: indent-string: 5.0.0 ajv-draft-04@1.0.0(ajv@8.16.0): - dependencies: + optionalDependencies: ajv: 8.16.0 ajv-formats@2.1.1(ajv@8.16.0): - dependencies: + optionalDependencies: ajv: 8.16.0 ajv-formats@3.0.1(ajv@8.16.0): - dependencies: + optionalDependencies: ajv: 8.16.0 ajv-keywords@3.5.2(ajv@6.12.6): @@ -18041,12 +18091,12 @@ snapshots: dependencies: '@babel/core': 7.24.7 - babel-loader@9.1.3(@babel/core@7.24.7)(webpack@5.91.0): + babel-loader@9.1.3(@babel/core@7.24.7)(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: '@babel/core': 7.24.7 find-cache-dir: 4.0.0 schema-utils: 4.2.0 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) babel-plugin-dynamic-import-node@2.3.3: dependencies: @@ -18604,7 +18654,7 @@ snapshots: copy-text-to-clipboard@3.2.0: {} - copy-webpack-plugin@11.0.0(webpack@5.91.0): + copy-webpack-plugin@11.0.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: fast-glob: 3.3.2 glob-parent: 6.0.2 @@ -18612,7 +18662,7 @@ snapshots: normalize-path: 3.0.0 schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) core-js-compat@3.37.1: dependencies: @@ -18642,6 +18692,7 @@ snapshots: js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 + optionalDependencies: typescript: 5.5.3 cosmiconfig@9.0.0(typescript@5.5.3): @@ -18650,6 +18701,7 @@ snapshots: import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 + optionalDependencies: typescript: 5.5.3 create-require@1.1.1: {} @@ -18767,7 +18819,7 @@ snapshots: dependencies: postcss: 8.4.39 - css-loader@6.10.0(webpack@5.91.0): + css-loader@6.10.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: icss-utils: 5.1.0(postcss@8.4.39) postcss: 8.4.39 @@ -18777,18 +18829,20 @@ snapshots: postcss-modules-values: 4.0.0(postcss@8.4.39) postcss-value-parser: 4.2.0 semver: 7.6.2 - webpack: 5.91.0(@swc/core@1.6.7) + optionalDependencies: + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) - css-minimizer-webpack-plugin@5.0.1(clean-css@5.3.3)(webpack@5.91.0): + css-minimizer-webpack-plugin@5.0.1(clean-css@5.3.3)(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: '@jridgewell/trace-mapping': 0.3.25 - clean-css: 5.3.3 cssnano: 6.1.2(postcss@8.4.39) jest-worker: 29.7.0 postcss: 8.4.39 schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) + optionalDependencies: + clean-css: 5.3.3 css-select@4.3.0: dependencies: @@ -19638,10 +19692,11 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.15.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): dependencies: - '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.5.3) debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: @@ -19657,9 +19712,8 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.15.0)(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0): dependencies: - '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.5.3) array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 array.prototype.flat: 1.3.2 @@ -19668,7 +19722,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.15.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -19678,6 +19732,8 @@ snapshots: object.values: 1.2.0 semver: 6.3.1 tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.5.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -19709,11 +19765,12 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-vitest@0.5.4(eslint@8.57.0)(typescript@5.5.3)(vitest@1.6.0): + eslint-plugin-vitest@0.5.4(eslint@8.57.0)(typescript@5.5.3)(vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0)): dependencies: '@typescript-eslint/utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 - vitest: 1.6.0(@types/node@18.11.19) + optionalDependencies: + vitest: 1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0) transitivePeerDependencies: - supports-color - typescript @@ -19986,11 +20043,11 @@ snapshots: dependencies: flat-cache: 4.0.1 - file-loader@6.2.0(webpack@5.91.0): + file-loader@6.2.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) file-system-cache@2.3.0: dependencies: @@ -20093,7 +20150,7 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - fork-ts-checker-webpack-plugin@6.5.3(eslint@8.57.0)(typescript@5.5.3)(webpack@5.91.0): + fork-ts-checker-webpack-plugin@6.5.3(eslint@8.57.0)(typescript@5.5.3)(vue-template-compiler@2.7.16)(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: '@babel/code-frame': 7.24.7 '@types/json-schema': 7.0.15 @@ -20101,7 +20158,6 @@ snapshots: chokidar: 3.6.0 cosmiconfig: 6.0.0 deepmerge: 4.3.1 - eslint: 8.57.0 fs-extra: 9.1.0 glob: 7.2.3 memfs: 3.5.3 @@ -20110,7 +20166,10 @@ snapshots: semver: 7.6.2 tapable: 1.1.3 typescript: 5.5.3 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) + optionalDependencies: + eslint: 8.57.0 + vue-template-compiler: 2.7.16 form-data-encoder@2.1.4: {} @@ -20608,14 +20667,15 @@ snapshots: html-void-elements@3.0.0: {} - html-webpack-plugin@5.6.0(webpack@5.91.0): + html-webpack-plugin@5.6.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 lodash: 4.17.21 pretty-error: 4.0.0 tapable: 2.2.1 - webpack: 5.91.0(@swc/core@1.6.7) + optionalDependencies: + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) htmlparser2@6.1.0: dependencies: @@ -20669,12 +20729,13 @@ snapshots: http-proxy-middleware@2.0.6(@types/express@4.17.21): dependencies: - '@types/express': 4.17.21 '@types/http-proxy': 1.17.14 http-proxy: 1.18.1 is-glob: 4.0.3 is-plain-obj: 3.0.0 micromatch: 4.0.7 + optionalDependencies: + '@types/express': 4.17.21 transitivePeerDependencies: - debug @@ -21090,7 +21151,7 @@ snapshots: jsbn@1.1.0: {} - jscodeshift@0.15.2(@babel/preset-env@7.24.5): + jscodeshift@0.15.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)): dependencies: '@babel/core': 7.24.7 '@babel/parser': 7.24.7 @@ -21099,7 +21160,6 @@ snapshots: '@babel/plugin-transform-nullish-coalescing-operator': 7.24.1(@babel/core@7.24.7) '@babel/plugin-transform-optional-chaining': 7.24.5(@babel/core@7.24.7) '@babel/plugin-transform-private-methods': 7.24.1(@babel/core@7.24.7) - '@babel/preset-env': 7.24.5(@babel/core@7.24.7) '@babel/preset-flow': 7.24.1(@babel/core@7.24.7) '@babel/preset-typescript': 7.24.1(@babel/core@7.24.7) '@babel/register': 7.23.7(@babel/core@7.24.7) @@ -21113,6 +21173,8 @@ snapshots: recast: 0.23.7 temp: 0.8.4 write-file-atomic: 2.4.3 + optionalDependencies: + '@babel/preset-env': 7.24.5(@babel/core@7.24.7) transitivePeerDependencies: - supports-color @@ -22197,11 +22259,11 @@ snapshots: min-indent@1.0.1: {} - mini-css-extract-plugin@2.8.1(webpack@5.91.0): + mini-css-extract-plugin@2.8.1(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: schema-utils: 4.2.0 tapable: 2.2.1 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) minimalistic-assert@1.0.1: {} @@ -22284,11 +22346,11 @@ snapshots: monaco-editor-core@0.50.0: {} - monaco-editor-webpack-plugin@7.1.0(monaco-editor@0.46.0)(webpack@5.91.0): + monaco-editor-webpack-plugin@7.1.0(monaco-editor@0.46.0)(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: loader-utils: 2.0.4 monaco-editor: 0.46.0 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) monaco-editor@0.46.0: {} @@ -22358,9 +22420,11 @@ snapshots: node-fetch-native@1.6.4: {} - node-fetch@2.7.0: + node-fetch@2.7.0(encoding@0.1.13): dependencies: whatwg-url: 5.0.0 + optionalDependencies: + encoding: 0.1.13 node-forge@1.3.1: {} @@ -22943,13 +23007,13 @@ snapshots: postcss: 8.4.39 postcss-selector-parser: 6.0.16 - postcss-loader@7.3.4(postcss@8.4.38)(typescript@5.5.3)(webpack@5.91.0): + postcss-loader@7.3.4(postcss@8.4.38)(typescript@5.5.3)(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: cosmiconfig: 8.3.6(typescript@5.5.3) jiti: 1.21.0 postcss: 8.4.38 semver: 7.6.2 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) transitivePeerDependencies: - typescript @@ -23408,11 +23472,11 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 - raw-loader@4.0.2(webpack@5.91.0): + raw-loader@4.0.2(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) rc@1.2.8: dependencies: @@ -23421,7 +23485,7 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - react-dev-utils@12.0.1(eslint@8.57.0)(typescript@5.5.3)(webpack@5.91.0): + react-dev-utils@12.0.1(eslint@8.57.0)(typescript@5.5.3)(vue-template-compiler@2.7.16)(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: '@babel/code-frame': 7.24.7 address: 1.2.2 @@ -23432,7 +23496,7 @@ snapshots: escape-string-regexp: 4.0.0 filesize: 8.0.7 find-up: 5.0.0 - fork-ts-checker-webpack-plugin: 6.5.3(eslint@8.57.0)(typescript@5.5.3)(webpack@5.91.0) + fork-ts-checker-webpack-plugin: 6.5.3(eslint@8.57.0)(typescript@5.5.3)(vue-template-compiler@2.7.16)(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) global-modules: 2.0.0 globby: 11.1.0 gzip-size: 6.0.0 @@ -23447,8 +23511,9 @@ snapshots: shell-quote: 1.8.1 strip-ansi: 6.0.1 text-table: 0.2.0 + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) + optionalDependencies: typescript: 5.5.3 - webpack: 5.91.0(@swc/core@1.6.7) transitivePeerDependencies: - eslint - supports-color @@ -23479,7 +23544,7 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 - react-element-to-jsx-string@15.0.0(react-dom@18.3.1)(react@18.3.1): + react-element-to-jsx-string@15.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@base2/pretty-print-object': 1.0.1 is-plain-object: 5.0.0 @@ -23496,7 +23561,7 @@ snapshots: react-fast-compare@3.2.2: {} - react-helmet-async@1.3.0(react-dom@18.3.1)(react@18.3.1): + react-helmet-async@1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.24.1 invariant: 2.2.4 @@ -23506,7 +23571,7 @@ snapshots: react-fast-compare: 3.2.2 shallowequal: 1.1.0 - react-helmet-async@2.0.4(react-dom@18.3.1)(react@18.3.1): + react-helmet-async@2.0.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: invariant: 2.2.4 react: 18.3.1 @@ -23514,7 +23579,7 @@ snapshots: react-fast-compare: 3.2.2 shallowequal: 1.1.0 - react-hotkeys-hook@4.5.0(react-dom@18.3.1)(react@18.3.1): + react-hotkeys-hook@4.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -23531,15 +23596,15 @@ snapshots: dependencies: react: 18.3.1 - react-loadable-ssr-addon-v5-slorber@1.0.1(@docusaurus/react-loadable@6.0.0)(webpack@5.91.0): + react-loadable-ssr-addon-v5-slorber@1.0.1(@docusaurus/react-loadable@6.0.0(react@18.3.1))(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: '@babel/runtime': 7.24.1 react-loadable: '@docusaurus/react-loadable@6.0.0(react@18.3.1)' - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) react-refresh@0.14.2: {} - react-router-config@5.1.1(react-router@5.3.4)(react@18.3.1): + react-router-config@5.1.1(react-router@5.3.4(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.24.1 react: 18.3.1 @@ -23569,7 +23634,7 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - react-transition-group@4.4.5(react-dom@18.3.1)(react@18.3.1): + react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.24.1 dom-helpers: 5.2.1 @@ -23860,12 +23925,14 @@ snapshots: robust-predicates@3.0.2: {} - rollup-plugin-visualizer@5.12.0: + rollup-plugin-visualizer@5.12.0(rollup@4.18.0): dependencies: open: 8.4.2 picomatch: 2.3.1 source-map: 0.7.4 yargs: 17.7.2 + optionalDependencies: + rollup: 4.18.0 rollup@4.18.0: dependencies: @@ -23947,10 +24014,6 @@ snapshots: dependencies: xmlchars: 2.2.0 - scheduler@0.23.0: - dependencies: - loose-envify: 1.4.0 - scheduler@0.23.2: dependencies: loose-envify: 1.4.0 @@ -24431,11 +24494,11 @@ snapshots: swagger-ui-dist@5.17.14: {} - swc-loader@0.2.6(@swc/core@1.6.7)(webpack@5.91.0): + swc-loader@0.2.6(@swc/core@1.6.7(@swc/helpers@0.5.8))(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: - '@swc/core': 1.6.7 + '@swc/core': 1.6.7(@swc/helpers@0.5.8) '@swc/counter': 0.1.3 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) symbol-tree@3.2.4: {} @@ -24523,15 +24586,16 @@ snapshots: type-fest: 2.19.0 unique-string: 3.0.0 - terser-webpack-plugin@5.3.10(@swc/core@1.6.7)(webpack@5.91.0): + terser-webpack-plugin@5.3.10(@swc/core@1.6.7(@swc/helpers@0.5.8))(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: '@jridgewell/trace-mapping': 0.3.25 - '@swc/core': 1.6.7 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.30.0 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) + optionalDependencies: + '@swc/core': 1.6.7(@swc/helpers@0.5.8) terser@5.30.0: dependencies: @@ -24612,7 +24676,7 @@ snapshots: ts-dedent@2.2.0: {} - ts-node@10.9.2(@types/node@18.11.19)(typescript@5.5.3): + ts-node@10.9.2(@swc/core@1.6.7)(@types/node@18.11.19)(typescript@5.5.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 @@ -24629,6 +24693,8 @@ snapshots: typescript: 5.5.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 + optionalDependencies: + '@swc/core': 1.6.7(@swc/helpers@0.5.8) ts-toolbelt@9.6.0: {} @@ -24736,7 +24802,7 @@ snapshots: dependencies: is-typedarray: 1.0.0 - typedoc-plugin-markdown@4.1.1(typedoc@0.26.3): + typedoc-plugin-markdown@4.1.1(typedoc@0.26.3(typescript@5.5.3)): dependencies: typedoc: 0.26.3(typescript@5.5.3) @@ -24751,10 +24817,11 @@ snapshots: typescript-eslint@7.15.0(eslint@8.57.0)(typescript@5.5.3): dependencies: - '@typescript-eslint/eslint-plugin': 7.15.0(@typescript-eslint/parser@7.15.0)(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/eslint-plugin': 7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.5.3) '@typescript-eslint/utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 + optionalDependencies: typescript: 5.5.3 transitivePeerDependencies: - supports-color @@ -24914,20 +24981,21 @@ snapshots: url-join@4.0.1: {} - url-loader@4.1.1(file-loader@6.2.0)(webpack@5.91.0): + url-loader@4.1.1(file-loader@6.2.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))))(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: - file-loader: 6.2.0(webpack@5.91.0) loader-utils: 2.0.4 mime-types: 2.1.35 schema-utils: 3.3.0 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) + optionalDependencies: + file-loader: 6.2.0(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) url-parse@1.5.10: dependencies: querystringify: 2.2.0 requires-port: 1.0.0 - use-disposable@1.0.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1): + use-disposable@1.0.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@types/react': 18.3.3 '@types/react-dom': 18.3.0 @@ -25004,13 +25072,13 @@ snapshots: unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 - vite-node@1.6.0(@types/node@18.11.19): + vite-node@1.6.0(@types/node@18.11.19)(terser@5.30.0): dependencies: cac: 6.7.14 debug: 4.3.4 pathe: 1.1.2 picocolors: 1.0.1 - vite: 5.3.3(@types/node@18.11.19) + vite: 5.3.3(@types/node@18.11.19)(terser@5.30.0) transitivePeerDependencies: - '@types/node' - less @@ -25021,7 +25089,7 @@ snapshots: - supports-color - terser - vite-plugin-checker@0.7.0(eslint@8.57.0)(typescript@5.5.3)(vite@5.3.3): + vite-plugin-checker@0.7.0(eslint@8.57.0)(optionator@0.9.3)(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)): dependencies: '@babel/code-frame': 7.24.7 '@volar/typescript': 2.3.4 @@ -25029,20 +25097,22 @@ snapshots: chalk: 4.1.2 chokidar: 3.6.0 commander: 8.3.0 - eslint: 8.57.0 fast-glob: 3.3.2 fs-extra: 11.2.0 npm-run-path: 4.0.1 strip-ansi: 6.0.1 tiny-invariant: 1.3.3 - typescript: 5.5.3 - vite: 5.3.3(@types/node@18.11.19) + vite: 5.3.3(@types/node@18.11.19)(terser@5.30.0) vscode-languageclient: 7.0.0 vscode-languageserver: 7.0.0 vscode-languageserver-textdocument: 1.0.11 vscode-uri: 3.0.8 + optionalDependencies: + eslint: 8.57.0 + optionator: 0.9.3 + typescript: 5.5.3 - vite-plugin-dts@3.9.1(@types/node@18.11.19)(typescript@5.5.3)(vite@5.3.3): + vite-plugin-dts@3.9.1(@types/node@18.11.19)(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.3(@types/node@18.11.19)(terser@5.30.0)): dependencies: '@microsoft/api-extractor': 7.43.0(@types/node@18.11.19) '@rollup/pluginutils': 5.1.0(rollup@4.18.0) @@ -25051,34 +25121,36 @@ snapshots: kolorist: 1.8.0 magic-string: 0.30.8 typescript: 5.5.3 - vite: 5.3.3(@types/node@18.11.19) vue-tsc: 1.8.27(typescript@5.5.3) + optionalDependencies: + vite: 5.3.3(@types/node@18.11.19)(terser@5.30.0) transitivePeerDependencies: - '@types/node' - rollup - supports-color - vite@5.2.11(@types/node@18.11.19): + vite@5.2.11(@types/node@18.11.19)(terser@5.30.0): dependencies: - '@types/node': 18.11.19 esbuild: 0.20.2 postcss: 8.4.38 rollup: 4.18.0 optionalDependencies: + '@types/node': 18.11.19 fsevents: 2.3.3 + terser: 5.30.0 - vite@5.3.3(@types/node@18.11.19): + vite@5.3.3(@types/node@18.11.19)(terser@5.30.0): dependencies: - '@types/node': 18.11.19 esbuild: 0.21.5 postcss: 8.4.39 rollup: 4.18.0 optionalDependencies: + '@types/node': 18.11.19 fsevents: 2.3.3 + terser: 5.30.0 - vitest@1.6.0(@types/node@18.11.19): + vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0(vitest@1.6.0))(happy-dom@14.12.3)(jsdom@19.0.0)(terser@5.30.0): dependencies: - '@types/node': 18.11.19 '@vitest/expect': 1.6.0 '@vitest/runner': 1.6.0 '@vitest/snapshot': 1.6.0 @@ -25096,43 +25168,14 @@ snapshots: strip-literal: 2.1.0 tinybench: 2.6.0 tinypool: 0.8.3 - vite: 5.3.3(@types/node@18.11.19) - vite-node: 1.6.0(@types/node@18.11.19) + vite: 5.2.11(@types/node@18.11.19)(terser@5.30.0) + vite-node: 1.6.0(@types/node@18.11.19)(terser@5.30.0) why-is-node-running: 2.2.2 - transitivePeerDependencies: - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - - vitest@1.6.0(@types/node@18.11.19)(@vitest/ui@1.6.0)(happy-dom@14.12.3): - dependencies: + optionalDependencies: '@types/node': 18.11.19 - '@vitest/expect': 1.6.0 - '@vitest/runner': 1.6.0 - '@vitest/snapshot': 1.6.0 - '@vitest/spy': 1.6.0 '@vitest/ui': 1.6.0(vitest@1.6.0) - '@vitest/utils': 1.6.0 - acorn-walk: 8.3.2 - chai: 4.4.1 - debug: 4.3.4 - execa: 8.0.1 happy-dom: 14.12.3 - local-pkg: 0.5.0 - magic-string: 0.30.8 - pathe: 1.1.2 - picocolors: 1.0.1 - std-env: 3.7.0 - strip-literal: 2.1.0 - tinybench: 2.6.0 - tinypool: 0.8.3 - vite: 5.2.11(@types/node@18.11.19) - vite-node: 1.6.0(@types/node@18.11.19) - why-is-node-running: 2.2.2 + jsdom: 19.0.0 transitivePeerDependencies: - less - lightningcss @@ -25248,16 +25291,16 @@ snapshots: - bufferutil - utf-8-validate - webpack-dev-middleware@5.3.4(webpack@5.91.0): + webpack-dev-middleware@5.3.4(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: colorette: 2.0.20 memfs: 3.5.3 mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.2.0 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) - webpack-dev-server@4.15.2(webpack@5.91.0): + webpack-dev-server@4.15.2(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -25287,9 +25330,10 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack: 5.91.0(@swc/core@1.6.7) - webpack-dev-middleware: 5.3.4(webpack@5.91.0) + webpack-dev-middleware: 5.3.4(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) ws: 8.16.0 + optionalDependencies: + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) transitivePeerDependencies: - bufferutil - debug @@ -25306,7 +25350,7 @@ snapshots: webpack-virtual-modules@0.6.1: {} - webpack@5.91.0(@swc/core@1.6.7): + webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.5 @@ -25329,7 +25373,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.6.7)(webpack@5.91.0) + terser-webpack-plugin: 5.3.10(@swc/core@1.6.7(@swc/helpers@0.5.8))(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))) watchpack: 2.4.1 webpack-sources: 3.2.3 transitivePeerDependencies: @@ -25337,13 +25381,13 @@ snapshots: - esbuild - uglify-js - webpackbar@5.0.2(webpack@5.91.0): + webpackbar@5.0.2(webpack@5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8))): dependencies: chalk: 4.1.2 consola: 2.15.3 pretty-time: 1.1.0 std-env: 3.7.0 - webpack: 5.91.0(@swc/core@1.6.7) + webpack: 5.91.0(@swc/core@1.6.7(@swc/helpers@0.5.8)) websocket-driver@0.7.4: dependencies: diff --git a/tsconfig.ws.json b/tsconfig.ws.json index 9221670b2e..f20e06a030 100644 --- a/tsconfig.ws.json +++ b/tsconfig.ws.json @@ -19,7 +19,8 @@ { "path": "packages/samples/tsconfig.json" }, { "path": "packages/json-schema/tsconfig.json" }, { "path": "packages/best-practices/tsconfig.json" }, - { "path": "packages/xml/tsconfig.json" } + { "path": "packages/xml/tsconfig.json" }, + { "path": "packages/http-server-javascript/tsconfig.json" } ], "files": [] }