From 33142d7bc7efba403575dafa7f15100ccf9aeb5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulin=20H=C3=A9leine?= Date: Sat, 10 Jan 2026 18:54:46 +0100 Subject: [PATCH 1/3] Add route middleware pipeline --- README.md | 82 +++++++++++---- package.json | 4 +- src/data-functions.ts | 102 ++++++++++++++++++ src/index.ts | 109 ++----------------- src/route-middleware.ts | 47 +++++++++ src/shared-types.ts | 7 ++ tests/action.test.ts | 42 ++++++++ tests/loader.test.ts | 34 ++++++ tests/route-middleware.test.ts | 184 +++++++++++++++++++++++++++++++++ 9 files changed, 489 insertions(+), 122 deletions(-) create mode 100644 src/data-functions.ts create mode 100644 src/route-middleware.ts create mode 100644 src/shared-types.ts create mode 100644 tests/route-middleware.test.ts diff --git a/README.md b/README.md index 279de37..a74e8e0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

React Router Dataflow

-

A tiny, fully type-safe composer for React Router loaders and actions

+

A tiny, fully type-safe composer for React Router loaders, actions, and route guards.

@@ -12,8 +12,7 @@ React Router loaders and actions scale poorly once you start sharing logic. Context becomes implicit, middleware composition is manual, and type safety quickly degrades. -React Router Dataflow fixes this by letting you compose loaders and actions as -typed middleware pipelines, producing a fully type-safe context per route. +React Router Dataflow fixes this by letting you compose loaders, actions, and route guards as typed pipelines, producing a fully type-safe execution context per route. ```typescript import { Loader } from "react-router-dataflow"; @@ -65,7 +64,7 @@ const mw: LoaderMiddleware<{ data: string }> = async (args) => { Loader.with(mw); ``` -> Middlewares can also be typed action-only (`ActionMiddleware`) or universal (`Middleware`). +> Middlewares steps (for loader/action context pipelines) can also be typed action-only (`ActionMiddleware`) or universal (`Middleware`). ### Declare middlewares inline @@ -128,9 +127,44 @@ Action > For more advanced patterns such as context enforcement, parameterized middlewares and middleware factorization, see the [advanced middleware documentation](https://github.com/pheleine/react-router-dataflow/blob/master/docs/advanced_middlewares.md). +## RouteMiddleware - Guarding routes with React Router + +React Router Dataflow includes support for building **React Router middlewares** with a fully typed internal pipeline, using the same `with`/`build` builder API as loaders and actions. +`RouteMiddleware` is a builder that produces a **single React Router middleware** suitable for guarding routes and short-circuiting navigation. + +> `RouteMiddleware` is not related to middlewares types used by `Loader` and `Action` builders which are composing functions of loaders and actions. + +`RouteMiddleware` focuses on composing route guards by letting you compose a sequence of typed steps called **route requirements**. +Each requirement runs before the route is entered, can enrich internal context, and can throw a `Response` to block navigation. +Route requirements can be predefined in the same way as [loaders and actions middlewares](#define-reusable-middlewares) using `RouteRequirement` type. + +> `RouteMiddleware` does not support post-processing or response interception. +> If you need a pre/post middleware, write a React Router middleware directly and compose it alongside `RouteMiddleware`. + +> *Terminology* +> - **Middleware**: a loader/action pipeline step +> - **RouteMiddleware**: a builder that produces a React Router middleware +> - **RouteRequirement**: a typed guard step executed inside a RouteMiddleware + +```typescript +import { RouteMiddleware } from "react-router-dataflow"; +import { requireAuth } from "~/guards/require-auth"; + +// Ensures user is authenticated and has "admin" role +RouteMiddleware + .with(requireAuth) // => { user } + .build(async (_, { user }) => { + if (user.role !== "admin") { + throw new Response("Unauthorized", { status: 401 }); + } + + return null; + }); +``` + ## Integration in React Router -Loaders and actions created with React Router Dataflow are standard React Router data functions and behave the same way on the client and on the server. +Loaders, actions, and route middlewares created with React Router Dataflow are standard React Router primitives and behave the same way on the client and on the server. They can be used in: - framework mode (route files) - data routers (`createBrowserRouter`) @@ -139,21 +173,33 @@ They can be used in: ### Framework mode example ```tsx -// app/routes/example.tsx +// app/routes/data.$id.tsx import { Loader, Action } from "react-router-dataflow"; -import { requireAuth } from "~/middlewares/require-auth"; - -// Auth is enforced, no data is returned -export const loader = Loader.with(requireAuth).build(); - -// Auth is enforced, only PATCH/patch requests are handled -export const action = Action.with(requireAuth).build({ - PATCH: async ({ request }) => { - const updatedData = /* data update using request */; - return { updatedData }; - } -}); +import { requireAuth } from "~/guards/require-auth"; +import { dataFromParams } from "~/middlewares/data-from-params"; + +// Auth is enforced on the route +export const middleware = [ + RouteMiddleware + .with(requireAuth) + .build() +]; + +// => reached only if authenticated, get data from route params +export const loader = Loader + .with(dataFromParams) // => { data } + .build(async (_, { data }) => data); + +// => reached only if authenticated, only PATCH/patch requests are handled +export const action = Action + .with(dataFromParams) // => { data } + .build({ + PATCH: async ({ request }, { data }) => { + const updatedData = /* data update using request */; + return updatedData; + } + }); const ExamplePage = () =>

Example page

; diff --git a/package.json b/package.json index aa72867..e593ed1 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "react-router-dataflow", - "version": "1.0.1", + "version": "1.1.0", "license": "MIT", "type": "module", "author": "Paulin Héleine", - "description": "A tiny, fully type-safe composer for React Router loaders and actions", + "description": "A tiny, fully type-safe composer for React Router loaders, actions, and route guards", "sideEffects": false, "files": [ "dist", diff --git a/src/data-functions.ts b/src/data-functions.ts new file mode 100644 index 0000000..1534b13 --- /dev/null +++ b/src/data-functions.ts @@ -0,0 +1,102 @@ +import { LoaderFunctionArgs, ActionFunctionArgs } from "react-router"; +import { Normalize, ContextBuilder } from "./shared-types"; + +type DataFunctionArgs = LoaderFunctionArgs | ActionFunctionArgs; +type DataFunction = (args: A) => Promise>; + +type Handler = (args: A, context: C) => Promise>; + +type InternalMiddleware = (args: A, context: C) => Promise; +type LoaderMiddleware = InternalMiddleware; +type ActionMiddleware = InternalMiddleware; +type Middleware = InternalMiddleware; + +type LoaderBuilder = { + with(middleware: LoaderMiddleware): LoaderBuilder>; + build(handler: Handler): DataFunction; + build(): DataFunction; +}; + +const createLoaderBuilder = (buildContext: ContextBuilder): LoaderBuilder => ({ + with(middleware: LoaderMiddleware) { + return createLoaderBuilder(async (args) => { + const context = await buildContext(args); + const result = await middleware(args, context); + + return (result === null ? context : { ...context, ...result }) as C & Normalize; + }); + }, + + // handlers must be typed to allow its optionality. The function overloads + // ensure type safety at the call site, but any must be used to type handler. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + build(handler?: Handler) { + return async (args: LoaderFunctionArgs) => { + const context = await buildContext(args); + + return handler !== undefined ? handler(args, context) : null; + }; + } +}); + +const Loader = createLoaderBuilder(async () => ({})); + +type ActionBuilder = { + with(middleware: ActionMiddleware): ActionBuilder>; + + // Use of any is necessary to allow different return types for handlers. + // The return type of the resulting function is infered automatically from their return types. + // TypeScript cannot express a constraint that allows "any R" while still preserving + // the ability to infer the union of all handler return types. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + build>>(handlers: H): DataFunction>>; +}; + +const createActionBuilder = (buildContext: ContextBuilder): ActionBuilder => ({ + with(middleware: ActionMiddleware) { + return createActionBuilder(async (args) => { + const context = await buildContext(args); + const result = await middleware(args, context); + + return (result === null ? context : { ...context, ...result }) as C & Normalize; + }); + }, + + build(handlers) { + // The return type cannot be known in advance as handlers can have different return types. + // Any is necessary because TypeScript cannot express a Record type where each value + // has a different generic type parameter (R) while maintaining type safety. + // The actual return type is correctly inferred at the call site through the overload signature. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const handlersMap: Record> = {}; + + for (const [ key, handler ] of Object.entries(handlers)) { + handlersMap[key.toLowerCase()] = handler; + } + + return async (args) => { + const context = await buildContext(args); + const method = args.request.method.toLowerCase(); + const handler = handlersMap[method]; + + if (!handler) { + throw new Response("Method not allowed", { status: 405 }); + } + + return handler(args, context); + }; + } +}); + +const Action = createActionBuilder(async () => ({})); + +export { + Loader, + Action +}; + +export type { + Middleware, + LoaderMiddleware, + ActionMiddleware +}; diff --git a/src/index.ts b/src/index.ts index 4fb0b18..9e9529a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,110 +1,15 @@ -import type { LoaderFunctionArgs, ActionFunctionArgs } from "react-router"; - -type DataFunctionArgs = LoaderFunctionArgs | ActionFunctionArgs; -type DataFunction = (args: A) => Promise>; - -type Handler = (args: A, context: C) => Promise>; - -type InternalMiddleware = (args: A, context: C) => Promise; -type LoaderMiddleware = InternalMiddleware; -type ActionMiddleware = InternalMiddleware; -type Middleware = InternalMiddleware; - -type ContextBuilder = (args: A) => Promise; - -type Normalize = R extends null ? object : R; - -type LoaderBuilder = { - with(middleware: LoaderMiddleware): LoaderBuilder>; - build(handler: Handler): DataFunction; - build(): DataFunction; -}; - -const createLoaderBuilder = (buildContext: ContextBuilder): LoaderBuilder => ({ - with(middleware: LoaderMiddleware) { - return createLoaderBuilder(async (args) => { - const context = await buildContext(args); - const result = await middleware(args, context); - - return (result === null ? context : { ...context, ...result }) as C & Normalize; - }); - }, - - // handlers must be typed to allow its optionality. The function overloads - // ensure type safety at the call site, but any must be used to type handler. - // eslint-disable-next-line @typescript-eslint/no-explicit-any - build(handler?: Handler) { - if (handler === undefined) { - return async () => null; - } - - return async (args: LoaderFunctionArgs) => { - const context = await buildContext(args); - - return handler(args, context); - }; - } -}); - -const Loader = createLoaderBuilder(async () => ({})); - -type ActionBuilder = { - with(middleware: ActionMiddleware): ActionBuilder>; - - // Use of any is necessary to allow different return types for handlers. - // The return type of the resulting function is infered automatically from their return types. - // TypeScript cannot express a constraint that allows "any R" while still preserving - // the ability to infer the union of all handler return types. - // eslint-disable-next-line @typescript-eslint/no-explicit-any - build>>(handlers: H): DataFunction>>; -}; - -const createActionBuilder = (buildContext: ContextBuilder): ActionBuilder => ({ - with(middleware: ActionMiddleware) { - return createActionBuilder(async (args) => { - const context = await buildContext(args); - const result = await middleware(args, context); - - return (result === null ? context : { ...context, ...result }) as C & Normalize; - }); - }, - - build(handlers) { - // The return type cannot be known in advance as handlers can have different return types. - // Any is necessary because TypeScript cannot express a Record type where each value - // has a different generic type parameter (R) while maintaining type safety. - // The actual return type is correctly inferred at the call site through the overload signature. - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const handlersMap: Record> = {}; - - for (const [ key, handler ] of Object.entries(handlers)) { - handlersMap[key.toLowerCase()] = handler; - } - - return async (args) => { - const method = args.request.method.toLowerCase(); - const handler = handlersMap[method]; - - if (!handler) { - throw new Response("Method not allowed", { status: 405 }); - } - - const context = await buildContext(args); - - return handler(args, context); - }; - } -}); - -const Action = createActionBuilder(async () => ({})); +import { Loader, Action, LoaderMiddleware, ActionMiddleware, Middleware } from "./data-functions"; +import { RouteMiddleware, RouteRequirement } from "./route-middleware"; export { Loader, - Action + Action, + RouteMiddleware }; export type { - Middleware, LoaderMiddleware, - ActionMiddleware + ActionMiddleware, + Middleware, + RouteRequirement }; diff --git a/src/route-middleware.ts b/src/route-middleware.ts new file mode 100644 index 0000000..5a22243 --- /dev/null +++ b/src/route-middleware.ts @@ -0,0 +1,47 @@ +import type { MiddlewareFunction, Params } from "react-router"; +import { Normalize, ContextBuilder } from "./shared-types"; + +type RouteMiddlewareArgs = { + request: Request; + params: Params; +}; + +type RouteRequirement = (args: RouteMiddlewareArgs, context: C) => Promise; +type RouteMiddlewareHandler = (args: RouteMiddlewareArgs, context: C) => Promise; + +type RouteMiddlewareBuilder = { + with(requirement: RouteRequirement): RouteMiddlewareBuilder>; + build(handler: RouteMiddlewareHandler): MiddlewareFunction; + build(): MiddlewareFunction; +}; + +const createRouteMiddlewareBuilder = (buildContext: ContextBuilder): RouteMiddlewareBuilder => ({ + with(requirement: RouteRequirement) { + return createRouteMiddlewareBuilder(async (args) => { + const context = await buildContext(args); + const result = await requirement(args, context); + + return (result === null ? context : { ...context, ...result }) as C & Normalize; + }); + }, + build(handler?: RouteMiddlewareHandler) { + return async (args, next) => { + const context = await buildContext(args); + + if (handler === undefined) { + return next(); + } + + return (await handler(args, context)) ?? next(); + }; + } +}); + +const RouteMiddleware = createRouteMiddlewareBuilder(async () => ({})); + +export { RouteMiddleware }; + +export type { + RouteRequirement, + RouteMiddlewareArgs +}; diff --git a/src/shared-types.ts b/src/shared-types.ts new file mode 100644 index 0000000..d03e526 --- /dev/null +++ b/src/shared-types.ts @@ -0,0 +1,7 @@ +type ContextBuilder = (args: A) => Promise; +type Normalize = R extends null ? object : R; + +export type { + ContextBuilder, + Normalize +}; diff --git a/tests/action.test.ts b/tests/action.test.ts index e34bec2..5a90cf1 100644 --- a/tests/action.test.ts +++ b/tests/action.test.ts @@ -240,3 +240,45 @@ describe("Action builder intermediate steps", () => { expect(result).toBe("post"); }); }); + +describe("Middlewares on the action usage", () => { + it("should be executed when method is handled", async () => { + let called = false; + + const action = Action + .with(async () => { + called = true; + + return null; + }) + .build({ + POST: async () => "post" + }); + + await action(MOCK_ARGS_POST); + + expect(called).toBe(true); + }); + + it("should be executed when method is not handled", async () => { + let called = false; + + const action = Action + .with(async () => { + called = true; + + return null; + }) + .build({ + POST: async () => "post" + }); + + try { + await action(MOCK_ARGS_DELETE); + } catch (error) { + expect(error).toBeInstanceOf(Response); + } + + expect(called).toBe(true); + }); +}); diff --git a/tests/loader.test.ts b/tests/loader.test.ts index 3c0b871..cd23ab3 100644 --- a/tests/loader.test.ts +++ b/tests/loader.test.ts @@ -171,3 +171,37 @@ describe("Loader builder intermediate steps", () => { expect(result).toBeNull(); }); }); + +describe("Middlewares on the loader usage", () => { + it("should be executed with default build", async () => { + let called = false; + + const loader = Loader + .with(async () => { + called = true; + + return null; + }) + .build(); + + await loader(MOCK_ARGS); + + expect(called).toBe(true); + }); + + it("should be executed with custom build", async () => { + let called = false; + + const loader = Loader + .with(async () => { + called = true; + + return null; + }) + .build(async () => null); + + await loader(MOCK_ARGS); + + expect(called).toBe(true); + }); +}); diff --git a/tests/route-middleware.test.ts b/tests/route-middleware.test.ts new file mode 100644 index 0000000..f2c8734 --- /dev/null +++ b/tests/route-middleware.test.ts @@ -0,0 +1,184 @@ +import { describe, expect, expectTypeOf, it } from "vitest"; +import { RouteMiddleware, RouteRequirement } from "../src"; +import { RouteMiddlewareArgs } from "../src/route-middleware"; + +const MOCK_ARGS = { + params: { id: "test" }, + request: new Request("http://example.com", { method: "GET" }), + // Any is used to mock the RouterContextProvider of React Router for testing. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + context: {} as any, + unstable_pattern: "" +}; +const MOCK_NEXT = async () => new Response(); +const CUSTOM_RESPONSE = new Response(null, { statusText: "custom response" }); + +describe("Route Middleware Builder", () => { + it("should build with an empty handler", async () => { + const routeMiddleware = RouteMiddleware.build(); + const result = await routeMiddleware(MOCK_ARGS, MOCK_NEXT); + + expect(result).toStrictEqual(await MOCK_NEXT()); + }); + + it("should build with a handler that returns nothing", async () => { + const routeMiddleware = RouteMiddleware.build(async () => { + return null; + }); + const result = await routeMiddleware(MOCK_ARGS, MOCK_NEXT); + + expect(result).toStrictEqual(await MOCK_NEXT()); + }); + + it("should build with a handler that returns a Response", async () => { + const routeMiddleware = RouteMiddleware.build(async () => { + return CUSTOM_RESPONSE; + }); + const result = await routeMiddleware(MOCK_ARGS, MOCK_NEXT); + + expect(result).toStrictEqual(CUSTOM_RESPONSE); + }); + + it("should pass function args to the handler", async () => { + const routeMiddleware = RouteMiddleware.build(async (args) => { + expectTypeOf(args).toEqualTypeOf(); + expect(args).toMatchObject({ + request: MOCK_ARGS.request, + params: MOCK_ARGS.params + }); + + return null; + }); + + await routeMiddleware(MOCK_ARGS, MOCK_NEXT); + }); +}); + +describe("Route Middleware builder intermediate steps", () => { + it("should enrich context with inline requirements", async () => { + const routeMiddleware = RouteMiddleware + .with(async () => { + return { + first: true + }; + }) + .with(async (_, context) => { + expectTypeOf(context).toMatchObjectType<{ first: boolean }>(); + expect(context).toStrictEqual({ first: true }); + + return { + second: "second" + }; + }) + .build(async (_, context) => { + expectTypeOf(context).toMatchObjectType<{ + first: boolean; + second: string; + }>(); + expect(context).toStrictEqual({ + first: true, + second: "second" + }); + + return null; + }); + + await routeMiddleware(MOCK_ARGS, MOCK_NEXT); + }); + + it("should enrich context with predefined requirements", async () => { + const requireOne: RouteRequirement<{ requireOne: string }> = async () => { + return { requireOne: "requireOne" }; + }; + + const requireTwo: RouteRequirement<{ requireTwo: string }> = async () => { + return { requireTwo: "requireTwo" }; + }; + + const routeMiddleware = RouteMiddleware + .with(requireOne) + .with(requireTwo) + .build(async (_, context) => { + expectTypeOf(context).toMatchObjectType<{ + requireOne: string; + requireTwo: string; + }>(); + expect(context).toStrictEqual({ + requireOne: "requireOne", + requireTwo: "requireTwo" + }); + + return null; + }); + + await routeMiddleware(MOCK_ARGS, MOCK_NEXT); + }); + + it("should not enrich context if requirements return null", async () => { + const routeMiddleware = RouteMiddleware + .with(async () => ({ first: true })) + .with(async () => ({ second: true })) + .with(async () => null) + .build(async (_, context) => { + expectTypeOf(context).toMatchObjectType<{ + first: boolean; + second: boolean; + }>(); + expect(context).toStrictEqual({ first: true, second: true }); + + return null; + }); + + await routeMiddleware(MOCK_ARGS, MOCK_NEXT); + }); + + it("should receive the args given to the route middleware", async () => { + const routeMiddleware = RouteMiddleware + .with(async (args) => { + expectTypeOf(args).toEqualTypeOf(); + expect(args).toMatchObject({ + request: MOCK_ARGS.request, + params: MOCK_ARGS.params + }); + + return null; + }) + .build(); + + await routeMiddleware(MOCK_ARGS, MOCK_NEXT); + }); +}); + +describe("Requirements on the route middleware usage", () => { + it("should be executed with default build", async () => { + let called = false; + + const routeMiddleware = RouteMiddleware + .with(async () => { + called = true; + + return null; + }) + .build(); + + await routeMiddleware(MOCK_ARGS, MOCK_NEXT); + + expect(called).toBe(true); + }); + + it("should be executed with custom build", async () => { + let called = false; + + const routeMiddleware = RouteMiddleware + .with(async () => { + called = true; + + return null; + }) + .build(async () => null); + + await routeMiddleware(MOCK_ARGS, MOCK_NEXT); + + expect(called).toBe(true); + }); +}); From 425f294751d6abed23b5b1c8a0ec4b14eb2c2f13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulin=20H=C3=A9leine?= Date: Sat, 10 Jan 2026 19:12:23 +0100 Subject: [PATCH 2/3] Add codecov badge --- .github/workflows/ci.yaml | 7 ++++--- README.md | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index bec45cb..0624681 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -42,8 +42,9 @@ jobs: run: pnpm build - name: Upload coverage reports - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 if: matrix.node-version == '20.x' with: - files: ./coverage/coverage-final.json - fail_ci_if_error: false \ No newline at end of file + files: coverage/lcov.info + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/README.md b/README.md index a74e8e0..87f3a83 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@

A tiny, fully type-safe composer for React Router loaders, actions, and route guards.

+

From 46d945d96ee9d7295ef7faccb8bb768eed272d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulin=20H=C3=A9leine?= Date: Sat, 10 Jan 2026 22:47:23 +0100 Subject: [PATCH 3/3] Fix ESM build --- package.json | 3 +- pnpm-lock.yaml | 271 +++++++++++++++++++++++++++++++++++++++++++++++++ tsconfig.json | 3 +- tsup.config.ts | 12 +++ 4 files changed, 286 insertions(+), 3 deletions(-) create mode 100644 tsup.config.ts diff --git a/package.json b/package.json index e593ed1..ce43335 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "scripts": { "test": "vitest --typecheck", "test:run": "vitest run --typecheck", - "build": "tsc" + "build": "tsup" }, "devDependencies": { "@eslint/js": "^9.39.2", @@ -48,6 +48,7 @@ "eslint": "^9.39.2", "eslint-plugin-unused-imports": "^4.3.0", "react-router": "^7.0.0", + "tsup": "^8.5.1", "typescript": "^5.0.0", "typescript-eslint": "^8.51.0", "vitest": "^4.0.16" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7ef0fcd..68669bc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,6 +32,9 @@ importers: react-router: specifier: ^7.0.0 version: 7.11.0(react@18.3.1) + tsup: + specifier: ^8.5.1 + version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3) typescript: specifier: ^5.0.0 version: 5.9.3 @@ -275,6 +278,9 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -539,6 +545,9 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -558,6 +567,16 @@ packages: brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + bundle-require@5.1.0: + resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.18' + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -570,6 +589,10 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -577,9 +600,20 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + cookie@1.1.1: resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} @@ -699,6 +733,9 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} + fix-dts-default-cjs-exports@1.0.1: + resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==} + flat-cache@4.0.1: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} @@ -773,6 +810,10 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -799,6 +840,17 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -827,9 +879,15 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} + mlly@1.8.0: + resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -838,6 +896,10 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + obug@2.1.1: resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} @@ -875,6 +937,31 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -901,10 +988,18 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + rollup@4.54.0: resolution: {integrity: sha512-3nk8Y3a9Ea8szgKhinMlGMhGMw89mqule3KWczxhIzqudyHdCIOHw8WJlj/r329fACjKLEh13ZSk7oE22kyeIw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -933,6 +1028,10 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -943,13 +1042,28 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + sucrase@3.35.1: + resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyexec@1.0.2: resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} engines: {node: '>=18'} @@ -962,12 +1076,38 @@ packages: resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} engines: {node: '>=14.0.0'} + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + ts-api-utils@2.3.0: resolution: {integrity: sha512-6eg3Y9SF7SsAvGzRHQvvc1skDAhwI4YQ32ui1scxD1Ccr0G5qIIbUBT3pFTKX8kmWIQClHobtUdNuaBgwdfdWg==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + tsup@8.5.1: + resolution: {integrity: sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + '@microsoft/api-extractor': ^7.36.0 + '@swc/core': ^1 + postcss: ^8.4.12 + typescript: '>=4.5.0' + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@swc/core': + optional: true + postcss: + optional: true + typescript: + optional: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -984,6 +1124,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + ufo@1.6.2: + resolution: {integrity: sha512-heMioaxBcG9+Znsda5Q8sQbWnLJSl98AFDXTO80wELWEzX3hordXsTdxrIfMQoO9IY1MEnoGoPjpoKpMj+Yx0Q==} + undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} @@ -1234,6 +1377,11 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/sourcemap-codec@1.5.5': {} @@ -1507,6 +1655,8 @@ snapshots: dependencies: color-convert: 2.0.1 + any-promise@1.3.0: {} + argparse@2.0.1: {} assertion-error@2.0.1: {} @@ -1528,6 +1678,13 @@ snapshots: dependencies: balanced-match: 1.0.2 + bundle-require@5.1.0(esbuild@0.27.2): + dependencies: + esbuild: 0.27.2 + load-tsconfig: 0.2.5 + + cac@6.7.14: {} + callsites@3.1.0: {} chai@6.2.2: {} @@ -1537,14 +1694,24 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + color-convert@2.0.1: dependencies: color-name: 1.1.4 color-name@1.1.4: {} + commander@4.1.1: {} + concat-map@0.0.1: {} + confbox@0.1.8: {} + + consola@3.4.2: {} + cookie@1.1.1: {} cross-spawn@7.0.6: @@ -1693,6 +1860,12 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 + fix-dts-default-cjs-exports@1.0.1: + dependencies: + magic-string: 0.30.21 + mlly: 1.8.0 + rollup: 4.54.0 + flat-cache@4.0.1: dependencies: flatted: 3.3.3 @@ -1756,6 +1929,8 @@ snapshots: jiti@2.6.1: optional: true + joycon@3.1.1: {} + js-tokens@4.0.0: {} js-tokens@9.0.1: {} @@ -1779,6 +1954,12 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + load-tsconfig@0.2.5: {} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -1811,12 +1992,27 @@ snapshots: dependencies: brace-expansion: 2.0.2 + mlly@1.8.0: + dependencies: + acorn: 8.15.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.2 + ms@2.1.3: {} + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + nanoid@3.3.11: {} natural-compare@1.4.0: {} + object-assign@4.1.1: {} + obug@2.1.1: {} optionator@0.9.4: @@ -1850,6 +2046,21 @@ snapshots: picomatch@4.0.3: {} + pirates@4.0.7: {} + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.0 + pathe: 2.0.3 + + postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.6): + dependencies: + lilconfig: 3.1.3 + optionalDependencies: + jiti: 2.6.1 + postcss: 8.5.6 + postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -1870,8 +2081,12 @@ snapshots: dependencies: loose-envify: 1.4.0 + readdirp@4.1.2: {} + resolve-from@4.0.0: {} + resolve-from@5.0.0: {} + rollup@4.54.0: dependencies: '@types/estree': 1.0.8 @@ -1914,18 +2129,40 @@ snapshots: source-map-js@1.2.1: {} + source-map@0.7.6: {} + stackback@0.0.2: {} std-env@3.10.0: {} strip-json-comments@3.1.1: {} + sucrase@3.35.1: + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + commander: 4.1.1 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.7 + tinyglobby: 0.2.15 + ts-interface-checker: 0.1.13 + supports-color@7.2.0: dependencies: has-flag: 4.0.0 + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + tinybench@2.9.0: {} + tinyexec@0.3.2: {} + tinyexec@1.0.2: {} tinyglobby@0.2.15: @@ -1935,10 +2172,42 @@ snapshots: tinyrainbow@3.0.3: {} + tree-kill@1.2.2: {} + ts-api-utils@2.3.0(typescript@5.9.3): dependencies: typescript: 5.9.3 + ts-interface-checker@0.1.13: {} + + tsup@8.5.1(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3): + dependencies: + bundle-require: 5.1.0(esbuild@0.27.2) + cac: 6.7.14 + chokidar: 4.0.3 + consola: 3.4.2 + debug: 4.4.3 + esbuild: 0.27.2 + fix-dts-default-cjs-exports: 1.0.1 + joycon: 3.1.1 + picocolors: 1.1.1 + postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6) + resolve-from: 5.0.0 + rollup: 4.54.0 + source-map: 0.7.6 + sucrase: 3.35.1 + tinyexec: 0.3.2 + tinyglobby: 0.2.15 + tree-kill: 1.2.2 + optionalDependencies: + postcss: 8.5.6 + typescript: 5.9.3 + transitivePeerDependencies: + - jiti + - supports-color + - tsx + - yaml + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -1956,6 +2225,8 @@ snapshots: typescript@5.9.3: {} + ufo@1.6.2: {} + undici-types@7.16.0: {} uri-js@4.4.1: diff --git a/tsconfig.json b/tsconfig.json index 37cdd1e..39b9f82 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,14 +2,13 @@ "compilerOptions": { "target": "ESNext", "module": "ESNext", + "moduleResolution": "bundler", "lib": [ "ESNext", "DOM" ], "outDir": "dist", "declaration": true, - "removeComments": true, - "moduleResolution": "bundler", "skipLibCheck": false, "strict": true }, diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 0000000..a496b50 --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: [ "src/index.ts" ], + format: [ "esm" ], + dts: true, + clean: true, + outDir: "dist", + esbuildOptions(options) { + options.legalComments = "none"; + } +});