From 6e513d7f25d8dd1083eb333652cce315eba245a7 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Thu, 12 Mar 2026 00:26:23 +0100 Subject: [PATCH 01/62] feat: add Inertia.js React pages with admin user and role management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement server-side Inertia protocol (InertiaResult + InertiaMiddleware) in Core, React host app with per-module page resolution via dynamic imports, and full admin CRUD for users and roles with proper authorization. Key additions: - Inertia protocol: X-Inertia header detection, JSON/HTML responses, version management - React host app with import map for shared vendor bundles (react, react-dom, @inertiajs/react) - Custom esbuild vendor bundler (build-vendors.mjs) for proper CJS→ESM conversion - Admin users: list with search/pagination, edit details, role assignment, lock/unlock - Admin roles: list with user counts, create, edit, delete with guard - Per-module React page bundles (Products.pages.js, Users.pages.js) - TypeScript type generation from C# DTOs via source generator - 100 tests passing (including 40 new integration tests) Co-Authored-By: Claude Opus 4.6 --- .../2026-03-11-user-role-management-design.md | 62 + docs/plans/2026-03-11-user-role-management.md | 1185 + package-lock.json | 1356 +- package.json | 7 +- src/SimpleModule.Api/ClientApp/app.tsx | 18 + .../ClientApp/build-vendors.mjs | 102 + src/SimpleModule.Api/ClientApp/package.json | 13 + src/SimpleModule.Api/ClientApp/vite.config.ts | 31 + src/SimpleModule.Api/Program.cs | 3 + src/SimpleModule.Api/SimpleModule.Api.csproj | 11 + src/SimpleModule.Api/wwwroot/css/app.css | 2 +- src/SimpleModule.Api/wwwroot/js/app.js | 1 + .../wwwroot/js/vendor/inertiajs-react.js | 13377 ++++++++++ .../wwwroot/js/vendor/react-dom-client.js | 20226 ++++++++++++++++ .../wwwroot/js/vendor/react-dom.js | 299 + .../wwwroot/js/vendor/react-jsx-runtime.js | 300 + .../wwwroot/js/vendor/react.js | 1049 + .../Inertia/InertiaMiddleware.cs | 33 + .../Inertia/InertiaResult.cs | 77 + .../ModuleDiscovererGenerator.cs | 83 + .../Products/src/Products/Pages/Browse.tsx | 26 + .../Products/src/Products/Pages/index.ts | 5 + .../Products/src/Products/Products.csproj | 3 + .../Products/src/Products/ProductsModule.cs | 9 + .../Products/src/Products/package.json | 12 + .../Products/src/Products/vite.config.ts | 20 + .../src/Products/wwwroot/Products.pages.js | 26 + .../ProductsBrowseEndpointTests.cs | 57 + .../Features/Admin/AdminRolesEndpoint.cs | 150 + .../Features/Admin/AdminUsersEndpoint.cs | 176 + .../Users/src/Users/Pages/Admin/Roles.tsx | 84 + .../src/Users/Pages/Admin/RolesCreate.tsx | 51 + .../Users/src/Users/Pages/Admin/RolesEdit.tsx | 98 + .../Users/src/Users/Pages/Admin/Users.tsx | 138 + .../Users/src/Users/Pages/Admin/UsersEdit.tsx | 167 + src/modules/Users/src/Users/Pages/index.ts | 13 + src/modules/Users/src/Users/Users.csproj | 4 +- src/modules/Users/src/Users/UsersModule.cs | 5 + src/modules/Users/src/Users/package.json | 10 +- src/modules/Users/src/Users/vite.config.ts | 28 +- .../Users/src/Users/wwwroot/Users.pages.js | 447 + .../Integration/AdminRolesEndpointTests.cs | 112 + .../Integration/AdminUsersEndpointTests.cs | 112 + .../Inertia/InertiaResultTests.cs | 104 + .../SimpleModule.Core.Tests.csproj | 1 + tools/extract-ts-types.mjs | 29 + tsconfig.json | 16 + 47 files changed, 40096 insertions(+), 42 deletions(-) create mode 100644 docs/plans/2026-03-11-user-role-management-design.md create mode 100644 docs/plans/2026-03-11-user-role-management.md create mode 100644 src/SimpleModule.Api/ClientApp/app.tsx create mode 100644 src/SimpleModule.Api/ClientApp/build-vendors.mjs create mode 100644 src/SimpleModule.Api/ClientApp/package.json create mode 100644 src/SimpleModule.Api/ClientApp/vite.config.ts create mode 100644 src/SimpleModule.Api/wwwroot/js/app.js create mode 100644 src/SimpleModule.Api/wwwroot/js/vendor/inertiajs-react.js create mode 100644 src/SimpleModule.Api/wwwroot/js/vendor/react-dom-client.js create mode 100644 src/SimpleModule.Api/wwwroot/js/vendor/react-dom.js create mode 100644 src/SimpleModule.Api/wwwroot/js/vendor/react-jsx-runtime.js create mode 100644 src/SimpleModule.Api/wwwroot/js/vendor/react.js create mode 100644 src/SimpleModule.Core/Inertia/InertiaMiddleware.cs create mode 100644 src/SimpleModule.Core/Inertia/InertiaResult.cs create mode 100644 src/modules/Products/src/Products/Pages/Browse.tsx create mode 100644 src/modules/Products/src/Products/Pages/index.ts create mode 100644 src/modules/Products/src/Products/package.json create mode 100644 src/modules/Products/src/Products/vite.config.ts create mode 100644 src/modules/Products/src/Products/wwwroot/Products.pages.js create mode 100644 src/modules/Products/tests/Products.Tests/Integration/ProductsBrowseEndpointTests.cs create mode 100644 src/modules/Users/src/Users/Features/Admin/AdminRolesEndpoint.cs create mode 100644 src/modules/Users/src/Users/Features/Admin/AdminUsersEndpoint.cs create mode 100644 src/modules/Users/src/Users/Pages/Admin/Roles.tsx create mode 100644 src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx create mode 100644 src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx create mode 100644 src/modules/Users/src/Users/Pages/Admin/Users.tsx create mode 100644 src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx create mode 100644 src/modules/Users/src/Users/Pages/index.ts create mode 100644 src/modules/Users/src/Users/wwwroot/Users.pages.js create mode 100644 src/modules/Users/tests/Users.Tests/Integration/AdminRolesEndpointTests.cs create mode 100644 src/modules/Users/tests/Users.Tests/Integration/AdminUsersEndpointTests.cs create mode 100644 tests/SimpleModule.Core.Tests/Inertia/InertiaResultTests.cs create mode 100644 tools/extract-ts-types.mjs create mode 100644 tsconfig.json diff --git a/docs/plans/2026-03-11-user-role-management-design.md b/docs/plans/2026-03-11-user-role-management-design.md new file mode 100644 index 00000000..f7deac40 --- /dev/null +++ b/docs/plans/2026-03-11-user-role-management-design.md @@ -0,0 +1,62 @@ +# User & Role Management Admin UI + +## Overview + +React-based admin panel for managing users and roles, served via Inertia protocol from the Users module. All endpoints gated with `RequireRole("Admin")`. + +## Pages + +### Users +- **Admin/Users** — Paginated table with search by name/email. Columns: display name, email, roles, email confirmed, locked out, created date. Actions: edit, lock/unlock. +- **Admin/Users/Edit** — Edit form: display name, email, email confirmed toggle, role assignment (multi-select), lock/unlock account. + +### Roles +- **Admin/Roles** — Table listing all roles with description, user count, created date. Actions: edit, delete. +- **Admin/Roles/Create** — Form: name, description. +- **Admin/Roles/Edit** — Form: name, description. Shows assigned users. + +## API Endpoints + +All under `/admin`, require Admin role. + +``` +GET /admin/users → Inertia: Admin/Users (paginated, ?search=&page=) +GET /admin/users/{id}/edit → Inertia: Admin/Users/Edit +POST /admin/users/{id} → Update user (display name, email, emailConfirmed) +POST /admin/users/{id}/roles → Set roles (replaces all) +POST /admin/users/{id}/lock → Lock account +POST /admin/users/{id}/unlock → Unlock account + +GET /admin/roles → Inertia: Admin/Roles +GET /admin/roles/create → Inertia: Admin/Roles/Create +POST /admin/roles → Create role +GET /admin/roles/{id}/edit → Inertia: Admin/Roles/Edit +POST /admin/roles/{id} → Update role +DELETE /admin/roles/{id} → Delete role (fails if users assigned) +``` + +## Data Flow + +Endpoints use `UserManager` and `RoleManager` directly. Props passed to React via `Inertia.Render()`. Form submissions POST back, then redirect via Inertia. + +## File Changes + +| Action | File | +|--------|------| +| New | `Users/Pages/Admin/Users.tsx` | +| New | `Users/Pages/Admin/UsersEdit.tsx` | +| New | `Users/Pages/Admin/Roles.tsx` | +| New | `Users/Pages/Admin/RolesCreate.tsx` | +| New | `Users/Pages/Admin/RolesEdit.tsx` | +| New | `Users/Pages/index.ts` | +| New | `Users/Features/Admin/AdminUsersEndpoint.cs` | +| New | `Users/Features/Admin/AdminRolesEndpoint.cs` | +| Modify | `UsersModule.cs` — register admin endpoints | +| Modify | `Users/vite.config.ts` — add pages build | +| Modify | `Users/package.json` — add react peer deps | + +## Decisions + +- No new contracts/DTOs — admin endpoints use UserManager/RoleManager directly with anonymous objects for Inertia props. +- Existing Blazor self-service pages (login, register, manage profile, 2FA) remain untouched. +- Admin role + seed user already exist via OpenIddictSeedService. diff --git a/docs/plans/2026-03-11-user-role-management.md b/docs/plans/2026-03-11-user-role-management.md new file mode 100644 index 00000000..dbf37a9c --- /dev/null +++ b/docs/plans/2026-03-11-user-role-management.md @@ -0,0 +1,1185 @@ +# User & Role Management Admin UI Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Build React admin pages for managing users (list, edit, lock/unlock, role assignment) and roles (CRUD), served via Inertia from the Users module, gated with Admin role. + +**Architecture:** Admin endpoints in `Features/Admin/` using `UserManager`/`RoleManager` directly. React pages in `Pages/Admin/`. Inertia protocol handles server→client data passing. Form submissions POST back to endpoints which redirect via Inertia. + +**Tech Stack:** ASP.NET Core Identity, Inertia.js, React 19, Vite, Tailwind CSS + +--- + +### Task 1: Users module Vite config for React pages + +The Users module already has a Vite config for building `Scripts/index.ts` → `Users.lib.module.js`. We need a second build for React pages → `Users.pages.js`. + +**Files:** +- Modify: `src/modules/Users/src/Users/vite.config.ts` +- Modify: `src/modules/Users/src/Users/package.json` +- Modify: `src/modules/Users/src/Users/Users.csproj` + +**Step 1: Update vite.config.ts to support two builds** + +Replace `src/modules/Users/src/Users/vite.config.ts` with: + +```ts +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import { resolve } from 'path'; + +const buildTarget = process.env.VITE_BUILD_TARGET; + +const libConfig = defineConfig({ + build: { + lib: { + entry: resolve(__dirname, 'Scripts/index.ts'), + formats: ['es'], + fileName: () => 'Users.lib.module.js', + }, + outDir: 'wwwroot', + emptyOutDir: false, + rollupOptions: { + output: { inlineDynamicImports: true }, + }, + }, +}); + +const pagesConfig = defineConfig({ + plugins: [react()], + build: { + lib: { + entry: resolve(__dirname, 'Pages/index.ts'), + formats: ['es'], + fileName: () => 'Users.pages.js', + }, + outDir: 'wwwroot', + emptyOutDir: false, + rollupOptions: { + external: ['react', 'react-dom', 'react/jsx-runtime'], + output: { inlineDynamicImports: true }, + }, + }, +}); + +export default buildTarget === 'pages' ? pagesConfig : libConfig; +``` + +**Step 2: Update package.json to add react peer deps and dual build script** + +Replace `src/modules/Users/src/Users/package.json` with: + +```json +{ + "private": true, + "name": "@simplemodule/users", + "scripts": { + "build": "vite build && cross-env VITE_BUILD_TARGET=pages vite build", + "build:lib": "vite build", + "build:pages": "cross-env VITE_BUILD_TARGET=pages vite build", + "watch": "cross-env VITE_BUILD_TARGET=pages vite build --watch" + }, + "dependencies": { + "qrcode": "^1.5.4" + }, + "devDependencies": { + "@types/qrcode": "^1.5.6" + }, + "peerDependencies": { + "react": "^19.0.0", + "react-dom": "^19.0.0" + } +} +``` + +**Step 3: Update Users.csproj JsBuild target to run both builds** + +In `src/modules/Users/src/Users/Users.csproj`, update the JsBuild target Exec command: + +```xml + +``` + +**Step 4: Install cross-env in root devDependencies** + +Run: `npm install -D cross-env` + +**Step 5: Verify builds** + +Run from `src/modules/Users/src/Users/`: +```bash +npx vite build +VITE_BUILD_TARGET=pages npx vite build +``` +Expected: `wwwroot/Users.lib.module.js` and `wwwroot/Users.pages.js` both exist. + +**Step 6: Commit** + +```bash +git add src/modules/Users/src/Users/vite.config.ts src/modules/Users/src/Users/package.json src/modules/Users/src/Users/Users.csproj package.json package-lock.json +git commit -m "feat(users): configure dual Vite builds for lib + React pages" +``` + +--- + +### Task 2: Admin Users endpoint (C# backend) + +**Files:** +- Create: `src/modules/Users/src/Users/Features/Admin/AdminUsersEndpoint.cs` +- Modify: `src/modules/Users/src/Users/UsersModule.cs` + +**Step 1: Create AdminUsersEndpoint.cs** + +Create `src/modules/Users/src/Users/Features/Admin/AdminUsersEndpoint.cs`: + +```csharp +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Routing; +using Microsoft.EntityFrameworkCore; +using SimpleModule.Core.Inertia; +using SimpleModule.Users.Entities; + +namespace SimpleModule.Users.Features.Admin; + +public static class AdminUsersEndpoint +{ + private const int PageSize = 20; + + public static void Map(IEndpointRouteBuilder endpoints) + { + var group = endpoints + .MapGroup("/admin/users") + .RequireAuthorization(policy => policy.RequireRole("Admin")); + + // List users + group.MapGet("/", async ( + UserManager userManager, + RoleManager roleManager, + string? search, + int page = 1) => + { + var query = userManager.Users.AsQueryable(); + + if (!string.IsNullOrWhiteSpace(search)) + { + var term = search.Trim().ToLower(); + query = query.Where(u => + (u.Email != null && u.Email.ToLower().Contains(term)) + || u.DisplayName.ToLower().Contains(term) + || (u.UserName != null && u.UserName.ToLower().Contains(term))); + } + + var totalCount = await query.CountAsync(); + var totalPages = (int)Math.Ceiling((double)totalCount / PageSize); + page = Math.Clamp(page, 1, Math.Max(1, totalPages)); + + var users = await query + .OrderBy(u => u.DisplayName) + .Skip((page - 1) * PageSize) + .Take(PageSize) + .ToListAsync(); + + var userList = new List(); + foreach (var user in users) + { + var roles = await userManager.GetRolesAsync(user); + userList.Add(new + { + id = user.Id, + displayName = user.DisplayName, + email = user.Email, + emailConfirmed = user.EmailConfirmed, + roles = roles.ToList(), + isLockedOut = user.LockoutEnd.HasValue && user.LockoutEnd > DateTimeOffset.UtcNow, + createdAt = user.CreatedAt.ToString("O"), + }); + } + + return Inertia.Render("Users/Admin/Users", new + { + users = userList, + search = search ?? "", + page, + totalPages, + totalCount, + }); + }); + + // Edit user page + group.MapGet("/{id}/edit", async ( + string id, + UserManager userManager, + RoleManager roleManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); + + var userRoles = await userManager.GetRolesAsync(user); + var allRoles = await roleManager.Roles.OrderBy(r => r.Name).ToListAsync(); + + return Inertia.Render("Users/Admin/UsersEdit", new + { + user = new + { + id = user.Id, + displayName = user.DisplayName, + email = user.Email, + emailConfirmed = user.EmailConfirmed, + isLockedOut = user.LockoutEnd.HasValue && user.LockoutEnd > DateTimeOffset.UtcNow, + createdAt = user.CreatedAt.ToString("O"), + lastLoginAt = user.LastLoginAt?.ToString("O"), + }, + userRoles = userRoles.ToList(), + allRoles = allRoles.Select(r => new { id = r.Id, name = r.Name, description = r.Description }).ToList(), + }); + }); + + // Update user + group.MapPost("/{id}", async ( + string id, + HttpContext context, + UserManager userManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); + + var form = await context.Request.ReadFormAsync(); + user.DisplayName = form["displayName"].ToString(); + user.Email = form["email"].ToString(); + user.EmailConfirmed = form.ContainsKey("emailConfirmed"); + + await userManager.UpdateAsync(user); + + return Results.Redirect($"/admin/users/{id}/edit"); + }); + + // Set roles + group.MapPost("/{id}/roles", async ( + string id, + HttpContext context, + UserManager userManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); + + var form = await context.Request.ReadFormAsync(); + var newRoles = form["roles"].ToArray().Where(r => !string.IsNullOrEmpty(r)).ToList(); + var currentRoles = await userManager.GetRolesAsync(user); + + await userManager.RemoveFromRolesAsync(user, currentRoles); + if (newRoles.Count > 0) + await userManager.AddToRolesAsync(user, newRoles!); + + return Results.Redirect($"/admin/users/{id}/edit"); + }); + + // Lock account + group.MapPost("/{id}/lock", async ( + string id, + UserManager userManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); + + await userManager.SetLockoutEnabledAsync(user, true); + await userManager.SetLockoutEndDateAsync(user, DateTimeOffset.UtcNow.AddYears(100)); + + return Results.Redirect($"/admin/users/{id}/edit"); + }); + + // Unlock account + group.MapPost("/{id}/unlock", async ( + string id, + UserManager userManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); + + await userManager.SetLockoutEndDateAsync(user, null); + await userManager.ResetAccessFailedCountAsync(user); + + return Results.Redirect($"/admin/users/{id}/edit"); + }); + } +} +``` + +**Step 2: Register in UsersModule.cs** + +Add to the using block: +```csharp +using SimpleModule.Users.Features.Admin; +``` + +Add at the end of `ConfigureEndpoints`, before the closing brace: +```csharp + // Admin endpoints + AdminUsersEndpoint.Map(endpoints); +``` + +**Step 3: Verify dotnet build succeeds** + +Run: `dotnet build` +Expected: 0 errors + +**Step 4: Commit** + +```bash +git add src/modules/Users/src/Users/Features/Admin/AdminUsersEndpoint.cs src/modules/Users/src/Users/UsersModule.cs +git commit -m "feat(users): add admin users management endpoints" +``` + +--- + +### Task 3: Admin Roles endpoint (C# backend) + +**Files:** +- Create: `src/modules/Users/src/Users/Features/Admin/AdminRolesEndpoint.cs` +- Modify: `src/modules/Users/src/Users/UsersModule.cs` + +**Step 1: Create AdminRolesEndpoint.cs** + +Create `src/modules/Users/src/Users/Features/Admin/AdminRolesEndpoint.cs`: + +```csharp +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Routing; +using Microsoft.EntityFrameworkCore; +using SimpleModule.Core.Inertia; +using SimpleModule.Users.Entities; + +namespace SimpleModule.Users.Features.Admin; + +public static class AdminRolesEndpoint +{ + public static void Map(IEndpointRouteBuilder endpoints) + { + var group = endpoints + .MapGroup("/admin/roles") + .RequireAuthorization(policy => policy.RequireRole("Admin")); + + // List roles + group.MapGet("/", async ( + RoleManager roleManager, + UserManager userManager) => + { + var roles = await roleManager.Roles + .OrderBy(r => r.Name) + .ToListAsync(); + + var roleList = new List(); + foreach (var role in roles) + { + var usersInRole = role.Name is not null + ? await userManager.GetUsersInRoleAsync(role.Name) + : []; + roleList.Add(new + { + id = role.Id, + name = role.Name, + description = role.Description, + userCount = usersInRole.Count, + createdAt = role.CreatedAt.ToString("O"), + }); + } + + return Inertia.Render("Users/Admin/Roles", new { roles = roleList }); + }); + + // Create role page + group.MapGet("/create", () => + Inertia.Render("Users/Admin/RolesCreate")); + + // Create role + group.MapPost("/", async ( + HttpContext context, + RoleManager roleManager) => + { + var form = await context.Request.ReadFormAsync(); + var name = form["name"].ToString().Trim(); + var description = form["description"].ToString().Trim(); + + if (string.IsNullOrEmpty(name)) + return Results.Redirect("/admin/roles/create"); + + var role = new ApplicationRole + { + Name = name, + Description = string.IsNullOrEmpty(description) ? null : description, + }; + + var result = await roleManager.CreateAsync(role); + if (!result.Succeeded) + return Results.Redirect("/admin/roles/create"); + + return Results.Redirect("/admin/roles"); + }); + + // Edit role page + group.MapGet("/{id}/edit", async ( + string id, + RoleManager roleManager, + UserManager userManager) => + { + var role = await roleManager.FindByIdAsync(id); + if (role is null) + return Results.NotFound(); + + var usersInRole = role.Name is not null + ? await userManager.GetUsersInRoleAsync(role.Name) + : []; + + return Inertia.Render("Users/Admin/RolesEdit", new + { + role = new + { + id = role.Id, + name = role.Name, + description = role.Description, + createdAt = role.CreatedAt.ToString("O"), + }, + users = usersInRole.Select(u => new + { + id = u.Id, + displayName = u.DisplayName, + email = u.Email, + }).ToList(), + }); + }); + + // Update role + group.MapPost("/{id}", async ( + string id, + HttpContext context, + RoleManager roleManager) => + { + var role = await roleManager.FindByIdAsync(id); + if (role is null) + return Results.NotFound(); + + var form = await context.Request.ReadFormAsync(); + role.Name = form["name"].ToString().Trim(); + var description = form["description"].ToString().Trim(); + role.Description = string.IsNullOrEmpty(description) ? null : description; + + await roleManager.UpdateAsync(role); + + return Results.Redirect($"/admin/roles/{id}/edit"); + }); + + // Delete role + group.MapDelete("/{id}", async ( + string id, + RoleManager roleManager, + UserManager userManager) => + { + var role = await roleManager.FindByIdAsync(id); + if (role is null) + return Results.NotFound(); + + // Don't delete if users are assigned + var usersInRole = role.Name is not null + ? await userManager.GetUsersInRoleAsync(role.Name) + : []; + if (usersInRole.Count > 0) + return Results.BadRequest(new { error = "Cannot delete role with assigned users" }); + + await roleManager.DeleteAsync(role); + + return Results.Ok(); + }); + } +} +``` + +**Step 2: Register in UsersModule.cs** + +Add after `AdminUsersEndpoint.Map(endpoints);`: +```csharp + AdminRolesEndpoint.Map(endpoints); +``` + +**Step 3: Verify dotnet build succeeds** + +Run: `dotnet build` +Expected: 0 errors + +**Step 4: Commit** + +```bash +git add src/modules/Users/src/Users/Features/Admin/AdminRolesEndpoint.cs src/modules/Users/src/Users/UsersModule.cs +git commit -m "feat(users): add admin roles management endpoints" +``` + +--- + +### Task 4: React pages — Users list and Users edit + +**Files:** +- Create: `src/modules/Users/src/Users/Pages/Admin/Users.tsx` +- Create: `src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx` + +**Step 1: Create Users list page** + +Create `src/modules/Users/src/Users/Pages/Admin/Users.tsx`: + +```tsx +import { router } from '@inertiajs/react'; +import { useState, FormEvent } from 'react'; + +interface User { + id: string; + displayName: string; + email: string; + emailConfirmed: boolean; + roles: string[]; + isLockedOut: boolean; + createdAt: string; +} + +interface Props { + users: User[]; + search: string; + page: number; + totalPages: number; + totalCount: number; +} + +export default function Users({ users, search, page, totalPages, totalCount }: Props) { + const [searchValue, setSearchValue] = useState(search); + + function handleSearch(e: FormEvent) { + e.preventDefault(); + router.get('/admin/users', { search: searchValue, page: 1 }, { preserveState: true }); + } + + function goToPage(p: number) { + router.get('/admin/users', { search: searchValue, page: p }, { preserveState: true }); + } + + return ( +
+
+

Users

+ {totalCount} total +
+ +
+ setSearchValue(e.target.value)} + placeholder="Search by name or email..." + className="flex-1 px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" + /> + +
+ +
+ + + + + + + + + + + + + {users.map((user) => ( + + + + + + + + + ))} + +
NameEmailRolesStatusCreated
{user.displayName || '—'} + {user.email} + {!user.emailConfirmed && ( + unverified + )} + +
+ {user.roles.map((role) => ( + + {role} + + ))} +
+
+ {user.isLockedOut ? ( + Locked + ) : ( + Active + )} + + {new Date(user.createdAt).toLocaleDateString()} + + +
+
+ + {totalPages > 1 && ( +
+ + + Page {page} of {totalPages} + + +
+ )} +
+ ); +} +``` + +**Step 2: Create Users edit page** + +Create `src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx`: + +```tsx +import { router } from '@inertiajs/react'; + +interface UserDetail { + id: string; + displayName: string; + email: string; + emailConfirmed: boolean; + isLockedOut: boolean; + createdAt: string; + lastLoginAt: string | null; +} + +interface Role { + id: string; + name: string; + description: string | null; +} + +interface Props { + user: UserDetail; + userRoles: string[]; + allRoles: Role[]; +} + +export default function UsersEdit({ user, userRoles, allRoles }: Props) { + function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + router.post(`/admin/users/${user.id}`, formData); + } + + function handleRolesSubmit(e: React.FormEvent) { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + router.post(`/admin/users/${user.id}/roles`, formData); + } + + function handleLock() { + router.post(`/admin/users/${user.id}/lock`); + } + + function handleUnlock() { + router.post(`/admin/users/${user.id}/unlock`); + } + + return ( +
+
+ +

Edit User

+
+ +
+ Created: {new Date(user.createdAt).toLocaleString()} + {user.lastLoginAt && ( + Last login: {new Date(user.lastLoginAt).toLocaleString()} + )} +
+ + {/* User Details Form */} +
+

Details

+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ + {/* Roles Form */} +
+

Roles

+
+ {allRoles.map((role) => ( +
+ + +
+ ))} + {allRoles.length === 0 && ( +

No roles defined.

+ )} +
+ +
+ + {/* Lock/Unlock */} +
+

Account Status

+ {user.isLockedOut ? ( +
+

This account is locked.

+ +
+ ) : ( +
+

This account is active.

+ +
+ )} +
+
+ ); +} +``` + +**Step 3: Verify TypeScript compiles** + +Run from repo root: `npx tsc --noEmit` +Expected: No errors + +**Step 4: Commit** + +```bash +git add src/modules/Users/src/Users/Pages/Admin/Users.tsx src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx +git commit -m "feat(users): add admin users list and edit React pages" +``` + +--- + +### Task 5: React pages — Roles list, create, edit + +**Files:** +- Create: `src/modules/Users/src/Users/Pages/Admin/Roles.tsx` +- Create: `src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx` +- Create: `src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx` + +**Step 1: Create Roles list page** + +Create `src/modules/Users/src/Users/Pages/Admin/Roles.tsx`: + +```tsx +import { router } from '@inertiajs/react'; + +interface Role { + id: string; + name: string; + description: string | null; + userCount: number; + createdAt: string; +} + +interface Props { + roles: Role[]; +} + +export default function Roles({ roles }: Props) { + function handleDelete(id: string, name: string) { + if (!confirm(`Delete role "${name}"?`)) return; + router.delete(`/admin/roles/${id}`, { + onError: () => alert('Cannot delete role with assigned users.'), + }); + } + + return ( +
+
+

Roles

+ +
+ +
+ + + + + + + + + + + + {roles.map((role) => ( + + + + + + + + ))} + +
NameDescriptionUsersCreated
{role.name} + {role.description || '—'} + + + {role.userCount} + + + {new Date(role.createdAt).toLocaleDateString()} + +
+ + +
+
+
+
+ ); +} +``` + +**Step 2: Create Roles create page** + +Create `src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx`: + +```tsx +import { router } from '@inertiajs/react'; + +export default function RolesCreate() { + function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + router.post('/admin/roles', formData); + } + + return ( +
+
+ +

Create Role

+
+ +
+
+
+ + +
+
+ + +
+ +
+
+
+ ); +} +``` + +**Step 3: Create Roles edit page** + +Create `src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx`: + +```tsx +import { router } from '@inertiajs/react'; + +interface RoleDetail { + id: string; + name: string; + description: string | null; + createdAt: string; +} + +interface UserSummary { + id: string; + displayName: string; + email: string; +} + +interface Props { + role: RoleDetail; + users: UserSummary[]; +} + +export default function RolesEdit({ role, users }: Props) { + function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + router.post(`/admin/roles/${role.id}`, formData); + } + + return ( +
+
+ +

Edit Role

+
+ +
+
+
+ + +
+
+ + +
+
+ Created: {new Date(role.createdAt).toLocaleString()} +
+ +
+
+ +
+

Assigned Users ({users.length})

+ {users.length === 0 ? ( +

No users assigned to this role.

+ ) : ( +
    + {users.map((user) => ( +
  • +
    + {user.displayName || '—'} + {user.email} +
    + +
  • + ))} +
+ )} +
+
+ ); +} +``` + +**Step 4: Commit** + +```bash +git add src/modules/Users/src/Users/Pages/Admin/ +git commit -m "feat(users): add admin roles list, create, and edit React pages" +``` + +--- + +### Task 6: Page registry and final build verification + +**Files:** +- Create: `src/modules/Users/src/Users/Pages/index.ts` + +**Step 1: Create page registry** + +Create `src/modules/Users/src/Users/Pages/index.ts`: + +```ts +import Users from './Admin/Users'; +import UsersEdit from './Admin/UsersEdit'; +import Roles from './Admin/Roles'; +import RolesCreate from './Admin/RolesCreate'; +import RolesEdit from './Admin/RolesEdit'; + +export const pages: Record = { + 'Users/Admin/Users': Users, + 'Users/Admin/UsersEdit': UsersEdit, + 'Users/Admin/Roles': Roles, + 'Users/Admin/RolesCreate': RolesCreate, + 'Users/Admin/RolesEdit': RolesEdit, +}; +``` + +**Step 2: Run full build** + +```bash +npm install +dotnet build +``` +Expected: 0 errors. Vite builds produce `Users.lib.module.js` and `Users.pages.js` in `wwwroot/`. + +**Step 3: Commit** + +```bash +git add src/modules/Users/src/Users/Pages/index.ts +git commit -m "feat(users): add page registry for admin React pages" +``` + +--- + +## Summary + +| Task | Description | +|------|-------------| +| 1 | Dual Vite config (lib + pages builds) | +| 2 | Admin users endpoints (list, edit, update, roles, lock/unlock) | +| 3 | Admin roles endpoints (list, create, edit, update, delete) | +| 4 | React pages: Users list + Users edit | +| 5 | React pages: Roles list, create, edit | +| 6 | Page registry + final build verification | diff --git a/package-lock.json b/package-lock.json index ed301f4a..53a034f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,13 +6,308 @@ "": { "name": "simplemodule", "workspaces": [ - "src/modules/*/*" + "src/modules/*/src/*", + "src/SimpleModule.Api/ClientApp" ], "devDependencies": { + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "@vitejs/plugin-react": "^4.4.0", + "cross-env": "^10.1.0", "typescript": "^5.8.0", "vite": "^6.2.0" } }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@epic-web/invariant": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", + "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==", + "dev": true, + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", @@ -455,6 +750,92 @@ "node": ">=18" } }, + "node_modules/@inertiajs/core": { + "version": "2.3.17", + "resolved": "https://registry.npmjs.org/@inertiajs/core/-/core-2.3.17.tgz", + "integrity": "sha512-CELuVhq2cBVrqxmrbRKqseuIQPBA6PcgDU7EPkPQxK02Lxxg7wTZWZZ5omaGBT+5mQtr0bkEUqUF2vxYbu4ogw==", + "license": "MIT", + "dependencies": { + "@types/lodash-es": "^4.17.12", + "axios": "^1.13.5", + "laravel-precognition": "^1.0.2", + "lodash-es": "^4.17.23", + "qs": "^6.15.0" + } + }, + "node_modules/@inertiajs/react": { + "version": "2.3.17", + "resolved": "https://registry.npmjs.org/@inertiajs/react/-/react-2.3.17.tgz", + "integrity": "sha512-TYCqRut0q2AuZb+BP/vbx50M0XYPoRvDOHBIcQGrDOkiAoHMZr2k260bcf8SfFPgZe1MxnMs6Ji+MdXcl55ckQ==", + "license": "MIT", + "dependencies": { + "@inertiajs/core": "2.3.17", + "@types/lodash-es": "^4.17.12", + "laravel-precognition": "^1.0.2", + "lodash-es": "^4.17.23" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.59.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", @@ -805,10 +1186,63 @@ "win32" ] }, + "node_modules/@simplemodule/app": { + "resolved": "src/SimpleModule.Api/ClientApp", + "link": true + }, + "node_modules/@simplemodule/products": { + "resolved": "src/modules/Products/src/Products", + "link": true + }, "node_modules/@simplemodule/users": { - "resolved": "src/modules/Users/Users", + "resolved": "src/modules/Users/src/Users", "link": true }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -816,6 +1250,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/lodash": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/node": { "version": "25.4.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.4.0.tgz", @@ -836,6 +1285,48 @@ "@types/node": "*" } }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -860,44 +1351,236 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "license": "MIT", - "engines": { - "node": ">=6" - } + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, - "node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "license": "ISC", + "node_modules/axios": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", + "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^1.1.0" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" + "node_modules/baseline-browser-mapping": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" }, "engines": { - "node": ">=7.0.0" + "node": ">=6.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001777", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz", + "integrity": "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-env": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz", + "integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@epic-web/invariant": "^1.0.0", + "cross-spawn": "^7.0.6" + }, + "bin": { + "cross-env": "dist/bin/cross-env.js", + "cross-env-shell": "dist/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -907,18 +1590,93 @@ "node": ">=0.10.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dijkstrajs": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", "license": "MIT" }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.307", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", + "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", + "dev": true, + "license": "ISC" + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", @@ -961,6 +1719,16 @@ "@esbuild/win32-x64": "0.25.12" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -992,6 +1760,42 @@ "node": ">=8" } }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -1007,6 +1811,25 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1016,6 +1839,94 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -1025,6 +1936,56 @@ "node": ">=8" } }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/laravel-precognition": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/laravel-precognition/-/laravel-precognition-1.0.2.tgz", + "integrity": "sha512-0H08JDdMWONrL/N314fvsO3FATJwGGlFKGkMF3nNmizVFJaWs17816iM+sX7Rp8d5hUjYCx6WLfsehSKfaTxjg==", + "license": "MIT", + "dependencies": { + "axios": "^1.4.0", + "lodash-es": "^4.17.21" + } + }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -1037,6 +1998,59 @@ "node": ">=8" } }, + "node_modules/lodash-es": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -1056,6 +2070,25 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/node-releases": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -1101,6 +2134,16 @@ "node": ">=8" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -1160,6 +2203,12 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/qrcode": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", @@ -1177,6 +2226,54 @@ "node": ">=10.13.0" } }, + "node_modules/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -1237,12 +2334,123 @@ "fsevents": "~2.3.2" } }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "license": "ISC" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -1317,12 +2525,44 @@ "dev": true, "license": "MIT" }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/vite": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -1392,6 +2632,22 @@ } } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/which-module": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", @@ -1418,6 +2674,13 @@ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "license": "ISC" }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, "node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", @@ -1453,14 +2716,43 @@ "node": ">=6" } }, + "src/modules/Products/src/Products": { + "name": "@simplemodule/products", + "peerDependencies": { + "react": "^19.0.0", + "react-dom": "^19.0.0" + } + }, + "src/modules/Users/src/Users": { + "name": "@simplemodule/users", + "dependencies": { + "qrcode": "^1.5.4" + }, + "devDependencies": { + "@types/qrcode": "^1.5.6" + }, + "peerDependencies": { + "react": "^19.0.0", + "react-dom": "^19.0.0" + } + }, "src/modules/Users/Users": { "name": "@simplemodule/users", + "extraneous": true, "dependencies": { "qrcode": "^1.5.4" }, "devDependencies": { "@types/qrcode": "^1.5.6" } + }, + "src/SimpleModule.Api/ClientApp": { + "name": "@simplemodule/app", + "dependencies": { + "@inertiajs/react": "^2.0.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + } } } } diff --git a/package.json b/package.json index 013d4656..242fb816 100644 --- a/package.json +++ b/package.json @@ -2,9 +2,14 @@ "private": true, "name": "simplemodule", "workspaces": [ - "src/modules/*/*" + "src/modules/*/src/*", + "src/SimpleModule.Api/ClientApp" ], "devDependencies": { + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "@vitejs/plugin-react": "^4.4.0", + "cross-env": "^10.1.0", "typescript": "^5.8.0", "vite": "^6.2.0" } diff --git a/src/SimpleModule.Api/ClientApp/app.tsx b/src/SimpleModule.Api/ClientApp/app.tsx new file mode 100644 index 00000000..b991c05e --- /dev/null +++ b/src/SimpleModule.Api/ClientApp/app.tsx @@ -0,0 +1,18 @@ +import { createInertiaApp } from '@inertiajs/react'; +import { createRoot } from 'react-dom/client'; + +createInertiaApp({ + resolve: async (name) => { + // "Products/Browse" → dynamic import from /_content/Products/Products.pages.js + const moduleName = name.split('/')[0]; + const mod = await import( + /* @vite-ignore */ + `/_content/${moduleName}/${moduleName}.pages.js` + ); + const page = mod.pages[name]; + return page.default ? page : { default: page }; + }, + setup({ el, App, props }) { + createRoot(el).render(); + }, +}); diff --git a/src/SimpleModule.Api/ClientApp/build-vendors.mjs b/src/SimpleModule.Api/ClientApp/build-vendors.mjs new file mode 100644 index 00000000..7662c3fb --- /dev/null +++ b/src/SimpleModule.Api/ClientApp/build-vendors.mjs @@ -0,0 +1,102 @@ +#!/usr/bin/env node +// Build vendor ESM bundles from CJS packages with proper named exports. +// Uses esbuild API to create bundles, then post-processes to: +// 1. Replace __require("pkg") calls with ESM imports (CJS externals don't work in browsers) +// 2. Add named exports from the default export + +import { build } from 'esbuild'; +import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs'; +import { resolve, dirname } from 'path'; +import { fileURLToPath } from 'url'; +import { createRequire } from 'module'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const outDir = resolve(__dirname, '../wwwroot/js/vendor'); +const require_ = createRequire(import.meta.url); + +if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true }); + +async function getExports(pkg) { + try { + const mod = require_(pkg); + return Object.keys(mod).filter(k => k !== 'default' && k !== '__esModule'); + } catch { + try { + const mod = await import(pkg); + return Object.keys(mod).filter(k => k !== 'default' && k !== '__esModule'); + } catch { + return []; + } + } +} + +async function buildVendor(pkg, file, externals = []) { + const outFile = resolve(outDir, file); + const exports = await getExports(pkg); + + console.log(`Building ${pkg} → ${file} (${exports.length} named exports)`); + + await build({ + entryPoints: [pkg], + bundle: true, + format: 'esm', + platform: 'browser', + external: externals, + outfile: outFile, + logLevel: 'warning', + }); + + let content = readFileSync(outFile, 'utf-8'); + + // Step 1: Replace __require("pkg") calls with ESM imports. + // esbuild's CJS externals produce __require() calls which fail in browsers. + // We add ESM imports at the top and replace __require("pkg") with the imported namespace. + const importLines = []; + for (let i = 0; i < externals.length; i++) { + const ext = externals[i]; + const varName = `__ext${i}`; + // Escape for regex: @ and / + const escaped = ext.replace(/[.*+?^${}()|[\]\\\/]/g, '\\$&'); + const re = new RegExp(`__require\\("${escaped}"\\)`, 'g'); + if (re.test(content)) { + importLines.push(`import * as ${varName} from "${ext}";`); + content = content.replace(re, varName); + } + } + if (importLines.length > 0) { + content = importLines.join('\n') + '\n' + content; + console.log(` Replaced __require() calls for: ${externals.filter((_, i) => content.includes(`__ext${i}`)).join(', ') || externals.join(', ')}`); + } + + // Step 2: Add named exports from the default export. + // esbuild's CJS→ESM only creates `export default`, not individual named exports. + if (exports.length > 0) { + const re = /export\s+default\s+(.+?)\s*;\s*$/m; + const match = content.match(re); + if (match) { + const callExpr = match[1]; + const namedExports = exports.map(e => ` ${e}`).join(',\n'); + content = content.replace( + match[0], + `var __mod = ${callExpr};\nexport default __mod;\nexport var {\n${namedExports}\n} = __mod;\n` + ); + console.log(` Added ${exports.length} named exports`); + } + } + + writeFileSync(outFile, content); +} + +const vendors = [ + { pkg: 'react', file: 'react.js', externals: [] }, + { pkg: 'react-dom', file: 'react-dom.js', externals: ['react'] }, + { pkg: 'react/jsx-runtime', file: 'react-jsx-runtime.js', externals: ['react'] }, + { pkg: 'react-dom/client', file: 'react-dom-client.js', externals: ['react', 'react-dom'] }, + { pkg: '@inertiajs/react', file: 'inertiajs-react.js', externals: ['react', 'react-dom', 'react/jsx-runtime', 'react-dom/client'] }, +]; + +for (const v of vendors) { + await buildVendor(v.pkg, v.file, v.externals); +} + +console.log('\nVendor bundles built successfully!'); diff --git a/src/SimpleModule.Api/ClientApp/package.json b/src/SimpleModule.Api/ClientApp/package.json new file mode 100644 index 00000000..c1e97c02 --- /dev/null +++ b/src/SimpleModule.Api/ClientApp/package.json @@ -0,0 +1,13 @@ +{ + "private": true, + "name": "@simplemodule/app", + "scripts": { + "build": "vite build", + "watch": "vite build --watch" + }, + "dependencies": { + "@inertiajs/react": "^2.0.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + } +} diff --git a/src/SimpleModule.Api/ClientApp/vite.config.ts b/src/SimpleModule.Api/ClientApp/vite.config.ts new file mode 100644 index 00000000..5e76a46b --- /dev/null +++ b/src/SimpleModule.Api/ClientApp/vite.config.ts @@ -0,0 +1,31 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import path from 'path'; + +export default defineConfig({ + plugins: [react()], + build: { + outDir: path.resolve(__dirname, '../wwwroot/js'), + emptyOutDir: false, + rollupOptions: { + input: path.resolve(__dirname, 'app.tsx'), + external: [ + 'react', + 'react-dom', + 'react/jsx-runtime', + 'react-dom/client', + '@inertiajs/react', + ], + output: { + entryFileNames: 'app.js', + paths: { + 'react': '/js/vendor/react.js', + 'react-dom': '/js/vendor/react-dom.js', + 'react/jsx-runtime': '/js/vendor/react-jsx-runtime.js', + 'react-dom/client': '/js/vendor/react-dom-client.js', + '@inertiajs/react': '/js/vendor/inertiajs-react.js', + }, + }, + }, + }, +}); diff --git a/src/SimpleModule.Api/Program.cs b/src/SimpleModule.Api/Program.cs index 20083b19..989ee538 100644 --- a/src/SimpleModule.Api/Program.cs +++ b/src/SimpleModule.Api/Program.cs @@ -7,6 +7,7 @@ using SimpleModule.Core.Constants; using SimpleModule.Core.Events; using SimpleModule.Core.Exceptions; +using SimpleModule.Core.Inertia; using SimpleModule.Database; using SimpleModule.Database.Health; @@ -119,6 +120,8 @@ app.UseHttpsRedirection(); +app.UseInertia(); + app.UseStaticFiles(); app.UseAuthentication(); diff --git a/src/SimpleModule.Api/SimpleModule.Api.csproj b/src/SimpleModule.Api/SimpleModule.Api.csproj index 90a7f527..4a7e35ff 100644 --- a/src/SimpleModule.Api/SimpleModule.Api.csproj +++ b/src/SimpleModule.Api/SimpleModule.Api.csproj @@ -41,4 +41,15 @@ /> + + + + + + + + diff --git a/src/SimpleModule.Api/wwwroot/css/app.css b/src/SimpleModule.Api/wwwroot/css/app.css index bde54fe1..cb9b9291 100644 --- a/src/SimpleModule.Api/wwwroot/css/app.css +++ b/src/SimpleModule.Api/wwwroot/css/app.css @@ -1,2 +1,2 @@ /*! tailwindcss v4.1.3 | MIT License | https://tailwindcss.com */ -@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:rotateX(0);--tw-rotate-y:rotateY(0);--tw-rotate-z:rotateZ(0);--tw-skew-x:skewX(0);--tw-skew-y:skewY(0);--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-duration:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height:calc(1.5/1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5/2.25);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--leading-relaxed:1.625;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--ease-out:cubic-bezier(0,0,.2,1);--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-primary:#0d9488;--color-primary-hover:#0f766e;--color-primary-subtle:#0d948814;--color-primary-ring:#0d948840;--color-accent:#059669;--color-success:#16a34a;--color-success-bg:#16a34a1a;--color-success-text:#15803d;--color-danger:#e11d48;--color-danger-hover:#be123c;--color-danger-bg:#e11d4814;--color-danger-text:#9f1239;--color-warning:#d97706;--color-warning-bg:#d9770614;--color-warning-border:#d9770633;--color-warning-text:#92400e;--color-info:#0ea5e9;--color-info-bg:#0ea5e914;--color-surface:#fff;--color-surface-raised:#f8fafc;--color-surface-sunken:#f1f5f9;--color-surface-overlay:#fffc;--color-text:#0f172a;--color-text-secondary:#475569;--color-text-muted:#94a3b8;--color-border:#e2e8f0;--color-border-strong:#cbd5e1;--color-code-bg:#1e293b;--color-code-text:#e2e8f0;--color-muted:#94a3b8}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html{scroll-behavior:smooth;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{background-color:var(--color-surface-sunken);color:var(--color-text);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.3s;font-family:DM Sans,system-ui,sans-serif;transition-duration:.3s}h1,h2,h3,h4,h5,h6{--tw-font-weight:var(--font-weight-bold);font-family:Sora,DM Sans,system-ui,sans-serif;font-weight:var(--font-weight-bold);--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight);color:var(--color-text);margin-top:0}h1{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}h2{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}h3{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}label{margin-bottom:calc(var(--spacing)*1.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);color:var(--color-text-secondary);display:block}input[type=email],input[type=password],input[type=text],input[type=tel]{border-radius:var(--radius-xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);width:100%;padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*3);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--color-text);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;transition-duration:.2s}:is(input[type=email],input[type=password],input[type=text],input[type=tel])::placeholder{color:var(--color-text-muted)}input[type=email]:focus,input[type=password]:focus,input[type=text]:focus,input[type=tel]:focus{border-color:var(--color-primary);--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(4px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);--tw-ring-color:var(--color-primary-ring);--tw-outline-style:none;outline-style:none}a{color:var(--color-primary);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;transition-duration:.15s}a:hover{color:var(--color-primary-hover)}hr{margin-block:calc(var(--spacing)*6);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--color-border)}::selection{background:#0d948833}}@layer components{.glass-card{border-radius:var(--radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface-overlay);--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);-webkit-backdrop-filter:blur(20px)saturate(180%)}.dark .glass-card{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);box-shadow:0 0 0 1px #94a3b80d,0 25px 50px -12px #00000080}.btn-primary,.btn-secondary,.btn-ghost,.btn-danger,.btn-outline{cursor:pointer;justify-content:center;align-items:center;gap:calc(var(--spacing)*2);border-radius:var(--radius-xl);--tw-border-style:none;padding-inline:calc(var(--spacing)*5);padding-block:calc(var(--spacing)*2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;--tw-ease:var(--ease-out);transition-duration:.2s;transition-timing-function:var(--ease-out);border-style:none;text-decoration-line:none;display:inline-flex}.btn-primary:active,.btn-secondary:active,.btn-ghost:active,.btn-danger:active,.btn-outline:active{transform:scale(.97)}.btn-primary{color:var(--color-white);background:linear-gradient(135deg,var(--color-primary),var(--color-accent));box-shadow:0 4px 14px #0d948859}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 6px 20px #0d948880}.btn-secondary{border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);color:var(--color-text)}.btn-secondary:hover{border-color:var(--color-border-strong);background-color:var(--color-surface-raised)}.btn-ghost{color:var(--color-text-secondary);background-color:#0000}.btn-ghost:hover{background-color:var(--color-primary-subtle);color:var(--color-primary)}.btn-danger{background-color:var(--color-danger);color:var(--color-white);box-shadow:0 4px 14px #e11d4840}.btn-danger:hover{background-color:var(--color-danger-hover);transform:translateY(-1px);box-shadow:0 6px 20px #e11d4866}.btn-outline{border-style:var(--tw-border-style);color:var(--color-primary);background-color:#0000;border-width:2px;border-color:#0d94884d}@supports (color:color-mix(in lab, red, red)){.btn-outline{border-color:color-mix(in oklab,var(--color-primary)30%,transparent)}}.btn-outline:hover{border-color:var(--color-primary);background-color:var(--color-primary-subtle)}.btn-sm{border-radius:var(--radius-lg);padding-inline:calc(var(--spacing)*3.5);padding-block:calc(var(--spacing)*1.5);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.btn-lg{padding-inline:calc(var(--spacing)*8);padding-block:calc(var(--spacing)*3.5);font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.form-group{margin-bottom:calc(var(--spacing)*5)}.badge-success,.badge-danger,.badge-warning,.badge-info{padding-inline:calc(var(--spacing)*2.5);padding-block:calc(var(--spacing)*1);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);border-radius:3.40282e38px;align-items:center;display:inline-flex}.badge-success{background-color:var(--color-success-bg);color:var(--color-success-text)}.badge-danger{background-color:var(--color-danger-bg);color:var(--color-danger-text)}.badge-warning{background-color:var(--color-warning-bg);color:var(--color-warning-text)}.badge-info{background-color:var(--color-info-bg);color:var(--color-primary)}.alert-success,.alert-danger,.alert-warning,.alert-info{border-radius:var(--radius-xl);border-style:var(--tw-border-style);padding:calc(var(--spacing)*4);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));border-width:1px}.alert-success{background-color:var(--color-success-bg);color:var(--color-success-text);border-color:#16a34a33}@supports (color:color-mix(in lab, red, red)){.alert-success{border-color:color-mix(in oklab,var(--color-success)20%,transparent)}}.alert-danger{background-color:var(--color-danger-bg);color:var(--color-danger-text);border-color:#e11d4833}@supports (color:color-mix(in lab, red, red)){.alert-danger{border-color:color-mix(in oklab,var(--color-danger)20%,transparent)}}.alert-warning{border-color:var(--color-warning-border);background-color:var(--color-warning-bg);color:var(--color-warning-text)}.alert-info{background-color:var(--color-info-bg);color:var(--color-primary);border-color:#0ea5e933}@supports (color:color-mix(in lab, red, red)){.alert-info{border-color:color-mix(in oklab,var(--color-info)20%,transparent)}}.code-block{border-radius:var(--radius-xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-code-bg);padding:calc(var(--spacing)*4);font-family:var(--font-mono);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--color-code-text);font-family:JetBrains Mono,Fira Code,monospace;overflow:auto}.panel{margin-bottom:calc(var(--spacing)*8)}.panel-title{margin-bottom:calc(var(--spacing)*4);align-items:center;gap:calc(var(--spacing)*2);padding-bottom:calc(var(--spacing)*3);font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height));--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold);font-family:Sora,system-ui,sans-serif;display:flex}.panel-title:before{content:"";height:calc(var(--spacing)*5);width:calc(var(--spacing)*1);background:linear-gradient(180deg,var(--color-primary),var(--color-accent));border-radius:3.40282e38px}.card{border-radius:var(--radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);padding:calc(var(--spacing)*5);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;transition-duration:.2s}.card:hover{border-color:var(--color-border-strong)}.nav-link-active,.nav-link-inactive{border-radius:var(--radius-xl);padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;text-decoration-line:none;transition-duration:.15s;display:block}.nav-link-active{background-color:var(--color-primary-subtle);--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--color-primary)}.nav-link-inactive{color:var(--color-text-secondary)}.nav-link-inactive:hover{background-color:var(--color-surface-raised);color:var(--color-text)}}@layer utilities{.absolute{position:absolute}.relative{position:relative}.static{position:static}.sticky{position:sticky}.top-0{top:calc(var(--spacing)*0)}.top-1\/2{top:50%}.left-1\/2{left:50%}.z-50{z-index:50}.m-0{margin:calc(var(--spacing)*0)}.mx-auto{margin-inline:auto}.my-4{margin-block:calc(var(--spacing)*4)}.my-6{margin-block:calc(var(--spacing)*6)}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-6{margin-top:calc(var(--spacing)*6)}.mt-8{margin-top:calc(var(--spacing)*8)}.mb-0{margin-bottom:calc(var(--spacing)*0)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-5{margin-bottom:calc(var(--spacing)*5)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.mb-16{margin-bottom:calc(var(--spacing)*16)}.ml-7{margin-left:calc(var(--spacing)*7)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.table{display:table}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-12{height:calc(var(--spacing)*12)}.h-14{height:calc(var(--spacing)*14)}.h-16{height:calc(var(--spacing)*16)}.h-\[18px\]{height:18px}.max-h-30{max-height:calc(var(--spacing)*30)}.max-h-50{max-height:calc(var(--spacing)*50)}.min-h-\[calc\(100vh-12rem\)\]{min-height:calc(100vh - 12rem)}.min-h-\[calc\(100vh-16rem\)\]{min-height:calc(100vh - 16rem)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-12{width:calc(var(--spacing)*12)}.w-14{width:calc(var(--spacing)*14)}.w-16{width:calc(var(--spacing)*16)}.w-\[18px\]{width:18px}.w-full{width:100%}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\[140px\]{max-width:140px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x)var(--tw-rotate-y)var(--tw-rotate-z)var(--tw-skew-x)var(--tw-skew-y)}.cursor-pointer{cursor:pointer}.list-decimal{list-style-type:decimal}.list-none{list-style-type:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-5{gap:calc(var(--spacing)*5)}.gap-6{gap:calc(var(--spacing)*6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-none{--tw-border-style:none;border-style:none}.border-border{border-color:var(--color-border)}.bg-info-bg{background-color:var(--color-info-bg)}.bg-primary-subtle{background-color:var(--color-primary-subtle)}.bg-success-bg{background-color:var(--color-success-bg)}.bg-surface{background-color:var(--color-surface)}.bg-surface-overlay{background-color:var(--color-surface-overlay)}.bg-surface-raised{background-color:var(--color-surface-raised)}.bg-transparent{background-color:#0000}.bg-warning-bg{background-color:var(--color-warning-bg)}.p-0{padding:calc(var(--spacing)*0)}.p-3{padding:calc(var(--spacing)*3)}.p-5{padding:calc(var(--spacing)*5)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-3{padding-block:calc(var(--spacing)*3)}.pl-5{padding-left:calc(var(--spacing)*5)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.break-all{word-break:break-all}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent{color:var(--color-accent)}.text-border{color:var(--color-border)}.text-danger{color:var(--color-danger)}.text-info{color:var(--color-info)}.text-muted{color:var(--color-muted)}.text-primary{color:var(--color-primary)}.text-success{color:var(--color-success)}.text-text{color:var(--color-text)}.text-text-muted{color:var(--color-text-muted)}.text-text-secondary{color:var(--color-text-secondary)}.text-warning{color:var(--color-warning)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.no-underline{text-decoration-line:none}.accent-primary{accent-color:var(--color-primary)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}@media (hover:hover){.group-hover\:scale-105:is(:where(.group):hover *){--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x)var(--tw-scale-y)}.group-hover\:text-primary:is(:where(.group):hover *){color:var(--color-primary)}}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:bg-surface-raised:hover{background-color:var(--color-surface-raised)}.hover\:text-primary:hover{color:var(--color-primary)}.hover\:text-text:hover{color:var(--color-text)}.hover\:underline:hover{text-decoration-line:underline}}@media (min-width:40rem){.sm\:sticky{position:sticky}.sm\:top-20{top:calc(var(--spacing)*20)}.sm\:block{display:block}.sm\:flex{display:flex}.sm\:inline-flex{display:inline-flex}.sm\:w-56{width:calc(var(--spacing)*56)}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:p-8{padding:calc(var(--spacing)*8)}.sm\:px-6{padding-inline:calc(var(--spacing)*6)}}@media (min-width:64rem){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (prefers-color-scheme:dark){.dark\:block{display:block}.dark\:hidden{display:none}}.gradient-text{background:linear-gradient(135deg,var(--color-primary),var(--color-accent));-webkit-text-fill-color:transparent;-webkit-background-clip:text;background-clip:text}.gradient-border{position:relative}.gradient-border:before{content:"";border-radius:inherit;background:linear-gradient(135deg,var(--color-primary),var(--color-accent));-webkit-mask-composite:xor;pointer-events:none;-webkit-mask-composite:xor;-webkit-mask-source-type:auto,auto;padding:1px;position:absolute;inset:0;-webkit-mask-image:linear-gradient(#fff 0 0),linear-gradient(#fff 0 0);mask-image:linear-gradient(#fff 0 0),linear-gradient(#fff 0 0);-webkit-mask-position:0 0,0 0;mask-position:0 0,0 0;-webkit-mask-size:auto,auto;mask-size:auto,auto;-webkit-mask-repeat:repeat,repeat;mask-repeat:repeat,repeat;-webkit-mask-clip:content-box,border-box;mask-clip:content-box,border-box;-webkit-mask-origin:content-box,border-box;mask-origin:content-box,border-box;-webkit-mask-composite:xor;mask-composite:exclude;-webkit-mask-source-type:auto,auto;mask-mode:match-source,match-source}}.dark{--color-primary-subtle:#0d948826;--color-primary-ring:#0d948859;--color-success-bg:#4ade801f;--color-success-text:#86efac;--color-danger-bg:#e11d481f;--color-danger-text:#fda4af;--color-warning-bg:#d977061f;--color-warning-border:#d977064d;--color-warning-text:#fcd34d;--color-info-bg:#0ea5e91f;--color-surface:#0f172a;--color-surface-raised:#1e293b;--color-surface-sunken:#0b1120;--color-surface-overlay:#0f172ad9;--color-text:#f1f5f9;--color-text-secondary:#94a3b8;--color-text-muted:#64748b;--color-text-inverse:#0f172a;--color-border:#1e293b;--color-border-strong:#334155;--color-code-bg:#020617;--color-code-text:#e2e8f0}.bg-mesh{z-index:-1;background:var(--color-surface-sunken);position:fixed;inset:0;overflow:hidden}.bg-mesh:before,.bg-mesh:after{content:"";filter:blur(100px);opacity:.15;border-radius:50%;animation:20s ease-in-out infinite mesh-float;position:absolute}.bg-mesh:before{background:var(--color-primary);width:600px;height:600px;top:-10%;right:-10%}.bg-mesh:after{background:var(--color-accent);width:500px;height:500px;animation-direction:reverse;animation-delay:-10s;bottom:-10%;left:-10%}.dark .bg-mesh:before,.dark .bg-mesh:after{opacity:.08}@keyframes mesh-float{0%,to{transform:translate(0)scale(1)}33%{transform:translate(40px,-30px)scale(1.05)}66%{transform:translate(-20px,20px)scale(.95)}}.spinner{margin-left:calc(var(--spacing)*2);height:calc(var(--spacing)*4);width:calc(var(--spacing)*4);animation:var(--animate-spin);border-style:var(--tw-border-style);border-width:2px;border-color:var(--color-border);border-top-color:var(--color-primary);vertical-align:middle;border-radius:3.40282e38px;display:inline-block}.user-dropdown-wrap{position:relative}.user-dropdown-trigger{cursor:pointer;align-items:center;gap:calc(var(--spacing)*2);border-radius:var(--radius-xl);--tw-border-style:none;padding-inline:calc(var(--spacing)*2);padding-block:calc(var(--spacing)*1.5);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;background-color:#0000;border-style:none;transition-duration:.2s;display:flex}.user-dropdown-trigger:hover,.user-dropdown-trigger[aria-expanded=true]{background-color:var(--color-surface-raised)}.user-dropdown{border-radius:var(--radius-xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);width:240px;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);opacity:0;pointer-events:none;z-index:100;transition:opacity .18s,transform .18s;position:absolute;top:calc(100% + 6px);right:0;transform:translateY(-4px)scale(.97)}.user-dropdown.open{opacity:1;pointer-events:auto;transform:translateY(0)scale(1)}.dark .user-dropdown{box-shadow:0 0 0 1px #94a3b80f,0 20px 40px -8px #0009}.user-dropdown-header{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--color-border);padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*3)}.user-dropdown-body{padding-block:calc(var(--spacing)*1.5)}.user-dropdown-item{cursor:pointer;align-items:center;gap:calc(var(--spacing)*2.5);padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*2);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--color-text-secondary);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;text-decoration-line:none;transition-duration:.15s;display:flex}.user-dropdown-item:hover{background-color:var(--color-surface-raised);color:var(--color-text)}.user-dropdown-divider{margin-block:calc(var(--spacing)*1.5);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--color-border)}.user-dropdown-item.danger{color:var(--color-danger)}.user-dropdown-item.danger:hover{background-color:var(--color-danger-bg);color:var(--color-danger)}.dash-card{border-radius:var(--radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);padding:calc(var(--spacing)*5);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;transition-duration:.2s}.dash-card:hover{border-color:var(--color-border-strong);--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dash-stat{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height));--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold);--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight);font-family:Sora,system-ui,sans-serif}.dash-label{margin-top:calc(var(--spacing)*1);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider);color:var(--color-text-muted);text-transform:uppercase}.validation-message{margin-top:calc(var(--spacing)*1.5);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);color:var(--color-danger)}table{width:100%;font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}table th{padding-bottom:calc(var(--spacing)*3);text-align:left;font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider);color:var(--color-text-muted);text-transform:uppercase}table td{border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--color-border);padding-block:calc(var(--spacing)*2.5);color:var(--color-text-secondary)}table td:first-child{font-family:var(--font-mono);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--color-primary)}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background-color:var(--color-border-strong);border-radius:3.40282e38px}::-webkit-scrollbar-thumb:hover{background-color:var(--color-text-muted)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false;initial-value:rotateX(0)}@property --tw-rotate-y{syntax:"*";inherits:false;initial-value:rotateY(0)}@property --tw-rotate-z{syntax:"*";inherits:false;initial-value:rotateZ(0)}@property --tw-skew-x{syntax:"*";inherits:false;initial-value:skewX(0)}@property --tw-skew-y{syntax:"*";inherits:false;initial-value:skewY(0)}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-duration{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}} \ No newline at end of file +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:rotateX(0);--tw-rotate-y:rotateY(0);--tw-rotate-z:rotateZ(0);--tw-skew-x:skewX(0);--tw-skew-y:skewY(0);--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-600:oklch(66.6% .179 58.318);--color-green-400:oklch(79.2% .209 151.711);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-blue-900:oklch(37.9% .146 265.522);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-3xl:48rem;--container-4xl:56rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height:calc(1.5/1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25/1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5/2.25);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--leading-relaxed:1.625;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--ease-out:cubic-bezier(0,0,.2,1);--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-primary:#0d9488;--color-primary-hover:#0f766e;--color-primary-subtle:#0d948814;--color-primary-ring:#0d948840;--color-accent:#059669;--color-success:#16a34a;--color-success-bg:#16a34a1a;--color-success-text:#15803d;--color-danger:#e11d48;--color-danger-hover:#be123c;--color-danger-bg:#e11d4814;--color-danger-text:#9f1239;--color-warning:#d97706;--color-warning-bg:#d9770614;--color-warning-border:#d9770633;--color-warning-text:#92400e;--color-info:#0ea5e9;--color-info-bg:#0ea5e914;--color-surface:#fff;--color-surface-raised:#f8fafc;--color-surface-sunken:#f1f5f9;--color-surface-overlay:#fffc;--color-text:#0f172a;--color-text-secondary:#475569;--color-text-muted:#94a3b8;--color-border:#e2e8f0;--color-border-strong:#cbd5e1;--color-code-bg:#1e293b;--color-code-text:#e2e8f0;--color-muted:#94a3b8}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html{scroll-behavior:smooth;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{background-color:var(--color-surface-sunken);color:var(--color-text);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.3s;font-family:DM Sans,system-ui,sans-serif;transition-duration:.3s}h1,h2,h3,h4,h5,h6{--tw-font-weight:var(--font-weight-bold);font-family:Sora,DM Sans,system-ui,sans-serif;font-weight:var(--font-weight-bold);--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight);color:var(--color-text);margin-top:0}h1{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}h2{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}h3{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}label{margin-bottom:calc(var(--spacing)*1.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);color:var(--color-text-secondary);display:block}input[type=email],input[type=password],input[type=text],input[type=tel]{border-radius:var(--radius-xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);width:100%;padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*3);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--color-text);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;transition-duration:.2s}:is(input[type=email],input[type=password],input[type=text],input[type=tel])::placeholder{color:var(--color-text-muted)}input[type=email]:focus,input[type=password]:focus,input[type=text]:focus,input[type=tel]:focus{border-color:var(--color-primary);--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(4px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);--tw-ring-color:var(--color-primary-ring);--tw-outline-style:none;outline-style:none}a{color:var(--color-primary);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;transition-duration:.15s}a:hover{color:var(--color-primary-hover)}hr{margin-block:calc(var(--spacing)*6);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--color-border)}::selection{background:#0d948833}}@layer components{.glass-card{border-radius:var(--radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface-overlay);--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);-webkit-backdrop-filter:blur(20px)saturate(180%)}.dark .glass-card{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);box-shadow:0 0 0 1px #94a3b80d,0 25px 50px -12px #00000080}.btn-primary,.btn-secondary,.btn-ghost,.btn-danger,.btn-outline{cursor:pointer;justify-content:center;align-items:center;gap:calc(var(--spacing)*2);border-radius:var(--radius-xl);--tw-border-style:none;padding-inline:calc(var(--spacing)*5);padding-block:calc(var(--spacing)*2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;--tw-ease:var(--ease-out);transition-duration:.2s;transition-timing-function:var(--ease-out);border-style:none;text-decoration-line:none;display:inline-flex}.btn-primary:active,.btn-secondary:active,.btn-ghost:active,.btn-danger:active,.btn-outline:active{transform:scale(.97)}.btn-primary{color:var(--color-white);background:linear-gradient(135deg,var(--color-primary),var(--color-accent));box-shadow:0 4px 14px #0d948859}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 6px 20px #0d948880}.btn-secondary{border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);color:var(--color-text)}.btn-secondary:hover{border-color:var(--color-border-strong);background-color:var(--color-surface-raised)}.btn-ghost{color:var(--color-text-secondary);background-color:#0000}.btn-ghost:hover{background-color:var(--color-primary-subtle);color:var(--color-primary)}.btn-danger{background-color:var(--color-danger);color:var(--color-white);box-shadow:0 4px 14px #e11d4840}.btn-danger:hover{background-color:var(--color-danger-hover);transform:translateY(-1px);box-shadow:0 6px 20px #e11d4866}.btn-outline{border-style:var(--tw-border-style);color:var(--color-primary);background-color:#0000;border-width:2px;border-color:#0d94884d}@supports (color:color-mix(in lab, red, red)){.btn-outline{border-color:color-mix(in oklab,var(--color-primary)30%,transparent)}}.btn-outline:hover{border-color:var(--color-primary);background-color:var(--color-primary-subtle)}.btn-sm{border-radius:var(--radius-lg);padding-inline:calc(var(--spacing)*3.5);padding-block:calc(var(--spacing)*1.5);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.btn-lg{padding-inline:calc(var(--spacing)*8);padding-block:calc(var(--spacing)*3.5);font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.form-group{margin-bottom:calc(var(--spacing)*5)}.badge-success,.badge-danger,.badge-warning,.badge-info{padding-inline:calc(var(--spacing)*2.5);padding-block:calc(var(--spacing)*1);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);border-radius:3.40282e38px;align-items:center;display:inline-flex}.badge-success{background-color:var(--color-success-bg);color:var(--color-success-text)}.badge-danger{background-color:var(--color-danger-bg);color:var(--color-danger-text)}.badge-warning{background-color:var(--color-warning-bg);color:var(--color-warning-text)}.badge-info{background-color:var(--color-info-bg);color:var(--color-primary)}.alert-success,.alert-danger,.alert-warning,.alert-info{border-radius:var(--radius-xl);border-style:var(--tw-border-style);padding:calc(var(--spacing)*4);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));border-width:1px}.alert-success{background-color:var(--color-success-bg);color:var(--color-success-text);border-color:#16a34a33}@supports (color:color-mix(in lab, red, red)){.alert-success{border-color:color-mix(in oklab,var(--color-success)20%,transparent)}}.alert-danger{background-color:var(--color-danger-bg);color:var(--color-danger-text);border-color:#e11d4833}@supports (color:color-mix(in lab, red, red)){.alert-danger{border-color:color-mix(in oklab,var(--color-danger)20%,transparent)}}.alert-warning{border-color:var(--color-warning-border);background-color:var(--color-warning-bg);color:var(--color-warning-text)}.alert-info{background-color:var(--color-info-bg);color:var(--color-primary);border-color:#0ea5e933}@supports (color:color-mix(in lab, red, red)){.alert-info{border-color:color-mix(in oklab,var(--color-info)20%,transparent)}}.code-block{border-radius:var(--radius-xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-code-bg);padding:calc(var(--spacing)*4);font-family:var(--font-mono);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--color-code-text);font-family:JetBrains Mono,Fira Code,monospace;overflow:auto}.panel{margin-bottom:calc(var(--spacing)*8)}.panel-title{margin-bottom:calc(var(--spacing)*4);align-items:center;gap:calc(var(--spacing)*2);padding-bottom:calc(var(--spacing)*3);font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height));--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold);font-family:Sora,system-ui,sans-serif;display:flex}.panel-title:before{content:"";height:calc(var(--spacing)*5);width:calc(var(--spacing)*1);background:linear-gradient(180deg,var(--color-primary),var(--color-accent));border-radius:3.40282e38px}.card{border-radius:var(--radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);padding:calc(var(--spacing)*5);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;transition-duration:.2s}.card:hover{border-color:var(--color-border-strong)}.nav-link-active,.nav-link-inactive{border-radius:var(--radius-xl);padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;text-decoration-line:none;transition-duration:.15s;display:block}.nav-link-active{background-color:var(--color-primary-subtle);--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--color-primary)}.nav-link-inactive{color:var(--color-text-secondary)}.nav-link-inactive:hover{background-color:var(--color-surface-raised);color:var(--color-text)}}@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.top-0{top:calc(var(--spacing)*0)}.top-1\/2{top:50%}.left-1\/2{left:50%}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:calc(var(--spacing)*0)}.mx-auto{margin-inline:auto}.my-4{margin-block:calc(var(--spacing)*4)}.my-6{margin-block:calc(var(--spacing)*6)}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-6{margin-top:calc(var(--spacing)*6)}.mt-8{margin-top:calc(var(--spacing)*8)}.mb-0{margin-bottom:calc(var(--spacing)*0)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-5{margin-bottom:calc(var(--spacing)*5)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.mb-16{margin-bottom:calc(var(--spacing)*16)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-2{margin-left:calc(var(--spacing)*2)}.ml-4{margin-left:calc(var(--spacing)*4)}.ml-7{margin-left:calc(var(--spacing)*7)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.table{display:table}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-12{height:calc(var(--spacing)*12)}.h-14{height:calc(var(--spacing)*14)}.h-16{height:calc(var(--spacing)*16)}.h-\[18px\]{height:18px}.max-h-30{max-height:calc(var(--spacing)*30)}.max-h-50{max-height:calc(var(--spacing)*50)}.min-h-\[calc\(100vh-12rem\)\]{min-height:calc(100vh - 12rem)}.min-h-\[calc\(100vh-16rem\)\]{min-height:calc(100vh - 16rem)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-12{width:calc(var(--spacing)*12)}.w-14{width:calc(var(--spacing)*14)}.w-16{width:calc(var(--spacing)*16)}.w-\[18px\]{width:18px}.w-full{width:100%}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\[140px\]{max-width:140px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x)var(--tw-rotate-y)var(--tw-rotate-z)var(--tw-skew-x)var(--tw-skew-y)}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-decimal{list-style-type:decimal}.list-none{list-style-type:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-5{gap:calc(var(--spacing)*5)}.gap-6{gap:calc(var(--spacing)*6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px*var(--tw-divide-y-reverse));border-bottom-width:calc(1px*calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-gray-200>:not(:last-child)){border-color:var(--color-gray-200)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-x-auto{overflow-x:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-none{--tw-border-style:none;border-style:none}.border-border{border-color:var(--color-border)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-green-600{background-color:var(--color-green-600)}.bg-info-bg{background-color:var(--color-info-bg)}.bg-primary-subtle{background-color:var(--color-primary-subtle)}.bg-red-600{background-color:var(--color-red-600)}.bg-success-bg{background-color:var(--color-success-bg)}.bg-surface{background-color:var(--color-surface)}.bg-surface-overlay{background-color:var(--color-surface-overlay)}.bg-surface-raised{background-color:var(--color-surface-raised)}.bg-transparent{background-color:#0000}.bg-warning-bg{background-color:var(--color-warning-bg)}.bg-white{background-color:var(--color-white)}.p-0{padding:calc(var(--spacing)*0)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-5{padding:calc(var(--spacing)*5)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-3{padding-block:calc(var(--spacing)*3)}.pl-5{padding-left:calc(var(--spacing)*5)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.break-all{word-break:break-all}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent{color:var(--color-accent)}.text-amber-600{color:var(--color-amber-600)}.text-blue-600{color:var(--color-blue-600)}.text-blue-800{color:var(--color-blue-800)}.text-border{color:var(--color-border)}.text-danger{color:var(--color-danger)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-green-600{color:var(--color-green-600)}.text-info{color:var(--color-info)}.text-muted{color:var(--color-muted)}.text-primary{color:var(--color-primary)}.text-red-600{color:var(--color-red-600)}.text-success{color:var(--color-success)}.text-text{color:var(--color-text)}.text-text-muted{color:var(--color-text-muted)}.text-text-secondary{color:var(--color-text-secondary)}.text-warning{color:var(--color-warning)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.no-underline{text-decoration-line:none}.accent-primary{accent-color:var(--color-primary)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}@media (hover:hover){.group-hover\:scale-105:is(:where(.group):hover *){--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x)var(--tw-scale-y)}.group-hover\:text-primary:is(:where(.group):hover *){color:var(--color-primary)}}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-green-700:hover{background-color:var(--color-green-700)}.hover\:bg-red-700:hover{background-color:var(--color-red-700)}.hover\:bg-surface-raised:hover{background-color:var(--color-surface-raised)}.hover\:text-blue-800:hover{color:var(--color-blue-800)}.hover\:text-gray-700:hover{color:var(--color-gray-700)}.hover\:text-primary:hover{color:var(--color-primary)}.hover\:text-red-800:hover{color:var(--color-red-800)}.hover\:text-text:hover{color:var(--color-text)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width:40rem){.sm\:sticky{position:sticky}.sm\:top-20{top:calc(var(--spacing)*20)}.sm\:block{display:block}.sm\:flex{display:flex}.sm\:inline-flex{display:inline-flex}.sm\:w-56{width:calc(var(--spacing)*56)}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:p-8{padding:calc(var(--spacing)*8)}.sm\:px-6{padding-inline:calc(var(--spacing)*6)}}@media (min-width:64rem){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (prefers-color-scheme:dark){.dark\:block{display:block}.dark\:hidden{display:none}:where(.dark\:divide-gray-700>:not(:last-child)){border-color:var(--color-gray-700)}.dark\:border-gray-600{border-color:var(--color-gray-600)}.dark\:border-gray-700{border-color:var(--color-gray-700)}.dark\:bg-blue-900\/30{background-color:#1c398e4d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-blue-900\/30{background-color:color-mix(in oklab,var(--color-blue-900)30%,transparent)}}.dark\:bg-gray-800{background-color:var(--color-gray-800)}.dark\:text-amber-400{color:var(--color-amber-400)}.dark\:text-blue-300{color:var(--color-blue-300)}.dark\:text-blue-400{color:var(--color-blue-400)}.dark\:text-gray-400{color:var(--color-gray-400)}.dark\:text-green-400{color:var(--color-green-400)}.dark\:text-red-400{color:var(--color-red-400)}@media (hover:hover){.dark\:hover\:bg-gray-800\/50:hover{background-color:#1e293980}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-gray-800\/50:hover{background-color:color-mix(in oklab,var(--color-gray-800)50%,transparent)}}.dark\:hover\:text-blue-300:hover{color:var(--color-blue-300)}.dark\:hover\:text-gray-300:hover{color:var(--color-gray-300)}}}.gradient-text{background:linear-gradient(135deg,var(--color-primary),var(--color-accent));-webkit-text-fill-color:transparent;-webkit-background-clip:text;background-clip:text}.gradient-border{position:relative}.gradient-border:before{content:"";border-radius:inherit;background:linear-gradient(135deg,var(--color-primary),var(--color-accent));-webkit-mask-composite:xor;pointer-events:none;-webkit-mask-composite:xor;-webkit-mask-source-type:auto,auto;padding:1px;position:absolute;inset:0;-webkit-mask-image:linear-gradient(#fff 0 0),linear-gradient(#fff 0 0);mask-image:linear-gradient(#fff 0 0),linear-gradient(#fff 0 0);-webkit-mask-position:0 0,0 0;mask-position:0 0,0 0;-webkit-mask-size:auto,auto;mask-size:auto,auto;-webkit-mask-repeat:repeat,repeat;mask-repeat:repeat,repeat;-webkit-mask-clip:content-box,border-box;mask-clip:content-box,border-box;-webkit-mask-origin:content-box,border-box;mask-origin:content-box,border-box;-webkit-mask-composite:xor;mask-composite:exclude;-webkit-mask-source-type:auto,auto;mask-mode:match-source,match-source}}.dark{--color-primary-subtle:#0d948826;--color-primary-ring:#0d948859;--color-success-bg:#4ade801f;--color-success-text:#86efac;--color-danger-bg:#e11d481f;--color-danger-text:#fda4af;--color-warning-bg:#d977061f;--color-warning-border:#d977064d;--color-warning-text:#fcd34d;--color-info-bg:#0ea5e91f;--color-surface:#0f172a;--color-surface-raised:#1e293b;--color-surface-sunken:#0b1120;--color-surface-overlay:#0f172ad9;--color-text:#f1f5f9;--color-text-secondary:#94a3b8;--color-text-muted:#64748b;--color-text-inverse:#0f172a;--color-border:#1e293b;--color-border-strong:#334155;--color-code-bg:#020617;--color-code-text:#e2e8f0}.bg-mesh{z-index:-1;background:var(--color-surface-sunken);position:fixed;inset:0;overflow:hidden}.bg-mesh:before,.bg-mesh:after{content:"";filter:blur(100px);opacity:.15;border-radius:50%;animation:20s ease-in-out infinite mesh-float;position:absolute}.bg-mesh:before{background:var(--color-primary);width:600px;height:600px;top:-10%;right:-10%}.bg-mesh:after{background:var(--color-accent);width:500px;height:500px;animation-direction:reverse;animation-delay:-10s;bottom:-10%;left:-10%}.dark .bg-mesh:before,.dark .bg-mesh:after{opacity:.08}@keyframes mesh-float{0%,to{transform:translate(0)scale(1)}33%{transform:translate(40px,-30px)scale(1.05)}66%{transform:translate(-20px,20px)scale(.95)}}.spinner{margin-left:calc(var(--spacing)*2);height:calc(var(--spacing)*4);width:calc(var(--spacing)*4);animation:var(--animate-spin);border-style:var(--tw-border-style);border-width:2px;border-color:var(--color-border);border-top-color:var(--color-primary);vertical-align:middle;border-radius:3.40282e38px;display:inline-block}.user-dropdown-wrap{position:relative}.user-dropdown-trigger{cursor:pointer;align-items:center;gap:calc(var(--spacing)*2);border-radius:var(--radius-xl);--tw-border-style:none;padding-inline:calc(var(--spacing)*2);padding-block:calc(var(--spacing)*1.5);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;background-color:#0000;border-style:none;transition-duration:.2s;display:flex}.user-dropdown-trigger:hover,.user-dropdown-trigger[aria-expanded=true]{background-color:var(--color-surface-raised)}.user-dropdown{border-radius:var(--radius-xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);width:240px;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);opacity:0;pointer-events:none;z-index:100;transition:opacity .18s,transform .18s;position:absolute;top:calc(100% + 6px);right:0;transform:translateY(-4px)scale(.97)}.user-dropdown.open{opacity:1;pointer-events:auto;transform:translateY(0)scale(1)}.dark .user-dropdown{box-shadow:0 0 0 1px #94a3b80f,0 20px 40px -8px #0009}.user-dropdown-header{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--color-border);padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*3)}.user-dropdown-body{padding-block:calc(var(--spacing)*1.5)}.user-dropdown-item{cursor:pointer;align-items:center;gap:calc(var(--spacing)*2.5);padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*2);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--color-text-secondary);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;text-decoration-line:none;transition-duration:.15s;display:flex}.user-dropdown-item:hover{background-color:var(--color-surface-raised);color:var(--color-text)}.user-dropdown-divider{margin-block:calc(var(--spacing)*1.5);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--color-border)}.user-dropdown-item.danger{color:var(--color-danger)}.user-dropdown-item.danger:hover{background-color:var(--color-danger-bg);color:var(--color-danger)}.dash-card{border-radius:var(--radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);padding:calc(var(--spacing)*5);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;transition-duration:.2s}.dash-card:hover{border-color:var(--color-border-strong);--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dash-stat{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height));--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold);--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight);font-family:Sora,system-ui,sans-serif}.dash-label{margin-top:calc(var(--spacing)*1);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider);color:var(--color-text-muted);text-transform:uppercase}.validation-message{margin-top:calc(var(--spacing)*1.5);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);color:var(--color-danger)}table{width:100%;font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}table th{padding-bottom:calc(var(--spacing)*3);text-align:left;font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider);color:var(--color-text-muted);text-transform:uppercase}table td{border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--color-border);padding-block:calc(var(--spacing)*2.5);color:var(--color-text-secondary)}table td:first-child{font-family:var(--font-mono);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--color-primary)}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background-color:var(--color-border-strong);border-radius:3.40282e38px}::-webkit-scrollbar-thumb:hover{background-color:var(--color-text-muted)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false;initial-value:rotateX(0)}@property --tw-rotate-y{syntax:"*";inherits:false;initial-value:rotateY(0)}@property --tw-rotate-z{syntax:"*";inherits:false;initial-value:rotateZ(0)}@property --tw-skew-x{syntax:"*";inherits:false;initial-value:skewX(0)}@property --tw-skew-y{syntax:"*";inherits:false;initial-value:skewY(0)}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}} \ No newline at end of file diff --git a/src/SimpleModule.Api/wwwroot/js/app.js b/src/SimpleModule.Api/wwwroot/js/app.js new file mode 100644 index 00000000..4e801e78 --- /dev/null +++ b/src/SimpleModule.Api/wwwroot/js/app.js @@ -0,0 +1 @@ +import{jsx as v}from"/js/vendor/react-jsx-runtime.js";import{createInertiaApp as E}from"/js/vendor/inertiajs-react.js";import{createRoot as g}from"/js/vendor/react-dom-client.js";const y="modulepreload",P=function(n){return"/"+n},f={},_=function(o,s,a){let u=Promise.resolve();if(s&&s.length>0){let i=function(t){return Promise.all(t.map(l=>Promise.resolve(l).then(c=>({status:"fulfilled",value:c}),c=>({status:"rejected",reason:c}))))};document.getElementsByTagName("link");const e=document.querySelector("meta[property=csp-nonce]"),m=(e==null?void 0:e.nonce)||(e==null?void 0:e.getAttribute("nonce"));u=i(s.map(t=>{if(t=P(t),t in f)return;f[t]=!0;const l=t.endsWith(".css"),c=l?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${t}"]${c}`))return;const r=document.createElement("link");if(r.rel=l?"stylesheet":y,l||(r.as="script"),r.crossOrigin="",r.href=t,m&&r.setAttribute("nonce",m),document.head.appendChild(r),l)return new Promise((p,h)=>{r.addEventListener("load",p),r.addEventListener("error",()=>h(new Error(`Unable to preload CSS for ${t}`)))})}))}function d(i){const e=new Event("vite:preloadError",{cancelable:!0});if(e.payload=i,window.dispatchEvent(e),!e.defaultPrevented)throw i}return u.then(i=>{for(const e of i||[])e.status==="rejected"&&d(e.reason);return o().catch(d)})};E({resolve:async n=>{const o=n.split("/")[0],a=(await _(()=>import(`/_content/${o}/${o}.pages.js`),[])).pages[n];return a.default?a:{default:a}},setup({el:n,App:o,props:s}){g(n).render(v(o,{...s}))}}); diff --git a/src/SimpleModule.Api/wwwroot/js/vendor/inertiajs-react.js b/src/SimpleModule.Api/wwwroot/js/vendor/inertiajs-react.js new file mode 100644 index 00000000..9b611027 --- /dev/null +++ b/src/SimpleModule.Api/wwwroot/js/vendor/inertiajs-react.js @@ -0,0 +1,13377 @@ +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var __export = (target, all3) => { + for (var name in all3) + __defProp(target, name, { get: all3[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); + +// node_modules/es-errors/type.js +var require_type = __commonJS({ + "node_modules/es-errors/type.js"(exports2, module2) { + "use strict"; + module2.exports = TypeError; + } +}); + +// (disabled):node_modules/object-inspect/util.inspect +var require_util = __commonJS({ + "(disabled):node_modules/object-inspect/util.inspect"() { + } +}); + +// node_modules/object-inspect/index.js +var require_object_inspect = __commonJS({ + "node_modules/object-inspect/index.js"(exports2, module2) { + var hasMap = typeof Map === "function" && Map.prototype; + var mapSizeDescriptor = Object.getOwnPropertyDescriptor && hasMap ? Object.getOwnPropertyDescriptor(Map.prototype, "size") : null; + var mapSize = hasMap && mapSizeDescriptor && typeof mapSizeDescriptor.get === "function" ? mapSizeDescriptor.get : null; + var mapForEach = hasMap && Map.prototype.forEach; + var hasSet = typeof Set === "function" && Set.prototype; + var setSizeDescriptor = Object.getOwnPropertyDescriptor && hasSet ? Object.getOwnPropertyDescriptor(Set.prototype, "size") : null; + var setSize = hasSet && setSizeDescriptor && typeof setSizeDescriptor.get === "function" ? setSizeDescriptor.get : null; + var setForEach = hasSet && Set.prototype.forEach; + var hasWeakMap = typeof WeakMap === "function" && WeakMap.prototype; + var weakMapHas = hasWeakMap ? WeakMap.prototype.has : null; + var hasWeakSet = typeof WeakSet === "function" && WeakSet.prototype; + var weakSetHas = hasWeakSet ? WeakSet.prototype.has : null; + var hasWeakRef = typeof WeakRef === "function" && WeakRef.prototype; + var weakRefDeref = hasWeakRef ? WeakRef.prototype.deref : null; + var booleanValueOf = Boolean.prototype.valueOf; + var objectToString2 = Object.prototype.toString; + var functionToString = Function.prototype.toString; + var $match = String.prototype.match; + var $slice = String.prototype.slice; + var $replace = String.prototype.replace; + var $toUpperCase = String.prototype.toUpperCase; + var $toLowerCase = String.prototype.toLowerCase; + var $test = RegExp.prototype.test; + var $concat = Array.prototype.concat; + var $join = Array.prototype.join; + var $arrSlice = Array.prototype.slice; + var $floor = Math.floor; + var bigIntValueOf = typeof BigInt === "function" ? BigInt.prototype.valueOf : null; + var gOPS = Object.getOwnPropertySymbols; + var symToString = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? Symbol.prototype.toString : null; + var hasShammedSymbols = typeof Symbol === "function" && typeof Symbol.iterator === "object"; + var toStringTag2 = typeof Symbol === "function" && Symbol.toStringTag && (typeof Symbol.toStringTag === hasShammedSymbols ? "object" : "symbol") ? Symbol.toStringTag : null; + var isEnumerable = Object.prototype.propertyIsEnumerable; + var gPO = (typeof Reflect === "function" ? Reflect.getPrototypeOf : Object.getPrototypeOf) || ([].__proto__ === Array.prototype ? function(O) { + return O.__proto__; + } : null); + function addNumericSeparator(num, str) { + if (num === Infinity || num === -Infinity || num !== num || num && num > -1e3 && num < 1e3 || $test.call(/e/, str)) { + return str; + } + var sepRegex = /[0-9](?=(?:[0-9]{3})+(?![0-9]))/g; + if (typeof num === "number") { + var int = num < 0 ? -$floor(-num) : $floor(num); + if (int !== num) { + var intStr = String(int); + var dec = $slice.call(str, intStr.length + 1); + return $replace.call(intStr, sepRegex, "$&_") + "." + $replace.call($replace.call(dec, /([0-9]{3})/g, "$&_"), /_$/, ""); + } + } + return $replace.call(str, sepRegex, "$&_"); + } + var utilInspect = require_util(); + var inspectCustom = utilInspect.custom; + var inspectSymbol = isSymbol2(inspectCustom) ? inspectCustom : null; + var quotes = { + __proto__: null, + "double": '"', + single: "'" + }; + var quoteREs = { + __proto__: null, + "double": /(["\\])/g, + single: /(['\\])/g + }; + module2.exports = function inspect_(obj, options, depth, seen) { + var opts = options || {}; + if (has2(opts, "quoteStyle") && !has2(quotes, opts.quoteStyle)) { + throw new TypeError('option "quoteStyle" must be "single" or "double"'); + } + if (has2(opts, "maxStringLength") && (typeof opts.maxStringLength === "number" ? opts.maxStringLength < 0 && opts.maxStringLength !== Infinity : opts.maxStringLength !== null)) { + throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`'); + } + var customInspect = has2(opts, "customInspect") ? opts.customInspect : true; + if (typeof customInspect !== "boolean" && customInspect !== "symbol") { + throw new TypeError("option \"customInspect\", if provided, must be `true`, `false`, or `'symbol'`"); + } + if (has2(opts, "indent") && opts.indent !== null && opts.indent !== " " && !(parseInt(opts.indent, 10) === opts.indent && opts.indent > 0)) { + throw new TypeError('option "indent" must be "\\t", an integer > 0, or `null`'); + } + if (has2(opts, "numericSeparator") && typeof opts.numericSeparator !== "boolean") { + throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`'); + } + var numericSeparator = opts.numericSeparator; + if (typeof obj === "undefined") { + return "undefined"; + } + if (obj === null) { + return "null"; + } + if (typeof obj === "boolean") { + return obj ? "true" : "false"; + } + if (typeof obj === "string") { + return inspectString(obj, opts); + } + if (typeof obj === "number") { + if (obj === 0) { + return Infinity / obj > 0 ? "0" : "-0"; + } + var str = String(obj); + return numericSeparator ? addNumericSeparator(obj, str) : str; + } + if (typeof obj === "bigint") { + var bigIntStr = String(obj) + "n"; + return numericSeparator ? addNumericSeparator(obj, bigIntStr) : bigIntStr; + } + var maxDepth = typeof opts.depth === "undefined" ? 5 : opts.depth; + if (typeof depth === "undefined") { + depth = 0; + } + if (depth >= maxDepth && maxDepth > 0 && typeof obj === "object") { + return isArray3(obj) ? "[Array]" : "[Object]"; + } + var indent = getIndent(opts, depth); + if (typeof seen === "undefined") { + seen = []; + } else if (indexOf(seen, obj) >= 0) { + return "[Circular]"; + } + function inspect(value, from, noIndent) { + if (from) { + seen = $arrSlice.call(seen); + seen.push(from); + } + if (noIndent) { + var newOpts = { + depth: opts.depth + }; + if (has2(opts, "quoteStyle")) { + newOpts.quoteStyle = opts.quoteStyle; + } + return inspect_(value, newOpts, depth + 1, seen); + } + return inspect_(value, opts, depth + 1, seen); + } + if (typeof obj === "function" && !isRegExp2(obj)) { + var name = nameOf(obj); + var keys2 = arrObjKeys(obj, inspect); + return "[Function" + (name ? ": " + name : " (anonymous)") + "]" + (keys2.length > 0 ? " { " + $join.call(keys2, ", ") + " }" : ""); + } + if (isSymbol2(obj)) { + var symString = hasShammedSymbols ? $replace.call(String(obj), /^(Symbol\(.*\))_[^)]*$/, "$1") : symToString.call(obj); + return typeof obj === "object" && !hasShammedSymbols ? markBoxed(symString) : symString; + } + if (isElement(obj)) { + var s = "<" + $toLowerCase.call(String(obj.nodeName)); + var attrs = obj.attributes || []; + for (var i = 0; i < attrs.length; i++) { + s += " " + attrs[i].name + "=" + wrapQuotes(quote(attrs[i].value), "double", opts); + } + s += ">"; + if (obj.childNodes && obj.childNodes.length) { + s += "..."; + } + s += ""; + return s; + } + if (isArray3(obj)) { + if (obj.length === 0) { + return "[]"; + } + var xs = arrObjKeys(obj, inspect); + if (indent && !singleLineValues(xs)) { + return "[" + indentedJoin(xs, indent) + "]"; + } + return "[ " + $join.call(xs, ", ") + " ]"; + } + if (isError(obj)) { + var parts = arrObjKeys(obj, inspect); + if (!("cause" in Error.prototype) && "cause" in obj && !isEnumerable.call(obj, "cause")) { + return "{ [" + String(obj) + "] " + $join.call($concat.call("[cause]: " + inspect(obj.cause), parts), ", ") + " }"; + } + if (parts.length === 0) { + return "[" + String(obj) + "]"; + } + return "{ [" + String(obj) + "] " + $join.call(parts, ", ") + " }"; + } + if (typeof obj === "object" && customInspect) { + if (inspectSymbol && typeof obj[inspectSymbol] === "function" && utilInspect) { + return utilInspect(obj, { depth: maxDepth - depth }); + } else if (customInspect !== "symbol" && typeof obj.inspect === "function") { + return obj.inspect(); + } + } + if (isMap2(obj)) { + var mapParts = []; + if (mapForEach) { + mapForEach.call(obj, function(value, key) { + mapParts.push(inspect(key, obj, true) + " => " + inspect(value, obj)); + }); + } + return collectionOf("Map", mapSize.call(obj), mapParts, indent); + } + if (isSet2(obj)) { + var setParts = []; + if (setForEach) { + setForEach.call(obj, function(value) { + setParts.push(inspect(value, obj)); + }); + } + return collectionOf("Set", setSize.call(obj), setParts, indent); + } + if (isWeakMap(obj)) { + return weakCollectionOf("WeakMap"); + } + if (isWeakSet(obj)) { + return weakCollectionOf("WeakSet"); + } + if (isWeakRef(obj)) { + return weakCollectionOf("WeakRef"); + } + if (isNumber2(obj)) { + return markBoxed(inspect(Number(obj))); + } + if (isBigInt(obj)) { + return markBoxed(inspect(bigIntValueOf.call(obj))); + } + if (isBoolean2(obj)) { + return markBoxed(booleanValueOf.call(obj)); + } + if (isString2(obj)) { + return markBoxed(inspect(String(obj))); + } + if (typeof window !== "undefined" && obj === window) { + return "{ [object Window] }"; + } + if (typeof globalThis !== "undefined" && obj === globalThis || typeof global !== "undefined" && obj === global) { + return "{ [object globalThis] }"; + } + if (!isDate2(obj) && !isRegExp2(obj)) { + var ys = arrObjKeys(obj, inspect); + var isPlainObject3 = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object; + var protoTag = obj instanceof Object ? "" : "null prototype"; + var stringTag5 = !isPlainObject3 && toStringTag2 && Object(obj) === obj && toStringTag2 in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? "Object" : ""; + var constructorTag = isPlainObject3 || typeof obj.constructor !== "function" ? "" : obj.constructor.name ? obj.constructor.name + " " : ""; + var tag = constructorTag + (stringTag5 || protoTag ? "[" + $join.call($concat.call([], stringTag5 || [], protoTag || []), ": ") + "] " : ""); + if (ys.length === 0) { + return tag + "{}"; + } + if (indent) { + return tag + "{" + indentedJoin(ys, indent) + "}"; + } + return tag + "{ " + $join.call(ys, ", ") + " }"; + } + return String(obj); + }; + function wrapQuotes(s, defaultStyle, opts) { + var style = opts.quoteStyle || defaultStyle; + var quoteChar = quotes[style]; + return quoteChar + s + quoteChar; + } + function quote(s) { + return $replace.call(String(s), /"/g, """); + } + function canTrustToString(obj) { + return !toStringTag2 || !(typeof obj === "object" && (toStringTag2 in obj || typeof obj[toStringTag2] !== "undefined")); + } + function isArray3(obj) { + return toStr(obj) === "[object Array]" && canTrustToString(obj); + } + function isDate2(obj) { + return toStr(obj) === "[object Date]" && canTrustToString(obj); + } + function isRegExp2(obj) { + return toStr(obj) === "[object RegExp]" && canTrustToString(obj); + } + function isError(obj) { + return toStr(obj) === "[object Error]" && canTrustToString(obj); + } + function isString2(obj) { + return toStr(obj) === "[object String]" && canTrustToString(obj); + } + function isNumber2(obj) { + return toStr(obj) === "[object Number]" && canTrustToString(obj); + } + function isBoolean2(obj) { + return toStr(obj) === "[object Boolean]" && canTrustToString(obj); + } + function isSymbol2(obj) { + if (hasShammedSymbols) { + return obj && typeof obj === "object" && obj instanceof Symbol; + } + if (typeof obj === "symbol") { + return true; + } + if (!obj || typeof obj !== "object" || !symToString) { + return false; + } + try { + symToString.call(obj); + return true; + } catch (e) { + } + return false; + } + function isBigInt(obj) { + if (!obj || typeof obj !== "object" || !bigIntValueOf) { + return false; + } + try { + bigIntValueOf.call(obj); + return true; + } catch (e) { + } + return false; + } + var hasOwn = Object.prototype.hasOwnProperty || function(key) { + return key in this; + }; + function has2(obj, key) { + return hasOwn.call(obj, key); + } + function toStr(obj) { + return objectToString2.call(obj); + } + function nameOf(f) { + if (f.name) { + return f.name; + } + var m = $match.call(functionToString.call(f), /^function\s*([\w$]+)/); + if (m) { + return m[1]; + } + return null; + } + function indexOf(xs, x) { + if (xs.indexOf) { + return xs.indexOf(x); + } + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) { + return i; + } + } + return -1; + } + function isMap2(x) { + if (!mapSize || !x || typeof x !== "object") { + return false; + } + try { + mapSize.call(x); + try { + setSize.call(x); + } catch (s) { + return true; + } + return x instanceof Map; + } catch (e) { + } + return false; + } + function isWeakMap(x) { + if (!weakMapHas || !x || typeof x !== "object") { + return false; + } + try { + weakMapHas.call(x, weakMapHas); + try { + weakSetHas.call(x, weakSetHas); + } catch (s) { + return true; + } + return x instanceof WeakMap; + } catch (e) { + } + return false; + } + function isWeakRef(x) { + if (!weakRefDeref || !x || typeof x !== "object") { + return false; + } + try { + weakRefDeref.call(x); + return true; + } catch (e) { + } + return false; + } + function isSet2(x) { + if (!setSize || !x || typeof x !== "object") { + return false; + } + try { + setSize.call(x); + try { + mapSize.call(x); + } catch (m) { + return true; + } + return x instanceof Set; + } catch (e) { + } + return false; + } + function isWeakSet(x) { + if (!weakSetHas || !x || typeof x !== "object") { + return false; + } + try { + weakSetHas.call(x, weakSetHas); + try { + weakMapHas.call(x, weakMapHas); + } catch (s) { + return true; + } + return x instanceof WeakSet; + } catch (e) { + } + return false; + } + function isElement(x) { + if (!x || typeof x !== "object") { + return false; + } + if (typeof HTMLElement !== "undefined" && x instanceof HTMLElement) { + return true; + } + return typeof x.nodeName === "string" && typeof x.getAttribute === "function"; + } + function inspectString(str, opts) { + if (str.length > opts.maxStringLength) { + var remaining = str.length - opts.maxStringLength; + var trailer = "... " + remaining + " more character" + (remaining > 1 ? "s" : ""); + return inspectString($slice.call(str, 0, opts.maxStringLength), opts) + trailer; + } + var quoteRE = quoteREs[opts.quoteStyle || "single"]; + quoteRE.lastIndex = 0; + var s = $replace.call($replace.call(str, quoteRE, "\\$1"), /[\x00-\x1f]/g, lowbyte); + return wrapQuotes(s, "single", opts); + } + function lowbyte(c) { + var n = c.charCodeAt(0); + var x = { + 8: "b", + 9: "t", + 10: "n", + 12: "f", + 13: "r" + }[n]; + if (x) { + return "\\" + x; + } + return "\\x" + (n < 16 ? "0" : "") + $toUpperCase.call(n.toString(16)); + } + function markBoxed(str) { + return "Object(" + str + ")"; + } + function weakCollectionOf(type) { + return type + " { ? }"; + } + function collectionOf(type, size, entries, indent) { + var joinedEntries = indent ? indentedJoin(entries, indent) : $join.call(entries, ", "); + return type + " (" + size + ") {" + joinedEntries + "}"; + } + function singleLineValues(xs) { + for (var i = 0; i < xs.length; i++) { + if (indexOf(xs[i], "\n") >= 0) { + return false; + } + } + return true; + } + function getIndent(opts, depth) { + var baseIndent; + if (opts.indent === " ") { + baseIndent = " "; + } else if (typeof opts.indent === "number" && opts.indent > 0) { + baseIndent = $join.call(Array(opts.indent + 1), " "); + } else { + return null; + } + return { + base: baseIndent, + prev: $join.call(Array(depth + 1), baseIndent) + }; + } + function indentedJoin(xs, indent) { + if (xs.length === 0) { + return ""; + } + var lineJoiner = "\n" + indent.prev + indent.base; + return lineJoiner + $join.call(xs, "," + lineJoiner) + "\n" + indent.prev; + } + function arrObjKeys(obj, inspect) { + var isArr = isArray3(obj); + var xs = []; + if (isArr) { + xs.length = obj.length; + for (var i = 0; i < obj.length; i++) { + xs[i] = has2(obj, i) ? inspect(obj[i], obj) : ""; + } + } + var syms = typeof gOPS === "function" ? gOPS(obj) : []; + var symMap; + if (hasShammedSymbols) { + symMap = {}; + for (var k = 0; k < syms.length; k++) { + symMap["$" + syms[k]] = syms[k]; + } + } + for (var key in obj) { + if (!has2(obj, key)) { + continue; + } + if (isArr && String(Number(key)) === key && key < obj.length) { + continue; + } + if (hasShammedSymbols && symMap["$" + key] instanceof Symbol) { + continue; + } else if ($test.call(/[^\w$]/, key)) { + xs.push(inspect(key, obj) + ": " + inspect(obj[key], obj)); + } else { + xs.push(key + ": " + inspect(obj[key], obj)); + } + } + if (typeof gOPS === "function") { + for (var j = 0; j < syms.length; j++) { + if (isEnumerable.call(obj, syms[j])) { + xs.push("[" + inspect(syms[j]) + "]: " + inspect(obj[syms[j]], obj)); + } + } + } + return xs; + } + } +}); + +// node_modules/side-channel-list/index.js +var require_side_channel_list = __commonJS({ + "node_modules/side-channel-list/index.js"(exports2, module2) { + "use strict"; + var inspect = require_object_inspect(); + var $TypeError = require_type(); + var listGetNode = function(list, key, isDelete) { + var prev = list; + var curr; + for (; (curr = prev.next) != null; prev = curr) { + if (curr.key === key) { + prev.next = curr.next; + if (!isDelete) { + curr.next = /** @type {NonNullable} */ + list.next; + list.next = curr; + } + return curr; + } + } + }; + var listGet = function(objects, key) { + if (!objects) { + return void 0; + } + var node = listGetNode(objects, key); + return node && node.value; + }; + var listSet = function(objects, key, value) { + var node = listGetNode(objects, key); + if (node) { + node.value = value; + } else { + objects.next = /** @type {import('./list.d.ts').ListNode} */ + { + // eslint-disable-line no-param-reassign, no-extra-parens + key, + next: objects.next, + value + }; + } + }; + var listHas = function(objects, key) { + if (!objects) { + return false; + } + return !!listGetNode(objects, key); + }; + var listDelete = function(objects, key) { + if (objects) { + return listGetNode(objects, key, true); + } + }; + module2.exports = function getSideChannelList() { + var $o; + var channel = { + assert: function(key) { + if (!channel.has(key)) { + throw new $TypeError("Side channel does not contain " + inspect(key)); + } + }, + "delete": function(key) { + var root2 = $o && $o.next; + var deletedNode = listDelete($o, key); + if (deletedNode && root2 && root2 === deletedNode) { + $o = void 0; + } + return !!deletedNode; + }, + get: function(key) { + return listGet($o, key); + }, + has: function(key) { + return listHas($o, key); + }, + set: function(key, value) { + if (!$o) { + $o = { + next: void 0 + }; + } + listSet( + /** @type {NonNullable} */ + $o, + key, + value + ); + } + }; + return channel; + }; + } +}); + +// node_modules/es-object-atoms/index.js +var require_es_object_atoms = __commonJS({ + "node_modules/es-object-atoms/index.js"(exports2, module2) { + "use strict"; + module2.exports = Object; + } +}); + +// node_modules/es-errors/index.js +var require_es_errors = __commonJS({ + "node_modules/es-errors/index.js"(exports2, module2) { + "use strict"; + module2.exports = Error; + } +}); + +// node_modules/es-errors/eval.js +var require_eval = __commonJS({ + "node_modules/es-errors/eval.js"(exports2, module2) { + "use strict"; + module2.exports = EvalError; + } +}); + +// node_modules/es-errors/range.js +var require_range = __commonJS({ + "node_modules/es-errors/range.js"(exports2, module2) { + "use strict"; + module2.exports = RangeError; + } +}); + +// node_modules/es-errors/ref.js +var require_ref = __commonJS({ + "node_modules/es-errors/ref.js"(exports2, module2) { + "use strict"; + module2.exports = ReferenceError; + } +}); + +// node_modules/es-errors/syntax.js +var require_syntax = __commonJS({ + "node_modules/es-errors/syntax.js"(exports2, module2) { + "use strict"; + module2.exports = SyntaxError; + } +}); + +// node_modules/es-errors/uri.js +var require_uri = __commonJS({ + "node_modules/es-errors/uri.js"(exports2, module2) { + "use strict"; + module2.exports = URIError; + } +}); + +// node_modules/math-intrinsics/abs.js +var require_abs = __commonJS({ + "node_modules/math-intrinsics/abs.js"(exports2, module2) { + "use strict"; + module2.exports = Math.abs; + } +}); + +// node_modules/math-intrinsics/floor.js +var require_floor = __commonJS({ + "node_modules/math-intrinsics/floor.js"(exports2, module2) { + "use strict"; + module2.exports = Math.floor; + } +}); + +// node_modules/math-intrinsics/max.js +var require_max = __commonJS({ + "node_modules/math-intrinsics/max.js"(exports2, module2) { + "use strict"; + module2.exports = Math.max; + } +}); + +// node_modules/math-intrinsics/min.js +var require_min = __commonJS({ + "node_modules/math-intrinsics/min.js"(exports2, module2) { + "use strict"; + module2.exports = Math.min; + } +}); + +// node_modules/math-intrinsics/pow.js +var require_pow = __commonJS({ + "node_modules/math-intrinsics/pow.js"(exports2, module2) { + "use strict"; + module2.exports = Math.pow; + } +}); + +// node_modules/math-intrinsics/round.js +var require_round = __commonJS({ + "node_modules/math-intrinsics/round.js"(exports2, module2) { + "use strict"; + module2.exports = Math.round; + } +}); + +// node_modules/math-intrinsics/isNaN.js +var require_isNaN = __commonJS({ + "node_modules/math-intrinsics/isNaN.js"(exports2, module2) { + "use strict"; + module2.exports = Number.isNaN || function isNaN2(a) { + return a !== a; + }; + } +}); + +// node_modules/math-intrinsics/sign.js +var require_sign = __commonJS({ + "node_modules/math-intrinsics/sign.js"(exports2, module2) { + "use strict"; + var $isNaN = require_isNaN(); + module2.exports = function sign(number) { + if ($isNaN(number) || number === 0) { + return number; + } + return number < 0 ? -1 : 1; + }; + } +}); + +// node_modules/gopd/gOPD.js +var require_gOPD = __commonJS({ + "node_modules/gopd/gOPD.js"(exports2, module2) { + "use strict"; + module2.exports = Object.getOwnPropertyDescriptor; + } +}); + +// node_modules/gopd/index.js +var require_gopd = __commonJS({ + "node_modules/gopd/index.js"(exports2, module2) { + "use strict"; + var $gOPD = require_gOPD(); + if ($gOPD) { + try { + $gOPD([], "length"); + } catch (e) { + $gOPD = null; + } + } + module2.exports = $gOPD; + } +}); + +// node_modules/es-define-property/index.js +var require_es_define_property = __commonJS({ + "node_modules/es-define-property/index.js"(exports2, module2) { + "use strict"; + var $defineProperty = Object.defineProperty || false; + if ($defineProperty) { + try { + $defineProperty({}, "a", { value: 1 }); + } catch (e) { + $defineProperty = false; + } + } + module2.exports = $defineProperty; + } +}); + +// node_modules/has-symbols/shams.js +var require_shams = __commonJS({ + "node_modules/has-symbols/shams.js"(exports2, module2) { + "use strict"; + module2.exports = function hasSymbols() { + if (typeof Symbol !== "function" || typeof Object.getOwnPropertySymbols !== "function") { + return false; + } + if (typeof Symbol.iterator === "symbol") { + return true; + } + var obj = {}; + var sym = Symbol("test"); + var symObj = Object(sym); + if (typeof sym === "string") { + return false; + } + if (Object.prototype.toString.call(sym) !== "[object Symbol]") { + return false; + } + if (Object.prototype.toString.call(symObj) !== "[object Symbol]") { + return false; + } + var symVal = 42; + obj[sym] = symVal; + for (var _ in obj) { + return false; + } + if (typeof Object.keys === "function" && Object.keys(obj).length !== 0) { + return false; + } + if (typeof Object.getOwnPropertyNames === "function" && Object.getOwnPropertyNames(obj).length !== 0) { + return false; + } + var syms = Object.getOwnPropertySymbols(obj); + if (syms.length !== 1 || syms[0] !== sym) { + return false; + } + if (!Object.prototype.propertyIsEnumerable.call(obj, sym)) { + return false; + } + if (typeof Object.getOwnPropertyDescriptor === "function") { + var descriptor = ( + /** @type {PropertyDescriptor} */ + Object.getOwnPropertyDescriptor(obj, sym) + ); + if (descriptor.value !== symVal || descriptor.enumerable !== true) { + return false; + } + } + return true; + }; + } +}); + +// node_modules/has-symbols/index.js +var require_has_symbols = __commonJS({ + "node_modules/has-symbols/index.js"(exports2, module2) { + "use strict"; + var origSymbol = typeof Symbol !== "undefined" && Symbol; + var hasSymbolSham = require_shams(); + module2.exports = function hasNativeSymbols() { + if (typeof origSymbol !== "function") { + return false; + } + if (typeof Symbol !== "function") { + return false; + } + if (typeof origSymbol("foo") !== "symbol") { + return false; + } + if (typeof Symbol("bar") !== "symbol") { + return false; + } + return hasSymbolSham(); + }; + } +}); + +// node_modules/get-proto/Reflect.getPrototypeOf.js +var require_Reflect_getPrototypeOf = __commonJS({ + "node_modules/get-proto/Reflect.getPrototypeOf.js"(exports2, module2) { + "use strict"; + module2.exports = typeof Reflect !== "undefined" && Reflect.getPrototypeOf || null; + } +}); + +// node_modules/get-proto/Object.getPrototypeOf.js +var require_Object_getPrototypeOf = __commonJS({ + "node_modules/get-proto/Object.getPrototypeOf.js"(exports2, module2) { + "use strict"; + var $Object = require_es_object_atoms(); + module2.exports = $Object.getPrototypeOf || null; + } +}); + +// node_modules/function-bind/implementation.js +var require_implementation = __commonJS({ + "node_modules/function-bind/implementation.js"(exports2, module2) { + "use strict"; + var ERROR_MESSAGE = "Function.prototype.bind called on incompatible "; + var toStr = Object.prototype.toString; + var max = Math.max; + var funcType = "[object Function]"; + var concatty = function concatty2(a, b) { + var arr = []; + for (var i = 0; i < a.length; i += 1) { + arr[i] = a[i]; + } + for (var j = 0; j < b.length; j += 1) { + arr[j + a.length] = b[j]; + } + return arr; + }; + var slicy = function slicy2(arrLike, offset) { + var arr = []; + for (var i = offset || 0, j = 0; i < arrLike.length; i += 1, j += 1) { + arr[j] = arrLike[i]; + } + return arr; + }; + var joiny = function(arr, joiner) { + var str = ""; + for (var i = 0; i < arr.length; i += 1) { + str += arr[i]; + if (i + 1 < arr.length) { + str += joiner; + } + } + return str; + }; + module2.exports = function bind2(that) { + var target = this; + if (typeof target !== "function" || toStr.apply(target) !== funcType) { + throw new TypeError(ERROR_MESSAGE + target); + } + var args = slicy(arguments, 1); + var bound; + var binder = function() { + if (this instanceof bound) { + var result = target.apply( + this, + concatty(args, arguments) + ); + if (Object(result) === result) { + return result; + } + return this; + } + return target.apply( + that, + concatty(args, arguments) + ); + }; + var boundLength = max(0, target.length - args.length); + var boundArgs = []; + for (var i = 0; i < boundLength; i++) { + boundArgs[i] = "$" + i; + } + bound = Function("binder", "return function (" + joiny(boundArgs, ",") + "){ return binder.apply(this,arguments); }")(binder); + if (target.prototype) { + var Empty = function Empty2() { + }; + Empty.prototype = target.prototype; + bound.prototype = new Empty(); + Empty.prototype = null; + } + return bound; + }; + } +}); + +// node_modules/function-bind/index.js +var require_function_bind = __commonJS({ + "node_modules/function-bind/index.js"(exports2, module2) { + "use strict"; + var implementation = require_implementation(); + module2.exports = Function.prototype.bind || implementation; + } +}); + +// node_modules/call-bind-apply-helpers/functionCall.js +var require_functionCall = __commonJS({ + "node_modules/call-bind-apply-helpers/functionCall.js"(exports2, module2) { + "use strict"; + module2.exports = Function.prototype.call; + } +}); + +// node_modules/call-bind-apply-helpers/functionApply.js +var require_functionApply = __commonJS({ + "node_modules/call-bind-apply-helpers/functionApply.js"(exports2, module2) { + "use strict"; + module2.exports = Function.prototype.apply; + } +}); + +// node_modules/call-bind-apply-helpers/reflectApply.js +var require_reflectApply = __commonJS({ + "node_modules/call-bind-apply-helpers/reflectApply.js"(exports2, module2) { + "use strict"; + module2.exports = typeof Reflect !== "undefined" && Reflect && Reflect.apply; + } +}); + +// node_modules/call-bind-apply-helpers/actualApply.js +var require_actualApply = __commonJS({ + "node_modules/call-bind-apply-helpers/actualApply.js"(exports2, module2) { + "use strict"; + var bind2 = require_function_bind(); + var $apply = require_functionApply(); + var $call = require_functionCall(); + var $reflectApply = require_reflectApply(); + module2.exports = $reflectApply || bind2.call($call, $apply); + } +}); + +// node_modules/call-bind-apply-helpers/index.js +var require_call_bind_apply_helpers = __commonJS({ + "node_modules/call-bind-apply-helpers/index.js"(exports2, module2) { + "use strict"; + var bind2 = require_function_bind(); + var $TypeError = require_type(); + var $call = require_functionCall(); + var $actualApply = require_actualApply(); + module2.exports = function callBindBasic(args) { + if (args.length < 1 || typeof args[0] !== "function") { + throw new $TypeError("a function is required"); + } + return $actualApply(bind2, $call, args); + }; + } +}); + +// node_modules/dunder-proto/get.js +var require_get = __commonJS({ + "node_modules/dunder-proto/get.js"(exports2, module2) { + "use strict"; + var callBind = require_call_bind_apply_helpers(); + var gOPD = require_gopd(); + var hasProtoAccessor; + try { + hasProtoAccessor = /** @type {{ __proto__?: typeof Array.prototype }} */ + [].__proto__ === Array.prototype; + } catch (e) { + if (!e || typeof e !== "object" || !("code" in e) || e.code !== "ERR_PROTO_ACCESS") { + throw e; + } + } + var desc = !!hasProtoAccessor && gOPD && gOPD( + Object.prototype, + /** @type {keyof typeof Object.prototype} */ + "__proto__" + ); + var $Object = Object; + var $getPrototypeOf = $Object.getPrototypeOf; + module2.exports = desc && typeof desc.get === "function" ? callBind([desc.get]) : typeof $getPrototypeOf === "function" ? ( + /** @type {import('./get')} */ + function getDunder(value) { + return $getPrototypeOf(value == null ? value : $Object(value)); + } + ) : false; + } +}); + +// node_modules/get-proto/index.js +var require_get_proto = __commonJS({ + "node_modules/get-proto/index.js"(exports2, module2) { + "use strict"; + var reflectGetProto = require_Reflect_getPrototypeOf(); + var originalGetProto = require_Object_getPrototypeOf(); + var getDunderProto = require_get(); + module2.exports = reflectGetProto ? function getProto(O) { + return reflectGetProto(O); + } : originalGetProto ? function getProto(O) { + if (!O || typeof O !== "object" && typeof O !== "function") { + throw new TypeError("getProto: not an object"); + } + return originalGetProto(O); + } : getDunderProto ? function getProto(O) { + return getDunderProto(O); + } : null; + } +}); + +// node_modules/hasown/index.js +var require_hasown = __commonJS({ + "node_modules/hasown/index.js"(exports2, module2) { + "use strict"; + var call = Function.prototype.call; + var $hasOwn = Object.prototype.hasOwnProperty; + var bind2 = require_function_bind(); + module2.exports = bind2.call(call, $hasOwn); + } +}); + +// node_modules/get-intrinsic/index.js +var require_get_intrinsic = __commonJS({ + "node_modules/get-intrinsic/index.js"(exports2, module2) { + "use strict"; + var undefined2; + var $Object = require_es_object_atoms(); + var $Error = require_es_errors(); + var $EvalError = require_eval(); + var $RangeError = require_range(); + var $ReferenceError = require_ref(); + var $SyntaxError = require_syntax(); + var $TypeError = require_type(); + var $URIError = require_uri(); + var abs = require_abs(); + var floor = require_floor(); + var max = require_max(); + var min = require_min(); + var pow = require_pow(); + var round = require_round(); + var sign = require_sign(); + var $Function = Function; + var getEvalledConstructor = function(expressionSyntax) { + try { + return $Function('"use strict"; return (' + expressionSyntax + ").constructor;")(); + } catch (e) { + } + }; + var $gOPD = require_gopd(); + var $defineProperty = require_es_define_property(); + var throwTypeError = function() { + throw new $TypeError(); + }; + var ThrowTypeError = $gOPD ? (function() { + try { + arguments.callee; + return throwTypeError; + } catch (calleeThrows) { + try { + return $gOPD(arguments, "callee").get; + } catch (gOPDthrows) { + return throwTypeError; + } + } + })() : throwTypeError; + var hasSymbols = require_has_symbols()(); + var getProto = require_get_proto(); + var $ObjectGPO = require_Object_getPrototypeOf(); + var $ReflectGPO = require_Reflect_getPrototypeOf(); + var $apply = require_functionApply(); + var $call = require_functionCall(); + var needsEval = {}; + var TypedArray = typeof Uint8Array === "undefined" || !getProto ? undefined2 : getProto(Uint8Array); + var INTRINSICS = { + __proto__: null, + "%AggregateError%": typeof AggregateError === "undefined" ? undefined2 : AggregateError, + "%Array%": Array, + "%ArrayBuffer%": typeof ArrayBuffer === "undefined" ? undefined2 : ArrayBuffer, + "%ArrayIteratorPrototype%": hasSymbols && getProto ? getProto([][Symbol.iterator]()) : undefined2, + "%AsyncFromSyncIteratorPrototype%": undefined2, + "%AsyncFunction%": needsEval, + "%AsyncGenerator%": needsEval, + "%AsyncGeneratorFunction%": needsEval, + "%AsyncIteratorPrototype%": needsEval, + "%Atomics%": typeof Atomics === "undefined" ? undefined2 : Atomics, + "%BigInt%": typeof BigInt === "undefined" ? undefined2 : BigInt, + "%BigInt64Array%": typeof BigInt64Array === "undefined" ? undefined2 : BigInt64Array, + "%BigUint64Array%": typeof BigUint64Array === "undefined" ? undefined2 : BigUint64Array, + "%Boolean%": Boolean, + "%DataView%": typeof DataView === "undefined" ? undefined2 : DataView, + "%Date%": Date, + "%decodeURI%": decodeURI, + "%decodeURIComponent%": decodeURIComponent, + "%encodeURI%": encodeURI, + "%encodeURIComponent%": encodeURIComponent, + "%Error%": $Error, + "%eval%": eval, + // eslint-disable-line no-eval + "%EvalError%": $EvalError, + "%Float16Array%": typeof Float16Array === "undefined" ? undefined2 : Float16Array, + "%Float32Array%": typeof Float32Array === "undefined" ? undefined2 : Float32Array, + "%Float64Array%": typeof Float64Array === "undefined" ? undefined2 : Float64Array, + "%FinalizationRegistry%": typeof FinalizationRegistry === "undefined" ? undefined2 : FinalizationRegistry, + "%Function%": $Function, + "%GeneratorFunction%": needsEval, + "%Int8Array%": typeof Int8Array === "undefined" ? undefined2 : Int8Array, + "%Int16Array%": typeof Int16Array === "undefined" ? undefined2 : Int16Array, + "%Int32Array%": typeof Int32Array === "undefined" ? undefined2 : Int32Array, + "%isFinite%": isFinite, + "%isNaN%": isNaN, + "%IteratorPrototype%": hasSymbols && getProto ? getProto(getProto([][Symbol.iterator]())) : undefined2, + "%JSON%": typeof JSON === "object" ? JSON : undefined2, + "%Map%": typeof Map === "undefined" ? undefined2 : Map, + "%MapIteratorPrototype%": typeof Map === "undefined" || !hasSymbols || !getProto ? undefined2 : getProto((/* @__PURE__ */ new Map())[Symbol.iterator]()), + "%Math%": Math, + "%Number%": Number, + "%Object%": $Object, + "%Object.getOwnPropertyDescriptor%": $gOPD, + "%parseFloat%": parseFloat, + "%parseInt%": parseInt, + "%Promise%": typeof Promise === "undefined" ? undefined2 : Promise, + "%Proxy%": typeof Proxy === "undefined" ? undefined2 : Proxy, + "%RangeError%": $RangeError, + "%ReferenceError%": $ReferenceError, + "%Reflect%": typeof Reflect === "undefined" ? undefined2 : Reflect, + "%RegExp%": RegExp, + "%Set%": typeof Set === "undefined" ? undefined2 : Set, + "%SetIteratorPrototype%": typeof Set === "undefined" || !hasSymbols || !getProto ? undefined2 : getProto((/* @__PURE__ */ new Set())[Symbol.iterator]()), + "%SharedArrayBuffer%": typeof SharedArrayBuffer === "undefined" ? undefined2 : SharedArrayBuffer, + "%String%": String, + "%StringIteratorPrototype%": hasSymbols && getProto ? getProto(""[Symbol.iterator]()) : undefined2, + "%Symbol%": hasSymbols ? Symbol : undefined2, + "%SyntaxError%": $SyntaxError, + "%ThrowTypeError%": ThrowTypeError, + "%TypedArray%": TypedArray, + "%TypeError%": $TypeError, + "%Uint8Array%": typeof Uint8Array === "undefined" ? undefined2 : Uint8Array, + "%Uint8ClampedArray%": typeof Uint8ClampedArray === "undefined" ? undefined2 : Uint8ClampedArray, + "%Uint16Array%": typeof Uint16Array === "undefined" ? undefined2 : Uint16Array, + "%Uint32Array%": typeof Uint32Array === "undefined" ? undefined2 : Uint32Array, + "%URIError%": $URIError, + "%WeakMap%": typeof WeakMap === "undefined" ? undefined2 : WeakMap, + "%WeakRef%": typeof WeakRef === "undefined" ? undefined2 : WeakRef, + "%WeakSet%": typeof WeakSet === "undefined" ? undefined2 : WeakSet, + "%Function.prototype.call%": $call, + "%Function.prototype.apply%": $apply, + "%Object.defineProperty%": $defineProperty, + "%Object.getPrototypeOf%": $ObjectGPO, + "%Math.abs%": abs, + "%Math.floor%": floor, + "%Math.max%": max, + "%Math.min%": min, + "%Math.pow%": pow, + "%Math.round%": round, + "%Math.sign%": sign, + "%Reflect.getPrototypeOf%": $ReflectGPO + }; + if (getProto) { + try { + null.error; + } catch (e) { + errorProto = getProto(getProto(e)); + INTRINSICS["%Error.prototype%"] = errorProto; + } + } + var errorProto; + var doEval = function doEval2(name) { + var value; + if (name === "%AsyncFunction%") { + value = getEvalledConstructor("async function () {}"); + } else if (name === "%GeneratorFunction%") { + value = getEvalledConstructor("function* () {}"); + } else if (name === "%AsyncGeneratorFunction%") { + value = getEvalledConstructor("async function* () {}"); + } else if (name === "%AsyncGenerator%") { + var fn = doEval2("%AsyncGeneratorFunction%"); + if (fn) { + value = fn.prototype; + } + } else if (name === "%AsyncIteratorPrototype%") { + var gen = doEval2("%AsyncGenerator%"); + if (gen && getProto) { + value = getProto(gen.prototype); + } + } + INTRINSICS[name] = value; + return value; + }; + var LEGACY_ALIASES = { + __proto__: null, + "%ArrayBufferPrototype%": ["ArrayBuffer", "prototype"], + "%ArrayPrototype%": ["Array", "prototype"], + "%ArrayProto_entries%": ["Array", "prototype", "entries"], + "%ArrayProto_forEach%": ["Array", "prototype", "forEach"], + "%ArrayProto_keys%": ["Array", "prototype", "keys"], + "%ArrayProto_values%": ["Array", "prototype", "values"], + "%AsyncFunctionPrototype%": ["AsyncFunction", "prototype"], + "%AsyncGenerator%": ["AsyncGeneratorFunction", "prototype"], + "%AsyncGeneratorPrototype%": ["AsyncGeneratorFunction", "prototype", "prototype"], + "%BooleanPrototype%": ["Boolean", "prototype"], + "%DataViewPrototype%": ["DataView", "prototype"], + "%DatePrototype%": ["Date", "prototype"], + "%ErrorPrototype%": ["Error", "prototype"], + "%EvalErrorPrototype%": ["EvalError", "prototype"], + "%Float32ArrayPrototype%": ["Float32Array", "prototype"], + "%Float64ArrayPrototype%": ["Float64Array", "prototype"], + "%FunctionPrototype%": ["Function", "prototype"], + "%Generator%": ["GeneratorFunction", "prototype"], + "%GeneratorPrototype%": ["GeneratorFunction", "prototype", "prototype"], + "%Int8ArrayPrototype%": ["Int8Array", "prototype"], + "%Int16ArrayPrototype%": ["Int16Array", "prototype"], + "%Int32ArrayPrototype%": ["Int32Array", "prototype"], + "%JSONParse%": ["JSON", "parse"], + "%JSONStringify%": ["JSON", "stringify"], + "%MapPrototype%": ["Map", "prototype"], + "%NumberPrototype%": ["Number", "prototype"], + "%ObjectPrototype%": ["Object", "prototype"], + "%ObjProto_toString%": ["Object", "prototype", "toString"], + "%ObjProto_valueOf%": ["Object", "prototype", "valueOf"], + "%PromisePrototype%": ["Promise", "prototype"], + "%PromiseProto_then%": ["Promise", "prototype", "then"], + "%Promise_all%": ["Promise", "all"], + "%Promise_reject%": ["Promise", "reject"], + "%Promise_resolve%": ["Promise", "resolve"], + "%RangeErrorPrototype%": ["RangeError", "prototype"], + "%ReferenceErrorPrototype%": ["ReferenceError", "prototype"], + "%RegExpPrototype%": ["RegExp", "prototype"], + "%SetPrototype%": ["Set", "prototype"], + "%SharedArrayBufferPrototype%": ["SharedArrayBuffer", "prototype"], + "%StringPrototype%": ["String", "prototype"], + "%SymbolPrototype%": ["Symbol", "prototype"], + "%SyntaxErrorPrototype%": ["SyntaxError", "prototype"], + "%TypedArrayPrototype%": ["TypedArray", "prototype"], + "%TypeErrorPrototype%": ["TypeError", "prototype"], + "%Uint8ArrayPrototype%": ["Uint8Array", "prototype"], + "%Uint8ClampedArrayPrototype%": ["Uint8ClampedArray", "prototype"], + "%Uint16ArrayPrototype%": ["Uint16Array", "prototype"], + "%Uint32ArrayPrototype%": ["Uint32Array", "prototype"], + "%URIErrorPrototype%": ["URIError", "prototype"], + "%WeakMapPrototype%": ["WeakMap", "prototype"], + "%WeakSetPrototype%": ["WeakSet", "prototype"] + }; + var bind2 = require_function_bind(); + var hasOwn = require_hasown(); + var $concat = bind2.call($call, Array.prototype.concat); + var $spliceApply = bind2.call($apply, Array.prototype.splice); + var $replace = bind2.call($call, String.prototype.replace); + var $strSlice = bind2.call($call, String.prototype.slice); + var $exec = bind2.call($call, RegExp.prototype.exec); + var rePropName2 = /[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g; + var reEscapeChar2 = /\\(\\)?/g; + var stringToPath2 = function stringToPath3(string) { + var first = $strSlice(string, 0, 1); + var last = $strSlice(string, -1); + if (first === "%" && last !== "%") { + throw new $SyntaxError("invalid intrinsic syntax, expected closing `%`"); + } else if (last === "%" && first !== "%") { + throw new $SyntaxError("invalid intrinsic syntax, expected opening `%`"); + } + var result = []; + $replace(string, rePropName2, function(match, number, quote, subString) { + result[result.length] = quote ? $replace(subString, reEscapeChar2, "$1") : number || match; + }); + return result; + }; + var getBaseIntrinsic = function getBaseIntrinsic2(name, allowMissing) { + var intrinsicName = name; + var alias; + if (hasOwn(LEGACY_ALIASES, intrinsicName)) { + alias = LEGACY_ALIASES[intrinsicName]; + intrinsicName = "%" + alias[0] + "%"; + } + if (hasOwn(INTRINSICS, intrinsicName)) { + var value = INTRINSICS[intrinsicName]; + if (value === needsEval) { + value = doEval(intrinsicName); + } + if (typeof value === "undefined" && !allowMissing) { + throw new $TypeError("intrinsic " + name + " exists, but is not available. Please file an issue!"); + } + return { + alias, + name: intrinsicName, + value + }; + } + throw new $SyntaxError("intrinsic " + name + " does not exist!"); + }; + module2.exports = function GetIntrinsic(name, allowMissing) { + if (typeof name !== "string" || name.length === 0) { + throw new $TypeError("intrinsic name must be a non-empty string"); + } + if (arguments.length > 1 && typeof allowMissing !== "boolean") { + throw new $TypeError('"allowMissing" argument must be a boolean'); + } + if ($exec(/^%?[^%]*%?$/, name) === null) { + throw new $SyntaxError("`%` may not be present anywhere but at the beginning and end of the intrinsic name"); + } + var parts = stringToPath2(name); + var intrinsicBaseName = parts.length > 0 ? parts[0] : ""; + var intrinsic = getBaseIntrinsic("%" + intrinsicBaseName + "%", allowMissing); + var intrinsicRealName = intrinsic.name; + var value = intrinsic.value; + var skipFurtherCaching = false; + var alias = intrinsic.alias; + if (alias) { + intrinsicBaseName = alias[0]; + $spliceApply(parts, $concat([0, 1], alias)); + } + for (var i = 1, isOwn = true; i < parts.length; i += 1) { + var part = parts[i]; + var first = $strSlice(part, 0, 1); + var last = $strSlice(part, -1); + if ((first === '"' || first === "'" || first === "`" || (last === '"' || last === "'" || last === "`")) && first !== last) { + throw new $SyntaxError("property names with quotes must have matching quotes"); + } + if (part === "constructor" || !isOwn) { + skipFurtherCaching = true; + } + intrinsicBaseName += "." + part; + intrinsicRealName = "%" + intrinsicBaseName + "%"; + if (hasOwn(INTRINSICS, intrinsicRealName)) { + value = INTRINSICS[intrinsicRealName]; + } else if (value != null) { + if (!(part in value)) { + if (!allowMissing) { + throw new $TypeError("base intrinsic for " + name + " exists, but the property is not available."); + } + return void undefined2; + } + if ($gOPD && i + 1 >= parts.length) { + var desc = $gOPD(value, part); + isOwn = !!desc; + if (isOwn && "get" in desc && !("originalValue" in desc.get)) { + value = desc.get; + } else { + value = value[part]; + } + } else { + isOwn = hasOwn(value, part); + value = value[part]; + } + if (isOwn && !skipFurtherCaching) { + INTRINSICS[intrinsicRealName] = value; + } + } + } + return value; + }; + } +}); + +// node_modules/call-bound/index.js +var require_call_bound = __commonJS({ + "node_modules/call-bound/index.js"(exports2, module2) { + "use strict"; + var GetIntrinsic = require_get_intrinsic(); + var callBindBasic = require_call_bind_apply_helpers(); + var $indexOf = callBindBasic([GetIntrinsic("%String.prototype.indexOf%")]); + module2.exports = function callBoundIntrinsic(name, allowMissing) { + var intrinsic = ( + /** @type {(this: unknown, ...args: unknown[]) => unknown} */ + GetIntrinsic(name, !!allowMissing) + ); + if (typeof intrinsic === "function" && $indexOf(name, ".prototype.") > -1) { + return callBindBasic( + /** @type {const} */ + [intrinsic] + ); + } + return intrinsic; + }; + } +}); + +// node_modules/side-channel-map/index.js +var require_side_channel_map = __commonJS({ + "node_modules/side-channel-map/index.js"(exports2, module2) { + "use strict"; + var GetIntrinsic = require_get_intrinsic(); + var callBound = require_call_bound(); + var inspect = require_object_inspect(); + var $TypeError = require_type(); + var $Map = GetIntrinsic("%Map%", true); + var $mapGet = callBound("Map.prototype.get", true); + var $mapSet = callBound("Map.prototype.set", true); + var $mapHas = callBound("Map.prototype.has", true); + var $mapDelete = callBound("Map.prototype.delete", true); + var $mapSize = callBound("Map.prototype.size", true); + module2.exports = !!$Map && /** @type {Exclude} */ + function getSideChannelMap() { + var $m; + var channel = { + assert: function(key) { + if (!channel.has(key)) { + throw new $TypeError("Side channel does not contain " + inspect(key)); + } + }, + "delete": function(key) { + if ($m) { + var result = $mapDelete($m, key); + if ($mapSize($m) === 0) { + $m = void 0; + } + return result; + } + return false; + }, + get: function(key) { + if ($m) { + return $mapGet($m, key); + } + }, + has: function(key) { + if ($m) { + return $mapHas($m, key); + } + return false; + }, + set: function(key, value) { + if (!$m) { + $m = new $Map(); + } + $mapSet($m, key, value); + } + }; + return channel; + }; + } +}); + +// node_modules/side-channel-weakmap/index.js +var require_side_channel_weakmap = __commonJS({ + "node_modules/side-channel-weakmap/index.js"(exports2, module2) { + "use strict"; + var GetIntrinsic = require_get_intrinsic(); + var callBound = require_call_bound(); + var inspect = require_object_inspect(); + var getSideChannelMap = require_side_channel_map(); + var $TypeError = require_type(); + var $WeakMap = GetIntrinsic("%WeakMap%", true); + var $weakMapGet = callBound("WeakMap.prototype.get", true); + var $weakMapSet = callBound("WeakMap.prototype.set", true); + var $weakMapHas = callBound("WeakMap.prototype.has", true); + var $weakMapDelete = callBound("WeakMap.prototype.delete", true); + module2.exports = $WeakMap ? ( + /** @type {Exclude} */ + function getSideChannelWeakMap() { + var $wm; + var $m; + var channel = { + assert: function(key) { + if (!channel.has(key)) { + throw new $TypeError("Side channel does not contain " + inspect(key)); + } + }, + "delete": function(key) { + if ($WeakMap && key && (typeof key === "object" || typeof key === "function")) { + if ($wm) { + return $weakMapDelete($wm, key); + } + } else if (getSideChannelMap) { + if ($m) { + return $m["delete"](key); + } + } + return false; + }, + get: function(key) { + if ($WeakMap && key && (typeof key === "object" || typeof key === "function")) { + if ($wm) { + return $weakMapGet($wm, key); + } + } + return $m && $m.get(key); + }, + has: function(key) { + if ($WeakMap && key && (typeof key === "object" || typeof key === "function")) { + if ($wm) { + return $weakMapHas($wm, key); + } + } + return !!$m && $m.has(key); + }, + set: function(key, value) { + if ($WeakMap && key && (typeof key === "object" || typeof key === "function")) { + if (!$wm) { + $wm = new $WeakMap(); + } + $weakMapSet($wm, key, value); + } else if (getSideChannelMap) { + if (!$m) { + $m = getSideChannelMap(); + } + $m.set(key, value); + } + } + }; + return channel; + } + ) : getSideChannelMap; + } +}); + +// node_modules/side-channel/index.js +var require_side_channel = __commonJS({ + "node_modules/side-channel/index.js"(exports2, module2) { + "use strict"; + var $TypeError = require_type(); + var inspect = require_object_inspect(); + var getSideChannelList = require_side_channel_list(); + var getSideChannelMap = require_side_channel_map(); + var getSideChannelWeakMap = require_side_channel_weakmap(); + var makeChannel = getSideChannelWeakMap || getSideChannelMap || getSideChannelList; + module2.exports = function getSideChannel() { + var $channelData; + var channel = { + assert: function(key) { + if (!channel.has(key)) { + throw new $TypeError("Side channel does not contain " + inspect(key)); + } + }, + "delete": function(key) { + return !!$channelData && $channelData["delete"](key); + }, + get: function(key) { + return $channelData && $channelData.get(key); + }, + has: function(key) { + return !!$channelData && $channelData.has(key); + }, + set: function(key, value) { + if (!$channelData) { + $channelData = makeChannel(); + } + $channelData.set(key, value); + } + }; + return channel; + }; + } +}); + +// node_modules/qs/lib/formats.js +var require_formats = __commonJS({ + "node_modules/qs/lib/formats.js"(exports2, module2) { + "use strict"; + var replace = String.prototype.replace; + var percentTwenties = /%20/g; + var Format = { + RFC1738: "RFC1738", + RFC3986: "RFC3986" + }; + module2.exports = { + "default": Format.RFC3986, + formatters: { + RFC1738: function(value) { + return replace.call(value, percentTwenties, "+"); + }, + RFC3986: function(value) { + return String(value); + } + }, + RFC1738: Format.RFC1738, + RFC3986: Format.RFC3986 + }; + } +}); + +// node_modules/qs/lib/utils.js +var require_utils = __commonJS({ + "node_modules/qs/lib/utils.js"(exports2, module2) { + "use strict"; + var formats = require_formats(); + var getSideChannel = require_side_channel(); + var has2 = Object.prototype.hasOwnProperty; + var isArray3 = Array.isArray; + var overflowChannel = getSideChannel(); + var markOverflow = function markOverflow2(obj, maxIndex) { + overflowChannel.set(obj, maxIndex); + return obj; + }; + var isOverflow = function isOverflow2(obj) { + return overflowChannel.has(obj); + }; + var getMaxIndex = function getMaxIndex2(obj) { + return overflowChannel.get(obj); + }; + var setMaxIndex = function setMaxIndex2(obj, maxIndex) { + overflowChannel.set(obj, maxIndex); + }; + var hexTable = (function() { + var array = []; + for (var i = 0; i < 256; ++i) { + array[array.length] = "%" + ((i < 16 ? "0" : "") + i.toString(16)).toUpperCase(); + } + return array; + })(); + var compactQueue = function compactQueue2(queue5) { + while (queue5.length > 1) { + var item = queue5.pop(); + var obj = item.obj[item.prop]; + if (isArray3(obj)) { + var compacted = []; + for (var j = 0; j < obj.length; ++j) { + if (typeof obj[j] !== "undefined") { + compacted[compacted.length] = obj[j]; + } + } + item.obj[item.prop] = compacted; + } + } + }; + var arrayToObject2 = function arrayToObject3(source, options) { + var obj = options && options.plainObjects ? { __proto__: null } : {}; + for (var i = 0; i < source.length; ++i) { + if (typeof source[i] !== "undefined") { + obj[i] = source[i]; + } + } + return obj; + }; + var merge3 = function merge4(target, source, options) { + if (!source) { + return target; + } + if (typeof source !== "object" && typeof source !== "function") { + if (isArray3(target)) { + var nextIndex = target.length; + if (options && typeof options.arrayLimit === "number" && nextIndex > options.arrayLimit) { + return markOverflow(arrayToObject2(target.concat(source), options), nextIndex); + } + target[nextIndex] = source; + } else if (target && typeof target === "object") { + if (isOverflow(target)) { + var newIndex = getMaxIndex(target) + 1; + target[newIndex] = source; + setMaxIndex(target, newIndex); + } else if (options && options.strictMerge) { + return [target, source]; + } else if (options && (options.plainObjects || options.allowPrototypes) || !has2.call(Object.prototype, source)) { + target[source] = true; + } + } else { + return [target, source]; + } + return target; + } + if (!target || typeof target !== "object") { + if (isOverflow(source)) { + var sourceKeys = Object.keys(source); + var result = options && options.plainObjects ? { __proto__: null, 0: target } : { 0: target }; + for (var m = 0; m < sourceKeys.length; m++) { + var oldKey = parseInt(sourceKeys[m], 10); + result[oldKey + 1] = source[sourceKeys[m]]; + } + return markOverflow(result, getMaxIndex(source) + 1); + } + var combined = [target].concat(source); + if (options && typeof options.arrayLimit === "number" && combined.length > options.arrayLimit) { + return markOverflow(arrayToObject2(combined, options), combined.length - 1); + } + return combined; + } + var mergeTarget = target; + if (isArray3(target) && !isArray3(source)) { + mergeTarget = arrayToObject2(target, options); + } + if (isArray3(target) && isArray3(source)) { + source.forEach(function(item, i) { + if (has2.call(target, i)) { + var targetItem = target[i]; + if (targetItem && typeof targetItem === "object" && item && typeof item === "object") { + target[i] = merge4(targetItem, item, options); + } else { + target[target.length] = item; + } + } else { + target[i] = item; + } + }); + return target; + } + return Object.keys(source).reduce(function(acc, key) { + var value = source[key]; + if (has2.call(acc, key)) { + acc[key] = merge4(acc[key], value, options); + } else { + acc[key] = value; + } + if (isOverflow(source) && !isOverflow(acc)) { + markOverflow(acc, getMaxIndex(source)); + } + if (isOverflow(acc)) { + var keyNum = parseInt(key, 10); + if (String(keyNum) === key && keyNum >= 0 && keyNum > getMaxIndex(acc)) { + setMaxIndex(acc, keyNum); + } + } + return acc; + }, mergeTarget); + }; + var assign = function assignSingleSource(target, source) { + return Object.keys(source).reduce(function(acc, key) { + acc[key] = source[key]; + return acc; + }, target); + }; + var decode = function(str, defaultDecoder, charset) { + var strWithoutPlus = str.replace(/\+/g, " "); + if (charset === "iso-8859-1") { + return strWithoutPlus.replace(/%[0-9a-f]{2}/gi, unescape); + } + try { + return decodeURIComponent(strWithoutPlus); + } catch (e) { + return strWithoutPlus; + } + }; + var limit = 1024; + var encode3 = function encode4(str, defaultEncoder, charset, kind, format) { + if (str.length === 0) { + return str; + } + var string = str; + if (typeof str === "symbol") { + string = Symbol.prototype.toString.call(str); + } else if (typeof str !== "string") { + string = String(str); + } + if (charset === "iso-8859-1") { + return escape(string).replace(/%u[0-9a-f]{4}/gi, function($0) { + return "%26%23" + parseInt($0.slice(2), 16) + "%3B"; + }); + } + var out = ""; + for (var j = 0; j < string.length; j += limit) { + var segment = string.length >= limit ? string.slice(j, j + limit) : string; + var arr = []; + for (var i = 0; i < segment.length; ++i) { + var c = segment.charCodeAt(i); + if (c === 45 || c === 46 || c === 95 || c === 126 || c >= 48 && c <= 57 || c >= 65 && c <= 90 || c >= 97 && c <= 122 || format === formats.RFC1738 && (c === 40 || c === 41)) { + arr[arr.length] = segment.charAt(i); + continue; + } + if (c < 128) { + arr[arr.length] = hexTable[c]; + continue; + } + if (c < 2048) { + arr[arr.length] = hexTable[192 | c >> 6] + hexTable[128 | c & 63]; + continue; + } + if (c < 55296 || c >= 57344) { + arr[arr.length] = hexTable[224 | c >> 12] + hexTable[128 | c >> 6 & 63] + hexTable[128 | c & 63]; + continue; + } + i += 1; + c = 65536 + ((c & 1023) << 10 | segment.charCodeAt(i) & 1023); + arr[arr.length] = hexTable[240 | c >> 18] + hexTable[128 | c >> 12 & 63] + hexTable[128 | c >> 6 & 63] + hexTable[128 | c & 63]; + } + out += arr.join(""); + } + return out; + }; + var compact = function compact2(value) { + var queue5 = [{ obj: { o: value }, prop: "o" }]; + var refs = []; + for (var i = 0; i < queue5.length; ++i) { + var item = queue5[i]; + var obj = item.obj[item.prop]; + var keys2 = Object.keys(obj); + for (var j = 0; j < keys2.length; ++j) { + var key = keys2[j]; + var val = obj[key]; + if (typeof val === "object" && val !== null && refs.indexOf(val) === -1) { + queue5[queue5.length] = { obj, prop: key }; + refs[refs.length] = val; + } + } + } + compactQueue(queue5); + return value; + }; + var isRegExp2 = function isRegExp3(obj) { + return Object.prototype.toString.call(obj) === "[object RegExp]"; + }; + var isBuffer3 = function isBuffer4(obj) { + if (!obj || typeof obj !== "object") { + return false; + } + return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj)); + }; + var combine = function combine2(a, b, arrayLimit, plainObjects) { + if (isOverflow(a)) { + var newIndex = getMaxIndex(a) + 1; + a[newIndex] = b; + setMaxIndex(a, newIndex); + return a; + } + var result = [].concat(a, b); + if (result.length > arrayLimit) { + return markOverflow(arrayToObject2(result, { plainObjects }), result.length - 1); + } + return result; + }; + var maybeMap = function maybeMap2(val, fn) { + if (isArray3(val)) { + var mapped = []; + for (var i = 0; i < val.length; i += 1) { + mapped[mapped.length] = fn(val[i]); + } + return mapped; + } + return fn(val); + }; + module2.exports = { + arrayToObject: arrayToObject2, + assign, + combine, + compact, + decode, + encode: encode3, + isBuffer: isBuffer3, + isOverflow, + isRegExp: isRegExp2, + markOverflow, + maybeMap, + merge: merge3 + }; + } +}); + +// node_modules/qs/lib/stringify.js +var require_stringify = __commonJS({ + "node_modules/qs/lib/stringify.js"(exports2, module2) { + "use strict"; + var getSideChannel = require_side_channel(); + var utils = require_utils(); + var formats = require_formats(); + var has2 = Object.prototype.hasOwnProperty; + var arrayPrefixGenerators = { + brackets: function brackets(prefix) { + return prefix + "[]"; + }, + comma: "comma", + indices: function indices(prefix, key) { + return prefix + "[" + key + "]"; + }, + repeat: function repeat(prefix) { + return prefix; + } + }; + var isArray3 = Array.isArray; + var push = Array.prototype.push; + var pushToArray = function(arr, valueOrArray) { + push.apply(arr, isArray3(valueOrArray) ? valueOrArray : [valueOrArray]); + }; + var toISO = Date.prototype.toISOString; + var defaultFormat = formats["default"]; + var defaults2 = { + addQueryPrefix: false, + allowDots: false, + allowEmptyArrays: false, + arrayFormat: "indices", + charset: "utf-8", + charsetSentinel: false, + commaRoundTrip: false, + delimiter: "&", + encode: true, + encodeDotInKeys: false, + encoder: utils.encode, + encodeValuesOnly: false, + filter: void 0, + format: defaultFormat, + formatter: formats.formatters[defaultFormat], + // deprecated + indices: false, + serializeDate: function serializeDate(date) { + return toISO.call(date); + }, + skipNulls: false, + strictNullHandling: false + }; + var isNonNullishPrimitive = function isNonNullishPrimitive2(v) { + return typeof v === "string" || typeof v === "number" || typeof v === "boolean" || typeof v === "symbol" || typeof v === "bigint"; + }; + var sentinel = {}; + var stringify2 = function stringify3(object, prefix, generateArrayPrefix, commaRoundTrip, allowEmptyArrays, strictNullHandling, skipNulls, encodeDotInKeys, encoder, filter2, sort, allowDots, serializeDate, format, formatter, encodeValuesOnly, charset, sideChannel) { + var obj = object; + var tmpSc = sideChannel; + var step = 0; + var findFlag = false; + while ((tmpSc = tmpSc.get(sentinel)) !== void 0 && !findFlag) { + var pos = tmpSc.get(object); + step += 1; + if (typeof pos !== "undefined") { + if (pos === step) { + throw new RangeError("Cyclic object value"); + } else { + findFlag = true; + } + } + if (typeof tmpSc.get(sentinel) === "undefined") { + step = 0; + } + } + if (typeof filter2 === "function") { + obj = filter2(prefix, obj); + } else if (obj instanceof Date) { + obj = serializeDate(obj); + } else if (generateArrayPrefix === "comma" && isArray3(obj)) { + obj = utils.maybeMap(obj, function(value2) { + if (value2 instanceof Date) { + return serializeDate(value2); + } + return value2; + }); + } + if (obj === null) { + if (strictNullHandling) { + return encoder && !encodeValuesOnly ? encoder(prefix, defaults2.encoder, charset, "key", format) : prefix; + } + obj = ""; + } + if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) { + if (encoder) { + var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults2.encoder, charset, "key", format); + return [formatter(keyValue) + "=" + formatter(encoder(obj, defaults2.encoder, charset, "value", format))]; + } + return [formatter(prefix) + "=" + formatter(String(obj))]; + } + var values = []; + if (typeof obj === "undefined") { + return values; + } + var objKeys; + if (generateArrayPrefix === "comma" && isArray3(obj)) { + if (encodeValuesOnly && encoder) { + obj = utils.maybeMap(obj, encoder); + } + objKeys = [{ value: obj.length > 0 ? obj.join(",") || null : void 0 }]; + } else if (isArray3(filter2)) { + objKeys = filter2; + } else { + var keys2 = Object.keys(obj); + objKeys = sort ? keys2.sort(sort) : keys2; + } + var encodedPrefix = encodeDotInKeys ? String(prefix).replace(/\./g, "%2E") : String(prefix); + var adjustedPrefix = commaRoundTrip && isArray3(obj) && obj.length === 1 ? encodedPrefix + "[]" : encodedPrefix; + if (allowEmptyArrays && isArray3(obj) && obj.length === 0) { + return adjustedPrefix + "[]"; + } + for (var j = 0; j < objKeys.length; ++j) { + var key = objKeys[j]; + var value = typeof key === "object" && key && typeof key.value !== "undefined" ? key.value : obj[key]; + if (skipNulls && value === null) { + continue; + } + var encodedKey = allowDots && encodeDotInKeys ? String(key).replace(/\./g, "%2E") : String(key); + var keyPrefix = isArray3(obj) ? typeof generateArrayPrefix === "function" ? generateArrayPrefix(adjustedPrefix, encodedKey) : adjustedPrefix : adjustedPrefix + (allowDots ? "." + encodedKey : "[" + encodedKey + "]"); + sideChannel.set(object, step); + var valueSideChannel = getSideChannel(); + valueSideChannel.set(sentinel, sideChannel); + pushToArray(values, stringify3( + value, + keyPrefix, + generateArrayPrefix, + commaRoundTrip, + allowEmptyArrays, + strictNullHandling, + skipNulls, + encodeDotInKeys, + generateArrayPrefix === "comma" && encodeValuesOnly && isArray3(obj) ? null : encoder, + filter2, + sort, + allowDots, + serializeDate, + format, + formatter, + encodeValuesOnly, + charset, + valueSideChannel + )); + } + return values; + }; + var normalizeStringifyOptions = function normalizeStringifyOptions2(opts) { + if (!opts) { + return defaults2; + } + if (typeof opts.allowEmptyArrays !== "undefined" && typeof opts.allowEmptyArrays !== "boolean") { + throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided"); + } + if (typeof opts.encodeDotInKeys !== "undefined" && typeof opts.encodeDotInKeys !== "boolean") { + throw new TypeError("`encodeDotInKeys` option can only be `true` or `false`, when provided"); + } + if (opts.encoder !== null && typeof opts.encoder !== "undefined" && typeof opts.encoder !== "function") { + throw new TypeError("Encoder has to be a function."); + } + var charset = opts.charset || defaults2.charset; + if (typeof opts.charset !== "undefined" && opts.charset !== "utf-8" && opts.charset !== "iso-8859-1") { + throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined"); + } + var format = formats["default"]; + if (typeof opts.format !== "undefined") { + if (!has2.call(formats.formatters, opts.format)) { + throw new TypeError("Unknown format option provided."); + } + format = opts.format; + } + var formatter = formats.formatters[format]; + var filter2 = defaults2.filter; + if (typeof opts.filter === "function" || isArray3(opts.filter)) { + filter2 = opts.filter; + } + var arrayFormat; + if (opts.arrayFormat in arrayPrefixGenerators) { + arrayFormat = opts.arrayFormat; + } else if ("indices" in opts) { + arrayFormat = opts.indices ? "indices" : "repeat"; + } else { + arrayFormat = defaults2.arrayFormat; + } + if ("commaRoundTrip" in opts && typeof opts.commaRoundTrip !== "boolean") { + throw new TypeError("`commaRoundTrip` must be a boolean, or absent"); + } + var allowDots = typeof opts.allowDots === "undefined" ? opts.encodeDotInKeys === true ? true : defaults2.allowDots : !!opts.allowDots; + return { + addQueryPrefix: typeof opts.addQueryPrefix === "boolean" ? opts.addQueryPrefix : defaults2.addQueryPrefix, + allowDots, + allowEmptyArrays: typeof opts.allowEmptyArrays === "boolean" ? !!opts.allowEmptyArrays : defaults2.allowEmptyArrays, + arrayFormat, + charset, + charsetSentinel: typeof opts.charsetSentinel === "boolean" ? opts.charsetSentinel : defaults2.charsetSentinel, + commaRoundTrip: !!opts.commaRoundTrip, + delimiter: typeof opts.delimiter === "undefined" ? defaults2.delimiter : opts.delimiter, + encode: typeof opts.encode === "boolean" ? opts.encode : defaults2.encode, + encodeDotInKeys: typeof opts.encodeDotInKeys === "boolean" ? opts.encodeDotInKeys : defaults2.encodeDotInKeys, + encoder: typeof opts.encoder === "function" ? opts.encoder : defaults2.encoder, + encodeValuesOnly: typeof opts.encodeValuesOnly === "boolean" ? opts.encodeValuesOnly : defaults2.encodeValuesOnly, + filter: filter2, + format, + formatter, + serializeDate: typeof opts.serializeDate === "function" ? opts.serializeDate : defaults2.serializeDate, + skipNulls: typeof opts.skipNulls === "boolean" ? opts.skipNulls : defaults2.skipNulls, + sort: typeof opts.sort === "function" ? opts.sort : null, + strictNullHandling: typeof opts.strictNullHandling === "boolean" ? opts.strictNullHandling : defaults2.strictNullHandling + }; + }; + module2.exports = function(object, opts) { + var obj = object; + var options = normalizeStringifyOptions(opts); + var objKeys; + var filter2; + if (typeof options.filter === "function") { + filter2 = options.filter; + obj = filter2("", obj); + } else if (isArray3(options.filter)) { + filter2 = options.filter; + objKeys = filter2; + } + var keys2 = []; + if (typeof obj !== "object" || obj === null) { + return ""; + } + var generateArrayPrefix = arrayPrefixGenerators[options.arrayFormat]; + var commaRoundTrip = generateArrayPrefix === "comma" && options.commaRoundTrip; + if (!objKeys) { + objKeys = Object.keys(obj); + } + if (options.sort) { + objKeys.sort(options.sort); + } + var sideChannel = getSideChannel(); + for (var i = 0; i < objKeys.length; ++i) { + var key = objKeys[i]; + var value = obj[key]; + if (options.skipNulls && value === null) { + continue; + } + pushToArray(keys2, stringify2( + value, + key, + generateArrayPrefix, + commaRoundTrip, + options.allowEmptyArrays, + options.strictNullHandling, + options.skipNulls, + options.encodeDotInKeys, + options.encode ? options.encoder : null, + options.filter, + options.sort, + options.allowDots, + options.serializeDate, + options.format, + options.formatter, + options.encodeValuesOnly, + options.charset, + sideChannel + )); + } + var joined = keys2.join(options.delimiter); + var prefix = options.addQueryPrefix === true ? "?" : ""; + if (options.charsetSentinel) { + if (options.charset === "iso-8859-1") { + prefix += "utf8=%26%2310003%3B&"; + } else { + prefix += "utf8=%E2%9C%93&"; + } + } + return joined.length > 0 ? prefix + joined : ""; + }; + } +}); + +// node_modules/qs/lib/parse.js +var require_parse = __commonJS({ + "node_modules/qs/lib/parse.js"(exports2, module2) { + "use strict"; + var utils = require_utils(); + var has2 = Object.prototype.hasOwnProperty; + var isArray3 = Array.isArray; + var defaults2 = { + allowDots: false, + allowEmptyArrays: false, + allowPrototypes: false, + allowSparse: false, + arrayLimit: 20, + charset: "utf-8", + charsetSentinel: false, + comma: false, + decodeDotInKeys: false, + decoder: utils.decode, + delimiter: "&", + depth: 5, + duplicates: "combine", + ignoreQueryPrefix: false, + interpretNumericEntities: false, + parameterLimit: 1e3, + parseArrays: true, + plainObjects: false, + strictDepth: false, + strictMerge: true, + strictNullHandling: false, + throwOnLimitExceeded: false + }; + var interpretNumericEntities = function(str) { + return str.replace(/&#(\d+);/g, function($0, numberStr) { + return String.fromCharCode(parseInt(numberStr, 10)); + }); + }; + var parseArrayValue = function(val, options, currentArrayLength) { + if (val && typeof val === "string" && options.comma && val.indexOf(",") > -1) { + return val.split(","); + } + if (options.throwOnLimitExceeded && currentArrayLength >= options.arrayLimit) { + throw new RangeError("Array limit exceeded. Only " + options.arrayLimit + " element" + (options.arrayLimit === 1 ? "" : "s") + " allowed in an array."); + } + return val; + }; + var isoSentinel = "utf8=%26%2310003%3B"; + var charsetSentinel = "utf8=%E2%9C%93"; + var parseValues = function parseQueryStringValues(str, options) { + var obj = { __proto__: null }; + var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, "") : str; + cleanStr = cleanStr.replace(/%5B/gi, "[").replace(/%5D/gi, "]"); + var limit = options.parameterLimit === Infinity ? void 0 : options.parameterLimit; + var parts = cleanStr.split( + options.delimiter, + options.throwOnLimitExceeded ? limit + 1 : limit + ); + if (options.throwOnLimitExceeded && parts.length > limit) { + throw new RangeError("Parameter limit exceeded. Only " + limit + " parameter" + (limit === 1 ? "" : "s") + " allowed."); + } + var skipIndex = -1; + var i; + var charset = options.charset; + if (options.charsetSentinel) { + for (i = 0; i < parts.length; ++i) { + if (parts[i].indexOf("utf8=") === 0) { + if (parts[i] === charsetSentinel) { + charset = "utf-8"; + } else if (parts[i] === isoSentinel) { + charset = "iso-8859-1"; + } + skipIndex = i; + i = parts.length; + } + } + } + for (i = 0; i < parts.length; ++i) { + if (i === skipIndex) { + continue; + } + var part = parts[i]; + var bracketEqualsPos = part.indexOf("]="); + var pos = bracketEqualsPos === -1 ? part.indexOf("=") : bracketEqualsPos + 1; + var key; + var val; + if (pos === -1) { + key = options.decoder(part, defaults2.decoder, charset, "key"); + val = options.strictNullHandling ? null : ""; + } else { + key = options.decoder(part.slice(0, pos), defaults2.decoder, charset, "key"); + if (key !== null) { + val = utils.maybeMap( + parseArrayValue( + part.slice(pos + 1), + options, + isArray3(obj[key]) ? obj[key].length : 0 + ), + function(encodedVal) { + return options.decoder(encodedVal, defaults2.decoder, charset, "value"); + } + ); + } + } + if (val && options.interpretNumericEntities && charset === "iso-8859-1") { + val = interpretNumericEntities(String(val)); + } + if (part.indexOf("[]=") > -1) { + val = isArray3(val) ? [val] : val; + } + if (options.comma && isArray3(val) && val.length > options.arrayLimit) { + if (options.throwOnLimitExceeded) { + throw new RangeError("Array limit exceeded. Only " + options.arrayLimit + " element" + (options.arrayLimit === 1 ? "" : "s") + " allowed in an array."); + } + val = utils.combine([], val, options.arrayLimit, options.plainObjects); + } + if (key !== null) { + var existing = has2.call(obj, key); + if (existing && (options.duplicates === "combine" || part.indexOf("[]=") > -1)) { + obj[key] = utils.combine( + obj[key], + val, + options.arrayLimit, + options.plainObjects + ); + } else if (!existing || options.duplicates === "last") { + obj[key] = val; + } + } + } + return obj; + }; + var parseObject = function(chain, val, options, valuesParsed) { + var currentArrayLength = 0; + if (chain.length > 0 && chain[chain.length - 1] === "[]") { + var parentKey = chain.slice(0, -1).join(""); + currentArrayLength = Array.isArray(val) && val[parentKey] ? val[parentKey].length : 0; + } + var leaf = valuesParsed ? val : parseArrayValue(val, options, currentArrayLength); + for (var i = chain.length - 1; i >= 0; --i) { + var obj; + var root2 = chain[i]; + if (root2 === "[]" && options.parseArrays) { + if (utils.isOverflow(leaf)) { + obj = leaf; + } else { + obj = options.allowEmptyArrays && (leaf === "" || options.strictNullHandling && leaf === null) ? [] : utils.combine( + [], + leaf, + options.arrayLimit, + options.plainObjects + ); + } + } else { + obj = options.plainObjects ? { __proto__: null } : {}; + var cleanRoot = root2.charAt(0) === "[" && root2.charAt(root2.length - 1) === "]" ? root2.slice(1, -1) : root2; + var decodedRoot = options.decodeDotInKeys ? cleanRoot.replace(/%2E/g, ".") : cleanRoot; + var index = parseInt(decodedRoot, 10); + var isValidArrayIndex = !isNaN(index) && root2 !== decodedRoot && String(index) === decodedRoot && index >= 0 && options.parseArrays; + if (!options.parseArrays && decodedRoot === "") { + obj = { 0: leaf }; + } else if (isValidArrayIndex && index < options.arrayLimit) { + obj = []; + obj[index] = leaf; + } else if (isValidArrayIndex && options.throwOnLimitExceeded) { + throw new RangeError("Array limit exceeded. Only " + options.arrayLimit + " element" + (options.arrayLimit === 1 ? "" : "s") + " allowed in an array."); + } else if (isValidArrayIndex) { + obj[index] = leaf; + utils.markOverflow(obj, index); + } else if (decodedRoot !== "__proto__") { + obj[decodedRoot] = leaf; + } + } + leaf = obj; + } + return leaf; + }; + var splitKeyIntoSegments = function splitKeyIntoSegments2(givenKey, options) { + var key = options.allowDots ? givenKey.replace(/\.([^.[]+)/g, "[$1]") : givenKey; + if (options.depth <= 0) { + if (!options.plainObjects && has2.call(Object.prototype, key)) { + if (!options.allowPrototypes) { + return; + } + } + return [key]; + } + var brackets = /(\[[^[\]]*])/; + var child = /(\[[^[\]]*])/g; + var segment = brackets.exec(key); + var parent = segment ? key.slice(0, segment.index) : key; + var keys2 = []; + if (parent) { + if (!options.plainObjects && has2.call(Object.prototype, parent)) { + if (!options.allowPrototypes) { + return; + } + } + keys2[keys2.length] = parent; + } + var i = 0; + while ((segment = child.exec(key)) !== null && i < options.depth) { + i += 1; + var segmentContent = segment[1].slice(1, -1); + if (!options.plainObjects && has2.call(Object.prototype, segmentContent)) { + if (!options.allowPrototypes) { + return; + } + } + keys2[keys2.length] = segment[1]; + } + if (segment) { + if (options.strictDepth === true) { + throw new RangeError("Input depth exceeded depth option of " + options.depth + " and strictDepth is true"); + } + keys2[keys2.length] = "[" + key.slice(segment.index) + "]"; + } + return keys2; + }; + var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesParsed) { + if (!givenKey) { + return; + } + var keys2 = splitKeyIntoSegments(givenKey, options); + if (!keys2) { + return; + } + return parseObject(keys2, val, options, valuesParsed); + }; + var normalizeParseOptions = function normalizeParseOptions2(opts) { + if (!opts) { + return defaults2; + } + if (typeof opts.allowEmptyArrays !== "undefined" && typeof opts.allowEmptyArrays !== "boolean") { + throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided"); + } + if (typeof opts.decodeDotInKeys !== "undefined" && typeof opts.decodeDotInKeys !== "boolean") { + throw new TypeError("`decodeDotInKeys` option can only be `true` or `false`, when provided"); + } + if (opts.decoder !== null && typeof opts.decoder !== "undefined" && typeof opts.decoder !== "function") { + throw new TypeError("Decoder has to be a function."); + } + if (typeof opts.charset !== "undefined" && opts.charset !== "utf-8" && opts.charset !== "iso-8859-1") { + throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined"); + } + if (typeof opts.throwOnLimitExceeded !== "undefined" && typeof opts.throwOnLimitExceeded !== "boolean") { + throw new TypeError("`throwOnLimitExceeded` option must be a boolean"); + } + var charset = typeof opts.charset === "undefined" ? defaults2.charset : opts.charset; + var duplicates = typeof opts.duplicates === "undefined" ? defaults2.duplicates : opts.duplicates; + if (duplicates !== "combine" && duplicates !== "first" && duplicates !== "last") { + throw new TypeError("The duplicates option must be either combine, first, or last"); + } + var allowDots = typeof opts.allowDots === "undefined" ? opts.decodeDotInKeys === true ? true : defaults2.allowDots : !!opts.allowDots; + return { + allowDots, + allowEmptyArrays: typeof opts.allowEmptyArrays === "boolean" ? !!opts.allowEmptyArrays : defaults2.allowEmptyArrays, + allowPrototypes: typeof opts.allowPrototypes === "boolean" ? opts.allowPrototypes : defaults2.allowPrototypes, + allowSparse: typeof opts.allowSparse === "boolean" ? opts.allowSparse : defaults2.allowSparse, + arrayLimit: typeof opts.arrayLimit === "number" ? opts.arrayLimit : defaults2.arrayLimit, + charset, + charsetSentinel: typeof opts.charsetSentinel === "boolean" ? opts.charsetSentinel : defaults2.charsetSentinel, + comma: typeof opts.comma === "boolean" ? opts.comma : defaults2.comma, + decodeDotInKeys: typeof opts.decodeDotInKeys === "boolean" ? opts.decodeDotInKeys : defaults2.decodeDotInKeys, + decoder: typeof opts.decoder === "function" ? opts.decoder : defaults2.decoder, + delimiter: typeof opts.delimiter === "string" || utils.isRegExp(opts.delimiter) ? opts.delimiter : defaults2.delimiter, + // eslint-disable-next-line no-implicit-coercion, no-extra-parens + depth: typeof opts.depth === "number" || opts.depth === false ? +opts.depth : defaults2.depth, + duplicates, + ignoreQueryPrefix: opts.ignoreQueryPrefix === true, + interpretNumericEntities: typeof opts.interpretNumericEntities === "boolean" ? opts.interpretNumericEntities : defaults2.interpretNumericEntities, + parameterLimit: typeof opts.parameterLimit === "number" ? opts.parameterLimit : defaults2.parameterLimit, + parseArrays: opts.parseArrays !== false, + plainObjects: typeof opts.plainObjects === "boolean" ? opts.plainObjects : defaults2.plainObjects, + strictDepth: typeof opts.strictDepth === "boolean" ? !!opts.strictDepth : defaults2.strictDepth, + strictMerge: typeof opts.strictMerge === "boolean" ? !!opts.strictMerge : defaults2.strictMerge, + strictNullHandling: typeof opts.strictNullHandling === "boolean" ? opts.strictNullHandling : defaults2.strictNullHandling, + throwOnLimitExceeded: typeof opts.throwOnLimitExceeded === "boolean" ? opts.throwOnLimitExceeded : false + }; + }; + module2.exports = function(str, opts) { + var options = normalizeParseOptions(opts); + if (str === "" || str === null || typeof str === "undefined") { + return options.plainObjects ? { __proto__: null } : {}; + } + var tempObj = typeof str === "string" ? parseValues(str, options) : str; + var obj = options.plainObjects ? { __proto__: null } : {}; + var keys2 = Object.keys(tempObj); + for (var i = 0; i < keys2.length; ++i) { + var key = keys2[i]; + var newObj = parseKeys(key, tempObj[key], options, typeof str === "string"); + obj = utils.merge(obj, newObj, options); + } + if (options.allowSparse === true) { + return obj; + } + return utils.compact(obj); + }; + } +}); + +// node_modules/qs/lib/index.js +var require_lib = __commonJS({ + "node_modules/qs/lib/index.js"(exports2, module2) { + "use strict"; + var stringify2 = require_stringify(); + var parse2 = require_parse(); + var formats = require_formats(); + module2.exports = { + formats, + parse: parse2, + stringify: stringify2 + }; + } +}); + +// node_modules/lodash-es/_freeGlobal.js +var freeGlobal = typeof global == "object" && global && global.Object === Object && global; +var freeGlobal_default = freeGlobal; + +// node_modules/lodash-es/_root.js +var freeSelf = typeof self == "object" && self && self.Object === Object && self; +var root = freeGlobal_default || freeSelf || Function("return this")(); +var root_default = root; + +// node_modules/lodash-es/_Symbol.js +var Symbol2 = root_default.Symbol; +var Symbol_default = Symbol2; + +// node_modules/lodash-es/_getRawTag.js +var objectProto = Object.prototype; +var hasOwnProperty = objectProto.hasOwnProperty; +var nativeObjectToString = objectProto.toString; +var symToStringTag = Symbol_default ? Symbol_default.toStringTag : void 0; +function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), tag = value[symToStringTag]; + try { + value[symToStringTag] = void 0; + var unmasked = true; + } catch (e) { + } + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; +} +var getRawTag_default = getRawTag; + +// node_modules/lodash-es/_objectToString.js +var objectProto2 = Object.prototype; +var nativeObjectToString2 = objectProto2.toString; +function objectToString(value) { + return nativeObjectToString2.call(value); +} +var objectToString_default = objectToString; + +// node_modules/lodash-es/_baseGetTag.js +var nullTag = "[object Null]"; +var undefinedTag = "[object Undefined]"; +var symToStringTag2 = Symbol_default ? Symbol_default.toStringTag : void 0; +function baseGetTag(value) { + if (value == null) { + return value === void 0 ? undefinedTag : nullTag; + } + return symToStringTag2 && symToStringTag2 in Object(value) ? getRawTag_default(value) : objectToString_default(value); +} +var baseGetTag_default = baseGetTag; + +// node_modules/lodash-es/isObjectLike.js +function isObjectLike(value) { + return value != null && typeof value == "object"; +} +var isObjectLike_default = isObjectLike; + +// node_modules/lodash-es/isSymbol.js +var symbolTag = "[object Symbol]"; +function isSymbol(value) { + return typeof value == "symbol" || isObjectLike_default(value) && baseGetTag_default(value) == symbolTag; +} +var isSymbol_default = isSymbol; + +// node_modules/lodash-es/_arrayMap.js +function arrayMap(array, iteratee) { + var index = -1, length = array == null ? 0 : array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; +} +var arrayMap_default = arrayMap; + +// node_modules/lodash-es/isArray.js +var isArray = Array.isArray; +var isArray_default = isArray; + +// node_modules/lodash-es/_baseToString.js +var INFINITY = 1 / 0; +var symbolProto = Symbol_default ? Symbol_default.prototype : void 0; +var symbolToString = symbolProto ? symbolProto.toString : void 0; +function baseToString(value) { + if (typeof value == "string") { + return value; + } + if (isArray_default(value)) { + return arrayMap_default(value, baseToString) + ""; + } + if (isSymbol_default(value)) { + return symbolToString ? symbolToString.call(value) : ""; + } + var result = value + ""; + return result == "0" && 1 / value == -INFINITY ? "-0" : result; +} +var baseToString_default = baseToString; + +// node_modules/lodash-es/_trimmedEndIndex.js +var reWhitespace = /\s/; +function trimmedEndIndex(string) { + var index = string.length; + while (index-- && reWhitespace.test(string.charAt(index))) { + } + return index; +} +var trimmedEndIndex_default = trimmedEndIndex; + +// node_modules/lodash-es/_baseTrim.js +var reTrimStart = /^\s+/; +function baseTrim(string) { + return string ? string.slice(0, trimmedEndIndex_default(string) + 1).replace(reTrimStart, "") : string; +} +var baseTrim_default = baseTrim; + +// node_modules/lodash-es/isObject.js +function isObject(value) { + var type = typeof value; + return value != null && (type == "object" || type == "function"); +} +var isObject_default = isObject; + +// node_modules/lodash-es/toNumber.js +var NAN = 0 / 0; +var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; +var reIsBinary = /^0b[01]+$/i; +var reIsOctal = /^0o[0-7]+$/i; +var freeParseInt = parseInt; +function toNumber(value) { + if (typeof value == "number") { + return value; + } + if (isSymbol_default(value)) { + return NAN; + } + if (isObject_default(value)) { + var other = typeof value.valueOf == "function" ? value.valueOf() : value; + value = isObject_default(other) ? other + "" : other; + } + if (typeof value != "string") { + return value === 0 ? value : +value; + } + value = baseTrim_default(value); + var isBinary = reIsBinary.test(value); + return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value; +} +var toNumber_default = toNumber; + +// node_modules/lodash-es/identity.js +function identity(value) { + return value; +} +var identity_default = identity; + +// node_modules/lodash-es/isFunction.js +var asyncTag = "[object AsyncFunction]"; +var funcTag = "[object Function]"; +var genTag = "[object GeneratorFunction]"; +var proxyTag = "[object Proxy]"; +function isFunction(value) { + if (!isObject_default(value)) { + return false; + } + var tag = baseGetTag_default(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; +} +var isFunction_default = isFunction; + +// node_modules/lodash-es/_coreJsData.js +var coreJsData = root_default["__core-js_shared__"]; +var coreJsData_default = coreJsData; + +// node_modules/lodash-es/_isMasked.js +var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData_default && coreJsData_default.keys && coreJsData_default.keys.IE_PROTO || ""); + return uid ? "Symbol(src)_1." + uid : ""; +})(); +function isMasked(func) { + return !!maskSrcKey && maskSrcKey in func; +} +var isMasked_default = isMasked; + +// node_modules/lodash-es/_toSource.js +var funcProto = Function.prototype; +var funcToString = funcProto.toString; +function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) { + } + try { + return func + ""; + } catch (e) { + } + } + return ""; +} +var toSource_default = toSource; + +// node_modules/lodash-es/_baseIsNative.js +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; +var reIsHostCtor = /^\[object .+?Constructor\]$/; +var funcProto2 = Function.prototype; +var objectProto3 = Object.prototype; +var funcToString2 = funcProto2.toString; +var hasOwnProperty2 = objectProto3.hasOwnProperty; +var reIsNative = RegExp( + "^" + funcToString2.call(hasOwnProperty2).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$" +); +function baseIsNative(value) { + if (!isObject_default(value) || isMasked_default(value)) { + return false; + } + var pattern = isFunction_default(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource_default(value)); +} +var baseIsNative_default = baseIsNative; + +// node_modules/lodash-es/_getValue.js +function getValue(object, key) { + return object == null ? void 0 : object[key]; +} +var getValue_default = getValue; + +// node_modules/lodash-es/_getNative.js +function getNative(object, key) { + var value = getValue_default(object, key); + return baseIsNative_default(value) ? value : void 0; +} +var getNative_default = getNative; + +// node_modules/lodash-es/_WeakMap.js +var WeakMap2 = getNative_default(root_default, "WeakMap"); +var WeakMap_default = WeakMap2; + +// node_modules/lodash-es/_baseCreate.js +var objectCreate = Object.create; +var baseCreate = /* @__PURE__ */ (function() { + function object() { + } + return function(proto) { + if (!isObject_default(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object(); + object.prototype = void 0; + return result; + }; +})(); +var baseCreate_default = baseCreate; + +// node_modules/lodash-es/_apply.js +function apply(func, thisArg, args) { + switch (args.length) { + case 0: + return func.call(thisArg); + case 1: + return func.call(thisArg, args[0]); + case 2: + return func.call(thisArg, args[0], args[1]); + case 3: + return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); +} +var apply_default = apply; + +// node_modules/lodash-es/_copyArray.js +function copyArray(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; +} +var copyArray_default = copyArray; + +// node_modules/lodash-es/_shortOut.js +var HOT_COUNT = 800; +var HOT_SPAN = 16; +var nativeNow = Date.now; +function shortOut(func) { + var count = 0, lastCalled = 0; + return function() { + var stamp = nativeNow(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(void 0, arguments); + }; +} +var shortOut_default = shortOut; + +// node_modules/lodash-es/constant.js +function constant(value) { + return function() { + return value; + }; +} +var constant_default = constant; + +// node_modules/lodash-es/_defineProperty.js +var defineProperty = (function() { + try { + var func = getNative_default(Object, "defineProperty"); + func({}, "", {}); + return func; + } catch (e) { + } +})(); +var defineProperty_default = defineProperty; + +// node_modules/lodash-es/_baseSetToString.js +var baseSetToString = !defineProperty_default ? identity_default : function(func, string) { + return defineProperty_default(func, "toString", { + "configurable": true, + "enumerable": false, + "value": constant_default(string), + "writable": true + }); +}; +var baseSetToString_default = baseSetToString; + +// node_modules/lodash-es/_setToString.js +var setToString = shortOut_default(baseSetToString_default); +var setToString_default = setToString; + +// node_modules/lodash-es/_arrayEach.js +function arrayEach(array, iteratee) { + var index = -1, length = array == null ? 0 : array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; +} +var arrayEach_default = arrayEach; + +// node_modules/lodash-es/_isIndex.js +var MAX_SAFE_INTEGER = 9007199254740991; +var reIsUint = /^(?:0|[1-9]\d*)$/; +function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + return !!length && (type == "number" || type != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length); +} +var isIndex_default = isIndex; + +// node_modules/lodash-es/_baseAssignValue.js +function baseAssignValue(object, key, value) { + if (key == "__proto__" && defineProperty_default) { + defineProperty_default(object, key, { + "configurable": true, + "enumerable": true, + "value": value, + "writable": true + }); + } else { + object[key] = value; + } +} +var baseAssignValue_default = baseAssignValue; + +// node_modules/lodash-es/eq.js +function eq(value, other) { + return value === other || value !== value && other !== other; +} +var eq_default = eq; + +// node_modules/lodash-es/_assignValue.js +var objectProto4 = Object.prototype; +var hasOwnProperty3 = objectProto4.hasOwnProperty; +function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty3.call(object, key) && eq_default(objValue, value)) || value === void 0 && !(key in object)) { + baseAssignValue_default(object, key, value); + } +} +var assignValue_default = assignValue; + +// node_modules/lodash-es/_copyObject.js +function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + var newValue = customizer ? customizer(object[key], source[key], key, object, source) : void 0; + if (newValue === void 0) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue_default(object, key, newValue); + } else { + assignValue_default(object, key, newValue); + } + } + return object; +} +var copyObject_default = copyObject; + +// node_modules/lodash-es/_overRest.js +var nativeMax = Math.max; +function overRest(func, start2, transform) { + start2 = nativeMax(start2 === void 0 ? func.length - 1 : start2, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start2, 0), array = Array(length); + while (++index < length) { + array[index] = args[start2 + index]; + } + index = -1; + var otherArgs = Array(start2 + 1); + while (++index < start2) { + otherArgs[index] = args[index]; + } + otherArgs[start2] = transform(array); + return apply_default(func, this, otherArgs); + }; +} +var overRest_default = overRest; + +// node_modules/lodash-es/_baseRest.js +function baseRest(func, start2) { + return setToString_default(overRest_default(func, start2, identity_default), func + ""); +} +var baseRest_default = baseRest; + +// node_modules/lodash-es/isLength.js +var MAX_SAFE_INTEGER2 = 9007199254740991; +function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER2; +} +var isLength_default = isLength; + +// node_modules/lodash-es/isArrayLike.js +function isArrayLike(value) { + return value != null && isLength_default(value.length) && !isFunction_default(value); +} +var isArrayLike_default = isArrayLike; + +// node_modules/lodash-es/_isIterateeCall.js +function isIterateeCall(value, index, object) { + if (!isObject_default(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike_default(object) && isIndex_default(index, object.length) : type == "string" && index in object) { + return eq_default(object[index], value); + } + return false; +} +var isIterateeCall_default = isIterateeCall; + +// node_modules/lodash-es/_createAssigner.js +function createAssigner(assigner) { + return baseRest_default(function(object, sources) { + var index = -1, length = sources.length, customizer = length > 1 ? sources[length - 1] : void 0, guard = length > 2 ? sources[2] : void 0; + customizer = assigner.length > 3 && typeof customizer == "function" ? (length--, customizer) : void 0; + if (guard && isIterateeCall_default(sources[0], sources[1], guard)) { + customizer = length < 3 ? void 0 : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); +} +var createAssigner_default = createAssigner; + +// node_modules/lodash-es/_isPrototype.js +var objectProto5 = Object.prototype; +function isPrototype(value) { + var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto5; + return value === proto; +} +var isPrototype_default = isPrototype; + +// node_modules/lodash-es/_baseTimes.js +function baseTimes(n, iteratee) { + var index = -1, result = Array(n); + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} +var baseTimes_default = baseTimes; + +// node_modules/lodash-es/_baseIsArguments.js +var argsTag = "[object Arguments]"; +function baseIsArguments(value) { + return isObjectLike_default(value) && baseGetTag_default(value) == argsTag; +} +var baseIsArguments_default = baseIsArguments; + +// node_modules/lodash-es/isArguments.js +var objectProto6 = Object.prototype; +var hasOwnProperty4 = objectProto6.hasOwnProperty; +var propertyIsEnumerable = objectProto6.propertyIsEnumerable; +var isArguments = baseIsArguments_default(/* @__PURE__ */ (function() { + return arguments; +})()) ? baseIsArguments_default : function(value) { + return isObjectLike_default(value) && hasOwnProperty4.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); +}; +var isArguments_default = isArguments; + +// node_modules/lodash-es/stubFalse.js +function stubFalse() { + return false; +} +var stubFalse_default = stubFalse; + +// node_modules/lodash-es/isBuffer.js +var freeExports = typeof exports == "object" && exports && !exports.nodeType && exports; +var freeModule = freeExports && typeof module == "object" && module && !module.nodeType && module; +var moduleExports = freeModule && freeModule.exports === freeExports; +var Buffer2 = moduleExports ? root_default.Buffer : void 0; +var nativeIsBuffer = Buffer2 ? Buffer2.isBuffer : void 0; +var isBuffer = nativeIsBuffer || stubFalse_default; +var isBuffer_default = isBuffer; + +// node_modules/lodash-es/_baseIsTypedArray.js +var argsTag2 = "[object Arguments]"; +var arrayTag = "[object Array]"; +var boolTag = "[object Boolean]"; +var dateTag = "[object Date]"; +var errorTag = "[object Error]"; +var funcTag2 = "[object Function]"; +var mapTag = "[object Map]"; +var numberTag = "[object Number]"; +var objectTag = "[object Object]"; +var regexpTag = "[object RegExp]"; +var setTag = "[object Set]"; +var stringTag = "[object String]"; +var weakMapTag = "[object WeakMap]"; +var arrayBufferTag = "[object ArrayBuffer]"; +var dataViewTag = "[object DataView]"; +var float32Tag = "[object Float32Array]"; +var float64Tag = "[object Float64Array]"; +var int8Tag = "[object Int8Array]"; +var int16Tag = "[object Int16Array]"; +var int32Tag = "[object Int32Array]"; +var uint8Tag = "[object Uint8Array]"; +var uint8ClampedTag = "[object Uint8ClampedArray]"; +var uint16Tag = "[object Uint16Array]"; +var uint32Tag = "[object Uint32Array]"; +var typedArrayTags = {}; +typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; +typedArrayTags[argsTag2] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag2] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; +function baseIsTypedArray(value) { + return isObjectLike_default(value) && isLength_default(value.length) && !!typedArrayTags[baseGetTag_default(value)]; +} +var baseIsTypedArray_default = baseIsTypedArray; + +// node_modules/lodash-es/_baseUnary.js +function baseUnary(func) { + return function(value) { + return func(value); + }; +} +var baseUnary_default = baseUnary; + +// node_modules/lodash-es/_nodeUtil.js +var freeExports2 = typeof exports == "object" && exports && !exports.nodeType && exports; +var freeModule2 = freeExports2 && typeof module == "object" && module && !module.nodeType && module; +var moduleExports2 = freeModule2 && freeModule2.exports === freeExports2; +var freeProcess = moduleExports2 && freeGlobal_default.process; +var nodeUtil = (function() { + try { + var types = freeModule2 && freeModule2.require && freeModule2.require("util").types; + if (types) { + return types; + } + return freeProcess && freeProcess.binding && freeProcess.binding("util"); + } catch (e) { + } +})(); +var nodeUtil_default = nodeUtil; + +// node_modules/lodash-es/isTypedArray.js +var nodeIsTypedArray = nodeUtil_default && nodeUtil_default.isTypedArray; +var isTypedArray = nodeIsTypedArray ? baseUnary_default(nodeIsTypedArray) : baseIsTypedArray_default; +var isTypedArray_default = isTypedArray; + +// node_modules/lodash-es/_arrayLikeKeys.js +var objectProto7 = Object.prototype; +var hasOwnProperty5 = objectProto7.hasOwnProperty; +function arrayLikeKeys(value, inherited) { + var isArr = isArray_default(value), isArg = !isArr && isArguments_default(value), isBuff = !isArr && !isArg && isBuffer_default(value), isType = !isArr && !isArg && !isBuff && isTypedArray_default(value), skipIndexes = isArr || isArg || isBuff || isType, result = skipIndexes ? baseTimes_default(value.length, String) : [], length = result.length; + for (var key in value) { + if ((inherited || hasOwnProperty5.call(value, key)) && !(skipIndexes && // Safari 9 has enumerable `arguments.length` in strict mode. + (key == "length" || // Node.js 0.10 has enumerable non-index properties on buffers. + isBuff && (key == "offset" || key == "parent") || // PhantomJS 2 has enumerable non-index properties on typed arrays. + isType && (key == "buffer" || key == "byteLength" || key == "byteOffset") || // Skip index properties. + isIndex_default(key, length)))) { + result.push(key); + } + } + return result; +} +var arrayLikeKeys_default = arrayLikeKeys; + +// node_modules/lodash-es/_overArg.js +function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; +} +var overArg_default = overArg; + +// node_modules/lodash-es/_nativeKeys.js +var nativeKeys = overArg_default(Object.keys, Object); +var nativeKeys_default = nativeKeys; + +// node_modules/lodash-es/_baseKeys.js +var objectProto8 = Object.prototype; +var hasOwnProperty6 = objectProto8.hasOwnProperty; +function baseKeys(object) { + if (!isPrototype_default(object)) { + return nativeKeys_default(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty6.call(object, key) && key != "constructor") { + result.push(key); + } + } + return result; +} +var baseKeys_default = baseKeys; + +// node_modules/lodash-es/keys.js +function keys(object) { + return isArrayLike_default(object) ? arrayLikeKeys_default(object) : baseKeys_default(object); +} +var keys_default = keys; + +// node_modules/lodash-es/_nativeKeysIn.js +function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; +} +var nativeKeysIn_default = nativeKeysIn; + +// node_modules/lodash-es/_baseKeysIn.js +var objectProto9 = Object.prototype; +var hasOwnProperty7 = objectProto9.hasOwnProperty; +function baseKeysIn(object) { + if (!isObject_default(object)) { + return nativeKeysIn_default(object); + } + var isProto = isPrototype_default(object), result = []; + for (var key in object) { + if (!(key == "constructor" && (isProto || !hasOwnProperty7.call(object, key)))) { + result.push(key); + } + } + return result; +} +var baseKeysIn_default = baseKeysIn; + +// node_modules/lodash-es/keysIn.js +function keysIn(object) { + return isArrayLike_default(object) ? arrayLikeKeys_default(object, true) : baseKeysIn_default(object); +} +var keysIn_default = keysIn; + +// node_modules/lodash-es/_isKey.js +var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; +var reIsPlainProp = /^\w*$/; +function isKey(value, object) { + if (isArray_default(value)) { + return false; + } + var type = typeof value; + if (type == "number" || type == "symbol" || type == "boolean" || value == null || isSymbol_default(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object(object); +} +var isKey_default = isKey; + +// node_modules/lodash-es/_nativeCreate.js +var nativeCreate = getNative_default(Object, "create"); +var nativeCreate_default = nativeCreate; + +// node_modules/lodash-es/_hashClear.js +function hashClear() { + this.__data__ = nativeCreate_default ? nativeCreate_default(null) : {}; + this.size = 0; +} +var hashClear_default = hashClear; + +// node_modules/lodash-es/_hashDelete.js +function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; +} +var hashDelete_default = hashDelete; + +// node_modules/lodash-es/_hashGet.js +var HASH_UNDEFINED = "__lodash_hash_undefined__"; +var objectProto10 = Object.prototype; +var hasOwnProperty8 = objectProto10.hasOwnProperty; +function hashGet(key) { + var data = this.__data__; + if (nativeCreate_default) { + var result = data[key]; + return result === HASH_UNDEFINED ? void 0 : result; + } + return hasOwnProperty8.call(data, key) ? data[key] : void 0; +} +var hashGet_default = hashGet; + +// node_modules/lodash-es/_hashHas.js +var objectProto11 = Object.prototype; +var hasOwnProperty9 = objectProto11.hasOwnProperty; +function hashHas(key) { + var data = this.__data__; + return nativeCreate_default ? data[key] !== void 0 : hasOwnProperty9.call(data, key); +} +var hashHas_default = hashHas; + +// node_modules/lodash-es/_hashSet.js +var HASH_UNDEFINED2 = "__lodash_hash_undefined__"; +function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = nativeCreate_default && value === void 0 ? HASH_UNDEFINED2 : value; + return this; +} +var hashSet_default = hashSet; + +// node_modules/lodash-es/_Hash.js +function Hash(entries) { + var index = -1, length = entries == null ? 0 : entries.length; + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} +Hash.prototype.clear = hashClear_default; +Hash.prototype["delete"] = hashDelete_default; +Hash.prototype.get = hashGet_default; +Hash.prototype.has = hashHas_default; +Hash.prototype.set = hashSet_default; +var Hash_default = Hash; + +// node_modules/lodash-es/_listCacheClear.js +function listCacheClear() { + this.__data__ = []; + this.size = 0; +} +var listCacheClear_default = listCacheClear; + +// node_modules/lodash-es/_assocIndexOf.js +function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq_default(array[length][0], key)) { + return length; + } + } + return -1; +} +var assocIndexOf_default = assocIndexOf; + +// node_modules/lodash-es/_listCacheDelete.js +var arrayProto = Array.prototype; +var splice = arrayProto.splice; +function listCacheDelete(key) { + var data = this.__data__, index = assocIndexOf_default(data, key); + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; +} +var listCacheDelete_default = listCacheDelete; + +// node_modules/lodash-es/_listCacheGet.js +function listCacheGet(key) { + var data = this.__data__, index = assocIndexOf_default(data, key); + return index < 0 ? void 0 : data[index][1]; +} +var listCacheGet_default = listCacheGet; + +// node_modules/lodash-es/_listCacheHas.js +function listCacheHas(key) { + return assocIndexOf_default(this.__data__, key) > -1; +} +var listCacheHas_default = listCacheHas; + +// node_modules/lodash-es/_listCacheSet.js +function listCacheSet(key, value) { + var data = this.__data__, index = assocIndexOf_default(data, key); + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; +} +var listCacheSet_default = listCacheSet; + +// node_modules/lodash-es/_ListCache.js +function ListCache(entries) { + var index = -1, length = entries == null ? 0 : entries.length; + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} +ListCache.prototype.clear = listCacheClear_default; +ListCache.prototype["delete"] = listCacheDelete_default; +ListCache.prototype.get = listCacheGet_default; +ListCache.prototype.has = listCacheHas_default; +ListCache.prototype.set = listCacheSet_default; +var ListCache_default = ListCache; + +// node_modules/lodash-es/_Map.js +var Map2 = getNative_default(root_default, "Map"); +var Map_default = Map2; + +// node_modules/lodash-es/_mapCacheClear.js +function mapCacheClear() { + this.size = 0; + this.__data__ = { + "hash": new Hash_default(), + "map": new (Map_default || ListCache_default)(), + "string": new Hash_default() + }; +} +var mapCacheClear_default = mapCacheClear; + +// node_modules/lodash-es/_isKeyable.js +function isKeyable(value) { + var type = typeof value; + return type == "string" || type == "number" || type == "symbol" || type == "boolean" ? value !== "__proto__" : value === null; +} +var isKeyable_default = isKeyable; + +// node_modules/lodash-es/_getMapData.js +function getMapData(map, key) { + var data = map.__data__; + return isKeyable_default(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map; +} +var getMapData_default = getMapData; + +// node_modules/lodash-es/_mapCacheDelete.js +function mapCacheDelete(key) { + var result = getMapData_default(this, key)["delete"](key); + this.size -= result ? 1 : 0; + return result; +} +var mapCacheDelete_default = mapCacheDelete; + +// node_modules/lodash-es/_mapCacheGet.js +function mapCacheGet(key) { + return getMapData_default(this, key).get(key); +} +var mapCacheGet_default = mapCacheGet; + +// node_modules/lodash-es/_mapCacheHas.js +function mapCacheHas(key) { + return getMapData_default(this, key).has(key); +} +var mapCacheHas_default = mapCacheHas; + +// node_modules/lodash-es/_mapCacheSet.js +function mapCacheSet(key, value) { + var data = getMapData_default(this, key), size = data.size; + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; +} +var mapCacheSet_default = mapCacheSet; + +// node_modules/lodash-es/_MapCache.js +function MapCache(entries) { + var index = -1, length = entries == null ? 0 : entries.length; + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} +MapCache.prototype.clear = mapCacheClear_default; +MapCache.prototype["delete"] = mapCacheDelete_default; +MapCache.prototype.get = mapCacheGet_default; +MapCache.prototype.has = mapCacheHas_default; +MapCache.prototype.set = mapCacheSet_default; +var MapCache_default = MapCache; + +// node_modules/lodash-es/memoize.js +var FUNC_ERROR_TEXT = "Expected a function"; +function memoize(func, resolver) { + if (typeof func != "function" || resolver != null && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result) || cache; + return result; + }; + memoized.cache = new (memoize.Cache || MapCache_default)(); + return memoized; +} +memoize.Cache = MapCache_default; +var memoize_default = memoize; + +// node_modules/lodash-es/_memoizeCapped.js +var MAX_MEMOIZE_SIZE = 500; +function memoizeCapped(func) { + var result = memoize_default(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + var cache = result.cache; + return result; +} +var memoizeCapped_default = memoizeCapped; + +// node_modules/lodash-es/_stringToPath.js +var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; +var reEscapeChar = /\\(\\)?/g; +var stringToPath = memoizeCapped_default(function(string) { + var result = []; + if (string.charCodeAt(0) === 46) { + result.push(""); + } + string.replace(rePropName, function(match, number, quote, subString) { + result.push(quote ? subString.replace(reEscapeChar, "$1") : number || match); + }); + return result; +}); +var stringToPath_default = stringToPath; + +// node_modules/lodash-es/toString.js +function toString(value) { + return value == null ? "" : baseToString_default(value); +} +var toString_default = toString; + +// node_modules/lodash-es/_castPath.js +function castPath(value, object) { + if (isArray_default(value)) { + return value; + } + return isKey_default(value, object) ? [value] : stringToPath_default(toString_default(value)); +} +var castPath_default = castPath; + +// node_modules/lodash-es/_toKey.js +var INFINITY2 = 1 / 0; +function toKey(value) { + if (typeof value == "string" || isSymbol_default(value)) { + return value; + } + var result = value + ""; + return result == "0" && 1 / value == -INFINITY2 ? "-0" : result; +} +var toKey_default = toKey; + +// node_modules/lodash-es/_baseGet.js +function baseGet(object, path) { + path = castPath_default(path, object); + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[toKey_default(path[index++])]; + } + return index && index == length ? object : void 0; +} +var baseGet_default = baseGet; + +// node_modules/lodash-es/get.js +function get(object, path, defaultValue) { + var result = object == null ? void 0 : baseGet_default(object, path); + return result === void 0 ? defaultValue : result; +} +var get_default = get; + +// node_modules/lodash-es/_arrayPush.js +function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; +} +var arrayPush_default = arrayPush; + +// node_modules/lodash-es/_getPrototype.js +var getPrototype = overArg_default(Object.getPrototypeOf, Object); +var getPrototype_default = getPrototype; + +// node_modules/lodash-es/isPlainObject.js +var objectTag2 = "[object Object]"; +var funcProto3 = Function.prototype; +var objectProto12 = Object.prototype; +var funcToString3 = funcProto3.toString; +var hasOwnProperty10 = objectProto12.hasOwnProperty; +var objectCtorString = funcToString3.call(Object); +function isPlainObject(value) { + if (!isObjectLike_default(value) || baseGetTag_default(value) != objectTag2) { + return false; + } + var proto = getPrototype_default(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty10.call(proto, "constructor") && proto.constructor; + return typeof Ctor == "function" && Ctor instanceof Ctor && funcToString3.call(Ctor) == objectCtorString; +} +var isPlainObject_default = isPlainObject; + +// node_modules/lodash-es/_basePropertyOf.js +function basePropertyOf(object) { + return function(key) { + return object == null ? void 0 : object[key]; + }; +} +var basePropertyOf_default = basePropertyOf; + +// node_modules/lodash-es/_stackClear.js +function stackClear() { + this.__data__ = new ListCache_default(); + this.size = 0; +} +var stackClear_default = stackClear; + +// node_modules/lodash-es/_stackDelete.js +function stackDelete(key) { + var data = this.__data__, result = data["delete"](key); + this.size = data.size; + return result; +} +var stackDelete_default = stackDelete; + +// node_modules/lodash-es/_stackGet.js +function stackGet(key) { + return this.__data__.get(key); +} +var stackGet_default = stackGet; + +// node_modules/lodash-es/_stackHas.js +function stackHas(key) { + return this.__data__.has(key); +} +var stackHas_default = stackHas; + +// node_modules/lodash-es/_stackSet.js +var LARGE_ARRAY_SIZE = 200; +function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache_default) { + var pairs = data.__data__; + if (!Map_default || pairs.length < LARGE_ARRAY_SIZE - 1) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache_default(pairs); + } + data.set(key, value); + this.size = data.size; + return this; +} +var stackSet_default = stackSet; + +// node_modules/lodash-es/_Stack.js +function Stack(entries) { + var data = this.__data__ = new ListCache_default(entries); + this.size = data.size; +} +Stack.prototype.clear = stackClear_default; +Stack.prototype["delete"] = stackDelete_default; +Stack.prototype.get = stackGet_default; +Stack.prototype.has = stackHas_default; +Stack.prototype.set = stackSet_default; +var Stack_default = Stack; + +// node_modules/lodash-es/_baseAssign.js +function baseAssign(object, source) { + return object && copyObject_default(source, keys_default(source), object); +} +var baseAssign_default = baseAssign; + +// node_modules/lodash-es/_baseAssignIn.js +function baseAssignIn(object, source) { + return object && copyObject_default(source, keysIn_default(source), object); +} +var baseAssignIn_default = baseAssignIn; + +// node_modules/lodash-es/_cloneBuffer.js +var freeExports3 = typeof exports == "object" && exports && !exports.nodeType && exports; +var freeModule3 = freeExports3 && typeof module == "object" && module && !module.nodeType && module; +var moduleExports3 = freeModule3 && freeModule3.exports === freeExports3; +var Buffer3 = moduleExports3 ? root_default.Buffer : void 0; +var allocUnsafe = Buffer3 ? Buffer3.allocUnsafe : void 0; +function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + buffer.copy(result); + return result; +} +var cloneBuffer_default = cloneBuffer; + +// node_modules/lodash-es/_arrayFilter.js +function arrayFilter(array, predicate) { + var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; +} +var arrayFilter_default = arrayFilter; + +// node_modules/lodash-es/stubArray.js +function stubArray() { + return []; +} +var stubArray_default = stubArray; + +// node_modules/lodash-es/_getSymbols.js +var objectProto13 = Object.prototype; +var propertyIsEnumerable2 = objectProto13.propertyIsEnumerable; +var nativeGetSymbols = Object.getOwnPropertySymbols; +var getSymbols = !nativeGetSymbols ? stubArray_default : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter_default(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable2.call(object, symbol); + }); +}; +var getSymbols_default = getSymbols; + +// node_modules/lodash-es/_copySymbols.js +function copySymbols(source, object) { + return copyObject_default(source, getSymbols_default(source), object); +} +var copySymbols_default = copySymbols; + +// node_modules/lodash-es/_getSymbolsIn.js +var nativeGetSymbols2 = Object.getOwnPropertySymbols; +var getSymbolsIn = !nativeGetSymbols2 ? stubArray_default : function(object) { + var result = []; + while (object) { + arrayPush_default(result, getSymbols_default(object)); + object = getPrototype_default(object); + } + return result; +}; +var getSymbolsIn_default = getSymbolsIn; + +// node_modules/lodash-es/_copySymbolsIn.js +function copySymbolsIn(source, object) { + return copyObject_default(source, getSymbolsIn_default(source), object); +} +var copySymbolsIn_default = copySymbolsIn; + +// node_modules/lodash-es/_baseGetAllKeys.js +function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray_default(object) ? result : arrayPush_default(result, symbolsFunc(object)); +} +var baseGetAllKeys_default = baseGetAllKeys; + +// node_modules/lodash-es/_getAllKeys.js +function getAllKeys(object) { + return baseGetAllKeys_default(object, keys_default, getSymbols_default); +} +var getAllKeys_default = getAllKeys; + +// node_modules/lodash-es/_getAllKeysIn.js +function getAllKeysIn(object) { + return baseGetAllKeys_default(object, keysIn_default, getSymbolsIn_default); +} +var getAllKeysIn_default = getAllKeysIn; + +// node_modules/lodash-es/_DataView.js +var DataView2 = getNative_default(root_default, "DataView"); +var DataView_default = DataView2; + +// node_modules/lodash-es/_Promise.js +var Promise2 = getNative_default(root_default, "Promise"); +var Promise_default = Promise2; + +// node_modules/lodash-es/_Set.js +var Set2 = getNative_default(root_default, "Set"); +var Set_default = Set2; + +// node_modules/lodash-es/_getTag.js +var mapTag2 = "[object Map]"; +var objectTag3 = "[object Object]"; +var promiseTag = "[object Promise]"; +var setTag2 = "[object Set]"; +var weakMapTag2 = "[object WeakMap]"; +var dataViewTag2 = "[object DataView]"; +var dataViewCtorString = toSource_default(DataView_default); +var mapCtorString = toSource_default(Map_default); +var promiseCtorString = toSource_default(Promise_default); +var setCtorString = toSource_default(Set_default); +var weakMapCtorString = toSource_default(WeakMap_default); +var getTag = baseGetTag_default; +if (DataView_default && getTag(new DataView_default(new ArrayBuffer(1))) != dataViewTag2 || Map_default && getTag(new Map_default()) != mapTag2 || Promise_default && getTag(Promise_default.resolve()) != promiseTag || Set_default && getTag(new Set_default()) != setTag2 || WeakMap_default && getTag(new WeakMap_default()) != weakMapTag2) { + getTag = function(value) { + var result = baseGetTag_default(value), Ctor = result == objectTag3 ? value.constructor : void 0, ctorString = Ctor ? toSource_default(Ctor) : ""; + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: + return dataViewTag2; + case mapCtorString: + return mapTag2; + case promiseCtorString: + return promiseTag; + case setCtorString: + return setTag2; + case weakMapCtorString: + return weakMapTag2; + } + } + return result; + }; +} +var getTag_default = getTag; + +// node_modules/lodash-es/_initCloneArray.js +var objectProto14 = Object.prototype; +var hasOwnProperty11 = objectProto14.hasOwnProperty; +function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty11.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; +} +var initCloneArray_default = initCloneArray; + +// node_modules/lodash-es/_Uint8Array.js +var Uint8Array2 = root_default.Uint8Array; +var Uint8Array_default = Uint8Array2; + +// node_modules/lodash-es/_cloneArrayBuffer.js +function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array_default(result).set(new Uint8Array_default(arrayBuffer)); + return result; +} +var cloneArrayBuffer_default = cloneArrayBuffer; + +// node_modules/lodash-es/_cloneDataView.js +function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer_default(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); +} +var cloneDataView_default = cloneDataView; + +// node_modules/lodash-es/_cloneRegExp.js +var reFlags = /\w*$/; +function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; +} +var cloneRegExp_default = cloneRegExp; + +// node_modules/lodash-es/_cloneSymbol.js +var symbolProto2 = Symbol_default ? Symbol_default.prototype : void 0; +var symbolValueOf = symbolProto2 ? symbolProto2.valueOf : void 0; +function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; +} +var cloneSymbol_default = cloneSymbol; + +// node_modules/lodash-es/_cloneTypedArray.js +function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer_default(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); +} +var cloneTypedArray_default = cloneTypedArray; + +// node_modules/lodash-es/_initCloneByTag.js +var boolTag2 = "[object Boolean]"; +var dateTag2 = "[object Date]"; +var mapTag3 = "[object Map]"; +var numberTag2 = "[object Number]"; +var regexpTag2 = "[object RegExp]"; +var setTag3 = "[object Set]"; +var stringTag2 = "[object String]"; +var symbolTag2 = "[object Symbol]"; +var arrayBufferTag2 = "[object ArrayBuffer]"; +var dataViewTag3 = "[object DataView]"; +var float32Tag2 = "[object Float32Array]"; +var float64Tag2 = "[object Float64Array]"; +var int8Tag2 = "[object Int8Array]"; +var int16Tag2 = "[object Int16Array]"; +var int32Tag2 = "[object Int32Array]"; +var uint8Tag2 = "[object Uint8Array]"; +var uint8ClampedTag2 = "[object Uint8ClampedArray]"; +var uint16Tag2 = "[object Uint16Array]"; +var uint32Tag2 = "[object Uint32Array]"; +function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag2: + return cloneArrayBuffer_default(object); + case boolTag2: + case dateTag2: + return new Ctor(+object); + case dataViewTag3: + return cloneDataView_default(object, isDeep); + case float32Tag2: + case float64Tag2: + case int8Tag2: + case int16Tag2: + case int32Tag2: + case uint8Tag2: + case uint8ClampedTag2: + case uint16Tag2: + case uint32Tag2: + return cloneTypedArray_default(object, isDeep); + case mapTag3: + return new Ctor(); + case numberTag2: + case stringTag2: + return new Ctor(object); + case regexpTag2: + return cloneRegExp_default(object); + case setTag3: + return new Ctor(); + case symbolTag2: + return cloneSymbol_default(object); + } +} +var initCloneByTag_default = initCloneByTag; + +// node_modules/lodash-es/_initCloneObject.js +function initCloneObject(object) { + return typeof object.constructor == "function" && !isPrototype_default(object) ? baseCreate_default(getPrototype_default(object)) : {}; +} +var initCloneObject_default = initCloneObject; + +// node_modules/lodash-es/_baseIsMap.js +var mapTag4 = "[object Map]"; +function baseIsMap(value) { + return isObjectLike_default(value) && getTag_default(value) == mapTag4; +} +var baseIsMap_default = baseIsMap; + +// node_modules/lodash-es/isMap.js +var nodeIsMap = nodeUtil_default && nodeUtil_default.isMap; +var isMap = nodeIsMap ? baseUnary_default(nodeIsMap) : baseIsMap_default; +var isMap_default = isMap; + +// node_modules/lodash-es/_baseIsSet.js +var setTag4 = "[object Set]"; +function baseIsSet(value) { + return isObjectLike_default(value) && getTag_default(value) == setTag4; +} +var baseIsSet_default = baseIsSet; + +// node_modules/lodash-es/isSet.js +var nodeIsSet = nodeUtil_default && nodeUtil_default.isSet; +var isSet = nodeIsSet ? baseUnary_default(nodeIsSet) : baseIsSet_default; +var isSet_default = isSet; + +// node_modules/lodash-es/_baseClone.js +var CLONE_DEEP_FLAG = 1; +var CLONE_FLAT_FLAG = 2; +var CLONE_SYMBOLS_FLAG = 4; +var argsTag3 = "[object Arguments]"; +var arrayTag2 = "[object Array]"; +var boolTag3 = "[object Boolean]"; +var dateTag3 = "[object Date]"; +var errorTag2 = "[object Error]"; +var funcTag3 = "[object Function]"; +var genTag2 = "[object GeneratorFunction]"; +var mapTag5 = "[object Map]"; +var numberTag3 = "[object Number]"; +var objectTag4 = "[object Object]"; +var regexpTag3 = "[object RegExp]"; +var setTag5 = "[object Set]"; +var stringTag3 = "[object String]"; +var symbolTag3 = "[object Symbol]"; +var weakMapTag3 = "[object WeakMap]"; +var arrayBufferTag3 = "[object ArrayBuffer]"; +var dataViewTag4 = "[object DataView]"; +var float32Tag3 = "[object Float32Array]"; +var float64Tag3 = "[object Float64Array]"; +var int8Tag3 = "[object Int8Array]"; +var int16Tag3 = "[object Int16Array]"; +var int32Tag3 = "[object Int32Array]"; +var uint8Tag3 = "[object Uint8Array]"; +var uint8ClampedTag3 = "[object Uint8ClampedArray]"; +var uint16Tag3 = "[object Uint16Array]"; +var uint32Tag3 = "[object Uint32Array]"; +var cloneableTags = {}; +cloneableTags[argsTag3] = cloneableTags[arrayTag2] = cloneableTags[arrayBufferTag3] = cloneableTags[dataViewTag4] = cloneableTags[boolTag3] = cloneableTags[dateTag3] = cloneableTags[float32Tag3] = cloneableTags[float64Tag3] = cloneableTags[int8Tag3] = cloneableTags[int16Tag3] = cloneableTags[int32Tag3] = cloneableTags[mapTag5] = cloneableTags[numberTag3] = cloneableTags[objectTag4] = cloneableTags[regexpTag3] = cloneableTags[setTag5] = cloneableTags[stringTag3] = cloneableTags[symbolTag3] = cloneableTags[uint8Tag3] = cloneableTags[uint8ClampedTag3] = cloneableTags[uint16Tag3] = cloneableTags[uint32Tag3] = true; +cloneableTags[errorTag2] = cloneableTags[funcTag3] = cloneableTags[weakMapTag3] = false; +function baseClone(value, bitmask, customizer, key, object, stack) { + var result, isDeep = bitmask & CLONE_DEEP_FLAG, isFlat = bitmask & CLONE_FLAT_FLAG, isFull = bitmask & CLONE_SYMBOLS_FLAG; + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== void 0) { + return result; + } + if (!isObject_default(value)) { + return value; + } + var isArr = isArray_default(value); + if (isArr) { + result = initCloneArray_default(value); + if (!isDeep) { + return copyArray_default(value, result); + } + } else { + var tag = getTag_default(value), isFunc = tag == funcTag3 || tag == genTag2; + if (isBuffer_default(value)) { + return cloneBuffer_default(value, isDeep); + } + if (tag == objectTag4 || tag == argsTag3 || isFunc && !object) { + result = isFlat || isFunc ? {} : initCloneObject_default(value); + if (!isDeep) { + return isFlat ? copySymbolsIn_default(value, baseAssignIn_default(result, value)) : copySymbols_default(value, baseAssign_default(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = initCloneByTag_default(value, tag, isDeep); + } + } + stack || (stack = new Stack_default()); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + if (isSet_default(value)) { + value.forEach(function(subValue) { + result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); + }); + } else if (isMap_default(value)) { + value.forEach(function(subValue, key2) { + result.set(key2, baseClone(subValue, bitmask, customizer, key2, value, stack)); + }); + } + var keysFunc = isFull ? isFlat ? getAllKeysIn_default : getAllKeys_default : isFlat ? keysIn_default : keys_default; + var props = isArr ? void 0 : keysFunc(value); + arrayEach_default(props || value, function(subValue, key2) { + if (props) { + key2 = subValue; + subValue = value[key2]; + } + assignValue_default(result, key2, baseClone(subValue, bitmask, customizer, key2, value, stack)); + }); + return result; +} +var baseClone_default = baseClone; + +// node_modules/lodash-es/cloneDeep.js +var CLONE_DEEP_FLAG2 = 1; +var CLONE_SYMBOLS_FLAG2 = 4; +function cloneDeep(value) { + return baseClone_default(value, CLONE_DEEP_FLAG2 | CLONE_SYMBOLS_FLAG2); +} +var cloneDeep_default = cloneDeep; + +// node_modules/lodash-es/_setCacheAdd.js +var HASH_UNDEFINED3 = "__lodash_hash_undefined__"; +function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED3); + return this; +} +var setCacheAdd_default = setCacheAdd; + +// node_modules/lodash-es/_setCacheHas.js +function setCacheHas(value) { + return this.__data__.has(value); +} +var setCacheHas_default = setCacheHas; + +// node_modules/lodash-es/_SetCache.js +function SetCache(values) { + var index = -1, length = values == null ? 0 : values.length; + this.__data__ = new MapCache_default(); + while (++index < length) { + this.add(values[index]); + } +} +SetCache.prototype.add = SetCache.prototype.push = setCacheAdd_default; +SetCache.prototype.has = setCacheHas_default; +var SetCache_default = SetCache; + +// node_modules/lodash-es/_arraySome.js +function arraySome(array, predicate) { + var index = -1, length = array == null ? 0 : array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; +} +var arraySome_default = arraySome; + +// node_modules/lodash-es/_cacheHas.js +function cacheHas(cache, key) { + return cache.has(key); +} +var cacheHas_default = cacheHas; + +// node_modules/lodash-es/_equalArrays.js +var COMPARE_PARTIAL_FLAG = 1; +var COMPARE_UNORDERED_FLAG = 2; +function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + var arrStacked = stack.get(array); + var othStacked = stack.get(other); + if (arrStacked && othStacked) { + return arrStacked == other && othStacked == array; + } + var index = -1, result = true, seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache_default() : void 0; + stack.set(array, other); + stack.set(other, array); + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index]; + if (customizer) { + var compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== void 0) { + if (compared) { + continue; + } + result = false; + break; + } + if (seen) { + if (!arraySome_default(other, function(othValue2, othIndex) { + if (!cacheHas_default(seen, othIndex) && (arrValue === othValue2 || equalFunc(arrValue, othValue2, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + result = false; + break; + } + } + stack["delete"](array); + stack["delete"](other); + return result; +} +var equalArrays_default = equalArrays; + +// node_modules/lodash-es/_mapToArray.js +function mapToArray(map) { + var index = -1, result = Array(map.size); + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; +} +var mapToArray_default = mapToArray; + +// node_modules/lodash-es/_setToArray.js +function setToArray(set2) { + var index = -1, result = Array(set2.size); + set2.forEach(function(value) { + result[++index] = value; + }); + return result; +} +var setToArray_default = setToArray; + +// node_modules/lodash-es/_equalByTag.js +var COMPARE_PARTIAL_FLAG2 = 1; +var COMPARE_UNORDERED_FLAG2 = 2; +var boolTag4 = "[object Boolean]"; +var dateTag4 = "[object Date]"; +var errorTag3 = "[object Error]"; +var mapTag6 = "[object Map]"; +var numberTag4 = "[object Number]"; +var regexpTag4 = "[object RegExp]"; +var setTag6 = "[object Set]"; +var stringTag4 = "[object String]"; +var symbolTag4 = "[object Symbol]"; +var arrayBufferTag4 = "[object ArrayBuffer]"; +var dataViewTag5 = "[object DataView]"; +var symbolProto3 = Symbol_default ? Symbol_default.prototype : void 0; +var symbolValueOf2 = symbolProto3 ? symbolProto3.valueOf : void 0; +function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag5: + if (object.byteLength != other.byteLength || object.byteOffset != other.byteOffset) { + return false; + } + object = object.buffer; + other = other.buffer; + case arrayBufferTag4: + if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array_default(object), new Uint8Array_default(other))) { + return false; + } + return true; + case boolTag4: + case dateTag4: + case numberTag4: + return eq_default(+object, +other); + case errorTag3: + return object.name == other.name && object.message == other.message; + case regexpTag4: + case stringTag4: + return object == other + ""; + case mapTag6: + var convert = mapToArray_default; + case setTag6: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG2; + convert || (convert = setToArray_default); + if (object.size != other.size && !isPartial) { + return false; + } + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG2; + stack.set(object, other); + var result = equalArrays_default(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack["delete"](object); + return result; + case symbolTag4: + if (symbolValueOf2) { + return symbolValueOf2.call(object) == symbolValueOf2.call(other); + } + } + return false; +} +var equalByTag_default = equalByTag; + +// node_modules/lodash-es/_equalObjects.js +var COMPARE_PARTIAL_FLAG3 = 1; +var objectProto15 = Object.prototype; +var hasOwnProperty12 = objectProto15.hasOwnProperty; +function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG3, objProps = getAllKeys_default(object), objLength = objProps.length, othProps = getAllKeys_default(other), othLength = othProps.length; + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty12.call(other, key))) { + return false; + } + } + var objStacked = stack.get(object); + var othStacked = stack.get(other); + if (objStacked && othStacked) { + return objStacked == other && othStacked == object; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key]; + if (customizer) { + var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack); + } + if (!(compared === void 0 ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared)) { + result = false; + break; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (result && !skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + result = false; + } + } + stack["delete"](object); + stack["delete"](other); + return result; +} +var equalObjects_default = equalObjects; + +// node_modules/lodash-es/_baseIsEqualDeep.js +var COMPARE_PARTIAL_FLAG4 = 1; +var argsTag4 = "[object Arguments]"; +var arrayTag3 = "[object Array]"; +var objectTag5 = "[object Object]"; +var objectProto16 = Object.prototype; +var hasOwnProperty13 = objectProto16.hasOwnProperty; +function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray_default(object), othIsArr = isArray_default(other), objTag = objIsArr ? arrayTag3 : getTag_default(object), othTag = othIsArr ? arrayTag3 : getTag_default(other); + objTag = objTag == argsTag4 ? objectTag5 : objTag; + othTag = othTag == argsTag4 ? objectTag5 : othTag; + var objIsObj = objTag == objectTag5, othIsObj = othTag == objectTag5, isSameTag = objTag == othTag; + if (isSameTag && isBuffer_default(object)) { + if (!isBuffer_default(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack_default()); + return objIsArr || isTypedArray_default(object) ? equalArrays_default(object, other, bitmask, customizer, equalFunc, stack) : equalByTag_default(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_FLAG4)) { + var objIsWrapped = objIsObj && hasOwnProperty13.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty13.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, othUnwrapped = othIsWrapped ? other.value() : other; + stack || (stack = new Stack_default()); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack_default()); + return equalObjects_default(object, other, bitmask, customizer, equalFunc, stack); +} +var baseIsEqualDeep_default = baseIsEqualDeep; + +// node_modules/lodash-es/_baseIsEqual.js +function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObjectLike_default(value) && !isObjectLike_default(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep_default(value, other, bitmask, customizer, baseIsEqual, stack); +} +var baseIsEqual_default = baseIsEqual; + +// node_modules/lodash-es/_hasPath.js +function hasPath(object, path, hasFunc) { + path = castPath_default(path, object); + var index = -1, length = path.length, result = false; + while (++index < length) { + var key = toKey_default(path[index]); + if (!(result = object != null && hasFunc(object, key))) { + break; + } + object = object[key]; + } + if (result || ++index != length) { + return result; + } + length = object == null ? 0 : object.length; + return !!length && isLength_default(length) && isIndex_default(key, length) && (isArray_default(object) || isArguments_default(object)); +} +var hasPath_default = hasPath; + +// node_modules/lodash-es/_createBaseFor.js +function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, iterable = Object(object), props = keysFunc(object), length = props.length; + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; +} +var createBaseFor_default = createBaseFor; + +// node_modules/lodash-es/_baseFor.js +var baseFor = createBaseFor_default(); +var baseFor_default = baseFor; + +// node_modules/lodash-es/now.js +var now = function() { + return root_default.Date.now(); +}; +var now_default = now; + +// node_modules/lodash-es/debounce.js +var FUNC_ERROR_TEXT2 = "Expected a function"; +var nativeMax2 = Math.max; +var nativeMin = Math.min; +function debounce(func, wait, options) { + var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT2); + } + wait = toNumber_default(wait) || 0; + if (isObject_default(options)) { + leading = !!options.leading; + maxing = "maxWait" in options; + maxWait = maxing ? nativeMax2(toNumber_default(options.maxWait) || 0, wait) : maxWait; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function invokeFunc(time) { + var args = lastArgs, thisArg = lastThis; + lastArgs = lastThis = void 0; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + function leadingEdge(time) { + lastInvokeTime = time; + timerId = setTimeout(timerExpired, wait); + return leading ? invokeFunc(time) : result; + } + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, timeWaiting = wait - timeSinceLastCall; + return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting; + } + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime; + return lastCallTime === void 0 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait; + } + function timerExpired() { + var time = now_default(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + timerId = setTimeout(timerExpired, remainingWait(time)); + } + function trailingEdge(time) { + timerId = void 0; + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = void 0; + return result; + } + function cancel() { + if (timerId !== void 0) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = void 0; + } + function flush() { + return timerId === void 0 ? result : trailingEdge(now_default()); + } + function debounced() { + var time = now_default(), isInvoking = shouldInvoke(time); + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + if (isInvoking) { + if (timerId === void 0) { + return leadingEdge(lastCallTime); + } + if (maxing) { + clearTimeout(timerId); + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === void 0) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; +} +var debounce_default = debounce; + +// node_modules/lodash-es/_assignMergeValue.js +function assignMergeValue(object, key, value) { + if (value !== void 0 && !eq_default(object[key], value) || value === void 0 && !(key in object)) { + baseAssignValue_default(object, key, value); + } +} +var assignMergeValue_default = assignMergeValue; + +// node_modules/lodash-es/isArrayLikeObject.js +function isArrayLikeObject(value) { + return isObjectLike_default(value) && isArrayLike_default(value); +} +var isArrayLikeObject_default = isArrayLikeObject; + +// node_modules/lodash-es/_safeGet.js +function safeGet(object, key) { + if (key === "constructor" && typeof object[key] === "function") { + return; + } + if (key == "__proto__") { + return; + } + return object[key]; +} +var safeGet_default = safeGet; + +// node_modules/lodash-es/toPlainObject.js +function toPlainObject(value) { + return copyObject_default(value, keysIn_default(value)); +} +var toPlainObject_default = toPlainObject; + +// node_modules/lodash-es/_baseMergeDeep.js +function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = safeGet_default(object, key), srcValue = safeGet_default(source, key), stacked = stack.get(srcValue); + if (stacked) { + assignMergeValue_default(object, key, stacked); + return; + } + var newValue = customizer ? customizer(objValue, srcValue, key + "", object, source, stack) : void 0; + var isCommon = newValue === void 0; + if (isCommon) { + var isArr = isArray_default(srcValue), isBuff = !isArr && isBuffer_default(srcValue), isTyped = !isArr && !isBuff && isTypedArray_default(srcValue); + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray_default(objValue)) { + newValue = objValue; + } else if (isArrayLikeObject_default(objValue)) { + newValue = copyArray_default(objValue); + } else if (isBuff) { + isCommon = false; + newValue = cloneBuffer_default(srcValue, true); + } else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray_default(srcValue, true); + } else { + newValue = []; + } + } else if (isPlainObject_default(srcValue) || isArguments_default(srcValue)) { + newValue = objValue; + if (isArguments_default(objValue)) { + newValue = toPlainObject_default(objValue); + } else if (!isObject_default(objValue) || isFunction_default(objValue)) { + newValue = initCloneObject_default(srcValue); + } + } else { + isCommon = false; + } + } + if (isCommon) { + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack["delete"](srcValue); + } + assignMergeValue_default(object, key, newValue); +} +var baseMergeDeep_default = baseMergeDeep; + +// node_modules/lodash-es/_baseMerge.js +function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor_default(source, function(srcValue, key) { + stack || (stack = new Stack_default()); + if (isObject_default(srcValue)) { + baseMergeDeep_default(object, source, key, srcIndex, baseMerge, customizer, stack); + } else { + var newValue = customizer ? customizer(safeGet_default(object, key), srcValue, key + "", object, source, stack) : void 0; + if (newValue === void 0) { + newValue = srcValue; + } + assignMergeValue_default(object, key, newValue); + } + }, keysIn_default); +} +var baseMerge_default = baseMerge; + +// node_modules/lodash-es/_escapeHtmlChar.js +var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'" +}; +var escapeHtmlChar = basePropertyOf_default(htmlEscapes); +var escapeHtmlChar_default = escapeHtmlChar; + +// node_modules/lodash-es/escape.js +var reUnescapedHtml = /[&<>"']/g; +var reHasUnescapedHtml = RegExp(reUnescapedHtml.source); +function escape2(string) { + string = toString_default(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar_default) : string; +} +var escape_default = escape2; + +// node_modules/lodash-es/_baseHas.js +var objectProto17 = Object.prototype; +var hasOwnProperty14 = objectProto17.hasOwnProperty; +function baseHas(object, key) { + return object != null && hasOwnProperty14.call(object, key); +} +var baseHas_default = baseHas; + +// node_modules/lodash-es/has.js +function has(object, path) { + return object != null && hasPath_default(object, path, baseHas_default); +} +var has_default = has; + +// node_modules/lodash-es/isEqual.js +function isEqual(value, other) { + return baseIsEqual_default(value, other); +} +var isEqual_default = isEqual; + +// node_modules/lodash-es/merge.js +var merge = createAssigner_default(function(object, source, srcIndex) { + baseMerge_default(object, source, srcIndex); +}); +var merge_default = merge; + +// node_modules/lodash-es/_baseSet.js +function baseSet(object, path, value, customizer) { + if (!isObject_default(object)) { + return object; + } + path = castPath_default(path, object); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = toKey_default(path[index]), newValue = value; + if (key === "__proto__" || key === "constructor" || key === "prototype") { + return object; + } + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : void 0; + if (newValue === void 0) { + newValue = isObject_default(objValue) ? objValue : isIndex_default(path[index + 1]) ? [] : {}; + } + } + assignValue_default(nested, key, newValue); + nested = nested[key]; + } + return object; +} +var baseSet_default = baseSet; + +// node_modules/lodash-es/set.js +function set(object, path, value) { + return object == null ? object : baseSet_default(object, path, value); +} +var set_default = set; + +// node_modules/@inertiajs/core/dist/index.esm.js +var qs = __toESM(require_lib(), 1); + +// node_modules/axios/lib/helpers/bind.js +function bind(fn, thisArg) { + return function wrap() { + return fn.apply(thisArg, arguments); + }; +} + +// node_modules/axios/lib/utils.js +var { toString: toString2 } = Object.prototype; +var { getPrototypeOf } = Object; +var { iterator, toStringTag } = Symbol; +var kindOf = /* @__PURE__ */ ((cache) => (thing) => { + const str = toString2.call(thing); + return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase()); +})(/* @__PURE__ */ Object.create(null)); +var kindOfTest = (type) => { + type = type.toLowerCase(); + return (thing) => kindOf(thing) === type; +}; +var typeOfTest = (type) => (thing) => typeof thing === type; +var { isArray: isArray2 } = Array; +var isUndefined = typeOfTest("undefined"); +function isBuffer2(val) { + return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor) && isFunction2(val.constructor.isBuffer) && val.constructor.isBuffer(val); +} +var isArrayBuffer = kindOfTest("ArrayBuffer"); +function isArrayBufferView(val) { + let result; + if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView) { + result = ArrayBuffer.isView(val); + } else { + result = val && val.buffer && isArrayBuffer(val.buffer); + } + return result; +} +var isString = typeOfTest("string"); +var isFunction2 = typeOfTest("function"); +var isNumber = typeOfTest("number"); +var isObject2 = (thing) => thing !== null && typeof thing === "object"; +var isBoolean = (thing) => thing === true || thing === false; +var isPlainObject2 = (val) => { + if (kindOf(val) !== "object") { + return false; + } + const prototype2 = getPrototypeOf(val); + return (prototype2 === null || prototype2 === Object.prototype || Object.getPrototypeOf(prototype2) === null) && !(toStringTag in val) && !(iterator in val); +}; +var isEmptyObject = (val) => { + if (!isObject2(val) || isBuffer2(val)) { + return false; + } + try { + return Object.keys(val).length === 0 && Object.getPrototypeOf(val) === Object.prototype; + } catch (e) { + return false; + } +}; +var isDate = kindOfTest("Date"); +var isFile = kindOfTest("File"); +var isReactNativeBlob = (value) => { + return !!(value && typeof value.uri !== "undefined"); +}; +var isReactNative = (formData) => formData && typeof formData.getParts !== "undefined"; +var isBlob = kindOfTest("Blob"); +var isFileList = kindOfTest("FileList"); +var isStream = (val) => isObject2(val) && isFunction2(val.pipe); +function getGlobal() { + if (typeof globalThis !== "undefined") return globalThis; + if (typeof self !== "undefined") return self; + if (typeof window !== "undefined") return window; + if (typeof global !== "undefined") return global; + return {}; +} +var G = getGlobal(); +var FormDataCtor = typeof G.FormData !== "undefined" ? G.FormData : void 0; +var isFormData = (thing) => { + let kind; + return thing && (FormDataCtor && thing instanceof FormDataCtor || isFunction2(thing.append) && ((kind = kindOf(thing)) === "formdata" || // detect form-data instance + kind === "object" && isFunction2(thing.toString) && thing.toString() === "[object FormData]")); +}; +var isURLSearchParams = kindOfTest("URLSearchParams"); +var [isReadableStream, isRequest, isResponse, isHeaders] = [ + "ReadableStream", + "Request", + "Response", + "Headers" +].map(kindOfTest); +var trim = (str) => { + return str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ""); +}; +function forEach(obj, fn, { allOwnKeys = false } = {}) { + if (obj === null || typeof obj === "undefined") { + return; + } + let i; + let l; + if (typeof obj !== "object") { + obj = [obj]; + } + if (isArray2(obj)) { + for (i = 0, l = obj.length; i < l; i++) { + fn.call(null, obj[i], i, obj); + } + } else { + if (isBuffer2(obj)) { + return; + } + const keys2 = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj); + const len = keys2.length; + let key; + for (i = 0; i < len; i++) { + key = keys2[i]; + fn.call(null, obj[key], key, obj); + } + } +} +function findKey(obj, key) { + if (isBuffer2(obj)) { + return null; + } + key = key.toLowerCase(); + const keys2 = Object.keys(obj); + let i = keys2.length; + let _key; + while (i-- > 0) { + _key = keys2[i]; + if (key === _key.toLowerCase()) { + return _key; + } + } + return null; +} +var _global = (() => { + if (typeof globalThis !== "undefined") return globalThis; + return typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : global; +})(); +var isContextDefined = (context) => !isUndefined(context) && context !== _global; +function merge2() { + const { caseless, skipUndefined } = isContextDefined(this) && this || {}; + const result = {}; + const assignValue2 = (val, key) => { + if (key === "__proto__" || key === "constructor" || key === "prototype") { + return; + } + const targetKey = caseless && findKey(result, key) || key; + if (isPlainObject2(result[targetKey]) && isPlainObject2(val)) { + result[targetKey] = merge2(result[targetKey], val); + } else if (isPlainObject2(val)) { + result[targetKey] = merge2({}, val); + } else if (isArray2(val)) { + result[targetKey] = val.slice(); + } else if (!skipUndefined || !isUndefined(val)) { + result[targetKey] = val; + } + }; + for (let i = 0, l = arguments.length; i < l; i++) { + arguments[i] && forEach(arguments[i], assignValue2); + } + return result; +} +var extend = (a, b, thisArg, { allOwnKeys } = {}) => { + forEach( + b, + (val, key) => { + if (thisArg && isFunction2(val)) { + Object.defineProperty(a, key, { + value: bind(val, thisArg), + writable: true, + enumerable: true, + configurable: true + }); + } else { + Object.defineProperty(a, key, { + value: val, + writable: true, + enumerable: true, + configurable: true + }); + } + }, + { allOwnKeys } + ); + return a; +}; +var stripBOM = (content) => { + if (content.charCodeAt(0) === 65279) { + content = content.slice(1); + } + return content; +}; +var inherits = (constructor, superConstructor, props, descriptors) => { + constructor.prototype = Object.create(superConstructor.prototype, descriptors); + Object.defineProperty(constructor.prototype, "constructor", { + value: constructor, + writable: true, + enumerable: false, + configurable: true + }); + Object.defineProperty(constructor, "super", { + value: superConstructor.prototype + }); + props && Object.assign(constructor.prototype, props); +}; +var toFlatObject = (sourceObj, destObj, filter2, propFilter) => { + let props; + let i; + let prop; + const merged = {}; + destObj = destObj || {}; + if (sourceObj == null) return destObj; + do { + props = Object.getOwnPropertyNames(sourceObj); + i = props.length; + while (i-- > 0) { + prop = props[i]; + if ((!propFilter || propFilter(prop, sourceObj, destObj)) && !merged[prop]) { + destObj[prop] = sourceObj[prop]; + merged[prop] = true; + } + } + sourceObj = filter2 !== false && getPrototypeOf(sourceObj); + } while (sourceObj && (!filter2 || filter2(sourceObj, destObj)) && sourceObj !== Object.prototype); + return destObj; +}; +var endsWith = (str, searchString, position) => { + str = String(str); + if (position === void 0 || position > str.length) { + position = str.length; + } + position -= searchString.length; + const lastIndex = str.indexOf(searchString, position); + return lastIndex !== -1 && lastIndex === position; +}; +var toArray = (thing) => { + if (!thing) return null; + if (isArray2(thing)) return thing; + let i = thing.length; + if (!isNumber(i)) return null; + const arr = new Array(i); + while (i-- > 0) { + arr[i] = thing[i]; + } + return arr; +}; +var isTypedArray2 = /* @__PURE__ */ ((TypedArray) => { + return (thing) => { + return TypedArray && thing instanceof TypedArray; + }; +})(typeof Uint8Array !== "undefined" && getPrototypeOf(Uint8Array)); +var forEachEntry = (obj, fn) => { + const generator = obj && obj[iterator]; + const _iterator = generator.call(obj); + let result; + while ((result = _iterator.next()) && !result.done) { + const pair = result.value; + fn.call(obj, pair[0], pair[1]); + } +}; +var matchAll = (regExp, str) => { + let matches; + const arr = []; + while ((matches = regExp.exec(str)) !== null) { + arr.push(matches); + } + return arr; +}; +var isHTMLForm = kindOfTest("HTMLFormElement"); +var toCamelCase = (str) => { + return str.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g, function replacer(m, p1, p2) { + return p1.toUpperCase() + p2; + }); +}; +var hasOwnProperty15 = (({ hasOwnProperty: hasOwnProperty16 }) => (obj, prop) => hasOwnProperty16.call(obj, prop))(Object.prototype); +var isRegExp = kindOfTest("RegExp"); +var reduceDescriptors = (obj, reducer) => { + const descriptors = Object.getOwnPropertyDescriptors(obj); + const reducedDescriptors = {}; + forEach(descriptors, (descriptor, name) => { + let ret; + if ((ret = reducer(descriptor, name, obj)) !== false) { + reducedDescriptors[name] = ret || descriptor; + } + }); + Object.defineProperties(obj, reducedDescriptors); +}; +var freezeMethods = (obj) => { + reduceDescriptors(obj, (descriptor, name) => { + if (isFunction2(obj) && ["arguments", "caller", "callee"].indexOf(name) !== -1) { + return false; + } + const value = obj[name]; + if (!isFunction2(value)) return; + descriptor.enumerable = false; + if ("writable" in descriptor) { + descriptor.writable = false; + return; + } + if (!descriptor.set) { + descriptor.set = () => { + throw Error("Can not rewrite read-only method '" + name + "'"); + }; + } + }); +}; +var toObjectSet = (arrayOrString, delimiter) => { + const obj = {}; + const define = (arr) => { + arr.forEach((value) => { + obj[value] = true; + }); + }; + isArray2(arrayOrString) ? define(arrayOrString) : define(String(arrayOrString).split(delimiter)); + return obj; +}; +var noop = () => { +}; +var toFiniteNumber = (value, defaultValue) => { + return value != null && Number.isFinite(value = +value) ? value : defaultValue; +}; +function isSpecCompliantForm(thing) { + return !!(thing && isFunction2(thing.append) && thing[toStringTag] === "FormData" && thing[iterator]); +} +var toJSONObject = (obj) => { + const stack = new Array(10); + const visit = (source, i) => { + if (isObject2(source)) { + if (stack.indexOf(source) >= 0) { + return; + } + if (isBuffer2(source)) { + return source; + } + if (!("toJSON" in source)) { + stack[i] = source; + const target = isArray2(source) ? [] : {}; + forEach(source, (value, key) => { + const reducedValue = visit(value, i + 1); + !isUndefined(reducedValue) && (target[key] = reducedValue); + }); + stack[i] = void 0; + return target; + } + } + return source; + }; + return visit(obj, 0); +}; +var isAsyncFn = kindOfTest("AsyncFunction"); +var isThenable = (thing) => thing && (isObject2(thing) || isFunction2(thing)) && isFunction2(thing.then) && isFunction2(thing.catch); +var _setImmediate = ((setImmediateSupported, postMessageSupported) => { + if (setImmediateSupported) { + return setImmediate; + } + return postMessageSupported ? ((token, callbacks) => { + _global.addEventListener( + "message", + ({ source, data }) => { + if (source === _global && data === token) { + callbacks.length && callbacks.shift()(); + } + }, + false + ); + return (cb) => { + callbacks.push(cb); + _global.postMessage(token, "*"); + }; + })(`axios@${Math.random()}`, []) : (cb) => setTimeout(cb); +})(typeof setImmediate === "function", isFunction2(_global.postMessage)); +var asap = typeof queueMicrotask !== "undefined" ? queueMicrotask.bind(_global) : typeof process !== "undefined" && process.nextTick || _setImmediate; +var isIterable = (thing) => thing != null && isFunction2(thing[iterator]); +var utils_default = { + isArray: isArray2, + isArrayBuffer, + isBuffer: isBuffer2, + isFormData, + isArrayBufferView, + isString, + isNumber, + isBoolean, + isObject: isObject2, + isPlainObject: isPlainObject2, + isEmptyObject, + isReadableStream, + isRequest, + isResponse, + isHeaders, + isUndefined, + isDate, + isFile, + isReactNativeBlob, + isReactNative, + isBlob, + isRegExp, + isFunction: isFunction2, + isStream, + isURLSearchParams, + isTypedArray: isTypedArray2, + isFileList, + forEach, + merge: merge2, + extend, + trim, + stripBOM, + inherits, + toFlatObject, + kindOf, + kindOfTest, + endsWith, + toArray, + forEachEntry, + matchAll, + isHTMLForm, + hasOwnProperty: hasOwnProperty15, + hasOwnProp: hasOwnProperty15, + // an alias to avoid ESLint no-prototype-builtins detection + reduceDescriptors, + freezeMethods, + toObjectSet, + toCamelCase, + noop, + toFiniteNumber, + findKey, + global: _global, + isContextDefined, + isSpecCompliantForm, + toJSONObject, + isAsyncFn, + isThenable, + setImmediate: _setImmediate, + asap, + isIterable +}; + +// node_modules/axios/lib/core/AxiosError.js +var AxiosError = class _AxiosError extends Error { + static from(error, code, config3, request2, response, customProps) { + const axiosError = new _AxiosError(error.message, code || error.code, config3, request2, response); + axiosError.cause = error; + axiosError.name = error.name; + if (error.status != null && axiosError.status == null) { + axiosError.status = error.status; + } + customProps && Object.assign(axiosError, customProps); + return axiosError; + } + /** + * Create an Error with the specified message, config, error code, request and response. + * + * @param {string} message The error message. + * @param {string} [code] The error code (for example, 'ECONNABORTED'). + * @param {Object} [config] The config. + * @param {Object} [request] The request. + * @param {Object} [response] The response. + * + * @returns {Error} The created error. + */ + constructor(message, code, config3, request2, response) { + super(message); + Object.defineProperty(this, "message", { + value: message, + enumerable: true, + writable: true, + configurable: true + }); + this.name = "AxiosError"; + this.isAxiosError = true; + code && (this.code = code); + config3 && (this.config = config3); + request2 && (this.request = request2); + if (response) { + this.response = response; + this.status = response.status; + } + } + toJSON() { + return { + // Standard + message: this.message, + name: this.name, + // Microsoft + description: this.description, + number: this.number, + // Mozilla + fileName: this.fileName, + lineNumber: this.lineNumber, + columnNumber: this.columnNumber, + stack: this.stack, + // Axios + config: utils_default.toJSONObject(this.config), + code: this.code, + status: this.status + }; + } +}; +AxiosError.ERR_BAD_OPTION_VALUE = "ERR_BAD_OPTION_VALUE"; +AxiosError.ERR_BAD_OPTION = "ERR_BAD_OPTION"; +AxiosError.ECONNABORTED = "ECONNABORTED"; +AxiosError.ETIMEDOUT = "ETIMEDOUT"; +AxiosError.ERR_NETWORK = "ERR_NETWORK"; +AxiosError.ERR_FR_TOO_MANY_REDIRECTS = "ERR_FR_TOO_MANY_REDIRECTS"; +AxiosError.ERR_DEPRECATED = "ERR_DEPRECATED"; +AxiosError.ERR_BAD_RESPONSE = "ERR_BAD_RESPONSE"; +AxiosError.ERR_BAD_REQUEST = "ERR_BAD_REQUEST"; +AxiosError.ERR_CANCELED = "ERR_CANCELED"; +AxiosError.ERR_NOT_SUPPORT = "ERR_NOT_SUPPORT"; +AxiosError.ERR_INVALID_URL = "ERR_INVALID_URL"; +var AxiosError_default = AxiosError; + +// node_modules/axios/lib/helpers/null.js +var null_default = null; + +// node_modules/axios/lib/helpers/toFormData.js +function isVisitable(thing) { + return utils_default.isPlainObject(thing) || utils_default.isArray(thing); +} +function removeBrackets(key) { + return utils_default.endsWith(key, "[]") ? key.slice(0, -2) : key; +} +function renderKey(path, key, dots) { + if (!path) return key; + return path.concat(key).map(function each(token, i) { + token = removeBrackets(token); + return !dots && i ? "[" + token + "]" : token; + }).join(dots ? "." : ""); +} +function isFlatArray(arr) { + return utils_default.isArray(arr) && !arr.some(isVisitable); +} +var predicates = utils_default.toFlatObject(utils_default, {}, null, function filter(prop) { + return /^is[A-Z]/.test(prop); +}); +function toFormData(obj, formData, options) { + if (!utils_default.isObject(obj)) { + throw new TypeError("target must be an object"); + } + formData = formData || new (null_default || FormData)(); + options = utils_default.toFlatObject( + options, + { + metaTokens: true, + dots: false, + indexes: false + }, + false, + function defined(option, source) { + return !utils_default.isUndefined(source[option]); + } + ); + const metaTokens = options.metaTokens; + const visitor = options.visitor || defaultVisitor; + const dots = options.dots; + const indexes = options.indexes; + const _Blob = options.Blob || typeof Blob !== "undefined" && Blob; + const useBlob = _Blob && utils_default.isSpecCompliantForm(formData); + if (!utils_default.isFunction(visitor)) { + throw new TypeError("visitor must be a function"); + } + function convertValue(value) { + if (value === null) return ""; + if (utils_default.isDate(value)) { + return value.toISOString(); + } + if (utils_default.isBoolean(value)) { + return value.toString(); + } + if (!useBlob && utils_default.isBlob(value)) { + throw new AxiosError_default("Blob is not supported. Use a Buffer instead."); + } + if (utils_default.isArrayBuffer(value) || utils_default.isTypedArray(value)) { + return useBlob && typeof Blob === "function" ? new Blob([value]) : Buffer.from(value); + } + return value; + } + function defaultVisitor(value, key, path) { + let arr = value; + if (utils_default.isReactNative(formData) && utils_default.isReactNativeBlob(value)) { + formData.append(renderKey(path, key, dots), convertValue(value)); + return false; + } + if (value && !path && typeof value === "object") { + if (utils_default.endsWith(key, "{}")) { + key = metaTokens ? key : key.slice(0, -2); + value = JSON.stringify(value); + } else if (utils_default.isArray(value) && isFlatArray(value) || (utils_default.isFileList(value) || utils_default.endsWith(key, "[]")) && (arr = utils_default.toArray(value))) { + key = removeBrackets(key); + arr.forEach(function each(el, index) { + !(utils_default.isUndefined(el) || el === null) && formData.append( + // eslint-disable-next-line no-nested-ternary + indexes === true ? renderKey([key], index, dots) : indexes === null ? key : key + "[]", + convertValue(el) + ); + }); + return false; + } + } + if (isVisitable(value)) { + return true; + } + formData.append(renderKey(path, key, dots), convertValue(value)); + return false; + } + const stack = []; + const exposedHelpers = Object.assign(predicates, { + defaultVisitor, + convertValue, + isVisitable + }); + function build(value, path) { + if (utils_default.isUndefined(value)) return; + if (stack.indexOf(value) !== -1) { + throw Error("Circular reference detected in " + path.join(".")); + } + stack.push(value); + utils_default.forEach(value, function each(el, key) { + const result = !(utils_default.isUndefined(el) || el === null) && visitor.call(formData, el, utils_default.isString(key) ? key.trim() : key, path, exposedHelpers); + if (result === true) { + build(el, path ? path.concat(key) : [key]); + } + }); + stack.pop(); + } + if (!utils_default.isObject(obj)) { + throw new TypeError("data must be an object"); + } + build(obj); + return formData; +} +var toFormData_default = toFormData; + +// node_modules/axios/lib/helpers/AxiosURLSearchParams.js +function encode(str) { + const charMap = { + "!": "%21", + "'": "%27", + "(": "%28", + ")": "%29", + "~": "%7E", + "%20": "+", + "%00": "\0" + }; + return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) { + return charMap[match]; + }); +} +function AxiosURLSearchParams(params, options) { + this._pairs = []; + params && toFormData_default(params, this, options); +} +var prototype = AxiosURLSearchParams.prototype; +prototype.append = function append(name, value) { + this._pairs.push([name, value]); +}; +prototype.toString = function toString3(encoder) { + const _encode = encoder ? function(value) { + return encoder.call(this, value, encode); + } : encode; + return this._pairs.map(function each(pair) { + return _encode(pair[0]) + "=" + _encode(pair[1]); + }, "").join("&"); +}; +var AxiosURLSearchParams_default = AxiosURLSearchParams; + +// node_modules/axios/lib/helpers/buildURL.js +function encode2(val) { + return encodeURIComponent(val).replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%20/g, "+"); +} +function buildURL(url, params, options) { + if (!params) { + return url; + } + const _encode = options && options.encode || encode2; + const _options = utils_default.isFunction(options) ? { + serialize: options + } : options; + const serializeFn = _options && _options.serialize; + let serializedParams; + if (serializeFn) { + serializedParams = serializeFn(params, _options); + } else { + serializedParams = utils_default.isURLSearchParams(params) ? params.toString() : new AxiosURLSearchParams_default(params, _options).toString(_encode); + } + if (serializedParams) { + const hashmarkIndex = url.indexOf("#"); + if (hashmarkIndex !== -1) { + url = url.slice(0, hashmarkIndex); + } + url += (url.indexOf("?") === -1 ? "?" : "&") + serializedParams; + } + return url; +} + +// node_modules/axios/lib/core/InterceptorManager.js +var InterceptorManager = class { + constructor() { + this.handlers = []; + } + /** + * Add a new interceptor to the stack + * + * @param {Function} fulfilled The function to handle `then` for a `Promise` + * @param {Function} rejected The function to handle `reject` for a `Promise` + * @param {Object} options The options for the interceptor, synchronous and runWhen + * + * @return {Number} An ID used to remove interceptor later + */ + use(fulfilled, rejected, options) { + this.handlers.push({ + fulfilled, + rejected, + synchronous: options ? options.synchronous : false, + runWhen: options ? options.runWhen : null + }); + return this.handlers.length - 1; + } + /** + * Remove an interceptor from the stack + * + * @param {Number} id The ID that was returned by `use` + * + * @returns {void} + */ + eject(id) { + if (this.handlers[id]) { + this.handlers[id] = null; + } + } + /** + * Clear all interceptors from the stack + * + * @returns {void} + */ + clear() { + if (this.handlers) { + this.handlers = []; + } + } + /** + * Iterate over all the registered interceptors + * + * This method is particularly useful for skipping over any + * interceptors that may have become `null` calling `eject`. + * + * @param {Function} fn The function to call for each interceptor + * + * @returns {void} + */ + forEach(fn) { + utils_default.forEach(this.handlers, function forEachHandler(h) { + if (h !== null) { + fn(h); + } + }); + } +}; +var InterceptorManager_default = InterceptorManager; + +// node_modules/axios/lib/defaults/transitional.js +var transitional_default = { + silentJSONParsing: true, + forcedJSONParsing: true, + clarifyTimeoutError: false, + legacyInterceptorReqResOrdering: true +}; + +// node_modules/axios/lib/platform/browser/classes/URLSearchParams.js +var URLSearchParams_default = typeof URLSearchParams !== "undefined" ? URLSearchParams : AxiosURLSearchParams_default; + +// node_modules/axios/lib/platform/browser/classes/FormData.js +var FormData_default = typeof FormData !== "undefined" ? FormData : null; + +// node_modules/axios/lib/platform/browser/classes/Blob.js +var Blob_default = typeof Blob !== "undefined" ? Blob : null; + +// node_modules/axios/lib/platform/browser/index.js +var browser_default = { + isBrowser: true, + classes: { + URLSearchParams: URLSearchParams_default, + FormData: FormData_default, + Blob: Blob_default + }, + protocols: ["http", "https", "file", "blob", "url", "data"] +}; + +// node_modules/axios/lib/platform/common/utils.js +var utils_exports = {}; +__export(utils_exports, { + hasBrowserEnv: () => hasBrowserEnv, + hasStandardBrowserEnv: () => hasStandardBrowserEnv, + hasStandardBrowserWebWorkerEnv: () => hasStandardBrowserWebWorkerEnv, + navigator: () => _navigator, + origin: () => origin +}); +var hasBrowserEnv = typeof window !== "undefined" && typeof document !== "undefined"; +var _navigator = typeof navigator === "object" && navigator || void 0; +var hasStandardBrowserEnv = hasBrowserEnv && (!_navigator || ["ReactNative", "NativeScript", "NS"].indexOf(_navigator.product) < 0); +var hasStandardBrowserWebWorkerEnv = (() => { + return typeof WorkerGlobalScope !== "undefined" && // eslint-disable-next-line no-undef + self instanceof WorkerGlobalScope && typeof self.importScripts === "function"; +})(); +var origin = hasBrowserEnv && window.location.href || "http://localhost"; + +// node_modules/axios/lib/platform/index.js +var platform_default = { + ...utils_exports, + ...browser_default +}; + +// node_modules/axios/lib/helpers/toURLEncodedForm.js +function toURLEncodedForm(data, options) { + return toFormData_default(data, new platform_default.classes.URLSearchParams(), { + visitor: function(value, key, path, helpers) { + if (platform_default.isNode && utils_default.isBuffer(value)) { + this.append(key, value.toString("base64")); + return false; + } + return helpers.defaultVisitor.apply(this, arguments); + }, + ...options + }); +} + +// node_modules/axios/lib/helpers/formDataToJSON.js +function parsePropPath(name) { + return utils_default.matchAll(/\w+|\[(\w*)]/g, name).map((match) => { + return match[0] === "[]" ? "" : match[1] || match[0]; + }); +} +function arrayToObject(arr) { + const obj = {}; + const keys2 = Object.keys(arr); + let i; + const len = keys2.length; + let key; + for (i = 0; i < len; i++) { + key = keys2[i]; + obj[key] = arr[key]; + } + return obj; +} +function formDataToJSON(formData) { + function buildPath(path, value, target, index) { + let name = path[index++]; + if (name === "__proto__") return true; + const isNumericKey = Number.isFinite(+name); + const isLast = index >= path.length; + name = !name && utils_default.isArray(target) ? target.length : name; + if (isLast) { + if (utils_default.hasOwnProp(target, name)) { + target[name] = [target[name], value]; + } else { + target[name] = value; + } + return !isNumericKey; + } + if (!target[name] || !utils_default.isObject(target[name])) { + target[name] = []; + } + const result = buildPath(path, value, target[name], index); + if (result && utils_default.isArray(target[name])) { + target[name] = arrayToObject(target[name]); + } + return !isNumericKey; + } + if (utils_default.isFormData(formData) && utils_default.isFunction(formData.entries)) { + const obj = {}; + utils_default.forEachEntry(formData, (name, value) => { + buildPath(parsePropPath(name), value, obj, 0); + }); + return obj; + } + return null; +} +var formDataToJSON_default = formDataToJSON; + +// node_modules/axios/lib/defaults/index.js +function stringifySafely(rawValue, parser, encoder) { + if (utils_default.isString(rawValue)) { + try { + (parser || JSON.parse)(rawValue); + return utils_default.trim(rawValue); + } catch (e) { + if (e.name !== "SyntaxError") { + throw e; + } + } + } + return (encoder || JSON.stringify)(rawValue); +} +var defaults = { + transitional: transitional_default, + adapter: ["xhr", "http", "fetch"], + transformRequest: [ + function transformRequest(data, headers) { + const contentType = headers.getContentType() || ""; + const hasJSONContentType = contentType.indexOf("application/json") > -1; + const isObjectPayload = utils_default.isObject(data); + if (isObjectPayload && utils_default.isHTMLForm(data)) { + data = new FormData(data); + } + const isFormData3 = utils_default.isFormData(data); + if (isFormData3) { + return hasJSONContentType ? JSON.stringify(formDataToJSON_default(data)) : data; + } + if (utils_default.isArrayBuffer(data) || utils_default.isBuffer(data) || utils_default.isStream(data) || utils_default.isFile(data) || utils_default.isBlob(data) || utils_default.isReadableStream(data)) { + return data; + } + if (utils_default.isArrayBufferView(data)) { + return data.buffer; + } + if (utils_default.isURLSearchParams(data)) { + headers.setContentType("application/x-www-form-urlencoded;charset=utf-8", false); + return data.toString(); + } + let isFileList2; + if (isObjectPayload) { + if (contentType.indexOf("application/x-www-form-urlencoded") > -1) { + return toURLEncodedForm(data, this.formSerializer).toString(); + } + if ((isFileList2 = utils_default.isFileList(data)) || contentType.indexOf("multipart/form-data") > -1) { + const _FormData = this.env && this.env.FormData; + return toFormData_default( + isFileList2 ? { "files[]": data } : data, + _FormData && new _FormData(), + this.formSerializer + ); + } + } + if (isObjectPayload || hasJSONContentType) { + headers.setContentType("application/json", false); + return stringifySafely(data); + } + return data; + } + ], + transformResponse: [ + function transformResponse(data) { + const transitional2 = this.transitional || defaults.transitional; + const forcedJSONParsing = transitional2 && transitional2.forcedJSONParsing; + const JSONRequested = this.responseType === "json"; + if (utils_default.isResponse(data) || utils_default.isReadableStream(data)) { + return data; + } + if (data && utils_default.isString(data) && (forcedJSONParsing && !this.responseType || JSONRequested)) { + const silentJSONParsing = transitional2 && transitional2.silentJSONParsing; + const strictJSONParsing = !silentJSONParsing && JSONRequested; + try { + return JSON.parse(data, this.parseReviver); + } catch (e) { + if (strictJSONParsing) { + if (e.name === "SyntaxError") { + throw AxiosError_default.from(e, AxiosError_default.ERR_BAD_RESPONSE, this, null, this.response); + } + throw e; + } + } + } + return data; + } + ], + /** + * A timeout in milliseconds to abort a request. If set to 0 (default) a + * timeout is not created. + */ + timeout: 0, + xsrfCookieName: "XSRF-TOKEN", + xsrfHeaderName: "X-XSRF-TOKEN", + maxContentLength: -1, + maxBodyLength: -1, + env: { + FormData: platform_default.classes.FormData, + Blob: platform_default.classes.Blob + }, + validateStatus: function validateStatus(status2) { + return status2 >= 200 && status2 < 300; + }, + headers: { + common: { + Accept: "application/json, text/plain, */*", + "Content-Type": void 0 + } + } +}; +utils_default.forEach(["delete", "get", "head", "post", "put", "patch"], (method) => { + defaults.headers[method] = {}; +}); +var defaults_default = defaults; + +// node_modules/axios/lib/helpers/parseHeaders.js +var ignoreDuplicateOf = utils_default.toObjectSet([ + "age", + "authorization", + "content-length", + "content-type", + "etag", + "expires", + "from", + "host", + "if-modified-since", + "if-unmodified-since", + "last-modified", + "location", + "max-forwards", + "proxy-authorization", + "referer", + "retry-after", + "user-agent" +]); +var parseHeaders_default = (rawHeaders) => { + const parsed = {}; + let key; + let val; + let i; + rawHeaders && rawHeaders.split("\n").forEach(function parser(line) { + i = line.indexOf(":"); + key = line.substring(0, i).trim().toLowerCase(); + val = line.substring(i + 1).trim(); + if (!key || parsed[key] && ignoreDuplicateOf[key]) { + return; + } + if (key === "set-cookie") { + if (parsed[key]) { + parsed[key].push(val); + } else { + parsed[key] = [val]; + } + } else { + parsed[key] = parsed[key] ? parsed[key] + ", " + val : val; + } + }); + return parsed; +}; + +// node_modules/axios/lib/core/AxiosHeaders.js +var $internals = Symbol("internals"); +function normalizeHeader(header) { + return header && String(header).trim().toLowerCase(); +} +function normalizeValue(value) { + if (value === false || value == null) { + return value; + } + return utils_default.isArray(value) ? value.map(normalizeValue) : String(value); +} +function parseTokens(str) { + const tokens = /* @__PURE__ */ Object.create(null); + const tokensRE = /([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g; + let match; + while (match = tokensRE.exec(str)) { + tokens[match[1]] = match[2]; + } + return tokens; +} +var isValidHeaderName = (str) => /^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(str.trim()); +function matchHeaderValue(context, value, header, filter2, isHeaderNameFilter) { + if (utils_default.isFunction(filter2)) { + return filter2.call(this, value, header); + } + if (isHeaderNameFilter) { + value = header; + } + if (!utils_default.isString(value)) return; + if (utils_default.isString(filter2)) { + return value.indexOf(filter2) !== -1; + } + if (utils_default.isRegExp(filter2)) { + return filter2.test(value); + } +} +function formatHeader(header) { + return header.trim().toLowerCase().replace(/([a-z\d])(\w*)/g, (w, char, str) => { + return char.toUpperCase() + str; + }); +} +function buildAccessors(obj, header) { + const accessorName = utils_default.toCamelCase(" " + header); + ["get", "set", "has"].forEach((methodName) => { + Object.defineProperty(obj, methodName + accessorName, { + value: function(arg1, arg2, arg3) { + return this[methodName].call(this, header, arg1, arg2, arg3); + }, + configurable: true + }); + }); +} +var AxiosHeaders = class { + constructor(headers) { + headers && this.set(headers); + } + set(header, valueOrRewrite, rewrite) { + const self2 = this; + function setHeader(_value, _header, _rewrite) { + const lHeader = normalizeHeader(_header); + if (!lHeader) { + throw new Error("header name must be a non-empty string"); + } + const key = utils_default.findKey(self2, lHeader); + if (!key || self2[key] === void 0 || _rewrite === true || _rewrite === void 0 && self2[key] !== false) { + self2[key || _header] = normalizeValue(_value); + } + } + const setHeaders = (headers, _rewrite) => utils_default.forEach(headers, (_value, _header) => setHeader(_value, _header, _rewrite)); + if (utils_default.isPlainObject(header) || header instanceof this.constructor) { + setHeaders(header, valueOrRewrite); + } else if (utils_default.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) { + setHeaders(parseHeaders_default(header), valueOrRewrite); + } else if (utils_default.isObject(header) && utils_default.isIterable(header)) { + let obj = {}, dest, key; + for (const entry of header) { + if (!utils_default.isArray(entry)) { + throw TypeError("Object iterator must return a key-value pair"); + } + obj[key = entry[0]] = (dest = obj[key]) ? utils_default.isArray(dest) ? [...dest, entry[1]] : [dest, entry[1]] : entry[1]; + } + setHeaders(obj, valueOrRewrite); + } else { + header != null && setHeader(valueOrRewrite, header, rewrite); + } + return this; + } + get(header, parser) { + header = normalizeHeader(header); + if (header) { + const key = utils_default.findKey(this, header); + if (key) { + const value = this[key]; + if (!parser) { + return value; + } + if (parser === true) { + return parseTokens(value); + } + if (utils_default.isFunction(parser)) { + return parser.call(this, value, key); + } + if (utils_default.isRegExp(parser)) { + return parser.exec(value); + } + throw new TypeError("parser must be boolean|regexp|function"); + } + } + } + has(header, matcher) { + header = normalizeHeader(header); + if (header) { + const key = utils_default.findKey(this, header); + return !!(key && this[key] !== void 0 && (!matcher || matchHeaderValue(this, this[key], key, matcher))); + } + return false; + } + delete(header, matcher) { + const self2 = this; + let deleted = false; + function deleteHeader(_header) { + _header = normalizeHeader(_header); + if (_header) { + const key = utils_default.findKey(self2, _header); + if (key && (!matcher || matchHeaderValue(self2, self2[key], key, matcher))) { + delete self2[key]; + deleted = true; + } + } + } + if (utils_default.isArray(header)) { + header.forEach(deleteHeader); + } else { + deleteHeader(header); + } + return deleted; + } + clear(matcher) { + const keys2 = Object.keys(this); + let i = keys2.length; + let deleted = false; + while (i--) { + const key = keys2[i]; + if (!matcher || matchHeaderValue(this, this[key], key, matcher, true)) { + delete this[key]; + deleted = true; + } + } + return deleted; + } + normalize(format) { + const self2 = this; + const headers = {}; + utils_default.forEach(this, (value, header) => { + const key = utils_default.findKey(headers, header); + if (key) { + self2[key] = normalizeValue(value); + delete self2[header]; + return; + } + const normalized = format ? formatHeader(header) : String(header).trim(); + if (normalized !== header) { + delete self2[header]; + } + self2[normalized] = normalizeValue(value); + headers[normalized] = true; + }); + return this; + } + concat(...targets) { + return this.constructor.concat(this, ...targets); + } + toJSON(asStrings) { + const obj = /* @__PURE__ */ Object.create(null); + utils_default.forEach(this, (value, header) => { + value != null && value !== false && (obj[header] = asStrings && utils_default.isArray(value) ? value.join(", ") : value); + }); + return obj; + } + [Symbol.iterator]() { + return Object.entries(this.toJSON())[Symbol.iterator](); + } + toString() { + return Object.entries(this.toJSON()).map(([header, value]) => header + ": " + value).join("\n"); + } + getSetCookie() { + return this.get("set-cookie") || []; + } + get [Symbol.toStringTag]() { + return "AxiosHeaders"; + } + static from(thing) { + return thing instanceof this ? thing : new this(thing); + } + static concat(first, ...targets) { + const computed = new this(first); + targets.forEach((target) => computed.set(target)); + return computed; + } + static accessor(header) { + const internals = this[$internals] = this[$internals] = { + accessors: {} + }; + const accessors = internals.accessors; + const prototype2 = this.prototype; + function defineAccessor(_header) { + const lHeader = normalizeHeader(_header); + if (!accessors[lHeader]) { + buildAccessors(prototype2, _header); + accessors[lHeader] = true; + } + } + utils_default.isArray(header) ? header.forEach(defineAccessor) : defineAccessor(header); + return this; + } +}; +AxiosHeaders.accessor([ + "Content-Type", + "Content-Length", + "Accept", + "Accept-Encoding", + "User-Agent", + "Authorization" +]); +utils_default.reduceDescriptors(AxiosHeaders.prototype, ({ value }, key) => { + let mapped = key[0].toUpperCase() + key.slice(1); + return { + get: () => value, + set(headerValue) { + this[mapped] = headerValue; + } + }; +}); +utils_default.freezeMethods(AxiosHeaders); +var AxiosHeaders_default = AxiosHeaders; + +// node_modules/axios/lib/core/transformData.js +function transformData(fns, response) { + const config3 = this || defaults_default; + const context = response || config3; + const headers = AxiosHeaders_default.from(context.headers); + let data = context.data; + utils_default.forEach(fns, function transform(fn) { + data = fn.call(config3, data, headers.normalize(), response ? response.status : void 0); + }); + headers.normalize(); + return data; +} + +// node_modules/axios/lib/cancel/isCancel.js +function isCancel(value) { + return !!(value && value.__CANCEL__); +} + +// node_modules/axios/lib/cancel/CanceledError.js +var CanceledError = class extends AxiosError_default { + /** + * A `CanceledError` is an object that is thrown when an operation is canceled. + * + * @param {string=} message The message. + * @param {Object=} config The config. + * @param {Object=} request The request. + * + * @returns {CanceledError} The created error. + */ + constructor(message, config3, request2) { + super(message == null ? "canceled" : message, AxiosError_default.ERR_CANCELED, config3, request2); + this.name = "CanceledError"; + this.__CANCEL__ = true; + } +}; +var CanceledError_default = CanceledError; + +// node_modules/axios/lib/core/settle.js +function settle(resolve, reject, response) { + const validateStatus2 = response.config.validateStatus; + if (!response.status || !validateStatus2 || validateStatus2(response.status)) { + resolve(response); + } else { + reject( + new AxiosError_default( + "Request failed with status code " + response.status, + [AxiosError_default.ERR_BAD_REQUEST, AxiosError_default.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4], + response.config, + response.request, + response + ) + ); + } +} + +// node_modules/axios/lib/helpers/parseProtocol.js +function parseProtocol(url) { + const match = /^([-+\w]{1,25})(:?\/\/|:)/.exec(url); + return match && match[1] || ""; +} + +// node_modules/axios/lib/helpers/speedometer.js +function speedometer(samplesCount, min) { + samplesCount = samplesCount || 10; + const bytes = new Array(samplesCount); + const timestamps = new Array(samplesCount); + let head = 0; + let tail = 0; + let firstSampleTS; + min = min !== void 0 ? min : 1e3; + return function push(chunkLength) { + const now2 = Date.now(); + const startedAt = timestamps[tail]; + if (!firstSampleTS) { + firstSampleTS = now2; + } + bytes[head] = chunkLength; + timestamps[head] = now2; + let i = tail; + let bytesCount = 0; + while (i !== head) { + bytesCount += bytes[i++]; + i = i % samplesCount; + } + head = (head + 1) % samplesCount; + if (head === tail) { + tail = (tail + 1) % samplesCount; + } + if (now2 - firstSampleTS < min) { + return; + } + const passed = startedAt && now2 - startedAt; + return passed ? Math.round(bytesCount * 1e3 / passed) : void 0; + }; +} +var speedometer_default = speedometer; + +// node_modules/axios/lib/helpers/throttle.js +function throttle(fn, freq) { + let timestamp = 0; + let threshold = 1e3 / freq; + let lastArgs; + let timer; + const invoke = (args, now2 = Date.now()) => { + timestamp = now2; + lastArgs = null; + if (timer) { + clearTimeout(timer); + timer = null; + } + fn(...args); + }; + const throttled = (...args) => { + const now2 = Date.now(); + const passed = now2 - timestamp; + if (passed >= threshold) { + invoke(args, now2); + } else { + lastArgs = args; + if (!timer) { + timer = setTimeout(() => { + timer = null; + invoke(lastArgs); + }, threshold - passed); + } + } + }; + const flush = () => lastArgs && invoke(lastArgs); + return [throttled, flush]; +} +var throttle_default = throttle; + +// node_modules/axios/lib/helpers/progressEventReducer.js +var progressEventReducer = (listener, isDownloadStream, freq = 3) => { + let bytesNotified = 0; + const _speedometer = speedometer_default(50, 250); + return throttle_default((e) => { + const loaded = e.loaded; + const total = e.lengthComputable ? e.total : void 0; + const progressBytes = loaded - bytesNotified; + const rate = _speedometer(progressBytes); + const inRange = loaded <= total; + bytesNotified = loaded; + const data = { + loaded, + total, + progress: total ? loaded / total : void 0, + bytes: progressBytes, + rate: rate ? rate : void 0, + estimated: rate && total && inRange ? (total - loaded) / rate : void 0, + event: e, + lengthComputable: total != null, + [isDownloadStream ? "download" : "upload"]: true + }; + listener(data); + }, freq); +}; +var progressEventDecorator = (total, throttled) => { + const lengthComputable = total != null; + return [ + (loaded) => throttled[0]({ + lengthComputable, + total, + loaded + }), + throttled[1] + ]; +}; +var asyncDecorator = (fn) => (...args) => utils_default.asap(() => fn(...args)); + +// node_modules/axios/lib/helpers/isURLSameOrigin.js +var isURLSameOrigin_default = platform_default.hasStandardBrowserEnv ? /* @__PURE__ */ ((origin2, isMSIE) => (url) => { + url = new URL(url, platform_default.origin); + return origin2.protocol === url.protocol && origin2.host === url.host && (isMSIE || origin2.port === url.port); +})( + new URL(platform_default.origin), + platform_default.navigator && /(msie|trident)/i.test(platform_default.navigator.userAgent) +) : () => true; + +// node_modules/axios/lib/helpers/cookies.js +var cookies_default = platform_default.hasStandardBrowserEnv ? ( + // Standard browser envs support document.cookie + { + write(name, value, expires, path, domain, secure, sameSite) { + if (typeof document === "undefined") return; + const cookie = [`${name}=${encodeURIComponent(value)}`]; + if (utils_default.isNumber(expires)) { + cookie.push(`expires=${new Date(expires).toUTCString()}`); + } + if (utils_default.isString(path)) { + cookie.push(`path=${path}`); + } + if (utils_default.isString(domain)) { + cookie.push(`domain=${domain}`); + } + if (secure === true) { + cookie.push("secure"); + } + if (utils_default.isString(sameSite)) { + cookie.push(`SameSite=${sameSite}`); + } + document.cookie = cookie.join("; "); + }, + read(name) { + if (typeof document === "undefined") return null; + const match = document.cookie.match(new RegExp("(?:^|; )" + name + "=([^;]*)")); + return match ? decodeURIComponent(match[1]) : null; + }, + remove(name) { + this.write(name, "", Date.now() - 864e5, "/"); + } + } +) : ( + // Non-standard browser env (web workers, react-native) lack needed support. + { + write() { + }, + read() { + return null; + }, + remove() { + } + } +); + +// node_modules/axios/lib/helpers/isAbsoluteURL.js +function isAbsoluteURL(url) { + if (typeof url !== "string") { + return false; + } + return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url); +} + +// node_modules/axios/lib/helpers/combineURLs.js +function combineURLs(baseURL, relativeURL) { + return relativeURL ? baseURL.replace(/\/?\/$/, "") + "/" + relativeURL.replace(/^\/+/, "") : baseURL; +} + +// node_modules/axios/lib/core/buildFullPath.js +function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) { + let isRelativeUrl = !isAbsoluteURL(requestedURL); + if (baseURL && (isRelativeUrl || allowAbsoluteUrls == false)) { + return combineURLs(baseURL, requestedURL); + } + return requestedURL; +} + +// node_modules/axios/lib/core/mergeConfig.js +var headersToObject = (thing) => thing instanceof AxiosHeaders_default ? { ...thing } : thing; +function mergeConfig(config1, config22) { + config22 = config22 || {}; + const config3 = {}; + function getMergedValue(target, source, prop, caseless) { + if (utils_default.isPlainObject(target) && utils_default.isPlainObject(source)) { + return utils_default.merge.call({ caseless }, target, source); + } else if (utils_default.isPlainObject(source)) { + return utils_default.merge({}, source); + } else if (utils_default.isArray(source)) { + return source.slice(); + } + return source; + } + function mergeDeepProperties(a, b, prop, caseless) { + if (!utils_default.isUndefined(b)) { + return getMergedValue(a, b, prop, caseless); + } else if (!utils_default.isUndefined(a)) { + return getMergedValue(void 0, a, prop, caseless); + } + } + function valueFromConfig2(a, b) { + if (!utils_default.isUndefined(b)) { + return getMergedValue(void 0, b); + } + } + function defaultToConfig2(a, b) { + if (!utils_default.isUndefined(b)) { + return getMergedValue(void 0, b); + } else if (!utils_default.isUndefined(a)) { + return getMergedValue(void 0, a); + } + } + function mergeDirectKeys(a, b, prop) { + if (prop in config22) { + return getMergedValue(a, b); + } else if (prop in config1) { + return getMergedValue(void 0, a); + } + } + const mergeMap = { + url: valueFromConfig2, + method: valueFromConfig2, + data: valueFromConfig2, + baseURL: defaultToConfig2, + transformRequest: defaultToConfig2, + transformResponse: defaultToConfig2, + paramsSerializer: defaultToConfig2, + timeout: defaultToConfig2, + timeoutMessage: defaultToConfig2, + withCredentials: defaultToConfig2, + withXSRFToken: defaultToConfig2, + adapter: defaultToConfig2, + responseType: defaultToConfig2, + xsrfCookieName: defaultToConfig2, + xsrfHeaderName: defaultToConfig2, + onUploadProgress: defaultToConfig2, + onDownloadProgress: defaultToConfig2, + decompress: defaultToConfig2, + maxContentLength: defaultToConfig2, + maxBodyLength: defaultToConfig2, + beforeRedirect: defaultToConfig2, + transport: defaultToConfig2, + httpAgent: defaultToConfig2, + httpsAgent: defaultToConfig2, + cancelToken: defaultToConfig2, + socketPath: defaultToConfig2, + responseEncoding: defaultToConfig2, + validateStatus: mergeDirectKeys, + headers: (a, b, prop) => mergeDeepProperties(headersToObject(a), headersToObject(b), prop, true) + }; + utils_default.forEach(Object.keys({ ...config1, ...config22 }), function computeConfigValue(prop) { + if (prop === "__proto__" || prop === "constructor" || prop === "prototype") return; + const merge3 = utils_default.hasOwnProp(mergeMap, prop) ? mergeMap[prop] : mergeDeepProperties; + const configValue = merge3(config1[prop], config22[prop], prop); + utils_default.isUndefined(configValue) && merge3 !== mergeDirectKeys || (config3[prop] = configValue); + }); + return config3; +} + +// node_modules/axios/lib/helpers/resolveConfig.js +var resolveConfig_default = (config3) => { + const newConfig = mergeConfig({}, config3); + let { data, withXSRFToken, xsrfHeaderName, xsrfCookieName, headers, auth } = newConfig; + newConfig.headers = headers = AxiosHeaders_default.from(headers); + newConfig.url = buildURL( + buildFullPath(newConfig.baseURL, newConfig.url, newConfig.allowAbsoluteUrls), + config3.params, + config3.paramsSerializer + ); + if (auth) { + headers.set( + "Authorization", + "Basic " + btoa( + (auth.username || "") + ":" + (auth.password ? unescape(encodeURIComponent(auth.password)) : "") + ) + ); + } + if (utils_default.isFormData(data)) { + if (platform_default.hasStandardBrowserEnv || platform_default.hasStandardBrowserWebWorkerEnv) { + headers.setContentType(void 0); + } else if (utils_default.isFunction(data.getHeaders)) { + const formHeaders = data.getHeaders(); + const allowedHeaders = ["content-type", "content-length"]; + Object.entries(formHeaders).forEach(([key, val]) => { + if (allowedHeaders.includes(key.toLowerCase())) { + headers.set(key, val); + } + }); + } + } + if (platform_default.hasStandardBrowserEnv) { + withXSRFToken && utils_default.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig)); + if (withXSRFToken || withXSRFToken !== false && isURLSameOrigin_default(newConfig.url)) { + const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies_default.read(xsrfCookieName); + if (xsrfValue) { + headers.set(xsrfHeaderName, xsrfValue); + } + } + } + return newConfig; +}; + +// node_modules/axios/lib/adapters/xhr.js +var isXHRAdapterSupported = typeof XMLHttpRequest !== "undefined"; +var xhr_default = isXHRAdapterSupported && function(config3) { + return new Promise(function dispatchXhrRequest(resolve, reject) { + const _config = resolveConfig_default(config3); + let requestData = _config.data; + const requestHeaders = AxiosHeaders_default.from(_config.headers).normalize(); + let { responseType, onUploadProgress, onDownloadProgress } = _config; + let onCanceled; + let uploadThrottled, downloadThrottled; + let flushUpload, flushDownload; + function done2() { + flushUpload && flushUpload(); + flushDownload && flushDownload(); + _config.cancelToken && _config.cancelToken.unsubscribe(onCanceled); + _config.signal && _config.signal.removeEventListener("abort", onCanceled); + } + let request2 = new XMLHttpRequest(); + request2.open(_config.method.toUpperCase(), _config.url, true); + request2.timeout = _config.timeout; + function onloadend() { + if (!request2) { + return; + } + const responseHeaders = AxiosHeaders_default.from( + "getAllResponseHeaders" in request2 && request2.getAllResponseHeaders() + ); + const responseData = !responseType || responseType === "text" || responseType === "json" ? request2.responseText : request2.response; + const response = { + data: responseData, + status: request2.status, + statusText: request2.statusText, + headers: responseHeaders, + config: config3, + request: request2 + }; + settle( + function _resolve(value) { + resolve(value); + done2(); + }, + function _reject(err) { + reject(err); + done2(); + }, + response + ); + request2 = null; + } + if ("onloadend" in request2) { + request2.onloadend = onloadend; + } else { + request2.onreadystatechange = function handleLoad() { + if (!request2 || request2.readyState !== 4) { + return; + } + if (request2.status === 0 && !(request2.responseURL && request2.responseURL.indexOf("file:") === 0)) { + return; + } + setTimeout(onloadend); + }; + } + request2.onabort = function handleAbort() { + if (!request2) { + return; + } + reject(new AxiosError_default("Request aborted", AxiosError_default.ECONNABORTED, config3, request2)); + request2 = null; + }; + request2.onerror = function handleError(event) { + const msg = event && event.message ? event.message : "Network Error"; + const err = new AxiosError_default(msg, AxiosError_default.ERR_NETWORK, config3, request2); + err.event = event || null; + reject(err); + request2 = null; + }; + request2.ontimeout = function handleTimeout() { + let timeoutErrorMessage = _config.timeout ? "timeout of " + _config.timeout + "ms exceeded" : "timeout exceeded"; + const transitional2 = _config.transitional || transitional_default; + if (_config.timeoutErrorMessage) { + timeoutErrorMessage = _config.timeoutErrorMessage; + } + reject( + new AxiosError_default( + timeoutErrorMessage, + transitional2.clarifyTimeoutError ? AxiosError_default.ETIMEDOUT : AxiosError_default.ECONNABORTED, + config3, + request2 + ) + ); + request2 = null; + }; + requestData === void 0 && requestHeaders.setContentType(null); + if ("setRequestHeader" in request2) { + utils_default.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) { + request2.setRequestHeader(key, val); + }); + } + if (!utils_default.isUndefined(_config.withCredentials)) { + request2.withCredentials = !!_config.withCredentials; + } + if (responseType && responseType !== "json") { + request2.responseType = _config.responseType; + } + if (onDownloadProgress) { + [downloadThrottled, flushDownload] = progressEventReducer(onDownloadProgress, true); + request2.addEventListener("progress", downloadThrottled); + } + if (onUploadProgress && request2.upload) { + [uploadThrottled, flushUpload] = progressEventReducer(onUploadProgress); + request2.upload.addEventListener("progress", uploadThrottled); + request2.upload.addEventListener("loadend", flushUpload); + } + if (_config.cancelToken || _config.signal) { + onCanceled = (cancel) => { + if (!request2) { + return; + } + reject(!cancel || cancel.type ? new CanceledError_default(null, config3, request2) : cancel); + request2.abort(); + request2 = null; + }; + _config.cancelToken && _config.cancelToken.subscribe(onCanceled); + if (_config.signal) { + _config.signal.aborted ? onCanceled() : _config.signal.addEventListener("abort", onCanceled); + } + } + const protocol = parseProtocol(_config.url); + if (protocol && platform_default.protocols.indexOf(protocol) === -1) { + reject( + new AxiosError_default( + "Unsupported protocol " + protocol + ":", + AxiosError_default.ERR_BAD_REQUEST, + config3 + ) + ); + return; + } + request2.send(requestData || null); + }); +}; + +// node_modules/axios/lib/helpers/composeSignals.js +var composeSignals = (signals, timeout) => { + const { length } = signals = signals ? signals.filter(Boolean) : []; + if (timeout || length) { + let controller = new AbortController(); + let aborted; + const onabort = function(reason) { + if (!aborted) { + aborted = true; + unsubscribe(); + const err = reason instanceof Error ? reason : this.reason; + controller.abort( + err instanceof AxiosError_default ? err : new CanceledError_default(err instanceof Error ? err.message : err) + ); + } + }; + let timer = timeout && setTimeout(() => { + timer = null; + onabort(new AxiosError_default(`timeout of ${timeout}ms exceeded`, AxiosError_default.ETIMEDOUT)); + }, timeout); + const unsubscribe = () => { + if (signals) { + timer && clearTimeout(timer); + timer = null; + signals.forEach((signal2) => { + signal2.unsubscribe ? signal2.unsubscribe(onabort) : signal2.removeEventListener("abort", onabort); + }); + signals = null; + } + }; + signals.forEach((signal2) => signal2.addEventListener("abort", onabort)); + const { signal } = controller; + signal.unsubscribe = () => utils_default.asap(unsubscribe); + return signal; + } +}; +var composeSignals_default = composeSignals; + +// node_modules/axios/lib/helpers/trackStream.js +var streamChunk = function* (chunk, chunkSize) { + let len = chunk.byteLength; + if (!chunkSize || len < chunkSize) { + yield chunk; + return; + } + let pos = 0; + let end; + while (pos < len) { + end = pos + chunkSize; + yield chunk.slice(pos, end); + pos = end; + } +}; +var readBytes = async function* (iterable, chunkSize) { + for await (const chunk of readStream(iterable)) { + yield* streamChunk(chunk, chunkSize); + } +}; +var readStream = async function* (stream) { + if (stream[Symbol.asyncIterator]) { + yield* stream; + return; + } + const reader = stream.getReader(); + try { + for (; ; ) { + const { done: done2, value } = await reader.read(); + if (done2) { + break; + } + yield value; + } + } finally { + await reader.cancel(); + } +}; +var trackStream = (stream, chunkSize, onProgress, onFinish) => { + const iterator2 = readBytes(stream, chunkSize); + let bytes = 0; + let done2; + let _onFinish = (e) => { + if (!done2) { + done2 = true; + onFinish && onFinish(e); + } + }; + return new ReadableStream( + { + async pull(controller) { + try { + const { done: done3, value } = await iterator2.next(); + if (done3) { + _onFinish(); + controller.close(); + return; + } + let len = value.byteLength; + if (onProgress) { + let loadedBytes = bytes += len; + onProgress(loadedBytes); + } + controller.enqueue(new Uint8Array(value)); + } catch (err) { + _onFinish(err); + throw err; + } + }, + cancel(reason) { + _onFinish(reason); + return iterator2.return(); + } + }, + { + highWaterMark: 2 + } + ); +}; + +// node_modules/axios/lib/adapters/fetch.js +var DEFAULT_CHUNK_SIZE = 64 * 1024; +var { isFunction: isFunction3 } = utils_default; +var globalFetchAPI = (({ Request: Request2, Response: Response2 }) => ({ + Request: Request2, + Response: Response2 +}))(utils_default.global); +var { ReadableStream: ReadableStream2, TextEncoder: TextEncoder2 } = utils_default.global; +var test = (fn, ...args) => { + try { + return !!fn(...args); + } catch (e) { + return false; + } +}; +var factory = (env) => { + env = utils_default.merge.call( + { + skipUndefined: true + }, + globalFetchAPI, + env + ); + const { fetch: envFetch, Request: Request2, Response: Response2 } = env; + const isFetchSupported = envFetch ? isFunction3(envFetch) : typeof fetch === "function"; + const isRequestSupported = isFunction3(Request2); + const isResponseSupported = isFunction3(Response2); + if (!isFetchSupported) { + return false; + } + const isReadableStreamSupported = isFetchSupported && isFunction3(ReadableStream2); + const encodeText = isFetchSupported && (typeof TextEncoder2 === "function" ? /* @__PURE__ */ ((encoder) => (str) => encoder.encode(str))(new TextEncoder2()) : async (str) => new Uint8Array(await new Request2(str).arrayBuffer())); + const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => { + let duplexAccessed = false; + const hasContentType = new Request2(platform_default.origin, { + body: new ReadableStream2(), + method: "POST", + get duplex() { + duplexAccessed = true; + return "half"; + } + }).headers.has("Content-Type"); + return duplexAccessed && !hasContentType; + }); + const supportsResponseStream = isResponseSupported && isReadableStreamSupported && test(() => utils_default.isReadableStream(new Response2("").body)); + const resolvers = { + stream: supportsResponseStream && ((res) => res.body) + }; + isFetchSupported && (() => { + ["text", "arrayBuffer", "blob", "formData", "stream"].forEach((type) => { + !resolvers[type] && (resolvers[type] = (res, config3) => { + let method = res && res[type]; + if (method) { + return method.call(res); + } + throw new AxiosError_default( + `Response type '${type}' is not supported`, + AxiosError_default.ERR_NOT_SUPPORT, + config3 + ); + }); + }); + })(); + const getBodyLength = async (body) => { + if (body == null) { + return 0; + } + if (utils_default.isBlob(body)) { + return body.size; + } + if (utils_default.isSpecCompliantForm(body)) { + const _request = new Request2(platform_default.origin, { + method: "POST", + body + }); + return (await _request.arrayBuffer()).byteLength; + } + if (utils_default.isArrayBufferView(body) || utils_default.isArrayBuffer(body)) { + return body.byteLength; + } + if (utils_default.isURLSearchParams(body)) { + body = body + ""; + } + if (utils_default.isString(body)) { + return (await encodeText(body)).byteLength; + } + }; + const resolveBodyLength = async (headers, body) => { + const length = utils_default.toFiniteNumber(headers.getContentLength()); + return length == null ? getBodyLength(body) : length; + }; + return async (config3) => { + let { + url, + method, + data, + signal, + cancelToken, + timeout, + onDownloadProgress, + onUploadProgress, + responseType, + headers, + withCredentials = "same-origin", + fetchOptions + } = resolveConfig_default(config3); + let _fetch = envFetch || fetch; + responseType = responseType ? (responseType + "").toLowerCase() : "text"; + let composedSignal = composeSignals_default( + [signal, cancelToken && cancelToken.toAbortSignal()], + timeout + ); + let request2 = null; + const unsubscribe = composedSignal && composedSignal.unsubscribe && (() => { + composedSignal.unsubscribe(); + }); + let requestContentLength; + try { + if (onUploadProgress && supportsRequestStream && method !== "get" && method !== "head" && (requestContentLength = await resolveBodyLength(headers, data)) !== 0) { + let _request = new Request2(url, { + method: "POST", + body: data, + duplex: "half" + }); + let contentTypeHeader; + if (utils_default.isFormData(data) && (contentTypeHeader = _request.headers.get("content-type"))) { + headers.setContentType(contentTypeHeader); + } + if (_request.body) { + const [onProgress, flush] = progressEventDecorator( + requestContentLength, + progressEventReducer(asyncDecorator(onUploadProgress)) + ); + data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush); + } + } + if (!utils_default.isString(withCredentials)) { + withCredentials = withCredentials ? "include" : "omit"; + } + const isCredentialsSupported = isRequestSupported && "credentials" in Request2.prototype; + const resolvedOptions = { + ...fetchOptions, + signal: composedSignal, + method: method.toUpperCase(), + headers: headers.normalize().toJSON(), + body: data, + duplex: "half", + credentials: isCredentialsSupported ? withCredentials : void 0 + }; + request2 = isRequestSupported && new Request2(url, resolvedOptions); + let response = await (isRequestSupported ? _fetch(request2, fetchOptions) : _fetch(url, resolvedOptions)); + const isStreamResponse = supportsResponseStream && (responseType === "stream" || responseType === "response"); + if (supportsResponseStream && (onDownloadProgress || isStreamResponse && unsubscribe)) { + const options = {}; + ["status", "statusText", "headers"].forEach((prop) => { + options[prop] = response[prop]; + }); + const responseContentLength = utils_default.toFiniteNumber(response.headers.get("content-length")); + const [onProgress, flush] = onDownloadProgress && progressEventDecorator( + responseContentLength, + progressEventReducer(asyncDecorator(onDownloadProgress), true) + ) || []; + response = new Response2( + trackStream(response.body, DEFAULT_CHUNK_SIZE, onProgress, () => { + flush && flush(); + unsubscribe && unsubscribe(); + }), + options + ); + } + responseType = responseType || "text"; + let responseData = await resolvers[utils_default.findKey(resolvers, responseType) || "text"]( + response, + config3 + ); + !isStreamResponse && unsubscribe && unsubscribe(); + return await new Promise((resolve, reject) => { + settle(resolve, reject, { + data: responseData, + headers: AxiosHeaders_default.from(response.headers), + status: response.status, + statusText: response.statusText, + config: config3, + request: request2 + }); + }); + } catch (err) { + unsubscribe && unsubscribe(); + if (err && err.name === "TypeError" && /Load failed|fetch/i.test(err.message)) { + throw Object.assign( + new AxiosError_default( + "Network Error", + AxiosError_default.ERR_NETWORK, + config3, + request2, + err && err.response + ), + { + cause: err.cause || err + } + ); + } + throw AxiosError_default.from(err, err && err.code, config3, request2, err && err.response); + } + }; +}; +var seedCache = /* @__PURE__ */ new Map(); +var getFetch = (config3) => { + let env = config3 && config3.env || {}; + const { fetch: fetch2, Request: Request2, Response: Response2 } = env; + const seeds = [Request2, Response2, fetch2]; + let len = seeds.length, i = len, seed, target, map = seedCache; + while (i--) { + seed = seeds[i]; + target = map.get(seed); + target === void 0 && map.set(seed, target = i ? /* @__PURE__ */ new Map() : factory(env)); + map = target; + } + return target; +}; +var adapter = getFetch(); + +// node_modules/axios/lib/adapters/adapters.js +var knownAdapters = { + http: null_default, + xhr: xhr_default, + fetch: { + get: getFetch + } +}; +utils_default.forEach(knownAdapters, (fn, value) => { + if (fn) { + try { + Object.defineProperty(fn, "name", { value }); + } catch (e) { + } + Object.defineProperty(fn, "adapterName", { value }); + } +}); +var renderReason = (reason) => `- ${reason}`; +var isResolvedHandle = (adapter2) => utils_default.isFunction(adapter2) || adapter2 === null || adapter2 === false; +function getAdapter(adapters, config3) { + adapters = utils_default.isArray(adapters) ? adapters : [adapters]; + const { length } = adapters; + let nameOrAdapter; + let adapter2; + const rejectedReasons = {}; + for (let i = 0; i < length; i++) { + nameOrAdapter = adapters[i]; + let id; + adapter2 = nameOrAdapter; + if (!isResolvedHandle(nameOrAdapter)) { + adapter2 = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()]; + if (adapter2 === void 0) { + throw new AxiosError_default(`Unknown adapter '${id}'`); + } + } + if (adapter2 && (utils_default.isFunction(adapter2) || (adapter2 = adapter2.get(config3)))) { + break; + } + rejectedReasons[id || "#" + i] = adapter2; + } + if (!adapter2) { + const reasons = Object.entries(rejectedReasons).map( + ([id, state]) => `adapter ${id} ` + (state === false ? "is not supported by the environment" : "is not available in the build") + ); + let s = length ? reasons.length > 1 ? "since :\n" + reasons.map(renderReason).join("\n") : " " + renderReason(reasons[0]) : "as no adapter specified"; + throw new AxiosError_default( + `There is no suitable adapter to dispatch the request ` + s, + "ERR_NOT_SUPPORT" + ); + } + return adapter2; +} +var adapters_default = { + /** + * Resolve an adapter from a list of adapter names or functions. + * @type {Function} + */ + getAdapter, + /** + * Exposes all known adapters + * @type {Object} + */ + adapters: knownAdapters +}; + +// node_modules/axios/lib/core/dispatchRequest.js +function throwIfCancellationRequested(config3) { + if (config3.cancelToken) { + config3.cancelToken.throwIfRequested(); + } + if (config3.signal && config3.signal.aborted) { + throw new CanceledError_default(null, config3); + } +} +function dispatchRequest(config3) { + throwIfCancellationRequested(config3); + config3.headers = AxiosHeaders_default.from(config3.headers); + config3.data = transformData.call(config3, config3.transformRequest); + if (["post", "put", "patch"].indexOf(config3.method) !== -1) { + config3.headers.setContentType("application/x-www-form-urlencoded", false); + } + const adapter2 = adapters_default.getAdapter(config3.adapter || defaults_default.adapter, config3); + return adapter2(config3).then( + function onAdapterResolution(response) { + throwIfCancellationRequested(config3); + response.data = transformData.call(config3, config3.transformResponse, response); + response.headers = AxiosHeaders_default.from(response.headers); + return response; + }, + function onAdapterRejection(reason) { + if (!isCancel(reason)) { + throwIfCancellationRequested(config3); + if (reason && reason.response) { + reason.response.data = transformData.call( + config3, + config3.transformResponse, + reason.response + ); + reason.response.headers = AxiosHeaders_default.from(reason.response.headers); + } + } + return Promise.reject(reason); + } + ); +} + +// node_modules/axios/lib/env/data.js +var VERSION = "1.13.6"; + +// node_modules/axios/lib/helpers/validator.js +var validators = {}; +["object", "boolean", "number", "function", "string", "symbol"].forEach((type, i) => { + validators[type] = function validator(thing) { + return typeof thing === type || "a" + (i < 1 ? "n " : " ") + type; + }; +}); +var deprecatedWarnings = {}; +validators.transitional = function transitional(validator, version, message) { + function formatMessage(opt, desc) { + return "[Axios v" + VERSION + "] Transitional option '" + opt + "'" + desc + (message ? ". " + message : ""); + } + return (value, opt, opts) => { + if (validator === false) { + throw new AxiosError_default( + formatMessage(opt, " has been removed" + (version ? " in " + version : "")), + AxiosError_default.ERR_DEPRECATED + ); + } + if (version && !deprecatedWarnings[opt]) { + deprecatedWarnings[opt] = true; + console.warn( + formatMessage( + opt, + " has been deprecated since v" + version + " and will be removed in the near future" + ) + ); + } + return validator ? validator(value, opt, opts) : true; + }; +}; +validators.spelling = function spelling(correctSpelling) { + return (value, opt) => { + console.warn(`${opt} is likely a misspelling of ${correctSpelling}`); + return true; + }; +}; +function assertOptions(options, schema, allowUnknown) { + if (typeof options !== "object") { + throw new AxiosError_default("options must be an object", AxiosError_default.ERR_BAD_OPTION_VALUE); + } + const keys2 = Object.keys(options); + let i = keys2.length; + while (i-- > 0) { + const opt = keys2[i]; + const validator = schema[opt]; + if (validator) { + const value = options[opt]; + const result = value === void 0 || validator(value, opt, options); + if (result !== true) { + throw new AxiosError_default( + "option " + opt + " must be " + result, + AxiosError_default.ERR_BAD_OPTION_VALUE + ); + } + continue; + } + if (allowUnknown !== true) { + throw new AxiosError_default("Unknown option " + opt, AxiosError_default.ERR_BAD_OPTION); + } + } +} +var validator_default = { + assertOptions, + validators +}; + +// node_modules/axios/lib/core/Axios.js +var validators2 = validator_default.validators; +var Axios = class { + constructor(instanceConfig) { + this.defaults = instanceConfig || {}; + this.interceptors = { + request: new InterceptorManager_default(), + response: new InterceptorManager_default() + }; + } + /** + * Dispatch a request + * + * @param {String|Object} configOrUrl The config specific for this request (merged with this.defaults) + * @param {?Object} config + * + * @returns {Promise} The Promise to be fulfilled + */ + async request(configOrUrl, config3) { + try { + return await this._request(configOrUrl, config3); + } catch (err) { + if (err instanceof Error) { + let dummy = {}; + Error.captureStackTrace ? Error.captureStackTrace(dummy) : dummy = new Error(); + const stack = dummy.stack ? dummy.stack.replace(/^.+\n/, "") : ""; + try { + if (!err.stack) { + err.stack = stack; + } else if (stack && !String(err.stack).endsWith(stack.replace(/^.+\n.+\n/, ""))) { + err.stack += "\n" + stack; + } + } catch (e) { + } + } + throw err; + } + } + _request(configOrUrl, config3) { + if (typeof configOrUrl === "string") { + config3 = config3 || {}; + config3.url = configOrUrl; + } else { + config3 = configOrUrl || {}; + } + config3 = mergeConfig(this.defaults, config3); + const { transitional: transitional2, paramsSerializer, headers } = config3; + if (transitional2 !== void 0) { + validator_default.assertOptions( + transitional2, + { + silentJSONParsing: validators2.transitional(validators2.boolean), + forcedJSONParsing: validators2.transitional(validators2.boolean), + clarifyTimeoutError: validators2.transitional(validators2.boolean), + legacyInterceptorReqResOrdering: validators2.transitional(validators2.boolean) + }, + false + ); + } + if (paramsSerializer != null) { + if (utils_default.isFunction(paramsSerializer)) { + config3.paramsSerializer = { + serialize: paramsSerializer + }; + } else { + validator_default.assertOptions( + paramsSerializer, + { + encode: validators2.function, + serialize: validators2.function + }, + true + ); + } + } + if (config3.allowAbsoluteUrls !== void 0) { + } else if (this.defaults.allowAbsoluteUrls !== void 0) { + config3.allowAbsoluteUrls = this.defaults.allowAbsoluteUrls; + } else { + config3.allowAbsoluteUrls = true; + } + validator_default.assertOptions( + config3, + { + baseUrl: validators2.spelling("baseURL"), + withXsrfToken: validators2.spelling("withXSRFToken") + }, + true + ); + config3.method = (config3.method || this.defaults.method || "get").toLowerCase(); + let contextHeaders = headers && utils_default.merge(headers.common, headers[config3.method]); + headers && utils_default.forEach(["delete", "get", "head", "post", "put", "patch", "common"], (method) => { + delete headers[method]; + }); + config3.headers = AxiosHeaders_default.concat(contextHeaders, headers); + const requestInterceptorChain = []; + let synchronousRequestInterceptors = true; + this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { + if (typeof interceptor.runWhen === "function" && interceptor.runWhen(config3) === false) { + return; + } + synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous; + const transitional3 = config3.transitional || transitional_default; + const legacyInterceptorReqResOrdering = transitional3 && transitional3.legacyInterceptorReqResOrdering; + if (legacyInterceptorReqResOrdering) { + requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected); + } else { + requestInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); + } + }); + const responseInterceptorChain = []; + this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { + responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); + }); + let promise; + let i = 0; + let len; + if (!synchronousRequestInterceptors) { + const chain = [dispatchRequest.bind(this), void 0]; + chain.unshift(...requestInterceptorChain); + chain.push(...responseInterceptorChain); + len = chain.length; + promise = Promise.resolve(config3); + while (i < len) { + promise = promise.then(chain[i++], chain[i++]); + } + return promise; + } + len = requestInterceptorChain.length; + let newConfig = config3; + while (i < len) { + const onFulfilled = requestInterceptorChain[i++]; + const onRejected = requestInterceptorChain[i++]; + try { + newConfig = onFulfilled(newConfig); + } catch (error) { + onRejected.call(this, error); + break; + } + } + try { + promise = dispatchRequest.call(this, newConfig); + } catch (error) { + return Promise.reject(error); + } + i = 0; + len = responseInterceptorChain.length; + while (i < len) { + promise = promise.then(responseInterceptorChain[i++], responseInterceptorChain[i++]); + } + return promise; + } + getUri(config3) { + config3 = mergeConfig(this.defaults, config3); + const fullPath = buildFullPath(config3.baseURL, config3.url, config3.allowAbsoluteUrls); + return buildURL(fullPath, config3.params, config3.paramsSerializer); + } +}; +utils_default.forEach(["delete", "get", "head", "options"], function forEachMethodNoData(method) { + Axios.prototype[method] = function(url, config3) { + return this.request( + mergeConfig(config3 || {}, { + method, + url, + data: (config3 || {}).data + }) + ); + }; +}); +utils_default.forEach(["post", "put", "patch"], function forEachMethodWithData(method) { + function generateHTTPMethod(isForm) { + return function httpMethod(url, data, config3) { + return this.request( + mergeConfig(config3 || {}, { + method, + headers: isForm ? { + "Content-Type": "multipart/form-data" + } : {}, + url, + data + }) + ); + }; + } + Axios.prototype[method] = generateHTTPMethod(); + Axios.prototype[method + "Form"] = generateHTTPMethod(true); +}); +var Axios_default = Axios; + +// node_modules/axios/lib/cancel/CancelToken.js +var CancelToken = class _CancelToken { + constructor(executor) { + if (typeof executor !== "function") { + throw new TypeError("executor must be a function."); + } + let resolvePromise; + this.promise = new Promise(function promiseExecutor(resolve) { + resolvePromise = resolve; + }); + const token = this; + this.promise.then((cancel) => { + if (!token._listeners) return; + let i = token._listeners.length; + while (i-- > 0) { + token._listeners[i](cancel); + } + token._listeners = null; + }); + this.promise.then = (onfulfilled) => { + let _resolve; + const promise = new Promise((resolve) => { + token.subscribe(resolve); + _resolve = resolve; + }).then(onfulfilled); + promise.cancel = function reject() { + token.unsubscribe(_resolve); + }; + return promise; + }; + executor(function cancel(message, config3, request2) { + if (token.reason) { + return; + } + token.reason = new CanceledError_default(message, config3, request2); + resolvePromise(token.reason); + }); + } + /** + * Throws a `CanceledError` if cancellation has been requested. + */ + throwIfRequested() { + if (this.reason) { + throw this.reason; + } + } + /** + * Subscribe to the cancel signal + */ + subscribe(listener) { + if (this.reason) { + listener(this.reason); + return; + } + if (this._listeners) { + this._listeners.push(listener); + } else { + this._listeners = [listener]; + } + } + /** + * Unsubscribe from the cancel signal + */ + unsubscribe(listener) { + if (!this._listeners) { + return; + } + const index = this._listeners.indexOf(listener); + if (index !== -1) { + this._listeners.splice(index, 1); + } + } + toAbortSignal() { + const controller = new AbortController(); + const abort = (err) => { + controller.abort(err); + }; + this.subscribe(abort); + controller.signal.unsubscribe = () => this.unsubscribe(abort); + return controller.signal; + } + /** + * Returns an object that contains a new `CancelToken` and a function that, when called, + * cancels the `CancelToken`. + */ + static source() { + let cancel; + const token = new _CancelToken(function executor(c) { + cancel = c; + }); + return { + token, + cancel + }; + } +}; +var CancelToken_default = CancelToken; + +// node_modules/axios/lib/helpers/spread.js +function spread(callback) { + return function wrap(arr) { + return callback.apply(null, arr); + }; +} + +// node_modules/axios/lib/helpers/isAxiosError.js +function isAxiosError(payload) { + return utils_default.isObject(payload) && payload.isAxiosError === true; +} + +// node_modules/axios/lib/helpers/HttpStatusCode.js +var HttpStatusCode = { + Continue: 100, + SwitchingProtocols: 101, + Processing: 102, + EarlyHints: 103, + Ok: 200, + Created: 201, + Accepted: 202, + NonAuthoritativeInformation: 203, + NoContent: 204, + ResetContent: 205, + PartialContent: 206, + MultiStatus: 207, + AlreadyReported: 208, + ImUsed: 226, + MultipleChoices: 300, + MovedPermanently: 301, + Found: 302, + SeeOther: 303, + NotModified: 304, + UseProxy: 305, + Unused: 306, + TemporaryRedirect: 307, + PermanentRedirect: 308, + BadRequest: 400, + Unauthorized: 401, + PaymentRequired: 402, + Forbidden: 403, + NotFound: 404, + MethodNotAllowed: 405, + NotAcceptable: 406, + ProxyAuthenticationRequired: 407, + RequestTimeout: 408, + Conflict: 409, + Gone: 410, + LengthRequired: 411, + PreconditionFailed: 412, + PayloadTooLarge: 413, + UriTooLong: 414, + UnsupportedMediaType: 415, + RangeNotSatisfiable: 416, + ExpectationFailed: 417, + ImATeapot: 418, + MisdirectedRequest: 421, + UnprocessableEntity: 422, + Locked: 423, + FailedDependency: 424, + TooEarly: 425, + UpgradeRequired: 426, + PreconditionRequired: 428, + TooManyRequests: 429, + RequestHeaderFieldsTooLarge: 431, + UnavailableForLegalReasons: 451, + InternalServerError: 500, + NotImplemented: 501, + BadGateway: 502, + ServiceUnavailable: 503, + GatewayTimeout: 504, + HttpVersionNotSupported: 505, + VariantAlsoNegotiates: 506, + InsufficientStorage: 507, + LoopDetected: 508, + NotExtended: 510, + NetworkAuthenticationRequired: 511, + WebServerIsDown: 521, + ConnectionTimedOut: 522, + OriginIsUnreachable: 523, + TimeoutOccurred: 524, + SslHandshakeFailed: 525, + InvalidSslCertificate: 526 +}; +Object.entries(HttpStatusCode).forEach(([key, value]) => { + HttpStatusCode[value] = key; +}); +var HttpStatusCode_default = HttpStatusCode; + +// node_modules/axios/lib/axios.js +function createInstance(defaultConfig) { + const context = new Axios_default(defaultConfig); + const instance = bind(Axios_default.prototype.request, context); + utils_default.extend(instance, Axios_default.prototype, context, { allOwnKeys: true }); + utils_default.extend(instance, context, null, { allOwnKeys: true }); + instance.create = function create(instanceConfig) { + return createInstance(mergeConfig(defaultConfig, instanceConfig)); + }; + return instance; +} +var axios = createInstance(defaults_default); +axios.Axios = Axios_default; +axios.CanceledError = CanceledError_default; +axios.CancelToken = CancelToken_default; +axios.isCancel = isCancel; +axios.VERSION = VERSION; +axios.toFormData = toFormData_default; +axios.AxiosError = AxiosError_default; +axios.Cancel = axios.CanceledError; +axios.all = function all(promises) { + return Promise.all(promises); +}; +axios.spread = spread; +axios.isAxiosError = isAxiosError; +axios.mergeConfig = mergeConfig; +axios.AxiosHeaders = AxiosHeaders_default; +axios.formToJSON = (thing) => formDataToJSON_default(utils_default.isHTMLForm(thing) ? new FormData(thing) : thing); +axios.getAdapter = adapters_default.getAdapter; +axios.HttpStatusCode = HttpStatusCode_default; +axios.default = axios; +var axios_default = axios; + +// node_modules/axios/index.js +var { + Axios: Axios2, + AxiosError: AxiosError2, + CanceledError: CanceledError2, + isCancel: isCancel2, + CancelToken: CancelToken2, + VERSION: VERSION2, + all: all2, + Cancel, + isAxiosError: isAxiosError2, + spread: spread2, + toFormData: toFormData2, + AxiosHeaders: AxiosHeaders2, + HttpStatusCode: HttpStatusCode2, + formToJSON, + getAdapter: getAdapter2, + mergeConfig: mergeConfig2 +} = axios_default; + +// node_modules/@inertiajs/core/dist/index.esm.js +var Config = class { + constructor(defaults2) { + this.config = {}; + this.defaults = defaults2; + } + extend(defaults2) { + if (defaults2) { + this.defaults = { ...this.defaults, ...defaults2 }; + } + return this; + } + replace(newConfig) { + this.config = newConfig; + } + get(key) { + return has_default(this.config, key) ? get_default(this.config, key) : get_default(this.defaults, key); + } + set(keyOrValues, value) { + if (typeof keyOrValues === "string") { + set_default(this.config, keyOrValues, value); + } else { + Object.entries(keyOrValues).forEach(([key, val]) => { + set_default(this.config, key, val); + }); + } + } +}; +var config = new Config({ + form: { + recentlySuccessfulDuration: 2e3, + forceIndicesArrayFormatInFormData: true, + withAllErrors: false + }, + future: { + preserveEqualProps: false, + useDataInertiaHeadAttribute: false, + useDialogForErrorModal: false, + useScriptElementForInitialPage: false + }, + prefetch: { + cacheFor: 3e4, + hoverDelay: 75 + } +}); +function debounce2(fn, delay) { + let timeoutID; + return function(...args) { + clearTimeout(timeoutID); + timeoutID = setTimeout(() => fn.apply(this, args), delay); + }; +} +function fireEvent(name, options) { + return document.dispatchEvent(new CustomEvent(`inertia:${name}`, options)); +} +var fireBeforeEvent = (visit) => { + return fireEvent("before", { cancelable: true, detail: { visit } }); +}; +var fireErrorEvent = (errors) => { + return fireEvent("error", { detail: { errors } }); +}; +var fireExceptionEvent = (exception) => { + return fireEvent("exception", { cancelable: true, detail: { exception } }); +}; +var fireFinishEvent = (visit) => { + return fireEvent("finish", { detail: { visit } }); +}; +var fireInvalidEvent = (response) => { + return fireEvent("invalid", { cancelable: true, detail: { response } }); +}; +var fireBeforeUpdateEvent = (page2) => { + return fireEvent("beforeUpdate", { detail: { page: page2 } }); +}; +var fireNavigateEvent = (page2) => { + return fireEvent("navigate", { detail: { page: page2 } }); +}; +var fireProgressEvent = (progress32) => { + return fireEvent("progress", { detail: { progress: progress32 } }); +}; +var fireStartEvent = (visit) => { + return fireEvent("start", { detail: { visit } }); +}; +var fireSuccessEvent = (page2) => { + return fireEvent("success", { detail: { page: page2 } }); +}; +var firePrefetchedEvent = (response, visit) => { + return fireEvent("prefetched", { detail: { fetchedAt: Date.now(), response: response.data, visit } }); +}; +var firePrefetchingEvent = (visit) => { + return fireEvent("prefetching", { detail: { visit } }); +}; +var fireFlashEvent = (flash) => { + return fireEvent("flash", { detail: { flash } }); +}; +var SessionStorage = class { + static set(key, value) { + if (typeof window !== "undefined") { + window.sessionStorage.setItem(key, JSON.stringify(value)); + } + } + static get(key) { + if (typeof window !== "undefined") { + return JSON.parse(window.sessionStorage.getItem(key) || "null"); + } + } + static merge(key, value) { + const existing = this.get(key); + if (existing === null) { + this.set(key, value); + } else { + this.set(key, { ...existing, ...value }); + } + } + static remove(key) { + if (typeof window !== "undefined") { + window.sessionStorage.removeItem(key); + } + } + static removeNested(key, nestedKey) { + const existing = this.get(key); + if (existing !== null) { + delete existing[nestedKey]; + this.set(key, existing); + } + } + static exists(key) { + try { + return this.get(key) !== null; + } catch (error) { + return false; + } + } + static clear() { + if (typeof window !== "undefined") { + window.sessionStorage.clear(); + } + } +}; +SessionStorage.locationVisitKey = "inertiaLocationVisit"; +var encryptHistory = async (data) => { + if (typeof window === "undefined") { + throw new Error("Unable to encrypt history"); + } + const iv = getIv(); + const storedKey = await getKeyFromSessionStorage(); + const key = await getOrCreateKey(storedKey); + if (!key) { + throw new Error("Unable to encrypt history"); + } + const encrypted = await encryptData(iv, key, data); + return encrypted; +}; +var historySessionStorageKeys = { + key: "historyKey", + iv: "historyIv" +}; +var decryptHistory = async (data) => { + const iv = getIv(); + const storedKey = await getKeyFromSessionStorage(); + if (!storedKey) { + throw new Error("Unable to decrypt history"); + } + return await decryptData(iv, storedKey, data); +}; +var encryptData = async (iv, key, data) => { + if (typeof window === "undefined") { + throw new Error("Unable to encrypt history"); + } + if (typeof window.crypto.subtle === "undefined") { + console.warn("Encryption is not supported in this environment. SSL is required."); + return Promise.resolve(data); + } + const textEncoder = new TextEncoder(); + const str = JSON.stringify(data); + const encoded = new Uint8Array(str.length * 3); + const result = textEncoder.encodeInto(str, encoded); + return window.crypto.subtle.encrypt( + { + name: "AES-GCM", + iv + }, + key, + encoded.subarray(0, result.written) + ); +}; +var decryptData = async (iv, key, data) => { + if (typeof window.crypto.subtle === "undefined") { + console.warn("Decryption is not supported in this environment. SSL is required."); + return Promise.resolve(data); + } + const decrypted = await window.crypto.subtle.decrypt( + { + name: "AES-GCM", + iv + }, + key, + data + ); + return JSON.parse(new TextDecoder().decode(decrypted)); +}; +var getIv = () => { + const ivString = SessionStorage.get(historySessionStorageKeys.iv); + if (ivString) { + return new Uint8Array(ivString); + } + const iv = window.crypto.getRandomValues(new Uint8Array(12)); + SessionStorage.set(historySessionStorageKeys.iv, Array.from(iv)); + return iv; +}; +var createKey = async () => { + if (typeof window.crypto.subtle === "undefined") { + console.warn("Encryption is not supported in this environment. SSL is required."); + return Promise.resolve(null); + } + return window.crypto.subtle.generateKey( + { + name: "AES-GCM", + length: 256 + }, + true, + ["encrypt", "decrypt"] + ); +}; +var saveKey = async (key) => { + if (typeof window.crypto.subtle === "undefined") { + console.warn("Encryption is not supported in this environment. SSL is required."); + return Promise.resolve(); + } + const keyData = await window.crypto.subtle.exportKey("raw", key); + SessionStorage.set(historySessionStorageKeys.key, Array.from(new Uint8Array(keyData))); +}; +var getOrCreateKey = async (key) => { + if (key) { + return key; + } + const newKey = await createKey(); + if (!newKey) { + return null; + } + await saveKey(newKey); + return newKey; +}; +var getKeyFromSessionStorage = async () => { + const stringKey = SessionStorage.get(historySessionStorageKeys.key); + if (!stringKey) { + return null; + } + const key = await window.crypto.subtle.importKey( + "raw", + new Uint8Array(stringKey), + { + name: "AES-GCM", + length: 256 + }, + true, + ["encrypt", "decrypt"] + ); + return key; +}; +var objectsAreEqual = (obj1, obj2, excludeKeys) => { + if (obj1 === obj2) { + return true; + } + for (const key in obj1) { + if (excludeKeys.includes(key)) { + continue; + } + if (obj1[key] === obj2[key]) { + continue; + } + if (!compareValues(obj1[key], obj2[key])) { + return false; + } + } + for (const key in obj2) { + if (excludeKeys.includes(key)) { + continue; + } + if (!(key in obj1)) { + return false; + } + } + return true; +}; +var compareValues = (value1, value2) => { + switch (typeof value1) { + case "object": + return objectsAreEqual(value1, value2, []); + case "function": + return value1.toString() === value2.toString(); + default: + return value1 === value2; + } +}; +var conversionMap = { + ms: 1, + s: 1e3, + m: 1e3 * 60, + h: 1e3 * 60 * 60, + d: 1e3 * 60 * 60 * 24 +}; +var timeToMs = (time) => { + if (typeof time === "number") { + return time; + } + for (const [unit, conversion] of Object.entries(conversionMap)) { + if (time.endsWith(unit)) { + return parseFloat(time) * conversion; + } + } + return parseInt(time); +}; +var PrefetchedRequests = class { + constructor() { + this.cached = []; + this.inFlightRequests = []; + this.removalTimers = []; + this.currentUseId = null; + } + add(params, sendFunc, { cacheFor, cacheTags }) { + const inFlight = this.findInFlight(params); + if (inFlight) { + return Promise.resolve(); + } + const existing = this.findCached(params); + if (!params.fresh && existing && existing.staleTimestamp > Date.now()) { + return Promise.resolve(); + } + const [stale, prefetchExpiresIn] = this.extractStaleValues(cacheFor); + const promise = new Promise((resolve, reject) => { + sendFunc({ + ...params, + onCancel: () => { + this.remove(params); + params.onCancel(); + reject(); + }, + onError: (error) => { + this.remove(params); + params.onError(error); + reject(); + }, + onPrefetching(visitParams) { + params.onPrefetching(visitParams); + }, + onPrefetched(response, visit) { + params.onPrefetched(response, visit); + }, + onPrefetchResponse(response) { + resolve(response); + }, + onPrefetchError(error) { + prefetchedRequests.removeFromInFlight(params); + reject(error); + } + }); + }).then((response) => { + this.remove(params); + const pageResponse = response.getPageResponse(); + page.mergeOncePropsIntoResponse(pageResponse); + this.cached.push({ + params: { ...params }, + staleTimestamp: Date.now() + stale, + expiresAt: Date.now() + prefetchExpiresIn, + response: promise, + singleUse: prefetchExpiresIn === 0, + timestamp: Date.now(), + inFlight: false, + tags: Array.isArray(cacheTags) ? cacheTags : [cacheTags] + }); + const oncePropExpiresIn = this.getShortestOncePropTtl(pageResponse); + this.scheduleForRemoval( + params, + oncePropExpiresIn ? Math.min(prefetchExpiresIn, oncePropExpiresIn) : prefetchExpiresIn + ); + this.removeFromInFlight(params); + response.handlePrefetch(); + return response; + }); + this.inFlightRequests.push({ + params: { ...params }, + response: promise, + staleTimestamp: null, + inFlight: true + }); + return promise; + } + removeAll() { + this.cached = []; + this.removalTimers.forEach((removalTimer) => { + clearTimeout(removalTimer.timer); + }); + this.removalTimers = []; + } + removeByTags(tags) { + this.cached = this.cached.filter((prefetched) => { + return !prefetched.tags.some((tag) => tags.includes(tag)); + }); + } + remove(params) { + this.cached = this.cached.filter((prefetched) => { + return !this.paramsAreEqual(prefetched.params, params); + }); + this.clearTimer(params); + } + removeFromInFlight(params) { + this.inFlightRequests = this.inFlightRequests.filter((prefetching) => { + return !this.paramsAreEqual(prefetching.params, params); + }); + } + extractStaleValues(cacheFor) { + const [stale, expires] = this.cacheForToStaleAndExpires(cacheFor); + return [timeToMs(stale), timeToMs(expires)]; + } + cacheForToStaleAndExpires(cacheFor) { + if (!Array.isArray(cacheFor)) { + return [cacheFor, cacheFor]; + } + switch (cacheFor.length) { + case 0: + return [0, 0]; + case 1: + return [cacheFor[0], cacheFor[0]]; + default: + return [cacheFor[0], cacheFor[1]]; + } + } + clearTimer(params) { + const timer = this.removalTimers.find((removalTimer) => { + return this.paramsAreEqual(removalTimer.params, params); + }); + if (timer) { + clearTimeout(timer.timer); + this.removalTimers = this.removalTimers.filter((removalTimer) => removalTimer !== timer); + } + } + scheduleForRemoval(params, expiresIn) { + if (typeof window === "undefined") { + return; + } + this.clearTimer(params); + if (expiresIn > 0) { + const timer = window.setTimeout(() => this.remove(params), expiresIn); + this.removalTimers.push({ + params, + timer + }); + } + } + get(params) { + return this.findCached(params) || this.findInFlight(params); + } + use(prefetched, params) { + const id = `${params.url.pathname}-${Date.now()}-${Math.random().toString(36).substring(7)}`; + this.currentUseId = id; + return prefetched.response.then((response) => { + if (this.currentUseId !== id) { + return; + } + response.mergeParams({ ...params, onPrefetched: () => { + } }); + this.removeSingleUseItems(params); + return response.handle(); + }); + } + removeSingleUseItems(params) { + this.cached = this.cached.filter((prefetched) => { + if (!this.paramsAreEqual(prefetched.params, params)) { + return true; + } + return !prefetched.singleUse; + }); + } + findCached(params) { + return this.cached.find((prefetched) => { + return this.paramsAreEqual(prefetched.params, params); + }) || null; + } + findInFlight(params) { + return this.inFlightRequests.find((prefetched) => { + return this.paramsAreEqual(prefetched.params, params); + }) || null; + } + withoutPurposePrefetchHeader(params) { + const newParams = cloneDeep_default(params); + if (newParams.headers["Purpose"] === "prefetch") { + delete newParams.headers["Purpose"]; + } + return newParams; + } + paramsAreEqual(params1, params2) { + return objectsAreEqual( + this.withoutPurposePrefetchHeader(params1), + this.withoutPurposePrefetchHeader(params2), + [ + "showProgress", + "replace", + "prefetch", + "preserveScroll", + "preserveState", + "onBefore", + "onBeforeUpdate", + "onStart", + "onProgress", + "onFinish", + "onCancel", + "onSuccess", + "onError", + "onFlash", + "onPrefetched", + "onCancelToken", + "onPrefetching", + "async", + "viewTransition" + ] + ); + } + updateCachedOncePropsFromCurrentPage() { + this.cached.forEach((prefetched) => { + prefetched.response.then((response) => { + const pageResponse = response.getPageResponse(); + page.mergeOncePropsIntoResponse(pageResponse, { force: true }); + for (const [group, deferredProps] of Object.entries(pageResponse.deferredProps ?? {})) { + const remaining = deferredProps.filter((prop) => pageResponse.props[prop] === void 0); + if (remaining.length > 0) { + pageResponse.deferredProps[group] = remaining; + } else { + delete pageResponse.deferredProps[group]; + } + } + const oncePropExpiresIn = this.getShortestOncePropTtl(pageResponse); + if (oncePropExpiresIn === null) { + return; + } + const prefetchExpiresIn = prefetched.expiresAt - Date.now(); + const expiresIn = Math.min(prefetchExpiresIn, oncePropExpiresIn); + if (expiresIn > 0) { + this.scheduleForRemoval(prefetched.params, expiresIn); + } else { + this.remove(prefetched.params); + } + }); + }); + } + getShortestOncePropTtl(page2) { + const expiryTimestamps = Object.values(page2.onceProps ?? {}).map((onceProp) => onceProp.expiresAt).filter((expiresAt) => !!expiresAt); + if (expiryTimestamps.length === 0) { + return null; + } + return Math.min(...expiryTimestamps) - Date.now(); + } +}; +var prefetchedRequests = new PrefetchedRequests(); +var elementInViewport = (el) => { + if (el.offsetParent === null) { + return false; + } + const rect = el.getBoundingClientRect(); + const verticallyVisible = rect.top < window.innerHeight && rect.bottom >= 0; + const horizontallyVisible = rect.left < window.innerWidth && rect.right >= 0; + return verticallyVisible && horizontallyVisible; +}; +var getScrollableParent = (element) => { + const allowsVerticalScroll = (el) => { + const computedStyle = window.getComputedStyle(el); + if (["scroll", "overlay"].includes(computedStyle.overflowY)) { + return true; + } + if (computedStyle.overflowY !== "auto") { + return false; + } + if (["visible", "clip"].includes(computedStyle.overflowX)) { + return true; + } + return hasDimensionConstraint(computedStyle.maxHeight, el.style.height) || isConstrainedByLayout(el, "height"); + }; + const allowsHorizontalScroll = (el) => { + const computedStyle = window.getComputedStyle(el); + if (["scroll", "overlay"].includes(computedStyle.overflowX)) { + return true; + } + if (computedStyle.overflowX !== "auto") { + return false; + } + if (["visible", "clip"].includes(computedStyle.overflowY)) { + return true; + } + return hasDimensionConstraint(computedStyle.maxWidth, el.style.width) || isConstrainedByLayout(el, "width"); + }; + const hasDimensionConstraint = (computedMaxDimension, inlineStyleDimension) => { + if (computedMaxDimension && computedMaxDimension !== "none" && computedMaxDimension !== "0px") { + return true; + } + if (inlineStyleDimension && inlineStyleDimension !== "auto" && inlineStyleDimension !== "0") { + return true; + } + return false; + }; + const isConstrainedByLayout = (el, dimension) => { + const parent2 = el.parentElement; + if (!parent2) { + return false; + } + const parentStyle = window.getComputedStyle(parent2); + if (["flex", "inline-flex"].includes(parentStyle.display)) { + const isColumnLayout = ["column", "column-reverse"].includes(parentStyle.flexDirection); + return dimension === "height" ? isColumnLayout : !isColumnLayout; + } + return ["grid", "inline-grid"].includes(parentStyle.display); + }; + let parent = element?.parentElement; + while (parent) { + const allowsScroll = allowsVerticalScroll(parent) || allowsHorizontalScroll(parent); + if (window.getComputedStyle(parent).display !== "contents" && allowsScroll) { + return parent; + } + parent = parent.parentElement; + } + return null; +}; +var getElementsInViewportFromCollection = (elements, referenceElement) => { + if (!referenceElement) { + return elements.filter((element) => elementInViewport(element)); + } + const referenceIndex = elements.indexOf(referenceElement); + const upwardElements = []; + const downwardElements = []; + for (let i = referenceIndex; i >= 0; i--) { + const element = elements[i]; + if (elementInViewport(element)) { + upwardElements.push(element); + } else { + break; + } + } + for (let i = referenceIndex + 1; i < elements.length; i++) { + const element = elements[i]; + if (elementInViewport(element)) { + downwardElements.push(element); + } else { + break; + } + } + return [...upwardElements.reverse(), ...downwardElements]; +}; +var requestAnimationFrame = (cb, times = 1) => { + window.requestAnimationFrame(() => { + if (times > 1) { + requestAnimationFrame(cb, times - 1); + } else { + cb(); + } + }); +}; +var getInitialPageFromDOM = (id, useScriptElement = false) => { + if (typeof window === "undefined") { + return null; + } + if (!useScriptElement) { + const el = document.getElementById(id); + if (el?.dataset.page) { + return JSON.parse(el.dataset.page); + } + } + const scriptEl = document.querySelector(`script[data-page="${id}"][type="application/json"]`); + if (scriptEl?.textContent) { + return JSON.parse(scriptEl.textContent); + } + return null; +}; +var isServer = typeof window === "undefined"; +var isFirefox = !isServer && /Firefox/i.test(window.navigator.userAgent); +var Scroll = class { + static save() { + history.saveScrollPositions(this.getScrollRegions()); + } + static getScrollRegions() { + return Array.from(this.regions()).map((region) => ({ + top: region.scrollTop, + left: region.scrollLeft + })); + } + static regions() { + return document.querySelectorAll("[scroll-region]"); + } + static scrollToTop() { + if (isFirefox && getComputedStyle(document.documentElement).scrollBehavior === "smooth") { + return requestAnimationFrame(() => window.scrollTo(0, 0), 2); + } + window.scrollTo(0, 0); + } + static reset() { + const anchorHash = isServer ? null : window.location.hash; + if (!anchorHash) { + this.scrollToTop(); + } + this.regions().forEach((region) => { + if (typeof region.scrollTo === "function") { + region.scrollTo(0, 0); + } else { + region.scrollTop = 0; + region.scrollLeft = 0; + } + }); + this.save(); + this.scrollToAnchor(); + } + static scrollToAnchor() { + const anchorHash = isServer ? null : window.location.hash; + if (anchorHash) { + setTimeout(() => { + const anchorElement = document.getElementById(anchorHash.slice(1)); + anchorElement ? anchorElement.scrollIntoView() : this.scrollToTop(); + }); + } + } + static restore(scrollRegions) { + if (isServer) { + return; + } + window.requestAnimationFrame(() => { + this.restoreDocument(); + this.restoreScrollRegions(scrollRegions); + }); + } + static restoreScrollRegions(scrollRegions) { + if (isServer) { + return; + } + this.regions().forEach((region, index) => { + const scrollPosition = scrollRegions[index]; + if (!scrollPosition) { + return; + } + if (typeof region.scrollTo === "function") { + region.scrollTo(scrollPosition.left, scrollPosition.top); + } else { + region.scrollTop = scrollPosition.top; + region.scrollLeft = scrollPosition.left; + } + }); + } + static restoreDocument() { + const scrollPosition = history.getDocumentScrollPosition(); + window.scrollTo(scrollPosition.left, scrollPosition.top); + } + static onScroll(event) { + const target = event.target; + if (typeof target.hasAttribute === "function" && target.hasAttribute("scroll-region")) { + this.save(); + } + } + static onWindowScroll() { + history.saveDocumentScrollPosition({ + top: window.scrollY, + left: window.scrollX + }); + } +}; +var isFile2 = (value) => typeof File !== "undefined" && value instanceof File || value instanceof Blob || typeof FileList !== "undefined" && value instanceof FileList && value.length > 0; +function hasFiles(data) { + return isFile2(data) || data instanceof FormData && Array.from(data.values()).some((value) => hasFiles(value)) || typeof data === "object" && data !== null && Object.values(data).some((value) => hasFiles(value)); +} +var isFormData2 = (value) => value instanceof FormData; +function objectToFormData(source, form = new FormData(), parentKey = null, queryStringArrayFormat = "brackets") { + source = source || {}; + for (const key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + append2(form, composeKey(parentKey, key, "indices"), source[key], queryStringArrayFormat); + } + } + return form; +} +function composeKey(parent, key, format) { + if (!parent) { + return key; + } + return format === "brackets" ? `${parent}[]` : `${parent}[${key}]`; +} +function append2(form, key, value, format) { + if (Array.isArray(value)) { + return Array.from(value.keys()).forEach( + (index) => append2(form, composeKey(key, index.toString(), format), value[index], format) + ); + } else if (value instanceof Date) { + return form.append(key, value.toISOString()); + } else if (value instanceof File) { + return form.append(key, value, value.name); + } else if (value instanceof Blob) { + return form.append(key, value); + } else if (typeof value === "boolean") { + return form.append(key, value ? "1" : "0"); + } else if (typeof value === "string") { + return form.append(key, value); + } else if (typeof value === "number") { + return form.append(key, `${value}`); + } else if (value === null || value === void 0) { + return form.append(key, ""); + } + objectToFormData(value, form, key, format); +} +function hrefToUrl(href) { + return new URL(href.toString(), typeof window === "undefined" ? void 0 : window.location.toString()); +} +var transformUrlAndData = (href, data, method, forceFormData, queryStringArrayFormat) => { + let url = typeof href === "string" ? hrefToUrl(href) : href; + if ((hasFiles(data) || forceFormData) && !isFormData2(data)) { + if (config.get("form.forceIndicesArrayFormatInFormData")) { + queryStringArrayFormat = "indices"; + } + data = objectToFormData(data, new FormData(), null, queryStringArrayFormat); + } + if (isFormData2(data)) { + return [url, data]; + } + const [_href, _data] = mergeDataIntoQueryString(method, url, data, queryStringArrayFormat); + return [hrefToUrl(_href), _data]; +}; +function mergeDataIntoQueryString(method, href, data, qsArrayFormat = "brackets") { + const hasDataForQueryString = method === "get" && !isFormData2(data) && Object.keys(data).length > 0; + const hasHost = urlHasProtocol(href.toString()); + const hasAbsolutePath = hasHost || href.toString().startsWith("/") || href.toString() === ""; + const hasRelativePath = !hasAbsolutePath && !href.toString().startsWith("#") && !href.toString().startsWith("?"); + const hasRelativePathWithDotPrefix = /^[.]{1,2}([/]|$)/.test(href.toString()); + const hasSearch = href.toString().includes("?") || hasDataForQueryString; + const hasHash = href.toString().includes("#"); + const url = new URL(href.toString(), typeof window === "undefined" ? "http://localhost" : window.location.toString()); + if (hasDataForQueryString) { + const hasIndices = /\[\d+\]/.test(decodeURIComponent(url.search)); + const parseOptions = { ignoreQueryPrefix: true, allowSparse: true }; + url.search = qs.stringify( + { ...qs.parse(url.search, parseOptions), ...data }, + { + encodeValuesOnly: true, + arrayFormat: hasIndices ? "indices" : qsArrayFormat + } + ); + } + return [ + [ + hasHost ? `${url.protocol}//${url.host}` : "", + hasAbsolutePath ? url.pathname : "", + hasRelativePath ? url.pathname.substring(hasRelativePathWithDotPrefix ? 0 : 1) : "", + hasSearch ? url.search : "", + hasHash ? url.hash : "" + ].join(""), + hasDataForQueryString ? {} : data + ]; +} +function urlWithoutHash(url) { + url = new URL(url.href); + url.hash = ""; + return url; +} +var setHashIfSameUrl = (originUrl, destinationUrl) => { + if (originUrl.hash && !destinationUrl.hash && urlWithoutHash(originUrl).href === destinationUrl.href) { + destinationUrl.hash = originUrl.hash; + } +}; +var isSameUrlWithoutHash = (url1, url2) => { + return urlWithoutHash(url1).href === urlWithoutHash(url2).href; +}; +var isSameUrlWithoutQueryOrHash = (url1, url2) => { + return url1.origin === url2.origin && url1.pathname === url2.pathname; +}; +function isUrlMethodPair(href) { + return href !== null && typeof href === "object" && href !== void 0 && "url" in href && "method" in href; +} +function urlHasProtocol(url) { + return /^([a-z][a-z0-9+.-]*:)?\/\/[^/]/i.test(url); +} +function urlToString(url, absolute) { + const urlObj = typeof url === "string" ? hrefToUrl(url) : url; + return absolute ? `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}${urlObj.search}${urlObj.hash}` : `${urlObj.pathname}${urlObj.search}${urlObj.hash}`; +} +var CurrentPage = class { + constructor() { + this.componentId = {}; + this.listeners = []; + this.isFirstPageLoad = true; + this.cleared = false; + this.pendingDeferredProps = null; + this.historyQuotaExceeded = false; + } + init({ + initialPage, + swapComponent: swapComponent2, + resolveComponent, + onFlash + }) { + this.page = { ...initialPage, flash: initialPage.flash ?? {} }; + this.swapComponent = swapComponent2; + this.resolveComponent = resolveComponent; + this.onFlashCallback = onFlash; + eventHandler.on("historyQuotaExceeded", () => { + this.historyQuotaExceeded = true; + }); + return this; + } + set(page2, { + replace = false, + preserveScroll = false, + preserveState = false, + viewTransition = false + } = {}) { + if (Object.keys(page2.deferredProps || {}).length) { + this.pendingDeferredProps = { + deferredProps: page2.deferredProps, + component: page2.component, + url: page2.url + }; + if (page2.initialDeferredProps === void 0) { + page2.initialDeferredProps = page2.deferredProps; + } + } + this.componentId = {}; + const componentId = this.componentId; + if (page2.clearHistory) { + history.clear(); + } + return this.resolve(page2.component).then((component) => { + if (componentId !== this.componentId) { + return; + } + page2.rememberedState ?? (page2.rememberedState = {}); + const isServer3 = typeof window === "undefined"; + const location = !isServer3 ? window.location : new URL(page2.url); + const scrollRegions = !isServer3 && preserveScroll ? Scroll.getScrollRegions() : []; + replace = replace || isSameUrlWithoutHash(hrefToUrl(page2.url), location); + const pageForHistory = { ...page2, flash: {} }; + return new Promise( + (resolve) => replace ? history.replaceState(pageForHistory, resolve) : history.pushState(pageForHistory, resolve) + ).then(() => { + const isNewComponent = !this.isTheSame(page2); + if (!isNewComponent && Object.keys(page2.props.errors || {}).length > 0) { + viewTransition = false; + } + this.page = page2; + this.cleared = false; + if (this.hasOnceProps()) { + prefetchedRequests.updateCachedOncePropsFromCurrentPage(); + } + if (isNewComponent) { + this.fireEventsFor("newComponent"); + } + if (this.isFirstPageLoad) { + this.fireEventsFor("firstLoad"); + } + this.isFirstPageLoad = false; + if (this.historyQuotaExceeded) { + this.historyQuotaExceeded = false; + return; + } + return this.swap({ + component, + page: page2, + preserveState, + viewTransition + }).then(() => { + if (preserveScroll) { + window.requestAnimationFrame(() => Scroll.restoreScrollRegions(scrollRegions)); + } else { + Scroll.reset(); + } + if (this.pendingDeferredProps && this.pendingDeferredProps.component === page2.component && this.pendingDeferredProps.url === page2.url) { + eventHandler.fireInternalEvent("loadDeferredProps", this.pendingDeferredProps.deferredProps); + } + this.pendingDeferredProps = null; + if (!replace) { + fireNavigateEvent(page2); + } + }); + }); + }); + } + setQuietly(page2, { + preserveState = false + } = {}) { + return this.resolve(page2.component).then((component) => { + this.page = page2; + this.cleared = false; + history.setCurrent(page2); + return this.swap({ component, page: page2, preserveState, viewTransition: false }); + }); + } + clear() { + this.cleared = true; + } + isCleared() { + return this.cleared; + } + get() { + return this.page; + } + getWithoutFlashData() { + return { ...this.page, flash: {} }; + } + hasOnceProps() { + return Object.keys(this.page.onceProps ?? {}).length > 0; + } + merge(data) { + this.page = { ...this.page, ...data }; + } + setFlash(flash) { + this.page = { ...this.page, flash }; + this.onFlashCallback?.(flash); + } + setUrlHash(hash) { + if (!this.page.url.includes(hash)) { + this.page.url += hash; + } + } + remember(data) { + this.page.rememberedState = data; + } + swap({ + component, + page: page2, + preserveState, + viewTransition + }) { + const doSwap = () => this.swapComponent({ component, page: page2, preserveState }); + if (!viewTransition || !document?.startViewTransition) { + return doSwap(); + } + const viewTransitionCallback = typeof viewTransition === "boolean" ? () => null : viewTransition; + return new Promise((resolve) => { + const transitionResult = document.startViewTransition(() => doSwap().then(resolve)); + viewTransitionCallback(transitionResult); + }); + } + resolve(component) { + return Promise.resolve(this.resolveComponent(component)); + } + isTheSame(page2) { + return this.page.component === page2.component; + } + on(event, callback) { + this.listeners.push({ event, callback }); + return () => { + this.listeners = this.listeners.filter((listener) => listener.event !== event && listener.callback !== callback); + }; + } + fireEventsFor(event) { + this.listeners.filter((listener) => listener.event === event).forEach((listener) => listener.callback()); + } + mergeOncePropsIntoResponse(response, { force = false } = {}) { + Object.entries(response.onceProps ?? {}).forEach(([key, onceProp]) => { + const existingOnceProp = this.page.onceProps?.[key]; + if (existingOnceProp === void 0) { + return; + } + if (force || response.props[onceProp.prop] === void 0) { + response.props[onceProp.prop] = this.page.props[existingOnceProp.prop]; + response.onceProps[key].expiresAt = existingOnceProp.expiresAt; + } + }); + } +}; +var page = new CurrentPage(); +var Queue = class { + constructor() { + this.items = []; + this.processingPromise = null; + } + add(item) { + this.items.push(item); + return this.process(); + } + process() { + this.processingPromise ?? (this.processingPromise = this.processNext().finally(() => { + this.processingPromise = null; + })); + return this.processingPromise; + } + processNext() { + const next = this.items.shift(); + if (next) { + return Promise.resolve(next()).then(() => this.processNext()); + } + return Promise.resolve(); + } +}; +var isServer2 = typeof window === "undefined"; +var queue = new Queue(); +var isChromeIOS = !isServer2 && /CriOS/.test(window.navigator.userAgent); +var History = class { + constructor() { + this.rememberedState = "rememberedState"; + this.scrollRegions = "scrollRegions"; + this.preserveUrl = false; + this.current = {}; + this.initialState = null; + } + remember(data, key) { + this.replaceState({ + ...page.getWithoutFlashData(), + rememberedState: { + ...page.get()?.rememberedState ?? {}, + [key]: data + } + }); + } + restore(key) { + if (!isServer2) { + return this.current[this.rememberedState]?.[key] !== void 0 ? this.current[this.rememberedState]?.[key] : this.initialState?.[this.rememberedState]?.[key]; + } + } + pushState(page2, cb = null) { + if (isServer2) { + return; + } + if (this.preserveUrl) { + cb && cb(); + return; + } + this.current = page2; + queue.add(() => { + return this.getPageData(page2).then((data) => { + const doPush = () => this.doPushState({ page: data }, page2.url).then(() => cb?.()); + if (isChromeIOS) { + return new Promise((resolve) => { + setTimeout(() => doPush().then(resolve)); + }); + } + return doPush(); + }); + }); + } + clonePageProps(page2) { + try { + structuredClone(page2.props); + return page2; + } catch { + return { + ...page2, + props: cloneDeep_default(page2.props) + }; + } + } + getPageData(page2) { + const pageWithClonedProps = this.clonePageProps(page2); + return new Promise((resolve) => { + return page2.encryptHistory ? encryptHistory(pageWithClonedProps).then(resolve) : resolve(pageWithClonedProps); + }); + } + processQueue() { + return queue.process(); + } + decrypt(page2 = null) { + if (isServer2) { + return Promise.resolve(page2 ?? page.get()); + } + const pageData = page2 ?? window.history.state?.page; + return this.decryptPageData(pageData).then((data) => { + if (!data) { + throw new Error("Unable to decrypt history"); + } + if (this.initialState === null) { + this.initialState = data ?? void 0; + } else { + this.current = data ?? {}; + } + return data; + }); + } + decryptPageData(pageData) { + return pageData instanceof ArrayBuffer ? decryptHistory(pageData) : Promise.resolve(pageData); + } + saveScrollPositions(scrollRegions) { + queue.add(() => { + return Promise.resolve().then(() => { + if (!window.history.state?.page) { + return; + } + if (isEqual_default(this.getScrollRegions(), scrollRegions)) { + return; + } + return this.doReplaceState({ + page: window.history.state.page, + scrollRegions + }); + }); + }); + } + saveDocumentScrollPosition(scrollRegion) { + queue.add(() => { + return Promise.resolve().then(() => { + if (!window.history.state?.page) { + return; + } + if (isEqual_default(this.getDocumentScrollPosition(), scrollRegion)) { + return; + } + return this.doReplaceState({ + page: window.history.state.page, + documentScrollPosition: scrollRegion + }); + }); + }); + } + getScrollRegions() { + return window.history.state?.scrollRegions || []; + } + getDocumentScrollPosition() { + return window.history.state?.documentScrollPosition || { top: 0, left: 0 }; + } + replaceState(page2, cb = null) { + if (isEqual_default(this.current, page2)) { + cb && cb(); + return; + } + const { flash, ...pageWithoutFlash } = page2; + page.merge(pageWithoutFlash); + if (isServer2) { + return; + } + if (this.preserveUrl) { + cb && cb(); + return; + } + this.current = page2; + queue.add(() => { + return this.getPageData(page2).then((data) => { + const doReplace = () => this.doReplaceState({ page: data }, page2.url).then(() => cb?.()); + if (isChromeIOS) { + return new Promise((resolve) => { + setTimeout(() => doReplace().then(resolve)); + }); + } + return doReplace(); + }); + }); + } + isHistoryThrottleError(error) { + return error instanceof Error && error.name === "SecurityError" && (error.message.includes("history.pushState") || error.message.includes("history.replaceState")); + } + isQuotaExceededError(error) { + return error instanceof Error && error.name === "QuotaExceededError"; + } + withThrottleProtection(cb) { + return Promise.resolve().then(() => { + try { + return cb(); + } catch (error) { + if (!this.isHistoryThrottleError(error)) { + throw error; + } + console.error(error.message); + } + }); + } + doReplaceState(data, url) { + return this.withThrottleProtection(() => { + window.history.replaceState( + { + ...data, + scrollRegions: data.scrollRegions ?? window.history.state?.scrollRegions, + documentScrollPosition: data.documentScrollPosition ?? window.history.state?.documentScrollPosition + }, + "", + url + ); + }); + } + doPushState(data, url) { + return this.withThrottleProtection(() => { + try { + window.history.pushState(data, "", url); + } catch (error) { + if (!this.isQuotaExceededError(error)) { + throw error; + } + eventHandler.fireInternalEvent("historyQuotaExceeded", url); + } + }); + } + getState(key, defaultValue) { + return this.current?.[key] ?? defaultValue; + } + deleteState(key) { + if (this.current[key] !== void 0) { + delete this.current[key]; + this.replaceState(this.current); + } + } + clearInitialState(key) { + if (this.initialState && this.initialState[key] !== void 0) { + delete this.initialState[key]; + } + } + browserHasHistoryEntry() { + return !isServer2 && !!window.history.state?.page; + } + clear() { + SessionStorage.remove(historySessionStorageKeys.key); + SessionStorage.remove(historySessionStorageKeys.iv); + } + setCurrent(page2) { + this.current = page2; + } + isValidState(state) { + return !!state.page; + } + getAllState() { + return this.current; + } +}; +if (typeof window !== "undefined" && window.history.scrollRestoration) { + window.history.scrollRestoration = "manual"; +} +var history = new History(); +var EventHandler = class { + constructor() { + this.internalListeners = []; + } + init() { + if (typeof window !== "undefined") { + window.addEventListener("popstate", this.handlePopstateEvent.bind(this)); + window.addEventListener("pageshow", this.handlePageshowEvent.bind(this)); + window.addEventListener("scroll", debounce2(Scroll.onWindowScroll.bind(Scroll), 100), true); + } + if (typeof document !== "undefined") { + document.addEventListener("scroll", debounce2(Scroll.onScroll.bind(Scroll), 100), true); + } + } + onGlobalEvent(type, callback) { + const listener = ((event) => { + const response = callback(event); + if (event.cancelable && !event.defaultPrevented && response === false) { + event.preventDefault(); + } + }); + return this.registerListener(`inertia:${type}`, listener); + } + on(event, callback) { + this.internalListeners.push({ event, listener: callback }); + return () => { + this.internalListeners = this.internalListeners.filter((listener) => listener.listener !== callback); + }; + } + onMissingHistoryItem() { + page.clear(); + this.fireInternalEvent("missingHistoryItem"); + } + fireInternalEvent(event, ...args) { + this.internalListeners.filter((listener) => listener.event === event).forEach((listener) => listener.listener(...args)); + } + registerListener(type, listener) { + document.addEventListener(type, listener); + return () => document.removeEventListener(type, listener); + } + // bfcache restores pages without firing `popstate`, so we use `pageshow` to + // re-validate encrypted history entries after `clearHistory` removed the keys. + // https://web.dev/articles/bfcache + handlePageshowEvent(event) { + if (event.persisted) { + history.decrypt().catch(() => this.onMissingHistoryItem()); + } + } + handlePopstateEvent(event) { + const state = event.state || null; + if (state === null) { + const url = hrefToUrl(page.get().url); + url.hash = window.location.hash; + history.replaceState({ ...page.getWithoutFlashData(), url: url.href }); + Scroll.reset(); + return; + } + if (!history.isValidState(state)) { + return this.onMissingHistoryItem(); + } + history.decrypt(state.page).then((data) => { + if (page.get().version !== data.version) { + this.onMissingHistoryItem(); + return; + } + router.cancelAll({ prefetch: false }); + page.setQuietly(data, { preserveState: false }).then(() => { + Scroll.restore(history.getScrollRegions()); + fireNavigateEvent(page.get()); + const pendingDeferred = {}; + const pageProps = page.get().props; + for (const [group, props] of Object.entries(data.initialDeferredProps ?? data.deferredProps ?? {})) { + const missing = props.filter((prop) => pageProps[prop] === void 0); + if (missing.length > 0) { + pendingDeferred[group] = missing; + } + } + if (Object.keys(pendingDeferred).length > 0) { + this.fireInternalEvent("loadDeferredProps", pendingDeferred); + } + }); + }).catch(() => { + this.onMissingHistoryItem(); + }); + } +}; +var eventHandler = new EventHandler(); +var NavigationType = class { + constructor() { + this.type = this.resolveType(); + } + resolveType() { + if (typeof window === "undefined") { + return "navigate"; + } + if (window.performance && window.performance.getEntriesByType && window.performance.getEntriesByType("navigation").length > 0) { + return window.performance.getEntriesByType("navigation")[0].type; + } + return "navigate"; + } + get() { + return this.type; + } + isBackForward() { + return this.type === "back_forward"; + } + isReload() { + return this.type === "reload"; + } +}; +var navigationType = new NavigationType(); +var InitialVisit = class { + static handle() { + this.clearRememberedStateOnReload(); + const scenarios = [this.handleBackForward, this.handleLocation, this.handleDefault]; + scenarios.find((handler) => handler.bind(this)()); + } + static clearRememberedStateOnReload() { + if (navigationType.isReload()) { + history.deleteState(history.rememberedState); + history.clearInitialState(history.rememberedState); + } + } + static handleBackForward() { + if (!navigationType.isBackForward() || !history.browserHasHistoryEntry()) { + return false; + } + const scrollRegions = history.getScrollRegions(); + history.decrypt().then((data) => { + page.set(data, { preserveScroll: true, preserveState: true }).then(() => { + Scroll.restore(scrollRegions); + fireNavigateEvent(page.get()); + }); + }).catch(() => { + eventHandler.onMissingHistoryItem(); + }); + return true; + } + /** + * @link https://inertiajs.com/redirects#external-redirects + */ + static handleLocation() { + if (!SessionStorage.exists(SessionStorage.locationVisitKey)) { + return false; + } + const locationVisit = SessionStorage.get(SessionStorage.locationVisitKey) || {}; + SessionStorage.remove(SessionStorage.locationVisitKey); + if (typeof window !== "undefined") { + page.setUrlHash(window.location.hash); + } + history.decrypt(page.get()).then(() => { + const rememberedState = history.getState(history.rememberedState, {}); + const scrollRegions = history.getScrollRegions(); + page.remember(rememberedState); + page.set(page.get(), { + preserveScroll: locationVisit.preserveScroll, + preserveState: true + }).then(() => { + if (locationVisit.preserveScroll) { + Scroll.restore(scrollRegions); + } + fireNavigateEvent(page.get()); + }); + }).catch(() => { + eventHandler.onMissingHistoryItem(); + }); + return true; + } + static handleDefault() { + if (typeof window !== "undefined") { + page.setUrlHash(window.location.hash); + } + page.set(page.get(), { preserveScroll: true, preserveState: true }).then(() => { + if (navigationType.isReload()) { + Scroll.restore(history.getScrollRegions()); + } else { + Scroll.scrollToAnchor(); + } + const page2 = page.get(); + fireNavigateEvent(page2); + const flash = page2.flash; + if (Object.keys(flash).length > 0) { + queueMicrotask(() => fireFlashEvent(flash)); + } + }); + } +}; +var Poll = class { + constructor(interval, cb, options) { + this.id = null; + this.throttle = false; + this.keepAlive = false; + this.cbCount = 0; + this.keepAlive = options.keepAlive ?? false; + this.cb = cb; + this.interval = interval; + if (options.autoStart ?? true) { + this.start(); + } + } + stop() { + if (this.id) { + clearInterval(this.id); + } + } + start() { + if (typeof window === "undefined") { + return; + } + this.stop(); + this.id = window.setInterval(() => { + if (!this.throttle || this.cbCount % 10 === 0) { + this.cb(); + } + if (this.throttle) { + this.cbCount++; + } + }, this.interval); + } + isInBackground(hidden) { + this.throttle = this.keepAlive ? false : hidden; + if (this.throttle) { + this.cbCount = 0; + } + } +}; +var Polls = class { + constructor() { + this.polls = []; + this.setupVisibilityListener(); + } + add(interval, cb, options) { + const poll = new Poll(interval, cb, options); + this.polls.push(poll); + return { + stop: () => poll.stop(), + start: () => poll.start() + }; + } + clear() { + this.polls.forEach((poll) => poll.stop()); + this.polls = []; + } + setupVisibilityListener() { + if (typeof document === "undefined") { + return; + } + document.addEventListener( + "visibilitychange", + () => { + this.polls.forEach((poll) => poll.isInBackground(document.hidden)); + }, + false + ); + } +}; +var polls = new Polls(); +var RequestParams = class _RequestParams { + constructor(params) { + this.callbacks = []; + if (!params.prefetch) { + this.params = params; + } else { + const wrappedCallbacks = { + onBefore: this.wrapCallback(params, "onBefore"), + onBeforeUpdate: this.wrapCallback(params, "onBeforeUpdate"), + onStart: this.wrapCallback(params, "onStart"), + onProgress: this.wrapCallback(params, "onProgress"), + onFinish: this.wrapCallback(params, "onFinish"), + onCancel: this.wrapCallback(params, "onCancel"), + onSuccess: this.wrapCallback(params, "onSuccess"), + onError: this.wrapCallback(params, "onError"), + onFlash: this.wrapCallback(params, "onFlash"), + onCancelToken: this.wrapCallback(params, "onCancelToken"), + onPrefetched: this.wrapCallback(params, "onPrefetched"), + onPrefetching: this.wrapCallback(params, "onPrefetching") + }; + this.params = { + ...params, + ...wrappedCallbacks, + onPrefetchResponse: params.onPrefetchResponse || (() => { + }), + onPrefetchError: params.onPrefetchError || (() => { + }) + }; + } + } + static create(params) { + return new _RequestParams(params); + } + data() { + return this.params.method === "get" ? null : this.params.data; + } + queryParams() { + return this.params.method === "get" ? this.params.data : {}; + } + isPartial() { + return this.params.only.length > 0 || this.params.except.length > 0 || this.params.reset.length > 0; + } + isPrefetch() { + return this.params.prefetch === true; + } + isDeferredPropsRequest() { + return this.params.deferredProps === true; + } + onCancelToken(cb) { + this.params.onCancelToken({ + cancel: cb + }); + } + markAsFinished() { + this.params.completed = true; + this.params.cancelled = false; + this.params.interrupted = false; + } + markAsCancelled({ cancelled = true, interrupted = false }) { + this.params.onCancel(); + this.params.completed = false; + this.params.cancelled = cancelled; + this.params.interrupted = interrupted; + } + wasCancelledAtAll() { + return this.params.cancelled || this.params.interrupted; + } + onFinish() { + this.params.onFinish(this.params); + } + onStart() { + this.params.onStart(this.params); + } + onPrefetching() { + this.params.onPrefetching(this.params); + } + onPrefetchResponse(response) { + if (this.params.onPrefetchResponse) { + this.params.onPrefetchResponse(response); + } + } + onPrefetchError(error) { + if (this.params.onPrefetchError) { + this.params.onPrefetchError(error); + } + } + all() { + return this.params; + } + headers() { + const headers = { + ...this.params.headers + }; + if (this.isPartial()) { + headers["X-Inertia-Partial-Component"] = page.get().component; + } + const only = this.params.only.concat(this.params.reset); + if (only.length > 0) { + headers["X-Inertia-Partial-Data"] = only.join(","); + } + if (this.params.except.length > 0) { + headers["X-Inertia-Partial-Except"] = this.params.except.join(","); + } + if (this.params.reset.length > 0) { + headers["X-Inertia-Reset"] = this.params.reset.join(","); + } + if (this.params.errorBag && this.params.errorBag.length > 0) { + headers["X-Inertia-Error-Bag"] = this.params.errorBag; + } + return headers; + } + setPreserveOptions(page2) { + this.params.preserveScroll = _RequestParams.resolvePreserveOption(this.params.preserveScroll, page2); + this.params.preserveState = _RequestParams.resolvePreserveOption(this.params.preserveState, page2); + } + runCallbacks() { + this.callbacks.forEach(({ name, args }) => { + this.params[name](...args); + }); + } + merge(toMerge) { + this.params = { + ...this.params, + ...toMerge + }; + } + wrapCallback(params, name) { + return (...args) => { + this.recordCallback(name, args); + params[name](...args); + }; + } + recordCallback(name, args) { + this.callbacks.push({ name, args }); + } + static resolvePreserveOption(value, page2) { + if (typeof value === "function") { + return value(page2); + } + if (value === "errors") { + return Object.keys(page2.props.errors || {}).length > 0; + } + return value; + } +}; +var modal_default = { + modal: null, + listener: null, + createIframeAndPage(html) { + if (typeof html === "object") { + html = `All Inertia requests must receive a valid Inertia response, however a plain JSON response was received.
${JSON.stringify( + html + )}`; + } + const page2 = document.createElement("html"); + page2.innerHTML = html; + page2.querySelectorAll("a").forEach((a) => a.setAttribute("target", "_top")); + const iframe = document.createElement("iframe"); + iframe.style.backgroundColor = "white"; + iframe.style.borderRadius = "5px"; + iframe.style.width = "100%"; + iframe.style.height = "100%"; + return { iframe, page: page2 }; + }, + show(html) { + const { iframe, page: page2 } = this.createIframeAndPage(html); + this.modal = document.createElement("div"); + this.modal.style.position = "fixed"; + this.modal.style.width = "100vw"; + this.modal.style.height = "100vh"; + this.modal.style.padding = "50px"; + this.modal.style.boxSizing = "border-box"; + this.modal.style.backgroundColor = "rgba(0, 0, 0, .6)"; + this.modal.style.zIndex = 2e5; + this.modal.addEventListener("click", () => this.hide()); + this.modal.appendChild(iframe); + document.body.prepend(this.modal); + document.body.style.overflow = "hidden"; + if (!iframe.contentWindow) { + throw new Error("iframe not yet ready."); + } + iframe.contentWindow.document.open(); + iframe.contentWindow.document.write(page2.outerHTML); + iframe.contentWindow.document.close(); + this.listener = this.hideOnEscape.bind(this); + document.addEventListener("keydown", this.listener); + }, + hide() { + this.modal.outerHTML = ""; + this.modal = null; + document.body.style.overflow = "visible"; + document.removeEventListener("keydown", this.listener); + }, + hideOnEscape(event) { + if (event.keyCode === 27) { + this.hide(); + } + } +}; +var dialog_default = { + show(html) { + const { iframe, page: page2 } = modal_default.createIframeAndPage(html); + iframe.style.boxSizing = "border-box"; + iframe.style.display = "block"; + const dialog = document.createElement("dialog"); + dialog.id = "inertia-error-dialog"; + Object.assign(dialog.style, { + width: "calc(100vw - 100px)", + height: "calc(100vh - 100px)", + padding: "0", + margin: "auto", + border: "none", + backgroundColor: "transparent" + }); + const dialogStyleElement = document.createElement("style"); + dialogStyleElement.textContent = ` + dialog#inertia-error-dialog::backdrop { + background-color: rgba(0, 0, 0, 0.6); + } + + dialog#inertia-error-dialog:focus { + outline: none; + } + `; + document.head.appendChild(dialogStyleElement); + dialog.addEventListener("click", (event) => { + if (event.target === dialog) { + dialog.close(); + } + }); + dialog.addEventListener("close", () => { + dialogStyleElement.remove(); + dialog.remove(); + }); + dialog.appendChild(iframe); + document.body.prepend(dialog); + dialog.showModal(); + dialog.focus(); + if (!iframe.contentWindow) { + throw new Error("iframe not yet ready."); + } + iframe.contentWindow.document.open(); + iframe.contentWindow.document.write(page2.outerHTML); + iframe.contentWindow.document.close(); + } +}; +var queue2 = new Queue(); +var Response = class _Response { + constructor(requestParams, response, originatingPage) { + this.requestParams = requestParams; + this.response = response; + this.originatingPage = originatingPage; + this.wasPrefetched = false; + } + static create(params, response, originatingPage) { + return new _Response(params, response, originatingPage); + } + async handlePrefetch() { + if (isSameUrlWithoutHash(this.requestParams.all().url, window.location)) { + this.handle(); + } + } + async handle() { + return queue2.add(() => this.process()); + } + async process() { + if (this.requestParams.all().prefetch) { + this.wasPrefetched = true; + this.requestParams.all().prefetch = false; + this.requestParams.all().onPrefetched(this.response, this.requestParams.all()); + firePrefetchedEvent(this.response, this.requestParams.all()); + return Promise.resolve(); + } + this.requestParams.runCallbacks(); + if (!this.isInertiaResponse()) { + return this.handleNonInertiaResponse(); + } + await history.processQueue(); + history.preserveUrl = this.requestParams.all().preserveUrl; + const previousFlash = page.get().flash; + await this.setPage(); + const errors = page.get().props.errors || {}; + if (Object.keys(errors).length > 0) { + const scopedErrors = this.getScopedErrors(errors); + fireErrorEvent(scopedErrors); + return this.requestParams.all().onError(scopedErrors); + } + router.flushByCacheTags(this.requestParams.all().invalidateCacheTags || []); + if (!this.wasPrefetched) { + router.flush(page.get().url); + } + const { flash } = page.get(); + if (Object.keys(flash).length > 0 && (!this.requestParams.isPartial() || !isEqual_default(flash, previousFlash))) { + fireFlashEvent(flash); + this.requestParams.all().onFlash(flash); + } + fireSuccessEvent(page.get()); + await this.requestParams.all().onSuccess(page.get()); + history.preserveUrl = false; + } + mergeParams(params) { + this.requestParams.merge(params); + } + getPageResponse() { + const data = this.getDataFromResponse(this.response.data); + if (typeof data === "object") { + return this.response.data = { ...data, flash: data.flash ?? {} }; + } + return this.response.data = data; + } + async handleNonInertiaResponse() { + if (this.isLocationVisit()) { + const locationUrl = hrefToUrl(this.getHeader("x-inertia-location")); + setHashIfSameUrl(this.requestParams.all().url, locationUrl); + return this.locationVisit(locationUrl); + } + const response = { + ...this.response, + data: this.getDataFromResponse(this.response.data) + }; + if (fireInvalidEvent(response)) { + return config.get("future.useDialogForErrorModal") ? dialog_default.show(response.data) : modal_default.show(response.data); + } + } + isInertiaResponse() { + return this.hasHeader("x-inertia"); + } + hasStatus(status2) { + return this.response.status === status2; + } + getHeader(header) { + return this.response.headers[header]; + } + hasHeader(header) { + return this.getHeader(header) !== void 0; + } + isLocationVisit() { + return this.hasStatus(409) && this.hasHeader("x-inertia-location"); + } + /** + * @link https://inertiajs.com/redirects#external-redirects + */ + locationVisit(url) { + try { + SessionStorage.set(SessionStorage.locationVisitKey, { + preserveScroll: this.requestParams.all().preserveScroll === true + }); + if (typeof window === "undefined") { + return; + } + if (isSameUrlWithoutHash(window.location, url)) { + window.location.reload(); + } else { + window.location.href = url.href; + } + } catch (error) { + return false; + } + } + async setPage() { + const pageResponse = this.getPageResponse(); + if (!this.shouldSetPage(pageResponse)) { + return Promise.resolve(); + } + this.mergeProps(pageResponse); + page.mergeOncePropsIntoResponse(pageResponse); + this.preserveEqualProps(pageResponse); + await this.setRememberedState(pageResponse); + this.requestParams.setPreserveOptions(pageResponse); + pageResponse.url = history.preserveUrl ? page.get().url : this.pageUrl(pageResponse); + this.requestParams.all().onBeforeUpdate(pageResponse); + fireBeforeUpdateEvent(pageResponse); + return page.set(pageResponse, { + replace: this.requestParams.all().replace, + preserveScroll: this.requestParams.all().preserveScroll, + preserveState: this.requestParams.all().preserveState, + viewTransition: this.requestParams.all().viewTransition + }); + } + getDataFromResponse(response) { + if (typeof response !== "string") { + return response; + } + try { + return JSON.parse(response); + } catch (error) { + return response; + } + } + shouldSetPage(pageResponse) { + if (!this.requestParams.all().async) { + return true; + } + if (this.originatingPage.component !== pageResponse.component) { + return true; + } + if (this.originatingPage.component !== page.get().component) { + return false; + } + const originatingUrl = hrefToUrl(this.originatingPage.url); + const currentPageUrl = hrefToUrl(page.get().url); + return originatingUrl.origin === currentPageUrl.origin && originatingUrl.pathname === currentPageUrl.pathname; + } + pageUrl(pageResponse) { + const responseUrl = hrefToUrl(pageResponse.url); + setHashIfSameUrl(this.requestParams.all().url, responseUrl); + return responseUrl.pathname + responseUrl.search + responseUrl.hash; + } + preserveEqualProps(pageResponse) { + if (pageResponse.component !== page.get().component || config.get("future.preserveEqualProps") !== true) { + return; + } + const currentPageProps = page.get().props; + Object.entries(pageResponse.props).forEach(([key, value]) => { + if (isEqual_default(value, currentPageProps[key])) { + pageResponse.props[key] = currentPageProps[key]; + } + }); + } + mergeProps(pageResponse) { + if (!this.requestParams.isPartial() || pageResponse.component !== page.get().component) { + return; + } + const propsToAppend = pageResponse.mergeProps || []; + const propsToPrepend = pageResponse.prependProps || []; + const propsToDeepMerge = pageResponse.deepMergeProps || []; + const matchPropsOn = pageResponse.matchPropsOn || []; + const mergeProp = (prop, shouldAppend) => { + const currentProp = get_default(page.get().props, prop); + const incomingProp = get_default(pageResponse.props, prop); + if (Array.isArray(incomingProp)) { + const newArray = this.mergeOrMatchItems( + currentProp || [], + incomingProp, + prop, + matchPropsOn, + shouldAppend + ); + set_default(pageResponse.props, prop, newArray); + } else if (typeof incomingProp === "object" && incomingProp !== null) { + const newObject = { + ...currentProp || {}, + ...incomingProp + }; + set_default(pageResponse.props, prop, newObject); + } + }; + propsToAppend.forEach((prop) => mergeProp(prop, true)); + propsToPrepend.forEach((prop) => mergeProp(prop, false)); + propsToDeepMerge.forEach((prop) => { + const currentProp = page.get().props[prop]; + const incomingProp = pageResponse.props[prop]; + const deepMerge = (target, source, matchProp) => { + if (Array.isArray(source)) { + return this.mergeOrMatchItems(target, source, matchProp, matchPropsOn); + } + if (typeof source === "object" && source !== null) { + return Object.keys(source).reduce( + (acc, key) => { + acc[key] = deepMerge(target ? target[key] : void 0, source[key], `${matchProp}.${key}`); + return acc; + }, + { ...target } + ); + } + return source; + }; + pageResponse.props[prop] = deepMerge(currentProp, incomingProp, prop); + }); + pageResponse.props = { ...page.get().props, ...pageResponse.props }; + if (this.requestParams.isDeferredPropsRequest()) { + const currentErrors = page.get().props.errors; + if (currentErrors && Object.keys(currentErrors).length > 0) { + pageResponse.props.errors = currentErrors; + } + } + if (page.get().scrollProps) { + pageResponse.scrollProps = { + ...page.get().scrollProps || {}, + ...pageResponse.scrollProps || {} + }; + } + if (page.hasOnceProps()) { + pageResponse.onceProps = { + ...page.get().onceProps || {}, + ...pageResponse.onceProps || {} + }; + } + pageResponse.flash = { + ...page.get().flash, + ...this.requestParams.isDeferredPropsRequest() ? {} : pageResponse.flash + }; + const currentOriginalDeferred = page.get().initialDeferredProps; + if (currentOriginalDeferred && Object.keys(currentOriginalDeferred).length > 0) { + pageResponse.initialDeferredProps = currentOriginalDeferred; + } + } + mergeOrMatchItems(existingItems, newItems, matchProp, matchPropsOn, shouldAppend = true) { + const items = Array.isArray(existingItems) ? existingItems : []; + const matchingKey = matchPropsOn.find((key) => { + const keyPath = key.split(".").slice(0, -1).join("."); + return keyPath === matchProp; + }); + if (!matchingKey) { + return shouldAppend ? [...items, ...newItems] : [...newItems, ...items]; + } + const uniqueProperty = matchingKey.split(".").pop() || ""; + const newItemsMap = /* @__PURE__ */ new Map(); + newItems.forEach((item) => { + if (this.hasUniqueProperty(item, uniqueProperty)) { + newItemsMap.set(item[uniqueProperty], item); + } + }); + return shouldAppend ? this.appendWithMatching(items, newItems, newItemsMap, uniqueProperty) : this.prependWithMatching(items, newItems, newItemsMap, uniqueProperty); + } + appendWithMatching(existingItems, newItems, newItemsMap, uniqueProperty) { + const updatedExisting = existingItems.map((item) => { + if (this.hasUniqueProperty(item, uniqueProperty) && newItemsMap.has(item[uniqueProperty])) { + return newItemsMap.get(item[uniqueProperty]); + } + return item; + }); + const newItemsToAdd = newItems.filter((item) => { + if (!this.hasUniqueProperty(item, uniqueProperty)) { + return true; + } + return !existingItems.some( + (existing) => this.hasUniqueProperty(existing, uniqueProperty) && existing[uniqueProperty] === item[uniqueProperty] + ); + }); + return [...updatedExisting, ...newItemsToAdd]; + } + prependWithMatching(existingItems, newItems, newItemsMap, uniqueProperty) { + const untouchedExisting = existingItems.filter((item) => { + if (this.hasUniqueProperty(item, uniqueProperty)) { + return !newItemsMap.has(item[uniqueProperty]); + } + return true; + }); + return [...newItems, ...untouchedExisting]; + } + hasUniqueProperty(item, property) { + return item && typeof item === "object" && property in item; + } + async setRememberedState(pageResponse) { + const rememberedState = await history.getState(history.rememberedState, {}); + if (this.requestParams.all().preserveState && rememberedState && pageResponse.component === page.get().component) { + pageResponse.rememberedState = rememberedState; + } + } + getScopedErrors(errors) { + if (!this.requestParams.all().errorBag) { + return errors; + } + return errors[this.requestParams.all().errorBag || ""] || {}; + } +}; +var Request = class _Request { + constructor(params, page2) { + this.page = page2; + this.requestHasFinished = false; + this.requestParams = RequestParams.create(params); + this.cancelToken = new AbortController(); + } + static create(params, page2) { + return new _Request(params, page2); + } + isPrefetch() { + return this.requestParams.isPrefetch(); + } + async send() { + this.requestParams.onCancelToken(() => this.cancel({ cancelled: true })); + fireStartEvent(this.requestParams.all()); + this.requestParams.onStart(); + if (this.requestParams.all().prefetch) { + this.requestParams.onPrefetching(); + firePrefetchingEvent(this.requestParams.all()); + } + const originallyPrefetch = this.requestParams.all().prefetch; + return axios_default({ + method: this.requestParams.all().method, + url: urlWithoutHash(this.requestParams.all().url).href, + data: this.requestParams.data(), + params: this.requestParams.queryParams(), + signal: this.cancelToken.signal, + headers: this.getHeaders(), + onUploadProgress: this.onProgress.bind(this), + // Why text? This allows us to delay JSON.parse until we're ready to use the response, + // helps with performance particularly on large responses + history encryption + responseType: "text" + }).then((response) => { + this.response = Response.create(this.requestParams, response, this.page); + return this.response.handle(); + }).catch((error) => { + if (error?.response) { + this.response = Response.create(this.requestParams, error.response, this.page); + return this.response.handle(); + } + return Promise.reject(error); + }).catch((error) => { + if (axios_default.isCancel(error)) { + return; + } + if (fireExceptionEvent(error)) { + if (originallyPrefetch) { + this.requestParams.onPrefetchError(error); + } + return Promise.reject(error); + } + }).finally(() => { + this.finish(); + if (originallyPrefetch && this.response) { + this.requestParams.onPrefetchResponse(this.response); + } + }); + } + finish() { + if (this.requestParams.wasCancelledAtAll()) { + return; + } + this.requestParams.markAsFinished(); + this.fireFinishEvents(); + } + fireFinishEvents() { + if (this.requestHasFinished) { + return; + } + this.requestHasFinished = true; + fireFinishEvent(this.requestParams.all()); + this.requestParams.onFinish(); + } + cancel({ cancelled = false, interrupted = false }) { + if (this.requestHasFinished) { + return; + } + this.cancelToken.abort(); + this.requestParams.markAsCancelled({ cancelled, interrupted }); + this.fireFinishEvents(); + } + onProgress(progress32) { + if (this.requestParams.data() instanceof FormData) { + progress32.percentage = progress32.progress ? Math.round(progress32.progress * 100) : 0; + fireProgressEvent(progress32); + this.requestParams.all().onProgress(progress32); + } + } + getHeaders() { + const headers = { + ...this.requestParams.headers(), + Accept: "text/html, application/xhtml+xml", + "X-Requested-With": "XMLHttpRequest", + "X-Inertia": true + }; + const page2 = page.get(); + if (page2.version) { + headers["X-Inertia-Version"] = page2.version; + } + const onceProps = Object.entries(page2.onceProps || {}).filter(([, onceProp]) => { + if (page2.props[onceProp.prop] === void 0) { + return false; + } + return !onceProp.expiresAt || onceProp.expiresAt > Date.now(); + }).map(([key]) => key); + if (onceProps.length > 0) { + headers["X-Inertia-Except-Once-Props"] = onceProps.join(","); + } + return headers; + } +}; +var RequestStream = class { + constructor({ maxConcurrent, interruptible }) { + this.requests = []; + this.maxConcurrent = maxConcurrent; + this.interruptible = interruptible; + } + send(request2) { + this.requests.push(request2); + request2.send().then(() => { + this.requests = this.requests.filter((r) => r !== request2); + }); + } + interruptInFlight() { + this.cancel({ interrupted: true }, false); + } + cancelInFlight({ prefetch = true } = {}) { + this.requests.filter((request2) => prefetch || !request2.isPrefetch()).forEach((request2) => request2.cancel({ cancelled: true })); + } + cancel({ cancelled = false, interrupted = false } = {}, force = false) { + if (!force && !this.shouldCancel()) { + return; + } + const request2 = this.requests.shift(); + request2?.cancel({ cancelled, interrupted }); + } + shouldCancel() { + return this.interruptible && this.requests.length >= this.maxConcurrent; + } +}; +var Router = class { + constructor() { + this.syncRequestStream = new RequestStream({ + maxConcurrent: 1, + interruptible: true + }); + this.asyncRequestStream = new RequestStream({ + maxConcurrent: Infinity, + interruptible: false + }); + this.clientVisitQueue = new Queue(); + } + init({ + initialPage, + resolveComponent, + swapComponent: swapComponent2, + onFlash + }) { + page.init({ + initialPage, + resolveComponent, + swapComponent: swapComponent2, + onFlash + }); + InitialVisit.handle(); + eventHandler.init(); + eventHandler.on("missingHistoryItem", () => { + if (typeof window !== "undefined") { + this.visit(window.location.href, { preserveState: true, preserveScroll: true, replace: true }); + } + }); + eventHandler.on("loadDeferredProps", (deferredProps) => { + this.loadDeferredProps(deferredProps); + }); + eventHandler.on("historyQuotaExceeded", (url) => { + window.location.href = url; + }); + } + get(url, data = {}, options = {}) { + return this.visit(url, { ...options, method: "get", data }); + } + post(url, data = {}, options = {}) { + return this.visit(url, { preserveState: true, ...options, method: "post", data }); + } + put(url, data = {}, options = {}) { + return this.visit(url, { preserveState: true, ...options, method: "put", data }); + } + patch(url, data = {}, options = {}) { + return this.visit(url, { preserveState: true, ...options, method: "patch", data }); + } + delete(url, options = {}) { + return this.visit(url, { preserveState: true, ...options, method: "delete" }); + } + reload(options = {}) { + return this.doReload(options); + } + doReload(options = {}) { + if (typeof window === "undefined") { + return; + } + return this.visit(window.location.href, { + ...options, + preserveScroll: true, + preserveState: true, + async: true, + headers: { + ...options.headers || {}, + "Cache-Control": "no-cache" + } + }); + } + remember(data, key = "default") { + history.remember(data, key); + } + restore(key = "default") { + return history.restore(key); + } + on(type, callback) { + if (typeof window === "undefined") { + return () => { + }; + } + return eventHandler.onGlobalEvent(type, callback); + } + /** + * @deprecated Use cancelAll() instead. + */ + cancel() { + this.syncRequestStream.cancelInFlight(); + } + cancelAll({ async = true, prefetch = true, sync = true } = {}) { + if (async) { + this.asyncRequestStream.cancelInFlight({ prefetch }); + } + if (sync) { + this.syncRequestStream.cancelInFlight(); + } + } + poll(interval, requestOptions = {}, options = {}) { + return polls.add(interval, () => this.reload(requestOptions), { + autoStart: options.autoStart ?? true, + keepAlive: options.keepAlive ?? false + }); + } + visit(href, options = {}) { + const visit = this.getPendingVisit(href, { + ...options, + showProgress: options.showProgress ?? !options.async + }); + const events = this.getVisitEvents(options); + if (events.onBefore(visit) === false || !fireBeforeEvent(visit)) { + return; + } + const currentPageUrl = hrefToUrl(page.get().url); + const isPartialReload = visit.only.length > 0 || visit.except.length > 0 || visit.reset.length > 0; + const isSamePage = isPartialReload ? isSameUrlWithoutQueryOrHash(visit.url, currentPageUrl) : isSameUrlWithoutHash(visit.url, currentPageUrl); + if (!isSamePage) { + this.asyncRequestStream.cancelInFlight({ prefetch: false }); + } + if (!visit.async) { + this.syncRequestStream.interruptInFlight(); + } + if (!page.isCleared() && !visit.preserveUrl) { + Scroll.save(); + } + const requestParams = { + ...visit, + ...events + }; + const prefetched = prefetchedRequests.get(requestParams); + if (prefetched) { + progress.reveal(prefetched.inFlight); + prefetchedRequests.use(prefetched, requestParams); + } else { + progress.reveal(true); + const requestStream = visit.async ? this.asyncRequestStream : this.syncRequestStream; + requestStream.send(Request.create(requestParams, page.get())); + } + } + getCached(href, options = {}) { + return prefetchedRequests.findCached(this.getPrefetchParams(href, options)); + } + flush(href, options = {}) { + prefetchedRequests.remove(this.getPrefetchParams(href, options)); + } + flushAll() { + prefetchedRequests.removeAll(); + } + flushByCacheTags(tags) { + prefetchedRequests.removeByTags(Array.isArray(tags) ? tags : [tags]); + } + getPrefetching(href, options = {}) { + return prefetchedRequests.findInFlight(this.getPrefetchParams(href, options)); + } + prefetch(href, options = {}, prefetchOptions = {}) { + const method = options.method ?? (isUrlMethodPair(href) ? href.method : "get"); + if (method !== "get") { + throw new Error("Prefetch requests must use the GET method"); + } + const visit = this.getPendingVisit(href, { + ...options, + async: true, + showProgress: false, + prefetch: true, + viewTransition: false + }); + const visitUrl = visit.url.origin + visit.url.pathname + visit.url.search; + const currentUrl = window.location.origin + window.location.pathname + window.location.search; + if (visitUrl === currentUrl) { + return; + } + const events = this.getVisitEvents(options); + if (events.onBefore(visit) === false || !fireBeforeEvent(visit)) { + return; + } + progress.hide(); + this.asyncRequestStream.interruptInFlight(); + const requestParams = { + ...visit, + ...events + }; + const ensureCurrentPageIsSet = () => { + return new Promise((resolve) => { + const checkIfPageIsDefined = () => { + if (page.get()) { + resolve(); + } else { + setTimeout(checkIfPageIsDefined, 50); + } + }; + checkIfPageIsDefined(); + }); + }; + ensureCurrentPageIsSet().then(() => { + prefetchedRequests.add( + requestParams, + (params) => { + this.asyncRequestStream.send(Request.create(params, page.get())); + }, + { + cacheFor: config.get("prefetch.cacheFor"), + cacheTags: [], + ...prefetchOptions + } + ); + }); + } + clearHistory() { + history.clear(); + } + decryptHistory() { + return history.decrypt(); + } + resolveComponent(component) { + return page.resolve(component); + } + replace(params) { + this.clientVisit(params, { replace: true }); + } + replaceProp(name, value, options) { + this.replace({ + preserveScroll: true, + preserveState: true, + props(currentProps) { + const newValue = typeof value === "function" ? value(get_default(currentProps, name), currentProps) : value; + return set_default(cloneDeep_default(currentProps), name, newValue); + }, + ...options || {} + }); + } + appendToProp(name, value, options) { + this.replaceProp( + name, + (currentValue, currentProps) => { + const newValue = typeof value === "function" ? value(currentValue, currentProps) : value; + if (!Array.isArray(currentValue)) { + currentValue = currentValue !== void 0 ? [currentValue] : []; + } + return [...currentValue, newValue]; + }, + options + ); + } + prependToProp(name, value, options) { + this.replaceProp( + name, + (currentValue, currentProps) => { + const newValue = typeof value === "function" ? value(currentValue, currentProps) : value; + if (!Array.isArray(currentValue)) { + currentValue = currentValue !== void 0 ? [currentValue] : []; + } + return [newValue, ...currentValue]; + }, + options + ); + } + push(params) { + this.clientVisit(params); + } + flash(keyOrData, value) { + const current = page.get().flash; + let flash; + if (typeof keyOrData === "function") { + flash = keyOrData(current); + } else if (typeof keyOrData === "string") { + flash = { ...current, [keyOrData]: value }; + } else if (keyOrData && Object.keys(keyOrData).length) { + flash = { ...current, ...keyOrData }; + } else { + return; + } + page.setFlash(flash); + if (Object.keys(flash).length) { + fireFlashEvent(flash); + } + } + clientVisit(params, { replace = false } = {}) { + this.clientVisitQueue.add(() => this.performClientVisit(params, { replace })); + } + performClientVisit(params, { replace = false } = {}) { + const current = page.get(); + const onceProps = typeof params.props === "function" ? Object.fromEntries( + Object.values(current.onceProps ?? {}).map((onceProp) => [onceProp.prop, current.props[onceProp.prop]]) + ) : {}; + const props = typeof params.props === "function" ? params.props(current.props, onceProps) : params.props ?? current.props; + const flash = typeof params.flash === "function" ? params.flash(current.flash) : params.flash; + const { viewTransition, onError, onFinish, onFlash, onSuccess, ...pageParams } = params; + const page2 = { + ...current, + ...pageParams, + flash: flash ?? {}, + props + }; + const preserveScroll = RequestParams.resolvePreserveOption(params.preserveScroll ?? false, page2); + const preserveState = RequestParams.resolvePreserveOption(params.preserveState ?? false, page2); + return page.set(page2, { + replace, + preserveScroll, + preserveState, + viewTransition + }).then(() => { + const currentFlash = page.get().flash; + if (Object.keys(currentFlash).length > 0) { + fireFlashEvent(currentFlash); + onFlash?.(currentFlash); + } + const errors = page.get().props.errors || {}; + if (Object.keys(errors).length === 0) { + onSuccess?.(page.get()); + return; + } + const scopedErrors = params.errorBag ? errors[params.errorBag || ""] || {} : errors; + onError?.(scopedErrors); + }).finally(() => onFinish?.(params)); + } + getPrefetchParams(href, options) { + return { + ...this.getPendingVisit(href, { + ...options, + async: true, + showProgress: false, + prefetch: true, + viewTransition: false + }), + ...this.getVisitEvents(options) + }; + } + getPendingVisit(href, options, pendingVisitOptions = {}) { + if (isUrlMethodPair(href)) { + const urlMethodPair = href; + href = urlMethodPair.url; + options.method = options.method ?? urlMethodPair.method; + } + const defaultVisitOptionsCallback = config.get("visitOptions"); + const configuredOptions = defaultVisitOptionsCallback ? defaultVisitOptionsCallback(href.toString(), cloneDeep_default(options)) || {} : {}; + const mergedOptions = { + method: "get", + data: {}, + replace: false, + preserveScroll: false, + preserveState: false, + only: [], + except: [], + headers: {}, + errorBag: "", + forceFormData: false, + queryStringArrayFormat: "brackets", + async: false, + showProgress: true, + fresh: false, + reset: [], + preserveUrl: false, + prefetch: false, + invalidateCacheTags: [], + viewTransition: false, + ...options, + ...configuredOptions + }; + const [url, _data] = transformUrlAndData( + href, + mergedOptions.data, + mergedOptions.method, + mergedOptions.forceFormData, + mergedOptions.queryStringArrayFormat + ); + const visit = { + cancelled: false, + completed: false, + interrupted: false, + ...mergedOptions, + ...pendingVisitOptions, + url, + data: _data + }; + if (visit.prefetch) { + visit.headers["Purpose"] = "prefetch"; + } + return visit; + } + getVisitEvents(options) { + return { + onCancelToken: options.onCancelToken || (() => { + }), + onBefore: options.onBefore || (() => { + }), + onBeforeUpdate: options.onBeforeUpdate || (() => { + }), + onStart: options.onStart || (() => { + }), + onProgress: options.onProgress || (() => { + }), + onFinish: options.onFinish || (() => { + }), + onCancel: options.onCancel || (() => { + }), + onSuccess: options.onSuccess || (() => { + }), + onError: options.onError || (() => { + }), + onFlash: options.onFlash || (() => { + }), + onPrefetched: options.onPrefetched || (() => { + }), + onPrefetching: options.onPrefetching || (() => { + }) + }; + } + loadDeferredProps(deferred) { + if (deferred) { + Object.entries(deferred).forEach(([_, group]) => { + this.doReload({ only: group, deferredProps: true }); + }); + } + } +}; +var UseFormUtils = class { + /** + * Creates a callback that returns a UrlMethodPair. + * + * createWayfinderCallback(urlMethodPair) + * createWayfinderCallback(method, url) + * createWayfinderCallback(() => urlMethodPair) + * createWayfinderCallback(() => method, () => url) + */ + static createWayfinderCallback(...args) { + return () => { + if (args.length === 1) { + return isUrlMethodPair(args[0]) ? args[0] : args[0](); + } + return { + method: typeof args[0] === "function" ? args[0]() : args[0], + url: typeof args[1] === "function" ? args[1]() : args[1] + }; + }; + } + /** + * Parses all useForm() arguments into { rememberKey, data, precognitionEndpoint }. + * + * useForm() + * useForm(data) + * useForm(rememberKey, data) + * useForm(method, url, data) + * useForm(urlMethodPair, data) + * + */ + static parseUseFormArguments(...args) { + if (args.length === 0) { + return { + rememberKey: null, + data: {}, + precognitionEndpoint: null + }; + } + if (args.length === 1) { + return { + rememberKey: null, + data: args[0], + precognitionEndpoint: null + }; + } + if (args.length === 2) { + if (typeof args[0] === "string") { + return { + rememberKey: args[0], + data: args[1], + precognitionEndpoint: null + }; + } + return { + rememberKey: null, + data: args[1], + precognitionEndpoint: this.createWayfinderCallback(args[0]) + }; + } + return { + rememberKey: null, + data: args[2], + precognitionEndpoint: this.createWayfinderCallback(args[0], args[1]) + }; + } + /** + * Parses all submission arguments into { method, url, options }. + * It uses the Precognition endpoint if no explicit method/url are provided. + * + * form.submit(method, url) + * form.submit(method, url, options) + * form.submit(urlMethodPair) + * form.submit(urlMethodPair, options) + * form.submit() + * form.submit(options) + */ + static parseSubmitArguments(args, precognitionEndpoint) { + if (args.length === 3 || args.length === 2 && typeof args[0] === "string") { + return { method: args[0], url: args[1], options: args[2] ?? {} }; + } + if (isUrlMethodPair(args[0])) { + return { ...args[0], options: args[1] ?? {} }; + } + return { ...precognitionEndpoint(), options: args[0] ?? {} }; + } + /** + * Merges headers into the Precognition validate() arguments. + */ + static mergeHeadersForValidation(field, config22, headers) { + const merge3 = (config3) => { + config3.headers = { + ...headers ?? {}, + ...config3.headers ?? {} + }; + return config3; + }; + if (field && typeof field === "object" && !("target" in field)) { + field = merge3(field); + } else if (config22 && typeof config22 === "object") { + config22 = merge3(config22); + } else if (typeof field === "string") { + config22 = merge3(config22 ?? {}); + } else { + field = merge3(field ?? {}); + } + return [field, config22]; + } +}; +function undotKey(key) { + if (!key.includes(".")) { + return key; + } + const transformSegment = (segment) => { + if (segment.startsWith("[") && segment.endsWith("]")) { + return segment; + } + return segment.split(".").reduce((result, part, index) => index === 0 ? part : `${result}[${part}]`); + }; + return key.replace(/\\\./g, "__ESCAPED_DOT__").split(/(\[[^\]]*\])/).filter(Boolean).map(transformSegment).join("").replace(/__ESCAPED_DOT__/g, "."); +} +function parseKey(key) { + const path = []; + const pattern = /([^\[\]]+)|\[(\d*)\]/g; + let match; + while ((match = pattern.exec(key)) !== null) { + if (match[1] !== void 0) { + path.push(match[1]); + } else if (match[2] !== void 0) { + path.push(match[2] === "" ? "" : Number(match[2])); + } + } + return path; +} +function setNestedObject(obj, path, value) { + let current = obj; + for (let i = 0; i < path.length - 1; i++) { + if (!(path[i] in current)) { + current[path[i]] = {}; + } + current = current[path[i]]; + } + current[path[path.length - 1]] = value; +} +function objectHasSequentialNumericKeys(value) { + const keys2 = Object.keys(value); + const numericKeys = keys2.filter((k) => /^\d+$/.test(k)).map(Number).sort((a, b) => a - b); + return keys2.length === numericKeys.length && numericKeys.length > 0 && numericKeys[0] === 0 && numericKeys.every((n, i) => n === i); +} +function convertSequentialObjectsToArrays(value) { + if (Array.isArray(value)) { + return value.map(convertSequentialObjectsToArrays); + } + if (typeof value !== "object" || value === null || isFile2(value)) { + return value; + } + if (objectHasSequentialNumericKeys(value)) { + const result2 = []; + for (let i = 0; i < Object.keys(value).length; i++) { + result2[i] = convertSequentialObjectsToArrays(value[i]); + } + return result2; + } + const result = {}; + for (const key in value) { + result[key] = convertSequentialObjectsToArrays(value[key]); + } + return result; +} +function formDataToObject(source) { + const form = {}; + for (const [key, value] of source.entries()) { + if (value instanceof File && value.size === 0 && value.name === "") { + continue; + } + const path = parseKey(undotKey(key)); + if (path[path.length - 1] === "") { + const arrayPath = path.slice(0, -1); + const existing = get_default(form, arrayPath); + if (Array.isArray(existing)) { + existing.push(value); + } else if (existing && typeof existing === "object" && !isFile2(existing)) { + const numericKeys = Object.keys(existing).filter((k) => /^\d+$/.test(k)).map(Number).sort((a, b) => a - b); + set_default(form, arrayPath, numericKeys.length > 0 ? [...numericKeys.map((k) => existing[k]), value] : [value]); + } else { + set_default(form, arrayPath, [value]); + } + continue; + } + setNestedObject(form, path.map(String), value); + } + return convertSequentialObjectsToArrays(form); +} +var Renderer = { + preferredAttribute() { + return config.get("future.useDataInertiaHeadAttribute") ? "data-inertia" : "inertia"; + }, + buildDOMElement(tag) { + const template = document.createElement("template"); + template.innerHTML = tag; + const node = template.content.firstChild; + if (!tag.startsWith(" + + +
+ + + + """); + } +} diff --git a/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs b/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs index 564b9f8e..39a097fc 100644 --- a/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs +++ b/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs @@ -31,7 +31,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context) GenerateRazorComponentExtensions(spc, data.Modules); if (data.DtoTypes.Length > 0) + { GenerateJsonResolver(spc, data.DtoTypes); + GenerateTypeScriptDefinitions(spc, data.DtoTypes); + } } ); } @@ -436,6 +439,86 @@ ImmutableArray dtoTypes ); } + private static void GenerateTypeScriptDefinitions( + SourceProductionContext context, + ImmutableArray dtoTypes + ) + { + var sb = new StringBuilder(); + sb.AppendLine("// "); + sb.AppendLine("#if SIMPLEMODULE_TS"); + sb.AppendLine("/*"); + sb.AppendLine("// TypeScript interfaces generated from [Dto] types"); + sb.AppendLine(); + + foreach (var dto in dtoTypes) + { + var typeName = dto.FullyQualifiedName; + var shortName = typeName.Contains(".") + ? typeName.Substring(typeName.LastIndexOf('.') + 1) + : typeName; + shortName = shortName.Replace("global::", ""); + + sb.AppendLine($"export interface {shortName} {{"); + foreach (var prop in dto.Properties) + { + var tsType = MapCSharpTypeToTypeScript(prop.TypeFqn); + var camelName = char.ToLowerInvariant(prop.Name[0]) + prop.Name.Substring(1); + sb.AppendLine($" {camelName}: {tsType};"); + } + sb.AppendLine("}"); + sb.AppendLine(); + } + + sb.AppendLine("*/"); + sb.AppendLine("#endif"); + + context.AddSource( + "DtoTypeScript.g.cs", + SourceText.From(sb.ToString(), Encoding.UTF8) + ); + } + + private static string MapCSharpTypeToTypeScript(string typeFqn) + { + var type = typeFqn.Replace("global::", ""); + + // Nullable → T | null + if (type.StartsWith("System.Nullable<", StringComparison.Ordinal) && type.EndsWith(">", StringComparison.Ordinal)) + { + var inner = type.Substring("System.Nullable<".Length, type.Length - "System.Nullable<".Length - 1); + return MapCSharpTypeToTypeScript(inner) + " | null"; + } + + // Collection types + if (type.StartsWith("System.Collections.Generic.List<", StringComparison.Ordinal) + || type.StartsWith("System.Collections.Generic.IList<", StringComparison.Ordinal) + || type.StartsWith("System.Collections.Generic.IEnumerable<", StringComparison.Ordinal) + || type.StartsWith("System.Collections.Generic.IReadOnlyList<", StringComparison.Ordinal) + || type.StartsWith("System.Collections.Generic.ICollection<", StringComparison.Ordinal)) + { + var start = type.IndexOf('<') + 1; + var inner = type.Substring(start, type.Length - start - 1); + return MapCSharpTypeToTypeScript(inner) + "[]"; + } + + return type switch + { + "string" or "System.String" => "string", + "int" or "System.Int32" => "number", + "long" or "System.Int64" => "number", + "short" or "System.Int16" => "number", + "byte" or "System.Byte" => "number", + "float" or "System.Single" => "number", + "double" or "System.Double" => "number", + "decimal" or "System.Decimal" => "number", + "bool" or "System.Boolean" => "boolean", + "System.DateTime" or "System.DateTimeOffset" or "System.DateOnly" or "System.TimeOnly" => "string", + "System.Guid" => "string", + _ => "any", + }; + } + private static bool HasComponentBaseDescendant( INamespaceSymbol namespaceSymbol, INamedTypeSymbol componentBaseSymbol diff --git a/src/modules/Products/src/Products/Pages/Browse.tsx b/src/modules/Products/src/Products/Pages/Browse.tsx new file mode 100644 index 00000000..ee581af4 --- /dev/null +++ b/src/modules/Products/src/Products/Pages/Browse.tsx @@ -0,0 +1,26 @@ +interface Product { + id: number; + name: string; + price: number; +} + +export default function Browse({ products }: { products: Product[] }) { + return ( +
+

Products

+
    + {products.map((p) => ( +
  • + {p.name} + + ${p.price.toFixed(2)} + +
  • + ))} +
+
+ ); +} diff --git a/src/modules/Products/src/Products/Pages/index.ts b/src/modules/Products/src/Products/Pages/index.ts new file mode 100644 index 00000000..b8434494 --- /dev/null +++ b/src/modules/Products/src/Products/Pages/index.ts @@ -0,0 +1,5 @@ +import Browse from './Browse'; + +export const pages: Record = { + 'Products/Browse': Browse, +}; diff --git a/src/modules/Products/src/Products/Products.csproj b/src/modules/Products/src/Products/Products.csproj index 34f43895..fd99a27c 100644 --- a/src/modules/Products/src/Products/Products.csproj +++ b/src/modules/Products/src/Products/Products.csproj @@ -10,4 +10,7 @@ + + + diff --git a/src/modules/Products/src/Products/ProductsModule.cs b/src/modules/Products/src/Products/ProductsModule.cs index 4de58913..3d7a1d80 100644 --- a/src/modules/Products/src/Products/ProductsModule.cs +++ b/src/modules/Products/src/Products/ProductsModule.cs @@ -1,8 +1,10 @@ using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using SimpleModule.Core; +using SimpleModule.Core.Inertia; using SimpleModule.Database; using SimpleModule.Products.Contracts; using SimpleModule.Products.Features.GetAllProducts; @@ -24,5 +26,12 @@ public void ConfigureEndpoints(IEndpointRouteBuilder endpoints) var group = endpoints.MapGroup(ProductsConstants.RoutePrefix); GetAllProductsEndpoint.Map(group); GetProductByIdEndpoint.Map(group); + + // Inertia page + endpoints.MapGroup("/products").MapGet( + "/browse", + async (IProductContracts products) => + Inertia.Render("Products/Browse", new { products = await products.GetAllProductsAsync() }) + ); } } diff --git a/src/modules/Products/src/Products/package.json b/src/modules/Products/src/Products/package.json new file mode 100644 index 00000000..7528d690 --- /dev/null +++ b/src/modules/Products/src/Products/package.json @@ -0,0 +1,12 @@ +{ + "private": true, + "name": "@simplemodule/products", + "scripts": { + "build": "vite build", + "watch": "vite build --watch" + }, + "peerDependencies": { + "react": "^19.0.0", + "react-dom": "^19.0.0" + } +} diff --git a/src/modules/Products/src/Products/vite.config.ts b/src/modules/Products/src/Products/vite.config.ts new file mode 100644 index 00000000..75b8c74a --- /dev/null +++ b/src/modules/Products/src/Products/vite.config.ts @@ -0,0 +1,20 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import { resolve } from 'path'; + +export default defineConfig({ + plugins: [react()], + build: { + lib: { + entry: resolve(__dirname, 'Pages/index.ts'), + formats: ['es'], + fileName: () => 'Products.pages.js', + }, + outDir: 'wwwroot', + emptyOutDir: false, + rollupOptions: { + external: ['react', 'react-dom', 'react/jsx-runtime'], + output: { inlineDynamicImports: true }, + }, + }, +}); diff --git a/src/modules/Products/src/Products/wwwroot/Products.pages.js b/src/modules/Products/src/Products/wwwroot/Products.pages.js new file mode 100644 index 00000000..48642ee4 --- /dev/null +++ b/src/modules/Products/src/Products/wwwroot/Products.pages.js @@ -0,0 +1,26 @@ +import { jsxs as r, jsx as a } from "react/jsx-runtime"; +function t({ products: s }) { + return /* @__PURE__ */ r("div", { className: "max-w-4xl mx-auto p-8", children: [ + /* @__PURE__ */ a("h1", { className: "text-3xl font-bold mb-6", children: "Products" }), + /* @__PURE__ */ a("ul", { className: "space-y-3", children: s.map((e) => /* @__PURE__ */ r( + "li", + { + className: "flex justify-between items-center p-4 rounded-lg border border-gray-200 dark:border-gray-700", + children: [ + /* @__PURE__ */ a("span", { className: "font-medium", children: e.name }), + /* @__PURE__ */ r("span", { className: "text-gray-600 dark:text-gray-400", children: [ + "$", + e.price.toFixed(2) + ] }) + ] + }, + e.id + )) }) + ] }); +} +const c = { + "Products/Browse": t +}; +export { + c as pages +}; diff --git a/src/modules/Products/tests/Products.Tests/Integration/ProductsBrowseEndpointTests.cs b/src/modules/Products/tests/Products.Tests/Integration/ProductsBrowseEndpointTests.cs new file mode 100644 index 00000000..5df91286 --- /dev/null +++ b/src/modules/Products/tests/Products.Tests/Integration/ProductsBrowseEndpointTests.cs @@ -0,0 +1,57 @@ +using System.Net; +using System.Net.Http.Json; +using System.Text.Json; +using FluentAssertions; +using SimpleModule.Tests.Shared.Fixtures; + +namespace SimpleModule.Products.Tests.Integration; + +public class ProductsBrowseEndpointTests : IClassFixture +{ + private readonly HttpClient _client; + + public ProductsBrowseEndpointTests(SimpleModuleWebApplicationFactory factory) + { + _client = factory.CreateClient(); + } + + [Fact] + public async Task Browse_ReturnsHtmlPage() + { + var response = await _client.GetAsync("/products/browse"); + response.StatusCode.Should().Be(HttpStatusCode.OK); + response.Content.Headers.ContentType?.MediaType.Should().Be("text/html"); + } + + [Fact] + public async Task Browse_WithInertia_ReturnsProductsData() + { + _client.DefaultRequestHeaders.Add("X-Inertia", "true"); + _client.DefaultRequestHeaders.Add("X-Inertia-Version", "1"); + + var response = await _client.GetAsync("/products/browse"); + response.StatusCode.Should().Be(HttpStatusCode.OK); + + var json = await response.Content.ReadFromJsonAsync(); + json.GetProperty("component").GetString().Should().Be("Products/Browse"); + + var props = json.GetProperty("props"); + props.TryGetProperty("products", out var products).Should().BeTrue(); + products.GetArrayLength().Should().BeGreaterThan(0); + } + + [Fact] + public async Task Browse_ProductsHaveExpectedFields() + { + _client.DefaultRequestHeaders.Add("X-Inertia", "true"); + _client.DefaultRequestHeaders.Add("X-Inertia-Version", "1"); + + var response = await _client.GetAsync("/products/browse"); + var json = await response.Content.ReadFromJsonAsync(); + var firstProduct = json.GetProperty("props").GetProperty("products")[0]; + + firstProduct.TryGetProperty("id", out _).Should().BeTrue(); + firstProduct.TryGetProperty("name", out _).Should().BeTrue(); + firstProduct.TryGetProperty("price", out _).Should().BeTrue(); + } +} diff --git a/src/modules/Users/src/Users/Features/Admin/AdminRolesEndpoint.cs b/src/modules/Users/src/Users/Features/Admin/AdminRolesEndpoint.cs new file mode 100644 index 00000000..91458be9 --- /dev/null +++ b/src/modules/Users/src/Users/Features/Admin/AdminRolesEndpoint.cs @@ -0,0 +1,150 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Routing; +using Microsoft.EntityFrameworkCore; +using SimpleModule.Core.Inertia; +using SimpleModule.Users.Entities; + +namespace SimpleModule.Users.Features.Admin; + +public static class AdminRolesEndpoint +{ + public static void Map(IEndpointRouteBuilder endpoints) + { + var group = endpoints + .MapGroup("/admin/roles") + .RequireAuthorization(policy => policy.RequireRole("Admin")); + + // List roles + group.MapGet("/", async ( + RoleManager roleManager, + UserManager userManager) => + { + var roles = await roleManager.Roles + .OrderBy(r => r.Name) + .ToListAsync(); + + var roleList = new List(); + foreach (var role in roles) + { + var usersInRole = role.Name is not null + ? await userManager.GetUsersInRoleAsync(role.Name) + : []; + roleList.Add(new + { + id = role.Id, + name = role.Name, + description = role.Description, + userCount = usersInRole.Count, + createdAt = role.CreatedAt.ToString("O"), + }); + } + + return Inertia.Render("Users/Admin/Roles", new { roles = roleList }); + }); + + // Create role page + group.MapGet("/create", () => + Inertia.Render("Users/Admin/RolesCreate")); + + // Create role + group.MapPost("/", async ( + HttpContext context, + RoleManager roleManager) => + { + var form = await context.Request.ReadFormAsync(); + var name = form["name"].ToString().Trim(); + var description = form["description"].ToString().Trim(); + + if (string.IsNullOrEmpty(name)) + return Results.Redirect("/admin/roles/create"); + + var role = new ApplicationRole + { + Name = name, + Description = string.IsNullOrEmpty(description) ? null : description, + }; + + var result = await roleManager.CreateAsync(role); + if (!result.Succeeded) + return Results.Redirect("/admin/roles/create"); + + return Results.Redirect("/admin/roles"); + }); + + // Edit role page + group.MapGet("/{id}/edit", async ( + string id, + RoleManager roleManager, + UserManager userManager) => + { + var role = await roleManager.FindByIdAsync(id); + if (role is null) + return Results.NotFound(); + + var usersInRole = role.Name is not null + ? await userManager.GetUsersInRoleAsync(role.Name) + : []; + + return Inertia.Render("Users/Admin/RolesEdit", new + { + role = new + { + id = role.Id, + name = role.Name, + description = role.Description, + createdAt = role.CreatedAt.ToString("O"), + }, + users = usersInRole.Select(u => new + { + id = u.Id, + displayName = u.DisplayName, + email = u.Email, + }).ToList(), + }); + }); + + // Update role + group.MapPost("/{id}", async ( + string id, + HttpContext context, + RoleManager roleManager) => + { + var role = await roleManager.FindByIdAsync(id); + if (role is null) + return Results.NotFound(); + + var form = await context.Request.ReadFormAsync(); + role.Name = form["name"].ToString().Trim(); + var description = form["description"].ToString().Trim(); + role.Description = string.IsNullOrEmpty(description) ? null : description; + + await roleManager.UpdateAsync(role); + + return Results.Redirect($"/admin/roles/{id}/edit"); + }); + + // Delete role + group.MapDelete("/{id}", async ( + string id, + RoleManager roleManager, + UserManager userManager) => + { + var role = await roleManager.FindByIdAsync(id); + if (role is null) + return Results.NotFound(); + + // Don't delete if users are assigned + var usersInRole = role.Name is not null + ? await userManager.GetUsersInRoleAsync(role.Name) + : []; + if (usersInRole.Count > 0) + return Results.BadRequest(new { error = "Cannot delete role with assigned users" }); + + await roleManager.DeleteAsync(role); + + return Results.Ok(); + }); + } +} diff --git a/src/modules/Users/src/Users/Features/Admin/AdminUsersEndpoint.cs b/src/modules/Users/src/Users/Features/Admin/AdminUsersEndpoint.cs new file mode 100644 index 00000000..8e21d8d1 --- /dev/null +++ b/src/modules/Users/src/Users/Features/Admin/AdminUsersEndpoint.cs @@ -0,0 +1,176 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Routing; +using Microsoft.EntityFrameworkCore; +using SimpleModule.Core.Inertia; +using SimpleModule.Users.Entities; + +namespace SimpleModule.Users.Features.Admin; + +public static class AdminUsersEndpoint +{ + private const int PageSize = 20; + + public static void Map(IEndpointRouteBuilder endpoints) + { + var group = endpoints + .MapGroup("/admin/users") + .RequireAuthorization(policy => policy.RequireRole("Admin")); + + // List users + group.MapGet("/", async ( + UserManager userManager, + RoleManager roleManager, + string? search, + int page = 1) => + { + var query = userManager.Users.AsQueryable(); + + if (!string.IsNullOrWhiteSpace(search)) + { + var pattern = $"%{search.Trim()}%"; + query = query.Where(u => + (u.Email != null && EF.Functions.Like(u.Email, pattern)) + || EF.Functions.Like(u.DisplayName, pattern) + || (u.UserName != null && EF.Functions.Like(u.UserName, pattern))); + } + + var totalCount = await query.CountAsync(); + var totalPages = (int)Math.Ceiling((double)totalCount / PageSize); + page = Math.Clamp(page, 1, Math.Max(1, totalPages)); + + var users = await query + .OrderBy(u => u.DisplayName) + .Skip((page - 1) * PageSize) + .Take(PageSize) + .ToListAsync(); + + var userList = new List(); + foreach (var user in users) + { + var roles = await userManager.GetRolesAsync(user); + userList.Add(new + { + id = user.Id, + displayName = user.DisplayName, + email = user.Email, + emailConfirmed = user.EmailConfirmed, + roles = roles.ToList(), + isLockedOut = user.LockoutEnd.HasValue && user.LockoutEnd > DateTimeOffset.UtcNow, + createdAt = user.CreatedAt.ToString("O"), + }); + } + + return Inertia.Render("Users/Admin/Users", new + { + users = userList, + search = search ?? "", + page, + totalPages, + totalCount, + }); + }); + + // Edit user page + group.MapGet("/{id}/edit", async ( + string id, + UserManager userManager, + RoleManager roleManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); + + var userRoles = await userManager.GetRolesAsync(user); + var allRoles = await roleManager.Roles.OrderBy(r => r.Name).ToListAsync(); + + return Inertia.Render("Users/Admin/UsersEdit", new + { + user = new + { + id = user.Id, + displayName = user.DisplayName, + email = user.Email, + emailConfirmed = user.EmailConfirmed, + isLockedOut = user.LockoutEnd.HasValue && user.LockoutEnd > DateTimeOffset.UtcNow, + createdAt = user.CreatedAt.ToString("O"), + lastLoginAt = user.LastLoginAt?.ToString("O"), + }, + userRoles = userRoles.ToList(), + allRoles = allRoles.Select(r => new { id = r.Id, name = r.Name, description = r.Description }).ToList(), + }); + }); + + // Update user + group.MapPost("/{id}", async ( + string id, + HttpContext context, + UserManager userManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); + + var form = await context.Request.ReadFormAsync(); + user.DisplayName = form["displayName"].ToString(); + user.Email = form["email"].ToString(); + user.EmailConfirmed = form.ContainsKey("emailConfirmed"); + + await userManager.UpdateAsync(user); + + return Results.Redirect($"/admin/users/{id}/edit"); + }); + + // Set roles + group.MapPost("/{id}/roles", async ( + string id, + HttpContext context, + UserManager userManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); + + var form = await context.Request.ReadFormAsync(); + var newRoles = form["roles"].ToArray().Where(r => !string.IsNullOrEmpty(r)).ToList(); + var currentRoles = await userManager.GetRolesAsync(user); + + await userManager.RemoveFromRolesAsync(user, currentRoles); + if (newRoles.Count > 0) + await userManager.AddToRolesAsync(user, newRoles!); + + return Results.Redirect($"/admin/users/{id}/edit"); + }); + + // Lock account + group.MapPost("/{id}/lock", async ( + string id, + UserManager userManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); + + await userManager.SetLockoutEnabledAsync(user, true); + await userManager.SetLockoutEndDateAsync(user, DateTimeOffset.UtcNow.AddYears(100)); + + return Results.Redirect($"/admin/users/{id}/edit"); + }); + + // Unlock account + group.MapPost("/{id}/unlock", async ( + string id, + UserManager userManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); + + await userManager.SetLockoutEndDateAsync(user, null); + await userManager.ResetAccessFailedCountAsync(user); + + return Results.Redirect($"/admin/users/{id}/edit"); + }); + } +} diff --git a/src/modules/Users/src/Users/Pages/Admin/Roles.tsx b/src/modules/Users/src/Users/Pages/Admin/Roles.tsx new file mode 100644 index 00000000..600f3cb3 --- /dev/null +++ b/src/modules/Users/src/Users/Pages/Admin/Roles.tsx @@ -0,0 +1,84 @@ +import { router } from '@inertiajs/react'; + +interface Role { + id: string; + name: string; + description: string | null; + userCount: number; + createdAt: string; +} + +interface Props { + roles: Role[]; +} + +export default function Roles({ roles }: Props) { + function handleDelete(id: string, name: string) { + if (!confirm(`Delete role "${name}"?`)) return; + router.delete(`/admin/roles/${id}`, { + onError: () => alert('Cannot delete role with assigned users.'), + }); + } + + return ( +
+
+

Roles

+ +
+ +
+ + + + + + + + + + + + {roles.map((role) => ( + + + + + + + + ))} + +
NameDescriptionUsersCreated
{role.name} + {role.description || '—'} + + + {role.userCount} + + + {new Date(role.createdAt).toLocaleDateString()} + +
+ + +
+
+
+
+ ); +} diff --git a/src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx b/src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx new file mode 100644 index 00000000..46cf1bd7 --- /dev/null +++ b/src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx @@ -0,0 +1,51 @@ +import { router } from '@inertiajs/react'; + +export default function RolesCreate() { + function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + router.post('/admin/roles', formData); + } + + return ( +
+
+ +

Create Role

+
+ +
+
+
+ + +
+
+ + +
+ +
+
+
+ ); +} diff --git a/src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx b/src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx new file mode 100644 index 00000000..616446df --- /dev/null +++ b/src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx @@ -0,0 +1,98 @@ +import { router } from '@inertiajs/react'; + +interface RoleDetail { + id: string; + name: string; + description: string | null; + createdAt: string; +} + +interface UserSummary { + id: string; + displayName: string; + email: string; +} + +interface Props { + role: RoleDetail; + users: UserSummary[]; +} + +export default function RolesEdit({ role, users }: Props) { + function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + router.post(`/admin/roles/${role.id}`, formData); + } + + return ( +
+
+ +

Edit Role

+
+ +
+
+
+ + +
+
+ + +
+
+ Created: {new Date(role.createdAt).toLocaleString()} +
+ +
+
+ +
+

Assigned Users ({users.length})

+ {users.length === 0 ? ( +

No users assigned to this role.

+ ) : ( +
    + {users.map((user) => ( +
  • +
    + {user.displayName || '—'} + {user.email} +
    + +
  • + ))} +
+ )} +
+
+ ); +} diff --git a/src/modules/Users/src/Users/Pages/Admin/Users.tsx b/src/modules/Users/src/Users/Pages/Admin/Users.tsx new file mode 100644 index 00000000..e995e84f --- /dev/null +++ b/src/modules/Users/src/Users/Pages/Admin/Users.tsx @@ -0,0 +1,138 @@ +import { router } from '@inertiajs/react'; +import { useState, FormEvent } from 'react'; + +interface User { + id: string; + displayName: string; + email: string; + emailConfirmed: boolean; + roles: string[]; + isLockedOut: boolean; + createdAt: string; +} + +interface Props { + users: User[]; + search: string; + page: number; + totalPages: number; + totalCount: number; +} + +export default function Users({ users, search, page, totalPages, totalCount }: Props) { + const [searchValue, setSearchValue] = useState(search); + + function handleSearch(e: FormEvent) { + e.preventDefault(); + router.get('/admin/users', { search: searchValue, page: 1 }, { preserveState: true }); + } + + function goToPage(p: number) { + router.get('/admin/users', { search: searchValue, page: p }, { preserveState: true }); + } + + return ( +
+
+

Users

+ {totalCount} total +
+ +
+ setSearchValue(e.target.value)} + placeholder="Search by name or email..." + className="flex-1 px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" + /> + +
+ +
+ + + + + + + + + + + + + {users.map((user) => ( + + + + + + + + + ))} + +
NameEmailRolesStatusCreated
{user.displayName || '—'} + {user.email} + {!user.emailConfirmed && ( + unverified + )} + +
+ {user.roles.map((role) => ( + + {role} + + ))} +
+
+ {user.isLockedOut ? ( + Locked + ) : ( + Active + )} + + {new Date(user.createdAt).toLocaleDateString()} + + +
+
+ + {totalPages > 1 && ( +
+ + + Page {page} of {totalPages} + + +
+ )} +
+ ); +} diff --git a/src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx b/src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx new file mode 100644 index 00000000..513b2405 --- /dev/null +++ b/src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx @@ -0,0 +1,167 @@ +import { router } from '@inertiajs/react'; + +interface UserDetail { + id: string; + displayName: string; + email: string; + emailConfirmed: boolean; + isLockedOut: boolean; + createdAt: string; + lastLoginAt: string | null; +} + +interface Role { + id: string; + name: string; + description: string | null; +} + +interface Props { + user: UserDetail; + userRoles: string[]; + allRoles: Role[]; +} + +export default function UsersEdit({ user, userRoles, allRoles }: Props) { + function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + router.post(`/admin/users/${user.id}`, formData); + } + + function handleRolesSubmit(e: React.FormEvent) { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + router.post(`/admin/users/${user.id}/roles`, formData); + } + + function handleLock() { + router.post(`/admin/users/${user.id}/lock`); + } + + function handleUnlock() { + router.post(`/admin/users/${user.id}/unlock`); + } + + return ( +
+
+ +

Edit User

+
+ +
+ Created: {new Date(user.createdAt).toLocaleString()} + {user.lastLoginAt && ( + Last login: {new Date(user.lastLoginAt).toLocaleString()} + )} +
+ + {/* User Details Form */} +
+

Details

+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ + {/* Roles Form */} +
+

Roles

+
+ {allRoles.map((role) => ( +
+ + +
+ ))} + {allRoles.length === 0 && ( +

No roles defined.

+ )} +
+ +
+ + {/* Lock/Unlock */} +
+

Account Status

+ {user.isLockedOut ? ( +
+

This account is locked.

+ +
+ ) : ( +
+

This account is active.

+ +
+ )} +
+
+ ); +} diff --git a/src/modules/Users/src/Users/Pages/index.ts b/src/modules/Users/src/Users/Pages/index.ts new file mode 100644 index 00000000..d21dfcde --- /dev/null +++ b/src/modules/Users/src/Users/Pages/index.ts @@ -0,0 +1,13 @@ +import Users from './Admin/Users'; +import UsersEdit from './Admin/UsersEdit'; +import Roles from './Admin/Roles'; +import RolesCreate from './Admin/RolesCreate'; +import RolesEdit from './Admin/RolesEdit'; + +export const pages: Record = { + 'Users/Admin/Users': Users, + 'Users/Admin/UsersEdit': UsersEdit, + 'Users/Admin/Roles': Roles, + 'Users/Admin/RolesCreate': RolesCreate, + 'Users/Admin/RolesEdit': RolesEdit, +}; diff --git a/src/modules/Users/src/Users/Users.csproj b/src/modules/Users/src/Users/Users.csproj index 36eb5e5e..634dbc2e 100644 --- a/src/modules/Users/src/Users/Users.csproj +++ b/src/modules/Users/src/Users/Users.csproj @@ -14,8 +14,8 @@ - + diff --git a/src/modules/Users/src/Users/UsersModule.cs b/src/modules/Users/src/Users/UsersModule.cs index 1dc0a238..1327b47c 100644 --- a/src/modules/Users/src/Users/UsersModule.cs +++ b/src/modules/Users/src/Users/UsersModule.cs @@ -12,6 +12,7 @@ using SimpleModule.Database; using SimpleModule.Users.Contracts; using SimpleModule.Users.Entities; +using SimpleModule.Users.Features.Admin; using SimpleModule.Users.Features.Connect; using SimpleModule.Users.Features.GetAllUsers; using SimpleModule.Users.Features.GetCurrentUser; @@ -196,5 +197,9 @@ await userManager.GetAuthenticatorKeyAsync(user) ?? "" } ) .RequireAuthorization(); + + // Admin endpoints + AdminUsersEndpoint.Map(endpoints); + AdminRolesEndpoint.Map(endpoints); } } diff --git a/src/modules/Users/src/Users/package.json b/src/modules/Users/src/Users/package.json index 7bd4d0af..06f794b5 100644 --- a/src/modules/Users/src/Users/package.json +++ b/src/modules/Users/src/Users/package.json @@ -2,13 +2,19 @@ "private": true, "name": "@simplemodule/users", "scripts": { - "build": "vite build", - "watch": "vite build --watch" + "build": "vite build && cross-env VITE_BUILD_TARGET=pages vite build", + "build:lib": "vite build", + "build:pages": "cross-env VITE_BUILD_TARGET=pages vite build", + "watch": "cross-env VITE_BUILD_TARGET=pages vite build --watch" }, "dependencies": { "qrcode": "^1.5.4" }, "devDependencies": { "@types/qrcode": "^1.5.6" + }, + "peerDependencies": { + "react": "^19.0.0", + "react-dom": "^19.0.0" } } diff --git a/src/modules/Users/src/Users/vite.config.ts b/src/modules/Users/src/Users/vite.config.ts index 9eaa8ce6..cadbc926 100644 --- a/src/modules/Users/src/Users/vite.config.ts +++ b/src/modules/Users/src/Users/vite.config.ts @@ -1,7 +1,10 @@ import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; import { resolve } from 'path'; -export default defineConfig({ +const buildTarget = process.env.VITE_BUILD_TARGET; + +const libConfig = defineConfig({ build: { lib: { entry: resolve(__dirname, 'Scripts/index.ts'), @@ -11,9 +14,26 @@ export default defineConfig({ outDir: 'wwwroot', emptyOutDir: false, rollupOptions: { - output: { - inlineDynamicImports: true, - }, + output: { inlineDynamicImports: true }, }, }, }); + +const pagesConfig = defineConfig({ + plugins: [react()], + build: { + lib: { + entry: resolve(__dirname, 'Pages/index.ts'), + formats: ['es'], + fileName: () => 'Users.pages.js', + }, + outDir: 'wwwroot', + emptyOutDir: false, + rollupOptions: { + external: ['react', 'react-dom', 'react/jsx-runtime', '@inertiajs/react'], + output: { inlineDynamicImports: true }, + }, + }, +}); + +export default buildTarget === 'pages' ? pagesConfig : libConfig; diff --git a/src/modules/Users/src/Users/wwwroot/Users.pages.js b/src/modules/Users/src/Users/wwwroot/Users.pages.js new file mode 100644 index 00000000..5d95443b --- /dev/null +++ b/src/modules/Users/src/Users/wwwroot/Users.pages.js @@ -0,0 +1,447 @@ +import { jsxs as t, jsx as e } from "react/jsx-runtime"; +import { router as l } from "@inertiajs/react"; +import { useState as b } from "react"; +function x({ users: r, search: i, page: a, totalPages: s, totalCount: m }) { + const [o, g] = b(i); + function d(n) { + n.preventDefault(), l.get("/admin/users", { search: o, page: 1 }, { preserveState: !0 }); + } + function c(n) { + l.get("/admin/users", { search: o, page: n }, { preserveState: !0 }); + } + return /* @__PURE__ */ t("div", { className: "max-w-6xl mx-auto p-8", children: [ + /* @__PURE__ */ t("div", { className: "flex justify-between items-center mb-6", children: [ + /* @__PURE__ */ e("h1", { className: "text-3xl font-bold", children: "Users" }), + /* @__PURE__ */ t("span", { className: "text-gray-500", children: [ + m, + " total" + ] }) + ] }), + /* @__PURE__ */ t("form", { onSubmit: d, className: "mb-6 flex gap-2", children: [ + /* @__PURE__ */ e( + "input", + { + type: "text", + value: o, + onChange: (n) => g(n.target.value), + placeholder: "Search by name or email...", + className: "flex-1 px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" + } + ), + /* @__PURE__ */ e( + "button", + { + type: "submit", + className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", + children: "Search" + } + ) + ] }), + /* @__PURE__ */ e("div", { className: "overflow-x-auto rounded-lg border border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ t("table", { className: "w-full text-left", children: [ + /* @__PURE__ */ e("thead", { className: "bg-gray-50 dark:bg-gray-800", children: /* @__PURE__ */ t("tr", { children: [ + /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Name" }), + /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Email" }), + /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Roles" }), + /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Status" }), + /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Created" }), + /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400" }) + ] }) }), + /* @__PURE__ */ e("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-700", children: r.map((n) => /* @__PURE__ */ t("tr", { className: "hover:bg-gray-50 dark:hover:bg-gray-800/50", children: [ + /* @__PURE__ */ e("td", { className: "px-4 py-3 font-medium", children: n.displayName || "—" }), + /* @__PURE__ */ t("td", { className: "px-4 py-3 text-gray-600 dark:text-gray-400", children: [ + n.email, + !n.emailConfirmed && /* @__PURE__ */ e("span", { className: "ml-2 text-xs text-amber-600 dark:text-amber-400", children: "unverified" }) + ] }), + /* @__PURE__ */ e("td", { className: "px-4 py-3", children: /* @__PURE__ */ e("div", { className: "flex gap-1 flex-wrap", children: n.roles.map((u) => /* @__PURE__ */ e( + "span", + { + className: "px-2 py-0.5 text-xs rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300", + children: u + }, + u + )) }) }), + /* @__PURE__ */ e("td", { className: "px-4 py-3", children: n.isLockedOut ? /* @__PURE__ */ e("span", { className: "text-red-600 dark:text-red-400 text-sm", children: "Locked" }) : /* @__PURE__ */ e("span", { className: "text-green-600 dark:text-green-400 text-sm", children: "Active" }) }), + /* @__PURE__ */ e("td", { className: "px-4 py-3 text-sm text-gray-500", children: new Date(n.createdAt).toLocaleDateString() }), + /* @__PURE__ */ e("td", { className: "px-4 py-3", children: /* @__PURE__ */ e( + "button", + { + onClick: () => l.get(`/admin/users/${n.id}/edit`), + className: "text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300 text-sm", + children: "Edit" + } + ) }) + ] }, n.id)) }) + ] }) }), + s > 1 && /* @__PURE__ */ t("div", { className: "flex justify-center gap-2 mt-6", children: [ + /* @__PURE__ */ e( + "button", + { + onClick: () => c(a - 1), + disabled: a <= 1, + className: "px-3 py-1 rounded border border-gray-300 dark:border-gray-600 disabled:opacity-50", + children: "Previous" + } + ), + /* @__PURE__ */ t("span", { className: "px-3 py-1 text-gray-600 dark:text-gray-400", children: [ + "Page ", + a, + " of ", + s + ] }), + /* @__PURE__ */ e( + "button", + { + onClick: () => c(a + 1), + disabled: a >= s, + className: "px-3 py-1 rounded border border-gray-300 dark:border-gray-600 disabled:opacity-50", + children: "Next" + } + ) + ] }) + ] }); +} +function h({ user: r, userRoles: i, allRoles: a }) { + function s(d) { + d.preventDefault(); + const c = new FormData(d.currentTarget); + l.post(`/admin/users/${r.id}`, c); + } + function m(d) { + d.preventDefault(); + const c = new FormData(d.currentTarget); + l.post(`/admin/users/${r.id}/roles`, c); + } + function o() { + l.post(`/admin/users/${r.id}/lock`); + } + function g() { + l.post(`/admin/users/${r.id}/unlock`); + } + return /* @__PURE__ */ t("div", { className: "max-w-3xl mx-auto p-8", children: [ + /* @__PURE__ */ t("div", { className: "flex items-center gap-4 mb-6", children: [ + /* @__PURE__ */ e( + "button", + { + onClick: () => l.get("/admin/users"), + className: "text-gray-500 hover:text-gray-700 dark:hover:text-gray-300", + children: "← Back" + } + ), + /* @__PURE__ */ e("h1", { className: "text-3xl font-bold", children: "Edit User" }) + ] }), + /* @__PURE__ */ t("div", { className: "mb-6 text-sm text-gray-500 dark:text-gray-400", children: [ + /* @__PURE__ */ t("span", { children: [ + "Created: ", + new Date(r.createdAt).toLocaleString() + ] }), + r.lastLoginAt && /* @__PURE__ */ t("span", { className: "ml-4", children: [ + "Last login: ", + new Date(r.lastLoginAt).toLocaleString() + ] }) + ] }), + /* @__PURE__ */ t("form", { onSubmit: s, className: "mb-8 p-6 rounded-lg border border-gray-200 dark:border-gray-700", children: [ + /* @__PURE__ */ e("h2", { className: "text-lg font-semibold mb-4", children: "Details" }), + /* @__PURE__ */ t("div", { className: "space-y-4", children: [ + /* @__PURE__ */ t("div", { children: [ + /* @__PURE__ */ e("label", { className: "block text-sm font-medium mb-1", children: "Display Name" }), + /* @__PURE__ */ e( + "input", + { + type: "text", + name: "displayName", + defaultValue: r.displayName, + className: "w-full px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" + } + ) + ] }), + /* @__PURE__ */ t("div", { children: [ + /* @__PURE__ */ e("label", { className: "block text-sm font-medium mb-1", children: "Email" }), + /* @__PURE__ */ e( + "input", + { + type: "email", + name: "email", + defaultValue: r.email, + className: "w-full px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" + } + ) + ] }), + /* @__PURE__ */ t("div", { className: "flex items-center gap-2", children: [ + /* @__PURE__ */ e( + "input", + { + type: "checkbox", + name: "emailConfirmed", + id: "emailConfirmed", + defaultChecked: r.emailConfirmed, + className: "rounded border-gray-300" + } + ), + /* @__PURE__ */ e("label", { htmlFor: "emailConfirmed", className: "text-sm", children: "Email confirmed" }) + ] }), + /* @__PURE__ */ e( + "button", + { + type: "submit", + className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", + children: "Save Details" + } + ) + ] }) + ] }), + /* @__PURE__ */ t("form", { onSubmit: m, className: "mb-8 p-6 rounded-lg border border-gray-200 dark:border-gray-700", children: [ + /* @__PURE__ */ e("h2", { className: "text-lg font-semibold mb-4", children: "Roles" }), + /* @__PURE__ */ t("div", { className: "space-y-2 mb-4", children: [ + a.map((d) => /* @__PURE__ */ t("div", { className: "flex items-center gap-2", children: [ + /* @__PURE__ */ e( + "input", + { + type: "checkbox", + name: "roles", + value: d.name ?? "", + id: `role-${d.id}`, + defaultChecked: i.includes(d.name ?? ""), + className: "rounded border-gray-300" + } + ), + /* @__PURE__ */ t("label", { htmlFor: `role-${d.id}`, className: "text-sm", children: [ + d.name, + d.description && /* @__PURE__ */ t("span", { className: "text-gray-500 ml-1", children: [ + "— ", + d.description + ] }) + ] }) + ] }, d.id)), + a.length === 0 && /* @__PURE__ */ e("p", { className: "text-sm text-gray-500", children: "No roles defined." }) + ] }), + /* @__PURE__ */ e( + "button", + { + type: "submit", + className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", + children: "Save Roles" + } + ) + ] }), + /* @__PURE__ */ t("div", { className: "p-6 rounded-lg border border-gray-200 dark:border-gray-700", children: [ + /* @__PURE__ */ e("h2", { className: "text-lg font-semibold mb-4", children: "Account Status" }), + r.isLockedOut ? /* @__PURE__ */ t("div", { children: [ + /* @__PURE__ */ e("p", { className: "text-sm text-red-600 dark:text-red-400 mb-3", children: "This account is locked." }), + /* @__PURE__ */ e( + "button", + { + onClick: g, + className: "px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700", + children: "Unlock Account" + } + ) + ] }) : /* @__PURE__ */ t("div", { children: [ + /* @__PURE__ */ e("p", { className: "text-sm text-green-600 dark:text-green-400 mb-3", children: "This account is active." }), + /* @__PURE__ */ e( + "button", + { + onClick: o, + className: "px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700", + children: "Lock Account" + } + ) + ] }) + ] }) + ] }); +} +function p({ roles: r }) { + function i(a, s) { + confirm(`Delete role "${s}"?`) && l.delete(`/admin/roles/${a}`, { + onError: () => alert("Cannot delete role with assigned users.") + }); + } + return /* @__PURE__ */ t("div", { className: "max-w-4xl mx-auto p-8", children: [ + /* @__PURE__ */ t("div", { className: "flex justify-between items-center mb-6", children: [ + /* @__PURE__ */ e("h1", { className: "text-3xl font-bold", children: "Roles" }), + /* @__PURE__ */ e( + "button", + { + onClick: () => l.get("/admin/roles/create"), + className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", + children: "Create Role" + } + ) + ] }), + /* @__PURE__ */ e("div", { className: "overflow-x-auto rounded-lg border border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ t("table", { className: "w-full text-left", children: [ + /* @__PURE__ */ e("thead", { className: "bg-gray-50 dark:bg-gray-800", children: /* @__PURE__ */ t("tr", { children: [ + /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Name" }), + /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Description" }), + /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Users" }), + /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Created" }), + /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400" }) + ] }) }), + /* @__PURE__ */ e("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-700", children: r.map((a) => /* @__PURE__ */ t("tr", { className: "hover:bg-gray-50 dark:hover:bg-gray-800/50", children: [ + /* @__PURE__ */ e("td", { className: "px-4 py-3 font-medium", children: a.name }), + /* @__PURE__ */ e("td", { className: "px-4 py-3 text-gray-600 dark:text-gray-400", children: a.description || "—" }), + /* @__PURE__ */ e("td", { className: "px-4 py-3", children: /* @__PURE__ */ e("span", { className: "px-2 py-0.5 text-xs rounded-full bg-gray-100 dark:bg-gray-800", children: a.userCount }) }), + /* @__PURE__ */ e("td", { className: "px-4 py-3 text-sm text-gray-500", children: new Date(a.createdAt).toLocaleDateString() }), + /* @__PURE__ */ e("td", { className: "px-4 py-3", children: /* @__PURE__ */ t("div", { className: "flex gap-3", children: [ + /* @__PURE__ */ e( + "button", + { + onClick: () => l.get(`/admin/roles/${a.id}/edit`), + className: "text-blue-600 hover:text-blue-800 dark:text-blue-400 text-sm", + children: "Edit" + } + ), + /* @__PURE__ */ e( + "button", + { + onClick: () => i(a.id, a.name), + className: "text-red-600 hover:text-red-800 dark:text-red-400 text-sm", + children: "Delete" + } + ) + ] }) }) + ] }, a.id)) }) + ] }) }) + ] }); +} +function y() { + function r(i) { + i.preventDefault(); + const a = new FormData(i.currentTarget); + l.post("/admin/roles", a); + } + return /* @__PURE__ */ t("div", { className: "max-w-xl mx-auto p-8", children: [ + /* @__PURE__ */ t("div", { className: "flex items-center gap-4 mb-6", children: [ + /* @__PURE__ */ e( + "button", + { + onClick: () => l.get("/admin/roles"), + className: "text-gray-500 hover:text-gray-700 dark:hover:text-gray-300", + children: "← Back" + } + ), + /* @__PURE__ */ e("h1", { className: "text-3xl font-bold", children: "Create Role" }) + ] }), + /* @__PURE__ */ e("form", { onSubmit: r, className: "p-6 rounded-lg border border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ t("div", { className: "space-y-4", children: [ + /* @__PURE__ */ t("div", { children: [ + /* @__PURE__ */ e("label", { className: "block text-sm font-medium mb-1", children: "Name" }), + /* @__PURE__ */ e( + "input", + { + type: "text", + name: "name", + required: !0, + className: "w-full px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" + } + ) + ] }), + /* @__PURE__ */ t("div", { children: [ + /* @__PURE__ */ e("label", { className: "block text-sm font-medium mb-1", children: "Description" }), + /* @__PURE__ */ e( + "input", + { + type: "text", + name: "description", + className: "w-full px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" + } + ) + ] }), + /* @__PURE__ */ e( + "button", + { + type: "submit", + className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", + children: "Create" + } + ) + ] }) }) + ] }); +} +function N({ role: r, users: i }) { + function a(s) { + s.preventDefault(); + const m = new FormData(s.currentTarget); + l.post(`/admin/roles/${r.id}`, m); + } + return /* @__PURE__ */ t("div", { className: "max-w-xl mx-auto p-8", children: [ + /* @__PURE__ */ t("div", { className: "flex items-center gap-4 mb-6", children: [ + /* @__PURE__ */ e( + "button", + { + onClick: () => l.get("/admin/roles"), + className: "text-gray-500 hover:text-gray-700 dark:hover:text-gray-300", + children: "← Back" + } + ), + /* @__PURE__ */ e("h1", { className: "text-3xl font-bold", children: "Edit Role" }) + ] }), + /* @__PURE__ */ e("form", { onSubmit: a, className: "mb-8 p-6 rounded-lg border border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ t("div", { className: "space-y-4", children: [ + /* @__PURE__ */ t("div", { children: [ + /* @__PURE__ */ e("label", { className: "block text-sm font-medium mb-1", children: "Name" }), + /* @__PURE__ */ e( + "input", + { + type: "text", + name: "name", + defaultValue: r.name, + required: !0, + className: "w-full px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" + } + ) + ] }), + /* @__PURE__ */ t("div", { children: [ + /* @__PURE__ */ e("label", { className: "block text-sm font-medium mb-1", children: "Description" }), + /* @__PURE__ */ e( + "input", + { + type: "text", + name: "description", + defaultValue: r.description ?? "", + className: "w-full px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" + } + ) + ] }), + /* @__PURE__ */ t("div", { className: "text-sm text-gray-500", children: [ + "Created: ", + new Date(r.createdAt).toLocaleString() + ] }), + /* @__PURE__ */ e( + "button", + { + type: "submit", + className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", + children: "Save" + } + ) + ] }) }), + /* @__PURE__ */ t("div", { className: "p-6 rounded-lg border border-gray-200 dark:border-gray-700", children: [ + /* @__PURE__ */ t("h2", { className: "text-lg font-semibold mb-4", children: [ + "Assigned Users (", + i.length, + ")" + ] }), + i.length === 0 ? /* @__PURE__ */ e("p", { className: "text-sm text-gray-500", children: "No users assigned to this role." }) : /* @__PURE__ */ e("ul", { className: "space-y-2", children: i.map((s) => /* @__PURE__ */ t("li", { className: "flex justify-between items-center py-2", children: [ + /* @__PURE__ */ t("div", { children: [ + /* @__PURE__ */ e("span", { className: "font-medium", children: s.displayName || "—" }), + /* @__PURE__ */ e("span", { className: "text-gray-500 ml-2 text-sm", children: s.email }) + ] }), + /* @__PURE__ */ e( + "button", + { + onClick: () => l.get(`/admin/users/${s.id}/edit`), + className: "text-blue-600 hover:text-blue-800 dark:text-blue-400 text-sm", + children: "Edit" + } + ) + ] }, s.id)) }) + ] }) + ] }); +} +const w = { + "Users/Admin/Users": x, + "Users/Admin/UsersEdit": h, + "Users/Admin/Roles": p, + "Users/Admin/RolesCreate": y, + "Users/Admin/RolesEdit": N +}; +export { + w as pages +}; diff --git a/src/modules/Users/tests/Users.Tests/Integration/AdminRolesEndpointTests.cs b/src/modules/Users/tests/Users.Tests/Integration/AdminRolesEndpointTests.cs new file mode 100644 index 00000000..f6ddee4e --- /dev/null +++ b/src/modules/Users/tests/Users.Tests/Integration/AdminRolesEndpointTests.cs @@ -0,0 +1,112 @@ +using System.Net; +using System.Security.Claims; +using FluentAssertions; +using SimpleModule.Tests.Shared.Fixtures; + +namespace SimpleModule.Users.Tests.Integration; + +public class AdminRolesEndpointTests : IClassFixture +{ + private readonly SimpleModuleWebApplicationFactory _factory; + + public AdminRolesEndpointTests(SimpleModuleWebApplicationFactory factory) + { + _factory = factory; + } + + private HttpClient CreateAdminClient() => + _factory.CreateAuthenticatedClient(new Claim(ClaimTypes.Role, "Admin")); + + [Fact] + public async Task ListRoles_Unauthenticated_ReturnsUnauthorized() + { + var client = _factory.CreateClient(); + var response = await client.GetAsync("/admin/roles"); + response.StatusCode.Should().Be(HttpStatusCode.Unauthorized); + } + + [Fact] + public async Task ListRoles_NonAdmin_ReturnsForbidden() + { + var client = _factory.CreateAuthenticatedClient(); + var response = await client.GetAsync("/admin/roles"); + response.StatusCode.Should().Be(HttpStatusCode.Forbidden); + } + + [Fact] + public async Task ListRoles_Admin_ReturnsOk() + { + var client = CreateAdminClient(); + var response = await client.GetAsync("/admin/roles"); + response.StatusCode.Should().Be(HttpStatusCode.OK); + } + + [Fact] + public async Task ListRoles_WithInertiaHeader_ReturnsJson() + { + var client = CreateAdminClient(); + client.DefaultRequestHeaders.Add("X-Inertia", "true"); + client.DefaultRequestHeaders.Add("X-Inertia-Version", "1"); + var response = await client.GetAsync("/admin/roles"); + response.StatusCode.Should().Be(HttpStatusCode.OK); + response.Content.Headers.ContentType?.MediaType.Should().Be("application/json"); + } + + [Fact] + public async Task CreateRolePage_Admin_ReturnsOk() + { + var client = CreateAdminClient(); + var response = await client.GetAsync("/admin/roles/create"); + response.StatusCode.Should().Be(HttpStatusCode.OK); + } + + [Fact] + public async Task CreateRole_WithEmptyName_Redirects() + { + var client = CreateAdminClient(); + using var content = new FormUrlEncodedContent(new Dictionary + { + ["name"] = "", + ["description"] = "Test", + }); + // Disable auto-redirect to check the redirect status + var handler = _factory.Server.CreateHandler(); + using var noRedirectClient = new HttpClient(handler) { BaseAddress = _factory.Server.BaseAddress }; + noRedirectClient.DefaultRequestHeaders.Add("Authorization", "Bearer test-token"); + var claims = $"{ClaimTypes.Role}=Admin;{ClaimTypes.NameIdentifier}=test-user-id"; + noRedirectClient.DefaultRequestHeaders.Add("X-Test-Claims", claims); + + var response = await noRedirectClient.PostAsync("/admin/roles", content); + response.StatusCode.Should().Be(HttpStatusCode.Redirect); + response.Headers.Location?.ToString().Should().Be("/admin/roles/create"); + } + + [Fact] + public async Task EditRole_NonexistentId_ReturnsNotFound() + { + var client = CreateAdminClient(); + var response = await client.GetAsync("/admin/roles/nonexistent-id/edit"); + response.StatusCode.Should().Be(HttpStatusCode.NotFound); + } + + [Fact] + public async Task UpdateRole_NonexistentId_ReturnsNotFound() + { + var client = CreateAdminClient(); + using var content = new FormUrlEncodedContent(new Dictionary + { + ["name"] = "Updated", + ["description"] = "Updated description", + }); + var response = await client.PostAsync("/admin/roles/nonexistent-id", content); + response.StatusCode.Should().Be(HttpStatusCode.NotFound); + } + + [Fact] + public async Task DeleteRole_NonexistentId_ReturnsNotFound() + { + var client = CreateAdminClient(); + var response = await client.DeleteAsync("/admin/roles/nonexistent-id"); + response.StatusCode.Should().Be(HttpStatusCode.NotFound); + } +} diff --git a/src/modules/Users/tests/Users.Tests/Integration/AdminUsersEndpointTests.cs b/src/modules/Users/tests/Users.Tests/Integration/AdminUsersEndpointTests.cs new file mode 100644 index 00000000..b3ccbc79 --- /dev/null +++ b/src/modules/Users/tests/Users.Tests/Integration/AdminUsersEndpointTests.cs @@ -0,0 +1,112 @@ +using System.Net; +using System.Net.Http.Json; +using System.Security.Claims; +using FluentAssertions; +using SimpleModule.Tests.Shared.Fixtures; + +namespace SimpleModule.Users.Tests.Integration; + +public class AdminUsersEndpointTests : IClassFixture +{ + private readonly SimpleModuleWebApplicationFactory _factory; + + public AdminUsersEndpointTests(SimpleModuleWebApplicationFactory factory) + { + _factory = factory; + } + + private HttpClient CreateAdminClient() => + _factory.CreateAuthenticatedClient(new Claim(ClaimTypes.Role, "Admin")); + + [Fact] + public async Task ListUsers_Unauthenticated_ReturnsUnauthorized() + { + var client = _factory.CreateClient(); + var response = await client.GetAsync("/admin/users"); + response.StatusCode.Should().Be(HttpStatusCode.Unauthorized); + } + + [Fact] + public async Task ListUsers_NonAdmin_ReturnsForbidden() + { + var client = _factory.CreateAuthenticatedClient(); + var response = await client.GetAsync("/admin/users"); + response.StatusCode.Should().Be(HttpStatusCode.Forbidden); + } + + [Fact] + public async Task ListUsers_Admin_ReturnsOk() + { + var client = CreateAdminClient(); + var response = await client.GetAsync("/admin/users"); + response.StatusCode.Should().Be(HttpStatusCode.OK); + } + + [Fact] + public async Task ListUsers_WithInertiaHeader_ReturnsJson() + { + var client = CreateAdminClient(); + client.DefaultRequestHeaders.Add("X-Inertia", "true"); + client.DefaultRequestHeaders.Add("X-Inertia-Version", "1"); + var response = await client.GetAsync("/admin/users"); + response.StatusCode.Should().Be(HttpStatusCode.OK); + response.Content.Headers.ContentType?.MediaType.Should().Be("application/json"); + } + + [Fact] + public async Task ListUsers_WithSearch_ReturnsOk() + { + var client = CreateAdminClient(); + var response = await client.GetAsync("/admin/users?search=admin"); + response.StatusCode.Should().Be(HttpStatusCode.OK); + } + + [Fact] + public async Task EditUser_NonexistentId_ReturnsNotFound() + { + var client = CreateAdminClient(); + var response = await client.GetAsync("/admin/users/nonexistent-id/edit"); + response.StatusCode.Should().Be(HttpStatusCode.NotFound); + } + + [Fact] + public async Task UpdateUser_NonexistentId_ReturnsNotFound() + { + var client = CreateAdminClient(); + using var content = new FormUrlEncodedContent(new Dictionary + { + ["displayName"] = "New Name", + ["email"] = "new@example.com", + }); + var response = await client.PostAsync("/admin/users/nonexistent-id", content); + response.StatusCode.Should().Be(HttpStatusCode.NotFound); + } + + [Fact] + public async Task SetRoles_NonexistentId_ReturnsNotFound() + { + var client = CreateAdminClient(); + using var content = new FormUrlEncodedContent(new Dictionary + { + ["roles"] = "Admin", + }); + var response = await client.PostAsync("/admin/users/nonexistent-id/roles", content); + response.StatusCode.Should().Be(HttpStatusCode.NotFound); + } + + [Fact] + public async Task LockUser_NonexistentId_ReturnsNotFound() + { + var client = CreateAdminClient(); + var response = await client.PostAsync("/admin/users/nonexistent-id/lock", null); + response.StatusCode.Should().Be(HttpStatusCode.NotFound); + } + + [Fact] + public async Task UnlockUser_NonexistentId_ReturnsNotFound() + { + var client = CreateAdminClient(); + var response = await client.PostAsync("/admin/users/nonexistent-id/unlock", null); + response.StatusCode.Should().Be(HttpStatusCode.NotFound); + } +} diff --git a/tests/SimpleModule.Core.Tests/Inertia/InertiaResultTests.cs b/tests/SimpleModule.Core.Tests/Inertia/InertiaResultTests.cs new file mode 100644 index 00000000..49480f63 --- /dev/null +++ b/tests/SimpleModule.Core.Tests/Inertia/InertiaResultTests.cs @@ -0,0 +1,104 @@ +using System.Net; +using System.Net.Http.Json; +using System.Text.Json; +using FluentAssertions; +using SimpleModule.Tests.Shared.Fixtures; + +namespace SimpleModule.Core.Tests.Inertia; + +public class InertiaResultTests : IClassFixture +{ + private readonly SimpleModuleWebApplicationFactory _factory; + + public InertiaResultTests(SimpleModuleWebApplicationFactory factory) + { + _factory = factory; + } + + [Fact] + public async Task InertiaEndpoint_WithoutInertiaHeader_ReturnsHtml() + { + using var client = _factory.CreateClient(); + var response = await client.GetAsync("/products/browse"); + response.StatusCode.Should().Be(HttpStatusCode.OK); + response.Content.Headers.ContentType?.MediaType.Should().Be("text/html"); + + var html = await response.Content.ReadAsStringAsync(); + html.Should().Contain("id=\"app\""); + html.Should().Contain("data-page="); + html.Should().Contain("/js/app.js"); + } + + [Fact] + public async Task InertiaEndpoint_WithInertiaHeader_ReturnsJson() + { + using var client = _factory.CreateClient(); + client.DefaultRequestHeaders.Add("X-Inertia", "true"); + client.DefaultRequestHeaders.Add("X-Inertia-Version", "1"); + + var response = await client.GetAsync("/products/browse"); + response.StatusCode.Should().Be(HttpStatusCode.OK); + response.Content.Headers.ContentType?.MediaType.Should().Be("application/json"); + + var json = await response.Content.ReadFromJsonAsync(); + json.GetProperty("component").GetString().Should().Be("Products/Browse"); + json.TryGetProperty("props", out _).Should().BeTrue(); + json.TryGetProperty("url", out _).Should().BeTrue(); + json.TryGetProperty("version", out _).Should().BeTrue(); + } + + [Fact] + public async Task InertiaEndpoint_JsonResponse_ContainsCorrectUrl() + { + using var client = _factory.CreateClient(); + client.DefaultRequestHeaders.Add("X-Inertia", "true"); + client.DefaultRequestHeaders.Add("X-Inertia-Version", "1"); + + var response = await client.GetAsync("/products/browse"); + var json = await response.Content.ReadFromJsonAsync(); + json.GetProperty("url").GetString().Should().Be("/products/browse"); + } + + [Fact] + public async Task InertiaEndpoint_JsonResponse_HasInertiaResponseHeader() + { + using var client = _factory.CreateClient(); + client.DefaultRequestHeaders.Add("X-Inertia", "true"); + client.DefaultRequestHeaders.Add("X-Inertia-Version", "1"); + + var response = await client.GetAsync("/products/browse"); + response.Headers.Contains("X-Inertia").Should().BeTrue(); + response.Headers.GetValues("X-Inertia").Should().Contain("true"); + } + + [Fact] + public async Task InertiaEndpoint_HtmlResponse_ContainsImportMap() + { + using var client = _factory.CreateClient(); + var response = await client.GetAsync("/products/browse"); + var html = await response.Content.ReadAsStringAsync(); + html.Should().Contain("importmap"); + html.Should().Contain("react"); + } + + [Fact] + public async Task InertiaMiddleware_AddsVersionHeader() + { + using var client = _factory.CreateClient(); + var response = await client.GetAsync("/products/browse"); + response.Headers.Contains("X-Inertia-Version").Should().BeTrue(); + } + + [Fact] + public async Task InertiaMiddleware_VersionMismatch_Returns409() + { + // Create a handler that doesn't auto-redirect + using var handler = _factory.Server.CreateHandler(); + using var client = new HttpClient(handler) { BaseAddress = _factory.Server.BaseAddress }; + client.DefaultRequestHeaders.Add("X-Inertia", "true"); + client.DefaultRequestHeaders.Add("X-Inertia-Version", "wrong-version"); + + var response = await client.GetAsync("/products/browse"); + response.StatusCode.Should().Be(HttpStatusCode.Conflict); + } +} diff --git a/tests/SimpleModule.Core.Tests/SimpleModule.Core.Tests.csproj b/tests/SimpleModule.Core.Tests/SimpleModule.Core.Tests.csproj index e5a94393..998d8d58 100644 --- a/tests/SimpleModule.Core.Tests/SimpleModule.Core.Tests.csproj +++ b/tests/SimpleModule.Core.Tests/SimpleModule.Core.Tests.csproj @@ -15,5 +15,6 @@ + diff --git a/tools/extract-ts-types.mjs b/tools/extract-ts-types.mjs new file mode 100644 index 00000000..5d61e2e0 --- /dev/null +++ b/tools/extract-ts-types.mjs @@ -0,0 +1,29 @@ +#!/usr/bin/env node +// Extracts TypeScript interfaces from generated DtoTypeScript.g.cs +// Usage: node tools/extract-ts-types.mjs + +import { readFileSync, writeFileSync, mkdirSync } from 'fs'; +import { dirname, resolve } from 'path'; + +const inputFile = process.argv[2]; +const outputDir = process.argv[3] || 'src/SimpleModule.Api/ClientApp/types'; + +if (!inputFile) { + console.error('Usage: node extract-ts-types.mjs '); + process.exit(1); +} + +const content = readFileSync(inputFile, 'utf-8'); +const match = content.match(/\/\*\n([\s\S]*?)\*\//); + +if (!match) { + console.log('No TypeScript definitions found in generated file.'); + process.exit(0); +} + +const tsContent = match[1]; +const outPath = resolve(outputDir, 'contracts.d.ts'); + +mkdirSync(dirname(outPath), { recursive: true }); +writeFileSync(outPath, `// Auto-generated from [Dto] types — do not edit\n${tsContent}`); +console.log(`Wrote TypeScript definitions to ${outPath}`); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..c7ee10c9 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true + }, + "exclude": ["node_modules", "**/wwwroot/**"] +} From bd45c51d5d9e351e2af3ba924035c04990df1d8f Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Thu, 12 Mar 2026 14:34:39 +0100 Subject: [PATCH 02/62] refactor: eliminate layout duplication between InertiaResult and MainLayout Render Inertia HTML shell via Blazor SSR's HtmlRenderer, reusing MainLayout.razor as the single source of truth for nav, user dropdown, and page chrome. - Add IInertiaPageRenderer interface in Core (decouples from Blazor) - Add InertiaShell.razor wrapping InertiaPage via LayoutView+MainLayout - Add InertiaPageRenderer using HtmlRenderer to render InertiaShell - Slim InertiaResult from ~130 lines of inline HTML to 3-line delegation - Extract shared user menu JS to shell.js (used by both Blazor and Inertia) - Replace NavigationManager with HttpContext.Request.Path in MainLayout Co-Authored-By: Claude Opus 4.6 --- src/SimpleModule.Api/Components/App.razor | 1 + .../Components/InertiaShell.razor | 59 +++++++++++++++++++ .../Components/Layout/MainLayout.razor | 47 +++++---------- .../Components/Pages/InertiaPage.razor | 6 ++ .../Inertia/InertiaPageRenderer.cs | 32 ++++++++++ src/SimpleModule.Api/Program.cs | 4 ++ src/SimpleModule.Api/wwwroot/js/shell.js | 30 ++++++++++ .../Inertia/IInertiaPageRenderer.cs | 8 +++ .../Inertia/InertiaResult.cs | 39 ++---------- 9 files changed, 159 insertions(+), 67 deletions(-) create mode 100644 src/SimpleModule.Api/Components/InertiaShell.razor create mode 100644 src/SimpleModule.Api/Components/Pages/InertiaPage.razor create mode 100644 src/SimpleModule.Api/Inertia/InertiaPageRenderer.cs create mode 100644 src/SimpleModule.Api/wwwroot/js/shell.js create mode 100644 src/SimpleModule.Core/Inertia/IInertiaPageRenderer.cs diff --git a/src/SimpleModule.Api/Components/App.razor b/src/SimpleModule.Api/Components/App.razor index 5d178cd0..78649552 100644 --- a/src/SimpleModule.Api/Components/App.razor +++ b/src/SimpleModule.Api/Components/App.razor @@ -42,6 +42,7 @@
+ diff --git a/src/SimpleModule.Api/Components/InertiaShell.razor b/src/SimpleModule.Api/Components/InertiaShell.razor new file mode 100644 index 00000000..fc4731e4 --- /dev/null +++ b/src/SimpleModule.Api/Components/InertiaShell.razor @@ -0,0 +1,59 @@ +@using Microsoft.AspNetCore.Components.Web +@using SimpleModule.Api.Components.Layout +@using SimpleModule.Api.Components.Pages + + + + + + + + + + + + SimpleModule + + + + +
+ + + + + + + + + +@code { + [Parameter] public string PageJson { get; set; } = ""; + [Parameter] public Microsoft.AspNetCore.Http.HttpContext? HttpContext { get; set; } +} diff --git a/src/SimpleModule.Api/Components/Layout/MainLayout.razor b/src/SimpleModule.Api/Components/Layout/MainLayout.razor index 825abc63..ba88c476 100644 --- a/src/SimpleModule.Api/Components/Layout/MainLayout.razor +++ b/src/SimpleModule.Api/Components/Layout/MainLayout.razor @@ -1,5 +1,4 @@ @inherits LayoutComponentBase -@inject NavigationManager Navigation @code { diff --git a/src/modules/Users/src/Users/Features/Admin/AdminRolesEndpoint.cs b/src/modules/Users/src/Users/Features/Admin/AdminRolesEndpoint.cs index 91458be9..617b56a8 100644 --- a/src/modules/Users/src/Users/Features/Admin/AdminRolesEndpoint.cs +++ b/src/modules/Users/src/Users/Features/Admin/AdminRolesEndpoint.cs @@ -17,134 +17,153 @@ public static void Map(IEndpointRouteBuilder endpoints) .RequireAuthorization(policy => policy.RequireRole("Admin")); // List roles - group.MapGet("/", async ( - RoleManager roleManager, - UserManager userManager) => - { - var roles = await roleManager.Roles - .OrderBy(r => r.Name) - .ToListAsync(); - - var roleList = new List(); - foreach (var role in roles) + group.MapGet( + "/", + async ( + RoleManager roleManager, + UserManager userManager + ) => { - var usersInRole = role.Name is not null - ? await userManager.GetUsersInRoleAsync(role.Name) - : []; - roleList.Add(new + var roles = await roleManager.Roles.OrderBy(r => r.Name).ToListAsync(); + + var roleList = new List(); + foreach (var role in roles) { - id = role.Id, - name = role.Name, - description = role.Description, - userCount = usersInRole.Count, - createdAt = role.CreatedAt.ToString("O"), - }); + var usersInRole = role.Name is not null + ? await userManager.GetUsersInRoleAsync(role.Name) + : []; + roleList.Add( + new + { + id = role.Id, + name = role.Name, + description = role.Description, + userCount = usersInRole.Count, + createdAt = role.CreatedAt.ToString("O"), + } + ); + } + + return Inertia.Render("Users/Admin/Roles", new { roles = roleList }); } - - return Inertia.Render("Users/Admin/Roles", new { roles = roleList }); - }); + ); // Create role page - group.MapGet("/create", () => - Inertia.Render("Users/Admin/RolesCreate")); + group.MapGet("/create", () => Inertia.Render("Users/Admin/RolesCreate")); // Create role - group.MapPost("/", async ( - HttpContext context, - RoleManager roleManager) => - { - var form = await context.Request.ReadFormAsync(); - var name = form["name"].ToString().Trim(); - var description = form["description"].ToString().Trim(); - - if (string.IsNullOrEmpty(name)) - return Results.Redirect("/admin/roles/create"); - - var role = new ApplicationRole + group.MapPost( + "/", + async (HttpContext context, RoleManager roleManager) => { - Name = name, - Description = string.IsNullOrEmpty(description) ? null : description, - }; + var form = await context.Request.ReadFormAsync(); + var name = form["name"].ToString().Trim(); + var description = form["description"].ToString().Trim(); + + if (string.IsNullOrEmpty(name)) + return Results.Redirect("/admin/roles/create"); + + var role = new ApplicationRole + { + Name = name, + Description = string.IsNullOrEmpty(description) ? null : description, + }; - var result = await roleManager.CreateAsync(role); - if (!result.Succeeded) - return Results.Redirect("/admin/roles/create"); + var result = await roleManager.CreateAsync(role); + if (!result.Succeeded) + return Results.Redirect("/admin/roles/create"); - return Results.Redirect("/admin/roles"); - }); + return Results.Redirect("/admin/roles"); + } + ); // Edit role page - group.MapGet("/{id}/edit", async ( - string id, - RoleManager roleManager, - UserManager userManager) => - { - var role = await roleManager.FindByIdAsync(id); - if (role is null) - return Results.NotFound(); - - var usersInRole = role.Name is not null - ? await userManager.GetUsersInRoleAsync(role.Name) - : []; - - return Inertia.Render("Users/Admin/RolesEdit", new + group.MapGet( + "/{id}/edit", + async ( + string id, + RoleManager roleManager, + UserManager userManager + ) => { - role = new - { - id = role.Id, - name = role.Name, - description = role.Description, - createdAt = role.CreatedAt.ToString("O"), - }, - users = usersInRole.Select(u => new - { - id = u.Id, - displayName = u.DisplayName, - email = u.Email, - }).ToList(), - }); - }); + var role = await roleManager.FindByIdAsync(id); + if (role is null) + return Results.NotFound(); + + var usersInRole = role.Name is not null + ? await userManager.GetUsersInRoleAsync(role.Name) + : []; + + return Inertia.Render( + "Users/Admin/RolesEdit", + new + { + role = new + { + id = role.Id, + name = role.Name, + description = role.Description, + createdAt = role.CreatedAt.ToString("O"), + }, + users = usersInRole + .Select(u => new + { + id = u.Id, + displayName = u.DisplayName, + email = u.Email, + }) + .ToList(), + } + ); + } + ); // Update role - group.MapPost("/{id}", async ( - string id, - HttpContext context, - RoleManager roleManager) => - { - var role = await roleManager.FindByIdAsync(id); - if (role is null) - return Results.NotFound(); + group.MapPost( + "/{id}", + async (string id, HttpContext context, RoleManager roleManager) => + { + var role = await roleManager.FindByIdAsync(id); + if (role is null) + return Results.NotFound(); - var form = await context.Request.ReadFormAsync(); - role.Name = form["name"].ToString().Trim(); - var description = form["description"].ToString().Trim(); - role.Description = string.IsNullOrEmpty(description) ? null : description; + var form = await context.Request.ReadFormAsync(); + role.Name = form["name"].ToString().Trim(); + var description = form["description"].ToString().Trim(); + role.Description = string.IsNullOrEmpty(description) ? null : description; - await roleManager.UpdateAsync(role); + await roleManager.UpdateAsync(role); - return Results.Redirect($"/admin/roles/{id}/edit"); - }); + return Results.Redirect($"/admin/roles/{id}/edit"); + } + ); // Delete role - group.MapDelete("/{id}", async ( - string id, - RoleManager roleManager, - UserManager userManager) => - { - var role = await roleManager.FindByIdAsync(id); - if (role is null) - return Results.NotFound(); - - // Don't delete if users are assigned - var usersInRole = role.Name is not null - ? await userManager.GetUsersInRoleAsync(role.Name) - : []; - if (usersInRole.Count > 0) - return Results.BadRequest(new { error = "Cannot delete role with assigned users" }); - - await roleManager.DeleteAsync(role); - - return Results.Ok(); - }); + group.MapDelete( + "/{id}", + async ( + string id, + RoleManager roleManager, + UserManager userManager + ) => + { + var role = await roleManager.FindByIdAsync(id); + if (role is null) + return Results.NotFound(); + + // Don't delete if users are assigned + var usersInRole = role.Name is not null + ? await userManager.GetUsersInRoleAsync(role.Name) + : []; + if (usersInRole.Count > 0) + return Results.BadRequest( + new { error = "Cannot delete role with assigned users" } + ); + + await roleManager.DeleteAsync(role); + + return Results.Ok(); + } + ); } } diff --git a/src/modules/Users/src/Users/Features/Admin/AdminUsersEndpoint.cs b/src/modules/Users/src/Users/Features/Admin/AdminUsersEndpoint.cs index 8e21d8d1..2c401b15 100644 --- a/src/modules/Users/src/Users/Features/Admin/AdminUsersEndpoint.cs +++ b/src/modules/Users/src/Users/Features/Admin/AdminUsersEndpoint.cs @@ -19,158 +19,189 @@ public static void Map(IEndpointRouteBuilder endpoints) .RequireAuthorization(policy => policy.RequireRole("Admin")); // List users - group.MapGet("/", async ( - UserManager userManager, - RoleManager roleManager, - string? search, - int page = 1) => - { - var query = userManager.Users.AsQueryable(); - - if (!string.IsNullOrWhiteSpace(search)) + group.MapGet( + "/", + async ( + UserManager userManager, + RoleManager roleManager, + string? search, + int page = 1 + ) => { - var pattern = $"%{search.Trim()}%"; - query = query.Where(u => - (u.Email != null && EF.Functions.Like(u.Email, pattern)) - || EF.Functions.Like(u.DisplayName, pattern) - || (u.UserName != null && EF.Functions.Like(u.UserName, pattern))); - } - - var totalCount = await query.CountAsync(); - var totalPages = (int)Math.Ceiling((double)totalCount / PageSize); - page = Math.Clamp(page, 1, Math.Max(1, totalPages)); - - var users = await query - .OrderBy(u => u.DisplayName) - .Skip((page - 1) * PageSize) - .Take(PageSize) - .ToListAsync(); + var query = userManager.Users.AsQueryable(); - var userList = new List(); - foreach (var user in users) - { - var roles = await userManager.GetRolesAsync(user); - userList.Add(new + if (!string.IsNullOrWhiteSpace(search)) + { + var pattern = $"%{search.Trim()}%"; + query = query.Where(u => + (u.Email != null && EF.Functions.Like(u.Email, pattern)) + || EF.Functions.Like(u.DisplayName, pattern) + || (u.UserName != null && EF.Functions.Like(u.UserName, pattern)) + ); + } + + var totalCount = await query.CountAsync(); + var totalPages = (int)Math.Ceiling((double)totalCount / PageSize); + page = Math.Clamp(page, 1, Math.Max(1, totalPages)); + + var users = await query + .OrderBy(u => u.DisplayName) + .Skip((page - 1) * PageSize) + .Take(PageSize) + .ToListAsync(); + + var userList = new List(); + foreach (var user in users) { - id = user.Id, - displayName = user.DisplayName, - email = user.Email, - emailConfirmed = user.EmailConfirmed, - roles = roles.ToList(), - isLockedOut = user.LockoutEnd.HasValue && user.LockoutEnd > DateTimeOffset.UtcNow, - createdAt = user.CreatedAt.ToString("O"), - }); + var roles = await userManager.GetRolesAsync(user); + userList.Add( + new + { + id = user.Id, + displayName = user.DisplayName, + email = user.Email, + emailConfirmed = user.EmailConfirmed, + roles = roles.ToList(), + isLockedOut = user.LockoutEnd.HasValue + && user.LockoutEnd > DateTimeOffset.UtcNow, + createdAt = user.CreatedAt.ToString("O"), + } + ); + } + + return Inertia.Render( + "Users/Admin/Users", + new + { + users = userList, + search = search ?? "", + page, + totalPages, + totalCount, + } + ); } - - return Inertia.Render("Users/Admin/Users", new - { - users = userList, - search = search ?? "", - page, - totalPages, - totalCount, - }); - }); + ); // Edit user page - group.MapGet("/{id}/edit", async ( - string id, - UserManager userManager, - RoleManager roleManager) => - { - var user = await userManager.FindByIdAsync(id); - if (user is null) - return Results.NotFound(); - - var userRoles = await userManager.GetRolesAsync(user); - var allRoles = await roleManager.Roles.OrderBy(r => r.Name).ToListAsync(); - - return Inertia.Render("Users/Admin/UsersEdit", new + group.MapGet( + "/{id}/edit", + async ( + string id, + UserManager userManager, + RoleManager roleManager + ) => { - user = new - { - id = user.Id, - displayName = user.DisplayName, - email = user.Email, - emailConfirmed = user.EmailConfirmed, - isLockedOut = user.LockoutEnd.HasValue && user.LockoutEnd > DateTimeOffset.UtcNow, - createdAt = user.CreatedAt.ToString("O"), - lastLoginAt = user.LastLoginAt?.ToString("O"), - }, - userRoles = userRoles.ToList(), - allRoles = allRoles.Select(r => new { id = r.Id, name = r.Name, description = r.Description }).ToList(), - }); - }); + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); + + var userRoles = await userManager.GetRolesAsync(user); + var allRoles = await roleManager.Roles.OrderBy(r => r.Name).ToListAsync(); + + return Inertia.Render( + "Users/Admin/UsersEdit", + new + { + user = new + { + id = user.Id, + displayName = user.DisplayName, + email = user.Email, + emailConfirmed = user.EmailConfirmed, + isLockedOut = user.LockoutEnd.HasValue + && user.LockoutEnd > DateTimeOffset.UtcNow, + createdAt = user.CreatedAt.ToString("O"), + lastLoginAt = user.LastLoginAt?.ToString("O"), + }, + userRoles = userRoles.ToList(), + allRoles = allRoles + .Select(r => new + { + id = r.Id, + name = r.Name, + description = r.Description, + }) + .ToList(), + } + ); + } + ); // Update user - group.MapPost("/{id}", async ( - string id, - HttpContext context, - UserManager userManager) => - { - var user = await userManager.FindByIdAsync(id); - if (user is null) - return Results.NotFound(); + group.MapPost( + "/{id}", + async (string id, HttpContext context, UserManager userManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); - var form = await context.Request.ReadFormAsync(); - user.DisplayName = form["displayName"].ToString(); - user.Email = form["email"].ToString(); - user.EmailConfirmed = form.ContainsKey("emailConfirmed"); + var form = await context.Request.ReadFormAsync(); + user.DisplayName = form["displayName"].ToString(); + user.Email = form["email"].ToString(); + user.EmailConfirmed = form.ContainsKey("emailConfirmed"); - await userManager.UpdateAsync(user); + await userManager.UpdateAsync(user); - return Results.Redirect($"/admin/users/{id}/edit"); - }); + return Results.Redirect($"/admin/users/{id}/edit"); + } + ); // Set roles - group.MapPost("/{id}/roles", async ( - string id, - HttpContext context, - UserManager userManager) => - { - var user = await userManager.FindByIdAsync(id); - if (user is null) - return Results.NotFound(); - - var form = await context.Request.ReadFormAsync(); - var newRoles = form["roles"].ToArray().Where(r => !string.IsNullOrEmpty(r)).ToList(); - var currentRoles = await userManager.GetRolesAsync(user); - - await userManager.RemoveFromRolesAsync(user, currentRoles); - if (newRoles.Count > 0) - await userManager.AddToRolesAsync(user, newRoles!); - - return Results.Redirect($"/admin/users/{id}/edit"); - }); + group.MapPost( + "/{id}/roles", + async (string id, HttpContext context, UserManager userManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); + + var form = await context.Request.ReadFormAsync(); + var newRoles = form["roles"] + .ToArray() + .Where(r => !string.IsNullOrEmpty(r)) + .ToList(); + var currentRoles = await userManager.GetRolesAsync(user); + + await userManager.RemoveFromRolesAsync(user, currentRoles); + if (newRoles.Count > 0) + await userManager.AddToRolesAsync(user, newRoles!); + + return Results.Redirect($"/admin/users/{id}/edit"); + } + ); // Lock account - group.MapPost("/{id}/lock", async ( - string id, - UserManager userManager) => - { - var user = await userManager.FindByIdAsync(id); - if (user is null) - return Results.NotFound(); + group.MapPost( + "/{id}/lock", + async (string id, UserManager userManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); - await userManager.SetLockoutEnabledAsync(user, true); - await userManager.SetLockoutEndDateAsync(user, DateTimeOffset.UtcNow.AddYears(100)); + await userManager.SetLockoutEnabledAsync(user, true); + await userManager.SetLockoutEndDateAsync(user, DateTimeOffset.UtcNow.AddYears(100)); - return Results.Redirect($"/admin/users/{id}/edit"); - }); + return Results.Redirect($"/admin/users/{id}/edit"); + } + ); // Unlock account - group.MapPost("/{id}/unlock", async ( - string id, - UserManager userManager) => - { - var user = await userManager.FindByIdAsync(id); - if (user is null) - return Results.NotFound(); - - await userManager.SetLockoutEndDateAsync(user, null); - await userManager.ResetAccessFailedCountAsync(user); - - return Results.Redirect($"/admin/users/{id}/edit"); - }); + group.MapPost( + "/{id}/unlock", + async (string id, UserManager userManager) => + { + var user = await userManager.FindByIdAsync(id); + if (user is null) + return Results.NotFound(); + + await userManager.SetLockoutEndDateAsync(user, null); + await userManager.ResetAccessFailedCountAsync(user); + + return Results.Redirect($"/admin/users/{id}/edit"); + } + ); } } diff --git a/src/modules/Users/src/Users/Pages/Admin/Roles.tsx b/src/modules/Users/src/Users/Pages/Admin/Roles.tsx index 600f3cb3..8e1bc23c 100644 --- a/src/modules/Users/src/Users/Pages/Admin/Roles.tsx +++ b/src/modules/Users/src/Users/Pages/Admin/Roles.tsx @@ -21,54 +21,54 @@ export default function Roles({ roles }: Props) { } return ( -
+
-

Roles

-
-
+
- + - - - - - + + + + + - + {roles.map((role) => ( - - - + + -
NameDescriptionUsersCreatedNameDescriptionUsersCreated
{role.name} - {role.description || '—'} +
{role.name} + {role.description || '\u2014'} - - {role.userCount} - + {role.userCount} + {new Date(role.createdAt).toLocaleDateString()}
diff --git a/src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx b/src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx index 46cf1bd7..9283f6fa 100644 --- a/src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx +++ b/src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx @@ -8,42 +8,28 @@ export default function RolesCreate() { } return ( -
-
- -

Create Role

+
+
+ + + +

+ Create Role +

+

Add a new application role

- +
- +
- +
- +
diff --git a/src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx b/src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx index 616446df..a477de49 100644 --- a/src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx +++ b/src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx @@ -26,65 +26,48 @@ export default function RolesEdit({ role, users }: Props) { } return ( -
-
- -

Edit Role

+
+
+ + + +

+ Edit Role +

+

+ Created: {new Date(role.createdAt).toLocaleString()} +

-
+
- +
- +
-
- Created: {new Date(role.createdAt).toLocaleString()} -
- +
-
+

Assigned Users ({users.length})

{users.length === 0 ? ( -

No users assigned to this role.

+

No users assigned to this role.

) : ( -
    +
      {users.map((user) => ( -
    • +
    • - {user.displayName || '—'} - {user.email} + {user.displayName || '\u2014'} + {user.email}
      diff --git a/src/modules/Users/src/Users/Pages/Admin/Users.tsx b/src/modules/Users/src/Users/Pages/Admin/Users.tsx index e995e84f..86211924 100644 --- a/src/modules/Users/src/Users/Pages/Admin/Users.tsx +++ b/src/modules/Users/src/Users/Pages/Admin/Users.tsx @@ -32,10 +32,14 @@ export default function Users({ users, search, page, totalPages, totalCount }: P } return ( -
      +
      -

      Users

      - {totalCount} total +
      +

      + Users +

      +

      {totalCount} total users

      +
      @@ -44,45 +48,39 @@ export default function Users({ users, search, page, totalPages, totalCount }: P value={searchValue} onChange={(e) => setSearchValue(e.target.value)} placeholder="Search by name or email..." - className="flex-1 px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" + className="flex-1" /> -
      -
      +
      - + - - - - - - + + + + + + - + {users.map((user) => ( - - - + + - - + diff --git a/src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx b/src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx index 9283f6fa..bc593156 100644 --- a/src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx +++ b/src/modules/Users/src/Users/Pages/Admin/RolesCreate.tsx @@ -10,10 +10,24 @@ export default function RolesCreate() { return (
      - - + + + + -

      +

      Create Role

      @@ -29,7 +43,9 @@ export default function RolesCreate() {
      - + diff --git a/src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx b/src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx index a477de49..8e87b626 100644 --- a/src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx +++ b/src/modules/Users/src/Users/Pages/Admin/RolesEdit.tsx @@ -28,10 +28,24 @@ export default function RolesEdit({ role, users }: Props) { return (
      - - + + + + -

      +

      Edit Role

      @@ -49,7 +63,9 @@ export default function RolesEdit({ role, users }: Props) {
      - + @@ -60,7 +76,10 @@ export default function RolesEdit({ role, users }: Props) { ) : (
        {users.map((user) => ( -
      • +
      • {user.displayName || '\u2014'} {user.email} diff --git a/src/modules/Users/src/Users/Pages/Admin/Users.tsx b/src/modules/Users/src/Users/Pages/Admin/Users.tsx index 86211924..d7d8ba18 100644 --- a/src/modules/Users/src/Users/Pages/Admin/Users.tsx +++ b/src/modules/Users/src/Users/Pages/Admin/Users.tsx @@ -1,5 +1,5 @@ import { router } from '@inertiajs/react'; -import { useState, FormEvent } from 'react'; +import { type FormEvent, useState } from 'react'; interface User { id: string; @@ -35,7 +35,10 @@ export default function Users({ users, search, page, totalPages, totalCount }: P
        -

        +

        Users

        {totalCount} total users

        @@ -73,9 +76,7 @@ export default function Users({ users, search, page, totalPages, totalCount }: P
      NameEmailRolesStatusCreatedNameEmailRolesStatusCreated
      {user.displayName || '—'} +
      {user.displayName || '\u2014'} {user.email} {!user.emailConfirmed && ( - unverified + unverified )}
      {user.roles.map((role) => ( - + {role} ))} @@ -90,18 +88,18 @@ export default function Users({ users, search, page, totalPages, totalCount }: P
      {user.isLockedOut ? ( - Locked + Locked ) : ( - Active + Active )} + {new Date(user.createdAt).toLocaleDateString()} @@ -117,17 +115,17 @@ export default function Users({ users, search, page, totalPages, totalCount }: P - + Page {page} of {totalPages} diff --git a/src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx b/src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx index 513b2405..f021f9af 100644 --- a/src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx +++ b/src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx @@ -44,45 +44,32 @@ export default function UsersEdit({ user, userRoles, allRoles }: Props) { } return ( -
      -
      - -

      Edit User

      +
      +
      + + + +

      + Edit User +

      - -
      - Created: {new Date(user.createdAt).toLocaleString()} +

      + Created: {new Date(user.createdAt).toLocaleString()} {user.lastLoginAt && ( Last login: {new Date(user.lastLoginAt).toLocaleString()} )} -

      +

      - {/* User Details Form */} -
      +

      Details

      - +
      - +
      - +
      - +
      - {/* Roles Form */} -
      +

      Roles

      {allRoles.map((role) => ( @@ -115,50 +96,36 @@ export default function UsersEdit({ user, userRoles, allRoles }: Props) { value={role.name ?? ''} id={`role-${role.id}`} defaultChecked={userRoles.includes(role.name ?? '')} - className="rounded border-gray-300" + className="accent-primary" /> -
      ))} {allRoles.length === 0 && ( -

      No roles defined.

      +

      No roles defined.

      )}
      - + - {/* Lock/Unlock */} -
      +

      Account Status

      {user.isLockedOut ? (
      -

      This account is locked.

      -
      ) : (
      -

      This account is active.

      - +

      This account is active.

      +
      )}
      diff --git a/src/modules/Users/src/Users/package.json b/src/modules/Users/src/Users/package.json index 06f794b5..d8e55373 100644 --- a/src/modules/Users/src/Users/package.json +++ b/src/modules/Users/src/Users/package.json @@ -2,10 +2,8 @@ "private": true, "name": "@simplemodule/users", "scripts": { - "build": "vite build && cross-env VITE_BUILD_TARGET=pages vite build", - "build:lib": "vite build", - "build:pages": "cross-env VITE_BUILD_TARGET=pages vite build", - "watch": "cross-env VITE_BUILD_TARGET=pages vite build --watch" + "build": "vite build", + "watch": "vite build --watch" }, "dependencies": { "qrcode": "^1.5.4" diff --git a/src/modules/Users/src/Users/vite.config.ts b/src/modules/Users/src/Users/vite.config.ts index cadbc926..6e02ae80 100644 --- a/src/modules/Users/src/Users/vite.config.ts +++ b/src/modules/Users/src/Users/vite.config.ts @@ -2,38 +2,21 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import { resolve } from 'path'; -const buildTarget = process.env.VITE_BUILD_TARGET; - -const libConfig = defineConfig({ - build: { - lib: { - entry: resolve(__dirname, 'Scripts/index.ts'), - formats: ['es'], - fileName: () => 'Users.lib.module.js', - }, - outDir: 'wwwroot', - emptyOutDir: false, - rollupOptions: { - output: { inlineDynamicImports: true }, - }, - }, -}); - -const pagesConfig = defineConfig({ +export default defineConfig({ plugins: [react()], build: { lib: { - entry: resolve(__dirname, 'Pages/index.ts'), + entry: { + 'Users.lib.module': resolve(__dirname, 'Scripts/index.ts'), + 'Users.pages': resolve(__dirname, 'Pages/index.ts'), + }, formats: ['es'], - fileName: () => 'Users.pages.js', + fileName: (_format, entryName) => `${entryName}.js`, }, outDir: 'wwwroot', emptyOutDir: false, rollupOptions: { external: ['react', 'react-dom', 'react/jsx-runtime', '@inertiajs/react'], - output: { inlineDynamicImports: true }, }, }, }); - -export default buildTarget === 'pages' ? pagesConfig : libConfig; diff --git a/src/modules/Users/tests/Users.Tests/Integration/AdminRolesEndpointTests.cs b/src/modules/Users/tests/Users.Tests/Integration/AdminRolesEndpointTests.cs index f6ddee4e..eb7da340 100644 --- a/src/modules/Users/tests/Users.Tests/Integration/AdminRolesEndpointTests.cs +++ b/src/modules/Users/tests/Users.Tests/Integration/AdminRolesEndpointTests.cs @@ -64,14 +64,15 @@ public async Task CreateRolePage_Admin_ReturnsOk() public async Task CreateRole_WithEmptyName_Redirects() { var client = CreateAdminClient(); - using var content = new FormUrlEncodedContent(new Dictionary - { - ["name"] = "", - ["description"] = "Test", - }); + using var content = new FormUrlEncodedContent( + new Dictionary { ["name"] = "", ["description"] = "Test" } + ); // Disable auto-redirect to check the redirect status var handler = _factory.Server.CreateHandler(); - using var noRedirectClient = new HttpClient(handler) { BaseAddress = _factory.Server.BaseAddress }; + using var noRedirectClient = new HttpClient(handler) + { + BaseAddress = _factory.Server.BaseAddress, + }; noRedirectClient.DefaultRequestHeaders.Add("Authorization", "Bearer test-token"); var claims = $"{ClaimTypes.Role}=Admin;{ClaimTypes.NameIdentifier}=test-user-id"; noRedirectClient.DefaultRequestHeaders.Add("X-Test-Claims", claims); @@ -93,11 +94,13 @@ public async Task EditRole_NonexistentId_ReturnsNotFound() public async Task UpdateRole_NonexistentId_ReturnsNotFound() { var client = CreateAdminClient(); - using var content = new FormUrlEncodedContent(new Dictionary - { - ["name"] = "Updated", - ["description"] = "Updated description", - }); + using var content = new FormUrlEncodedContent( + new Dictionary + { + ["name"] = "Updated", + ["description"] = "Updated description", + } + ); var response = await client.PostAsync("/admin/roles/nonexistent-id", content); response.StatusCode.Should().Be(HttpStatusCode.NotFound); } diff --git a/src/modules/Users/tests/Users.Tests/Integration/AdminUsersEndpointTests.cs b/src/modules/Users/tests/Users.Tests/Integration/AdminUsersEndpointTests.cs index b3ccbc79..79a666e5 100644 --- a/src/modules/Users/tests/Users.Tests/Integration/AdminUsersEndpointTests.cs +++ b/src/modules/Users/tests/Users.Tests/Integration/AdminUsersEndpointTests.cs @@ -73,11 +73,13 @@ public async Task EditUser_NonexistentId_ReturnsNotFound() public async Task UpdateUser_NonexistentId_ReturnsNotFound() { var client = CreateAdminClient(); - using var content = new FormUrlEncodedContent(new Dictionary - { - ["displayName"] = "New Name", - ["email"] = "new@example.com", - }); + using var content = new FormUrlEncodedContent( + new Dictionary + { + ["displayName"] = "New Name", + ["email"] = "new@example.com", + } + ); var response = await client.PostAsync("/admin/users/nonexistent-id", content); response.StatusCode.Should().Be(HttpStatusCode.NotFound); } @@ -86,10 +88,9 @@ public async Task UpdateUser_NonexistentId_ReturnsNotFound() public async Task SetRoles_NonexistentId_ReturnsNotFound() { var client = CreateAdminClient(); - using var content = new FormUrlEncodedContent(new Dictionary - { - ["roles"] = "Admin", - }); + using var content = new FormUrlEncodedContent( + new Dictionary { ["roles"] = "Admin" } + ); var response = await client.PostAsync("/admin/users/nonexistent-id/roles", content); response.StatusCode.Should().Be(HttpStatusCode.NotFound); } From 42ab718512d9a8898d30c87d94b827ea340fcadb Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Thu, 12 Mar 2026 14:37:28 +0100 Subject: [PATCH 04/62] chore: remove generated build outputs from git and add to .gitignore Tailwind CSS (app.css), Vite app bundle (app.js), and module page bundles (*.pages.js) are build artifacts regenerated on every build. Co-Authored-By: Claude Opus 4.6 --- .gitignore | 7 + src/SimpleModule.Api/wwwroot/css/app.css | 2 - src/SimpleModule.Api/wwwroot/js/app.js | 1 - .../src/Products/wwwroot/Products.pages.js | 26 - .../Users/src/Users/wwwroot/Users.pages.js | 447 ------------------ 5 files changed, 7 insertions(+), 476 deletions(-) delete mode 100644 src/SimpleModule.Api/wwwroot/css/app.css delete mode 100644 src/SimpleModule.Api/wwwroot/js/app.js delete mode 100644 src/modules/Products/src/Products/wwwroot/Products.pages.js delete mode 100644 src/modules/Users/src/Users/wwwroot/Users.pages.js diff --git a/.gitignore b/.gitignore index 7a7c25f9..16feb77a 100644 --- a/.gitignore +++ b/.gitignore @@ -415,3 +415,10 @@ tools/tailwindcss* # Module JS build output (generated by Vite) src/modules/**/wwwroot/*.lib.module.js src/modules/**/wwwroot/*.lib.module.js.map +src/modules/**/wwwroot/*.pages.js + +# Tailwind CSS build output +src/SimpleModule.Api/wwwroot/css/app.css + +# Vite app bundle output +src/SimpleModule.Api/wwwroot/js/app.js diff --git a/src/SimpleModule.Api/wwwroot/css/app.css b/src/SimpleModule.Api/wwwroot/css/app.css deleted file mode 100644 index 12949aee..00000000 --- a/src/SimpleModule.Api/wwwroot/css/app.css +++ /dev/null @@ -1,2 +0,0 @@ -/*! tailwindcss v4.1.3 | MIT License | https://tailwindcss.com */ -@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:rotateX(0);--tw-rotate-y:rotateY(0);--tw-rotate-z:rotateZ(0);--tw-skew-x:skewX(0);--tw-skew-y:skewY(0);--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-600:oklch(66.6% .179 58.318);--color-green-400:oklch(79.2% .209 151.711);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-blue-900:oklch(37.9% .146 265.522);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-3xl:48rem;--container-4xl:56rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height:calc(1.5/1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25/1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5/2.25);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--leading-relaxed:1.625;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--ease-out:cubic-bezier(0,0,.2,1);--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-primary:#0d9488;--color-primary-hover:#0f766e;--color-primary-subtle:#0d948814;--color-primary-ring:#0d948840;--color-accent:#059669;--color-success:#16a34a;--color-success-bg:#16a34a1a;--color-success-text:#15803d;--color-danger:#e11d48;--color-danger-hover:#be123c;--color-danger-bg:#e11d4814;--color-danger-text:#9f1239;--color-warning:#d97706;--color-warning-bg:#d9770614;--color-warning-border:#d9770633;--color-warning-text:#92400e;--color-info:#0ea5e9;--color-info-bg:#0ea5e914;--color-surface:#fff;--color-surface-raised:#f8fafc;--color-surface-sunken:#f1f5f9;--color-surface-overlay:#fffc;--color-text:#0f172a;--color-text-secondary:#475569;--color-text-muted:#94a3b8;--color-border:#e2e8f0;--color-border-strong:#cbd5e1;--color-code-bg:#1e293b;--color-code-text:#e2e8f0;--color-muted:#94a3b8}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html{scroll-behavior:smooth;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{background-color:var(--color-surface-sunken);color:var(--color-text);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.3s;font-family:DM Sans,system-ui,sans-serif;transition-duration:.3s}h1,h2,h3,h4,h5,h6{--tw-font-weight:var(--font-weight-bold);font-family:Sora,DM Sans,system-ui,sans-serif;font-weight:var(--font-weight-bold);--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight);color:var(--color-text);margin-top:0}h1{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}h2{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}h3{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}label{margin-bottom:calc(var(--spacing)*1.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);color:var(--color-text-secondary);display:block}input[type=email],input[type=password],input[type=text],input[type=tel]{border-radius:var(--radius-xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);width:100%;padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*3);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--color-text);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;transition-duration:.2s}:is(input[type=email],input[type=password],input[type=text],input[type=tel])::placeholder{color:var(--color-text-muted)}input[type=email]:focus,input[type=password]:focus,input[type=text]:focus,input[type=tel]:focus{border-color:var(--color-primary);--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(4px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);--tw-ring-color:var(--color-primary-ring);--tw-outline-style:none;outline-style:none}a{color:var(--color-primary);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;transition-duration:.15s}a:hover{color:var(--color-primary-hover)}hr{margin-block:calc(var(--spacing)*6);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--color-border)}::selection{background:#0d948833}}@layer components{.glass-card{border-radius:var(--radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface-overlay);--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);-webkit-backdrop-filter:blur(20px)saturate(180%)}.dark .glass-card{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);box-shadow:0 0 0 1px #94a3b80d,0 25px 50px -12px #00000080}.btn-primary,.btn-secondary,.btn-ghost,.btn-danger,.btn-outline{cursor:pointer;justify-content:center;align-items:center;gap:calc(var(--spacing)*2);border-radius:var(--radius-xl);--tw-border-style:none;padding-inline:calc(var(--spacing)*5);padding-block:calc(var(--spacing)*2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;--tw-ease:var(--ease-out);transition-duration:.2s;transition-timing-function:var(--ease-out);border-style:none;text-decoration-line:none;display:inline-flex}.btn-primary:active,.btn-secondary:active,.btn-ghost:active,.btn-danger:active,.btn-outline:active{transform:scale(.97)}.btn-primary{color:var(--color-white);background:linear-gradient(135deg,var(--color-primary),var(--color-accent));box-shadow:0 4px 14px #0d948859}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 6px 20px #0d948880}.btn-secondary{border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);color:var(--color-text)}.btn-secondary:hover{border-color:var(--color-border-strong);background-color:var(--color-surface-raised)}.btn-ghost{color:var(--color-text-secondary);background-color:#0000}.btn-ghost:hover{background-color:var(--color-primary-subtle);color:var(--color-primary)}.btn-danger{background-color:var(--color-danger);color:var(--color-white);box-shadow:0 4px 14px #e11d4840}.btn-danger:hover{background-color:var(--color-danger-hover);transform:translateY(-1px);box-shadow:0 6px 20px #e11d4866}.btn-outline{border-style:var(--tw-border-style);color:var(--color-primary);background-color:#0000;border-width:2px;border-color:#0d94884d}@supports (color:color-mix(in lab, red, red)){.btn-outline{border-color:color-mix(in oklab,var(--color-primary)30%,transparent)}}.btn-outline:hover{border-color:var(--color-primary);background-color:var(--color-primary-subtle)}.btn-sm{border-radius:var(--radius-lg);padding-inline:calc(var(--spacing)*3.5);padding-block:calc(var(--spacing)*1.5);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.btn-lg{padding-inline:calc(var(--spacing)*8);padding-block:calc(var(--spacing)*3.5);font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.form-group{margin-bottom:calc(var(--spacing)*5)}.badge-success,.badge-danger,.badge-warning,.badge-info{padding-inline:calc(var(--spacing)*2.5);padding-block:calc(var(--spacing)*1);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);border-radius:3.40282e38px;align-items:center;display:inline-flex}.badge-success{background-color:var(--color-success-bg);color:var(--color-success-text)}.badge-danger{background-color:var(--color-danger-bg);color:var(--color-danger-text)}.badge-warning{background-color:var(--color-warning-bg);color:var(--color-warning-text)}.badge-info{background-color:var(--color-info-bg);color:var(--color-primary)}.alert-success,.alert-danger,.alert-warning,.alert-info{border-radius:var(--radius-xl);border-style:var(--tw-border-style);padding:calc(var(--spacing)*4);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));border-width:1px}.alert-success{background-color:var(--color-success-bg);color:var(--color-success-text);border-color:#16a34a33}@supports (color:color-mix(in lab, red, red)){.alert-success{border-color:color-mix(in oklab,var(--color-success)20%,transparent)}}.alert-danger{background-color:var(--color-danger-bg);color:var(--color-danger-text);border-color:#e11d4833}@supports (color:color-mix(in lab, red, red)){.alert-danger{border-color:color-mix(in oklab,var(--color-danger)20%,transparent)}}.alert-warning{border-color:var(--color-warning-border);background-color:var(--color-warning-bg);color:var(--color-warning-text)}.alert-info{background-color:var(--color-info-bg);color:var(--color-primary);border-color:#0ea5e933}@supports (color:color-mix(in lab, red, red)){.alert-info{border-color:color-mix(in oklab,var(--color-info)20%,transparent)}}.code-block{border-radius:var(--radius-xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-code-bg);padding:calc(var(--spacing)*4);font-family:var(--font-mono);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--color-code-text);font-family:JetBrains Mono,Fira Code,monospace;overflow:auto}.panel{margin-bottom:calc(var(--spacing)*8)}.panel-title{margin-bottom:calc(var(--spacing)*4);align-items:center;gap:calc(var(--spacing)*2);padding-bottom:calc(var(--spacing)*3);font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height));--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold);font-family:Sora,system-ui,sans-serif;display:flex}.panel-title:before{content:"";height:calc(var(--spacing)*5);width:calc(var(--spacing)*1);background:linear-gradient(180deg,var(--color-primary),var(--color-accent));border-radius:3.40282e38px}.card{border-radius:var(--radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);padding:calc(var(--spacing)*5);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;transition-duration:.2s}.card:hover{border-color:var(--color-border-strong)}.nav-link-active,.nav-link-inactive{border-radius:var(--radius-xl);padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;text-decoration-line:none;transition-duration:.15s;display:block}.nav-link-active{background-color:var(--color-primary-subtle);--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--color-primary)}.nav-link-inactive{color:var(--color-text-secondary)}.nav-link-inactive:hover{background-color:var(--color-surface-raised);color:var(--color-text)}}@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.top-0{top:calc(var(--spacing)*0)}.top-1\/2{top:50%}.left-1\/2{left:50%}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:calc(var(--spacing)*0)}.mx-auto{margin-inline:auto}.my-4{margin-block:calc(var(--spacing)*4)}.my-6{margin-block:calc(var(--spacing)*6)}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-6{margin-top:calc(var(--spacing)*6)}.mt-8{margin-top:calc(var(--spacing)*8)}.mb-0{margin-bottom:calc(var(--spacing)*0)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-5{margin-bottom:calc(var(--spacing)*5)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.mb-16{margin-bottom:calc(var(--spacing)*16)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-2{margin-left:calc(var(--spacing)*2)}.ml-4{margin-left:calc(var(--spacing)*4)}.ml-7{margin-left:calc(var(--spacing)*7)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.table{display:table}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-12{height:calc(var(--spacing)*12)}.h-14{height:calc(var(--spacing)*14)}.h-16{height:calc(var(--spacing)*16)}.h-\[18px\]{height:18px}.max-h-30{max-height:calc(var(--spacing)*30)}.max-h-50{max-height:calc(var(--spacing)*50)}.min-h-\[calc\(100vh-12rem\)\]{min-height:calc(100vh - 12rem)}.min-h-\[calc\(100vh-16rem\)\]{min-height:calc(100vh - 16rem)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-12{width:calc(var(--spacing)*12)}.w-14{width:calc(var(--spacing)*14)}.w-16{width:calc(var(--spacing)*16)}.w-\[18px\]{width:18px}.w-full{width:100%}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\[140px\]{max-width:140px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x)var(--tw-rotate-y)var(--tw-rotate-z)var(--tw-skew-x)var(--tw-skew-y)}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-decimal{list-style-type:decimal}.list-none{list-style-type:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-5{gap:calc(var(--spacing)*5)}.gap-6{gap:calc(var(--spacing)*6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px*var(--tw-divide-y-reverse));border-bottom-width:calc(1px*calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-gray-200>:not(:last-child)){border-color:var(--color-gray-200)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-x-auto{overflow-x:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-none{--tw-border-style:none;border-style:none}.border-border{border-color:var(--color-border)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-green-600{background-color:var(--color-green-600)}.bg-info-bg{background-color:var(--color-info-bg)}.bg-primary-subtle{background-color:var(--color-primary-subtle)}.bg-red-600{background-color:var(--color-red-600)}.bg-success-bg{background-color:var(--color-success-bg)}.bg-surface{background-color:var(--color-surface)}.bg-surface-overlay{background-color:var(--color-surface-overlay)}.bg-surface-raised{background-color:var(--color-surface-raised)}.bg-transparent{background-color:#0000}.bg-warning-bg{background-color:var(--color-warning-bg)}.bg-white{background-color:var(--color-white)}.p-0{padding:calc(var(--spacing)*0)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-5{padding:calc(var(--spacing)*5)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-3{padding-block:calc(var(--spacing)*3)}.pt-3{padding-top:calc(var(--spacing)*3)}.pl-5{padding-left:calc(var(--spacing)*5)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-all{word-break:break-all}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent{color:var(--color-accent)}.text-amber-600{color:var(--color-amber-600)}.text-blue-600{color:var(--color-blue-600)}.text-blue-800{color:var(--color-blue-800)}.text-border{color:var(--color-border)}.text-danger{color:var(--color-danger)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-green-600{color:var(--color-green-600)}.text-info{color:var(--color-info)}.text-muted{color:var(--color-muted)}.text-primary{color:var(--color-primary)}.text-red-600{color:var(--color-red-600)}.text-success{color:var(--color-success)}.text-text{color:var(--color-text)}.text-text-muted{color:var(--color-text-muted)}.text-text-secondary{color:var(--color-text-secondary)}.text-warning{color:var(--color-warning)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.no-underline{text-decoration-line:none}.accent-primary{accent-color:var(--color-primary)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}@media (hover:hover){.group-hover\:scale-105:is(:where(.group):hover *){--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x)var(--tw-scale-y)}.group-hover\:text-primary:is(:where(.group):hover *){color:var(--color-primary)}}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-green-700:hover{background-color:var(--color-green-700)}.hover\:bg-red-700:hover{background-color:var(--color-red-700)}.hover\:bg-surface-raised:hover{background-color:var(--color-surface-raised)}.hover\:text-blue-800:hover{color:var(--color-blue-800)}.hover\:text-danger-hover:hover{color:var(--color-danger-hover)}.hover\:text-gray-700:hover{color:var(--color-gray-700)}.hover\:text-primary:hover{color:var(--color-primary)}.hover\:text-primary-hover:hover{color:var(--color-primary-hover)}.hover\:text-red-800:hover{color:var(--color-red-800)}.hover\:text-text:hover{color:var(--color-text)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width:40rem){.sm\:sticky{position:sticky}.sm\:top-20{top:calc(var(--spacing)*20)}.sm\:block{display:block}.sm\:flex{display:flex}.sm\:inline-flex{display:inline-flex}.sm\:w-56{width:calc(var(--spacing)*56)}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:p-8{padding:calc(var(--spacing)*8)}.sm\:px-6{padding-inline:calc(var(--spacing)*6)}}@media (min-width:64rem){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (prefers-color-scheme:dark){.dark\:block{display:block}.dark\:hidden{display:none}:where(.dark\:divide-gray-700>:not(:last-child)){border-color:var(--color-gray-700)}.dark\:border-gray-600{border-color:var(--color-gray-600)}.dark\:border-gray-700{border-color:var(--color-gray-700)}.dark\:bg-blue-900\/30{background-color:#1c398e4d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-blue-900\/30{background-color:color-mix(in oklab,var(--color-blue-900)30%,transparent)}}.dark\:bg-gray-800{background-color:var(--color-gray-800)}.dark\:text-amber-400{color:var(--color-amber-400)}.dark\:text-blue-300{color:var(--color-blue-300)}.dark\:text-blue-400{color:var(--color-blue-400)}.dark\:text-gray-400{color:var(--color-gray-400)}.dark\:text-green-400{color:var(--color-green-400)}.dark\:text-red-400{color:var(--color-red-400)}@media (hover:hover){.dark\:hover\:bg-gray-800\/50:hover{background-color:#1e293980}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-gray-800\/50:hover{background-color:color-mix(in oklab,var(--color-gray-800)50%,transparent)}}.dark\:hover\:text-blue-300:hover{color:var(--color-blue-300)}.dark\:hover\:text-gray-300:hover{color:var(--color-gray-300)}}}.gradient-text{background:linear-gradient(135deg,var(--color-primary),var(--color-accent));-webkit-text-fill-color:transparent;-webkit-background-clip:text;background-clip:text}.gradient-border{position:relative}.gradient-border:before{content:"";border-radius:inherit;background:linear-gradient(135deg,var(--color-primary),var(--color-accent));-webkit-mask-composite:xor;pointer-events:none;-webkit-mask-composite:xor;-webkit-mask-source-type:auto,auto;padding:1px;position:absolute;inset:0;-webkit-mask-image:linear-gradient(#fff 0 0),linear-gradient(#fff 0 0);mask-image:linear-gradient(#fff 0 0),linear-gradient(#fff 0 0);-webkit-mask-position:0 0,0 0;mask-position:0 0,0 0;-webkit-mask-size:auto,auto;mask-size:auto,auto;-webkit-mask-repeat:repeat,repeat;mask-repeat:repeat,repeat;-webkit-mask-clip:content-box,border-box;mask-clip:content-box,border-box;-webkit-mask-origin:content-box,border-box;mask-origin:content-box,border-box;-webkit-mask-composite:xor;mask-composite:exclude;-webkit-mask-source-type:auto,auto;mask-mode:match-source,match-source}}.dark{--color-primary-subtle:#0d948826;--color-primary-ring:#0d948859;--color-success-bg:#4ade801f;--color-success-text:#86efac;--color-danger-bg:#e11d481f;--color-danger-text:#fda4af;--color-warning-bg:#d977061f;--color-warning-border:#d977064d;--color-warning-text:#fcd34d;--color-info-bg:#0ea5e91f;--color-surface:#0f172a;--color-surface-raised:#1e293b;--color-surface-sunken:#0b1120;--color-surface-overlay:#0f172ad9;--color-text:#f1f5f9;--color-text-secondary:#94a3b8;--color-text-muted:#64748b;--color-text-inverse:#0f172a;--color-border:#1e293b;--color-border-strong:#334155;--color-code-bg:#020617;--color-code-text:#e2e8f0}.bg-mesh{z-index:-1;background:var(--color-surface-sunken);position:fixed;inset:0;overflow:hidden}.bg-mesh:before,.bg-mesh:after{content:"";filter:blur(100px);opacity:.15;border-radius:50%;animation:20s ease-in-out infinite mesh-float;position:absolute}.bg-mesh:before{background:var(--color-primary);width:600px;height:600px;top:-10%;right:-10%}.bg-mesh:after{background:var(--color-accent);width:500px;height:500px;animation-direction:reverse;animation-delay:-10s;bottom:-10%;left:-10%}.dark .bg-mesh:before,.dark .bg-mesh:after{opacity:.08}@keyframes mesh-float{0%,to{transform:translate(0)scale(1)}33%{transform:translate(40px,-30px)scale(1.05)}66%{transform:translate(-20px,20px)scale(.95)}}.spinner{margin-left:calc(var(--spacing)*2);height:calc(var(--spacing)*4);width:calc(var(--spacing)*4);animation:var(--animate-spin);border-style:var(--tw-border-style);border-width:2px;border-color:var(--color-border);border-top-color:var(--color-primary);vertical-align:middle;border-radius:3.40282e38px;display:inline-block}.user-dropdown-wrap{position:relative}.user-dropdown-trigger{cursor:pointer;align-items:center;gap:calc(var(--spacing)*2);border-radius:var(--radius-xl);--tw-border-style:none;padding-inline:calc(var(--spacing)*2);padding-block:calc(var(--spacing)*1.5);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;background-color:#0000;border-style:none;transition-duration:.2s;display:flex}.user-dropdown-trigger:hover,.user-dropdown-trigger[aria-expanded=true]{background-color:var(--color-surface-raised)}.user-dropdown{border-radius:var(--radius-xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);width:240px;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);opacity:0;pointer-events:none;z-index:100;transition:opacity .18s,transform .18s;position:absolute;top:calc(100% + 6px);right:0;transform:translateY(-4px)scale(.97)}.user-dropdown.open{opacity:1;pointer-events:auto;transform:translateY(0)scale(1)}.dark .user-dropdown{box-shadow:0 0 0 1px #94a3b80f,0 20px 40px -8px #0009}.user-dropdown-header{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--color-border);padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*3)}.user-dropdown-body{padding-block:calc(var(--spacing)*1.5)}.user-dropdown-item{cursor:pointer;align-items:center;gap:calc(var(--spacing)*2.5);padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*2);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--color-text-secondary);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;text-decoration-line:none;transition-duration:.15s;display:flex}.user-dropdown-item:hover{background-color:var(--color-surface-raised);color:var(--color-text)}.user-dropdown-divider{margin-block:calc(var(--spacing)*1.5);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--color-border)}.user-dropdown-item.danger{color:var(--color-danger)}.user-dropdown-item.danger:hover{background-color:var(--color-danger-bg);color:var(--color-danger)}.dash-card{border-radius:var(--radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);padding:calc(var(--spacing)*5);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;transition-duration:.2s}.dash-card:hover{border-color:var(--color-border-strong);--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dash-stat{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height));--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold);--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight);font-family:Sora,system-ui,sans-serif}.dash-label{margin-top:calc(var(--spacing)*1);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider);color:var(--color-text-muted);text-transform:uppercase}.validation-message{margin-top:calc(var(--spacing)*1.5);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);color:var(--color-danger)}table{width:100%;font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}table th{padding-bottom:calc(var(--spacing)*3);text-align:left;font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider);color:var(--color-text-muted);text-transform:uppercase}table td{border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--color-border);padding-block:calc(var(--spacing)*2.5);color:var(--color-text-secondary)}table td:first-child{font-family:var(--font-mono);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--color-primary)}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background-color:var(--color-border-strong);border-radius:3.40282e38px}::-webkit-scrollbar-thumb:hover{background-color:var(--color-text-muted)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false;initial-value:rotateX(0)}@property --tw-rotate-y{syntax:"*";inherits:false;initial-value:rotateY(0)}@property --tw-rotate-z{syntax:"*";inherits:false;initial-value:rotateZ(0)}@property --tw-skew-x{syntax:"*";inherits:false;initial-value:skewX(0)}@property --tw-skew-y{syntax:"*";inherits:false;initial-value:skewY(0)}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}} \ No newline at end of file diff --git a/src/SimpleModule.Api/wwwroot/js/app.js b/src/SimpleModule.Api/wwwroot/js/app.js deleted file mode 100644 index 4e801e78..00000000 --- a/src/SimpleModule.Api/wwwroot/js/app.js +++ /dev/null @@ -1 +0,0 @@ -import{jsx as v}from"/js/vendor/react-jsx-runtime.js";import{createInertiaApp as E}from"/js/vendor/inertiajs-react.js";import{createRoot as g}from"/js/vendor/react-dom-client.js";const y="modulepreload",P=function(n){return"/"+n},f={},_=function(o,s,a){let u=Promise.resolve();if(s&&s.length>0){let i=function(t){return Promise.all(t.map(l=>Promise.resolve(l).then(c=>({status:"fulfilled",value:c}),c=>({status:"rejected",reason:c}))))};document.getElementsByTagName("link");const e=document.querySelector("meta[property=csp-nonce]"),m=(e==null?void 0:e.nonce)||(e==null?void 0:e.getAttribute("nonce"));u=i(s.map(t=>{if(t=P(t),t in f)return;f[t]=!0;const l=t.endsWith(".css"),c=l?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${t}"]${c}`))return;const r=document.createElement("link");if(r.rel=l?"stylesheet":y,l||(r.as="script"),r.crossOrigin="",r.href=t,m&&r.setAttribute("nonce",m),document.head.appendChild(r),l)return new Promise((p,h)=>{r.addEventListener("load",p),r.addEventListener("error",()=>h(new Error(`Unable to preload CSS for ${t}`)))})}))}function d(i){const e=new Event("vite:preloadError",{cancelable:!0});if(e.payload=i,window.dispatchEvent(e),!e.defaultPrevented)throw i}return u.then(i=>{for(const e of i||[])e.status==="rejected"&&d(e.reason);return o().catch(d)})};E({resolve:async n=>{const o=n.split("/")[0],a=(await _(()=>import(`/_content/${o}/${o}.pages.js`),[])).pages[n];return a.default?a:{default:a}},setup({el:n,App:o,props:s}){g(n).render(v(o,{...s}))}}); diff --git a/src/modules/Products/src/Products/wwwroot/Products.pages.js b/src/modules/Products/src/Products/wwwroot/Products.pages.js deleted file mode 100644 index 48642ee4..00000000 --- a/src/modules/Products/src/Products/wwwroot/Products.pages.js +++ /dev/null @@ -1,26 +0,0 @@ -import { jsxs as r, jsx as a } from "react/jsx-runtime"; -function t({ products: s }) { - return /* @__PURE__ */ r("div", { className: "max-w-4xl mx-auto p-8", children: [ - /* @__PURE__ */ a("h1", { className: "text-3xl font-bold mb-6", children: "Products" }), - /* @__PURE__ */ a("ul", { className: "space-y-3", children: s.map((e) => /* @__PURE__ */ r( - "li", - { - className: "flex justify-between items-center p-4 rounded-lg border border-gray-200 dark:border-gray-700", - children: [ - /* @__PURE__ */ a("span", { className: "font-medium", children: e.name }), - /* @__PURE__ */ r("span", { className: "text-gray-600 dark:text-gray-400", children: [ - "$", - e.price.toFixed(2) - ] }) - ] - }, - e.id - )) }) - ] }); -} -const c = { - "Products/Browse": t -}; -export { - c as pages -}; diff --git a/src/modules/Users/src/Users/wwwroot/Users.pages.js b/src/modules/Users/src/Users/wwwroot/Users.pages.js deleted file mode 100644 index 5d95443b..00000000 --- a/src/modules/Users/src/Users/wwwroot/Users.pages.js +++ /dev/null @@ -1,447 +0,0 @@ -import { jsxs as t, jsx as e } from "react/jsx-runtime"; -import { router as l } from "@inertiajs/react"; -import { useState as b } from "react"; -function x({ users: r, search: i, page: a, totalPages: s, totalCount: m }) { - const [o, g] = b(i); - function d(n) { - n.preventDefault(), l.get("/admin/users", { search: o, page: 1 }, { preserveState: !0 }); - } - function c(n) { - l.get("/admin/users", { search: o, page: n }, { preserveState: !0 }); - } - return /* @__PURE__ */ t("div", { className: "max-w-6xl mx-auto p-8", children: [ - /* @__PURE__ */ t("div", { className: "flex justify-between items-center mb-6", children: [ - /* @__PURE__ */ e("h1", { className: "text-3xl font-bold", children: "Users" }), - /* @__PURE__ */ t("span", { className: "text-gray-500", children: [ - m, - " total" - ] }) - ] }), - /* @__PURE__ */ t("form", { onSubmit: d, className: "mb-6 flex gap-2", children: [ - /* @__PURE__ */ e( - "input", - { - type: "text", - value: o, - onChange: (n) => g(n.target.value), - placeholder: "Search by name or email...", - className: "flex-1 px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" - } - ), - /* @__PURE__ */ e( - "button", - { - type: "submit", - className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", - children: "Search" - } - ) - ] }), - /* @__PURE__ */ e("div", { className: "overflow-x-auto rounded-lg border border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ t("table", { className: "w-full text-left", children: [ - /* @__PURE__ */ e("thead", { className: "bg-gray-50 dark:bg-gray-800", children: /* @__PURE__ */ t("tr", { children: [ - /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Name" }), - /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Email" }), - /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Roles" }), - /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Status" }), - /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Created" }), - /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400" }) - ] }) }), - /* @__PURE__ */ e("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-700", children: r.map((n) => /* @__PURE__ */ t("tr", { className: "hover:bg-gray-50 dark:hover:bg-gray-800/50", children: [ - /* @__PURE__ */ e("td", { className: "px-4 py-3 font-medium", children: n.displayName || "—" }), - /* @__PURE__ */ t("td", { className: "px-4 py-3 text-gray-600 dark:text-gray-400", children: [ - n.email, - !n.emailConfirmed && /* @__PURE__ */ e("span", { className: "ml-2 text-xs text-amber-600 dark:text-amber-400", children: "unverified" }) - ] }), - /* @__PURE__ */ e("td", { className: "px-4 py-3", children: /* @__PURE__ */ e("div", { className: "flex gap-1 flex-wrap", children: n.roles.map((u) => /* @__PURE__ */ e( - "span", - { - className: "px-2 py-0.5 text-xs rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300", - children: u - }, - u - )) }) }), - /* @__PURE__ */ e("td", { className: "px-4 py-3", children: n.isLockedOut ? /* @__PURE__ */ e("span", { className: "text-red-600 dark:text-red-400 text-sm", children: "Locked" }) : /* @__PURE__ */ e("span", { className: "text-green-600 dark:text-green-400 text-sm", children: "Active" }) }), - /* @__PURE__ */ e("td", { className: "px-4 py-3 text-sm text-gray-500", children: new Date(n.createdAt).toLocaleDateString() }), - /* @__PURE__ */ e("td", { className: "px-4 py-3", children: /* @__PURE__ */ e( - "button", - { - onClick: () => l.get(`/admin/users/${n.id}/edit`), - className: "text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300 text-sm", - children: "Edit" - } - ) }) - ] }, n.id)) }) - ] }) }), - s > 1 && /* @__PURE__ */ t("div", { className: "flex justify-center gap-2 mt-6", children: [ - /* @__PURE__ */ e( - "button", - { - onClick: () => c(a - 1), - disabled: a <= 1, - className: "px-3 py-1 rounded border border-gray-300 dark:border-gray-600 disabled:opacity-50", - children: "Previous" - } - ), - /* @__PURE__ */ t("span", { className: "px-3 py-1 text-gray-600 dark:text-gray-400", children: [ - "Page ", - a, - " of ", - s - ] }), - /* @__PURE__ */ e( - "button", - { - onClick: () => c(a + 1), - disabled: a >= s, - className: "px-3 py-1 rounded border border-gray-300 dark:border-gray-600 disabled:opacity-50", - children: "Next" - } - ) - ] }) - ] }); -} -function h({ user: r, userRoles: i, allRoles: a }) { - function s(d) { - d.preventDefault(); - const c = new FormData(d.currentTarget); - l.post(`/admin/users/${r.id}`, c); - } - function m(d) { - d.preventDefault(); - const c = new FormData(d.currentTarget); - l.post(`/admin/users/${r.id}/roles`, c); - } - function o() { - l.post(`/admin/users/${r.id}/lock`); - } - function g() { - l.post(`/admin/users/${r.id}/unlock`); - } - return /* @__PURE__ */ t("div", { className: "max-w-3xl mx-auto p-8", children: [ - /* @__PURE__ */ t("div", { className: "flex items-center gap-4 mb-6", children: [ - /* @__PURE__ */ e( - "button", - { - onClick: () => l.get("/admin/users"), - className: "text-gray-500 hover:text-gray-700 dark:hover:text-gray-300", - children: "← Back" - } - ), - /* @__PURE__ */ e("h1", { className: "text-3xl font-bold", children: "Edit User" }) - ] }), - /* @__PURE__ */ t("div", { className: "mb-6 text-sm text-gray-500 dark:text-gray-400", children: [ - /* @__PURE__ */ t("span", { children: [ - "Created: ", - new Date(r.createdAt).toLocaleString() - ] }), - r.lastLoginAt && /* @__PURE__ */ t("span", { className: "ml-4", children: [ - "Last login: ", - new Date(r.lastLoginAt).toLocaleString() - ] }) - ] }), - /* @__PURE__ */ t("form", { onSubmit: s, className: "mb-8 p-6 rounded-lg border border-gray-200 dark:border-gray-700", children: [ - /* @__PURE__ */ e("h2", { className: "text-lg font-semibold mb-4", children: "Details" }), - /* @__PURE__ */ t("div", { className: "space-y-4", children: [ - /* @__PURE__ */ t("div", { children: [ - /* @__PURE__ */ e("label", { className: "block text-sm font-medium mb-1", children: "Display Name" }), - /* @__PURE__ */ e( - "input", - { - type: "text", - name: "displayName", - defaultValue: r.displayName, - className: "w-full px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" - } - ) - ] }), - /* @__PURE__ */ t("div", { children: [ - /* @__PURE__ */ e("label", { className: "block text-sm font-medium mb-1", children: "Email" }), - /* @__PURE__ */ e( - "input", - { - type: "email", - name: "email", - defaultValue: r.email, - className: "w-full px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" - } - ) - ] }), - /* @__PURE__ */ t("div", { className: "flex items-center gap-2", children: [ - /* @__PURE__ */ e( - "input", - { - type: "checkbox", - name: "emailConfirmed", - id: "emailConfirmed", - defaultChecked: r.emailConfirmed, - className: "rounded border-gray-300" - } - ), - /* @__PURE__ */ e("label", { htmlFor: "emailConfirmed", className: "text-sm", children: "Email confirmed" }) - ] }), - /* @__PURE__ */ e( - "button", - { - type: "submit", - className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", - children: "Save Details" - } - ) - ] }) - ] }), - /* @__PURE__ */ t("form", { onSubmit: m, className: "mb-8 p-6 rounded-lg border border-gray-200 dark:border-gray-700", children: [ - /* @__PURE__ */ e("h2", { className: "text-lg font-semibold mb-4", children: "Roles" }), - /* @__PURE__ */ t("div", { className: "space-y-2 mb-4", children: [ - a.map((d) => /* @__PURE__ */ t("div", { className: "flex items-center gap-2", children: [ - /* @__PURE__ */ e( - "input", - { - type: "checkbox", - name: "roles", - value: d.name ?? "", - id: `role-${d.id}`, - defaultChecked: i.includes(d.name ?? ""), - className: "rounded border-gray-300" - } - ), - /* @__PURE__ */ t("label", { htmlFor: `role-${d.id}`, className: "text-sm", children: [ - d.name, - d.description && /* @__PURE__ */ t("span", { className: "text-gray-500 ml-1", children: [ - "— ", - d.description - ] }) - ] }) - ] }, d.id)), - a.length === 0 && /* @__PURE__ */ e("p", { className: "text-sm text-gray-500", children: "No roles defined." }) - ] }), - /* @__PURE__ */ e( - "button", - { - type: "submit", - className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", - children: "Save Roles" - } - ) - ] }), - /* @__PURE__ */ t("div", { className: "p-6 rounded-lg border border-gray-200 dark:border-gray-700", children: [ - /* @__PURE__ */ e("h2", { className: "text-lg font-semibold mb-4", children: "Account Status" }), - r.isLockedOut ? /* @__PURE__ */ t("div", { children: [ - /* @__PURE__ */ e("p", { className: "text-sm text-red-600 dark:text-red-400 mb-3", children: "This account is locked." }), - /* @__PURE__ */ e( - "button", - { - onClick: g, - className: "px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700", - children: "Unlock Account" - } - ) - ] }) : /* @__PURE__ */ t("div", { children: [ - /* @__PURE__ */ e("p", { className: "text-sm text-green-600 dark:text-green-400 mb-3", children: "This account is active." }), - /* @__PURE__ */ e( - "button", - { - onClick: o, - className: "px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700", - children: "Lock Account" - } - ) - ] }) - ] }) - ] }); -} -function p({ roles: r }) { - function i(a, s) { - confirm(`Delete role "${s}"?`) && l.delete(`/admin/roles/${a}`, { - onError: () => alert("Cannot delete role with assigned users.") - }); - } - return /* @__PURE__ */ t("div", { className: "max-w-4xl mx-auto p-8", children: [ - /* @__PURE__ */ t("div", { className: "flex justify-between items-center mb-6", children: [ - /* @__PURE__ */ e("h1", { className: "text-3xl font-bold", children: "Roles" }), - /* @__PURE__ */ e( - "button", - { - onClick: () => l.get("/admin/roles/create"), - className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", - children: "Create Role" - } - ) - ] }), - /* @__PURE__ */ e("div", { className: "overflow-x-auto rounded-lg border border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ t("table", { className: "w-full text-left", children: [ - /* @__PURE__ */ e("thead", { className: "bg-gray-50 dark:bg-gray-800", children: /* @__PURE__ */ t("tr", { children: [ - /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Name" }), - /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Description" }), - /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Users" }), - /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400", children: "Created" }), - /* @__PURE__ */ e("th", { className: "px-4 py-3 text-sm font-medium text-gray-500 dark:text-gray-400" }) - ] }) }), - /* @__PURE__ */ e("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-700", children: r.map((a) => /* @__PURE__ */ t("tr", { className: "hover:bg-gray-50 dark:hover:bg-gray-800/50", children: [ - /* @__PURE__ */ e("td", { className: "px-4 py-3 font-medium", children: a.name }), - /* @__PURE__ */ e("td", { className: "px-4 py-3 text-gray-600 dark:text-gray-400", children: a.description || "—" }), - /* @__PURE__ */ e("td", { className: "px-4 py-3", children: /* @__PURE__ */ e("span", { className: "px-2 py-0.5 text-xs rounded-full bg-gray-100 dark:bg-gray-800", children: a.userCount }) }), - /* @__PURE__ */ e("td", { className: "px-4 py-3 text-sm text-gray-500", children: new Date(a.createdAt).toLocaleDateString() }), - /* @__PURE__ */ e("td", { className: "px-4 py-3", children: /* @__PURE__ */ t("div", { className: "flex gap-3", children: [ - /* @__PURE__ */ e( - "button", - { - onClick: () => l.get(`/admin/roles/${a.id}/edit`), - className: "text-blue-600 hover:text-blue-800 dark:text-blue-400 text-sm", - children: "Edit" - } - ), - /* @__PURE__ */ e( - "button", - { - onClick: () => i(a.id, a.name), - className: "text-red-600 hover:text-red-800 dark:text-red-400 text-sm", - children: "Delete" - } - ) - ] }) }) - ] }, a.id)) }) - ] }) }) - ] }); -} -function y() { - function r(i) { - i.preventDefault(); - const a = new FormData(i.currentTarget); - l.post("/admin/roles", a); - } - return /* @__PURE__ */ t("div", { className: "max-w-xl mx-auto p-8", children: [ - /* @__PURE__ */ t("div", { className: "flex items-center gap-4 mb-6", children: [ - /* @__PURE__ */ e( - "button", - { - onClick: () => l.get("/admin/roles"), - className: "text-gray-500 hover:text-gray-700 dark:hover:text-gray-300", - children: "← Back" - } - ), - /* @__PURE__ */ e("h1", { className: "text-3xl font-bold", children: "Create Role" }) - ] }), - /* @__PURE__ */ e("form", { onSubmit: r, className: "p-6 rounded-lg border border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ t("div", { className: "space-y-4", children: [ - /* @__PURE__ */ t("div", { children: [ - /* @__PURE__ */ e("label", { className: "block text-sm font-medium mb-1", children: "Name" }), - /* @__PURE__ */ e( - "input", - { - type: "text", - name: "name", - required: !0, - className: "w-full px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" - } - ) - ] }), - /* @__PURE__ */ t("div", { children: [ - /* @__PURE__ */ e("label", { className: "block text-sm font-medium mb-1", children: "Description" }), - /* @__PURE__ */ e( - "input", - { - type: "text", - name: "description", - className: "w-full px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" - } - ) - ] }), - /* @__PURE__ */ e( - "button", - { - type: "submit", - className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", - children: "Create" - } - ) - ] }) }) - ] }); -} -function N({ role: r, users: i }) { - function a(s) { - s.preventDefault(); - const m = new FormData(s.currentTarget); - l.post(`/admin/roles/${r.id}`, m); - } - return /* @__PURE__ */ t("div", { className: "max-w-xl mx-auto p-8", children: [ - /* @__PURE__ */ t("div", { className: "flex items-center gap-4 mb-6", children: [ - /* @__PURE__ */ e( - "button", - { - onClick: () => l.get("/admin/roles"), - className: "text-gray-500 hover:text-gray-700 dark:hover:text-gray-300", - children: "← Back" - } - ), - /* @__PURE__ */ e("h1", { className: "text-3xl font-bold", children: "Edit Role" }) - ] }), - /* @__PURE__ */ e("form", { onSubmit: a, className: "mb-8 p-6 rounded-lg border border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ t("div", { className: "space-y-4", children: [ - /* @__PURE__ */ t("div", { children: [ - /* @__PURE__ */ e("label", { className: "block text-sm font-medium mb-1", children: "Name" }), - /* @__PURE__ */ e( - "input", - { - type: "text", - name: "name", - defaultValue: r.name, - required: !0, - className: "w-full px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" - } - ) - ] }), - /* @__PURE__ */ t("div", { children: [ - /* @__PURE__ */ e("label", { className: "block text-sm font-medium mb-1", children: "Description" }), - /* @__PURE__ */ e( - "input", - { - type: "text", - name: "description", - defaultValue: r.description ?? "", - className: "w-full px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500" - } - ) - ] }), - /* @__PURE__ */ t("div", { className: "text-sm text-gray-500", children: [ - "Created: ", - new Date(r.createdAt).toLocaleString() - ] }), - /* @__PURE__ */ e( - "button", - { - type: "submit", - className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700", - children: "Save" - } - ) - ] }) }), - /* @__PURE__ */ t("div", { className: "p-6 rounded-lg border border-gray-200 dark:border-gray-700", children: [ - /* @__PURE__ */ t("h2", { className: "text-lg font-semibold mb-4", children: [ - "Assigned Users (", - i.length, - ")" - ] }), - i.length === 0 ? /* @__PURE__ */ e("p", { className: "text-sm text-gray-500", children: "No users assigned to this role." }) : /* @__PURE__ */ e("ul", { className: "space-y-2", children: i.map((s) => /* @__PURE__ */ t("li", { className: "flex justify-between items-center py-2", children: [ - /* @__PURE__ */ t("div", { children: [ - /* @__PURE__ */ e("span", { className: "font-medium", children: s.displayName || "—" }), - /* @__PURE__ */ e("span", { className: "text-gray-500 ml-2 text-sm", children: s.email }) - ] }), - /* @__PURE__ */ e( - "button", - { - onClick: () => l.get(`/admin/users/${s.id}/edit`), - className: "text-blue-600 hover:text-blue-800 dark:text-blue-400 text-sm", - children: "Edit" - } - ) - ] }, s.id)) }) - ] }) - ] }); -} -const w = { - "Users/Admin/Users": x, - "Users/Admin/UsersEdit": h, - "Users/Admin/Roles": p, - "Users/Admin/RolesCreate": y, - "Users/Admin/RolesEdit": N -}; -export { - w as pages -}; From 65d067c5f00810586633ee110946b0c17a076999 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Thu, 12 Mar 2026 15:16:32 +0100 Subject: [PATCH 05/62] feat: add module-driven menu system with source generator support Modules can now contribute navbar and user dropdown menu items via ConfigureMenu(IMenuBuilder). The source generator emits CollectModuleMenuItems() which wires everything into a singleton IMenuRegistry. MainLayout renders menu items dynamically instead of hardcoding links. Co-Authored-By: Claude Opus 4.6 --- .../Components/Layout/MainLayout.razor | 55 ++-- src/SimpleModule.Api/Program.cs | 3 + src/SimpleModule.Core/IModule.cs | 2 + src/SimpleModule.Core/Menu/IMenuCollection.cs | 6 + src/SimpleModule.Core/Menu/IMenuRegistry.cs | 6 + src/SimpleModule.Core/Menu/MenuCollection.cs | 14 + src/SimpleModule.Core/Menu/MenuItem.cs | 17 ++ src/SimpleModule.Core/Menu/MenuRegistry.cs | 14 + src/SimpleModule.Core/Menu/MenuSection.cs | 7 + .../ModuleDiscovererGenerator.cs | 41 +++ src/modules/Orders/src/Orders/OrdersModule.cs | 16 ++ .../Products/src/Products/ProductsModule.cs | 17 ++ src/modules/Users/src/Users/UsersModule.cs | 90 ++++++ .../Menu/IModuleConfigureMenuTests.cs | 85 ++++++ .../Menu/MenuBuilderTests.cs | 130 +++++++++ .../Menu/MenuItemTests.cs | 42 +++ .../Menu/MenuRegistryTests.cs | 137 +++++++++ .../MenuExtensionsGenerationTests.cs | 265 ++++++++++++++++++ 18 files changed, 923 insertions(+), 24 deletions(-) create mode 100644 src/SimpleModule.Core/Menu/IMenuCollection.cs create mode 100644 src/SimpleModule.Core/Menu/IMenuRegistry.cs create mode 100644 src/SimpleModule.Core/Menu/MenuCollection.cs create mode 100644 src/SimpleModule.Core/Menu/MenuItem.cs create mode 100644 src/SimpleModule.Core/Menu/MenuRegistry.cs create mode 100644 src/SimpleModule.Core/Menu/MenuSection.cs create mode 100644 tests/SimpleModule.Core.Tests/Menu/IModuleConfigureMenuTests.cs create mode 100644 tests/SimpleModule.Core.Tests/Menu/MenuBuilderTests.cs create mode 100644 tests/SimpleModule.Core.Tests/Menu/MenuItemTests.cs create mode 100644 tests/SimpleModule.Core.Tests/Menu/MenuRegistryTests.cs create mode 100644 tests/SimpleModule.Generator.Tests/MenuExtensionsGenerationTests.cs diff --git a/src/SimpleModule.Api/Components/Layout/MainLayout.razor b/src/SimpleModule.Api/Components/Layout/MainLayout.razor index ba88c476..862545c9 100644 --- a/src/SimpleModule.Api/Components/Layout/MainLayout.razor +++ b/src/SimpleModule.Api/Components/Layout/MainLayout.razor @@ -1,4 +1,6 @@ +@using SimpleModule.Core.Menu @inherits LayoutComponentBase +@inject IMenuRegistry MenuRegistry
      ); diff --git a/src/modules/Orders/src/Orders/Pages/List.tsx b/src/modules/Orders/src/Orders/Pages/List.tsx index da74118a..29ce340b 100644 --- a/src/modules/Orders/src/Orders/Pages/List.tsx +++ b/src/modules/Orders/src/Orders/Pages/List.tsx @@ -27,7 +27,10 @@ export default function List({ orders }: Props) {
      -

      +

      Orders

      {orders.length} total orders

      @@ -55,7 +58,9 @@ export default function List({ orders }: Props) {
      #{order.id} {order.userId} - {order.items.length} item{order.items.length !== 1 ? 's' : ''} + + {order.items.length} item{order.items.length !== 1 ? 's' : ''} + ${order.total.toFixed(2)} diff --git a/src/modules/Orders/src/Orders/Pages/index.ts b/src/modules/Orders/src/Orders/Pages/index.ts index fb996335..e1308f30 100644 --- a/src/modules/Orders/src/Orders/Pages/index.ts +++ b/src/modules/Orders/src/Orders/Pages/index.ts @@ -1,6 +1,6 @@ -import List from './List'; import Create from './Create'; import Edit from './Edit'; +import List from './List'; export const pages: Record = { 'Orders/List': List, diff --git a/src/modules/Orders/src/Orders/vite.config.ts b/src/modules/Orders/src/Orders/vite.config.ts index a0d83366..a2fd490a 100644 --- a/src/modules/Orders/src/Orders/vite.config.ts +++ b/src/modules/Orders/src/Orders/vite.config.ts @@ -1,6 +1,6 @@ -import { defineConfig } from 'vite'; +import { resolve } from 'node:path'; import react from '@vitejs/plugin-react'; -import { resolve } from 'path'; +import { defineConfig } from 'vite'; export default defineConfig({ plugins: [react()], diff --git a/src/modules/Products/src/Products/Pages/Browse.tsx b/src/modules/Products/src/Products/Pages/Browse.tsx index ee581af4..17f8b8b3 100644 --- a/src/modules/Products/src/Products/Pages/Browse.tsx +++ b/src/modules/Products/src/Products/Pages/Browse.tsx @@ -15,9 +15,7 @@ export default function Browse({ products }: { products: Product[] }) { className="flex justify-between items-center p-4 rounded-lg border border-gray-200 dark:border-gray-700" > {p.name} - - ${p.price.toFixed(2)} - + ${p.price.toFixed(2)} ))} diff --git a/src/modules/Products/src/Products/Pages/Create.tsx b/src/modules/Products/src/Products/Pages/Create.tsx index b662cef1..1b976dc9 100644 --- a/src/modules/Products/src/Products/Pages/Create.tsx +++ b/src/modules/Products/src/Products/Pages/Create.tsx @@ -10,10 +10,24 @@ export default function Create() { return (
      - - + + + + -

      +

      Create Product

      @@ -29,7 +43,9 @@ export default function Create() {
      - + diff --git a/src/modules/Products/src/Products/Pages/Edit.tsx b/src/modules/Products/src/Products/Pages/Edit.tsx index 33c436c3..7a59affd 100644 --- a/src/modules/Products/src/Products/Pages/Edit.tsx +++ b/src/modules/Products/src/Products/Pages/Edit.tsx @@ -25,10 +25,24 @@ export default function Edit({ product }: Props) { return (
      - - + + + + -

      +

      Edit Product

      @@ -42,16 +56,29 @@ export default function Edit({ product }: Props) {
      - +
      - +

      Danger Zone

      -

      Permanently delete this product. This action cannot be undone.

      - +

      + Permanently delete this product. This action cannot be undone. +

      +
      ); diff --git a/src/modules/Products/src/Products/Pages/Manage.tsx b/src/modules/Products/src/Products/Pages/Manage.tsx index 3e940422..9b158d64 100644 --- a/src/modules/Products/src/Products/Pages/Manage.tsx +++ b/src/modules/Products/src/Products/Pages/Manage.tsx @@ -20,7 +20,10 @@ export default function Manage({ products }: Props) {
      -

      +

      Manage Products

      {products.length} total products

      diff --git a/src/modules/Products/src/Products/Pages/index.ts b/src/modules/Products/src/Products/Pages/index.ts index 919e51a8..74a5a9d7 100644 --- a/src/modules/Products/src/Products/Pages/index.ts +++ b/src/modules/Products/src/Products/Pages/index.ts @@ -1,7 +1,7 @@ import Browse from './Browse'; -import Manage from './Manage'; import Create from './Create'; import Edit from './Edit'; +import Manage from './Manage'; export const pages: Record = { 'Products/Browse': Browse, diff --git a/src/modules/Products/src/Products/vite.config.ts b/src/modules/Products/src/Products/vite.config.ts index 3171f041..30faef6e 100644 --- a/src/modules/Products/src/Products/vite.config.ts +++ b/src/modules/Products/src/Products/vite.config.ts @@ -1,6 +1,6 @@ -import { defineConfig } from 'vite'; +import { resolve } from 'node:path'; import react from '@vitejs/plugin-react'; -import { resolve } from 'path'; +import { defineConfig } from 'vite'; export default defineConfig({ plugins: [react()], diff --git a/src/modules/Users/src/Users/Pages/Admin/Roles.tsx b/src/modules/Users/src/Users/Pages/Admin/Roles.tsx index 8e1bc23c..fb3b18a6 100644 --- a/src/modules/Users/src/Users/Pages/Admin/Roles.tsx +++ b/src/modules/Users/src/Users/Pages/Admin/Roles.tsx @@ -24,7 +24,10 @@ export default function Roles({ roles }: Props) {
      -

      +

      Roles

      Manage application roles

      @@ -49,9 +52,7 @@ export default function Roles({ roles }: Props) { {roles.map((role) => (
      {role.name} - {role.description || '\u2014'} - {role.description || '\u2014'} {role.userCount} {user.displayName || '\u2014'} {user.email} - {!user.emailConfirmed && ( - unverified - )} + {!user.emailConfirmed && unverified}
      diff --git a/src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx b/src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx index f021f9af..e1acada6 100644 --- a/src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx +++ b/src/modules/Users/src/Users/Pages/Admin/UsersEdit.tsx @@ -46,10 +46,24 @@ export default function UsersEdit({ user, userRoles, allRoles }: Props) { return (
      - - + + + + -

      +

      Edit User

      @@ -79,9 +93,13 @@ export default function UsersEdit({ user, userRoles, allRoles }: Props) { defaultChecked={user.emailConfirmed} className="accent-primary" /> - +
      - +
      @@ -106,11 +124,11 @@ export default function UsersEdit({ user, userRoles, allRoles }: Props) { ))} - {allRoles.length === 0 && ( -

      No roles defined.

      - )} + {allRoles.length === 0 &&

      No roles defined.

      } - +
      @@ -118,14 +136,20 @@ export default function UsersEdit({ user, userRoles, allRoles }: Props) { {user.isLockedOut ? (

      This account is locked.

      -
      ) : (

      This account is active.

      - +
      )}
      diff --git a/src/modules/Users/src/Users/Pages/index.ts b/src/modules/Users/src/Users/Pages/index.ts index d21dfcde..96caa0f9 100644 --- a/src/modules/Users/src/Users/Pages/index.ts +++ b/src/modules/Users/src/Users/Pages/index.ts @@ -1,8 +1,8 @@ -import Users from './Admin/Users'; -import UsersEdit from './Admin/UsersEdit'; import Roles from './Admin/Roles'; import RolesCreate from './Admin/RolesCreate'; import RolesEdit from './Admin/RolesEdit'; +import Users from './Admin/Users'; +import UsersEdit from './Admin/UsersEdit'; export const pages: Record = { 'Users/Admin/Users': Users, diff --git a/src/modules/Users/src/Users/Scripts/index.ts b/src/modules/Users/src/Users/Scripts/index.ts index 1310319f..ff362812 100644 --- a/src/modules/Users/src/Users/Scripts/index.ts +++ b/src/modules/Users/src/Users/Scripts/index.ts @@ -1,10 +1,10 @@ import { initQrCode } from './qrcode'; export function afterWebStarted(blazor: any) { - initModuleScripts(); - blazor.addEventListener('enhancedload', initModuleScripts); + initModuleScripts(); + blazor.addEventListener('enhancedload', initModuleScripts); } function initModuleScripts() { - initQrCode(); + initQrCode(); } diff --git a/src/modules/Users/src/Users/Scripts/qrcode.ts b/src/modules/Users/src/Users/Scripts/qrcode.ts index 2667dd19..50c2a78e 100644 --- a/src/modules/Users/src/Users/Scripts/qrcode.ts +++ b/src/modules/Users/src/Users/Scripts/qrcode.ts @@ -1,22 +1,22 @@ import QRCode from 'qrcode'; export function initQrCode() { - const dataEl = document.getElementById('qrCodeData'); - const qrEl = document.getElementById('qrCode'); + const dataEl = document.getElementById('qrCodeData'); + const qrEl = document.getElementById('qrCode'); - if (!dataEl || !qrEl) return; + if (!dataEl || !qrEl) return; - const url = dataEl.getAttribute('data-url'); - if (!url) return; + const url = dataEl.getAttribute('data-url'); + if (!url) return; - while (qrEl.firstChild) { - qrEl.removeChild(qrEl.firstChild); - } + while (qrEl.firstChild) { + qrEl.removeChild(qrEl.firstChild); + } - const canvas = document.createElement('canvas'); - qrEl.appendChild(canvas); + const canvas = document.createElement('canvas'); + qrEl.appendChild(canvas); - QRCode.toCanvas(canvas, url, { width: 200 }, (error) => { - if (error) console.error('QR code generation failed:', error); - }); + QRCode.toCanvas(canvas, url, { width: 200 }, (error) => { + if (error) console.error('QR code generation failed:', error); + }); } diff --git a/src/modules/Users/src/Users/vite.config.ts b/src/modules/Users/src/Users/vite.config.ts index 6e02ae80..aa7db406 100644 --- a/src/modules/Users/src/Users/vite.config.ts +++ b/src/modules/Users/src/Users/vite.config.ts @@ -1,6 +1,6 @@ -import { defineConfig } from 'vite'; +import { resolve } from 'node:path'; import react from '@vitejs/plugin-react'; -import { resolve } from 'path'; +import { defineConfig } from 'vite'; export default defineConfig({ plugins: [react()], From b57b90b81ae97e0ff26513ee79504c1b3c9d7f9a Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Fri, 13 Mar 2026 11:30:33 +0100 Subject: [PATCH 16/62] refactor: rename SimpleModule.Api to SimpleModule.Host Co-Authored-By: Claude Opus 4.6 --- .claude/skills/new-module/SKILL.md | 2 +- CLAUDE.md | 10 +- SimpleModule.slnx | 2 +- package-lock.json | 308 +- package.json | 2 +- .../Doctor/Checks/ProjectReferenceCheck.cs | 2 +- .../Infrastructure/SolutionContext.cs | 4 +- .../ClientApp/app.tsx | 0 .../ClientApp/package.json | 0 .../ClientApp/vite.config.ts | 0 .../Components/App.razor | 0 .../Components/InertiaShell.razor | 0 .../Components/Layout/MainLayout.razor | 0 .../Components/Pages/OAuthCallback.razor | 0 .../Components/Routes.razor | 0 .../Components/_Imports.razor | 4 +- .../Program.cs | 2 +- .../Properties/launchSettings.json | 2 +- .../SimpleModule.Host.csproj} | 0 .../Styles/app.css | 0 .../appsettings.json | 0 .../wwwroot/css/.gitkeep | 0 src/SimpleModule.Host/wwwroot/css/app.css | 2 + src/SimpleModule.Host/wwwroot/js/app.js | 1 + .../wwwroot/js/shell.js | 0 .../wwwroot/js/vendor/inertiajs-react.js | 13377 ++++++++++ .../wwwroot/js/vendor/react-dom-client.js | 20226 ++++++++++++++++ .../wwwroot/js/vendor/react-dom.js | 299 + .../wwwroot/js/vendor/react-jsx-runtime.js | 300 + .../wwwroot/js/vendor/react.js | 1047 + .../SolutionContextTests.cs | 2 +- .../SimpleModule.Tests.Shared.csproj | 2 +- tools/extract-ts-types.mjs | 2 +- 33 files changed, 35280 insertions(+), 316 deletions(-) rename src/{SimpleModule.Api => SimpleModule.Host}/ClientApp/app.tsx (100%) rename src/{SimpleModule.Api => SimpleModule.Host}/ClientApp/package.json (100%) rename src/{SimpleModule.Api => SimpleModule.Host}/ClientApp/vite.config.ts (100%) rename src/{SimpleModule.Api => SimpleModule.Host}/Components/App.razor (100%) rename src/{SimpleModule.Api => SimpleModule.Host}/Components/InertiaShell.razor (100%) rename src/{SimpleModule.Api => SimpleModule.Host}/Components/Layout/MainLayout.razor (100%) rename src/{SimpleModule.Api => SimpleModule.Host}/Components/Pages/OAuthCallback.razor (100%) rename src/{SimpleModule.Api => SimpleModule.Host}/Components/Routes.razor (100%) rename src/{SimpleModule.Api => SimpleModule.Host}/Components/_Imports.razor (72%) rename src/{SimpleModule.Api => SimpleModule.Host}/Program.cs (99%) rename src/{SimpleModule.Api => SimpleModule.Host}/Properties/launchSettings.json (91%) rename src/{SimpleModule.Api/SimpleModule.Api.csproj => SimpleModule.Host/SimpleModule.Host.csproj} (100%) rename src/{SimpleModule.Api => SimpleModule.Host}/Styles/app.css (100%) rename src/{SimpleModule.Api => SimpleModule.Host}/appsettings.json (100%) rename src/{SimpleModule.Api => SimpleModule.Host}/wwwroot/css/.gitkeep (100%) create mode 100644 src/SimpleModule.Host/wwwroot/css/app.css create mode 100644 src/SimpleModule.Host/wwwroot/js/app.js rename src/{SimpleModule.Api => SimpleModule.Host}/wwwroot/js/shell.js (100%) create mode 100644 src/SimpleModule.Host/wwwroot/js/vendor/inertiajs-react.js create mode 100644 src/SimpleModule.Host/wwwroot/js/vendor/react-dom-client.js create mode 100644 src/SimpleModule.Host/wwwroot/js/vendor/react-dom.js create mode 100644 src/SimpleModule.Host/wwwroot/js/vendor/react-jsx-runtime.js create mode 100644 src/SimpleModule.Host/wwwroot/js/vendor/react.js diff --git a/.claude/skills/new-module/SKILL.md b/.claude/skills/new-module/SKILL.md index 5e5bc539..5282eccb 100644 --- a/.claude/skills/new-module/SKILL.md +++ b/.claude/skills/new-module/SKILL.md @@ -58,7 +58,7 @@ public class Module : IModule } ``` -4. Add `` to `src/SimpleModule.Api/SimpleModule.Api.csproj` +4. Add `` to `src/SimpleModule.Host/SimpleModule.Host.csproj` 5. Add the project to `SimpleModule.sln` using `dotnet sln add` diff --git a/CLAUDE.md b/CLAUDE.md index 002c35be..89ae6b7a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,7 +10,7 @@ Modular monolith framework for .NET with compile-time module discovery via Rosly ```bash dotnet build -dotnet run --project src/SimpleModule.Api # runs on https://localhost:5001 +dotnet run --project src/SimpleModule.Host # runs on https://localhost:5001 ``` ## Frontend (npm workspaces) @@ -23,7 +23,7 @@ npm run lint # lint only npm run format # format only (with write) ``` -Workspaces: `src/modules/*/src/*` and `src/SimpleModule.Api/ClientApp`. +Workspaces: `src/modules/*/src/*` and `src/SimpleModule.Host/ClientApp`. ## Testing @@ -41,11 +41,11 @@ Test stack: xUnit.v3, FluentAssertions, Bogus, Microsoft.AspNetCore.Mvc.Testing. - **SimpleModule.Core** — `IModule` interface, `[Module]` attribute, `IEndpoint` interface, `[Dto]` attribute, menu system (`IMenuRegistry`), event bus (`IEventBus`), Inertia integration. - **SimpleModule.Generator** — Roslyn `IIncrementalGenerator` (netstandard2.0). Scans referenced assemblies for `[Module]` classes, `IEndpoint` implementors, and `[Dto]` types. Generates: `AddModules()`, `MapModuleEndpoints()`, `CollectModuleMenuItems()`, AOT JSON serializers, TypeScript interface definitions, Razor component assembly discovery. -- **SimpleModule.Api** — Host app (net10.0, PublishAot). Calls generated extension methods in `Program.cs`. Custom Inertia middleware bridges Blazor SSR → React. +- **SimpleModule.Host** — Host app (net10.0, PublishAot). Calls generated extension methods in `Program.cs`. Custom Inertia middleware bridges Blazor SSR → React. ### Frontend (React + Inertia.js) -- **ClientApp** (`src/SimpleModule.Api/ClientApp/app.tsx`) — Inertia bootstrap. Resolves pages by splitting route name (e.g., `Products/Browse` → imports `/_content/Products/Products.pages.js`). +- **ClientApp** (`src/SimpleModule.Host/ClientApp/app.tsx`) — Inertia bootstrap. Resolves pages by splitting route name (e.g., `Products/Browse` → imports `/_content/Products/Products.pages.js`). - **Module pages** — Each module builds its React pages via Vite in library mode → `{ModuleName}.pages.js` in module's `wwwroot/`. Entry point: `Pages/index.ts` exporting a `pages` record mapping route names to components. - **Type generation** — `[Dto]` types → source generator embeds TS interfaces → `tools/extract-ts-types.mjs` writes `.ts` files to `ClientApp/types/`. @@ -80,7 +80,7 @@ Test stack: xUnit.v3, FluentAssertions, Bogus, Microsoft.AspNetCore.Mvc.Testing. - Register contract interface in `ConfigureServices` - **Escape hatch**: For non-standard routes, implement `ConfigureEndpoints` on the module class 4. Create `src/modules//tests/.Tests/` with xUnit test project -5. Add `ProjectReference` to `src/SimpleModule.Api/SimpleModule.Api.csproj` +5. Add `ProjectReference` to `src/SimpleModule.Host/SimpleModule.Host.csproj` 6. Add all projects to `SimpleModule.slnx` ## Linting & Formatting diff --git a/SimpleModule.slnx b/SimpleModule.slnx index 9cc11ca7..aba15916 100644 --- a/SimpleModule.slnx +++ b/SimpleModule.slnx @@ -5,7 +5,7 @@ - + diff --git a/package-lock.json b/package-lock.json index 3f4f5815..0a9f9dd3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "src/modules/*/src/*", "src/SimpleModule.Client", "src/SimpleModule.Theme.Default", - "src/SimpleModule.Api/ClientApp" + "src/SimpleModule.Host/ClientApp" ], "devDependencies": { "@biomejs/biome": "^2.4.6", @@ -22,8 +22,6 @@ }, "node_modules/@babel/code-frame": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "license": "MIT", "dependencies": { @@ -37,8 +35,6 @@ }, "node_modules/@babel/compat-data": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "dev": true, "license": "MIT", "engines": { @@ -47,8 +43,6 @@ }, "node_modules/@babel/core": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", "peer": true, @@ -79,8 +73,6 @@ }, "node_modules/@babel/generator": { "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, "license": "MIT", "dependencies": { @@ -96,8 +88,6 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, "license": "MIT", "dependencies": { @@ -113,8 +103,6 @@ }, "node_modules/@babel/helper-globals": { "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, "license": "MIT", "engines": { @@ -123,8 +111,6 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, "license": "MIT", "dependencies": { @@ -137,8 +123,6 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, "license": "MIT", "dependencies": { @@ -155,8 +139,6 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true, "license": "MIT", "engines": { @@ -165,8 +147,6 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", "engines": { @@ -175,8 +155,6 @@ }, "node_modules/@babel/helper-validator-identifier": { "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, "license": "MIT", "engines": { @@ -185,8 +163,6 @@ }, "node_modules/@babel/helper-validator-option": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "license": "MIT", "engines": { @@ -195,8 +171,6 @@ }, "node_modules/@babel/helpers": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", "dev": true, "license": "MIT", "dependencies": { @@ -209,8 +183,6 @@ }, "node_modules/@babel/parser": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", "dev": true, "license": "MIT", "dependencies": { @@ -225,8 +197,6 @@ }, "node_modules/@babel/plugin-transform-react-jsx-self": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", "dev": true, "license": "MIT", "dependencies": { @@ -241,8 +211,6 @@ }, "node_modules/@babel/plugin-transform-react-jsx-source": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", "dev": true, "license": "MIT", "dependencies": { @@ -257,8 +225,6 @@ }, "node_modules/@babel/template": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, "license": "MIT", "dependencies": { @@ -272,8 +238,6 @@ }, "node_modules/@babel/traverse": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", "dev": true, "license": "MIT", "dependencies": { @@ -291,8 +255,6 @@ }, "node_modules/@babel/types": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "license": "MIT", "dependencies": { @@ -305,8 +267,6 @@ }, "node_modules/@biomejs/biome": { "version": "2.4.6", - "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.6.tgz", - "integrity": "sha512-QnHe81PMslpy3mnpL8DnO2M4S4ZnYPkjlGCLWBZT/3R9M6b5daArWMMtEfP52/n174RKnwRIf3oT8+wc9ihSfQ==", "dev": true, "license": "MIT OR Apache-2.0", "bin": { @@ -451,8 +411,6 @@ }, "node_modules/@biomejs/cli-win32-x64": { "version": "2.4.6", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.6.tgz", - "integrity": "sha512-7++XhnsPlr1HDbor5amovPjOH6vsrFOCdp93iKXhFn6bcMUI6soodj3WWKfgEO6JosKU1W5n3uky3WW9RlRjTg==", "cpu": [ "x64" ], @@ -868,8 +826,6 @@ }, "node_modules/@esbuild/win32-x64": { "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", "cpu": [ "x64" ], @@ -884,8 +840,6 @@ }, "node_modules/@inertiajs/core": { "version": "2.3.17", - "resolved": "https://registry.npmjs.org/@inertiajs/core/-/core-2.3.17.tgz", - "integrity": "sha512-CELuVhq2cBVrqxmrbRKqseuIQPBA6PcgDU7EPkPQxK02Lxxg7wTZWZZ5omaGBT+5mQtr0bkEUqUF2vxYbu4ogw==", "license": "MIT", "dependencies": { "@types/lodash-es": "^4.17.12", @@ -897,8 +851,6 @@ }, "node_modules/@inertiajs/react": { "version": "2.3.17", - "resolved": "https://registry.npmjs.org/@inertiajs/react/-/react-2.3.17.tgz", - "integrity": "sha512-TYCqRut0q2AuZb+BP/vbx50M0XYPoRvDOHBIcQGrDOkiAoHMZr2k260bcf8SfFPgZe1MxnMs6Ji+MdXcl55ckQ==", "license": "MIT", "peer": true, "dependencies": { @@ -914,8 +866,6 @@ }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", "dependencies": { @@ -925,8 +875,6 @@ }, "node_modules/@jridgewell/remapping": { "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", "dependencies": { @@ -936,8 +884,6 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", "engines": { @@ -946,15 +892,11 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -964,8 +906,6 @@ }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", - "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", "dev": true, "license": "MIT" }, @@ -1270,8 +1210,6 @@ }, "node_modules/@rollup/rollup-win32-x64-gnu": { "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", "cpu": [ "x64" ], @@ -1283,8 +1221,6 @@ }, "node_modules/@rollup/rollup-win32-x64-msvc": { "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", "cpu": [ "x64" ], @@ -1295,7 +1231,7 @@ ] }, "node_modules/@simplemodule/app": { - "resolved": "src/SimpleModule.Api/ClientApp", + "resolved": "src/SimpleModule.Host/ClientApp", "link": true }, "node_modules/@simplemodule/client": { @@ -1324,8 +1260,6 @@ }, "node_modules/@types/babel__core": { "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "license": "MIT", "dependencies": { @@ -1338,8 +1272,6 @@ }, "node_modules/@types/babel__generator": { "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, "license": "MIT", "dependencies": { @@ -1348,8 +1280,6 @@ }, "node_modules/@types/babel__template": { "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "license": "MIT", "dependencies": { @@ -1359,8 +1289,6 @@ }, "node_modules/@types/babel__traverse": { "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1369,20 +1297,14 @@ }, "node_modules/@types/estree": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, "node_modules/@types/lodash": { "version": "4.17.24", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", - "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", "license": "MIT" }, "node_modules/@types/lodash-es": { "version": "4.17.12", - "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", - "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", "license": "MIT", "dependencies": { "@types/lodash": "*" @@ -1390,8 +1312,6 @@ }, "node_modules/@types/node": { "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.4.0.tgz", - "integrity": "sha512-9wLpoeWuBlcbBpOY3XmzSTG3oscB6xjBEEtn+pYXTfhyXhIxC5FsBer2KTopBlvKEiW9l13po9fq+SJY/5lkhw==", "devOptional": true, "license": "MIT", "dependencies": { @@ -1400,8 +1320,6 @@ }, "node_modules/@types/qrcode": { "version": "1.5.6", - "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.6.tgz", - "integrity": "sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==", "dev": true, "license": "MIT", "dependencies": { @@ -1410,8 +1328,6 @@ }, "node_modules/@types/react": { "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "dev": true, "license": "MIT", "peer": true, @@ -1421,8 +1337,6 @@ }, "node_modules/@types/react-dom": { "version": "19.2.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -1431,8 +1345,6 @@ }, "node_modules/@vitejs/plugin-react": { "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", - "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", "dev": true, "license": "MIT", "dependencies": { @@ -1452,8 +1364,6 @@ }, "node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", "engines": { "node": ">=8" @@ -1461,8 +1371,6 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -1476,14 +1384,10 @@ }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, "node_modules/axios": { "version": "1.13.6", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", - "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.11", @@ -1493,8 +1397,6 @@ }, "node_modules/baseline-browser-mapping": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", - "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -1506,8 +1408,6 @@ }, "node_modules/browserslist": { "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -1541,8 +1441,6 @@ }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -1554,8 +1452,6 @@ }, "node_modules/call-bound": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -1570,8 +1466,6 @@ }, "node_modules/camelcase": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "license": "MIT", "engines": { "node": ">=6" @@ -1579,8 +1473,6 @@ }, "node_modules/caniuse-lite": { "version": "1.0.30001777", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz", - "integrity": "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==", "dev": true, "funding": [ { @@ -1600,8 +1492,6 @@ }, "node_modules/cliui": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -1611,8 +1501,6 @@ }, "node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -1623,14 +1511,10 @@ }, "node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -1641,22 +1525,16 @@ }, "node_modules/convert-source-map": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, "node_modules/csstype": { "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "dev": true, "license": "MIT" }, "node_modules/debug": { "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -1673,8 +1551,6 @@ }, "node_modules/decamelize": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -1682,8 +1558,6 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", "engines": { "node": ">=0.4.0" @@ -1691,14 +1565,10 @@ }, "node_modules/dijkstrajs": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", - "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", "license": "MIT" }, "node_modules/dunder-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -1711,21 +1581,15 @@ }, "node_modules/electron-to-chromium": { "version": "1.5.307", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", - "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", "dev": true, "license": "ISC" }, "node_modules/emoji-regex": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, "node_modules/es-define-property": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -1733,8 +1597,6 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -1742,8 +1604,6 @@ }, "node_modules/es-object-atoms": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -1754,8 +1614,6 @@ }, "node_modules/es-set-tostringtag": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -1769,8 +1627,6 @@ }, "node_modules/esbuild": { "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "hasInstallScript": true, "license": "MIT", "peer": true, @@ -1811,8 +1667,6 @@ }, "node_modules/escalade": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { @@ -1821,8 +1675,6 @@ }, "node_modules/fdir": { "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "license": "MIT", "engines": { "node": ">=12.0.0" @@ -1838,8 +1690,6 @@ }, "node_modules/find-up": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "license": "MIT", "dependencies": { "locate-path": "^5.0.0", @@ -1851,8 +1701,6 @@ }, "node_modules/follow-redirects": { "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "funding": [ { "type": "individual", @@ -1871,8 +1719,6 @@ }, "node_modules/form-data": { "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -1901,8 +1747,6 @@ }, "node_modules/function-bind": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1910,8 +1754,6 @@ }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "license": "MIT", "engines": { @@ -1920,8 +1762,6 @@ }, "node_modules/get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -1929,8 +1769,6 @@ }, "node_modules/get-intrinsic": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -1953,8 +1791,6 @@ }, "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -1966,8 +1802,6 @@ }, "node_modules/gopd": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -1978,8 +1812,6 @@ }, "node_modules/has-symbols": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -1990,8 +1822,6 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -2005,8 +1835,6 @@ }, "node_modules/hasown": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -2017,8 +1845,6 @@ }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", "engines": { "node": ">=8" @@ -2026,15 +1852,11 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, "license": "MIT" }, "node_modules/jsesc": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", "bin": { @@ -2046,8 +1868,6 @@ }, "node_modules/json5": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", "bin": { @@ -2059,8 +1879,6 @@ }, "node_modules/laravel-precognition": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/laravel-precognition/-/laravel-precognition-1.0.2.tgz", - "integrity": "sha512-0H08JDdMWONrL/N314fvsO3FATJwGGlFKGkMF3nNmizVFJaWs17816iM+sX7Rp8d5hUjYCx6WLfsehSKfaTxjg==", "license": "MIT", "dependencies": { "axios": "^1.4.0", @@ -2069,8 +1887,6 @@ }, "node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "license": "MIT", "dependencies": { "p-locate": "^4.1.0" @@ -2081,14 +1897,10 @@ }, "node_modules/lodash-es": { "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", - "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", "license": "MIT" }, "node_modules/lru-cache": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "license": "ISC", "dependencies": { @@ -2097,8 +1909,6 @@ }, "node_modules/math-intrinsics": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -2106,8 +1916,6 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -2115,8 +1923,6 @@ }, "node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -2127,15 +1933,11 @@ }, "node_modules/ms": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", @@ -2152,15 +1954,11 @@ }, "node_modules/node-releases": { "version": "2.0.36", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", - "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", "dev": true, "license": "MIT" }, "node_modules/object-inspect": { "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -2171,8 +1969,6 @@ }, "node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -2186,8 +1982,6 @@ }, "node_modules/p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "license": "MIT", "dependencies": { "p-limit": "^2.2.0" @@ -2198,8 +1992,6 @@ }, "node_modules/p-try": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "license": "MIT", "engines": { "node": ">=6" @@ -2207,8 +1999,6 @@ }, "node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "license": "MIT", "engines": { "node": ">=8" @@ -2216,14 +2006,10 @@ }, "node_modules/picocolors": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", "peer": true, "engines": { @@ -2235,8 +2021,6 @@ }, "node_modules/pngjs": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", - "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", "license": "MIT", "engines": { "node": ">=10.13.0" @@ -2244,8 +2028,6 @@ }, "node_modules/postcss": { "version": "8.5.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", - "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", "funding": [ { "type": "opencollective", @@ -2272,14 +2054,10 @@ }, "node_modules/proxy-from-env": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, "node_modules/qrcode": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", - "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", "license": "MIT", "dependencies": { "dijkstrajs": "^1.0.1", @@ -2295,8 +2073,6 @@ }, "node_modules/qs": { "version": "6.15.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", - "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -2310,8 +2086,6 @@ }, "node_modules/react": { "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", "peer": true, "engines": { @@ -2320,8 +2094,6 @@ }, "node_modules/react-dom": { "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", - "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", "peer": true, "dependencies": { @@ -2333,8 +2105,6 @@ }, "node_modules/react-refresh": { "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", "dev": true, "license": "MIT", "engines": { @@ -2343,8 +2113,6 @@ }, "node_modules/require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -2352,14 +2120,10 @@ }, "node_modules/require-main-filename": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "license": "ISC" }, "node_modules/rollup": { "version": "4.59.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", - "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -2402,14 +2166,10 @@ }, "node_modules/scheduler": { "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, "node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { @@ -2418,14 +2178,10 @@ }, "node_modules/set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "license": "ISC" }, "node_modules/side-channel": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -2443,8 +2199,6 @@ }, "node_modules/side-channel-list": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -2459,8 +2213,6 @@ }, "node_modules/side-channel-map": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -2477,8 +2229,6 @@ }, "node_modules/side-channel-weakmap": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -2496,8 +2246,6 @@ }, "node_modules/source-map-js": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -2505,8 +2253,6 @@ }, "node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -2519,8 +2265,6 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -2531,8 +2275,6 @@ }, "node_modules/tinyglobby": { "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -2547,8 +2289,6 @@ }, "node_modules/typescript": { "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2561,15 +2301,11 @@ }, "node_modules/undici-types": { "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", - "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", "devOptional": true, "license": "MIT" }, "node_modules/update-browserslist-db": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -2599,8 +2335,6 @@ }, "node_modules/vite": { "version": "6.4.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "license": "MIT", "peer": true, "dependencies": { @@ -2674,14 +2408,10 @@ }, "node_modules/which-module": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "license": "ISC" }, "node_modules/wrap-ansi": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -2694,21 +2424,15 @@ }, "node_modules/y18n": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "license": "ISC" }, "node_modules/yallist": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" }, "node_modules/yargs": { "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "license": "MIT", "dependencies": { "cliui": "^6.0.0", @@ -2729,8 +2453,6 @@ }, "node_modules/yargs-parser": { "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "license": "ISC", "dependencies": { "camelcase": "^5.0.0", @@ -2774,24 +2496,6 @@ "react-dom": "^19.0.0" } }, - "src/modules/Users/Users": { - "name": "@simplemodule/users", - "extraneous": true, - "dependencies": { - "qrcode": "^1.5.4" - }, - "devDependencies": { - "@types/qrcode": "^1.5.6" - } - }, - "src/SimpleModule.Api/ClientApp": { - "name": "@simplemodule/app", - "dependencies": { - "@inertiajs/react": "^2.0.0", - "react": "^19.0.0", - "react-dom": "^19.0.0" - } - }, "src/SimpleModule.Client": { "name": "@simplemodule/client", "peerDependencies": { @@ -2802,6 +2506,14 @@ "vite": "^6.0.0" } }, + "src/SimpleModule.Host/ClientApp": { + "name": "@simplemodule/app", + "dependencies": { + "@inertiajs/react": "^2.0.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + } + }, "src/SimpleModule.Theme.Default": { "name": "@simplemodule/theme-default" } diff --git a/package.json b/package.json index 3835cefa..d9a72a8e 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "src/modules/*/src/*", "src/SimpleModule.Client", "src/SimpleModule.Theme.Default", - "src/SimpleModule.Api/ClientApp" + "src/SimpleModule.Host/ClientApp" ], "scripts": { "lint": "biome lint ./src", diff --git a/src/SimpleModule.Cli/Commands/Doctor/Checks/ProjectReferenceCheck.cs b/src/SimpleModule.Cli/Commands/Doctor/Checks/ProjectReferenceCheck.cs index 7c2e64e5..18623469 100644 --- a/src/SimpleModule.Cli/Commands/Doctor/Checks/ProjectReferenceCheck.cs +++ b/src/SimpleModule.Cli/Commands/Doctor/Checks/ProjectReferenceCheck.cs @@ -11,7 +11,7 @@ public IEnumerable Run(SolutionContext solution) yield return new CheckResult( "API csproj", CheckStatus.Fail, - "SimpleModule.Api.csproj not found" + "SimpleModule.Host.csproj not found" ); yield break; } diff --git a/src/SimpleModule.Cli/Infrastructure/SolutionContext.cs b/src/SimpleModule.Cli/Infrastructure/SolutionContext.cs index d8d20422..f05ac4cf 100644 --- a/src/SimpleModule.Cli/Infrastructure/SolutionContext.cs +++ b/src/SimpleModule.Cli/Infrastructure/SolutionContext.cs @@ -16,8 +16,8 @@ private SolutionContext(string rootPath, string slnxPath) ApiCsprojPath = Path.Combine( rootPath, "src", - "SimpleModule.Api", - "SimpleModule.Api.csproj" + "SimpleModule.Host", + "SimpleModule.Host.csproj" ); ModulesPath = Path.Combine(rootPath, "src", "modules"); diff --git a/src/SimpleModule.Api/ClientApp/app.tsx b/src/SimpleModule.Host/ClientApp/app.tsx similarity index 100% rename from src/SimpleModule.Api/ClientApp/app.tsx rename to src/SimpleModule.Host/ClientApp/app.tsx diff --git a/src/SimpleModule.Api/ClientApp/package.json b/src/SimpleModule.Host/ClientApp/package.json similarity index 100% rename from src/SimpleModule.Api/ClientApp/package.json rename to src/SimpleModule.Host/ClientApp/package.json diff --git a/src/SimpleModule.Api/ClientApp/vite.config.ts b/src/SimpleModule.Host/ClientApp/vite.config.ts similarity index 100% rename from src/SimpleModule.Api/ClientApp/vite.config.ts rename to src/SimpleModule.Host/ClientApp/vite.config.ts diff --git a/src/SimpleModule.Api/Components/App.razor b/src/SimpleModule.Host/Components/App.razor similarity index 100% rename from src/SimpleModule.Api/Components/App.razor rename to src/SimpleModule.Host/Components/App.razor diff --git a/src/SimpleModule.Api/Components/InertiaShell.razor b/src/SimpleModule.Host/Components/InertiaShell.razor similarity index 100% rename from src/SimpleModule.Api/Components/InertiaShell.razor rename to src/SimpleModule.Host/Components/InertiaShell.razor diff --git a/src/SimpleModule.Api/Components/Layout/MainLayout.razor b/src/SimpleModule.Host/Components/Layout/MainLayout.razor similarity index 100% rename from src/SimpleModule.Api/Components/Layout/MainLayout.razor rename to src/SimpleModule.Host/Components/Layout/MainLayout.razor diff --git a/src/SimpleModule.Api/Components/Pages/OAuthCallback.razor b/src/SimpleModule.Host/Components/Pages/OAuthCallback.razor similarity index 100% rename from src/SimpleModule.Api/Components/Pages/OAuthCallback.razor rename to src/SimpleModule.Host/Components/Pages/OAuthCallback.razor diff --git a/src/SimpleModule.Api/Components/Routes.razor b/src/SimpleModule.Host/Components/Routes.razor similarity index 100% rename from src/SimpleModule.Api/Components/Routes.razor rename to src/SimpleModule.Host/Components/Routes.razor diff --git a/src/SimpleModule.Api/Components/_Imports.razor b/src/SimpleModule.Host/Components/_Imports.razor similarity index 72% rename from src/SimpleModule.Api/Components/_Imports.razor rename to src/SimpleModule.Host/Components/_Imports.razor index 2b240525..497b80c1 100644 --- a/src/SimpleModule.Api/Components/_Imports.razor +++ b/src/SimpleModule.Host/Components/_Imports.razor @@ -3,5 +3,5 @@ @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Authorization -@using SimpleModule.Api.Components -@using SimpleModule.Api.Components.Layout +@using SimpleModule.Host.Components +@using SimpleModule.Host.Components.Layout diff --git a/src/SimpleModule.Api/Program.cs b/src/SimpleModule.Host/Program.cs similarity index 99% rename from src/SimpleModule.Api/Program.cs rename to src/SimpleModule.Host/Program.cs index c0f9abbd..f60e9a8c 100644 --- a/src/SimpleModule.Api/Program.cs +++ b/src/SimpleModule.Host/Program.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Identity; using Microsoft.OpenApi; using OpenIddict.Validation.AspNetCore; -using SimpleModule.Api.Components; +using SimpleModule.Host.Components; using SimpleModule.Blazor; using SimpleModule.Core; using SimpleModule.Core.Constants; diff --git a/src/SimpleModule.Api/Properties/launchSettings.json b/src/SimpleModule.Host/Properties/launchSettings.json similarity index 91% rename from src/SimpleModule.Api/Properties/launchSettings.json rename to src/SimpleModule.Host/Properties/launchSettings.json index 8eeca313..c855ec9b 100644 --- a/src/SimpleModule.Api/Properties/launchSettings.json +++ b/src/SimpleModule.Host/Properties/launchSettings.json @@ -1,6 +1,6 @@ { "profiles": { - "SimpleModule.Api": { + "SimpleModule.Host": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": false, diff --git a/src/SimpleModule.Api/SimpleModule.Api.csproj b/src/SimpleModule.Host/SimpleModule.Host.csproj similarity index 100% rename from src/SimpleModule.Api/SimpleModule.Api.csproj rename to src/SimpleModule.Host/SimpleModule.Host.csproj diff --git a/src/SimpleModule.Api/Styles/app.css b/src/SimpleModule.Host/Styles/app.css similarity index 100% rename from src/SimpleModule.Api/Styles/app.css rename to src/SimpleModule.Host/Styles/app.css diff --git a/src/SimpleModule.Api/appsettings.json b/src/SimpleModule.Host/appsettings.json similarity index 100% rename from src/SimpleModule.Api/appsettings.json rename to src/SimpleModule.Host/appsettings.json diff --git a/src/SimpleModule.Api/wwwroot/css/.gitkeep b/src/SimpleModule.Host/wwwroot/css/.gitkeep similarity index 100% rename from src/SimpleModule.Api/wwwroot/css/.gitkeep rename to src/SimpleModule.Host/wwwroot/css/.gitkeep diff --git a/src/SimpleModule.Host/wwwroot/css/app.css b/src/SimpleModule.Host/wwwroot/css/app.css new file mode 100644 index 00000000..51fe4845 --- /dev/null +++ b/src/SimpleModule.Host/wwwroot/css/app.css @@ -0,0 +1,2 @@ +/*! tailwindcss v4.1.3 | MIT License | https://tailwindcss.com */ +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:rotateX(0);--tw-rotate-y:rotateY(0);--tw-rotate-z:rotateZ(0);--tw-skew-x:skewX(0);--tw-skew-y:skewY(0);--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-gray-200:oklch(92.8% .006 264.531);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-4xl:56rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height:calc(1.5/1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25/1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5/2.25);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--leading-relaxed:1.625;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--ease-out:cubic-bezier(0,0,.2,1);--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-primary:#0d9488;--color-primary-hover:#0f766e;--color-primary-subtle:#0d948814;--color-primary-ring:#0d948840;--color-accent:#059669;--color-success:#16a34a;--color-success-bg:#16a34a1a;--color-success-text:#15803d;--color-danger:#e11d48;--color-danger-hover:#be123c;--color-danger-bg:#e11d4814;--color-danger-text:#9f1239;--color-warning:#d97706;--color-warning-bg:#d9770614;--color-warning-border:#d9770633;--color-warning-text:#92400e;--color-info:#0ea5e9;--color-info-bg:#0ea5e914;--color-surface:#fff;--color-surface-raised:#f8fafc;--color-surface-sunken:#f1f5f9;--color-surface-overlay:#fffc;--color-text:#0f172a;--color-text-secondary:#475569;--color-text-muted:#94a3b8;--color-border:#e2e8f0;--color-border-strong:#cbd5e1;--color-code-bg:#1e293b;--color-code-text:#e2e8f0;--color-muted:#94a3b8}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html{scroll-behavior:smooth;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{background-color:var(--color-surface-sunken);color:var(--color-text);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.3s;font-family:DM Sans,system-ui,sans-serif;transition-duration:.3s}h1,h2,h3,h4,h5,h6{--tw-font-weight:var(--font-weight-bold);font-family:Sora,DM Sans,system-ui,sans-serif;font-weight:var(--font-weight-bold);--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight);color:var(--color-text);margin-top:0}h1{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}h2{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}h3{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}label{margin-bottom:calc(var(--spacing)*1.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);color:var(--color-text-secondary);display:block}input[type=email],input[type=password],input[type=text],input[type=tel]{border-radius:var(--radius-xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);width:100%;padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*3);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--color-text);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;transition-duration:.2s}:is(input[type=email],input[type=password],input[type=text],input[type=tel])::placeholder{color:var(--color-text-muted)}input[type=email]:focus,input[type=password]:focus,input[type=text]:focus,input[type=tel]:focus{border-color:var(--color-primary);--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(4px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);--tw-ring-color:var(--color-primary-ring);--tw-outline-style:none;outline-style:none}a{color:var(--color-primary);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;transition-duration:.15s}a:hover{color:var(--color-primary-hover)}hr{margin-block:calc(var(--spacing)*6);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--color-border)}::selection{background:#0d948833}table{width:100%;font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}table th{padding-bottom:calc(var(--spacing)*3);text-align:left;font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider);color:var(--color-text-muted);text-transform:uppercase}table td{border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--color-border);padding-block:calc(var(--spacing)*2.5);color:var(--color-text-secondary)}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background-color:var(--color-border-strong);border-radius:3.40282e38px}::-webkit-scrollbar-thumb:hover{background-color:var(--color-text-muted)}}@layer components{.glass-card{border-radius:var(--radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface-overlay);--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);-webkit-backdrop-filter:blur(20px)saturate(180%)}.dark .glass-card{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);box-shadow:0 0 0 1px #94a3b80d,0 25px 50px -12px #00000080}.btn-primary,.btn-secondary,.btn-ghost,.btn-danger,.btn-outline{cursor:pointer;justify-content:center;align-items:center;gap:calc(var(--spacing)*2);border-radius:var(--radius-xl);--tw-border-style:none;padding-inline:calc(var(--spacing)*5);padding-block:calc(var(--spacing)*2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;--tw-ease:var(--ease-out);transition-duration:.2s;transition-timing-function:var(--ease-out);border-style:none;text-decoration-line:none;display:inline-flex}.btn-primary:active,.btn-secondary:active,.btn-ghost:active,.btn-danger:active,.btn-outline:active{transform:scale(.97)}.btn-primary{color:var(--color-white);background:linear-gradient(135deg,var(--color-primary),var(--color-accent));box-shadow:0 4px 14px #0d948859}.btn-primary:hover{transform:translateY(-1px);box-shadow:0 6px 20px #0d948880}.btn-secondary{border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);color:var(--color-text)}.btn-secondary:hover{border-color:var(--color-border-strong);background-color:var(--color-surface-raised)}.btn-ghost{color:var(--color-text-secondary);background-color:#0000}.btn-ghost:hover{background-color:var(--color-primary-subtle);color:var(--color-primary)}.btn-danger{background-color:var(--color-danger);color:var(--color-white);box-shadow:0 4px 14px #e11d4840}.btn-danger:hover{background-color:var(--color-danger-hover);transform:translateY(-1px);box-shadow:0 6px 20px #e11d4866}.btn-outline{border-style:var(--tw-border-style);color:var(--color-primary);background-color:#0000;border-width:2px;border-color:#0d94884d}@supports (color:color-mix(in lab, red, red)){.btn-outline{border-color:color-mix(in oklab,var(--color-primary)30%,transparent)}}.btn-outline:hover{border-color:var(--color-primary);background-color:var(--color-primary-subtle)}.btn-sm{border-radius:var(--radius-lg);padding-inline:calc(var(--spacing)*3.5);padding-block:calc(var(--spacing)*1.5);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.btn-lg{padding-inline:calc(var(--spacing)*8);padding-block:calc(var(--spacing)*3.5);font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.form-group{margin-bottom:calc(var(--spacing)*5)}.badge-success,.badge-danger,.badge-warning,.badge-info{padding-inline:calc(var(--spacing)*2.5);padding-block:calc(var(--spacing)*1);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);border-radius:3.40282e38px;align-items:center;display:inline-flex}.badge-success{background-color:var(--color-success-bg);color:var(--color-success-text)}.badge-danger{background-color:var(--color-danger-bg);color:var(--color-danger-text)}.badge-warning{background-color:var(--color-warning-bg);color:var(--color-warning-text)}.badge-info{background-color:var(--color-info-bg);color:var(--color-primary)}.alert-success,.alert-danger,.alert-warning,.alert-info{border-radius:var(--radius-xl);border-style:var(--tw-border-style);padding:calc(var(--spacing)*4);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));border-width:1px}.alert-success{background-color:var(--color-success-bg);color:var(--color-success-text);border-color:#16a34a33}@supports (color:color-mix(in lab, red, red)){.alert-success{border-color:color-mix(in oklab,var(--color-success)20%,transparent)}}.alert-danger{background-color:var(--color-danger-bg);color:var(--color-danger-text);border-color:#e11d4833}@supports (color:color-mix(in lab, red, red)){.alert-danger{border-color:color-mix(in oklab,var(--color-danger)20%,transparent)}}.alert-warning{border-color:var(--color-warning-border);background-color:var(--color-warning-bg);color:var(--color-warning-text)}.alert-info{background-color:var(--color-info-bg);color:var(--color-primary);border-color:#0ea5e933}@supports (color:color-mix(in lab, red, red)){.alert-info{border-color:color-mix(in oklab,var(--color-info)20%,transparent)}}.code-block{border-radius:var(--radius-xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-code-bg);padding:calc(var(--spacing)*4);font-family:var(--font-mono);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));color:var(--color-code-text);font-family:JetBrains Mono,Fira Code,monospace;overflow:auto}.panel{margin-bottom:calc(var(--spacing)*8)}.panel-title{margin-bottom:calc(var(--spacing)*4);align-items:center;gap:calc(var(--spacing)*2);padding-bottom:calc(var(--spacing)*3);font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height));--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold);font-family:Sora,system-ui,sans-serif;display:flex}.panel-title:before{content:"";height:calc(var(--spacing)*5);width:calc(var(--spacing)*1);background:linear-gradient(180deg,var(--color-primary),var(--color-accent));border-radius:3.40282e38px}.card{border-radius:var(--radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);padding:calc(var(--spacing)*5);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;transition-duration:.2s}.card:hover{border-color:var(--color-border-strong)}.nav-link-active,.nav-link-inactive{border-radius:var(--radius-xl);padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*2.5);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;text-decoration-line:none;transition-duration:.15s;display:block}.nav-link-active{background-color:var(--color-primary-subtle);--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);color:var(--color-primary)}.nav-link-inactive{color:var(--color-text-secondary)}.nav-link-inactive:hover{background-color:var(--color-surface-raised);color:var(--color-text)}.bg-mesh{z-index:-1;background:var(--color-surface-sunken);position:fixed;inset:0;overflow:hidden}.bg-mesh:before,.bg-mesh:after{content:"";filter:blur(100px);opacity:.15;border-radius:50%;animation:20s ease-in-out infinite mesh-float;position:absolute}.bg-mesh:before{background:var(--color-primary);width:600px;height:600px;top:-10%;right:-10%}.bg-mesh:after{background:var(--color-accent);width:500px;height:500px;animation-direction:reverse;animation-delay:-10s;bottom:-10%;left:-10%}.dark .bg-mesh:before,.dark .bg-mesh:after{opacity:.08}@keyframes mesh-float{0%,to{transform:translate(0)scale(1)}33%{transform:translate(40px,-30px)scale(1.05)}66%{transform:translate(-20px,20px)scale(.95)}}.spinner{margin-left:calc(var(--spacing)*2);height:calc(var(--spacing)*4);width:calc(var(--spacing)*4);animation:var(--animate-spin);border-style:var(--tw-border-style);border-width:2px;border-color:var(--color-border);border-top-color:var(--color-primary);vertical-align:middle;border-radius:3.40282e38px;display:inline-block}.user-dropdown-wrap{position:relative}.user-dropdown-trigger{cursor:pointer;align-items:center;gap:calc(var(--spacing)*2);border-radius:var(--radius-xl);--tw-border-style:none;padding-inline:calc(var(--spacing)*2);padding-block:calc(var(--spacing)*1.5);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;background-color:#0000;border-style:none;transition-duration:.2s;display:flex}.user-dropdown-trigger:hover,.user-dropdown-trigger[aria-expanded=true]{background-color:var(--color-surface-raised)}.user-dropdown{border-radius:var(--radius-xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);width:240px;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);opacity:0;pointer-events:none;z-index:100;transition:opacity .18s,transform .18s;position:absolute;top:calc(100% + 6px);right:0;transform:translateY(-4px)scale(.97)}.user-dropdown.open{opacity:1;pointer-events:auto;transform:translateY(0)scale(1)}.dark .user-dropdown{box-shadow:0 0 0 1px #94a3b80f,0 20px 40px -8px #0009}.user-dropdown-header{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--color-border);padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*3)}.user-dropdown-body{padding-block:calc(var(--spacing)*1.5)}.user-dropdown-item{cursor:pointer;align-items:center;gap:calc(var(--spacing)*2.5);padding-inline:calc(var(--spacing)*4);padding-block:calc(var(--spacing)*2);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height));color:var(--color-text-secondary);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.15s;text-decoration-line:none;transition-duration:.15s;display:flex}.user-dropdown-item:hover{background-color:var(--color-surface-raised);color:var(--color-text)}.user-dropdown-divider{margin-block:calc(var(--spacing)*1.5);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:var(--color-border)}.user-dropdown-item.danger{color:var(--color-danger)}.user-dropdown-item.danger:hover{background-color:var(--color-danger-bg);color:var(--color-danger)}.dash-card{border-radius:var(--radius-2xl);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-border);background-color:var(--color-surface);padding:calc(var(--spacing)*5);transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration));--tw-duration:.2s;transition-duration:.2s}.dash-card:hover{border-color:var(--color-border-strong);--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dash-stat{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height));--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold);--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight);font-family:Sora,system-ui,sans-serif}.dash-label{margin-top:calc(var(--spacing)*1);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider);color:var(--color-text-muted);text-transform:uppercase}.validation-message{margin-top:calc(var(--spacing)*1.5);font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium);color:var(--color-danger)}}@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.top-0{top:calc(var(--spacing)*0)}.top-1\/2{top:50%}.left-1\/2{left:50%}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:calc(var(--spacing)*0)}.mx-auto{margin-inline:auto}.my-4{margin-block:calc(var(--spacing)*4)}.my-6{margin-block:calc(var(--spacing)*6)}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-6{margin-top:calc(var(--spacing)*6)}.mt-8{margin-top:calc(var(--spacing)*8)}.mb-0{margin-bottom:calc(var(--spacing)*0)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-5{margin-bottom:calc(var(--spacing)*5)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.mb-16{margin-bottom:calc(var(--spacing)*16)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-2{margin-left:calc(var(--spacing)*2)}.ml-4{margin-left:calc(var(--spacing)*4)}.ml-7{margin-left:calc(var(--spacing)*7)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.table{display:table}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-12{height:calc(var(--spacing)*12)}.h-14{height:calc(var(--spacing)*14)}.h-16{height:calc(var(--spacing)*16)}.h-\[18px\]{height:18px}.max-h-30{max-height:calc(var(--spacing)*30)}.max-h-50{max-height:calc(var(--spacing)*50)}.min-h-\[calc\(100vh-12rem\)\]{min-height:calc(100vh - 12rem)}.min-h-\[calc\(100vh-16rem\)\]{min-height:calc(100vh - 16rem)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-12{width:calc(var(--spacing)*12)}.w-14{width:calc(var(--spacing)*14)}.w-16{width:calc(var(--spacing)*16)}.w-\[18px\]{width:18px}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\[140px\]{max-width:140px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x)var(--tw-rotate-y)var(--tw-rotate-z)var(--tw-skew-x)var(--tw-skew-y)}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-decimal{list-style-type:decimal}.list-none{list-style-type:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-5{gap:calc(var(--spacing)*5)}.gap-6{gap:calc(var(--spacing)*6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-x-auto{overflow-x:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-none{--tw-border-style:none;border-style:none}.border-border{border-color:var(--color-border)}.border-gray-200{border-color:var(--color-gray-200)}.bg-info-bg{background-color:var(--color-info-bg)}.bg-primary-subtle{background-color:var(--color-primary-subtle)}.bg-success-bg{background-color:var(--color-success-bg)}.bg-surface{background-color:var(--color-surface)}.bg-surface-overlay{background-color:var(--color-surface-overlay)}.bg-surface-raised{background-color:var(--color-surface-raised)}.bg-transparent{background-color:#0000}.bg-warning-bg{background-color:var(--color-warning-bg)}.p-0{padding:calc(var(--spacing)*0)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-5{padding:calc(var(--spacing)*5)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-3{padding-block:calc(var(--spacing)*3)}.py-8{padding-block:calc(var(--spacing)*8)}.pt-2{padding-top:calc(var(--spacing)*2)}.pt-3{padding-top:calc(var(--spacing)*3)}.pl-5{padding-left:calc(var(--spacing)*5)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-all{word-break:break-all}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent{color:var(--color-accent)}.text-border{color:var(--color-border)}.text-danger{color:var(--color-danger)}.text-gray-600{color:var(--color-gray-600)}.text-info{color:var(--color-info)}.text-muted{color:var(--color-muted)}.text-primary{color:var(--color-primary)}.text-success{color:var(--color-success)}.text-text{color:var(--color-text)}.text-text-muted{color:var(--color-text-muted)}.text-text-secondary{color:var(--color-text-secondary)}.text-warning{color:var(--color-warning)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.no-underline{text-decoration-line:none}.accent-primary{accent-color:var(--color-primary)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}@media (hover:hover){.group-hover\:scale-105:is(:where(.group):hover *){--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x)var(--tw-scale-y)}.group-hover\:text-primary:is(:where(.group):hover *){color:var(--color-primary)}}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:bg-surface-raised:hover{background-color:var(--color-surface-raised)}.hover\:text-danger-hover:hover{color:var(--color-danger-hover)}.hover\:text-primary:hover{color:var(--color-primary)}.hover\:text-primary-hover:hover{color:var(--color-primary-hover)}.hover\:text-text:hover{color:var(--color-text)}.hover\:underline:hover{text-decoration-line:underline}}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width:40rem){.sm\:sticky{position:sticky}.sm\:top-20{top:calc(var(--spacing)*20)}.sm\:block{display:block}.sm\:flex{display:flex}.sm\:inline-flex{display:inline-flex}.sm\:w-56{width:calc(var(--spacing)*56)}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:p-8{padding:calc(var(--spacing)*8)}.sm\:px-6{padding-inline:calc(var(--spacing)*6)}}@media (min-width:64rem){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (prefers-color-scheme:dark){.dark\:block{display:block}.dark\:hidden{display:none}.dark\:border-gray-700{border-color:var(--color-gray-700)}.dark\:text-gray-400{color:var(--color-gray-400)}}.gradient-text{background:linear-gradient(135deg,var(--color-primary),var(--color-accent));-webkit-text-fill-color:transparent;-webkit-background-clip:text;background-clip:text}.gradient-border{position:relative}.gradient-border:before{content:"";border-radius:inherit;background:linear-gradient(135deg,var(--color-primary),var(--color-accent));-webkit-mask-composite:xor;pointer-events:none;-webkit-mask-composite:xor;-webkit-mask-source-type:auto,auto;padding:1px;position:absolute;inset:0;-webkit-mask-image:linear-gradient(#fff 0 0),linear-gradient(#fff 0 0);mask-image:linear-gradient(#fff 0 0),linear-gradient(#fff 0 0);-webkit-mask-position:0 0,0 0;mask-position:0 0,0 0;-webkit-mask-size:auto,auto;mask-size:auto,auto;-webkit-mask-repeat:repeat,repeat;mask-repeat:repeat,repeat;-webkit-mask-clip:content-box,border-box;mask-clip:content-box,border-box;-webkit-mask-origin:content-box,border-box;mask-origin:content-box,border-box;-webkit-mask-composite:xor;mask-composite:exclude;-webkit-mask-source-type:auto,auto;mask-mode:match-source,match-source}}.dark{--color-primary-subtle:#0d948826;--color-primary-ring:#0d948859;--color-success-bg:#4ade801f;--color-success-text:#86efac;--color-danger-bg:#e11d481f;--color-danger-text:#fda4af;--color-warning-bg:#d977061f;--color-warning-border:#d977064d;--color-warning-text:#fcd34d;--color-info-bg:#0ea5e91f;--color-surface:#0f172a;--color-surface-raised:#1e293b;--color-surface-sunken:#0b1120;--color-surface-overlay:#0f172ad9;--color-text:#f1f5f9;--color-text-secondary:#94a3b8;--color-text-muted:#64748b;--color-text-inverse:#0f172a;--color-border:#1e293b;--color-border-strong:#334155;--color-code-bg:#020617;--color-code-text:#e2e8f0}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false;initial-value:rotateX(0)}@property --tw-rotate-y{syntax:"*";inherits:false;initial-value:rotateY(0)}@property --tw-rotate-z{syntax:"*";inherits:false;initial-value:rotateZ(0)}@property --tw-skew-x{syntax:"*";inherits:false;initial-value:skewX(0)}@property --tw-skew-y{syntax:"*";inherits:false;initial-value:skewY(0)}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}} \ No newline at end of file diff --git a/src/SimpleModule.Host/wwwroot/js/app.js b/src/SimpleModule.Host/wwwroot/js/app.js new file mode 100644 index 00000000..e77a7a3f --- /dev/null +++ b/src/SimpleModule.Host/wwwroot/js/app.js @@ -0,0 +1 @@ +import{jsx as v}from"/js/vendor/react-jsx-runtime.js";import{createInertiaApp as E}from"/js/vendor/inertiajs-react.js";import{createRoot as g}from"/js/vendor/react-dom-client.js";const P="modulepreload",y=function(n){return"/"+n},f={},_=function(o,s,a){let u=Promise.resolve();if(s&&s.length>0){let i=function(t){return Promise.all(t.map(l=>Promise.resolve(l).then(c=>({status:"fulfilled",value:c}),c=>({status:"rejected",reason:c}))))};document.getElementsByTagName("link");const e=document.querySelector("meta[property=csp-nonce]"),m=(e==null?void 0:e.nonce)||(e==null?void 0:e.getAttribute("nonce"));u=i(s.map(t=>{if(t=y(t),t in f)return;f[t]=!0;const l=t.endsWith(".css"),c=l?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${t}"]${c}`))return;const r=document.createElement("link");if(r.rel=l?"stylesheet":P,l||(r.as="script"),r.crossOrigin="",r.href=t,m&&r.setAttribute("nonce",m),document.head.appendChild(r),l)return new Promise((p,h)=>{r.addEventListener("load",p),r.addEventListener("error",()=>h(new Error(`Unable to preload CSS for ${t}`)))})}))}function d(i){const e=new Event("vite:preloadError",{cancelable:!0});if(e.payload=i,window.dispatchEvent(e),!e.defaultPrevented)throw i}return u.then(i=>{for(const e of i||[])e.status==="rejected"&&d(e.reason);return o().catch(d)})};async function w(n){const o=n.split("/")[0],a=(await _(()=>import(`/_content/${o}/${o}.pages.js`),[])).pages[n];return a.default?a:{default:a}}E({resolve:w,setup({el:n,App:o,props:s}){g(n).render(v(o,{...s}))}}); diff --git a/src/SimpleModule.Api/wwwroot/js/shell.js b/src/SimpleModule.Host/wwwroot/js/shell.js similarity index 100% rename from src/SimpleModule.Api/wwwroot/js/shell.js rename to src/SimpleModule.Host/wwwroot/js/shell.js diff --git a/src/SimpleModule.Host/wwwroot/js/vendor/inertiajs-react.js b/src/SimpleModule.Host/wwwroot/js/vendor/inertiajs-react.js new file mode 100644 index 00000000..e9c67700 --- /dev/null +++ b/src/SimpleModule.Host/wwwroot/js/vendor/inertiajs-react.js @@ -0,0 +1,13377 @@ +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var __export = (target, all3) => { + for (var name in all3) + __defProp(target, name, { get: all3[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); + +// ../../../node_modules/es-errors/type.js +var require_type = __commonJS({ + "../../../node_modules/es-errors/type.js"(exports2, module2) { + "use strict"; + module2.exports = TypeError; + } +}); + +// (disabled):../../../node_modules/object-inspect/util.inspect +var require_util = __commonJS({ + "(disabled):../../../node_modules/object-inspect/util.inspect"() { + } +}); + +// ../../../node_modules/object-inspect/index.js +var require_object_inspect = __commonJS({ + "../../../node_modules/object-inspect/index.js"(exports2, module2) { + var hasMap = typeof Map === "function" && Map.prototype; + var mapSizeDescriptor = Object.getOwnPropertyDescriptor && hasMap ? Object.getOwnPropertyDescriptor(Map.prototype, "size") : null; + var mapSize = hasMap && mapSizeDescriptor && typeof mapSizeDescriptor.get === "function" ? mapSizeDescriptor.get : null; + var mapForEach = hasMap && Map.prototype.forEach; + var hasSet = typeof Set === "function" && Set.prototype; + var setSizeDescriptor = Object.getOwnPropertyDescriptor && hasSet ? Object.getOwnPropertyDescriptor(Set.prototype, "size") : null; + var setSize = hasSet && setSizeDescriptor && typeof setSizeDescriptor.get === "function" ? setSizeDescriptor.get : null; + var setForEach = hasSet && Set.prototype.forEach; + var hasWeakMap = typeof WeakMap === "function" && WeakMap.prototype; + var weakMapHas = hasWeakMap ? WeakMap.prototype.has : null; + var hasWeakSet = typeof WeakSet === "function" && WeakSet.prototype; + var weakSetHas = hasWeakSet ? WeakSet.prototype.has : null; + var hasWeakRef = typeof WeakRef === "function" && WeakRef.prototype; + var weakRefDeref = hasWeakRef ? WeakRef.prototype.deref : null; + var booleanValueOf = Boolean.prototype.valueOf; + var objectToString2 = Object.prototype.toString; + var functionToString = Function.prototype.toString; + var $match = String.prototype.match; + var $slice = String.prototype.slice; + var $replace = String.prototype.replace; + var $toUpperCase = String.prototype.toUpperCase; + var $toLowerCase = String.prototype.toLowerCase; + var $test = RegExp.prototype.test; + var $concat = Array.prototype.concat; + var $join = Array.prototype.join; + var $arrSlice = Array.prototype.slice; + var $floor = Math.floor; + var bigIntValueOf = typeof BigInt === "function" ? BigInt.prototype.valueOf : null; + var gOPS = Object.getOwnPropertySymbols; + var symToString = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? Symbol.prototype.toString : null; + var hasShammedSymbols = typeof Symbol === "function" && typeof Symbol.iterator === "object"; + var toStringTag2 = typeof Symbol === "function" && Symbol.toStringTag && (typeof Symbol.toStringTag === hasShammedSymbols ? "object" : "symbol") ? Symbol.toStringTag : null; + var isEnumerable = Object.prototype.propertyIsEnumerable; + var gPO = (typeof Reflect === "function" ? Reflect.getPrototypeOf : Object.getPrototypeOf) || ([].__proto__ === Array.prototype ? function(O) { + return O.__proto__; + } : null); + function addNumericSeparator(num, str) { + if (num === Infinity || num === -Infinity || num !== num || num && num > -1e3 && num < 1e3 || $test.call(/e/, str)) { + return str; + } + var sepRegex = /[0-9](?=(?:[0-9]{3})+(?![0-9]))/g; + if (typeof num === "number") { + var int = num < 0 ? -$floor(-num) : $floor(num); + if (int !== num) { + var intStr = String(int); + var dec = $slice.call(str, intStr.length + 1); + return $replace.call(intStr, sepRegex, "$&_") + "." + $replace.call($replace.call(dec, /([0-9]{3})/g, "$&_"), /_$/, ""); + } + } + return $replace.call(str, sepRegex, "$&_"); + } + var utilInspect = require_util(); + var inspectCustom = utilInspect.custom; + var inspectSymbol = isSymbol2(inspectCustom) ? inspectCustom : null; + var quotes = { + __proto__: null, + "double": '"', + single: "'" + }; + var quoteREs = { + __proto__: null, + "double": /(["\\])/g, + single: /(['\\])/g + }; + module2.exports = function inspect_(obj, options, depth, seen) { + var opts = options || {}; + if (has2(opts, "quoteStyle") && !has2(quotes, opts.quoteStyle)) { + throw new TypeError('option "quoteStyle" must be "single" or "double"'); + } + if (has2(opts, "maxStringLength") && (typeof opts.maxStringLength === "number" ? opts.maxStringLength < 0 && opts.maxStringLength !== Infinity : opts.maxStringLength !== null)) { + throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`'); + } + var customInspect = has2(opts, "customInspect") ? opts.customInspect : true; + if (typeof customInspect !== "boolean" && customInspect !== "symbol") { + throw new TypeError("option \"customInspect\", if provided, must be `true`, `false`, or `'symbol'`"); + } + if (has2(opts, "indent") && opts.indent !== null && opts.indent !== " " && !(parseInt(opts.indent, 10) === opts.indent && opts.indent > 0)) { + throw new TypeError('option "indent" must be "\\t", an integer > 0, or `null`'); + } + if (has2(opts, "numericSeparator") && typeof opts.numericSeparator !== "boolean") { + throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`'); + } + var numericSeparator = opts.numericSeparator; + if (typeof obj === "undefined") { + return "undefined"; + } + if (obj === null) { + return "null"; + } + if (typeof obj === "boolean") { + return obj ? "true" : "false"; + } + if (typeof obj === "string") { + return inspectString(obj, opts); + } + if (typeof obj === "number") { + if (obj === 0) { + return Infinity / obj > 0 ? "0" : "-0"; + } + var str = String(obj); + return numericSeparator ? addNumericSeparator(obj, str) : str; + } + if (typeof obj === "bigint") { + var bigIntStr = String(obj) + "n"; + return numericSeparator ? addNumericSeparator(obj, bigIntStr) : bigIntStr; + } + var maxDepth = typeof opts.depth === "undefined" ? 5 : opts.depth; + if (typeof depth === "undefined") { + depth = 0; + } + if (depth >= maxDepth && maxDepth > 0 && typeof obj === "object") { + return isArray3(obj) ? "[Array]" : "[Object]"; + } + var indent = getIndent(opts, depth); + if (typeof seen === "undefined") { + seen = []; + } else if (indexOf(seen, obj) >= 0) { + return "[Circular]"; + } + function inspect(value, from, noIndent) { + if (from) { + seen = $arrSlice.call(seen); + seen.push(from); + } + if (noIndent) { + var newOpts = { + depth: opts.depth + }; + if (has2(opts, "quoteStyle")) { + newOpts.quoteStyle = opts.quoteStyle; + } + return inspect_(value, newOpts, depth + 1, seen); + } + return inspect_(value, opts, depth + 1, seen); + } + if (typeof obj === "function" && !isRegExp2(obj)) { + var name = nameOf(obj); + var keys2 = arrObjKeys(obj, inspect); + return "[Function" + (name ? ": " + name : " (anonymous)") + "]" + (keys2.length > 0 ? " { " + $join.call(keys2, ", ") + " }" : ""); + } + if (isSymbol2(obj)) { + var symString = hasShammedSymbols ? $replace.call(String(obj), /^(Symbol\(.*\))_[^)]*$/, "$1") : symToString.call(obj); + return typeof obj === "object" && !hasShammedSymbols ? markBoxed(symString) : symString; + } + if (isElement(obj)) { + var s = "<" + $toLowerCase.call(String(obj.nodeName)); + var attrs = obj.attributes || []; + for (var i = 0; i < attrs.length; i++) { + s += " " + attrs[i].name + "=" + wrapQuotes(quote(attrs[i].value), "double", opts); + } + s += ">"; + if (obj.childNodes && obj.childNodes.length) { + s += "..."; + } + s += ""; + return s; + } + if (isArray3(obj)) { + if (obj.length === 0) { + return "[]"; + } + var xs = arrObjKeys(obj, inspect); + if (indent && !singleLineValues(xs)) { + return "[" + indentedJoin(xs, indent) + "]"; + } + return "[ " + $join.call(xs, ", ") + " ]"; + } + if (isError(obj)) { + var parts = arrObjKeys(obj, inspect); + if (!("cause" in Error.prototype) && "cause" in obj && !isEnumerable.call(obj, "cause")) { + return "{ [" + String(obj) + "] " + $join.call($concat.call("[cause]: " + inspect(obj.cause), parts), ", ") + " }"; + } + if (parts.length === 0) { + return "[" + String(obj) + "]"; + } + return "{ [" + String(obj) + "] " + $join.call(parts, ", ") + " }"; + } + if (typeof obj === "object" && customInspect) { + if (inspectSymbol && typeof obj[inspectSymbol] === "function" && utilInspect) { + return utilInspect(obj, { depth: maxDepth - depth }); + } else if (customInspect !== "symbol" && typeof obj.inspect === "function") { + return obj.inspect(); + } + } + if (isMap2(obj)) { + var mapParts = []; + if (mapForEach) { + mapForEach.call(obj, function(value, key) { + mapParts.push(inspect(key, obj, true) + " => " + inspect(value, obj)); + }); + } + return collectionOf("Map", mapSize.call(obj), mapParts, indent); + } + if (isSet2(obj)) { + var setParts = []; + if (setForEach) { + setForEach.call(obj, function(value) { + setParts.push(inspect(value, obj)); + }); + } + return collectionOf("Set", setSize.call(obj), setParts, indent); + } + if (isWeakMap(obj)) { + return weakCollectionOf("WeakMap"); + } + if (isWeakSet(obj)) { + return weakCollectionOf("WeakSet"); + } + if (isWeakRef(obj)) { + return weakCollectionOf("WeakRef"); + } + if (isNumber2(obj)) { + return markBoxed(inspect(Number(obj))); + } + if (isBigInt(obj)) { + return markBoxed(inspect(bigIntValueOf.call(obj))); + } + if (isBoolean2(obj)) { + return markBoxed(booleanValueOf.call(obj)); + } + if (isString2(obj)) { + return markBoxed(inspect(String(obj))); + } + if (typeof window !== "undefined" && obj === window) { + return "{ [object Window] }"; + } + if (typeof globalThis !== "undefined" && obj === globalThis || typeof global !== "undefined" && obj === global) { + return "{ [object globalThis] }"; + } + if (!isDate2(obj) && !isRegExp2(obj)) { + var ys = arrObjKeys(obj, inspect); + var isPlainObject3 = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object; + var protoTag = obj instanceof Object ? "" : "null prototype"; + var stringTag5 = !isPlainObject3 && toStringTag2 && Object(obj) === obj && toStringTag2 in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? "Object" : ""; + var constructorTag = isPlainObject3 || typeof obj.constructor !== "function" ? "" : obj.constructor.name ? obj.constructor.name + " " : ""; + var tag = constructorTag + (stringTag5 || protoTag ? "[" + $join.call($concat.call([], stringTag5 || [], protoTag || []), ": ") + "] " : ""); + if (ys.length === 0) { + return tag + "{}"; + } + if (indent) { + return tag + "{" + indentedJoin(ys, indent) + "}"; + } + return tag + "{ " + $join.call(ys, ", ") + " }"; + } + return String(obj); + }; + function wrapQuotes(s, defaultStyle, opts) { + var style = opts.quoteStyle || defaultStyle; + var quoteChar = quotes[style]; + return quoteChar + s + quoteChar; + } + function quote(s) { + return $replace.call(String(s), /"/g, """); + } + function canTrustToString(obj) { + return !toStringTag2 || !(typeof obj === "object" && (toStringTag2 in obj || typeof obj[toStringTag2] !== "undefined")); + } + function isArray3(obj) { + return toStr(obj) === "[object Array]" && canTrustToString(obj); + } + function isDate2(obj) { + return toStr(obj) === "[object Date]" && canTrustToString(obj); + } + function isRegExp2(obj) { + return toStr(obj) === "[object RegExp]" && canTrustToString(obj); + } + function isError(obj) { + return toStr(obj) === "[object Error]" && canTrustToString(obj); + } + function isString2(obj) { + return toStr(obj) === "[object String]" && canTrustToString(obj); + } + function isNumber2(obj) { + return toStr(obj) === "[object Number]" && canTrustToString(obj); + } + function isBoolean2(obj) { + return toStr(obj) === "[object Boolean]" && canTrustToString(obj); + } + function isSymbol2(obj) { + if (hasShammedSymbols) { + return obj && typeof obj === "object" && obj instanceof Symbol; + } + if (typeof obj === "symbol") { + return true; + } + if (!obj || typeof obj !== "object" || !symToString) { + return false; + } + try { + symToString.call(obj); + return true; + } catch (e) { + } + return false; + } + function isBigInt(obj) { + if (!obj || typeof obj !== "object" || !bigIntValueOf) { + return false; + } + try { + bigIntValueOf.call(obj); + return true; + } catch (e) { + } + return false; + } + var hasOwn = Object.prototype.hasOwnProperty || function(key) { + return key in this; + }; + function has2(obj, key) { + return hasOwn.call(obj, key); + } + function toStr(obj) { + return objectToString2.call(obj); + } + function nameOf(f) { + if (f.name) { + return f.name; + } + var m = $match.call(functionToString.call(f), /^function\s*([\w$]+)/); + if (m) { + return m[1]; + } + return null; + } + function indexOf(xs, x) { + if (xs.indexOf) { + return xs.indexOf(x); + } + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) { + return i; + } + } + return -1; + } + function isMap2(x) { + if (!mapSize || !x || typeof x !== "object") { + return false; + } + try { + mapSize.call(x); + try { + setSize.call(x); + } catch (s) { + return true; + } + return x instanceof Map; + } catch (e) { + } + return false; + } + function isWeakMap(x) { + if (!weakMapHas || !x || typeof x !== "object") { + return false; + } + try { + weakMapHas.call(x, weakMapHas); + try { + weakSetHas.call(x, weakSetHas); + } catch (s) { + return true; + } + return x instanceof WeakMap; + } catch (e) { + } + return false; + } + function isWeakRef(x) { + if (!weakRefDeref || !x || typeof x !== "object") { + return false; + } + try { + weakRefDeref.call(x); + return true; + } catch (e) { + } + return false; + } + function isSet2(x) { + if (!setSize || !x || typeof x !== "object") { + return false; + } + try { + setSize.call(x); + try { + mapSize.call(x); + } catch (m) { + return true; + } + return x instanceof Set; + } catch (e) { + } + return false; + } + function isWeakSet(x) { + if (!weakSetHas || !x || typeof x !== "object") { + return false; + } + try { + weakSetHas.call(x, weakSetHas); + try { + weakMapHas.call(x, weakMapHas); + } catch (s) { + return true; + } + return x instanceof WeakSet; + } catch (e) { + } + return false; + } + function isElement(x) { + if (!x || typeof x !== "object") { + return false; + } + if (typeof HTMLElement !== "undefined" && x instanceof HTMLElement) { + return true; + } + return typeof x.nodeName === "string" && typeof x.getAttribute === "function"; + } + function inspectString(str, opts) { + if (str.length > opts.maxStringLength) { + var remaining = str.length - opts.maxStringLength; + var trailer = "... " + remaining + " more character" + (remaining > 1 ? "s" : ""); + return inspectString($slice.call(str, 0, opts.maxStringLength), opts) + trailer; + } + var quoteRE = quoteREs[opts.quoteStyle || "single"]; + quoteRE.lastIndex = 0; + var s = $replace.call($replace.call(str, quoteRE, "\\$1"), /[\x00-\x1f]/g, lowbyte); + return wrapQuotes(s, "single", opts); + } + function lowbyte(c) { + var n = c.charCodeAt(0); + var x = { + 8: "b", + 9: "t", + 10: "n", + 12: "f", + 13: "r" + }[n]; + if (x) { + return "\\" + x; + } + return "\\x" + (n < 16 ? "0" : "") + $toUpperCase.call(n.toString(16)); + } + function markBoxed(str) { + return "Object(" + str + ")"; + } + function weakCollectionOf(type) { + return type + " { ? }"; + } + function collectionOf(type, size, entries, indent) { + var joinedEntries = indent ? indentedJoin(entries, indent) : $join.call(entries, ", "); + return type + " (" + size + ") {" + joinedEntries + "}"; + } + function singleLineValues(xs) { + for (var i = 0; i < xs.length; i++) { + if (indexOf(xs[i], "\n") >= 0) { + return false; + } + } + return true; + } + function getIndent(opts, depth) { + var baseIndent; + if (opts.indent === " ") { + baseIndent = " "; + } else if (typeof opts.indent === "number" && opts.indent > 0) { + baseIndent = $join.call(Array(opts.indent + 1), " "); + } else { + return null; + } + return { + base: baseIndent, + prev: $join.call(Array(depth + 1), baseIndent) + }; + } + function indentedJoin(xs, indent) { + if (xs.length === 0) { + return ""; + } + var lineJoiner = "\n" + indent.prev + indent.base; + return lineJoiner + $join.call(xs, "," + lineJoiner) + "\n" + indent.prev; + } + function arrObjKeys(obj, inspect) { + var isArr = isArray3(obj); + var xs = []; + if (isArr) { + xs.length = obj.length; + for (var i = 0; i < obj.length; i++) { + xs[i] = has2(obj, i) ? inspect(obj[i], obj) : ""; + } + } + var syms = typeof gOPS === "function" ? gOPS(obj) : []; + var symMap; + if (hasShammedSymbols) { + symMap = {}; + for (var k = 0; k < syms.length; k++) { + symMap["$" + syms[k]] = syms[k]; + } + } + for (var key in obj) { + if (!has2(obj, key)) { + continue; + } + if (isArr && String(Number(key)) === key && key < obj.length) { + continue; + } + if (hasShammedSymbols && symMap["$" + key] instanceof Symbol) { + continue; + } else if ($test.call(/[^\w$]/, key)) { + xs.push(inspect(key, obj) + ": " + inspect(obj[key], obj)); + } else { + xs.push(key + ": " + inspect(obj[key], obj)); + } + } + if (typeof gOPS === "function") { + for (var j = 0; j < syms.length; j++) { + if (isEnumerable.call(obj, syms[j])) { + xs.push("[" + inspect(syms[j]) + "]: " + inspect(obj[syms[j]], obj)); + } + } + } + return xs; + } + } +}); + +// ../../../node_modules/side-channel-list/index.js +var require_side_channel_list = __commonJS({ + "../../../node_modules/side-channel-list/index.js"(exports2, module2) { + "use strict"; + var inspect = require_object_inspect(); + var $TypeError = require_type(); + var listGetNode = function(list, key, isDelete) { + var prev = list; + var curr; + for (; (curr = prev.next) != null; prev = curr) { + if (curr.key === key) { + prev.next = curr.next; + if (!isDelete) { + curr.next = /** @type {NonNullable} */ + list.next; + list.next = curr; + } + return curr; + } + } + }; + var listGet = function(objects, key) { + if (!objects) { + return void 0; + } + var node = listGetNode(objects, key); + return node && node.value; + }; + var listSet = function(objects, key, value) { + var node = listGetNode(objects, key); + if (node) { + node.value = value; + } else { + objects.next = /** @type {import('./list.d.ts').ListNode} */ + { + // eslint-disable-line no-param-reassign, no-extra-parens + key, + next: objects.next, + value + }; + } + }; + var listHas = function(objects, key) { + if (!objects) { + return false; + } + return !!listGetNode(objects, key); + }; + var listDelete = function(objects, key) { + if (objects) { + return listGetNode(objects, key, true); + } + }; + module2.exports = function getSideChannelList() { + var $o; + var channel = { + assert: function(key) { + if (!channel.has(key)) { + throw new $TypeError("Side channel does not contain " + inspect(key)); + } + }, + "delete": function(key) { + var root2 = $o && $o.next; + var deletedNode = listDelete($o, key); + if (deletedNode && root2 && root2 === deletedNode) { + $o = void 0; + } + return !!deletedNode; + }, + get: function(key) { + return listGet($o, key); + }, + has: function(key) { + return listHas($o, key); + }, + set: function(key, value) { + if (!$o) { + $o = { + next: void 0 + }; + } + listSet( + /** @type {NonNullable} */ + $o, + key, + value + ); + } + }; + return channel; + }; + } +}); + +// ../../../node_modules/es-object-atoms/index.js +var require_es_object_atoms = __commonJS({ + "../../../node_modules/es-object-atoms/index.js"(exports2, module2) { + "use strict"; + module2.exports = Object; + } +}); + +// ../../../node_modules/es-errors/index.js +var require_es_errors = __commonJS({ + "../../../node_modules/es-errors/index.js"(exports2, module2) { + "use strict"; + module2.exports = Error; + } +}); + +// ../../../node_modules/es-errors/eval.js +var require_eval = __commonJS({ + "../../../node_modules/es-errors/eval.js"(exports2, module2) { + "use strict"; + module2.exports = EvalError; + } +}); + +// ../../../node_modules/es-errors/range.js +var require_range = __commonJS({ + "../../../node_modules/es-errors/range.js"(exports2, module2) { + "use strict"; + module2.exports = RangeError; + } +}); + +// ../../../node_modules/es-errors/ref.js +var require_ref = __commonJS({ + "../../../node_modules/es-errors/ref.js"(exports2, module2) { + "use strict"; + module2.exports = ReferenceError; + } +}); + +// ../../../node_modules/es-errors/syntax.js +var require_syntax = __commonJS({ + "../../../node_modules/es-errors/syntax.js"(exports2, module2) { + "use strict"; + module2.exports = SyntaxError; + } +}); + +// ../../../node_modules/es-errors/uri.js +var require_uri = __commonJS({ + "../../../node_modules/es-errors/uri.js"(exports2, module2) { + "use strict"; + module2.exports = URIError; + } +}); + +// ../../../node_modules/math-intrinsics/abs.js +var require_abs = __commonJS({ + "../../../node_modules/math-intrinsics/abs.js"(exports2, module2) { + "use strict"; + module2.exports = Math.abs; + } +}); + +// ../../../node_modules/math-intrinsics/floor.js +var require_floor = __commonJS({ + "../../../node_modules/math-intrinsics/floor.js"(exports2, module2) { + "use strict"; + module2.exports = Math.floor; + } +}); + +// ../../../node_modules/math-intrinsics/max.js +var require_max = __commonJS({ + "../../../node_modules/math-intrinsics/max.js"(exports2, module2) { + "use strict"; + module2.exports = Math.max; + } +}); + +// ../../../node_modules/math-intrinsics/min.js +var require_min = __commonJS({ + "../../../node_modules/math-intrinsics/min.js"(exports2, module2) { + "use strict"; + module2.exports = Math.min; + } +}); + +// ../../../node_modules/math-intrinsics/pow.js +var require_pow = __commonJS({ + "../../../node_modules/math-intrinsics/pow.js"(exports2, module2) { + "use strict"; + module2.exports = Math.pow; + } +}); + +// ../../../node_modules/math-intrinsics/round.js +var require_round = __commonJS({ + "../../../node_modules/math-intrinsics/round.js"(exports2, module2) { + "use strict"; + module2.exports = Math.round; + } +}); + +// ../../../node_modules/math-intrinsics/isNaN.js +var require_isNaN = __commonJS({ + "../../../node_modules/math-intrinsics/isNaN.js"(exports2, module2) { + "use strict"; + module2.exports = Number.isNaN || function isNaN2(a) { + return a !== a; + }; + } +}); + +// ../../../node_modules/math-intrinsics/sign.js +var require_sign = __commonJS({ + "../../../node_modules/math-intrinsics/sign.js"(exports2, module2) { + "use strict"; + var $isNaN = require_isNaN(); + module2.exports = function sign(number) { + if ($isNaN(number) || number === 0) { + return number; + } + return number < 0 ? -1 : 1; + }; + } +}); + +// ../../../node_modules/gopd/gOPD.js +var require_gOPD = __commonJS({ + "../../../node_modules/gopd/gOPD.js"(exports2, module2) { + "use strict"; + module2.exports = Object.getOwnPropertyDescriptor; + } +}); + +// ../../../node_modules/gopd/index.js +var require_gopd = __commonJS({ + "../../../node_modules/gopd/index.js"(exports2, module2) { + "use strict"; + var $gOPD = require_gOPD(); + if ($gOPD) { + try { + $gOPD([], "length"); + } catch (e) { + $gOPD = null; + } + } + module2.exports = $gOPD; + } +}); + +// ../../../node_modules/es-define-property/index.js +var require_es_define_property = __commonJS({ + "../../../node_modules/es-define-property/index.js"(exports2, module2) { + "use strict"; + var $defineProperty = Object.defineProperty || false; + if ($defineProperty) { + try { + $defineProperty({}, "a", { value: 1 }); + } catch (e) { + $defineProperty = false; + } + } + module2.exports = $defineProperty; + } +}); + +// ../../../node_modules/has-symbols/shams.js +var require_shams = __commonJS({ + "../../../node_modules/has-symbols/shams.js"(exports2, module2) { + "use strict"; + module2.exports = function hasSymbols() { + if (typeof Symbol !== "function" || typeof Object.getOwnPropertySymbols !== "function") { + return false; + } + if (typeof Symbol.iterator === "symbol") { + return true; + } + var obj = {}; + var sym = Symbol("test"); + var symObj = Object(sym); + if (typeof sym === "string") { + return false; + } + if (Object.prototype.toString.call(sym) !== "[object Symbol]") { + return false; + } + if (Object.prototype.toString.call(symObj) !== "[object Symbol]") { + return false; + } + var symVal = 42; + obj[sym] = symVal; + for (var _ in obj) { + return false; + } + if (typeof Object.keys === "function" && Object.keys(obj).length !== 0) { + return false; + } + if (typeof Object.getOwnPropertyNames === "function" && Object.getOwnPropertyNames(obj).length !== 0) { + return false; + } + var syms = Object.getOwnPropertySymbols(obj); + if (syms.length !== 1 || syms[0] !== sym) { + return false; + } + if (!Object.prototype.propertyIsEnumerable.call(obj, sym)) { + return false; + } + if (typeof Object.getOwnPropertyDescriptor === "function") { + var descriptor = ( + /** @type {PropertyDescriptor} */ + Object.getOwnPropertyDescriptor(obj, sym) + ); + if (descriptor.value !== symVal || descriptor.enumerable !== true) { + return false; + } + } + return true; + }; + } +}); + +// ../../../node_modules/has-symbols/index.js +var require_has_symbols = __commonJS({ + "../../../node_modules/has-symbols/index.js"(exports2, module2) { + "use strict"; + var origSymbol = typeof Symbol !== "undefined" && Symbol; + var hasSymbolSham = require_shams(); + module2.exports = function hasNativeSymbols() { + if (typeof origSymbol !== "function") { + return false; + } + if (typeof Symbol !== "function") { + return false; + } + if (typeof origSymbol("foo") !== "symbol") { + return false; + } + if (typeof Symbol("bar") !== "symbol") { + return false; + } + return hasSymbolSham(); + }; + } +}); + +// ../../../node_modules/get-proto/Reflect.getPrototypeOf.js +var require_Reflect_getPrototypeOf = __commonJS({ + "../../../node_modules/get-proto/Reflect.getPrototypeOf.js"(exports2, module2) { + "use strict"; + module2.exports = typeof Reflect !== "undefined" && Reflect.getPrototypeOf || null; + } +}); + +// ../../../node_modules/get-proto/Object.getPrototypeOf.js +var require_Object_getPrototypeOf = __commonJS({ + "../../../node_modules/get-proto/Object.getPrototypeOf.js"(exports2, module2) { + "use strict"; + var $Object = require_es_object_atoms(); + module2.exports = $Object.getPrototypeOf || null; + } +}); + +// ../../../node_modules/function-bind/implementation.js +var require_implementation = __commonJS({ + "../../../node_modules/function-bind/implementation.js"(exports2, module2) { + "use strict"; + var ERROR_MESSAGE = "Function.prototype.bind called on incompatible "; + var toStr = Object.prototype.toString; + var max = Math.max; + var funcType = "[object Function]"; + var concatty = function concatty2(a, b) { + var arr = []; + for (var i = 0; i < a.length; i += 1) { + arr[i] = a[i]; + } + for (var j = 0; j < b.length; j += 1) { + arr[j + a.length] = b[j]; + } + return arr; + }; + var slicy = function slicy2(arrLike, offset) { + var arr = []; + for (var i = offset || 0, j = 0; i < arrLike.length; i += 1, j += 1) { + arr[j] = arrLike[i]; + } + return arr; + }; + var joiny = function(arr, joiner) { + var str = ""; + for (var i = 0; i < arr.length; i += 1) { + str += arr[i]; + if (i + 1 < arr.length) { + str += joiner; + } + } + return str; + }; + module2.exports = function bind2(that) { + var target = this; + if (typeof target !== "function" || toStr.apply(target) !== funcType) { + throw new TypeError(ERROR_MESSAGE + target); + } + var args = slicy(arguments, 1); + var bound; + var binder = function() { + if (this instanceof bound) { + var result = target.apply( + this, + concatty(args, arguments) + ); + if (Object(result) === result) { + return result; + } + return this; + } + return target.apply( + that, + concatty(args, arguments) + ); + }; + var boundLength = max(0, target.length - args.length); + var boundArgs = []; + for (var i = 0; i < boundLength; i++) { + boundArgs[i] = "$" + i; + } + bound = Function("binder", "return function (" + joiny(boundArgs, ",") + "){ return binder.apply(this,arguments); }")(binder); + if (target.prototype) { + var Empty = function Empty2() { + }; + Empty.prototype = target.prototype; + bound.prototype = new Empty(); + Empty.prototype = null; + } + return bound; + }; + } +}); + +// ../../../node_modules/function-bind/index.js +var require_function_bind = __commonJS({ + "../../../node_modules/function-bind/index.js"(exports2, module2) { + "use strict"; + var implementation = require_implementation(); + module2.exports = Function.prototype.bind || implementation; + } +}); + +// ../../../node_modules/call-bind-apply-helpers/functionCall.js +var require_functionCall = __commonJS({ + "../../../node_modules/call-bind-apply-helpers/functionCall.js"(exports2, module2) { + "use strict"; + module2.exports = Function.prototype.call; + } +}); + +// ../../../node_modules/call-bind-apply-helpers/functionApply.js +var require_functionApply = __commonJS({ + "../../../node_modules/call-bind-apply-helpers/functionApply.js"(exports2, module2) { + "use strict"; + module2.exports = Function.prototype.apply; + } +}); + +// ../../../node_modules/call-bind-apply-helpers/reflectApply.js +var require_reflectApply = __commonJS({ + "../../../node_modules/call-bind-apply-helpers/reflectApply.js"(exports2, module2) { + "use strict"; + module2.exports = typeof Reflect !== "undefined" && Reflect && Reflect.apply; + } +}); + +// ../../../node_modules/call-bind-apply-helpers/actualApply.js +var require_actualApply = __commonJS({ + "../../../node_modules/call-bind-apply-helpers/actualApply.js"(exports2, module2) { + "use strict"; + var bind2 = require_function_bind(); + var $apply = require_functionApply(); + var $call = require_functionCall(); + var $reflectApply = require_reflectApply(); + module2.exports = $reflectApply || bind2.call($call, $apply); + } +}); + +// ../../../node_modules/call-bind-apply-helpers/index.js +var require_call_bind_apply_helpers = __commonJS({ + "../../../node_modules/call-bind-apply-helpers/index.js"(exports2, module2) { + "use strict"; + var bind2 = require_function_bind(); + var $TypeError = require_type(); + var $call = require_functionCall(); + var $actualApply = require_actualApply(); + module2.exports = function callBindBasic(args) { + if (args.length < 1 || typeof args[0] !== "function") { + throw new $TypeError("a function is required"); + } + return $actualApply(bind2, $call, args); + }; + } +}); + +// ../../../node_modules/dunder-proto/get.js +var require_get = __commonJS({ + "../../../node_modules/dunder-proto/get.js"(exports2, module2) { + "use strict"; + var callBind = require_call_bind_apply_helpers(); + var gOPD = require_gopd(); + var hasProtoAccessor; + try { + hasProtoAccessor = /** @type {{ __proto__?: typeof Array.prototype }} */ + [].__proto__ === Array.prototype; + } catch (e) { + if (!e || typeof e !== "object" || !("code" in e) || e.code !== "ERR_PROTO_ACCESS") { + throw e; + } + } + var desc = !!hasProtoAccessor && gOPD && gOPD( + Object.prototype, + /** @type {keyof typeof Object.prototype} */ + "__proto__" + ); + var $Object = Object; + var $getPrototypeOf = $Object.getPrototypeOf; + module2.exports = desc && typeof desc.get === "function" ? callBind([desc.get]) : typeof $getPrototypeOf === "function" ? ( + /** @type {import('./get')} */ + function getDunder(value) { + return $getPrototypeOf(value == null ? value : $Object(value)); + } + ) : false; + } +}); + +// ../../../node_modules/get-proto/index.js +var require_get_proto = __commonJS({ + "../../../node_modules/get-proto/index.js"(exports2, module2) { + "use strict"; + var reflectGetProto = require_Reflect_getPrototypeOf(); + var originalGetProto = require_Object_getPrototypeOf(); + var getDunderProto = require_get(); + module2.exports = reflectGetProto ? function getProto(O) { + return reflectGetProto(O); + } : originalGetProto ? function getProto(O) { + if (!O || typeof O !== "object" && typeof O !== "function") { + throw new TypeError("getProto: not an object"); + } + return originalGetProto(O); + } : getDunderProto ? function getProto(O) { + return getDunderProto(O); + } : null; + } +}); + +// ../../../node_modules/hasown/index.js +var require_hasown = __commonJS({ + "../../../node_modules/hasown/index.js"(exports2, module2) { + "use strict"; + var call = Function.prototype.call; + var $hasOwn = Object.prototype.hasOwnProperty; + var bind2 = require_function_bind(); + module2.exports = bind2.call(call, $hasOwn); + } +}); + +// ../../../node_modules/get-intrinsic/index.js +var require_get_intrinsic = __commonJS({ + "../../../node_modules/get-intrinsic/index.js"(exports2, module2) { + "use strict"; + var undefined2; + var $Object = require_es_object_atoms(); + var $Error = require_es_errors(); + var $EvalError = require_eval(); + var $RangeError = require_range(); + var $ReferenceError = require_ref(); + var $SyntaxError = require_syntax(); + var $TypeError = require_type(); + var $URIError = require_uri(); + var abs = require_abs(); + var floor = require_floor(); + var max = require_max(); + var min = require_min(); + var pow = require_pow(); + var round = require_round(); + var sign = require_sign(); + var $Function = Function; + var getEvalledConstructor = function(expressionSyntax) { + try { + return $Function('"use strict"; return (' + expressionSyntax + ").constructor;")(); + } catch (e) { + } + }; + var $gOPD = require_gopd(); + var $defineProperty = require_es_define_property(); + var throwTypeError = function() { + throw new $TypeError(); + }; + var ThrowTypeError = $gOPD ? (function() { + try { + arguments.callee; + return throwTypeError; + } catch (calleeThrows) { + try { + return $gOPD(arguments, "callee").get; + } catch (gOPDthrows) { + return throwTypeError; + } + } + })() : throwTypeError; + var hasSymbols = require_has_symbols()(); + var getProto = require_get_proto(); + var $ObjectGPO = require_Object_getPrototypeOf(); + var $ReflectGPO = require_Reflect_getPrototypeOf(); + var $apply = require_functionApply(); + var $call = require_functionCall(); + var needsEval = {}; + var TypedArray = typeof Uint8Array === "undefined" || !getProto ? undefined2 : getProto(Uint8Array); + var INTRINSICS = { + __proto__: null, + "%AggregateError%": typeof AggregateError === "undefined" ? undefined2 : AggregateError, + "%Array%": Array, + "%ArrayBuffer%": typeof ArrayBuffer === "undefined" ? undefined2 : ArrayBuffer, + "%ArrayIteratorPrototype%": hasSymbols && getProto ? getProto([][Symbol.iterator]()) : undefined2, + "%AsyncFromSyncIteratorPrototype%": undefined2, + "%AsyncFunction%": needsEval, + "%AsyncGenerator%": needsEval, + "%AsyncGeneratorFunction%": needsEval, + "%AsyncIteratorPrototype%": needsEval, + "%Atomics%": typeof Atomics === "undefined" ? undefined2 : Atomics, + "%BigInt%": typeof BigInt === "undefined" ? undefined2 : BigInt, + "%BigInt64Array%": typeof BigInt64Array === "undefined" ? undefined2 : BigInt64Array, + "%BigUint64Array%": typeof BigUint64Array === "undefined" ? undefined2 : BigUint64Array, + "%Boolean%": Boolean, + "%DataView%": typeof DataView === "undefined" ? undefined2 : DataView, + "%Date%": Date, + "%decodeURI%": decodeURI, + "%decodeURIComponent%": decodeURIComponent, + "%encodeURI%": encodeURI, + "%encodeURIComponent%": encodeURIComponent, + "%Error%": $Error, + "%eval%": eval, + // eslint-disable-line no-eval + "%EvalError%": $EvalError, + "%Float16Array%": typeof Float16Array === "undefined" ? undefined2 : Float16Array, + "%Float32Array%": typeof Float32Array === "undefined" ? undefined2 : Float32Array, + "%Float64Array%": typeof Float64Array === "undefined" ? undefined2 : Float64Array, + "%FinalizationRegistry%": typeof FinalizationRegistry === "undefined" ? undefined2 : FinalizationRegistry, + "%Function%": $Function, + "%GeneratorFunction%": needsEval, + "%Int8Array%": typeof Int8Array === "undefined" ? undefined2 : Int8Array, + "%Int16Array%": typeof Int16Array === "undefined" ? undefined2 : Int16Array, + "%Int32Array%": typeof Int32Array === "undefined" ? undefined2 : Int32Array, + "%isFinite%": isFinite, + "%isNaN%": isNaN, + "%IteratorPrototype%": hasSymbols && getProto ? getProto(getProto([][Symbol.iterator]())) : undefined2, + "%JSON%": typeof JSON === "object" ? JSON : undefined2, + "%Map%": typeof Map === "undefined" ? undefined2 : Map, + "%MapIteratorPrototype%": typeof Map === "undefined" || !hasSymbols || !getProto ? undefined2 : getProto((/* @__PURE__ */ new Map())[Symbol.iterator]()), + "%Math%": Math, + "%Number%": Number, + "%Object%": $Object, + "%Object.getOwnPropertyDescriptor%": $gOPD, + "%parseFloat%": parseFloat, + "%parseInt%": parseInt, + "%Promise%": typeof Promise === "undefined" ? undefined2 : Promise, + "%Proxy%": typeof Proxy === "undefined" ? undefined2 : Proxy, + "%RangeError%": $RangeError, + "%ReferenceError%": $ReferenceError, + "%Reflect%": typeof Reflect === "undefined" ? undefined2 : Reflect, + "%RegExp%": RegExp, + "%Set%": typeof Set === "undefined" ? undefined2 : Set, + "%SetIteratorPrototype%": typeof Set === "undefined" || !hasSymbols || !getProto ? undefined2 : getProto((/* @__PURE__ */ new Set())[Symbol.iterator]()), + "%SharedArrayBuffer%": typeof SharedArrayBuffer === "undefined" ? undefined2 : SharedArrayBuffer, + "%String%": String, + "%StringIteratorPrototype%": hasSymbols && getProto ? getProto(""[Symbol.iterator]()) : undefined2, + "%Symbol%": hasSymbols ? Symbol : undefined2, + "%SyntaxError%": $SyntaxError, + "%ThrowTypeError%": ThrowTypeError, + "%TypedArray%": TypedArray, + "%TypeError%": $TypeError, + "%Uint8Array%": typeof Uint8Array === "undefined" ? undefined2 : Uint8Array, + "%Uint8ClampedArray%": typeof Uint8ClampedArray === "undefined" ? undefined2 : Uint8ClampedArray, + "%Uint16Array%": typeof Uint16Array === "undefined" ? undefined2 : Uint16Array, + "%Uint32Array%": typeof Uint32Array === "undefined" ? undefined2 : Uint32Array, + "%URIError%": $URIError, + "%WeakMap%": typeof WeakMap === "undefined" ? undefined2 : WeakMap, + "%WeakRef%": typeof WeakRef === "undefined" ? undefined2 : WeakRef, + "%WeakSet%": typeof WeakSet === "undefined" ? undefined2 : WeakSet, + "%Function.prototype.call%": $call, + "%Function.prototype.apply%": $apply, + "%Object.defineProperty%": $defineProperty, + "%Object.getPrototypeOf%": $ObjectGPO, + "%Math.abs%": abs, + "%Math.floor%": floor, + "%Math.max%": max, + "%Math.min%": min, + "%Math.pow%": pow, + "%Math.round%": round, + "%Math.sign%": sign, + "%Reflect.getPrototypeOf%": $ReflectGPO + }; + if (getProto) { + try { + null.error; + } catch (e) { + errorProto = getProto(getProto(e)); + INTRINSICS["%Error.prototype%"] = errorProto; + } + } + var errorProto; + var doEval = function doEval2(name) { + var value; + if (name === "%AsyncFunction%") { + value = getEvalledConstructor("async function () {}"); + } else if (name === "%GeneratorFunction%") { + value = getEvalledConstructor("function* () {}"); + } else if (name === "%AsyncGeneratorFunction%") { + value = getEvalledConstructor("async function* () {}"); + } else if (name === "%AsyncGenerator%") { + var fn = doEval2("%AsyncGeneratorFunction%"); + if (fn) { + value = fn.prototype; + } + } else if (name === "%AsyncIteratorPrototype%") { + var gen = doEval2("%AsyncGenerator%"); + if (gen && getProto) { + value = getProto(gen.prototype); + } + } + INTRINSICS[name] = value; + return value; + }; + var LEGACY_ALIASES = { + __proto__: null, + "%ArrayBufferPrototype%": ["ArrayBuffer", "prototype"], + "%ArrayPrototype%": ["Array", "prototype"], + "%ArrayProto_entries%": ["Array", "prototype", "entries"], + "%ArrayProto_forEach%": ["Array", "prototype", "forEach"], + "%ArrayProto_keys%": ["Array", "prototype", "keys"], + "%ArrayProto_values%": ["Array", "prototype", "values"], + "%AsyncFunctionPrototype%": ["AsyncFunction", "prototype"], + "%AsyncGenerator%": ["AsyncGeneratorFunction", "prototype"], + "%AsyncGeneratorPrototype%": ["AsyncGeneratorFunction", "prototype", "prototype"], + "%BooleanPrototype%": ["Boolean", "prototype"], + "%DataViewPrototype%": ["DataView", "prototype"], + "%DatePrototype%": ["Date", "prototype"], + "%ErrorPrototype%": ["Error", "prototype"], + "%EvalErrorPrototype%": ["EvalError", "prototype"], + "%Float32ArrayPrototype%": ["Float32Array", "prototype"], + "%Float64ArrayPrototype%": ["Float64Array", "prototype"], + "%FunctionPrototype%": ["Function", "prototype"], + "%Generator%": ["GeneratorFunction", "prototype"], + "%GeneratorPrototype%": ["GeneratorFunction", "prototype", "prototype"], + "%Int8ArrayPrototype%": ["Int8Array", "prototype"], + "%Int16ArrayPrototype%": ["Int16Array", "prototype"], + "%Int32ArrayPrototype%": ["Int32Array", "prototype"], + "%JSONParse%": ["JSON", "parse"], + "%JSONStringify%": ["JSON", "stringify"], + "%MapPrototype%": ["Map", "prototype"], + "%NumberPrototype%": ["Number", "prototype"], + "%ObjectPrototype%": ["Object", "prototype"], + "%ObjProto_toString%": ["Object", "prototype", "toString"], + "%ObjProto_valueOf%": ["Object", "prototype", "valueOf"], + "%PromisePrototype%": ["Promise", "prototype"], + "%PromiseProto_then%": ["Promise", "prototype", "then"], + "%Promise_all%": ["Promise", "all"], + "%Promise_reject%": ["Promise", "reject"], + "%Promise_resolve%": ["Promise", "resolve"], + "%RangeErrorPrototype%": ["RangeError", "prototype"], + "%ReferenceErrorPrototype%": ["ReferenceError", "prototype"], + "%RegExpPrototype%": ["RegExp", "prototype"], + "%SetPrototype%": ["Set", "prototype"], + "%SharedArrayBufferPrototype%": ["SharedArrayBuffer", "prototype"], + "%StringPrototype%": ["String", "prototype"], + "%SymbolPrototype%": ["Symbol", "prototype"], + "%SyntaxErrorPrototype%": ["SyntaxError", "prototype"], + "%TypedArrayPrototype%": ["TypedArray", "prototype"], + "%TypeErrorPrototype%": ["TypeError", "prototype"], + "%Uint8ArrayPrototype%": ["Uint8Array", "prototype"], + "%Uint8ClampedArrayPrototype%": ["Uint8ClampedArray", "prototype"], + "%Uint16ArrayPrototype%": ["Uint16Array", "prototype"], + "%Uint32ArrayPrototype%": ["Uint32Array", "prototype"], + "%URIErrorPrototype%": ["URIError", "prototype"], + "%WeakMapPrototype%": ["WeakMap", "prototype"], + "%WeakSetPrototype%": ["WeakSet", "prototype"] + }; + var bind2 = require_function_bind(); + var hasOwn = require_hasown(); + var $concat = bind2.call($call, Array.prototype.concat); + var $spliceApply = bind2.call($apply, Array.prototype.splice); + var $replace = bind2.call($call, String.prototype.replace); + var $strSlice = bind2.call($call, String.prototype.slice); + var $exec = bind2.call($call, RegExp.prototype.exec); + var rePropName2 = /[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g; + var reEscapeChar2 = /\\(\\)?/g; + var stringToPath2 = function stringToPath3(string) { + var first = $strSlice(string, 0, 1); + var last = $strSlice(string, -1); + if (first === "%" && last !== "%") { + throw new $SyntaxError("invalid intrinsic syntax, expected closing `%`"); + } else if (last === "%" && first !== "%") { + throw new $SyntaxError("invalid intrinsic syntax, expected opening `%`"); + } + var result = []; + $replace(string, rePropName2, function(match, number, quote, subString) { + result[result.length] = quote ? $replace(subString, reEscapeChar2, "$1") : number || match; + }); + return result; + }; + var getBaseIntrinsic = function getBaseIntrinsic2(name, allowMissing) { + var intrinsicName = name; + var alias; + if (hasOwn(LEGACY_ALIASES, intrinsicName)) { + alias = LEGACY_ALIASES[intrinsicName]; + intrinsicName = "%" + alias[0] + "%"; + } + if (hasOwn(INTRINSICS, intrinsicName)) { + var value = INTRINSICS[intrinsicName]; + if (value === needsEval) { + value = doEval(intrinsicName); + } + if (typeof value === "undefined" && !allowMissing) { + throw new $TypeError("intrinsic " + name + " exists, but is not available. Please file an issue!"); + } + return { + alias, + name: intrinsicName, + value + }; + } + throw new $SyntaxError("intrinsic " + name + " does not exist!"); + }; + module2.exports = function GetIntrinsic(name, allowMissing) { + if (typeof name !== "string" || name.length === 0) { + throw new $TypeError("intrinsic name must be a non-empty string"); + } + if (arguments.length > 1 && typeof allowMissing !== "boolean") { + throw new $TypeError('"allowMissing" argument must be a boolean'); + } + if ($exec(/^%?[^%]*%?$/, name) === null) { + throw new $SyntaxError("`%` may not be present anywhere but at the beginning and end of the intrinsic name"); + } + var parts = stringToPath2(name); + var intrinsicBaseName = parts.length > 0 ? parts[0] : ""; + var intrinsic = getBaseIntrinsic("%" + intrinsicBaseName + "%", allowMissing); + var intrinsicRealName = intrinsic.name; + var value = intrinsic.value; + var skipFurtherCaching = false; + var alias = intrinsic.alias; + if (alias) { + intrinsicBaseName = alias[0]; + $spliceApply(parts, $concat([0, 1], alias)); + } + for (var i = 1, isOwn = true; i < parts.length; i += 1) { + var part = parts[i]; + var first = $strSlice(part, 0, 1); + var last = $strSlice(part, -1); + if ((first === '"' || first === "'" || first === "`" || (last === '"' || last === "'" || last === "`")) && first !== last) { + throw new $SyntaxError("property names with quotes must have matching quotes"); + } + if (part === "constructor" || !isOwn) { + skipFurtherCaching = true; + } + intrinsicBaseName += "." + part; + intrinsicRealName = "%" + intrinsicBaseName + "%"; + if (hasOwn(INTRINSICS, intrinsicRealName)) { + value = INTRINSICS[intrinsicRealName]; + } else if (value != null) { + if (!(part in value)) { + if (!allowMissing) { + throw new $TypeError("base intrinsic for " + name + " exists, but the property is not available."); + } + return void undefined2; + } + if ($gOPD && i + 1 >= parts.length) { + var desc = $gOPD(value, part); + isOwn = !!desc; + if (isOwn && "get" in desc && !("originalValue" in desc.get)) { + value = desc.get; + } else { + value = value[part]; + } + } else { + isOwn = hasOwn(value, part); + value = value[part]; + } + if (isOwn && !skipFurtherCaching) { + INTRINSICS[intrinsicRealName] = value; + } + } + } + return value; + }; + } +}); + +// ../../../node_modules/call-bound/index.js +var require_call_bound = __commonJS({ + "../../../node_modules/call-bound/index.js"(exports2, module2) { + "use strict"; + var GetIntrinsic = require_get_intrinsic(); + var callBindBasic = require_call_bind_apply_helpers(); + var $indexOf = callBindBasic([GetIntrinsic("%String.prototype.indexOf%")]); + module2.exports = function callBoundIntrinsic(name, allowMissing) { + var intrinsic = ( + /** @type {(this: unknown, ...args: unknown[]) => unknown} */ + GetIntrinsic(name, !!allowMissing) + ); + if (typeof intrinsic === "function" && $indexOf(name, ".prototype.") > -1) { + return callBindBasic( + /** @type {const} */ + [intrinsic] + ); + } + return intrinsic; + }; + } +}); + +// ../../../node_modules/side-channel-map/index.js +var require_side_channel_map = __commonJS({ + "../../../node_modules/side-channel-map/index.js"(exports2, module2) { + "use strict"; + var GetIntrinsic = require_get_intrinsic(); + var callBound = require_call_bound(); + var inspect = require_object_inspect(); + var $TypeError = require_type(); + var $Map = GetIntrinsic("%Map%", true); + var $mapGet = callBound("Map.prototype.get", true); + var $mapSet = callBound("Map.prototype.set", true); + var $mapHas = callBound("Map.prototype.has", true); + var $mapDelete = callBound("Map.prototype.delete", true); + var $mapSize = callBound("Map.prototype.size", true); + module2.exports = !!$Map && /** @type {Exclude} */ + function getSideChannelMap() { + var $m; + var channel = { + assert: function(key) { + if (!channel.has(key)) { + throw new $TypeError("Side channel does not contain " + inspect(key)); + } + }, + "delete": function(key) { + if ($m) { + var result = $mapDelete($m, key); + if ($mapSize($m) === 0) { + $m = void 0; + } + return result; + } + return false; + }, + get: function(key) { + if ($m) { + return $mapGet($m, key); + } + }, + has: function(key) { + if ($m) { + return $mapHas($m, key); + } + return false; + }, + set: function(key, value) { + if (!$m) { + $m = new $Map(); + } + $mapSet($m, key, value); + } + }; + return channel; + }; + } +}); + +// ../../../node_modules/side-channel-weakmap/index.js +var require_side_channel_weakmap = __commonJS({ + "../../../node_modules/side-channel-weakmap/index.js"(exports2, module2) { + "use strict"; + var GetIntrinsic = require_get_intrinsic(); + var callBound = require_call_bound(); + var inspect = require_object_inspect(); + var getSideChannelMap = require_side_channel_map(); + var $TypeError = require_type(); + var $WeakMap = GetIntrinsic("%WeakMap%", true); + var $weakMapGet = callBound("WeakMap.prototype.get", true); + var $weakMapSet = callBound("WeakMap.prototype.set", true); + var $weakMapHas = callBound("WeakMap.prototype.has", true); + var $weakMapDelete = callBound("WeakMap.prototype.delete", true); + module2.exports = $WeakMap ? ( + /** @type {Exclude} */ + function getSideChannelWeakMap() { + var $wm; + var $m; + var channel = { + assert: function(key) { + if (!channel.has(key)) { + throw new $TypeError("Side channel does not contain " + inspect(key)); + } + }, + "delete": function(key) { + if ($WeakMap && key && (typeof key === "object" || typeof key === "function")) { + if ($wm) { + return $weakMapDelete($wm, key); + } + } else if (getSideChannelMap) { + if ($m) { + return $m["delete"](key); + } + } + return false; + }, + get: function(key) { + if ($WeakMap && key && (typeof key === "object" || typeof key === "function")) { + if ($wm) { + return $weakMapGet($wm, key); + } + } + return $m && $m.get(key); + }, + has: function(key) { + if ($WeakMap && key && (typeof key === "object" || typeof key === "function")) { + if ($wm) { + return $weakMapHas($wm, key); + } + } + return !!$m && $m.has(key); + }, + set: function(key, value) { + if ($WeakMap && key && (typeof key === "object" || typeof key === "function")) { + if (!$wm) { + $wm = new $WeakMap(); + } + $weakMapSet($wm, key, value); + } else if (getSideChannelMap) { + if (!$m) { + $m = getSideChannelMap(); + } + $m.set(key, value); + } + } + }; + return channel; + } + ) : getSideChannelMap; + } +}); + +// ../../../node_modules/side-channel/index.js +var require_side_channel = __commonJS({ + "../../../node_modules/side-channel/index.js"(exports2, module2) { + "use strict"; + var $TypeError = require_type(); + var inspect = require_object_inspect(); + var getSideChannelList = require_side_channel_list(); + var getSideChannelMap = require_side_channel_map(); + var getSideChannelWeakMap = require_side_channel_weakmap(); + var makeChannel = getSideChannelWeakMap || getSideChannelMap || getSideChannelList; + module2.exports = function getSideChannel() { + var $channelData; + var channel = { + assert: function(key) { + if (!channel.has(key)) { + throw new $TypeError("Side channel does not contain " + inspect(key)); + } + }, + "delete": function(key) { + return !!$channelData && $channelData["delete"](key); + }, + get: function(key) { + return $channelData && $channelData.get(key); + }, + has: function(key) { + return !!$channelData && $channelData.has(key); + }, + set: function(key, value) { + if (!$channelData) { + $channelData = makeChannel(); + } + $channelData.set(key, value); + } + }; + return channel; + }; + } +}); + +// ../../../node_modules/qs/lib/formats.js +var require_formats = __commonJS({ + "../../../node_modules/qs/lib/formats.js"(exports2, module2) { + "use strict"; + var replace = String.prototype.replace; + var percentTwenties = /%20/g; + var Format = { + RFC1738: "RFC1738", + RFC3986: "RFC3986" + }; + module2.exports = { + "default": Format.RFC3986, + formatters: { + RFC1738: function(value) { + return replace.call(value, percentTwenties, "+"); + }, + RFC3986: function(value) { + return String(value); + } + }, + RFC1738: Format.RFC1738, + RFC3986: Format.RFC3986 + }; + } +}); + +// ../../../node_modules/qs/lib/utils.js +var require_utils = __commonJS({ + "../../../node_modules/qs/lib/utils.js"(exports2, module2) { + "use strict"; + var formats = require_formats(); + var getSideChannel = require_side_channel(); + var has2 = Object.prototype.hasOwnProperty; + var isArray3 = Array.isArray; + var overflowChannel = getSideChannel(); + var markOverflow = function markOverflow2(obj, maxIndex) { + overflowChannel.set(obj, maxIndex); + return obj; + }; + var isOverflow = function isOverflow2(obj) { + return overflowChannel.has(obj); + }; + var getMaxIndex = function getMaxIndex2(obj) { + return overflowChannel.get(obj); + }; + var setMaxIndex = function setMaxIndex2(obj, maxIndex) { + overflowChannel.set(obj, maxIndex); + }; + var hexTable = (function() { + var array = []; + for (var i = 0; i < 256; ++i) { + array[array.length] = "%" + ((i < 16 ? "0" : "") + i.toString(16)).toUpperCase(); + } + return array; + })(); + var compactQueue = function compactQueue2(queue5) { + while (queue5.length > 1) { + var item = queue5.pop(); + var obj = item.obj[item.prop]; + if (isArray3(obj)) { + var compacted = []; + for (var j = 0; j < obj.length; ++j) { + if (typeof obj[j] !== "undefined") { + compacted[compacted.length] = obj[j]; + } + } + item.obj[item.prop] = compacted; + } + } + }; + var arrayToObject2 = function arrayToObject3(source, options) { + var obj = options && options.plainObjects ? { __proto__: null } : {}; + for (var i = 0; i < source.length; ++i) { + if (typeof source[i] !== "undefined") { + obj[i] = source[i]; + } + } + return obj; + }; + var merge3 = function merge4(target, source, options) { + if (!source) { + return target; + } + if (typeof source !== "object" && typeof source !== "function") { + if (isArray3(target)) { + var nextIndex = target.length; + if (options && typeof options.arrayLimit === "number" && nextIndex > options.arrayLimit) { + return markOverflow(arrayToObject2(target.concat(source), options), nextIndex); + } + target[nextIndex] = source; + } else if (target && typeof target === "object") { + if (isOverflow(target)) { + var newIndex = getMaxIndex(target) + 1; + target[newIndex] = source; + setMaxIndex(target, newIndex); + } else if (options && options.strictMerge) { + return [target, source]; + } else if (options && (options.plainObjects || options.allowPrototypes) || !has2.call(Object.prototype, source)) { + target[source] = true; + } + } else { + return [target, source]; + } + return target; + } + if (!target || typeof target !== "object") { + if (isOverflow(source)) { + var sourceKeys = Object.keys(source); + var result = options && options.plainObjects ? { __proto__: null, 0: target } : { 0: target }; + for (var m = 0; m < sourceKeys.length; m++) { + var oldKey = parseInt(sourceKeys[m], 10); + result[oldKey + 1] = source[sourceKeys[m]]; + } + return markOverflow(result, getMaxIndex(source) + 1); + } + var combined = [target].concat(source); + if (options && typeof options.arrayLimit === "number" && combined.length > options.arrayLimit) { + return markOverflow(arrayToObject2(combined, options), combined.length - 1); + } + return combined; + } + var mergeTarget = target; + if (isArray3(target) && !isArray3(source)) { + mergeTarget = arrayToObject2(target, options); + } + if (isArray3(target) && isArray3(source)) { + source.forEach(function(item, i) { + if (has2.call(target, i)) { + var targetItem = target[i]; + if (targetItem && typeof targetItem === "object" && item && typeof item === "object") { + target[i] = merge4(targetItem, item, options); + } else { + target[target.length] = item; + } + } else { + target[i] = item; + } + }); + return target; + } + return Object.keys(source).reduce(function(acc, key) { + var value = source[key]; + if (has2.call(acc, key)) { + acc[key] = merge4(acc[key], value, options); + } else { + acc[key] = value; + } + if (isOverflow(source) && !isOverflow(acc)) { + markOverflow(acc, getMaxIndex(source)); + } + if (isOverflow(acc)) { + var keyNum = parseInt(key, 10); + if (String(keyNum) === key && keyNum >= 0 && keyNum > getMaxIndex(acc)) { + setMaxIndex(acc, keyNum); + } + } + return acc; + }, mergeTarget); + }; + var assign = function assignSingleSource(target, source) { + return Object.keys(source).reduce(function(acc, key) { + acc[key] = source[key]; + return acc; + }, target); + }; + var decode = function(str, defaultDecoder, charset) { + var strWithoutPlus = str.replace(/\+/g, " "); + if (charset === "iso-8859-1") { + return strWithoutPlus.replace(/%[0-9a-f]{2}/gi, unescape); + } + try { + return decodeURIComponent(strWithoutPlus); + } catch (e) { + return strWithoutPlus; + } + }; + var limit = 1024; + var encode3 = function encode4(str, defaultEncoder, charset, kind, format) { + if (str.length === 0) { + return str; + } + var string = str; + if (typeof str === "symbol") { + string = Symbol.prototype.toString.call(str); + } else if (typeof str !== "string") { + string = String(str); + } + if (charset === "iso-8859-1") { + return escape(string).replace(/%u[0-9a-f]{4}/gi, function($0) { + return "%26%23" + parseInt($0.slice(2), 16) + "%3B"; + }); + } + var out = ""; + for (var j = 0; j < string.length; j += limit) { + var segment = string.length >= limit ? string.slice(j, j + limit) : string; + var arr = []; + for (var i = 0; i < segment.length; ++i) { + var c = segment.charCodeAt(i); + if (c === 45 || c === 46 || c === 95 || c === 126 || c >= 48 && c <= 57 || c >= 65 && c <= 90 || c >= 97 && c <= 122 || format === formats.RFC1738 && (c === 40 || c === 41)) { + arr[arr.length] = segment.charAt(i); + continue; + } + if (c < 128) { + arr[arr.length] = hexTable[c]; + continue; + } + if (c < 2048) { + arr[arr.length] = hexTable[192 | c >> 6] + hexTable[128 | c & 63]; + continue; + } + if (c < 55296 || c >= 57344) { + arr[arr.length] = hexTable[224 | c >> 12] + hexTable[128 | c >> 6 & 63] + hexTable[128 | c & 63]; + continue; + } + i += 1; + c = 65536 + ((c & 1023) << 10 | segment.charCodeAt(i) & 1023); + arr[arr.length] = hexTable[240 | c >> 18] + hexTable[128 | c >> 12 & 63] + hexTable[128 | c >> 6 & 63] + hexTable[128 | c & 63]; + } + out += arr.join(""); + } + return out; + }; + var compact = function compact2(value) { + var queue5 = [{ obj: { o: value }, prop: "o" }]; + var refs = []; + for (var i = 0; i < queue5.length; ++i) { + var item = queue5[i]; + var obj = item.obj[item.prop]; + var keys2 = Object.keys(obj); + for (var j = 0; j < keys2.length; ++j) { + var key = keys2[j]; + var val = obj[key]; + if (typeof val === "object" && val !== null && refs.indexOf(val) === -1) { + queue5[queue5.length] = { obj, prop: key }; + refs[refs.length] = val; + } + } + } + compactQueue(queue5); + return value; + }; + var isRegExp2 = function isRegExp3(obj) { + return Object.prototype.toString.call(obj) === "[object RegExp]"; + }; + var isBuffer3 = function isBuffer4(obj) { + if (!obj || typeof obj !== "object") { + return false; + } + return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj)); + }; + var combine = function combine2(a, b, arrayLimit, plainObjects) { + if (isOverflow(a)) { + var newIndex = getMaxIndex(a) + 1; + a[newIndex] = b; + setMaxIndex(a, newIndex); + return a; + } + var result = [].concat(a, b); + if (result.length > arrayLimit) { + return markOverflow(arrayToObject2(result, { plainObjects }), result.length - 1); + } + return result; + }; + var maybeMap = function maybeMap2(val, fn) { + if (isArray3(val)) { + var mapped = []; + for (var i = 0; i < val.length; i += 1) { + mapped[mapped.length] = fn(val[i]); + } + return mapped; + } + return fn(val); + }; + module2.exports = { + arrayToObject: arrayToObject2, + assign, + combine, + compact, + decode, + encode: encode3, + isBuffer: isBuffer3, + isOverflow, + isRegExp: isRegExp2, + markOverflow, + maybeMap, + merge: merge3 + }; + } +}); + +// ../../../node_modules/qs/lib/stringify.js +var require_stringify = __commonJS({ + "../../../node_modules/qs/lib/stringify.js"(exports2, module2) { + "use strict"; + var getSideChannel = require_side_channel(); + var utils = require_utils(); + var formats = require_formats(); + var has2 = Object.prototype.hasOwnProperty; + var arrayPrefixGenerators = { + brackets: function brackets(prefix) { + return prefix + "[]"; + }, + comma: "comma", + indices: function indices(prefix, key) { + return prefix + "[" + key + "]"; + }, + repeat: function repeat(prefix) { + return prefix; + } + }; + var isArray3 = Array.isArray; + var push = Array.prototype.push; + var pushToArray = function(arr, valueOrArray) { + push.apply(arr, isArray3(valueOrArray) ? valueOrArray : [valueOrArray]); + }; + var toISO = Date.prototype.toISOString; + var defaultFormat = formats["default"]; + var defaults2 = { + addQueryPrefix: false, + allowDots: false, + allowEmptyArrays: false, + arrayFormat: "indices", + charset: "utf-8", + charsetSentinel: false, + commaRoundTrip: false, + delimiter: "&", + encode: true, + encodeDotInKeys: false, + encoder: utils.encode, + encodeValuesOnly: false, + filter: void 0, + format: defaultFormat, + formatter: formats.formatters[defaultFormat], + // deprecated + indices: false, + serializeDate: function serializeDate(date) { + return toISO.call(date); + }, + skipNulls: false, + strictNullHandling: false + }; + var isNonNullishPrimitive = function isNonNullishPrimitive2(v) { + return typeof v === "string" || typeof v === "number" || typeof v === "boolean" || typeof v === "symbol" || typeof v === "bigint"; + }; + var sentinel = {}; + var stringify2 = function stringify3(object, prefix, generateArrayPrefix, commaRoundTrip, allowEmptyArrays, strictNullHandling, skipNulls, encodeDotInKeys, encoder, filter2, sort, allowDots, serializeDate, format, formatter, encodeValuesOnly, charset, sideChannel) { + var obj = object; + var tmpSc = sideChannel; + var step = 0; + var findFlag = false; + while ((tmpSc = tmpSc.get(sentinel)) !== void 0 && !findFlag) { + var pos = tmpSc.get(object); + step += 1; + if (typeof pos !== "undefined") { + if (pos === step) { + throw new RangeError("Cyclic object value"); + } else { + findFlag = true; + } + } + if (typeof tmpSc.get(sentinel) === "undefined") { + step = 0; + } + } + if (typeof filter2 === "function") { + obj = filter2(prefix, obj); + } else if (obj instanceof Date) { + obj = serializeDate(obj); + } else if (generateArrayPrefix === "comma" && isArray3(obj)) { + obj = utils.maybeMap(obj, function(value2) { + if (value2 instanceof Date) { + return serializeDate(value2); + } + return value2; + }); + } + if (obj === null) { + if (strictNullHandling) { + return encoder && !encodeValuesOnly ? encoder(prefix, defaults2.encoder, charset, "key", format) : prefix; + } + obj = ""; + } + if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) { + if (encoder) { + var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults2.encoder, charset, "key", format); + return [formatter(keyValue) + "=" + formatter(encoder(obj, defaults2.encoder, charset, "value", format))]; + } + return [formatter(prefix) + "=" + formatter(String(obj))]; + } + var values = []; + if (typeof obj === "undefined") { + return values; + } + var objKeys; + if (generateArrayPrefix === "comma" && isArray3(obj)) { + if (encodeValuesOnly && encoder) { + obj = utils.maybeMap(obj, encoder); + } + objKeys = [{ value: obj.length > 0 ? obj.join(",") || null : void 0 }]; + } else if (isArray3(filter2)) { + objKeys = filter2; + } else { + var keys2 = Object.keys(obj); + objKeys = sort ? keys2.sort(sort) : keys2; + } + var encodedPrefix = encodeDotInKeys ? String(prefix).replace(/\./g, "%2E") : String(prefix); + var adjustedPrefix = commaRoundTrip && isArray3(obj) && obj.length === 1 ? encodedPrefix + "[]" : encodedPrefix; + if (allowEmptyArrays && isArray3(obj) && obj.length === 0) { + return adjustedPrefix + "[]"; + } + for (var j = 0; j < objKeys.length; ++j) { + var key = objKeys[j]; + var value = typeof key === "object" && key && typeof key.value !== "undefined" ? key.value : obj[key]; + if (skipNulls && value === null) { + continue; + } + var encodedKey = allowDots && encodeDotInKeys ? String(key).replace(/\./g, "%2E") : String(key); + var keyPrefix = isArray3(obj) ? typeof generateArrayPrefix === "function" ? generateArrayPrefix(adjustedPrefix, encodedKey) : adjustedPrefix : adjustedPrefix + (allowDots ? "." + encodedKey : "[" + encodedKey + "]"); + sideChannel.set(object, step); + var valueSideChannel = getSideChannel(); + valueSideChannel.set(sentinel, sideChannel); + pushToArray(values, stringify3( + value, + keyPrefix, + generateArrayPrefix, + commaRoundTrip, + allowEmptyArrays, + strictNullHandling, + skipNulls, + encodeDotInKeys, + generateArrayPrefix === "comma" && encodeValuesOnly && isArray3(obj) ? null : encoder, + filter2, + sort, + allowDots, + serializeDate, + format, + formatter, + encodeValuesOnly, + charset, + valueSideChannel + )); + } + return values; + }; + var normalizeStringifyOptions = function normalizeStringifyOptions2(opts) { + if (!opts) { + return defaults2; + } + if (typeof opts.allowEmptyArrays !== "undefined" && typeof opts.allowEmptyArrays !== "boolean") { + throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided"); + } + if (typeof opts.encodeDotInKeys !== "undefined" && typeof opts.encodeDotInKeys !== "boolean") { + throw new TypeError("`encodeDotInKeys` option can only be `true` or `false`, when provided"); + } + if (opts.encoder !== null && typeof opts.encoder !== "undefined" && typeof opts.encoder !== "function") { + throw new TypeError("Encoder has to be a function."); + } + var charset = opts.charset || defaults2.charset; + if (typeof opts.charset !== "undefined" && opts.charset !== "utf-8" && opts.charset !== "iso-8859-1") { + throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined"); + } + var format = formats["default"]; + if (typeof opts.format !== "undefined") { + if (!has2.call(formats.formatters, opts.format)) { + throw new TypeError("Unknown format option provided."); + } + format = opts.format; + } + var formatter = formats.formatters[format]; + var filter2 = defaults2.filter; + if (typeof opts.filter === "function" || isArray3(opts.filter)) { + filter2 = opts.filter; + } + var arrayFormat; + if (opts.arrayFormat in arrayPrefixGenerators) { + arrayFormat = opts.arrayFormat; + } else if ("indices" in opts) { + arrayFormat = opts.indices ? "indices" : "repeat"; + } else { + arrayFormat = defaults2.arrayFormat; + } + if ("commaRoundTrip" in opts && typeof opts.commaRoundTrip !== "boolean") { + throw new TypeError("`commaRoundTrip` must be a boolean, or absent"); + } + var allowDots = typeof opts.allowDots === "undefined" ? opts.encodeDotInKeys === true ? true : defaults2.allowDots : !!opts.allowDots; + return { + addQueryPrefix: typeof opts.addQueryPrefix === "boolean" ? opts.addQueryPrefix : defaults2.addQueryPrefix, + allowDots, + allowEmptyArrays: typeof opts.allowEmptyArrays === "boolean" ? !!opts.allowEmptyArrays : defaults2.allowEmptyArrays, + arrayFormat, + charset, + charsetSentinel: typeof opts.charsetSentinel === "boolean" ? opts.charsetSentinel : defaults2.charsetSentinel, + commaRoundTrip: !!opts.commaRoundTrip, + delimiter: typeof opts.delimiter === "undefined" ? defaults2.delimiter : opts.delimiter, + encode: typeof opts.encode === "boolean" ? opts.encode : defaults2.encode, + encodeDotInKeys: typeof opts.encodeDotInKeys === "boolean" ? opts.encodeDotInKeys : defaults2.encodeDotInKeys, + encoder: typeof opts.encoder === "function" ? opts.encoder : defaults2.encoder, + encodeValuesOnly: typeof opts.encodeValuesOnly === "boolean" ? opts.encodeValuesOnly : defaults2.encodeValuesOnly, + filter: filter2, + format, + formatter, + serializeDate: typeof opts.serializeDate === "function" ? opts.serializeDate : defaults2.serializeDate, + skipNulls: typeof opts.skipNulls === "boolean" ? opts.skipNulls : defaults2.skipNulls, + sort: typeof opts.sort === "function" ? opts.sort : null, + strictNullHandling: typeof opts.strictNullHandling === "boolean" ? opts.strictNullHandling : defaults2.strictNullHandling + }; + }; + module2.exports = function(object, opts) { + var obj = object; + var options = normalizeStringifyOptions(opts); + var objKeys; + var filter2; + if (typeof options.filter === "function") { + filter2 = options.filter; + obj = filter2("", obj); + } else if (isArray3(options.filter)) { + filter2 = options.filter; + objKeys = filter2; + } + var keys2 = []; + if (typeof obj !== "object" || obj === null) { + return ""; + } + var generateArrayPrefix = arrayPrefixGenerators[options.arrayFormat]; + var commaRoundTrip = generateArrayPrefix === "comma" && options.commaRoundTrip; + if (!objKeys) { + objKeys = Object.keys(obj); + } + if (options.sort) { + objKeys.sort(options.sort); + } + var sideChannel = getSideChannel(); + for (var i = 0; i < objKeys.length; ++i) { + var key = objKeys[i]; + var value = obj[key]; + if (options.skipNulls && value === null) { + continue; + } + pushToArray(keys2, stringify2( + value, + key, + generateArrayPrefix, + commaRoundTrip, + options.allowEmptyArrays, + options.strictNullHandling, + options.skipNulls, + options.encodeDotInKeys, + options.encode ? options.encoder : null, + options.filter, + options.sort, + options.allowDots, + options.serializeDate, + options.format, + options.formatter, + options.encodeValuesOnly, + options.charset, + sideChannel + )); + } + var joined = keys2.join(options.delimiter); + var prefix = options.addQueryPrefix === true ? "?" : ""; + if (options.charsetSentinel) { + if (options.charset === "iso-8859-1") { + prefix += "utf8=%26%2310003%3B&"; + } else { + prefix += "utf8=%E2%9C%93&"; + } + } + return joined.length > 0 ? prefix + joined : ""; + }; + } +}); + +// ../../../node_modules/qs/lib/parse.js +var require_parse = __commonJS({ + "../../../node_modules/qs/lib/parse.js"(exports2, module2) { + "use strict"; + var utils = require_utils(); + var has2 = Object.prototype.hasOwnProperty; + var isArray3 = Array.isArray; + var defaults2 = { + allowDots: false, + allowEmptyArrays: false, + allowPrototypes: false, + allowSparse: false, + arrayLimit: 20, + charset: "utf-8", + charsetSentinel: false, + comma: false, + decodeDotInKeys: false, + decoder: utils.decode, + delimiter: "&", + depth: 5, + duplicates: "combine", + ignoreQueryPrefix: false, + interpretNumericEntities: false, + parameterLimit: 1e3, + parseArrays: true, + plainObjects: false, + strictDepth: false, + strictMerge: true, + strictNullHandling: false, + throwOnLimitExceeded: false + }; + var interpretNumericEntities = function(str) { + return str.replace(/&#(\d+);/g, function($0, numberStr) { + return String.fromCharCode(parseInt(numberStr, 10)); + }); + }; + var parseArrayValue = function(val, options, currentArrayLength) { + if (val && typeof val === "string" && options.comma && val.indexOf(",") > -1) { + return val.split(","); + } + if (options.throwOnLimitExceeded && currentArrayLength >= options.arrayLimit) { + throw new RangeError("Array limit exceeded. Only " + options.arrayLimit + " element" + (options.arrayLimit === 1 ? "" : "s") + " allowed in an array."); + } + return val; + }; + var isoSentinel = "utf8=%26%2310003%3B"; + var charsetSentinel = "utf8=%E2%9C%93"; + var parseValues = function parseQueryStringValues(str, options) { + var obj = { __proto__: null }; + var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, "") : str; + cleanStr = cleanStr.replace(/%5B/gi, "[").replace(/%5D/gi, "]"); + var limit = options.parameterLimit === Infinity ? void 0 : options.parameterLimit; + var parts = cleanStr.split( + options.delimiter, + options.throwOnLimitExceeded ? limit + 1 : limit + ); + if (options.throwOnLimitExceeded && parts.length > limit) { + throw new RangeError("Parameter limit exceeded. Only " + limit + " parameter" + (limit === 1 ? "" : "s") + " allowed."); + } + var skipIndex = -1; + var i; + var charset = options.charset; + if (options.charsetSentinel) { + for (i = 0; i < parts.length; ++i) { + if (parts[i].indexOf("utf8=") === 0) { + if (parts[i] === charsetSentinel) { + charset = "utf-8"; + } else if (parts[i] === isoSentinel) { + charset = "iso-8859-1"; + } + skipIndex = i; + i = parts.length; + } + } + } + for (i = 0; i < parts.length; ++i) { + if (i === skipIndex) { + continue; + } + var part = parts[i]; + var bracketEqualsPos = part.indexOf("]="); + var pos = bracketEqualsPos === -1 ? part.indexOf("=") : bracketEqualsPos + 1; + var key; + var val; + if (pos === -1) { + key = options.decoder(part, defaults2.decoder, charset, "key"); + val = options.strictNullHandling ? null : ""; + } else { + key = options.decoder(part.slice(0, pos), defaults2.decoder, charset, "key"); + if (key !== null) { + val = utils.maybeMap( + parseArrayValue( + part.slice(pos + 1), + options, + isArray3(obj[key]) ? obj[key].length : 0 + ), + function(encodedVal) { + return options.decoder(encodedVal, defaults2.decoder, charset, "value"); + } + ); + } + } + if (val && options.interpretNumericEntities && charset === "iso-8859-1") { + val = interpretNumericEntities(String(val)); + } + if (part.indexOf("[]=") > -1) { + val = isArray3(val) ? [val] : val; + } + if (options.comma && isArray3(val) && val.length > options.arrayLimit) { + if (options.throwOnLimitExceeded) { + throw new RangeError("Array limit exceeded. Only " + options.arrayLimit + " element" + (options.arrayLimit === 1 ? "" : "s") + " allowed in an array."); + } + val = utils.combine([], val, options.arrayLimit, options.plainObjects); + } + if (key !== null) { + var existing = has2.call(obj, key); + if (existing && (options.duplicates === "combine" || part.indexOf("[]=") > -1)) { + obj[key] = utils.combine( + obj[key], + val, + options.arrayLimit, + options.plainObjects + ); + } else if (!existing || options.duplicates === "last") { + obj[key] = val; + } + } + } + return obj; + }; + var parseObject = function(chain, val, options, valuesParsed) { + var currentArrayLength = 0; + if (chain.length > 0 && chain[chain.length - 1] === "[]") { + var parentKey = chain.slice(0, -1).join(""); + currentArrayLength = Array.isArray(val) && val[parentKey] ? val[parentKey].length : 0; + } + var leaf = valuesParsed ? val : parseArrayValue(val, options, currentArrayLength); + for (var i = chain.length - 1; i >= 0; --i) { + var obj; + var root2 = chain[i]; + if (root2 === "[]" && options.parseArrays) { + if (utils.isOverflow(leaf)) { + obj = leaf; + } else { + obj = options.allowEmptyArrays && (leaf === "" || options.strictNullHandling && leaf === null) ? [] : utils.combine( + [], + leaf, + options.arrayLimit, + options.plainObjects + ); + } + } else { + obj = options.plainObjects ? { __proto__: null } : {}; + var cleanRoot = root2.charAt(0) === "[" && root2.charAt(root2.length - 1) === "]" ? root2.slice(1, -1) : root2; + var decodedRoot = options.decodeDotInKeys ? cleanRoot.replace(/%2E/g, ".") : cleanRoot; + var index = parseInt(decodedRoot, 10); + var isValidArrayIndex = !isNaN(index) && root2 !== decodedRoot && String(index) === decodedRoot && index >= 0 && options.parseArrays; + if (!options.parseArrays && decodedRoot === "") { + obj = { 0: leaf }; + } else if (isValidArrayIndex && index < options.arrayLimit) { + obj = []; + obj[index] = leaf; + } else if (isValidArrayIndex && options.throwOnLimitExceeded) { + throw new RangeError("Array limit exceeded. Only " + options.arrayLimit + " element" + (options.arrayLimit === 1 ? "" : "s") + " allowed in an array."); + } else if (isValidArrayIndex) { + obj[index] = leaf; + utils.markOverflow(obj, index); + } else if (decodedRoot !== "__proto__") { + obj[decodedRoot] = leaf; + } + } + leaf = obj; + } + return leaf; + }; + var splitKeyIntoSegments = function splitKeyIntoSegments2(givenKey, options) { + var key = options.allowDots ? givenKey.replace(/\.([^.[]+)/g, "[$1]") : givenKey; + if (options.depth <= 0) { + if (!options.plainObjects && has2.call(Object.prototype, key)) { + if (!options.allowPrototypes) { + return; + } + } + return [key]; + } + var brackets = /(\[[^[\]]*])/; + var child = /(\[[^[\]]*])/g; + var segment = brackets.exec(key); + var parent = segment ? key.slice(0, segment.index) : key; + var keys2 = []; + if (parent) { + if (!options.plainObjects && has2.call(Object.prototype, parent)) { + if (!options.allowPrototypes) { + return; + } + } + keys2[keys2.length] = parent; + } + var i = 0; + while ((segment = child.exec(key)) !== null && i < options.depth) { + i += 1; + var segmentContent = segment[1].slice(1, -1); + if (!options.plainObjects && has2.call(Object.prototype, segmentContent)) { + if (!options.allowPrototypes) { + return; + } + } + keys2[keys2.length] = segment[1]; + } + if (segment) { + if (options.strictDepth === true) { + throw new RangeError("Input depth exceeded depth option of " + options.depth + " and strictDepth is true"); + } + keys2[keys2.length] = "[" + key.slice(segment.index) + "]"; + } + return keys2; + }; + var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesParsed) { + if (!givenKey) { + return; + } + var keys2 = splitKeyIntoSegments(givenKey, options); + if (!keys2) { + return; + } + return parseObject(keys2, val, options, valuesParsed); + }; + var normalizeParseOptions = function normalizeParseOptions2(opts) { + if (!opts) { + return defaults2; + } + if (typeof opts.allowEmptyArrays !== "undefined" && typeof opts.allowEmptyArrays !== "boolean") { + throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided"); + } + if (typeof opts.decodeDotInKeys !== "undefined" && typeof opts.decodeDotInKeys !== "boolean") { + throw new TypeError("`decodeDotInKeys` option can only be `true` or `false`, when provided"); + } + if (opts.decoder !== null && typeof opts.decoder !== "undefined" && typeof opts.decoder !== "function") { + throw new TypeError("Decoder has to be a function."); + } + if (typeof opts.charset !== "undefined" && opts.charset !== "utf-8" && opts.charset !== "iso-8859-1") { + throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined"); + } + if (typeof opts.throwOnLimitExceeded !== "undefined" && typeof opts.throwOnLimitExceeded !== "boolean") { + throw new TypeError("`throwOnLimitExceeded` option must be a boolean"); + } + var charset = typeof opts.charset === "undefined" ? defaults2.charset : opts.charset; + var duplicates = typeof opts.duplicates === "undefined" ? defaults2.duplicates : opts.duplicates; + if (duplicates !== "combine" && duplicates !== "first" && duplicates !== "last") { + throw new TypeError("The duplicates option must be either combine, first, or last"); + } + var allowDots = typeof opts.allowDots === "undefined" ? opts.decodeDotInKeys === true ? true : defaults2.allowDots : !!opts.allowDots; + return { + allowDots, + allowEmptyArrays: typeof opts.allowEmptyArrays === "boolean" ? !!opts.allowEmptyArrays : defaults2.allowEmptyArrays, + allowPrototypes: typeof opts.allowPrototypes === "boolean" ? opts.allowPrototypes : defaults2.allowPrototypes, + allowSparse: typeof opts.allowSparse === "boolean" ? opts.allowSparse : defaults2.allowSparse, + arrayLimit: typeof opts.arrayLimit === "number" ? opts.arrayLimit : defaults2.arrayLimit, + charset, + charsetSentinel: typeof opts.charsetSentinel === "boolean" ? opts.charsetSentinel : defaults2.charsetSentinel, + comma: typeof opts.comma === "boolean" ? opts.comma : defaults2.comma, + decodeDotInKeys: typeof opts.decodeDotInKeys === "boolean" ? opts.decodeDotInKeys : defaults2.decodeDotInKeys, + decoder: typeof opts.decoder === "function" ? opts.decoder : defaults2.decoder, + delimiter: typeof opts.delimiter === "string" || utils.isRegExp(opts.delimiter) ? opts.delimiter : defaults2.delimiter, + // eslint-disable-next-line no-implicit-coercion, no-extra-parens + depth: typeof opts.depth === "number" || opts.depth === false ? +opts.depth : defaults2.depth, + duplicates, + ignoreQueryPrefix: opts.ignoreQueryPrefix === true, + interpretNumericEntities: typeof opts.interpretNumericEntities === "boolean" ? opts.interpretNumericEntities : defaults2.interpretNumericEntities, + parameterLimit: typeof opts.parameterLimit === "number" ? opts.parameterLimit : defaults2.parameterLimit, + parseArrays: opts.parseArrays !== false, + plainObjects: typeof opts.plainObjects === "boolean" ? opts.plainObjects : defaults2.plainObjects, + strictDepth: typeof opts.strictDepth === "boolean" ? !!opts.strictDepth : defaults2.strictDepth, + strictMerge: typeof opts.strictMerge === "boolean" ? !!opts.strictMerge : defaults2.strictMerge, + strictNullHandling: typeof opts.strictNullHandling === "boolean" ? opts.strictNullHandling : defaults2.strictNullHandling, + throwOnLimitExceeded: typeof opts.throwOnLimitExceeded === "boolean" ? opts.throwOnLimitExceeded : false + }; + }; + module2.exports = function(str, opts) { + var options = normalizeParseOptions(opts); + if (str === "" || str === null || typeof str === "undefined") { + return options.plainObjects ? { __proto__: null } : {}; + } + var tempObj = typeof str === "string" ? parseValues(str, options) : str; + var obj = options.plainObjects ? { __proto__: null } : {}; + var keys2 = Object.keys(tempObj); + for (var i = 0; i < keys2.length; ++i) { + var key = keys2[i]; + var newObj = parseKeys(key, tempObj[key], options, typeof str === "string"); + obj = utils.merge(obj, newObj, options); + } + if (options.allowSparse === true) { + return obj; + } + return utils.compact(obj); + }; + } +}); + +// ../../../node_modules/qs/lib/index.js +var require_lib = __commonJS({ + "../../../node_modules/qs/lib/index.js"(exports2, module2) { + "use strict"; + var stringify2 = require_stringify(); + var parse2 = require_parse(); + var formats = require_formats(); + module2.exports = { + formats, + parse: parse2, + stringify: stringify2 + }; + } +}); + +// ../../../node_modules/lodash-es/_freeGlobal.js +var freeGlobal = typeof global == "object" && global && global.Object === Object && global; +var freeGlobal_default = freeGlobal; + +// ../../../node_modules/lodash-es/_root.js +var freeSelf = typeof self == "object" && self && self.Object === Object && self; +var root = freeGlobal_default || freeSelf || Function("return this")(); +var root_default = root; + +// ../../../node_modules/lodash-es/_Symbol.js +var Symbol2 = root_default.Symbol; +var Symbol_default = Symbol2; + +// ../../../node_modules/lodash-es/_getRawTag.js +var objectProto = Object.prototype; +var hasOwnProperty = objectProto.hasOwnProperty; +var nativeObjectToString = objectProto.toString; +var symToStringTag = Symbol_default ? Symbol_default.toStringTag : void 0; +function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), tag = value[symToStringTag]; + try { + value[symToStringTag] = void 0; + var unmasked = true; + } catch (e) { + } + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; +} +var getRawTag_default = getRawTag; + +// ../../../node_modules/lodash-es/_objectToString.js +var objectProto2 = Object.prototype; +var nativeObjectToString2 = objectProto2.toString; +function objectToString(value) { + return nativeObjectToString2.call(value); +} +var objectToString_default = objectToString; + +// ../../../node_modules/lodash-es/_baseGetTag.js +var nullTag = "[object Null]"; +var undefinedTag = "[object Undefined]"; +var symToStringTag2 = Symbol_default ? Symbol_default.toStringTag : void 0; +function baseGetTag(value) { + if (value == null) { + return value === void 0 ? undefinedTag : nullTag; + } + return symToStringTag2 && symToStringTag2 in Object(value) ? getRawTag_default(value) : objectToString_default(value); +} +var baseGetTag_default = baseGetTag; + +// ../../../node_modules/lodash-es/isObjectLike.js +function isObjectLike(value) { + return value != null && typeof value == "object"; +} +var isObjectLike_default = isObjectLike; + +// ../../../node_modules/lodash-es/isSymbol.js +var symbolTag = "[object Symbol]"; +function isSymbol(value) { + return typeof value == "symbol" || isObjectLike_default(value) && baseGetTag_default(value) == symbolTag; +} +var isSymbol_default = isSymbol; + +// ../../../node_modules/lodash-es/_arrayMap.js +function arrayMap(array, iteratee) { + var index = -1, length = array == null ? 0 : array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; +} +var arrayMap_default = arrayMap; + +// ../../../node_modules/lodash-es/isArray.js +var isArray = Array.isArray; +var isArray_default = isArray; + +// ../../../node_modules/lodash-es/_baseToString.js +var INFINITY = 1 / 0; +var symbolProto = Symbol_default ? Symbol_default.prototype : void 0; +var symbolToString = symbolProto ? symbolProto.toString : void 0; +function baseToString(value) { + if (typeof value == "string") { + return value; + } + if (isArray_default(value)) { + return arrayMap_default(value, baseToString) + ""; + } + if (isSymbol_default(value)) { + return symbolToString ? symbolToString.call(value) : ""; + } + var result = value + ""; + return result == "0" && 1 / value == -INFINITY ? "-0" : result; +} +var baseToString_default = baseToString; + +// ../../../node_modules/lodash-es/_trimmedEndIndex.js +var reWhitespace = /\s/; +function trimmedEndIndex(string) { + var index = string.length; + while (index-- && reWhitespace.test(string.charAt(index))) { + } + return index; +} +var trimmedEndIndex_default = trimmedEndIndex; + +// ../../../node_modules/lodash-es/_baseTrim.js +var reTrimStart = /^\s+/; +function baseTrim(string) { + return string ? string.slice(0, trimmedEndIndex_default(string) + 1).replace(reTrimStart, "") : string; +} +var baseTrim_default = baseTrim; + +// ../../../node_modules/lodash-es/isObject.js +function isObject(value) { + var type = typeof value; + return value != null && (type == "object" || type == "function"); +} +var isObject_default = isObject; + +// ../../../node_modules/lodash-es/toNumber.js +var NAN = 0 / 0; +var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; +var reIsBinary = /^0b[01]+$/i; +var reIsOctal = /^0o[0-7]+$/i; +var freeParseInt = parseInt; +function toNumber(value) { + if (typeof value == "number") { + return value; + } + if (isSymbol_default(value)) { + return NAN; + } + if (isObject_default(value)) { + var other = typeof value.valueOf == "function" ? value.valueOf() : value; + value = isObject_default(other) ? other + "" : other; + } + if (typeof value != "string") { + return value === 0 ? value : +value; + } + value = baseTrim_default(value); + var isBinary = reIsBinary.test(value); + return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value; +} +var toNumber_default = toNumber; + +// ../../../node_modules/lodash-es/identity.js +function identity(value) { + return value; +} +var identity_default = identity; + +// ../../../node_modules/lodash-es/isFunction.js +var asyncTag = "[object AsyncFunction]"; +var funcTag = "[object Function]"; +var genTag = "[object GeneratorFunction]"; +var proxyTag = "[object Proxy]"; +function isFunction(value) { + if (!isObject_default(value)) { + return false; + } + var tag = baseGetTag_default(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; +} +var isFunction_default = isFunction; + +// ../../../node_modules/lodash-es/_coreJsData.js +var coreJsData = root_default["__core-js_shared__"]; +var coreJsData_default = coreJsData; + +// ../../../node_modules/lodash-es/_isMasked.js +var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData_default && coreJsData_default.keys && coreJsData_default.keys.IE_PROTO || ""); + return uid ? "Symbol(src)_1." + uid : ""; +})(); +function isMasked(func) { + return !!maskSrcKey && maskSrcKey in func; +} +var isMasked_default = isMasked; + +// ../../../node_modules/lodash-es/_toSource.js +var funcProto = Function.prototype; +var funcToString = funcProto.toString; +function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) { + } + try { + return func + ""; + } catch (e) { + } + } + return ""; +} +var toSource_default = toSource; + +// ../../../node_modules/lodash-es/_baseIsNative.js +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; +var reIsHostCtor = /^\[object .+?Constructor\]$/; +var funcProto2 = Function.prototype; +var objectProto3 = Object.prototype; +var funcToString2 = funcProto2.toString; +var hasOwnProperty2 = objectProto3.hasOwnProperty; +var reIsNative = RegExp( + "^" + funcToString2.call(hasOwnProperty2).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$" +); +function baseIsNative(value) { + if (!isObject_default(value) || isMasked_default(value)) { + return false; + } + var pattern = isFunction_default(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource_default(value)); +} +var baseIsNative_default = baseIsNative; + +// ../../../node_modules/lodash-es/_getValue.js +function getValue(object, key) { + return object == null ? void 0 : object[key]; +} +var getValue_default = getValue; + +// ../../../node_modules/lodash-es/_getNative.js +function getNative(object, key) { + var value = getValue_default(object, key); + return baseIsNative_default(value) ? value : void 0; +} +var getNative_default = getNative; + +// ../../../node_modules/lodash-es/_WeakMap.js +var WeakMap2 = getNative_default(root_default, "WeakMap"); +var WeakMap_default = WeakMap2; + +// ../../../node_modules/lodash-es/_baseCreate.js +var objectCreate = Object.create; +var baseCreate = /* @__PURE__ */ (function() { + function object() { + } + return function(proto) { + if (!isObject_default(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object(); + object.prototype = void 0; + return result; + }; +})(); +var baseCreate_default = baseCreate; + +// ../../../node_modules/lodash-es/_apply.js +function apply(func, thisArg, args) { + switch (args.length) { + case 0: + return func.call(thisArg); + case 1: + return func.call(thisArg, args[0]); + case 2: + return func.call(thisArg, args[0], args[1]); + case 3: + return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); +} +var apply_default = apply; + +// ../../../node_modules/lodash-es/_copyArray.js +function copyArray(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; +} +var copyArray_default = copyArray; + +// ../../../node_modules/lodash-es/_shortOut.js +var HOT_COUNT = 800; +var HOT_SPAN = 16; +var nativeNow = Date.now; +function shortOut(func) { + var count = 0, lastCalled = 0; + return function() { + var stamp = nativeNow(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(void 0, arguments); + }; +} +var shortOut_default = shortOut; + +// ../../../node_modules/lodash-es/constant.js +function constant(value) { + return function() { + return value; + }; +} +var constant_default = constant; + +// ../../../node_modules/lodash-es/_defineProperty.js +var defineProperty = (function() { + try { + var func = getNative_default(Object, "defineProperty"); + func({}, "", {}); + return func; + } catch (e) { + } +})(); +var defineProperty_default = defineProperty; + +// ../../../node_modules/lodash-es/_baseSetToString.js +var baseSetToString = !defineProperty_default ? identity_default : function(func, string) { + return defineProperty_default(func, "toString", { + "configurable": true, + "enumerable": false, + "value": constant_default(string), + "writable": true + }); +}; +var baseSetToString_default = baseSetToString; + +// ../../../node_modules/lodash-es/_setToString.js +var setToString = shortOut_default(baseSetToString_default); +var setToString_default = setToString; + +// ../../../node_modules/lodash-es/_arrayEach.js +function arrayEach(array, iteratee) { + var index = -1, length = array == null ? 0 : array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; +} +var arrayEach_default = arrayEach; + +// ../../../node_modules/lodash-es/_isIndex.js +var MAX_SAFE_INTEGER = 9007199254740991; +var reIsUint = /^(?:0|[1-9]\d*)$/; +function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + return !!length && (type == "number" || type != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length); +} +var isIndex_default = isIndex; + +// ../../../node_modules/lodash-es/_baseAssignValue.js +function baseAssignValue(object, key, value) { + if (key == "__proto__" && defineProperty_default) { + defineProperty_default(object, key, { + "configurable": true, + "enumerable": true, + "value": value, + "writable": true + }); + } else { + object[key] = value; + } +} +var baseAssignValue_default = baseAssignValue; + +// ../../../node_modules/lodash-es/eq.js +function eq(value, other) { + return value === other || value !== value && other !== other; +} +var eq_default = eq; + +// ../../../node_modules/lodash-es/_assignValue.js +var objectProto4 = Object.prototype; +var hasOwnProperty3 = objectProto4.hasOwnProperty; +function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty3.call(object, key) && eq_default(objValue, value)) || value === void 0 && !(key in object)) { + baseAssignValue_default(object, key, value); + } +} +var assignValue_default = assignValue; + +// ../../../node_modules/lodash-es/_copyObject.js +function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + var newValue = customizer ? customizer(object[key], source[key], key, object, source) : void 0; + if (newValue === void 0) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue_default(object, key, newValue); + } else { + assignValue_default(object, key, newValue); + } + } + return object; +} +var copyObject_default = copyObject; + +// ../../../node_modules/lodash-es/_overRest.js +var nativeMax = Math.max; +function overRest(func, start2, transform) { + start2 = nativeMax(start2 === void 0 ? func.length - 1 : start2, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start2, 0), array = Array(length); + while (++index < length) { + array[index] = args[start2 + index]; + } + index = -1; + var otherArgs = Array(start2 + 1); + while (++index < start2) { + otherArgs[index] = args[index]; + } + otherArgs[start2] = transform(array); + return apply_default(func, this, otherArgs); + }; +} +var overRest_default = overRest; + +// ../../../node_modules/lodash-es/_baseRest.js +function baseRest(func, start2) { + return setToString_default(overRest_default(func, start2, identity_default), func + ""); +} +var baseRest_default = baseRest; + +// ../../../node_modules/lodash-es/isLength.js +var MAX_SAFE_INTEGER2 = 9007199254740991; +function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER2; +} +var isLength_default = isLength; + +// ../../../node_modules/lodash-es/isArrayLike.js +function isArrayLike(value) { + return value != null && isLength_default(value.length) && !isFunction_default(value); +} +var isArrayLike_default = isArrayLike; + +// ../../../node_modules/lodash-es/_isIterateeCall.js +function isIterateeCall(value, index, object) { + if (!isObject_default(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike_default(object) && isIndex_default(index, object.length) : type == "string" && index in object) { + return eq_default(object[index], value); + } + return false; +} +var isIterateeCall_default = isIterateeCall; + +// ../../../node_modules/lodash-es/_createAssigner.js +function createAssigner(assigner) { + return baseRest_default(function(object, sources) { + var index = -1, length = sources.length, customizer = length > 1 ? sources[length - 1] : void 0, guard = length > 2 ? sources[2] : void 0; + customizer = assigner.length > 3 && typeof customizer == "function" ? (length--, customizer) : void 0; + if (guard && isIterateeCall_default(sources[0], sources[1], guard)) { + customizer = length < 3 ? void 0 : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); +} +var createAssigner_default = createAssigner; + +// ../../../node_modules/lodash-es/_isPrototype.js +var objectProto5 = Object.prototype; +function isPrototype(value) { + var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto5; + return value === proto; +} +var isPrototype_default = isPrototype; + +// ../../../node_modules/lodash-es/_baseTimes.js +function baseTimes(n, iteratee) { + var index = -1, result = Array(n); + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} +var baseTimes_default = baseTimes; + +// ../../../node_modules/lodash-es/_baseIsArguments.js +var argsTag = "[object Arguments]"; +function baseIsArguments(value) { + return isObjectLike_default(value) && baseGetTag_default(value) == argsTag; +} +var baseIsArguments_default = baseIsArguments; + +// ../../../node_modules/lodash-es/isArguments.js +var objectProto6 = Object.prototype; +var hasOwnProperty4 = objectProto6.hasOwnProperty; +var propertyIsEnumerable = objectProto6.propertyIsEnumerable; +var isArguments = baseIsArguments_default(/* @__PURE__ */ (function() { + return arguments; +})()) ? baseIsArguments_default : function(value) { + return isObjectLike_default(value) && hasOwnProperty4.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); +}; +var isArguments_default = isArguments; + +// ../../../node_modules/lodash-es/stubFalse.js +function stubFalse() { + return false; +} +var stubFalse_default = stubFalse; + +// ../../../node_modules/lodash-es/isBuffer.js +var freeExports = typeof exports == "object" && exports && !exports.nodeType && exports; +var freeModule = freeExports && typeof module == "object" && module && !module.nodeType && module; +var moduleExports = freeModule && freeModule.exports === freeExports; +var Buffer2 = moduleExports ? root_default.Buffer : void 0; +var nativeIsBuffer = Buffer2 ? Buffer2.isBuffer : void 0; +var isBuffer = nativeIsBuffer || stubFalse_default; +var isBuffer_default = isBuffer; + +// ../../../node_modules/lodash-es/_baseIsTypedArray.js +var argsTag2 = "[object Arguments]"; +var arrayTag = "[object Array]"; +var boolTag = "[object Boolean]"; +var dateTag = "[object Date]"; +var errorTag = "[object Error]"; +var funcTag2 = "[object Function]"; +var mapTag = "[object Map]"; +var numberTag = "[object Number]"; +var objectTag = "[object Object]"; +var regexpTag = "[object RegExp]"; +var setTag = "[object Set]"; +var stringTag = "[object String]"; +var weakMapTag = "[object WeakMap]"; +var arrayBufferTag = "[object ArrayBuffer]"; +var dataViewTag = "[object DataView]"; +var float32Tag = "[object Float32Array]"; +var float64Tag = "[object Float64Array]"; +var int8Tag = "[object Int8Array]"; +var int16Tag = "[object Int16Array]"; +var int32Tag = "[object Int32Array]"; +var uint8Tag = "[object Uint8Array]"; +var uint8ClampedTag = "[object Uint8ClampedArray]"; +var uint16Tag = "[object Uint16Array]"; +var uint32Tag = "[object Uint32Array]"; +var typedArrayTags = {}; +typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; +typedArrayTags[argsTag2] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag2] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; +function baseIsTypedArray(value) { + return isObjectLike_default(value) && isLength_default(value.length) && !!typedArrayTags[baseGetTag_default(value)]; +} +var baseIsTypedArray_default = baseIsTypedArray; + +// ../../../node_modules/lodash-es/_baseUnary.js +function baseUnary(func) { + return function(value) { + return func(value); + }; +} +var baseUnary_default = baseUnary; + +// ../../../node_modules/lodash-es/_nodeUtil.js +var freeExports2 = typeof exports == "object" && exports && !exports.nodeType && exports; +var freeModule2 = freeExports2 && typeof module == "object" && module && !module.nodeType && module; +var moduleExports2 = freeModule2 && freeModule2.exports === freeExports2; +var freeProcess = moduleExports2 && freeGlobal_default.process; +var nodeUtil = (function() { + try { + var types = freeModule2 && freeModule2.require && freeModule2.require("util").types; + if (types) { + return types; + } + return freeProcess && freeProcess.binding && freeProcess.binding("util"); + } catch (e) { + } +})(); +var nodeUtil_default = nodeUtil; + +// ../../../node_modules/lodash-es/isTypedArray.js +var nodeIsTypedArray = nodeUtil_default && nodeUtil_default.isTypedArray; +var isTypedArray = nodeIsTypedArray ? baseUnary_default(nodeIsTypedArray) : baseIsTypedArray_default; +var isTypedArray_default = isTypedArray; + +// ../../../node_modules/lodash-es/_arrayLikeKeys.js +var objectProto7 = Object.prototype; +var hasOwnProperty5 = objectProto7.hasOwnProperty; +function arrayLikeKeys(value, inherited) { + var isArr = isArray_default(value), isArg = !isArr && isArguments_default(value), isBuff = !isArr && !isArg && isBuffer_default(value), isType = !isArr && !isArg && !isBuff && isTypedArray_default(value), skipIndexes = isArr || isArg || isBuff || isType, result = skipIndexes ? baseTimes_default(value.length, String) : [], length = result.length; + for (var key in value) { + if ((inherited || hasOwnProperty5.call(value, key)) && !(skipIndexes && // Safari 9 has enumerable `arguments.length` in strict mode. + (key == "length" || // Node.js 0.10 has enumerable non-index properties on buffers. + isBuff && (key == "offset" || key == "parent") || // PhantomJS 2 has enumerable non-index properties on typed arrays. + isType && (key == "buffer" || key == "byteLength" || key == "byteOffset") || // Skip index properties. + isIndex_default(key, length)))) { + result.push(key); + } + } + return result; +} +var arrayLikeKeys_default = arrayLikeKeys; + +// ../../../node_modules/lodash-es/_overArg.js +function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; +} +var overArg_default = overArg; + +// ../../../node_modules/lodash-es/_nativeKeys.js +var nativeKeys = overArg_default(Object.keys, Object); +var nativeKeys_default = nativeKeys; + +// ../../../node_modules/lodash-es/_baseKeys.js +var objectProto8 = Object.prototype; +var hasOwnProperty6 = objectProto8.hasOwnProperty; +function baseKeys(object) { + if (!isPrototype_default(object)) { + return nativeKeys_default(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty6.call(object, key) && key != "constructor") { + result.push(key); + } + } + return result; +} +var baseKeys_default = baseKeys; + +// ../../../node_modules/lodash-es/keys.js +function keys(object) { + return isArrayLike_default(object) ? arrayLikeKeys_default(object) : baseKeys_default(object); +} +var keys_default = keys; + +// ../../../node_modules/lodash-es/_nativeKeysIn.js +function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; +} +var nativeKeysIn_default = nativeKeysIn; + +// ../../../node_modules/lodash-es/_baseKeysIn.js +var objectProto9 = Object.prototype; +var hasOwnProperty7 = objectProto9.hasOwnProperty; +function baseKeysIn(object) { + if (!isObject_default(object)) { + return nativeKeysIn_default(object); + } + var isProto = isPrototype_default(object), result = []; + for (var key in object) { + if (!(key == "constructor" && (isProto || !hasOwnProperty7.call(object, key)))) { + result.push(key); + } + } + return result; +} +var baseKeysIn_default = baseKeysIn; + +// ../../../node_modules/lodash-es/keysIn.js +function keysIn(object) { + return isArrayLike_default(object) ? arrayLikeKeys_default(object, true) : baseKeysIn_default(object); +} +var keysIn_default = keysIn; + +// ../../../node_modules/lodash-es/_isKey.js +var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; +var reIsPlainProp = /^\w*$/; +function isKey(value, object) { + if (isArray_default(value)) { + return false; + } + var type = typeof value; + if (type == "number" || type == "symbol" || type == "boolean" || value == null || isSymbol_default(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object(object); +} +var isKey_default = isKey; + +// ../../../node_modules/lodash-es/_nativeCreate.js +var nativeCreate = getNative_default(Object, "create"); +var nativeCreate_default = nativeCreate; + +// ../../../node_modules/lodash-es/_hashClear.js +function hashClear() { + this.__data__ = nativeCreate_default ? nativeCreate_default(null) : {}; + this.size = 0; +} +var hashClear_default = hashClear; + +// ../../../node_modules/lodash-es/_hashDelete.js +function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; +} +var hashDelete_default = hashDelete; + +// ../../../node_modules/lodash-es/_hashGet.js +var HASH_UNDEFINED = "__lodash_hash_undefined__"; +var objectProto10 = Object.prototype; +var hasOwnProperty8 = objectProto10.hasOwnProperty; +function hashGet(key) { + var data = this.__data__; + if (nativeCreate_default) { + var result = data[key]; + return result === HASH_UNDEFINED ? void 0 : result; + } + return hasOwnProperty8.call(data, key) ? data[key] : void 0; +} +var hashGet_default = hashGet; + +// ../../../node_modules/lodash-es/_hashHas.js +var objectProto11 = Object.prototype; +var hasOwnProperty9 = objectProto11.hasOwnProperty; +function hashHas(key) { + var data = this.__data__; + return nativeCreate_default ? data[key] !== void 0 : hasOwnProperty9.call(data, key); +} +var hashHas_default = hashHas; + +// ../../../node_modules/lodash-es/_hashSet.js +var HASH_UNDEFINED2 = "__lodash_hash_undefined__"; +function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = nativeCreate_default && value === void 0 ? HASH_UNDEFINED2 : value; + return this; +} +var hashSet_default = hashSet; + +// ../../../node_modules/lodash-es/_Hash.js +function Hash(entries) { + var index = -1, length = entries == null ? 0 : entries.length; + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} +Hash.prototype.clear = hashClear_default; +Hash.prototype["delete"] = hashDelete_default; +Hash.prototype.get = hashGet_default; +Hash.prototype.has = hashHas_default; +Hash.prototype.set = hashSet_default; +var Hash_default = Hash; + +// ../../../node_modules/lodash-es/_listCacheClear.js +function listCacheClear() { + this.__data__ = []; + this.size = 0; +} +var listCacheClear_default = listCacheClear; + +// ../../../node_modules/lodash-es/_assocIndexOf.js +function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq_default(array[length][0], key)) { + return length; + } + } + return -1; +} +var assocIndexOf_default = assocIndexOf; + +// ../../../node_modules/lodash-es/_listCacheDelete.js +var arrayProto = Array.prototype; +var splice = arrayProto.splice; +function listCacheDelete(key) { + var data = this.__data__, index = assocIndexOf_default(data, key); + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; +} +var listCacheDelete_default = listCacheDelete; + +// ../../../node_modules/lodash-es/_listCacheGet.js +function listCacheGet(key) { + var data = this.__data__, index = assocIndexOf_default(data, key); + return index < 0 ? void 0 : data[index][1]; +} +var listCacheGet_default = listCacheGet; + +// ../../../node_modules/lodash-es/_listCacheHas.js +function listCacheHas(key) { + return assocIndexOf_default(this.__data__, key) > -1; +} +var listCacheHas_default = listCacheHas; + +// ../../../node_modules/lodash-es/_listCacheSet.js +function listCacheSet(key, value) { + var data = this.__data__, index = assocIndexOf_default(data, key); + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; +} +var listCacheSet_default = listCacheSet; + +// ../../../node_modules/lodash-es/_ListCache.js +function ListCache(entries) { + var index = -1, length = entries == null ? 0 : entries.length; + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} +ListCache.prototype.clear = listCacheClear_default; +ListCache.prototype["delete"] = listCacheDelete_default; +ListCache.prototype.get = listCacheGet_default; +ListCache.prototype.has = listCacheHas_default; +ListCache.prototype.set = listCacheSet_default; +var ListCache_default = ListCache; + +// ../../../node_modules/lodash-es/_Map.js +var Map2 = getNative_default(root_default, "Map"); +var Map_default = Map2; + +// ../../../node_modules/lodash-es/_mapCacheClear.js +function mapCacheClear() { + this.size = 0; + this.__data__ = { + "hash": new Hash_default(), + "map": new (Map_default || ListCache_default)(), + "string": new Hash_default() + }; +} +var mapCacheClear_default = mapCacheClear; + +// ../../../node_modules/lodash-es/_isKeyable.js +function isKeyable(value) { + var type = typeof value; + return type == "string" || type == "number" || type == "symbol" || type == "boolean" ? value !== "__proto__" : value === null; +} +var isKeyable_default = isKeyable; + +// ../../../node_modules/lodash-es/_getMapData.js +function getMapData(map, key) { + var data = map.__data__; + return isKeyable_default(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map; +} +var getMapData_default = getMapData; + +// ../../../node_modules/lodash-es/_mapCacheDelete.js +function mapCacheDelete(key) { + var result = getMapData_default(this, key)["delete"](key); + this.size -= result ? 1 : 0; + return result; +} +var mapCacheDelete_default = mapCacheDelete; + +// ../../../node_modules/lodash-es/_mapCacheGet.js +function mapCacheGet(key) { + return getMapData_default(this, key).get(key); +} +var mapCacheGet_default = mapCacheGet; + +// ../../../node_modules/lodash-es/_mapCacheHas.js +function mapCacheHas(key) { + return getMapData_default(this, key).has(key); +} +var mapCacheHas_default = mapCacheHas; + +// ../../../node_modules/lodash-es/_mapCacheSet.js +function mapCacheSet(key, value) { + var data = getMapData_default(this, key), size = data.size; + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; +} +var mapCacheSet_default = mapCacheSet; + +// ../../../node_modules/lodash-es/_MapCache.js +function MapCache(entries) { + var index = -1, length = entries == null ? 0 : entries.length; + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} +MapCache.prototype.clear = mapCacheClear_default; +MapCache.prototype["delete"] = mapCacheDelete_default; +MapCache.prototype.get = mapCacheGet_default; +MapCache.prototype.has = mapCacheHas_default; +MapCache.prototype.set = mapCacheSet_default; +var MapCache_default = MapCache; + +// ../../../node_modules/lodash-es/memoize.js +var FUNC_ERROR_TEXT = "Expected a function"; +function memoize(func, resolver) { + if (typeof func != "function" || resolver != null && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result) || cache; + return result; + }; + memoized.cache = new (memoize.Cache || MapCache_default)(); + return memoized; +} +memoize.Cache = MapCache_default; +var memoize_default = memoize; + +// ../../../node_modules/lodash-es/_memoizeCapped.js +var MAX_MEMOIZE_SIZE = 500; +function memoizeCapped(func) { + var result = memoize_default(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + var cache = result.cache; + return result; +} +var memoizeCapped_default = memoizeCapped; + +// ../../../node_modules/lodash-es/_stringToPath.js +var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; +var reEscapeChar = /\\(\\)?/g; +var stringToPath = memoizeCapped_default(function(string) { + var result = []; + if (string.charCodeAt(0) === 46) { + result.push(""); + } + string.replace(rePropName, function(match, number, quote, subString) { + result.push(quote ? subString.replace(reEscapeChar, "$1") : number || match); + }); + return result; +}); +var stringToPath_default = stringToPath; + +// ../../../node_modules/lodash-es/toString.js +function toString(value) { + return value == null ? "" : baseToString_default(value); +} +var toString_default = toString; + +// ../../../node_modules/lodash-es/_castPath.js +function castPath(value, object) { + if (isArray_default(value)) { + return value; + } + return isKey_default(value, object) ? [value] : stringToPath_default(toString_default(value)); +} +var castPath_default = castPath; + +// ../../../node_modules/lodash-es/_toKey.js +var INFINITY2 = 1 / 0; +function toKey(value) { + if (typeof value == "string" || isSymbol_default(value)) { + return value; + } + var result = value + ""; + return result == "0" && 1 / value == -INFINITY2 ? "-0" : result; +} +var toKey_default = toKey; + +// ../../../node_modules/lodash-es/_baseGet.js +function baseGet(object, path) { + path = castPath_default(path, object); + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[toKey_default(path[index++])]; + } + return index && index == length ? object : void 0; +} +var baseGet_default = baseGet; + +// ../../../node_modules/lodash-es/get.js +function get(object, path, defaultValue) { + var result = object == null ? void 0 : baseGet_default(object, path); + return result === void 0 ? defaultValue : result; +} +var get_default = get; + +// ../../../node_modules/lodash-es/_arrayPush.js +function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; +} +var arrayPush_default = arrayPush; + +// ../../../node_modules/lodash-es/_getPrototype.js +var getPrototype = overArg_default(Object.getPrototypeOf, Object); +var getPrototype_default = getPrototype; + +// ../../../node_modules/lodash-es/isPlainObject.js +var objectTag2 = "[object Object]"; +var funcProto3 = Function.prototype; +var objectProto12 = Object.prototype; +var funcToString3 = funcProto3.toString; +var hasOwnProperty10 = objectProto12.hasOwnProperty; +var objectCtorString = funcToString3.call(Object); +function isPlainObject(value) { + if (!isObjectLike_default(value) || baseGetTag_default(value) != objectTag2) { + return false; + } + var proto = getPrototype_default(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty10.call(proto, "constructor") && proto.constructor; + return typeof Ctor == "function" && Ctor instanceof Ctor && funcToString3.call(Ctor) == objectCtorString; +} +var isPlainObject_default = isPlainObject; + +// ../../../node_modules/lodash-es/_basePropertyOf.js +function basePropertyOf(object) { + return function(key) { + return object == null ? void 0 : object[key]; + }; +} +var basePropertyOf_default = basePropertyOf; + +// ../../../node_modules/lodash-es/_stackClear.js +function stackClear() { + this.__data__ = new ListCache_default(); + this.size = 0; +} +var stackClear_default = stackClear; + +// ../../../node_modules/lodash-es/_stackDelete.js +function stackDelete(key) { + var data = this.__data__, result = data["delete"](key); + this.size = data.size; + return result; +} +var stackDelete_default = stackDelete; + +// ../../../node_modules/lodash-es/_stackGet.js +function stackGet(key) { + return this.__data__.get(key); +} +var stackGet_default = stackGet; + +// ../../../node_modules/lodash-es/_stackHas.js +function stackHas(key) { + return this.__data__.has(key); +} +var stackHas_default = stackHas; + +// ../../../node_modules/lodash-es/_stackSet.js +var LARGE_ARRAY_SIZE = 200; +function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache_default) { + var pairs = data.__data__; + if (!Map_default || pairs.length < LARGE_ARRAY_SIZE - 1) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache_default(pairs); + } + data.set(key, value); + this.size = data.size; + return this; +} +var stackSet_default = stackSet; + +// ../../../node_modules/lodash-es/_Stack.js +function Stack(entries) { + var data = this.__data__ = new ListCache_default(entries); + this.size = data.size; +} +Stack.prototype.clear = stackClear_default; +Stack.prototype["delete"] = stackDelete_default; +Stack.prototype.get = stackGet_default; +Stack.prototype.has = stackHas_default; +Stack.prototype.set = stackSet_default; +var Stack_default = Stack; + +// ../../../node_modules/lodash-es/_baseAssign.js +function baseAssign(object, source) { + return object && copyObject_default(source, keys_default(source), object); +} +var baseAssign_default = baseAssign; + +// ../../../node_modules/lodash-es/_baseAssignIn.js +function baseAssignIn(object, source) { + return object && copyObject_default(source, keysIn_default(source), object); +} +var baseAssignIn_default = baseAssignIn; + +// ../../../node_modules/lodash-es/_cloneBuffer.js +var freeExports3 = typeof exports == "object" && exports && !exports.nodeType && exports; +var freeModule3 = freeExports3 && typeof module == "object" && module && !module.nodeType && module; +var moduleExports3 = freeModule3 && freeModule3.exports === freeExports3; +var Buffer3 = moduleExports3 ? root_default.Buffer : void 0; +var allocUnsafe = Buffer3 ? Buffer3.allocUnsafe : void 0; +function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + buffer.copy(result); + return result; +} +var cloneBuffer_default = cloneBuffer; + +// ../../../node_modules/lodash-es/_arrayFilter.js +function arrayFilter(array, predicate) { + var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; +} +var arrayFilter_default = arrayFilter; + +// ../../../node_modules/lodash-es/stubArray.js +function stubArray() { + return []; +} +var stubArray_default = stubArray; + +// ../../../node_modules/lodash-es/_getSymbols.js +var objectProto13 = Object.prototype; +var propertyIsEnumerable2 = objectProto13.propertyIsEnumerable; +var nativeGetSymbols = Object.getOwnPropertySymbols; +var getSymbols = !nativeGetSymbols ? stubArray_default : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter_default(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable2.call(object, symbol); + }); +}; +var getSymbols_default = getSymbols; + +// ../../../node_modules/lodash-es/_copySymbols.js +function copySymbols(source, object) { + return copyObject_default(source, getSymbols_default(source), object); +} +var copySymbols_default = copySymbols; + +// ../../../node_modules/lodash-es/_getSymbolsIn.js +var nativeGetSymbols2 = Object.getOwnPropertySymbols; +var getSymbolsIn = !nativeGetSymbols2 ? stubArray_default : function(object) { + var result = []; + while (object) { + arrayPush_default(result, getSymbols_default(object)); + object = getPrototype_default(object); + } + return result; +}; +var getSymbolsIn_default = getSymbolsIn; + +// ../../../node_modules/lodash-es/_copySymbolsIn.js +function copySymbolsIn(source, object) { + return copyObject_default(source, getSymbolsIn_default(source), object); +} +var copySymbolsIn_default = copySymbolsIn; + +// ../../../node_modules/lodash-es/_baseGetAllKeys.js +function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray_default(object) ? result : arrayPush_default(result, symbolsFunc(object)); +} +var baseGetAllKeys_default = baseGetAllKeys; + +// ../../../node_modules/lodash-es/_getAllKeys.js +function getAllKeys(object) { + return baseGetAllKeys_default(object, keys_default, getSymbols_default); +} +var getAllKeys_default = getAllKeys; + +// ../../../node_modules/lodash-es/_getAllKeysIn.js +function getAllKeysIn(object) { + return baseGetAllKeys_default(object, keysIn_default, getSymbolsIn_default); +} +var getAllKeysIn_default = getAllKeysIn; + +// ../../../node_modules/lodash-es/_DataView.js +var DataView2 = getNative_default(root_default, "DataView"); +var DataView_default = DataView2; + +// ../../../node_modules/lodash-es/_Promise.js +var Promise2 = getNative_default(root_default, "Promise"); +var Promise_default = Promise2; + +// ../../../node_modules/lodash-es/_Set.js +var Set2 = getNative_default(root_default, "Set"); +var Set_default = Set2; + +// ../../../node_modules/lodash-es/_getTag.js +var mapTag2 = "[object Map]"; +var objectTag3 = "[object Object]"; +var promiseTag = "[object Promise]"; +var setTag2 = "[object Set]"; +var weakMapTag2 = "[object WeakMap]"; +var dataViewTag2 = "[object DataView]"; +var dataViewCtorString = toSource_default(DataView_default); +var mapCtorString = toSource_default(Map_default); +var promiseCtorString = toSource_default(Promise_default); +var setCtorString = toSource_default(Set_default); +var weakMapCtorString = toSource_default(WeakMap_default); +var getTag = baseGetTag_default; +if (DataView_default && getTag(new DataView_default(new ArrayBuffer(1))) != dataViewTag2 || Map_default && getTag(new Map_default()) != mapTag2 || Promise_default && getTag(Promise_default.resolve()) != promiseTag || Set_default && getTag(new Set_default()) != setTag2 || WeakMap_default && getTag(new WeakMap_default()) != weakMapTag2) { + getTag = function(value) { + var result = baseGetTag_default(value), Ctor = result == objectTag3 ? value.constructor : void 0, ctorString = Ctor ? toSource_default(Ctor) : ""; + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: + return dataViewTag2; + case mapCtorString: + return mapTag2; + case promiseCtorString: + return promiseTag; + case setCtorString: + return setTag2; + case weakMapCtorString: + return weakMapTag2; + } + } + return result; + }; +} +var getTag_default = getTag; + +// ../../../node_modules/lodash-es/_initCloneArray.js +var objectProto14 = Object.prototype; +var hasOwnProperty11 = objectProto14.hasOwnProperty; +function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty11.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; +} +var initCloneArray_default = initCloneArray; + +// ../../../node_modules/lodash-es/_Uint8Array.js +var Uint8Array2 = root_default.Uint8Array; +var Uint8Array_default = Uint8Array2; + +// ../../../node_modules/lodash-es/_cloneArrayBuffer.js +function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array_default(result).set(new Uint8Array_default(arrayBuffer)); + return result; +} +var cloneArrayBuffer_default = cloneArrayBuffer; + +// ../../../node_modules/lodash-es/_cloneDataView.js +function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer_default(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); +} +var cloneDataView_default = cloneDataView; + +// ../../../node_modules/lodash-es/_cloneRegExp.js +var reFlags = /\w*$/; +function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; +} +var cloneRegExp_default = cloneRegExp; + +// ../../../node_modules/lodash-es/_cloneSymbol.js +var symbolProto2 = Symbol_default ? Symbol_default.prototype : void 0; +var symbolValueOf = symbolProto2 ? symbolProto2.valueOf : void 0; +function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; +} +var cloneSymbol_default = cloneSymbol; + +// ../../../node_modules/lodash-es/_cloneTypedArray.js +function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer_default(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); +} +var cloneTypedArray_default = cloneTypedArray; + +// ../../../node_modules/lodash-es/_initCloneByTag.js +var boolTag2 = "[object Boolean]"; +var dateTag2 = "[object Date]"; +var mapTag3 = "[object Map]"; +var numberTag2 = "[object Number]"; +var regexpTag2 = "[object RegExp]"; +var setTag3 = "[object Set]"; +var stringTag2 = "[object String]"; +var symbolTag2 = "[object Symbol]"; +var arrayBufferTag2 = "[object ArrayBuffer]"; +var dataViewTag3 = "[object DataView]"; +var float32Tag2 = "[object Float32Array]"; +var float64Tag2 = "[object Float64Array]"; +var int8Tag2 = "[object Int8Array]"; +var int16Tag2 = "[object Int16Array]"; +var int32Tag2 = "[object Int32Array]"; +var uint8Tag2 = "[object Uint8Array]"; +var uint8ClampedTag2 = "[object Uint8ClampedArray]"; +var uint16Tag2 = "[object Uint16Array]"; +var uint32Tag2 = "[object Uint32Array]"; +function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag2: + return cloneArrayBuffer_default(object); + case boolTag2: + case dateTag2: + return new Ctor(+object); + case dataViewTag3: + return cloneDataView_default(object, isDeep); + case float32Tag2: + case float64Tag2: + case int8Tag2: + case int16Tag2: + case int32Tag2: + case uint8Tag2: + case uint8ClampedTag2: + case uint16Tag2: + case uint32Tag2: + return cloneTypedArray_default(object, isDeep); + case mapTag3: + return new Ctor(); + case numberTag2: + case stringTag2: + return new Ctor(object); + case regexpTag2: + return cloneRegExp_default(object); + case setTag3: + return new Ctor(); + case symbolTag2: + return cloneSymbol_default(object); + } +} +var initCloneByTag_default = initCloneByTag; + +// ../../../node_modules/lodash-es/_initCloneObject.js +function initCloneObject(object) { + return typeof object.constructor == "function" && !isPrototype_default(object) ? baseCreate_default(getPrototype_default(object)) : {}; +} +var initCloneObject_default = initCloneObject; + +// ../../../node_modules/lodash-es/_baseIsMap.js +var mapTag4 = "[object Map]"; +function baseIsMap(value) { + return isObjectLike_default(value) && getTag_default(value) == mapTag4; +} +var baseIsMap_default = baseIsMap; + +// ../../../node_modules/lodash-es/isMap.js +var nodeIsMap = nodeUtil_default && nodeUtil_default.isMap; +var isMap = nodeIsMap ? baseUnary_default(nodeIsMap) : baseIsMap_default; +var isMap_default = isMap; + +// ../../../node_modules/lodash-es/_baseIsSet.js +var setTag4 = "[object Set]"; +function baseIsSet(value) { + return isObjectLike_default(value) && getTag_default(value) == setTag4; +} +var baseIsSet_default = baseIsSet; + +// ../../../node_modules/lodash-es/isSet.js +var nodeIsSet = nodeUtil_default && nodeUtil_default.isSet; +var isSet = nodeIsSet ? baseUnary_default(nodeIsSet) : baseIsSet_default; +var isSet_default = isSet; + +// ../../../node_modules/lodash-es/_baseClone.js +var CLONE_DEEP_FLAG = 1; +var CLONE_FLAT_FLAG = 2; +var CLONE_SYMBOLS_FLAG = 4; +var argsTag3 = "[object Arguments]"; +var arrayTag2 = "[object Array]"; +var boolTag3 = "[object Boolean]"; +var dateTag3 = "[object Date]"; +var errorTag2 = "[object Error]"; +var funcTag3 = "[object Function]"; +var genTag2 = "[object GeneratorFunction]"; +var mapTag5 = "[object Map]"; +var numberTag3 = "[object Number]"; +var objectTag4 = "[object Object]"; +var regexpTag3 = "[object RegExp]"; +var setTag5 = "[object Set]"; +var stringTag3 = "[object String]"; +var symbolTag3 = "[object Symbol]"; +var weakMapTag3 = "[object WeakMap]"; +var arrayBufferTag3 = "[object ArrayBuffer]"; +var dataViewTag4 = "[object DataView]"; +var float32Tag3 = "[object Float32Array]"; +var float64Tag3 = "[object Float64Array]"; +var int8Tag3 = "[object Int8Array]"; +var int16Tag3 = "[object Int16Array]"; +var int32Tag3 = "[object Int32Array]"; +var uint8Tag3 = "[object Uint8Array]"; +var uint8ClampedTag3 = "[object Uint8ClampedArray]"; +var uint16Tag3 = "[object Uint16Array]"; +var uint32Tag3 = "[object Uint32Array]"; +var cloneableTags = {}; +cloneableTags[argsTag3] = cloneableTags[arrayTag2] = cloneableTags[arrayBufferTag3] = cloneableTags[dataViewTag4] = cloneableTags[boolTag3] = cloneableTags[dateTag3] = cloneableTags[float32Tag3] = cloneableTags[float64Tag3] = cloneableTags[int8Tag3] = cloneableTags[int16Tag3] = cloneableTags[int32Tag3] = cloneableTags[mapTag5] = cloneableTags[numberTag3] = cloneableTags[objectTag4] = cloneableTags[regexpTag3] = cloneableTags[setTag5] = cloneableTags[stringTag3] = cloneableTags[symbolTag3] = cloneableTags[uint8Tag3] = cloneableTags[uint8ClampedTag3] = cloneableTags[uint16Tag3] = cloneableTags[uint32Tag3] = true; +cloneableTags[errorTag2] = cloneableTags[funcTag3] = cloneableTags[weakMapTag3] = false; +function baseClone(value, bitmask, customizer, key, object, stack) { + var result, isDeep = bitmask & CLONE_DEEP_FLAG, isFlat = bitmask & CLONE_FLAT_FLAG, isFull = bitmask & CLONE_SYMBOLS_FLAG; + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== void 0) { + return result; + } + if (!isObject_default(value)) { + return value; + } + var isArr = isArray_default(value); + if (isArr) { + result = initCloneArray_default(value); + if (!isDeep) { + return copyArray_default(value, result); + } + } else { + var tag = getTag_default(value), isFunc = tag == funcTag3 || tag == genTag2; + if (isBuffer_default(value)) { + return cloneBuffer_default(value, isDeep); + } + if (tag == objectTag4 || tag == argsTag3 || isFunc && !object) { + result = isFlat || isFunc ? {} : initCloneObject_default(value); + if (!isDeep) { + return isFlat ? copySymbolsIn_default(value, baseAssignIn_default(result, value)) : copySymbols_default(value, baseAssign_default(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = initCloneByTag_default(value, tag, isDeep); + } + } + stack || (stack = new Stack_default()); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + if (isSet_default(value)) { + value.forEach(function(subValue) { + result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); + }); + } else if (isMap_default(value)) { + value.forEach(function(subValue, key2) { + result.set(key2, baseClone(subValue, bitmask, customizer, key2, value, stack)); + }); + } + var keysFunc = isFull ? isFlat ? getAllKeysIn_default : getAllKeys_default : isFlat ? keysIn_default : keys_default; + var props = isArr ? void 0 : keysFunc(value); + arrayEach_default(props || value, function(subValue, key2) { + if (props) { + key2 = subValue; + subValue = value[key2]; + } + assignValue_default(result, key2, baseClone(subValue, bitmask, customizer, key2, value, stack)); + }); + return result; +} +var baseClone_default = baseClone; + +// ../../../node_modules/lodash-es/cloneDeep.js +var CLONE_DEEP_FLAG2 = 1; +var CLONE_SYMBOLS_FLAG2 = 4; +function cloneDeep(value) { + return baseClone_default(value, CLONE_DEEP_FLAG2 | CLONE_SYMBOLS_FLAG2); +} +var cloneDeep_default = cloneDeep; + +// ../../../node_modules/lodash-es/_setCacheAdd.js +var HASH_UNDEFINED3 = "__lodash_hash_undefined__"; +function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED3); + return this; +} +var setCacheAdd_default = setCacheAdd; + +// ../../../node_modules/lodash-es/_setCacheHas.js +function setCacheHas(value) { + return this.__data__.has(value); +} +var setCacheHas_default = setCacheHas; + +// ../../../node_modules/lodash-es/_SetCache.js +function SetCache(values) { + var index = -1, length = values == null ? 0 : values.length; + this.__data__ = new MapCache_default(); + while (++index < length) { + this.add(values[index]); + } +} +SetCache.prototype.add = SetCache.prototype.push = setCacheAdd_default; +SetCache.prototype.has = setCacheHas_default; +var SetCache_default = SetCache; + +// ../../../node_modules/lodash-es/_arraySome.js +function arraySome(array, predicate) { + var index = -1, length = array == null ? 0 : array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; +} +var arraySome_default = arraySome; + +// ../../../node_modules/lodash-es/_cacheHas.js +function cacheHas(cache, key) { + return cache.has(key); +} +var cacheHas_default = cacheHas; + +// ../../../node_modules/lodash-es/_equalArrays.js +var COMPARE_PARTIAL_FLAG = 1; +var COMPARE_UNORDERED_FLAG = 2; +function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + var arrStacked = stack.get(array); + var othStacked = stack.get(other); + if (arrStacked && othStacked) { + return arrStacked == other && othStacked == array; + } + var index = -1, result = true, seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache_default() : void 0; + stack.set(array, other); + stack.set(other, array); + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index]; + if (customizer) { + var compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== void 0) { + if (compared) { + continue; + } + result = false; + break; + } + if (seen) { + if (!arraySome_default(other, function(othValue2, othIndex) { + if (!cacheHas_default(seen, othIndex) && (arrValue === othValue2 || equalFunc(arrValue, othValue2, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + result = false; + break; + } + } + stack["delete"](array); + stack["delete"](other); + return result; +} +var equalArrays_default = equalArrays; + +// ../../../node_modules/lodash-es/_mapToArray.js +function mapToArray(map) { + var index = -1, result = Array(map.size); + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; +} +var mapToArray_default = mapToArray; + +// ../../../node_modules/lodash-es/_setToArray.js +function setToArray(set2) { + var index = -1, result = Array(set2.size); + set2.forEach(function(value) { + result[++index] = value; + }); + return result; +} +var setToArray_default = setToArray; + +// ../../../node_modules/lodash-es/_equalByTag.js +var COMPARE_PARTIAL_FLAG2 = 1; +var COMPARE_UNORDERED_FLAG2 = 2; +var boolTag4 = "[object Boolean]"; +var dateTag4 = "[object Date]"; +var errorTag3 = "[object Error]"; +var mapTag6 = "[object Map]"; +var numberTag4 = "[object Number]"; +var regexpTag4 = "[object RegExp]"; +var setTag6 = "[object Set]"; +var stringTag4 = "[object String]"; +var symbolTag4 = "[object Symbol]"; +var arrayBufferTag4 = "[object ArrayBuffer]"; +var dataViewTag5 = "[object DataView]"; +var symbolProto3 = Symbol_default ? Symbol_default.prototype : void 0; +var symbolValueOf2 = symbolProto3 ? symbolProto3.valueOf : void 0; +function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag5: + if (object.byteLength != other.byteLength || object.byteOffset != other.byteOffset) { + return false; + } + object = object.buffer; + other = other.buffer; + case arrayBufferTag4: + if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array_default(object), new Uint8Array_default(other))) { + return false; + } + return true; + case boolTag4: + case dateTag4: + case numberTag4: + return eq_default(+object, +other); + case errorTag3: + return object.name == other.name && object.message == other.message; + case regexpTag4: + case stringTag4: + return object == other + ""; + case mapTag6: + var convert = mapToArray_default; + case setTag6: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG2; + convert || (convert = setToArray_default); + if (object.size != other.size && !isPartial) { + return false; + } + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG2; + stack.set(object, other); + var result = equalArrays_default(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack["delete"](object); + return result; + case symbolTag4: + if (symbolValueOf2) { + return symbolValueOf2.call(object) == symbolValueOf2.call(other); + } + } + return false; +} +var equalByTag_default = equalByTag; + +// ../../../node_modules/lodash-es/_equalObjects.js +var COMPARE_PARTIAL_FLAG3 = 1; +var objectProto15 = Object.prototype; +var hasOwnProperty12 = objectProto15.hasOwnProperty; +function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG3, objProps = getAllKeys_default(object), objLength = objProps.length, othProps = getAllKeys_default(other), othLength = othProps.length; + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty12.call(other, key))) { + return false; + } + } + var objStacked = stack.get(object); + var othStacked = stack.get(other); + if (objStacked && othStacked) { + return objStacked == other && othStacked == object; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key]; + if (customizer) { + var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack); + } + if (!(compared === void 0 ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared)) { + result = false; + break; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (result && !skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + result = false; + } + } + stack["delete"](object); + stack["delete"](other); + return result; +} +var equalObjects_default = equalObjects; + +// ../../../node_modules/lodash-es/_baseIsEqualDeep.js +var COMPARE_PARTIAL_FLAG4 = 1; +var argsTag4 = "[object Arguments]"; +var arrayTag3 = "[object Array]"; +var objectTag5 = "[object Object]"; +var objectProto16 = Object.prototype; +var hasOwnProperty13 = objectProto16.hasOwnProperty; +function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray_default(object), othIsArr = isArray_default(other), objTag = objIsArr ? arrayTag3 : getTag_default(object), othTag = othIsArr ? arrayTag3 : getTag_default(other); + objTag = objTag == argsTag4 ? objectTag5 : objTag; + othTag = othTag == argsTag4 ? objectTag5 : othTag; + var objIsObj = objTag == objectTag5, othIsObj = othTag == objectTag5, isSameTag = objTag == othTag; + if (isSameTag && isBuffer_default(object)) { + if (!isBuffer_default(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack_default()); + return objIsArr || isTypedArray_default(object) ? equalArrays_default(object, other, bitmask, customizer, equalFunc, stack) : equalByTag_default(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_FLAG4)) { + var objIsWrapped = objIsObj && hasOwnProperty13.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty13.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, othUnwrapped = othIsWrapped ? other.value() : other; + stack || (stack = new Stack_default()); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack_default()); + return equalObjects_default(object, other, bitmask, customizer, equalFunc, stack); +} +var baseIsEqualDeep_default = baseIsEqualDeep; + +// ../../../node_modules/lodash-es/_baseIsEqual.js +function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObjectLike_default(value) && !isObjectLike_default(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep_default(value, other, bitmask, customizer, baseIsEqual, stack); +} +var baseIsEqual_default = baseIsEqual; + +// ../../../node_modules/lodash-es/_hasPath.js +function hasPath(object, path, hasFunc) { + path = castPath_default(path, object); + var index = -1, length = path.length, result = false; + while (++index < length) { + var key = toKey_default(path[index]); + if (!(result = object != null && hasFunc(object, key))) { + break; + } + object = object[key]; + } + if (result || ++index != length) { + return result; + } + length = object == null ? 0 : object.length; + return !!length && isLength_default(length) && isIndex_default(key, length) && (isArray_default(object) || isArguments_default(object)); +} +var hasPath_default = hasPath; + +// ../../../node_modules/lodash-es/_createBaseFor.js +function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, iterable = Object(object), props = keysFunc(object), length = props.length; + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; +} +var createBaseFor_default = createBaseFor; + +// ../../../node_modules/lodash-es/_baseFor.js +var baseFor = createBaseFor_default(); +var baseFor_default = baseFor; + +// ../../../node_modules/lodash-es/now.js +var now = function() { + return root_default.Date.now(); +}; +var now_default = now; + +// ../../../node_modules/lodash-es/debounce.js +var FUNC_ERROR_TEXT2 = "Expected a function"; +var nativeMax2 = Math.max; +var nativeMin = Math.min; +function debounce(func, wait, options) { + var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT2); + } + wait = toNumber_default(wait) || 0; + if (isObject_default(options)) { + leading = !!options.leading; + maxing = "maxWait" in options; + maxWait = maxing ? nativeMax2(toNumber_default(options.maxWait) || 0, wait) : maxWait; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function invokeFunc(time) { + var args = lastArgs, thisArg = lastThis; + lastArgs = lastThis = void 0; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + function leadingEdge(time) { + lastInvokeTime = time; + timerId = setTimeout(timerExpired, wait); + return leading ? invokeFunc(time) : result; + } + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, timeWaiting = wait - timeSinceLastCall; + return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting; + } + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime; + return lastCallTime === void 0 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait; + } + function timerExpired() { + var time = now_default(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + timerId = setTimeout(timerExpired, remainingWait(time)); + } + function trailingEdge(time) { + timerId = void 0; + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = void 0; + return result; + } + function cancel() { + if (timerId !== void 0) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = void 0; + } + function flush() { + return timerId === void 0 ? result : trailingEdge(now_default()); + } + function debounced() { + var time = now_default(), isInvoking = shouldInvoke(time); + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + if (isInvoking) { + if (timerId === void 0) { + return leadingEdge(lastCallTime); + } + if (maxing) { + clearTimeout(timerId); + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === void 0) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; +} +var debounce_default = debounce; + +// ../../../node_modules/lodash-es/_assignMergeValue.js +function assignMergeValue(object, key, value) { + if (value !== void 0 && !eq_default(object[key], value) || value === void 0 && !(key in object)) { + baseAssignValue_default(object, key, value); + } +} +var assignMergeValue_default = assignMergeValue; + +// ../../../node_modules/lodash-es/isArrayLikeObject.js +function isArrayLikeObject(value) { + return isObjectLike_default(value) && isArrayLike_default(value); +} +var isArrayLikeObject_default = isArrayLikeObject; + +// ../../../node_modules/lodash-es/_safeGet.js +function safeGet(object, key) { + if (key === "constructor" && typeof object[key] === "function") { + return; + } + if (key == "__proto__") { + return; + } + return object[key]; +} +var safeGet_default = safeGet; + +// ../../../node_modules/lodash-es/toPlainObject.js +function toPlainObject(value) { + return copyObject_default(value, keysIn_default(value)); +} +var toPlainObject_default = toPlainObject; + +// ../../../node_modules/lodash-es/_baseMergeDeep.js +function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = safeGet_default(object, key), srcValue = safeGet_default(source, key), stacked = stack.get(srcValue); + if (stacked) { + assignMergeValue_default(object, key, stacked); + return; + } + var newValue = customizer ? customizer(objValue, srcValue, key + "", object, source, stack) : void 0; + var isCommon = newValue === void 0; + if (isCommon) { + var isArr = isArray_default(srcValue), isBuff = !isArr && isBuffer_default(srcValue), isTyped = !isArr && !isBuff && isTypedArray_default(srcValue); + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray_default(objValue)) { + newValue = objValue; + } else if (isArrayLikeObject_default(objValue)) { + newValue = copyArray_default(objValue); + } else if (isBuff) { + isCommon = false; + newValue = cloneBuffer_default(srcValue, true); + } else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray_default(srcValue, true); + } else { + newValue = []; + } + } else if (isPlainObject_default(srcValue) || isArguments_default(srcValue)) { + newValue = objValue; + if (isArguments_default(objValue)) { + newValue = toPlainObject_default(objValue); + } else if (!isObject_default(objValue) || isFunction_default(objValue)) { + newValue = initCloneObject_default(srcValue); + } + } else { + isCommon = false; + } + } + if (isCommon) { + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack["delete"](srcValue); + } + assignMergeValue_default(object, key, newValue); +} +var baseMergeDeep_default = baseMergeDeep; + +// ../../../node_modules/lodash-es/_baseMerge.js +function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor_default(source, function(srcValue, key) { + stack || (stack = new Stack_default()); + if (isObject_default(srcValue)) { + baseMergeDeep_default(object, source, key, srcIndex, baseMerge, customizer, stack); + } else { + var newValue = customizer ? customizer(safeGet_default(object, key), srcValue, key + "", object, source, stack) : void 0; + if (newValue === void 0) { + newValue = srcValue; + } + assignMergeValue_default(object, key, newValue); + } + }, keysIn_default); +} +var baseMerge_default = baseMerge; + +// ../../../node_modules/lodash-es/_escapeHtmlChar.js +var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'" +}; +var escapeHtmlChar = basePropertyOf_default(htmlEscapes); +var escapeHtmlChar_default = escapeHtmlChar; + +// ../../../node_modules/lodash-es/escape.js +var reUnescapedHtml = /[&<>"']/g; +var reHasUnescapedHtml = RegExp(reUnescapedHtml.source); +function escape2(string) { + string = toString_default(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar_default) : string; +} +var escape_default = escape2; + +// ../../../node_modules/lodash-es/_baseHas.js +var objectProto17 = Object.prototype; +var hasOwnProperty14 = objectProto17.hasOwnProperty; +function baseHas(object, key) { + return object != null && hasOwnProperty14.call(object, key); +} +var baseHas_default = baseHas; + +// ../../../node_modules/lodash-es/has.js +function has(object, path) { + return object != null && hasPath_default(object, path, baseHas_default); +} +var has_default = has; + +// ../../../node_modules/lodash-es/isEqual.js +function isEqual(value, other) { + return baseIsEqual_default(value, other); +} +var isEqual_default = isEqual; + +// ../../../node_modules/lodash-es/merge.js +var merge = createAssigner_default(function(object, source, srcIndex) { + baseMerge_default(object, source, srcIndex); +}); +var merge_default = merge; + +// ../../../node_modules/lodash-es/_baseSet.js +function baseSet(object, path, value, customizer) { + if (!isObject_default(object)) { + return object; + } + path = castPath_default(path, object); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = toKey_default(path[index]), newValue = value; + if (key === "__proto__" || key === "constructor" || key === "prototype") { + return object; + } + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : void 0; + if (newValue === void 0) { + newValue = isObject_default(objValue) ? objValue : isIndex_default(path[index + 1]) ? [] : {}; + } + } + assignValue_default(nested, key, newValue); + nested = nested[key]; + } + return object; +} +var baseSet_default = baseSet; + +// ../../../node_modules/lodash-es/set.js +function set(object, path, value) { + return object == null ? object : baseSet_default(object, path, value); +} +var set_default = set; + +// ../../../node_modules/@inertiajs/core/dist/index.esm.js +var qs = __toESM(require_lib(), 1); + +// ../../../node_modules/axios/lib/helpers/bind.js +function bind(fn, thisArg) { + return function wrap() { + return fn.apply(thisArg, arguments); + }; +} + +// ../../../node_modules/axios/lib/utils.js +var { toString: toString2 } = Object.prototype; +var { getPrototypeOf } = Object; +var { iterator, toStringTag } = Symbol; +var kindOf = /* @__PURE__ */ ((cache) => (thing) => { + const str = toString2.call(thing); + return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase()); +})(/* @__PURE__ */ Object.create(null)); +var kindOfTest = (type) => { + type = type.toLowerCase(); + return (thing) => kindOf(thing) === type; +}; +var typeOfTest = (type) => (thing) => typeof thing === type; +var { isArray: isArray2 } = Array; +var isUndefined = typeOfTest("undefined"); +function isBuffer2(val) { + return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor) && isFunction2(val.constructor.isBuffer) && val.constructor.isBuffer(val); +} +var isArrayBuffer = kindOfTest("ArrayBuffer"); +function isArrayBufferView(val) { + let result; + if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView) { + result = ArrayBuffer.isView(val); + } else { + result = val && val.buffer && isArrayBuffer(val.buffer); + } + return result; +} +var isString = typeOfTest("string"); +var isFunction2 = typeOfTest("function"); +var isNumber = typeOfTest("number"); +var isObject2 = (thing) => thing !== null && typeof thing === "object"; +var isBoolean = (thing) => thing === true || thing === false; +var isPlainObject2 = (val) => { + if (kindOf(val) !== "object") { + return false; + } + const prototype2 = getPrototypeOf(val); + return (prototype2 === null || prototype2 === Object.prototype || Object.getPrototypeOf(prototype2) === null) && !(toStringTag in val) && !(iterator in val); +}; +var isEmptyObject = (val) => { + if (!isObject2(val) || isBuffer2(val)) { + return false; + } + try { + return Object.keys(val).length === 0 && Object.getPrototypeOf(val) === Object.prototype; + } catch (e) { + return false; + } +}; +var isDate = kindOfTest("Date"); +var isFile = kindOfTest("File"); +var isReactNativeBlob = (value) => { + return !!(value && typeof value.uri !== "undefined"); +}; +var isReactNative = (formData) => formData && typeof formData.getParts !== "undefined"; +var isBlob = kindOfTest("Blob"); +var isFileList = kindOfTest("FileList"); +var isStream = (val) => isObject2(val) && isFunction2(val.pipe); +function getGlobal() { + if (typeof globalThis !== "undefined") return globalThis; + if (typeof self !== "undefined") return self; + if (typeof window !== "undefined") return window; + if (typeof global !== "undefined") return global; + return {}; +} +var G = getGlobal(); +var FormDataCtor = typeof G.FormData !== "undefined" ? G.FormData : void 0; +var isFormData = (thing) => { + let kind; + return thing && (FormDataCtor && thing instanceof FormDataCtor || isFunction2(thing.append) && ((kind = kindOf(thing)) === "formdata" || // detect form-data instance + kind === "object" && isFunction2(thing.toString) && thing.toString() === "[object FormData]")); +}; +var isURLSearchParams = kindOfTest("URLSearchParams"); +var [isReadableStream, isRequest, isResponse, isHeaders] = [ + "ReadableStream", + "Request", + "Response", + "Headers" +].map(kindOfTest); +var trim = (str) => { + return str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ""); +}; +function forEach(obj, fn, { allOwnKeys = false } = {}) { + if (obj === null || typeof obj === "undefined") { + return; + } + let i; + let l; + if (typeof obj !== "object") { + obj = [obj]; + } + if (isArray2(obj)) { + for (i = 0, l = obj.length; i < l; i++) { + fn.call(null, obj[i], i, obj); + } + } else { + if (isBuffer2(obj)) { + return; + } + const keys2 = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj); + const len = keys2.length; + let key; + for (i = 0; i < len; i++) { + key = keys2[i]; + fn.call(null, obj[key], key, obj); + } + } +} +function findKey(obj, key) { + if (isBuffer2(obj)) { + return null; + } + key = key.toLowerCase(); + const keys2 = Object.keys(obj); + let i = keys2.length; + let _key; + while (i-- > 0) { + _key = keys2[i]; + if (key === _key.toLowerCase()) { + return _key; + } + } + return null; +} +var _global = (() => { + if (typeof globalThis !== "undefined") return globalThis; + return typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : global; +})(); +var isContextDefined = (context) => !isUndefined(context) && context !== _global; +function merge2() { + const { caseless, skipUndefined } = isContextDefined(this) && this || {}; + const result = {}; + const assignValue2 = (val, key) => { + if (key === "__proto__" || key === "constructor" || key === "prototype") { + return; + } + const targetKey = caseless && findKey(result, key) || key; + if (isPlainObject2(result[targetKey]) && isPlainObject2(val)) { + result[targetKey] = merge2(result[targetKey], val); + } else if (isPlainObject2(val)) { + result[targetKey] = merge2({}, val); + } else if (isArray2(val)) { + result[targetKey] = val.slice(); + } else if (!skipUndefined || !isUndefined(val)) { + result[targetKey] = val; + } + }; + for (let i = 0, l = arguments.length; i < l; i++) { + arguments[i] && forEach(arguments[i], assignValue2); + } + return result; +} +var extend = (a, b, thisArg, { allOwnKeys } = {}) => { + forEach( + b, + (val, key) => { + if (thisArg && isFunction2(val)) { + Object.defineProperty(a, key, { + value: bind(val, thisArg), + writable: true, + enumerable: true, + configurable: true + }); + } else { + Object.defineProperty(a, key, { + value: val, + writable: true, + enumerable: true, + configurable: true + }); + } + }, + { allOwnKeys } + ); + return a; +}; +var stripBOM = (content) => { + if (content.charCodeAt(0) === 65279) { + content = content.slice(1); + } + return content; +}; +var inherits = (constructor, superConstructor, props, descriptors) => { + constructor.prototype = Object.create(superConstructor.prototype, descriptors); + Object.defineProperty(constructor.prototype, "constructor", { + value: constructor, + writable: true, + enumerable: false, + configurable: true + }); + Object.defineProperty(constructor, "super", { + value: superConstructor.prototype + }); + props && Object.assign(constructor.prototype, props); +}; +var toFlatObject = (sourceObj, destObj, filter2, propFilter) => { + let props; + let i; + let prop; + const merged = {}; + destObj = destObj || {}; + if (sourceObj == null) return destObj; + do { + props = Object.getOwnPropertyNames(sourceObj); + i = props.length; + while (i-- > 0) { + prop = props[i]; + if ((!propFilter || propFilter(prop, sourceObj, destObj)) && !merged[prop]) { + destObj[prop] = sourceObj[prop]; + merged[prop] = true; + } + } + sourceObj = filter2 !== false && getPrototypeOf(sourceObj); + } while (sourceObj && (!filter2 || filter2(sourceObj, destObj)) && sourceObj !== Object.prototype); + return destObj; +}; +var endsWith = (str, searchString, position) => { + str = String(str); + if (position === void 0 || position > str.length) { + position = str.length; + } + position -= searchString.length; + const lastIndex = str.indexOf(searchString, position); + return lastIndex !== -1 && lastIndex === position; +}; +var toArray = (thing) => { + if (!thing) return null; + if (isArray2(thing)) return thing; + let i = thing.length; + if (!isNumber(i)) return null; + const arr = new Array(i); + while (i-- > 0) { + arr[i] = thing[i]; + } + return arr; +}; +var isTypedArray2 = /* @__PURE__ */ ((TypedArray) => { + return (thing) => { + return TypedArray && thing instanceof TypedArray; + }; +})(typeof Uint8Array !== "undefined" && getPrototypeOf(Uint8Array)); +var forEachEntry = (obj, fn) => { + const generator = obj && obj[iterator]; + const _iterator = generator.call(obj); + let result; + while ((result = _iterator.next()) && !result.done) { + const pair = result.value; + fn.call(obj, pair[0], pair[1]); + } +}; +var matchAll = (regExp, str) => { + let matches; + const arr = []; + while ((matches = regExp.exec(str)) !== null) { + arr.push(matches); + } + return arr; +}; +var isHTMLForm = kindOfTest("HTMLFormElement"); +var toCamelCase = (str) => { + return str.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g, function replacer(m, p1, p2) { + return p1.toUpperCase() + p2; + }); +}; +var hasOwnProperty15 = (({ hasOwnProperty: hasOwnProperty16 }) => (obj, prop) => hasOwnProperty16.call(obj, prop))(Object.prototype); +var isRegExp = kindOfTest("RegExp"); +var reduceDescriptors = (obj, reducer) => { + const descriptors = Object.getOwnPropertyDescriptors(obj); + const reducedDescriptors = {}; + forEach(descriptors, (descriptor, name) => { + let ret; + if ((ret = reducer(descriptor, name, obj)) !== false) { + reducedDescriptors[name] = ret || descriptor; + } + }); + Object.defineProperties(obj, reducedDescriptors); +}; +var freezeMethods = (obj) => { + reduceDescriptors(obj, (descriptor, name) => { + if (isFunction2(obj) && ["arguments", "caller", "callee"].indexOf(name) !== -1) { + return false; + } + const value = obj[name]; + if (!isFunction2(value)) return; + descriptor.enumerable = false; + if ("writable" in descriptor) { + descriptor.writable = false; + return; + } + if (!descriptor.set) { + descriptor.set = () => { + throw Error("Can not rewrite read-only method '" + name + "'"); + }; + } + }); +}; +var toObjectSet = (arrayOrString, delimiter) => { + const obj = {}; + const define = (arr) => { + arr.forEach((value) => { + obj[value] = true; + }); + }; + isArray2(arrayOrString) ? define(arrayOrString) : define(String(arrayOrString).split(delimiter)); + return obj; +}; +var noop = () => { +}; +var toFiniteNumber = (value, defaultValue) => { + return value != null && Number.isFinite(value = +value) ? value : defaultValue; +}; +function isSpecCompliantForm(thing) { + return !!(thing && isFunction2(thing.append) && thing[toStringTag] === "FormData" && thing[iterator]); +} +var toJSONObject = (obj) => { + const stack = new Array(10); + const visit = (source, i) => { + if (isObject2(source)) { + if (stack.indexOf(source) >= 0) { + return; + } + if (isBuffer2(source)) { + return source; + } + if (!("toJSON" in source)) { + stack[i] = source; + const target = isArray2(source) ? [] : {}; + forEach(source, (value, key) => { + const reducedValue = visit(value, i + 1); + !isUndefined(reducedValue) && (target[key] = reducedValue); + }); + stack[i] = void 0; + return target; + } + } + return source; + }; + return visit(obj, 0); +}; +var isAsyncFn = kindOfTest("AsyncFunction"); +var isThenable = (thing) => thing && (isObject2(thing) || isFunction2(thing)) && isFunction2(thing.then) && isFunction2(thing.catch); +var _setImmediate = ((setImmediateSupported, postMessageSupported) => { + if (setImmediateSupported) { + return setImmediate; + } + return postMessageSupported ? ((token, callbacks) => { + _global.addEventListener( + "message", + ({ source, data }) => { + if (source === _global && data === token) { + callbacks.length && callbacks.shift()(); + } + }, + false + ); + return (cb) => { + callbacks.push(cb); + _global.postMessage(token, "*"); + }; + })(`axios@${Math.random()}`, []) : (cb) => setTimeout(cb); +})(typeof setImmediate === "function", isFunction2(_global.postMessage)); +var asap = typeof queueMicrotask !== "undefined" ? queueMicrotask.bind(_global) : typeof process !== "undefined" && process.nextTick || _setImmediate; +var isIterable = (thing) => thing != null && isFunction2(thing[iterator]); +var utils_default = { + isArray: isArray2, + isArrayBuffer, + isBuffer: isBuffer2, + isFormData, + isArrayBufferView, + isString, + isNumber, + isBoolean, + isObject: isObject2, + isPlainObject: isPlainObject2, + isEmptyObject, + isReadableStream, + isRequest, + isResponse, + isHeaders, + isUndefined, + isDate, + isFile, + isReactNativeBlob, + isReactNative, + isBlob, + isRegExp, + isFunction: isFunction2, + isStream, + isURLSearchParams, + isTypedArray: isTypedArray2, + isFileList, + forEach, + merge: merge2, + extend, + trim, + stripBOM, + inherits, + toFlatObject, + kindOf, + kindOfTest, + endsWith, + toArray, + forEachEntry, + matchAll, + isHTMLForm, + hasOwnProperty: hasOwnProperty15, + hasOwnProp: hasOwnProperty15, + // an alias to avoid ESLint no-prototype-builtins detection + reduceDescriptors, + freezeMethods, + toObjectSet, + toCamelCase, + noop, + toFiniteNumber, + findKey, + global: _global, + isContextDefined, + isSpecCompliantForm, + toJSONObject, + isAsyncFn, + isThenable, + setImmediate: _setImmediate, + asap, + isIterable +}; + +// ../../../node_modules/axios/lib/core/AxiosError.js +var AxiosError = class _AxiosError extends Error { + static from(error, code, config3, request2, response, customProps) { + const axiosError = new _AxiosError(error.message, code || error.code, config3, request2, response); + axiosError.cause = error; + axiosError.name = error.name; + if (error.status != null && axiosError.status == null) { + axiosError.status = error.status; + } + customProps && Object.assign(axiosError, customProps); + return axiosError; + } + /** + * Create an Error with the specified message, config, error code, request and response. + * + * @param {string} message The error message. + * @param {string} [code] The error code (for example, 'ECONNABORTED'). + * @param {Object} [config] The config. + * @param {Object} [request] The request. + * @param {Object} [response] The response. + * + * @returns {Error} The created error. + */ + constructor(message, code, config3, request2, response) { + super(message); + Object.defineProperty(this, "message", { + value: message, + enumerable: true, + writable: true, + configurable: true + }); + this.name = "AxiosError"; + this.isAxiosError = true; + code && (this.code = code); + config3 && (this.config = config3); + request2 && (this.request = request2); + if (response) { + this.response = response; + this.status = response.status; + } + } + toJSON() { + return { + // Standard + message: this.message, + name: this.name, + // Microsoft + description: this.description, + number: this.number, + // Mozilla + fileName: this.fileName, + lineNumber: this.lineNumber, + columnNumber: this.columnNumber, + stack: this.stack, + // Axios + config: utils_default.toJSONObject(this.config), + code: this.code, + status: this.status + }; + } +}; +AxiosError.ERR_BAD_OPTION_VALUE = "ERR_BAD_OPTION_VALUE"; +AxiosError.ERR_BAD_OPTION = "ERR_BAD_OPTION"; +AxiosError.ECONNABORTED = "ECONNABORTED"; +AxiosError.ETIMEDOUT = "ETIMEDOUT"; +AxiosError.ERR_NETWORK = "ERR_NETWORK"; +AxiosError.ERR_FR_TOO_MANY_REDIRECTS = "ERR_FR_TOO_MANY_REDIRECTS"; +AxiosError.ERR_DEPRECATED = "ERR_DEPRECATED"; +AxiosError.ERR_BAD_RESPONSE = "ERR_BAD_RESPONSE"; +AxiosError.ERR_BAD_REQUEST = "ERR_BAD_REQUEST"; +AxiosError.ERR_CANCELED = "ERR_CANCELED"; +AxiosError.ERR_NOT_SUPPORT = "ERR_NOT_SUPPORT"; +AxiosError.ERR_INVALID_URL = "ERR_INVALID_URL"; +var AxiosError_default = AxiosError; + +// ../../../node_modules/axios/lib/helpers/null.js +var null_default = null; + +// ../../../node_modules/axios/lib/helpers/toFormData.js +function isVisitable(thing) { + return utils_default.isPlainObject(thing) || utils_default.isArray(thing); +} +function removeBrackets(key) { + return utils_default.endsWith(key, "[]") ? key.slice(0, -2) : key; +} +function renderKey(path, key, dots) { + if (!path) return key; + return path.concat(key).map(function each(token, i) { + token = removeBrackets(token); + return !dots && i ? "[" + token + "]" : token; + }).join(dots ? "." : ""); +} +function isFlatArray(arr) { + return utils_default.isArray(arr) && !arr.some(isVisitable); +} +var predicates = utils_default.toFlatObject(utils_default, {}, null, function filter(prop) { + return /^is[A-Z]/.test(prop); +}); +function toFormData(obj, formData, options) { + if (!utils_default.isObject(obj)) { + throw new TypeError("target must be an object"); + } + formData = formData || new (null_default || FormData)(); + options = utils_default.toFlatObject( + options, + { + metaTokens: true, + dots: false, + indexes: false + }, + false, + function defined(option, source) { + return !utils_default.isUndefined(source[option]); + } + ); + const metaTokens = options.metaTokens; + const visitor = options.visitor || defaultVisitor; + const dots = options.dots; + const indexes = options.indexes; + const _Blob = options.Blob || typeof Blob !== "undefined" && Blob; + const useBlob = _Blob && utils_default.isSpecCompliantForm(formData); + if (!utils_default.isFunction(visitor)) { + throw new TypeError("visitor must be a function"); + } + function convertValue(value) { + if (value === null) return ""; + if (utils_default.isDate(value)) { + return value.toISOString(); + } + if (utils_default.isBoolean(value)) { + return value.toString(); + } + if (!useBlob && utils_default.isBlob(value)) { + throw new AxiosError_default("Blob is not supported. Use a Buffer instead."); + } + if (utils_default.isArrayBuffer(value) || utils_default.isTypedArray(value)) { + return useBlob && typeof Blob === "function" ? new Blob([value]) : Buffer.from(value); + } + return value; + } + function defaultVisitor(value, key, path) { + let arr = value; + if (utils_default.isReactNative(formData) && utils_default.isReactNativeBlob(value)) { + formData.append(renderKey(path, key, dots), convertValue(value)); + return false; + } + if (value && !path && typeof value === "object") { + if (utils_default.endsWith(key, "{}")) { + key = metaTokens ? key : key.slice(0, -2); + value = JSON.stringify(value); + } else if (utils_default.isArray(value) && isFlatArray(value) || (utils_default.isFileList(value) || utils_default.endsWith(key, "[]")) && (arr = utils_default.toArray(value))) { + key = removeBrackets(key); + arr.forEach(function each(el, index) { + !(utils_default.isUndefined(el) || el === null) && formData.append( + // eslint-disable-next-line no-nested-ternary + indexes === true ? renderKey([key], index, dots) : indexes === null ? key : key + "[]", + convertValue(el) + ); + }); + return false; + } + } + if (isVisitable(value)) { + return true; + } + formData.append(renderKey(path, key, dots), convertValue(value)); + return false; + } + const stack = []; + const exposedHelpers = Object.assign(predicates, { + defaultVisitor, + convertValue, + isVisitable + }); + function build(value, path) { + if (utils_default.isUndefined(value)) return; + if (stack.indexOf(value) !== -1) { + throw Error("Circular reference detected in " + path.join(".")); + } + stack.push(value); + utils_default.forEach(value, function each(el, key) { + const result = !(utils_default.isUndefined(el) || el === null) && visitor.call(formData, el, utils_default.isString(key) ? key.trim() : key, path, exposedHelpers); + if (result === true) { + build(el, path ? path.concat(key) : [key]); + } + }); + stack.pop(); + } + if (!utils_default.isObject(obj)) { + throw new TypeError("data must be an object"); + } + build(obj); + return formData; +} +var toFormData_default = toFormData; + +// ../../../node_modules/axios/lib/helpers/AxiosURLSearchParams.js +function encode(str) { + const charMap = { + "!": "%21", + "'": "%27", + "(": "%28", + ")": "%29", + "~": "%7E", + "%20": "+", + "%00": "\0" + }; + return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) { + return charMap[match]; + }); +} +function AxiosURLSearchParams(params, options) { + this._pairs = []; + params && toFormData_default(params, this, options); +} +var prototype = AxiosURLSearchParams.prototype; +prototype.append = function append(name, value) { + this._pairs.push([name, value]); +}; +prototype.toString = function toString3(encoder) { + const _encode = encoder ? function(value) { + return encoder.call(this, value, encode); + } : encode; + return this._pairs.map(function each(pair) { + return _encode(pair[0]) + "=" + _encode(pair[1]); + }, "").join("&"); +}; +var AxiosURLSearchParams_default = AxiosURLSearchParams; + +// ../../../node_modules/axios/lib/helpers/buildURL.js +function encode2(val) { + return encodeURIComponent(val).replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%20/g, "+"); +} +function buildURL(url, params, options) { + if (!params) { + return url; + } + const _encode = options && options.encode || encode2; + const _options = utils_default.isFunction(options) ? { + serialize: options + } : options; + const serializeFn = _options && _options.serialize; + let serializedParams; + if (serializeFn) { + serializedParams = serializeFn(params, _options); + } else { + serializedParams = utils_default.isURLSearchParams(params) ? params.toString() : new AxiosURLSearchParams_default(params, _options).toString(_encode); + } + if (serializedParams) { + const hashmarkIndex = url.indexOf("#"); + if (hashmarkIndex !== -1) { + url = url.slice(0, hashmarkIndex); + } + url += (url.indexOf("?") === -1 ? "?" : "&") + serializedParams; + } + return url; +} + +// ../../../node_modules/axios/lib/core/InterceptorManager.js +var InterceptorManager = class { + constructor() { + this.handlers = []; + } + /** + * Add a new interceptor to the stack + * + * @param {Function} fulfilled The function to handle `then` for a `Promise` + * @param {Function} rejected The function to handle `reject` for a `Promise` + * @param {Object} options The options for the interceptor, synchronous and runWhen + * + * @return {Number} An ID used to remove interceptor later + */ + use(fulfilled, rejected, options) { + this.handlers.push({ + fulfilled, + rejected, + synchronous: options ? options.synchronous : false, + runWhen: options ? options.runWhen : null + }); + return this.handlers.length - 1; + } + /** + * Remove an interceptor from the stack + * + * @param {Number} id The ID that was returned by `use` + * + * @returns {void} + */ + eject(id) { + if (this.handlers[id]) { + this.handlers[id] = null; + } + } + /** + * Clear all interceptors from the stack + * + * @returns {void} + */ + clear() { + if (this.handlers) { + this.handlers = []; + } + } + /** + * Iterate over all the registered interceptors + * + * This method is particularly useful for skipping over any + * interceptors that may have become `null` calling `eject`. + * + * @param {Function} fn The function to call for each interceptor + * + * @returns {void} + */ + forEach(fn) { + utils_default.forEach(this.handlers, function forEachHandler(h) { + if (h !== null) { + fn(h); + } + }); + } +}; +var InterceptorManager_default = InterceptorManager; + +// ../../../node_modules/axios/lib/defaults/transitional.js +var transitional_default = { + silentJSONParsing: true, + forcedJSONParsing: true, + clarifyTimeoutError: false, + legacyInterceptorReqResOrdering: true +}; + +// ../../../node_modules/axios/lib/platform/browser/classes/URLSearchParams.js +var URLSearchParams_default = typeof URLSearchParams !== "undefined" ? URLSearchParams : AxiosURLSearchParams_default; + +// ../../../node_modules/axios/lib/platform/browser/classes/FormData.js +var FormData_default = typeof FormData !== "undefined" ? FormData : null; + +// ../../../node_modules/axios/lib/platform/browser/classes/Blob.js +var Blob_default = typeof Blob !== "undefined" ? Blob : null; + +// ../../../node_modules/axios/lib/platform/browser/index.js +var browser_default = { + isBrowser: true, + classes: { + URLSearchParams: URLSearchParams_default, + FormData: FormData_default, + Blob: Blob_default + }, + protocols: ["http", "https", "file", "blob", "url", "data"] +}; + +// ../../../node_modules/axios/lib/platform/common/utils.js +var utils_exports = {}; +__export(utils_exports, { + hasBrowserEnv: () => hasBrowserEnv, + hasStandardBrowserEnv: () => hasStandardBrowserEnv, + hasStandardBrowserWebWorkerEnv: () => hasStandardBrowserWebWorkerEnv, + navigator: () => _navigator, + origin: () => origin +}); +var hasBrowserEnv = typeof window !== "undefined" && typeof document !== "undefined"; +var _navigator = typeof navigator === "object" && navigator || void 0; +var hasStandardBrowserEnv = hasBrowserEnv && (!_navigator || ["ReactNative", "NativeScript", "NS"].indexOf(_navigator.product) < 0); +var hasStandardBrowserWebWorkerEnv = (() => { + return typeof WorkerGlobalScope !== "undefined" && // eslint-disable-next-line no-undef + self instanceof WorkerGlobalScope && typeof self.importScripts === "function"; +})(); +var origin = hasBrowserEnv && window.location.href || "http://localhost"; + +// ../../../node_modules/axios/lib/platform/index.js +var platform_default = { + ...utils_exports, + ...browser_default +}; + +// ../../../node_modules/axios/lib/helpers/toURLEncodedForm.js +function toURLEncodedForm(data, options) { + return toFormData_default(data, new platform_default.classes.URLSearchParams(), { + visitor: function(value, key, path, helpers) { + if (platform_default.isNode && utils_default.isBuffer(value)) { + this.append(key, value.toString("base64")); + return false; + } + return helpers.defaultVisitor.apply(this, arguments); + }, + ...options + }); +} + +// ../../../node_modules/axios/lib/helpers/formDataToJSON.js +function parsePropPath(name) { + return utils_default.matchAll(/\w+|\[(\w*)]/g, name).map((match) => { + return match[0] === "[]" ? "" : match[1] || match[0]; + }); +} +function arrayToObject(arr) { + const obj = {}; + const keys2 = Object.keys(arr); + let i; + const len = keys2.length; + let key; + for (i = 0; i < len; i++) { + key = keys2[i]; + obj[key] = arr[key]; + } + return obj; +} +function formDataToJSON(formData) { + function buildPath(path, value, target, index) { + let name = path[index++]; + if (name === "__proto__") return true; + const isNumericKey = Number.isFinite(+name); + const isLast = index >= path.length; + name = !name && utils_default.isArray(target) ? target.length : name; + if (isLast) { + if (utils_default.hasOwnProp(target, name)) { + target[name] = [target[name], value]; + } else { + target[name] = value; + } + return !isNumericKey; + } + if (!target[name] || !utils_default.isObject(target[name])) { + target[name] = []; + } + const result = buildPath(path, value, target[name], index); + if (result && utils_default.isArray(target[name])) { + target[name] = arrayToObject(target[name]); + } + return !isNumericKey; + } + if (utils_default.isFormData(formData) && utils_default.isFunction(formData.entries)) { + const obj = {}; + utils_default.forEachEntry(formData, (name, value) => { + buildPath(parsePropPath(name), value, obj, 0); + }); + return obj; + } + return null; +} +var formDataToJSON_default = formDataToJSON; + +// ../../../node_modules/axios/lib/defaults/index.js +function stringifySafely(rawValue, parser, encoder) { + if (utils_default.isString(rawValue)) { + try { + (parser || JSON.parse)(rawValue); + return utils_default.trim(rawValue); + } catch (e) { + if (e.name !== "SyntaxError") { + throw e; + } + } + } + return (encoder || JSON.stringify)(rawValue); +} +var defaults = { + transitional: transitional_default, + adapter: ["xhr", "http", "fetch"], + transformRequest: [ + function transformRequest(data, headers) { + const contentType = headers.getContentType() || ""; + const hasJSONContentType = contentType.indexOf("application/json") > -1; + const isObjectPayload = utils_default.isObject(data); + if (isObjectPayload && utils_default.isHTMLForm(data)) { + data = new FormData(data); + } + const isFormData3 = utils_default.isFormData(data); + if (isFormData3) { + return hasJSONContentType ? JSON.stringify(formDataToJSON_default(data)) : data; + } + if (utils_default.isArrayBuffer(data) || utils_default.isBuffer(data) || utils_default.isStream(data) || utils_default.isFile(data) || utils_default.isBlob(data) || utils_default.isReadableStream(data)) { + return data; + } + if (utils_default.isArrayBufferView(data)) { + return data.buffer; + } + if (utils_default.isURLSearchParams(data)) { + headers.setContentType("application/x-www-form-urlencoded;charset=utf-8", false); + return data.toString(); + } + let isFileList2; + if (isObjectPayload) { + if (contentType.indexOf("application/x-www-form-urlencoded") > -1) { + return toURLEncodedForm(data, this.formSerializer).toString(); + } + if ((isFileList2 = utils_default.isFileList(data)) || contentType.indexOf("multipart/form-data") > -1) { + const _FormData = this.env && this.env.FormData; + return toFormData_default( + isFileList2 ? { "files[]": data } : data, + _FormData && new _FormData(), + this.formSerializer + ); + } + } + if (isObjectPayload || hasJSONContentType) { + headers.setContentType("application/json", false); + return stringifySafely(data); + } + return data; + } + ], + transformResponse: [ + function transformResponse(data) { + const transitional2 = this.transitional || defaults.transitional; + const forcedJSONParsing = transitional2 && transitional2.forcedJSONParsing; + const JSONRequested = this.responseType === "json"; + if (utils_default.isResponse(data) || utils_default.isReadableStream(data)) { + return data; + } + if (data && utils_default.isString(data) && (forcedJSONParsing && !this.responseType || JSONRequested)) { + const silentJSONParsing = transitional2 && transitional2.silentJSONParsing; + const strictJSONParsing = !silentJSONParsing && JSONRequested; + try { + return JSON.parse(data, this.parseReviver); + } catch (e) { + if (strictJSONParsing) { + if (e.name === "SyntaxError") { + throw AxiosError_default.from(e, AxiosError_default.ERR_BAD_RESPONSE, this, null, this.response); + } + throw e; + } + } + } + return data; + } + ], + /** + * A timeout in milliseconds to abort a request. If set to 0 (default) a + * timeout is not created. + */ + timeout: 0, + xsrfCookieName: "XSRF-TOKEN", + xsrfHeaderName: "X-XSRF-TOKEN", + maxContentLength: -1, + maxBodyLength: -1, + env: { + FormData: platform_default.classes.FormData, + Blob: platform_default.classes.Blob + }, + validateStatus: function validateStatus(status2) { + return status2 >= 200 && status2 < 300; + }, + headers: { + common: { + Accept: "application/json, text/plain, */*", + "Content-Type": void 0 + } + } +}; +utils_default.forEach(["delete", "get", "head", "post", "put", "patch"], (method) => { + defaults.headers[method] = {}; +}); +var defaults_default = defaults; + +// ../../../node_modules/axios/lib/helpers/parseHeaders.js +var ignoreDuplicateOf = utils_default.toObjectSet([ + "age", + "authorization", + "content-length", + "content-type", + "etag", + "expires", + "from", + "host", + "if-modified-since", + "if-unmodified-since", + "last-modified", + "location", + "max-forwards", + "proxy-authorization", + "referer", + "retry-after", + "user-agent" +]); +var parseHeaders_default = (rawHeaders) => { + const parsed = {}; + let key; + let val; + let i; + rawHeaders && rawHeaders.split("\n").forEach(function parser(line) { + i = line.indexOf(":"); + key = line.substring(0, i).trim().toLowerCase(); + val = line.substring(i + 1).trim(); + if (!key || parsed[key] && ignoreDuplicateOf[key]) { + return; + } + if (key === "set-cookie") { + if (parsed[key]) { + parsed[key].push(val); + } else { + parsed[key] = [val]; + } + } else { + parsed[key] = parsed[key] ? parsed[key] + ", " + val : val; + } + }); + return parsed; +}; + +// ../../../node_modules/axios/lib/core/AxiosHeaders.js +var $internals = Symbol("internals"); +function normalizeHeader(header) { + return header && String(header).trim().toLowerCase(); +} +function normalizeValue(value) { + if (value === false || value == null) { + return value; + } + return utils_default.isArray(value) ? value.map(normalizeValue) : String(value); +} +function parseTokens(str) { + const tokens = /* @__PURE__ */ Object.create(null); + const tokensRE = /([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g; + let match; + while (match = tokensRE.exec(str)) { + tokens[match[1]] = match[2]; + } + return tokens; +} +var isValidHeaderName = (str) => /^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(str.trim()); +function matchHeaderValue(context, value, header, filter2, isHeaderNameFilter) { + if (utils_default.isFunction(filter2)) { + return filter2.call(this, value, header); + } + if (isHeaderNameFilter) { + value = header; + } + if (!utils_default.isString(value)) return; + if (utils_default.isString(filter2)) { + return value.indexOf(filter2) !== -1; + } + if (utils_default.isRegExp(filter2)) { + return filter2.test(value); + } +} +function formatHeader(header) { + return header.trim().toLowerCase().replace(/([a-z\d])(\w*)/g, (w, char, str) => { + return char.toUpperCase() + str; + }); +} +function buildAccessors(obj, header) { + const accessorName = utils_default.toCamelCase(" " + header); + ["get", "set", "has"].forEach((methodName) => { + Object.defineProperty(obj, methodName + accessorName, { + value: function(arg1, arg2, arg3) { + return this[methodName].call(this, header, arg1, arg2, arg3); + }, + configurable: true + }); + }); +} +var AxiosHeaders = class { + constructor(headers) { + headers && this.set(headers); + } + set(header, valueOrRewrite, rewrite) { + const self2 = this; + function setHeader(_value, _header, _rewrite) { + const lHeader = normalizeHeader(_header); + if (!lHeader) { + throw new Error("header name must be a non-empty string"); + } + const key = utils_default.findKey(self2, lHeader); + if (!key || self2[key] === void 0 || _rewrite === true || _rewrite === void 0 && self2[key] !== false) { + self2[key || _header] = normalizeValue(_value); + } + } + const setHeaders = (headers, _rewrite) => utils_default.forEach(headers, (_value, _header) => setHeader(_value, _header, _rewrite)); + if (utils_default.isPlainObject(header) || header instanceof this.constructor) { + setHeaders(header, valueOrRewrite); + } else if (utils_default.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) { + setHeaders(parseHeaders_default(header), valueOrRewrite); + } else if (utils_default.isObject(header) && utils_default.isIterable(header)) { + let obj = {}, dest, key; + for (const entry of header) { + if (!utils_default.isArray(entry)) { + throw TypeError("Object iterator must return a key-value pair"); + } + obj[key = entry[0]] = (dest = obj[key]) ? utils_default.isArray(dest) ? [...dest, entry[1]] : [dest, entry[1]] : entry[1]; + } + setHeaders(obj, valueOrRewrite); + } else { + header != null && setHeader(valueOrRewrite, header, rewrite); + } + return this; + } + get(header, parser) { + header = normalizeHeader(header); + if (header) { + const key = utils_default.findKey(this, header); + if (key) { + const value = this[key]; + if (!parser) { + return value; + } + if (parser === true) { + return parseTokens(value); + } + if (utils_default.isFunction(parser)) { + return parser.call(this, value, key); + } + if (utils_default.isRegExp(parser)) { + return parser.exec(value); + } + throw new TypeError("parser must be boolean|regexp|function"); + } + } + } + has(header, matcher) { + header = normalizeHeader(header); + if (header) { + const key = utils_default.findKey(this, header); + return !!(key && this[key] !== void 0 && (!matcher || matchHeaderValue(this, this[key], key, matcher))); + } + return false; + } + delete(header, matcher) { + const self2 = this; + let deleted = false; + function deleteHeader(_header) { + _header = normalizeHeader(_header); + if (_header) { + const key = utils_default.findKey(self2, _header); + if (key && (!matcher || matchHeaderValue(self2, self2[key], key, matcher))) { + delete self2[key]; + deleted = true; + } + } + } + if (utils_default.isArray(header)) { + header.forEach(deleteHeader); + } else { + deleteHeader(header); + } + return deleted; + } + clear(matcher) { + const keys2 = Object.keys(this); + let i = keys2.length; + let deleted = false; + while (i--) { + const key = keys2[i]; + if (!matcher || matchHeaderValue(this, this[key], key, matcher, true)) { + delete this[key]; + deleted = true; + } + } + return deleted; + } + normalize(format) { + const self2 = this; + const headers = {}; + utils_default.forEach(this, (value, header) => { + const key = utils_default.findKey(headers, header); + if (key) { + self2[key] = normalizeValue(value); + delete self2[header]; + return; + } + const normalized = format ? formatHeader(header) : String(header).trim(); + if (normalized !== header) { + delete self2[header]; + } + self2[normalized] = normalizeValue(value); + headers[normalized] = true; + }); + return this; + } + concat(...targets) { + return this.constructor.concat(this, ...targets); + } + toJSON(asStrings) { + const obj = /* @__PURE__ */ Object.create(null); + utils_default.forEach(this, (value, header) => { + value != null && value !== false && (obj[header] = asStrings && utils_default.isArray(value) ? value.join(", ") : value); + }); + return obj; + } + [Symbol.iterator]() { + return Object.entries(this.toJSON())[Symbol.iterator](); + } + toString() { + return Object.entries(this.toJSON()).map(([header, value]) => header + ": " + value).join("\n"); + } + getSetCookie() { + return this.get("set-cookie") || []; + } + get [Symbol.toStringTag]() { + return "AxiosHeaders"; + } + static from(thing) { + return thing instanceof this ? thing : new this(thing); + } + static concat(first, ...targets) { + const computed = new this(first); + targets.forEach((target) => computed.set(target)); + return computed; + } + static accessor(header) { + const internals = this[$internals] = this[$internals] = { + accessors: {} + }; + const accessors = internals.accessors; + const prototype2 = this.prototype; + function defineAccessor(_header) { + const lHeader = normalizeHeader(_header); + if (!accessors[lHeader]) { + buildAccessors(prototype2, _header); + accessors[lHeader] = true; + } + } + utils_default.isArray(header) ? header.forEach(defineAccessor) : defineAccessor(header); + return this; + } +}; +AxiosHeaders.accessor([ + "Content-Type", + "Content-Length", + "Accept", + "Accept-Encoding", + "User-Agent", + "Authorization" +]); +utils_default.reduceDescriptors(AxiosHeaders.prototype, ({ value }, key) => { + let mapped = key[0].toUpperCase() + key.slice(1); + return { + get: () => value, + set(headerValue) { + this[mapped] = headerValue; + } + }; +}); +utils_default.freezeMethods(AxiosHeaders); +var AxiosHeaders_default = AxiosHeaders; + +// ../../../node_modules/axios/lib/core/transformData.js +function transformData(fns, response) { + const config3 = this || defaults_default; + const context = response || config3; + const headers = AxiosHeaders_default.from(context.headers); + let data = context.data; + utils_default.forEach(fns, function transform(fn) { + data = fn.call(config3, data, headers.normalize(), response ? response.status : void 0); + }); + headers.normalize(); + return data; +} + +// ../../../node_modules/axios/lib/cancel/isCancel.js +function isCancel(value) { + return !!(value && value.__CANCEL__); +} + +// ../../../node_modules/axios/lib/cancel/CanceledError.js +var CanceledError = class extends AxiosError_default { + /** + * A `CanceledError` is an object that is thrown when an operation is canceled. + * + * @param {string=} message The message. + * @param {Object=} config The config. + * @param {Object=} request The request. + * + * @returns {CanceledError} The created error. + */ + constructor(message, config3, request2) { + super(message == null ? "canceled" : message, AxiosError_default.ERR_CANCELED, config3, request2); + this.name = "CanceledError"; + this.__CANCEL__ = true; + } +}; +var CanceledError_default = CanceledError; + +// ../../../node_modules/axios/lib/core/settle.js +function settle(resolve, reject, response) { + const validateStatus2 = response.config.validateStatus; + if (!response.status || !validateStatus2 || validateStatus2(response.status)) { + resolve(response); + } else { + reject( + new AxiosError_default( + "Request failed with status code " + response.status, + [AxiosError_default.ERR_BAD_REQUEST, AxiosError_default.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4], + response.config, + response.request, + response + ) + ); + } +} + +// ../../../node_modules/axios/lib/helpers/parseProtocol.js +function parseProtocol(url) { + const match = /^([-+\w]{1,25})(:?\/\/|:)/.exec(url); + return match && match[1] || ""; +} + +// ../../../node_modules/axios/lib/helpers/speedometer.js +function speedometer(samplesCount, min) { + samplesCount = samplesCount || 10; + const bytes = new Array(samplesCount); + const timestamps = new Array(samplesCount); + let head = 0; + let tail = 0; + let firstSampleTS; + min = min !== void 0 ? min : 1e3; + return function push(chunkLength) { + const now2 = Date.now(); + const startedAt = timestamps[tail]; + if (!firstSampleTS) { + firstSampleTS = now2; + } + bytes[head] = chunkLength; + timestamps[head] = now2; + let i = tail; + let bytesCount = 0; + while (i !== head) { + bytesCount += bytes[i++]; + i = i % samplesCount; + } + head = (head + 1) % samplesCount; + if (head === tail) { + tail = (tail + 1) % samplesCount; + } + if (now2 - firstSampleTS < min) { + return; + } + const passed = startedAt && now2 - startedAt; + return passed ? Math.round(bytesCount * 1e3 / passed) : void 0; + }; +} +var speedometer_default = speedometer; + +// ../../../node_modules/axios/lib/helpers/throttle.js +function throttle(fn, freq) { + let timestamp = 0; + let threshold = 1e3 / freq; + let lastArgs; + let timer; + const invoke = (args, now2 = Date.now()) => { + timestamp = now2; + lastArgs = null; + if (timer) { + clearTimeout(timer); + timer = null; + } + fn(...args); + }; + const throttled = (...args) => { + const now2 = Date.now(); + const passed = now2 - timestamp; + if (passed >= threshold) { + invoke(args, now2); + } else { + lastArgs = args; + if (!timer) { + timer = setTimeout(() => { + timer = null; + invoke(lastArgs); + }, threshold - passed); + } + } + }; + const flush = () => lastArgs && invoke(lastArgs); + return [throttled, flush]; +} +var throttle_default = throttle; + +// ../../../node_modules/axios/lib/helpers/progressEventReducer.js +var progressEventReducer = (listener, isDownloadStream, freq = 3) => { + let bytesNotified = 0; + const _speedometer = speedometer_default(50, 250); + return throttle_default((e) => { + const loaded = e.loaded; + const total = e.lengthComputable ? e.total : void 0; + const progressBytes = loaded - bytesNotified; + const rate = _speedometer(progressBytes); + const inRange = loaded <= total; + bytesNotified = loaded; + const data = { + loaded, + total, + progress: total ? loaded / total : void 0, + bytes: progressBytes, + rate: rate ? rate : void 0, + estimated: rate && total && inRange ? (total - loaded) / rate : void 0, + event: e, + lengthComputable: total != null, + [isDownloadStream ? "download" : "upload"]: true + }; + listener(data); + }, freq); +}; +var progressEventDecorator = (total, throttled) => { + const lengthComputable = total != null; + return [ + (loaded) => throttled[0]({ + lengthComputable, + total, + loaded + }), + throttled[1] + ]; +}; +var asyncDecorator = (fn) => (...args) => utils_default.asap(() => fn(...args)); + +// ../../../node_modules/axios/lib/helpers/isURLSameOrigin.js +var isURLSameOrigin_default = platform_default.hasStandardBrowserEnv ? /* @__PURE__ */ ((origin2, isMSIE) => (url) => { + url = new URL(url, platform_default.origin); + return origin2.protocol === url.protocol && origin2.host === url.host && (isMSIE || origin2.port === url.port); +})( + new URL(platform_default.origin), + platform_default.navigator && /(msie|trident)/i.test(platform_default.navigator.userAgent) +) : () => true; + +// ../../../node_modules/axios/lib/helpers/cookies.js +var cookies_default = platform_default.hasStandardBrowserEnv ? ( + // Standard browser envs support document.cookie + { + write(name, value, expires, path, domain, secure, sameSite) { + if (typeof document === "undefined") return; + const cookie = [`${name}=${encodeURIComponent(value)}`]; + if (utils_default.isNumber(expires)) { + cookie.push(`expires=${new Date(expires).toUTCString()}`); + } + if (utils_default.isString(path)) { + cookie.push(`path=${path}`); + } + if (utils_default.isString(domain)) { + cookie.push(`domain=${domain}`); + } + if (secure === true) { + cookie.push("secure"); + } + if (utils_default.isString(sameSite)) { + cookie.push(`SameSite=${sameSite}`); + } + document.cookie = cookie.join("; "); + }, + read(name) { + if (typeof document === "undefined") return null; + const match = document.cookie.match(new RegExp("(?:^|; )" + name + "=([^;]*)")); + return match ? decodeURIComponent(match[1]) : null; + }, + remove(name) { + this.write(name, "", Date.now() - 864e5, "/"); + } + } +) : ( + // Non-standard browser env (web workers, react-native) lack needed support. + { + write() { + }, + read() { + return null; + }, + remove() { + } + } +); + +// ../../../node_modules/axios/lib/helpers/isAbsoluteURL.js +function isAbsoluteURL(url) { + if (typeof url !== "string") { + return false; + } + return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url); +} + +// ../../../node_modules/axios/lib/helpers/combineURLs.js +function combineURLs(baseURL, relativeURL) { + return relativeURL ? baseURL.replace(/\/?\/$/, "") + "/" + relativeURL.replace(/^\/+/, "") : baseURL; +} + +// ../../../node_modules/axios/lib/core/buildFullPath.js +function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) { + let isRelativeUrl = !isAbsoluteURL(requestedURL); + if (baseURL && (isRelativeUrl || allowAbsoluteUrls == false)) { + return combineURLs(baseURL, requestedURL); + } + return requestedURL; +} + +// ../../../node_modules/axios/lib/core/mergeConfig.js +var headersToObject = (thing) => thing instanceof AxiosHeaders_default ? { ...thing } : thing; +function mergeConfig(config1, config22) { + config22 = config22 || {}; + const config3 = {}; + function getMergedValue(target, source, prop, caseless) { + if (utils_default.isPlainObject(target) && utils_default.isPlainObject(source)) { + return utils_default.merge.call({ caseless }, target, source); + } else if (utils_default.isPlainObject(source)) { + return utils_default.merge({}, source); + } else if (utils_default.isArray(source)) { + return source.slice(); + } + return source; + } + function mergeDeepProperties(a, b, prop, caseless) { + if (!utils_default.isUndefined(b)) { + return getMergedValue(a, b, prop, caseless); + } else if (!utils_default.isUndefined(a)) { + return getMergedValue(void 0, a, prop, caseless); + } + } + function valueFromConfig2(a, b) { + if (!utils_default.isUndefined(b)) { + return getMergedValue(void 0, b); + } + } + function defaultToConfig2(a, b) { + if (!utils_default.isUndefined(b)) { + return getMergedValue(void 0, b); + } else if (!utils_default.isUndefined(a)) { + return getMergedValue(void 0, a); + } + } + function mergeDirectKeys(a, b, prop) { + if (prop in config22) { + return getMergedValue(a, b); + } else if (prop in config1) { + return getMergedValue(void 0, a); + } + } + const mergeMap = { + url: valueFromConfig2, + method: valueFromConfig2, + data: valueFromConfig2, + baseURL: defaultToConfig2, + transformRequest: defaultToConfig2, + transformResponse: defaultToConfig2, + paramsSerializer: defaultToConfig2, + timeout: defaultToConfig2, + timeoutMessage: defaultToConfig2, + withCredentials: defaultToConfig2, + withXSRFToken: defaultToConfig2, + adapter: defaultToConfig2, + responseType: defaultToConfig2, + xsrfCookieName: defaultToConfig2, + xsrfHeaderName: defaultToConfig2, + onUploadProgress: defaultToConfig2, + onDownloadProgress: defaultToConfig2, + decompress: defaultToConfig2, + maxContentLength: defaultToConfig2, + maxBodyLength: defaultToConfig2, + beforeRedirect: defaultToConfig2, + transport: defaultToConfig2, + httpAgent: defaultToConfig2, + httpsAgent: defaultToConfig2, + cancelToken: defaultToConfig2, + socketPath: defaultToConfig2, + responseEncoding: defaultToConfig2, + validateStatus: mergeDirectKeys, + headers: (a, b, prop) => mergeDeepProperties(headersToObject(a), headersToObject(b), prop, true) + }; + utils_default.forEach(Object.keys({ ...config1, ...config22 }), function computeConfigValue(prop) { + if (prop === "__proto__" || prop === "constructor" || prop === "prototype") return; + const merge3 = utils_default.hasOwnProp(mergeMap, prop) ? mergeMap[prop] : mergeDeepProperties; + const configValue = merge3(config1[prop], config22[prop], prop); + utils_default.isUndefined(configValue) && merge3 !== mergeDirectKeys || (config3[prop] = configValue); + }); + return config3; +} + +// ../../../node_modules/axios/lib/helpers/resolveConfig.js +var resolveConfig_default = (config3) => { + const newConfig = mergeConfig({}, config3); + let { data, withXSRFToken, xsrfHeaderName, xsrfCookieName, headers, auth } = newConfig; + newConfig.headers = headers = AxiosHeaders_default.from(headers); + newConfig.url = buildURL( + buildFullPath(newConfig.baseURL, newConfig.url, newConfig.allowAbsoluteUrls), + config3.params, + config3.paramsSerializer + ); + if (auth) { + headers.set( + "Authorization", + "Basic " + btoa( + (auth.username || "") + ":" + (auth.password ? unescape(encodeURIComponent(auth.password)) : "") + ) + ); + } + if (utils_default.isFormData(data)) { + if (platform_default.hasStandardBrowserEnv || platform_default.hasStandardBrowserWebWorkerEnv) { + headers.setContentType(void 0); + } else if (utils_default.isFunction(data.getHeaders)) { + const formHeaders = data.getHeaders(); + const allowedHeaders = ["content-type", "content-length"]; + Object.entries(formHeaders).forEach(([key, val]) => { + if (allowedHeaders.includes(key.toLowerCase())) { + headers.set(key, val); + } + }); + } + } + if (platform_default.hasStandardBrowserEnv) { + withXSRFToken && utils_default.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig)); + if (withXSRFToken || withXSRFToken !== false && isURLSameOrigin_default(newConfig.url)) { + const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies_default.read(xsrfCookieName); + if (xsrfValue) { + headers.set(xsrfHeaderName, xsrfValue); + } + } + } + return newConfig; +}; + +// ../../../node_modules/axios/lib/adapters/xhr.js +var isXHRAdapterSupported = typeof XMLHttpRequest !== "undefined"; +var xhr_default = isXHRAdapterSupported && function(config3) { + return new Promise(function dispatchXhrRequest(resolve, reject) { + const _config = resolveConfig_default(config3); + let requestData = _config.data; + const requestHeaders = AxiosHeaders_default.from(_config.headers).normalize(); + let { responseType, onUploadProgress, onDownloadProgress } = _config; + let onCanceled; + let uploadThrottled, downloadThrottled; + let flushUpload, flushDownload; + function done2() { + flushUpload && flushUpload(); + flushDownload && flushDownload(); + _config.cancelToken && _config.cancelToken.unsubscribe(onCanceled); + _config.signal && _config.signal.removeEventListener("abort", onCanceled); + } + let request2 = new XMLHttpRequest(); + request2.open(_config.method.toUpperCase(), _config.url, true); + request2.timeout = _config.timeout; + function onloadend() { + if (!request2) { + return; + } + const responseHeaders = AxiosHeaders_default.from( + "getAllResponseHeaders" in request2 && request2.getAllResponseHeaders() + ); + const responseData = !responseType || responseType === "text" || responseType === "json" ? request2.responseText : request2.response; + const response = { + data: responseData, + status: request2.status, + statusText: request2.statusText, + headers: responseHeaders, + config: config3, + request: request2 + }; + settle( + function _resolve(value) { + resolve(value); + done2(); + }, + function _reject(err) { + reject(err); + done2(); + }, + response + ); + request2 = null; + } + if ("onloadend" in request2) { + request2.onloadend = onloadend; + } else { + request2.onreadystatechange = function handleLoad() { + if (!request2 || request2.readyState !== 4) { + return; + } + if (request2.status === 0 && !(request2.responseURL && request2.responseURL.indexOf("file:") === 0)) { + return; + } + setTimeout(onloadend); + }; + } + request2.onabort = function handleAbort() { + if (!request2) { + return; + } + reject(new AxiosError_default("Request aborted", AxiosError_default.ECONNABORTED, config3, request2)); + request2 = null; + }; + request2.onerror = function handleError(event) { + const msg = event && event.message ? event.message : "Network Error"; + const err = new AxiosError_default(msg, AxiosError_default.ERR_NETWORK, config3, request2); + err.event = event || null; + reject(err); + request2 = null; + }; + request2.ontimeout = function handleTimeout() { + let timeoutErrorMessage = _config.timeout ? "timeout of " + _config.timeout + "ms exceeded" : "timeout exceeded"; + const transitional2 = _config.transitional || transitional_default; + if (_config.timeoutErrorMessage) { + timeoutErrorMessage = _config.timeoutErrorMessage; + } + reject( + new AxiosError_default( + timeoutErrorMessage, + transitional2.clarifyTimeoutError ? AxiosError_default.ETIMEDOUT : AxiosError_default.ECONNABORTED, + config3, + request2 + ) + ); + request2 = null; + }; + requestData === void 0 && requestHeaders.setContentType(null); + if ("setRequestHeader" in request2) { + utils_default.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) { + request2.setRequestHeader(key, val); + }); + } + if (!utils_default.isUndefined(_config.withCredentials)) { + request2.withCredentials = !!_config.withCredentials; + } + if (responseType && responseType !== "json") { + request2.responseType = _config.responseType; + } + if (onDownloadProgress) { + [downloadThrottled, flushDownload] = progressEventReducer(onDownloadProgress, true); + request2.addEventListener("progress", downloadThrottled); + } + if (onUploadProgress && request2.upload) { + [uploadThrottled, flushUpload] = progressEventReducer(onUploadProgress); + request2.upload.addEventListener("progress", uploadThrottled); + request2.upload.addEventListener("loadend", flushUpload); + } + if (_config.cancelToken || _config.signal) { + onCanceled = (cancel) => { + if (!request2) { + return; + } + reject(!cancel || cancel.type ? new CanceledError_default(null, config3, request2) : cancel); + request2.abort(); + request2 = null; + }; + _config.cancelToken && _config.cancelToken.subscribe(onCanceled); + if (_config.signal) { + _config.signal.aborted ? onCanceled() : _config.signal.addEventListener("abort", onCanceled); + } + } + const protocol = parseProtocol(_config.url); + if (protocol && platform_default.protocols.indexOf(protocol) === -1) { + reject( + new AxiosError_default( + "Unsupported protocol " + protocol + ":", + AxiosError_default.ERR_BAD_REQUEST, + config3 + ) + ); + return; + } + request2.send(requestData || null); + }); +}; + +// ../../../node_modules/axios/lib/helpers/composeSignals.js +var composeSignals = (signals, timeout) => { + const { length } = signals = signals ? signals.filter(Boolean) : []; + if (timeout || length) { + let controller = new AbortController(); + let aborted; + const onabort = function(reason) { + if (!aborted) { + aborted = true; + unsubscribe(); + const err = reason instanceof Error ? reason : this.reason; + controller.abort( + err instanceof AxiosError_default ? err : new CanceledError_default(err instanceof Error ? err.message : err) + ); + } + }; + let timer = timeout && setTimeout(() => { + timer = null; + onabort(new AxiosError_default(`timeout of ${timeout}ms exceeded`, AxiosError_default.ETIMEDOUT)); + }, timeout); + const unsubscribe = () => { + if (signals) { + timer && clearTimeout(timer); + timer = null; + signals.forEach((signal2) => { + signal2.unsubscribe ? signal2.unsubscribe(onabort) : signal2.removeEventListener("abort", onabort); + }); + signals = null; + } + }; + signals.forEach((signal2) => signal2.addEventListener("abort", onabort)); + const { signal } = controller; + signal.unsubscribe = () => utils_default.asap(unsubscribe); + return signal; + } +}; +var composeSignals_default = composeSignals; + +// ../../../node_modules/axios/lib/helpers/trackStream.js +var streamChunk = function* (chunk, chunkSize) { + let len = chunk.byteLength; + if (!chunkSize || len < chunkSize) { + yield chunk; + return; + } + let pos = 0; + let end; + while (pos < len) { + end = pos + chunkSize; + yield chunk.slice(pos, end); + pos = end; + } +}; +var readBytes = async function* (iterable, chunkSize) { + for await (const chunk of readStream(iterable)) { + yield* streamChunk(chunk, chunkSize); + } +}; +var readStream = async function* (stream) { + if (stream[Symbol.asyncIterator]) { + yield* stream; + return; + } + const reader = stream.getReader(); + try { + for (; ; ) { + const { done: done2, value } = await reader.read(); + if (done2) { + break; + } + yield value; + } + } finally { + await reader.cancel(); + } +}; +var trackStream = (stream, chunkSize, onProgress, onFinish) => { + const iterator2 = readBytes(stream, chunkSize); + let bytes = 0; + let done2; + let _onFinish = (e) => { + if (!done2) { + done2 = true; + onFinish && onFinish(e); + } + }; + return new ReadableStream( + { + async pull(controller) { + try { + const { done: done3, value } = await iterator2.next(); + if (done3) { + _onFinish(); + controller.close(); + return; + } + let len = value.byteLength; + if (onProgress) { + let loadedBytes = bytes += len; + onProgress(loadedBytes); + } + controller.enqueue(new Uint8Array(value)); + } catch (err) { + _onFinish(err); + throw err; + } + }, + cancel(reason) { + _onFinish(reason); + return iterator2.return(); + } + }, + { + highWaterMark: 2 + } + ); +}; + +// ../../../node_modules/axios/lib/adapters/fetch.js +var DEFAULT_CHUNK_SIZE = 64 * 1024; +var { isFunction: isFunction3 } = utils_default; +var globalFetchAPI = (({ Request: Request2, Response: Response2 }) => ({ + Request: Request2, + Response: Response2 +}))(utils_default.global); +var { ReadableStream: ReadableStream2, TextEncoder: TextEncoder2 } = utils_default.global; +var test = (fn, ...args) => { + try { + return !!fn(...args); + } catch (e) { + return false; + } +}; +var factory = (env) => { + env = utils_default.merge.call( + { + skipUndefined: true + }, + globalFetchAPI, + env + ); + const { fetch: envFetch, Request: Request2, Response: Response2 } = env; + const isFetchSupported = envFetch ? isFunction3(envFetch) : typeof fetch === "function"; + const isRequestSupported = isFunction3(Request2); + const isResponseSupported = isFunction3(Response2); + if (!isFetchSupported) { + return false; + } + const isReadableStreamSupported = isFetchSupported && isFunction3(ReadableStream2); + const encodeText = isFetchSupported && (typeof TextEncoder2 === "function" ? /* @__PURE__ */ ((encoder) => (str) => encoder.encode(str))(new TextEncoder2()) : async (str) => new Uint8Array(await new Request2(str).arrayBuffer())); + const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => { + let duplexAccessed = false; + const hasContentType = new Request2(platform_default.origin, { + body: new ReadableStream2(), + method: "POST", + get duplex() { + duplexAccessed = true; + return "half"; + } + }).headers.has("Content-Type"); + return duplexAccessed && !hasContentType; + }); + const supportsResponseStream = isResponseSupported && isReadableStreamSupported && test(() => utils_default.isReadableStream(new Response2("").body)); + const resolvers = { + stream: supportsResponseStream && ((res) => res.body) + }; + isFetchSupported && (() => { + ["text", "arrayBuffer", "blob", "formData", "stream"].forEach((type) => { + !resolvers[type] && (resolvers[type] = (res, config3) => { + let method = res && res[type]; + if (method) { + return method.call(res); + } + throw new AxiosError_default( + `Response type '${type}' is not supported`, + AxiosError_default.ERR_NOT_SUPPORT, + config3 + ); + }); + }); + })(); + const getBodyLength = async (body) => { + if (body == null) { + return 0; + } + if (utils_default.isBlob(body)) { + return body.size; + } + if (utils_default.isSpecCompliantForm(body)) { + const _request = new Request2(platform_default.origin, { + method: "POST", + body + }); + return (await _request.arrayBuffer()).byteLength; + } + if (utils_default.isArrayBufferView(body) || utils_default.isArrayBuffer(body)) { + return body.byteLength; + } + if (utils_default.isURLSearchParams(body)) { + body = body + ""; + } + if (utils_default.isString(body)) { + return (await encodeText(body)).byteLength; + } + }; + const resolveBodyLength = async (headers, body) => { + const length = utils_default.toFiniteNumber(headers.getContentLength()); + return length == null ? getBodyLength(body) : length; + }; + return async (config3) => { + let { + url, + method, + data, + signal, + cancelToken, + timeout, + onDownloadProgress, + onUploadProgress, + responseType, + headers, + withCredentials = "same-origin", + fetchOptions + } = resolveConfig_default(config3); + let _fetch = envFetch || fetch; + responseType = responseType ? (responseType + "").toLowerCase() : "text"; + let composedSignal = composeSignals_default( + [signal, cancelToken && cancelToken.toAbortSignal()], + timeout + ); + let request2 = null; + const unsubscribe = composedSignal && composedSignal.unsubscribe && (() => { + composedSignal.unsubscribe(); + }); + let requestContentLength; + try { + if (onUploadProgress && supportsRequestStream && method !== "get" && method !== "head" && (requestContentLength = await resolveBodyLength(headers, data)) !== 0) { + let _request = new Request2(url, { + method: "POST", + body: data, + duplex: "half" + }); + let contentTypeHeader; + if (utils_default.isFormData(data) && (contentTypeHeader = _request.headers.get("content-type"))) { + headers.setContentType(contentTypeHeader); + } + if (_request.body) { + const [onProgress, flush] = progressEventDecorator( + requestContentLength, + progressEventReducer(asyncDecorator(onUploadProgress)) + ); + data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush); + } + } + if (!utils_default.isString(withCredentials)) { + withCredentials = withCredentials ? "include" : "omit"; + } + const isCredentialsSupported = isRequestSupported && "credentials" in Request2.prototype; + const resolvedOptions = { + ...fetchOptions, + signal: composedSignal, + method: method.toUpperCase(), + headers: headers.normalize().toJSON(), + body: data, + duplex: "half", + credentials: isCredentialsSupported ? withCredentials : void 0 + }; + request2 = isRequestSupported && new Request2(url, resolvedOptions); + let response = await (isRequestSupported ? _fetch(request2, fetchOptions) : _fetch(url, resolvedOptions)); + const isStreamResponse = supportsResponseStream && (responseType === "stream" || responseType === "response"); + if (supportsResponseStream && (onDownloadProgress || isStreamResponse && unsubscribe)) { + const options = {}; + ["status", "statusText", "headers"].forEach((prop) => { + options[prop] = response[prop]; + }); + const responseContentLength = utils_default.toFiniteNumber(response.headers.get("content-length")); + const [onProgress, flush] = onDownloadProgress && progressEventDecorator( + responseContentLength, + progressEventReducer(asyncDecorator(onDownloadProgress), true) + ) || []; + response = new Response2( + trackStream(response.body, DEFAULT_CHUNK_SIZE, onProgress, () => { + flush && flush(); + unsubscribe && unsubscribe(); + }), + options + ); + } + responseType = responseType || "text"; + let responseData = await resolvers[utils_default.findKey(resolvers, responseType) || "text"]( + response, + config3 + ); + !isStreamResponse && unsubscribe && unsubscribe(); + return await new Promise((resolve, reject) => { + settle(resolve, reject, { + data: responseData, + headers: AxiosHeaders_default.from(response.headers), + status: response.status, + statusText: response.statusText, + config: config3, + request: request2 + }); + }); + } catch (err) { + unsubscribe && unsubscribe(); + if (err && err.name === "TypeError" && /Load failed|fetch/i.test(err.message)) { + throw Object.assign( + new AxiosError_default( + "Network Error", + AxiosError_default.ERR_NETWORK, + config3, + request2, + err && err.response + ), + { + cause: err.cause || err + } + ); + } + throw AxiosError_default.from(err, err && err.code, config3, request2, err && err.response); + } + }; +}; +var seedCache = /* @__PURE__ */ new Map(); +var getFetch = (config3) => { + let env = config3 && config3.env || {}; + const { fetch: fetch2, Request: Request2, Response: Response2 } = env; + const seeds = [Request2, Response2, fetch2]; + let len = seeds.length, i = len, seed, target, map = seedCache; + while (i--) { + seed = seeds[i]; + target = map.get(seed); + target === void 0 && map.set(seed, target = i ? /* @__PURE__ */ new Map() : factory(env)); + map = target; + } + return target; +}; +var adapter = getFetch(); + +// ../../../node_modules/axios/lib/adapters/adapters.js +var knownAdapters = { + http: null_default, + xhr: xhr_default, + fetch: { + get: getFetch + } +}; +utils_default.forEach(knownAdapters, (fn, value) => { + if (fn) { + try { + Object.defineProperty(fn, "name", { value }); + } catch (e) { + } + Object.defineProperty(fn, "adapterName", { value }); + } +}); +var renderReason = (reason) => `- ${reason}`; +var isResolvedHandle = (adapter2) => utils_default.isFunction(adapter2) || adapter2 === null || adapter2 === false; +function getAdapter(adapters, config3) { + adapters = utils_default.isArray(adapters) ? adapters : [adapters]; + const { length } = adapters; + let nameOrAdapter; + let adapter2; + const rejectedReasons = {}; + for (let i = 0; i < length; i++) { + nameOrAdapter = adapters[i]; + let id; + adapter2 = nameOrAdapter; + if (!isResolvedHandle(nameOrAdapter)) { + adapter2 = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()]; + if (adapter2 === void 0) { + throw new AxiosError_default(`Unknown adapter '${id}'`); + } + } + if (adapter2 && (utils_default.isFunction(adapter2) || (adapter2 = adapter2.get(config3)))) { + break; + } + rejectedReasons[id || "#" + i] = adapter2; + } + if (!adapter2) { + const reasons = Object.entries(rejectedReasons).map( + ([id, state]) => `adapter ${id} ` + (state === false ? "is not supported by the environment" : "is not available in the build") + ); + let s = length ? reasons.length > 1 ? "since :\n" + reasons.map(renderReason).join("\n") : " " + renderReason(reasons[0]) : "as no adapter specified"; + throw new AxiosError_default( + `There is no suitable adapter to dispatch the request ` + s, + "ERR_NOT_SUPPORT" + ); + } + return adapter2; +} +var adapters_default = { + /** + * Resolve an adapter from a list of adapter names or functions. + * @type {Function} + */ + getAdapter, + /** + * Exposes all known adapters + * @type {Object} + */ + adapters: knownAdapters +}; + +// ../../../node_modules/axios/lib/core/dispatchRequest.js +function throwIfCancellationRequested(config3) { + if (config3.cancelToken) { + config3.cancelToken.throwIfRequested(); + } + if (config3.signal && config3.signal.aborted) { + throw new CanceledError_default(null, config3); + } +} +function dispatchRequest(config3) { + throwIfCancellationRequested(config3); + config3.headers = AxiosHeaders_default.from(config3.headers); + config3.data = transformData.call(config3, config3.transformRequest); + if (["post", "put", "patch"].indexOf(config3.method) !== -1) { + config3.headers.setContentType("application/x-www-form-urlencoded", false); + } + const adapter2 = adapters_default.getAdapter(config3.adapter || defaults_default.adapter, config3); + return adapter2(config3).then( + function onAdapterResolution(response) { + throwIfCancellationRequested(config3); + response.data = transformData.call(config3, config3.transformResponse, response); + response.headers = AxiosHeaders_default.from(response.headers); + return response; + }, + function onAdapterRejection(reason) { + if (!isCancel(reason)) { + throwIfCancellationRequested(config3); + if (reason && reason.response) { + reason.response.data = transformData.call( + config3, + config3.transformResponse, + reason.response + ); + reason.response.headers = AxiosHeaders_default.from(reason.response.headers); + } + } + return Promise.reject(reason); + } + ); +} + +// ../../../node_modules/axios/lib/env/data.js +var VERSION = "1.13.6"; + +// ../../../node_modules/axios/lib/helpers/validator.js +var validators = {}; +["object", "boolean", "number", "function", "string", "symbol"].forEach((type, i) => { + validators[type] = function validator(thing) { + return typeof thing === type || "a" + (i < 1 ? "n " : " ") + type; + }; +}); +var deprecatedWarnings = {}; +validators.transitional = function transitional(validator, version, message) { + function formatMessage(opt, desc) { + return "[Axios v" + VERSION + "] Transitional option '" + opt + "'" + desc + (message ? ". " + message : ""); + } + return (value, opt, opts) => { + if (validator === false) { + throw new AxiosError_default( + formatMessage(opt, " has been removed" + (version ? " in " + version : "")), + AxiosError_default.ERR_DEPRECATED + ); + } + if (version && !deprecatedWarnings[opt]) { + deprecatedWarnings[opt] = true; + console.warn( + formatMessage( + opt, + " has been deprecated since v" + version + " and will be removed in the near future" + ) + ); + } + return validator ? validator(value, opt, opts) : true; + }; +}; +validators.spelling = function spelling(correctSpelling) { + return (value, opt) => { + console.warn(`${opt} is likely a misspelling of ${correctSpelling}`); + return true; + }; +}; +function assertOptions(options, schema, allowUnknown) { + if (typeof options !== "object") { + throw new AxiosError_default("options must be an object", AxiosError_default.ERR_BAD_OPTION_VALUE); + } + const keys2 = Object.keys(options); + let i = keys2.length; + while (i-- > 0) { + const opt = keys2[i]; + const validator = schema[opt]; + if (validator) { + const value = options[opt]; + const result = value === void 0 || validator(value, opt, options); + if (result !== true) { + throw new AxiosError_default( + "option " + opt + " must be " + result, + AxiosError_default.ERR_BAD_OPTION_VALUE + ); + } + continue; + } + if (allowUnknown !== true) { + throw new AxiosError_default("Unknown option " + opt, AxiosError_default.ERR_BAD_OPTION); + } + } +} +var validator_default = { + assertOptions, + validators +}; + +// ../../../node_modules/axios/lib/core/Axios.js +var validators2 = validator_default.validators; +var Axios = class { + constructor(instanceConfig) { + this.defaults = instanceConfig || {}; + this.interceptors = { + request: new InterceptorManager_default(), + response: new InterceptorManager_default() + }; + } + /** + * Dispatch a request + * + * @param {String|Object} configOrUrl The config specific for this request (merged with this.defaults) + * @param {?Object} config + * + * @returns {Promise} The Promise to be fulfilled + */ + async request(configOrUrl, config3) { + try { + return await this._request(configOrUrl, config3); + } catch (err) { + if (err instanceof Error) { + let dummy = {}; + Error.captureStackTrace ? Error.captureStackTrace(dummy) : dummy = new Error(); + const stack = dummy.stack ? dummy.stack.replace(/^.+\n/, "") : ""; + try { + if (!err.stack) { + err.stack = stack; + } else if (stack && !String(err.stack).endsWith(stack.replace(/^.+\n.+\n/, ""))) { + err.stack += "\n" + stack; + } + } catch (e) { + } + } + throw err; + } + } + _request(configOrUrl, config3) { + if (typeof configOrUrl === "string") { + config3 = config3 || {}; + config3.url = configOrUrl; + } else { + config3 = configOrUrl || {}; + } + config3 = mergeConfig(this.defaults, config3); + const { transitional: transitional2, paramsSerializer, headers } = config3; + if (transitional2 !== void 0) { + validator_default.assertOptions( + transitional2, + { + silentJSONParsing: validators2.transitional(validators2.boolean), + forcedJSONParsing: validators2.transitional(validators2.boolean), + clarifyTimeoutError: validators2.transitional(validators2.boolean), + legacyInterceptorReqResOrdering: validators2.transitional(validators2.boolean) + }, + false + ); + } + if (paramsSerializer != null) { + if (utils_default.isFunction(paramsSerializer)) { + config3.paramsSerializer = { + serialize: paramsSerializer + }; + } else { + validator_default.assertOptions( + paramsSerializer, + { + encode: validators2.function, + serialize: validators2.function + }, + true + ); + } + } + if (config3.allowAbsoluteUrls !== void 0) { + } else if (this.defaults.allowAbsoluteUrls !== void 0) { + config3.allowAbsoluteUrls = this.defaults.allowAbsoluteUrls; + } else { + config3.allowAbsoluteUrls = true; + } + validator_default.assertOptions( + config3, + { + baseUrl: validators2.spelling("baseURL"), + withXsrfToken: validators2.spelling("withXSRFToken") + }, + true + ); + config3.method = (config3.method || this.defaults.method || "get").toLowerCase(); + let contextHeaders = headers && utils_default.merge(headers.common, headers[config3.method]); + headers && utils_default.forEach(["delete", "get", "head", "post", "put", "patch", "common"], (method) => { + delete headers[method]; + }); + config3.headers = AxiosHeaders_default.concat(contextHeaders, headers); + const requestInterceptorChain = []; + let synchronousRequestInterceptors = true; + this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { + if (typeof interceptor.runWhen === "function" && interceptor.runWhen(config3) === false) { + return; + } + synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous; + const transitional3 = config3.transitional || transitional_default; + const legacyInterceptorReqResOrdering = transitional3 && transitional3.legacyInterceptorReqResOrdering; + if (legacyInterceptorReqResOrdering) { + requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected); + } else { + requestInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); + } + }); + const responseInterceptorChain = []; + this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { + responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); + }); + let promise; + let i = 0; + let len; + if (!synchronousRequestInterceptors) { + const chain = [dispatchRequest.bind(this), void 0]; + chain.unshift(...requestInterceptorChain); + chain.push(...responseInterceptorChain); + len = chain.length; + promise = Promise.resolve(config3); + while (i < len) { + promise = promise.then(chain[i++], chain[i++]); + } + return promise; + } + len = requestInterceptorChain.length; + let newConfig = config3; + while (i < len) { + const onFulfilled = requestInterceptorChain[i++]; + const onRejected = requestInterceptorChain[i++]; + try { + newConfig = onFulfilled(newConfig); + } catch (error) { + onRejected.call(this, error); + break; + } + } + try { + promise = dispatchRequest.call(this, newConfig); + } catch (error) { + return Promise.reject(error); + } + i = 0; + len = responseInterceptorChain.length; + while (i < len) { + promise = promise.then(responseInterceptorChain[i++], responseInterceptorChain[i++]); + } + return promise; + } + getUri(config3) { + config3 = mergeConfig(this.defaults, config3); + const fullPath = buildFullPath(config3.baseURL, config3.url, config3.allowAbsoluteUrls); + return buildURL(fullPath, config3.params, config3.paramsSerializer); + } +}; +utils_default.forEach(["delete", "get", "head", "options"], function forEachMethodNoData(method) { + Axios.prototype[method] = function(url, config3) { + return this.request( + mergeConfig(config3 || {}, { + method, + url, + data: (config3 || {}).data + }) + ); + }; +}); +utils_default.forEach(["post", "put", "patch"], function forEachMethodWithData(method) { + function generateHTTPMethod(isForm) { + return function httpMethod(url, data, config3) { + return this.request( + mergeConfig(config3 || {}, { + method, + headers: isForm ? { + "Content-Type": "multipart/form-data" + } : {}, + url, + data + }) + ); + }; + } + Axios.prototype[method] = generateHTTPMethod(); + Axios.prototype[method + "Form"] = generateHTTPMethod(true); +}); +var Axios_default = Axios; + +// ../../../node_modules/axios/lib/cancel/CancelToken.js +var CancelToken = class _CancelToken { + constructor(executor) { + if (typeof executor !== "function") { + throw new TypeError("executor must be a function."); + } + let resolvePromise; + this.promise = new Promise(function promiseExecutor(resolve) { + resolvePromise = resolve; + }); + const token = this; + this.promise.then((cancel) => { + if (!token._listeners) return; + let i = token._listeners.length; + while (i-- > 0) { + token._listeners[i](cancel); + } + token._listeners = null; + }); + this.promise.then = (onfulfilled) => { + let _resolve; + const promise = new Promise((resolve) => { + token.subscribe(resolve); + _resolve = resolve; + }).then(onfulfilled); + promise.cancel = function reject() { + token.unsubscribe(_resolve); + }; + return promise; + }; + executor(function cancel(message, config3, request2) { + if (token.reason) { + return; + } + token.reason = new CanceledError_default(message, config3, request2); + resolvePromise(token.reason); + }); + } + /** + * Throws a `CanceledError` if cancellation has been requested. + */ + throwIfRequested() { + if (this.reason) { + throw this.reason; + } + } + /** + * Subscribe to the cancel signal + */ + subscribe(listener) { + if (this.reason) { + listener(this.reason); + return; + } + if (this._listeners) { + this._listeners.push(listener); + } else { + this._listeners = [listener]; + } + } + /** + * Unsubscribe from the cancel signal + */ + unsubscribe(listener) { + if (!this._listeners) { + return; + } + const index = this._listeners.indexOf(listener); + if (index !== -1) { + this._listeners.splice(index, 1); + } + } + toAbortSignal() { + const controller = new AbortController(); + const abort = (err) => { + controller.abort(err); + }; + this.subscribe(abort); + controller.signal.unsubscribe = () => this.unsubscribe(abort); + return controller.signal; + } + /** + * Returns an object that contains a new `CancelToken` and a function that, when called, + * cancels the `CancelToken`. + */ + static source() { + let cancel; + const token = new _CancelToken(function executor(c) { + cancel = c; + }); + return { + token, + cancel + }; + } +}; +var CancelToken_default = CancelToken; + +// ../../../node_modules/axios/lib/helpers/spread.js +function spread(callback) { + return function wrap(arr) { + return callback.apply(null, arr); + }; +} + +// ../../../node_modules/axios/lib/helpers/isAxiosError.js +function isAxiosError(payload) { + return utils_default.isObject(payload) && payload.isAxiosError === true; +} + +// ../../../node_modules/axios/lib/helpers/HttpStatusCode.js +var HttpStatusCode = { + Continue: 100, + SwitchingProtocols: 101, + Processing: 102, + EarlyHints: 103, + Ok: 200, + Created: 201, + Accepted: 202, + NonAuthoritativeInformation: 203, + NoContent: 204, + ResetContent: 205, + PartialContent: 206, + MultiStatus: 207, + AlreadyReported: 208, + ImUsed: 226, + MultipleChoices: 300, + MovedPermanently: 301, + Found: 302, + SeeOther: 303, + NotModified: 304, + UseProxy: 305, + Unused: 306, + TemporaryRedirect: 307, + PermanentRedirect: 308, + BadRequest: 400, + Unauthorized: 401, + PaymentRequired: 402, + Forbidden: 403, + NotFound: 404, + MethodNotAllowed: 405, + NotAcceptable: 406, + ProxyAuthenticationRequired: 407, + RequestTimeout: 408, + Conflict: 409, + Gone: 410, + LengthRequired: 411, + PreconditionFailed: 412, + PayloadTooLarge: 413, + UriTooLong: 414, + UnsupportedMediaType: 415, + RangeNotSatisfiable: 416, + ExpectationFailed: 417, + ImATeapot: 418, + MisdirectedRequest: 421, + UnprocessableEntity: 422, + Locked: 423, + FailedDependency: 424, + TooEarly: 425, + UpgradeRequired: 426, + PreconditionRequired: 428, + TooManyRequests: 429, + RequestHeaderFieldsTooLarge: 431, + UnavailableForLegalReasons: 451, + InternalServerError: 500, + NotImplemented: 501, + BadGateway: 502, + ServiceUnavailable: 503, + GatewayTimeout: 504, + HttpVersionNotSupported: 505, + VariantAlsoNegotiates: 506, + InsufficientStorage: 507, + LoopDetected: 508, + NotExtended: 510, + NetworkAuthenticationRequired: 511, + WebServerIsDown: 521, + ConnectionTimedOut: 522, + OriginIsUnreachable: 523, + TimeoutOccurred: 524, + SslHandshakeFailed: 525, + InvalidSslCertificate: 526 +}; +Object.entries(HttpStatusCode).forEach(([key, value]) => { + HttpStatusCode[value] = key; +}); +var HttpStatusCode_default = HttpStatusCode; + +// ../../../node_modules/axios/lib/axios.js +function createInstance(defaultConfig) { + const context = new Axios_default(defaultConfig); + const instance = bind(Axios_default.prototype.request, context); + utils_default.extend(instance, Axios_default.prototype, context, { allOwnKeys: true }); + utils_default.extend(instance, context, null, { allOwnKeys: true }); + instance.create = function create(instanceConfig) { + return createInstance(mergeConfig(defaultConfig, instanceConfig)); + }; + return instance; +} +var axios = createInstance(defaults_default); +axios.Axios = Axios_default; +axios.CanceledError = CanceledError_default; +axios.CancelToken = CancelToken_default; +axios.isCancel = isCancel; +axios.VERSION = VERSION; +axios.toFormData = toFormData_default; +axios.AxiosError = AxiosError_default; +axios.Cancel = axios.CanceledError; +axios.all = function all(promises) { + return Promise.all(promises); +}; +axios.spread = spread; +axios.isAxiosError = isAxiosError; +axios.mergeConfig = mergeConfig; +axios.AxiosHeaders = AxiosHeaders_default; +axios.formToJSON = (thing) => formDataToJSON_default(utils_default.isHTMLForm(thing) ? new FormData(thing) : thing); +axios.getAdapter = adapters_default.getAdapter; +axios.HttpStatusCode = HttpStatusCode_default; +axios.default = axios; +var axios_default = axios; + +// ../../../node_modules/axios/index.js +var { + Axios: Axios2, + AxiosError: AxiosError2, + CanceledError: CanceledError2, + isCancel: isCancel2, + CancelToken: CancelToken2, + VERSION: VERSION2, + all: all2, + Cancel, + isAxiosError: isAxiosError2, + spread: spread2, + toFormData: toFormData2, + AxiosHeaders: AxiosHeaders2, + HttpStatusCode: HttpStatusCode2, + formToJSON, + getAdapter: getAdapter2, + mergeConfig: mergeConfig2 +} = axios_default; + +// ../../../node_modules/@inertiajs/core/dist/index.esm.js +var Config = class { + constructor(defaults2) { + this.config = {}; + this.defaults = defaults2; + } + extend(defaults2) { + if (defaults2) { + this.defaults = { ...this.defaults, ...defaults2 }; + } + return this; + } + replace(newConfig) { + this.config = newConfig; + } + get(key) { + return has_default(this.config, key) ? get_default(this.config, key) : get_default(this.defaults, key); + } + set(keyOrValues, value) { + if (typeof keyOrValues === "string") { + set_default(this.config, keyOrValues, value); + } else { + Object.entries(keyOrValues).forEach(([key, val]) => { + set_default(this.config, key, val); + }); + } + } +}; +var config = new Config({ + form: { + recentlySuccessfulDuration: 2e3, + forceIndicesArrayFormatInFormData: true, + withAllErrors: false + }, + future: { + preserveEqualProps: false, + useDataInertiaHeadAttribute: false, + useDialogForErrorModal: false, + useScriptElementForInitialPage: false + }, + prefetch: { + cacheFor: 3e4, + hoverDelay: 75 + } +}); +function debounce2(fn, delay) { + let timeoutID; + return function(...args) { + clearTimeout(timeoutID); + timeoutID = setTimeout(() => fn.apply(this, args), delay); + }; +} +function fireEvent(name, options) { + return document.dispatchEvent(new CustomEvent(`inertia:${name}`, options)); +} +var fireBeforeEvent = (visit) => { + return fireEvent("before", { cancelable: true, detail: { visit } }); +}; +var fireErrorEvent = (errors) => { + return fireEvent("error", { detail: { errors } }); +}; +var fireExceptionEvent = (exception) => { + return fireEvent("exception", { cancelable: true, detail: { exception } }); +}; +var fireFinishEvent = (visit) => { + return fireEvent("finish", { detail: { visit } }); +}; +var fireInvalidEvent = (response) => { + return fireEvent("invalid", { cancelable: true, detail: { response } }); +}; +var fireBeforeUpdateEvent = (page2) => { + return fireEvent("beforeUpdate", { detail: { page: page2 } }); +}; +var fireNavigateEvent = (page2) => { + return fireEvent("navigate", { detail: { page: page2 } }); +}; +var fireProgressEvent = (progress32) => { + return fireEvent("progress", { detail: { progress: progress32 } }); +}; +var fireStartEvent = (visit) => { + return fireEvent("start", { detail: { visit } }); +}; +var fireSuccessEvent = (page2) => { + return fireEvent("success", { detail: { page: page2 } }); +}; +var firePrefetchedEvent = (response, visit) => { + return fireEvent("prefetched", { detail: { fetchedAt: Date.now(), response: response.data, visit } }); +}; +var firePrefetchingEvent = (visit) => { + return fireEvent("prefetching", { detail: { visit } }); +}; +var fireFlashEvent = (flash) => { + return fireEvent("flash", { detail: { flash } }); +}; +var SessionStorage = class { + static set(key, value) { + if (typeof window !== "undefined") { + window.sessionStorage.setItem(key, JSON.stringify(value)); + } + } + static get(key) { + if (typeof window !== "undefined") { + return JSON.parse(window.sessionStorage.getItem(key) || "null"); + } + } + static merge(key, value) { + const existing = this.get(key); + if (existing === null) { + this.set(key, value); + } else { + this.set(key, { ...existing, ...value }); + } + } + static remove(key) { + if (typeof window !== "undefined") { + window.sessionStorage.removeItem(key); + } + } + static removeNested(key, nestedKey) { + const existing = this.get(key); + if (existing !== null) { + delete existing[nestedKey]; + this.set(key, existing); + } + } + static exists(key) { + try { + return this.get(key) !== null; + } catch (error) { + return false; + } + } + static clear() { + if (typeof window !== "undefined") { + window.sessionStorage.clear(); + } + } +}; +SessionStorage.locationVisitKey = "inertiaLocationVisit"; +var encryptHistory = async (data) => { + if (typeof window === "undefined") { + throw new Error("Unable to encrypt history"); + } + const iv = getIv(); + const storedKey = await getKeyFromSessionStorage(); + const key = await getOrCreateKey(storedKey); + if (!key) { + throw new Error("Unable to encrypt history"); + } + const encrypted = await encryptData(iv, key, data); + return encrypted; +}; +var historySessionStorageKeys = { + key: "historyKey", + iv: "historyIv" +}; +var decryptHistory = async (data) => { + const iv = getIv(); + const storedKey = await getKeyFromSessionStorage(); + if (!storedKey) { + throw new Error("Unable to decrypt history"); + } + return await decryptData(iv, storedKey, data); +}; +var encryptData = async (iv, key, data) => { + if (typeof window === "undefined") { + throw new Error("Unable to encrypt history"); + } + if (typeof window.crypto.subtle === "undefined") { + console.warn("Encryption is not supported in this environment. SSL is required."); + return Promise.resolve(data); + } + const textEncoder = new TextEncoder(); + const str = JSON.stringify(data); + const encoded = new Uint8Array(str.length * 3); + const result = textEncoder.encodeInto(str, encoded); + return window.crypto.subtle.encrypt( + { + name: "AES-GCM", + iv + }, + key, + encoded.subarray(0, result.written) + ); +}; +var decryptData = async (iv, key, data) => { + if (typeof window.crypto.subtle === "undefined") { + console.warn("Decryption is not supported in this environment. SSL is required."); + return Promise.resolve(data); + } + const decrypted = await window.crypto.subtle.decrypt( + { + name: "AES-GCM", + iv + }, + key, + data + ); + return JSON.parse(new TextDecoder().decode(decrypted)); +}; +var getIv = () => { + const ivString = SessionStorage.get(historySessionStorageKeys.iv); + if (ivString) { + return new Uint8Array(ivString); + } + const iv = window.crypto.getRandomValues(new Uint8Array(12)); + SessionStorage.set(historySessionStorageKeys.iv, Array.from(iv)); + return iv; +}; +var createKey = async () => { + if (typeof window.crypto.subtle === "undefined") { + console.warn("Encryption is not supported in this environment. SSL is required."); + return Promise.resolve(null); + } + return window.crypto.subtle.generateKey( + { + name: "AES-GCM", + length: 256 + }, + true, + ["encrypt", "decrypt"] + ); +}; +var saveKey = async (key) => { + if (typeof window.crypto.subtle === "undefined") { + console.warn("Encryption is not supported in this environment. SSL is required."); + return Promise.resolve(); + } + const keyData = await window.crypto.subtle.exportKey("raw", key); + SessionStorage.set(historySessionStorageKeys.key, Array.from(new Uint8Array(keyData))); +}; +var getOrCreateKey = async (key) => { + if (key) { + return key; + } + const newKey = await createKey(); + if (!newKey) { + return null; + } + await saveKey(newKey); + return newKey; +}; +var getKeyFromSessionStorage = async () => { + const stringKey = SessionStorage.get(historySessionStorageKeys.key); + if (!stringKey) { + return null; + } + const key = await window.crypto.subtle.importKey( + "raw", + new Uint8Array(stringKey), + { + name: "AES-GCM", + length: 256 + }, + true, + ["encrypt", "decrypt"] + ); + return key; +}; +var objectsAreEqual = (obj1, obj2, excludeKeys) => { + if (obj1 === obj2) { + return true; + } + for (const key in obj1) { + if (excludeKeys.includes(key)) { + continue; + } + if (obj1[key] === obj2[key]) { + continue; + } + if (!compareValues(obj1[key], obj2[key])) { + return false; + } + } + for (const key in obj2) { + if (excludeKeys.includes(key)) { + continue; + } + if (!(key in obj1)) { + return false; + } + } + return true; +}; +var compareValues = (value1, value2) => { + switch (typeof value1) { + case "object": + return objectsAreEqual(value1, value2, []); + case "function": + return value1.toString() === value2.toString(); + default: + return value1 === value2; + } +}; +var conversionMap = { + ms: 1, + s: 1e3, + m: 1e3 * 60, + h: 1e3 * 60 * 60, + d: 1e3 * 60 * 60 * 24 +}; +var timeToMs = (time) => { + if (typeof time === "number") { + return time; + } + for (const [unit, conversion] of Object.entries(conversionMap)) { + if (time.endsWith(unit)) { + return parseFloat(time) * conversion; + } + } + return parseInt(time); +}; +var PrefetchedRequests = class { + constructor() { + this.cached = []; + this.inFlightRequests = []; + this.removalTimers = []; + this.currentUseId = null; + } + add(params, sendFunc, { cacheFor, cacheTags }) { + const inFlight = this.findInFlight(params); + if (inFlight) { + return Promise.resolve(); + } + const existing = this.findCached(params); + if (!params.fresh && existing && existing.staleTimestamp > Date.now()) { + return Promise.resolve(); + } + const [stale, prefetchExpiresIn] = this.extractStaleValues(cacheFor); + const promise = new Promise((resolve, reject) => { + sendFunc({ + ...params, + onCancel: () => { + this.remove(params); + params.onCancel(); + reject(); + }, + onError: (error) => { + this.remove(params); + params.onError(error); + reject(); + }, + onPrefetching(visitParams) { + params.onPrefetching(visitParams); + }, + onPrefetched(response, visit) { + params.onPrefetched(response, visit); + }, + onPrefetchResponse(response) { + resolve(response); + }, + onPrefetchError(error) { + prefetchedRequests.removeFromInFlight(params); + reject(error); + } + }); + }).then((response) => { + this.remove(params); + const pageResponse = response.getPageResponse(); + page.mergeOncePropsIntoResponse(pageResponse); + this.cached.push({ + params: { ...params }, + staleTimestamp: Date.now() + stale, + expiresAt: Date.now() + prefetchExpiresIn, + response: promise, + singleUse: prefetchExpiresIn === 0, + timestamp: Date.now(), + inFlight: false, + tags: Array.isArray(cacheTags) ? cacheTags : [cacheTags] + }); + const oncePropExpiresIn = this.getShortestOncePropTtl(pageResponse); + this.scheduleForRemoval( + params, + oncePropExpiresIn ? Math.min(prefetchExpiresIn, oncePropExpiresIn) : prefetchExpiresIn + ); + this.removeFromInFlight(params); + response.handlePrefetch(); + return response; + }); + this.inFlightRequests.push({ + params: { ...params }, + response: promise, + staleTimestamp: null, + inFlight: true + }); + return promise; + } + removeAll() { + this.cached = []; + this.removalTimers.forEach((removalTimer) => { + clearTimeout(removalTimer.timer); + }); + this.removalTimers = []; + } + removeByTags(tags) { + this.cached = this.cached.filter((prefetched) => { + return !prefetched.tags.some((tag) => tags.includes(tag)); + }); + } + remove(params) { + this.cached = this.cached.filter((prefetched) => { + return !this.paramsAreEqual(prefetched.params, params); + }); + this.clearTimer(params); + } + removeFromInFlight(params) { + this.inFlightRequests = this.inFlightRequests.filter((prefetching) => { + return !this.paramsAreEqual(prefetching.params, params); + }); + } + extractStaleValues(cacheFor) { + const [stale, expires] = this.cacheForToStaleAndExpires(cacheFor); + return [timeToMs(stale), timeToMs(expires)]; + } + cacheForToStaleAndExpires(cacheFor) { + if (!Array.isArray(cacheFor)) { + return [cacheFor, cacheFor]; + } + switch (cacheFor.length) { + case 0: + return [0, 0]; + case 1: + return [cacheFor[0], cacheFor[0]]; + default: + return [cacheFor[0], cacheFor[1]]; + } + } + clearTimer(params) { + const timer = this.removalTimers.find((removalTimer) => { + return this.paramsAreEqual(removalTimer.params, params); + }); + if (timer) { + clearTimeout(timer.timer); + this.removalTimers = this.removalTimers.filter((removalTimer) => removalTimer !== timer); + } + } + scheduleForRemoval(params, expiresIn) { + if (typeof window === "undefined") { + return; + } + this.clearTimer(params); + if (expiresIn > 0) { + const timer = window.setTimeout(() => this.remove(params), expiresIn); + this.removalTimers.push({ + params, + timer + }); + } + } + get(params) { + return this.findCached(params) || this.findInFlight(params); + } + use(prefetched, params) { + const id = `${params.url.pathname}-${Date.now()}-${Math.random().toString(36).substring(7)}`; + this.currentUseId = id; + return prefetched.response.then((response) => { + if (this.currentUseId !== id) { + return; + } + response.mergeParams({ ...params, onPrefetched: () => { + } }); + this.removeSingleUseItems(params); + return response.handle(); + }); + } + removeSingleUseItems(params) { + this.cached = this.cached.filter((prefetched) => { + if (!this.paramsAreEqual(prefetched.params, params)) { + return true; + } + return !prefetched.singleUse; + }); + } + findCached(params) { + return this.cached.find((prefetched) => { + return this.paramsAreEqual(prefetched.params, params); + }) || null; + } + findInFlight(params) { + return this.inFlightRequests.find((prefetched) => { + return this.paramsAreEqual(prefetched.params, params); + }) || null; + } + withoutPurposePrefetchHeader(params) { + const newParams = cloneDeep_default(params); + if (newParams.headers["Purpose"] === "prefetch") { + delete newParams.headers["Purpose"]; + } + return newParams; + } + paramsAreEqual(params1, params2) { + return objectsAreEqual( + this.withoutPurposePrefetchHeader(params1), + this.withoutPurposePrefetchHeader(params2), + [ + "showProgress", + "replace", + "prefetch", + "preserveScroll", + "preserveState", + "onBefore", + "onBeforeUpdate", + "onStart", + "onProgress", + "onFinish", + "onCancel", + "onSuccess", + "onError", + "onFlash", + "onPrefetched", + "onCancelToken", + "onPrefetching", + "async", + "viewTransition" + ] + ); + } + updateCachedOncePropsFromCurrentPage() { + this.cached.forEach((prefetched) => { + prefetched.response.then((response) => { + const pageResponse = response.getPageResponse(); + page.mergeOncePropsIntoResponse(pageResponse, { force: true }); + for (const [group, deferredProps] of Object.entries(pageResponse.deferredProps ?? {})) { + const remaining = deferredProps.filter((prop) => pageResponse.props[prop] === void 0); + if (remaining.length > 0) { + pageResponse.deferredProps[group] = remaining; + } else { + delete pageResponse.deferredProps[group]; + } + } + const oncePropExpiresIn = this.getShortestOncePropTtl(pageResponse); + if (oncePropExpiresIn === null) { + return; + } + const prefetchExpiresIn = prefetched.expiresAt - Date.now(); + const expiresIn = Math.min(prefetchExpiresIn, oncePropExpiresIn); + if (expiresIn > 0) { + this.scheduleForRemoval(prefetched.params, expiresIn); + } else { + this.remove(prefetched.params); + } + }); + }); + } + getShortestOncePropTtl(page2) { + const expiryTimestamps = Object.values(page2.onceProps ?? {}).map((onceProp) => onceProp.expiresAt).filter((expiresAt) => !!expiresAt); + if (expiryTimestamps.length === 0) { + return null; + } + return Math.min(...expiryTimestamps) - Date.now(); + } +}; +var prefetchedRequests = new PrefetchedRequests(); +var elementInViewport = (el) => { + if (el.offsetParent === null) { + return false; + } + const rect = el.getBoundingClientRect(); + const verticallyVisible = rect.top < window.innerHeight && rect.bottom >= 0; + const horizontallyVisible = rect.left < window.innerWidth && rect.right >= 0; + return verticallyVisible && horizontallyVisible; +}; +var getScrollableParent = (element) => { + const allowsVerticalScroll = (el) => { + const computedStyle = window.getComputedStyle(el); + if (["scroll", "overlay"].includes(computedStyle.overflowY)) { + return true; + } + if (computedStyle.overflowY !== "auto") { + return false; + } + if (["visible", "clip"].includes(computedStyle.overflowX)) { + return true; + } + return hasDimensionConstraint(computedStyle.maxHeight, el.style.height) || isConstrainedByLayout(el, "height"); + }; + const allowsHorizontalScroll = (el) => { + const computedStyle = window.getComputedStyle(el); + if (["scroll", "overlay"].includes(computedStyle.overflowX)) { + return true; + } + if (computedStyle.overflowX !== "auto") { + return false; + } + if (["visible", "clip"].includes(computedStyle.overflowY)) { + return true; + } + return hasDimensionConstraint(computedStyle.maxWidth, el.style.width) || isConstrainedByLayout(el, "width"); + }; + const hasDimensionConstraint = (computedMaxDimension, inlineStyleDimension) => { + if (computedMaxDimension && computedMaxDimension !== "none" && computedMaxDimension !== "0px") { + return true; + } + if (inlineStyleDimension && inlineStyleDimension !== "auto" && inlineStyleDimension !== "0") { + return true; + } + return false; + }; + const isConstrainedByLayout = (el, dimension) => { + const parent2 = el.parentElement; + if (!parent2) { + return false; + } + const parentStyle = window.getComputedStyle(parent2); + if (["flex", "inline-flex"].includes(parentStyle.display)) { + const isColumnLayout = ["column", "column-reverse"].includes(parentStyle.flexDirection); + return dimension === "height" ? isColumnLayout : !isColumnLayout; + } + return ["grid", "inline-grid"].includes(parentStyle.display); + }; + let parent = element?.parentElement; + while (parent) { + const allowsScroll = allowsVerticalScroll(parent) || allowsHorizontalScroll(parent); + if (window.getComputedStyle(parent).display !== "contents" && allowsScroll) { + return parent; + } + parent = parent.parentElement; + } + return null; +}; +var getElementsInViewportFromCollection = (elements, referenceElement) => { + if (!referenceElement) { + return elements.filter((element) => elementInViewport(element)); + } + const referenceIndex = elements.indexOf(referenceElement); + const upwardElements = []; + const downwardElements = []; + for (let i = referenceIndex; i >= 0; i--) { + const element = elements[i]; + if (elementInViewport(element)) { + upwardElements.push(element); + } else { + break; + } + } + for (let i = referenceIndex + 1; i < elements.length; i++) { + const element = elements[i]; + if (elementInViewport(element)) { + downwardElements.push(element); + } else { + break; + } + } + return [...upwardElements.reverse(), ...downwardElements]; +}; +var requestAnimationFrame = (cb, times = 1) => { + window.requestAnimationFrame(() => { + if (times > 1) { + requestAnimationFrame(cb, times - 1); + } else { + cb(); + } + }); +}; +var getInitialPageFromDOM = (id, useScriptElement = false) => { + if (typeof window === "undefined") { + return null; + } + if (!useScriptElement) { + const el = document.getElementById(id); + if (el?.dataset.page) { + return JSON.parse(el.dataset.page); + } + } + const scriptEl = document.querySelector(`script[data-page="${id}"][type="application/json"]`); + if (scriptEl?.textContent) { + return JSON.parse(scriptEl.textContent); + } + return null; +}; +var isServer = typeof window === "undefined"; +var isFirefox = !isServer && /Firefox/i.test(window.navigator.userAgent); +var Scroll = class { + static save() { + history.saveScrollPositions(this.getScrollRegions()); + } + static getScrollRegions() { + return Array.from(this.regions()).map((region) => ({ + top: region.scrollTop, + left: region.scrollLeft + })); + } + static regions() { + return document.querySelectorAll("[scroll-region]"); + } + static scrollToTop() { + if (isFirefox && getComputedStyle(document.documentElement).scrollBehavior === "smooth") { + return requestAnimationFrame(() => window.scrollTo(0, 0), 2); + } + window.scrollTo(0, 0); + } + static reset() { + const anchorHash = isServer ? null : window.location.hash; + if (!anchorHash) { + this.scrollToTop(); + } + this.regions().forEach((region) => { + if (typeof region.scrollTo === "function") { + region.scrollTo(0, 0); + } else { + region.scrollTop = 0; + region.scrollLeft = 0; + } + }); + this.save(); + this.scrollToAnchor(); + } + static scrollToAnchor() { + const anchorHash = isServer ? null : window.location.hash; + if (anchorHash) { + setTimeout(() => { + const anchorElement = document.getElementById(anchorHash.slice(1)); + anchorElement ? anchorElement.scrollIntoView() : this.scrollToTop(); + }); + } + } + static restore(scrollRegions) { + if (isServer) { + return; + } + window.requestAnimationFrame(() => { + this.restoreDocument(); + this.restoreScrollRegions(scrollRegions); + }); + } + static restoreScrollRegions(scrollRegions) { + if (isServer) { + return; + } + this.regions().forEach((region, index) => { + const scrollPosition = scrollRegions[index]; + if (!scrollPosition) { + return; + } + if (typeof region.scrollTo === "function") { + region.scrollTo(scrollPosition.left, scrollPosition.top); + } else { + region.scrollTop = scrollPosition.top; + region.scrollLeft = scrollPosition.left; + } + }); + } + static restoreDocument() { + const scrollPosition = history.getDocumentScrollPosition(); + window.scrollTo(scrollPosition.left, scrollPosition.top); + } + static onScroll(event) { + const target = event.target; + if (typeof target.hasAttribute === "function" && target.hasAttribute("scroll-region")) { + this.save(); + } + } + static onWindowScroll() { + history.saveDocumentScrollPosition({ + top: window.scrollY, + left: window.scrollX + }); + } +}; +var isFile2 = (value) => typeof File !== "undefined" && value instanceof File || value instanceof Blob || typeof FileList !== "undefined" && value instanceof FileList && value.length > 0; +function hasFiles(data) { + return isFile2(data) || data instanceof FormData && Array.from(data.values()).some((value) => hasFiles(value)) || typeof data === "object" && data !== null && Object.values(data).some((value) => hasFiles(value)); +} +var isFormData2 = (value) => value instanceof FormData; +function objectToFormData(source, form = new FormData(), parentKey = null, queryStringArrayFormat = "brackets") { + source = source || {}; + for (const key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + append2(form, composeKey(parentKey, key, "indices"), source[key], queryStringArrayFormat); + } + } + return form; +} +function composeKey(parent, key, format) { + if (!parent) { + return key; + } + return format === "brackets" ? `${parent}[]` : `${parent}[${key}]`; +} +function append2(form, key, value, format) { + if (Array.isArray(value)) { + return Array.from(value.keys()).forEach( + (index) => append2(form, composeKey(key, index.toString(), format), value[index], format) + ); + } else if (value instanceof Date) { + return form.append(key, value.toISOString()); + } else if (value instanceof File) { + return form.append(key, value, value.name); + } else if (value instanceof Blob) { + return form.append(key, value); + } else if (typeof value === "boolean") { + return form.append(key, value ? "1" : "0"); + } else if (typeof value === "string") { + return form.append(key, value); + } else if (typeof value === "number") { + return form.append(key, `${value}`); + } else if (value === null || value === void 0) { + return form.append(key, ""); + } + objectToFormData(value, form, key, format); +} +function hrefToUrl(href) { + return new URL(href.toString(), typeof window === "undefined" ? void 0 : window.location.toString()); +} +var transformUrlAndData = (href, data, method, forceFormData, queryStringArrayFormat) => { + let url = typeof href === "string" ? hrefToUrl(href) : href; + if ((hasFiles(data) || forceFormData) && !isFormData2(data)) { + if (config.get("form.forceIndicesArrayFormatInFormData")) { + queryStringArrayFormat = "indices"; + } + data = objectToFormData(data, new FormData(), null, queryStringArrayFormat); + } + if (isFormData2(data)) { + return [url, data]; + } + const [_href, _data] = mergeDataIntoQueryString(method, url, data, queryStringArrayFormat); + return [hrefToUrl(_href), _data]; +}; +function mergeDataIntoQueryString(method, href, data, qsArrayFormat = "brackets") { + const hasDataForQueryString = method === "get" && !isFormData2(data) && Object.keys(data).length > 0; + const hasHost = urlHasProtocol(href.toString()); + const hasAbsolutePath = hasHost || href.toString().startsWith("/") || href.toString() === ""; + const hasRelativePath = !hasAbsolutePath && !href.toString().startsWith("#") && !href.toString().startsWith("?"); + const hasRelativePathWithDotPrefix = /^[.]{1,2}([/]|$)/.test(href.toString()); + const hasSearch = href.toString().includes("?") || hasDataForQueryString; + const hasHash = href.toString().includes("#"); + const url = new URL(href.toString(), typeof window === "undefined" ? "http://localhost" : window.location.toString()); + if (hasDataForQueryString) { + const hasIndices = /\[\d+\]/.test(decodeURIComponent(url.search)); + const parseOptions = { ignoreQueryPrefix: true, allowSparse: true }; + url.search = qs.stringify( + { ...qs.parse(url.search, parseOptions), ...data }, + { + encodeValuesOnly: true, + arrayFormat: hasIndices ? "indices" : qsArrayFormat + } + ); + } + return [ + [ + hasHost ? `${url.protocol}//${url.host}` : "", + hasAbsolutePath ? url.pathname : "", + hasRelativePath ? url.pathname.substring(hasRelativePathWithDotPrefix ? 0 : 1) : "", + hasSearch ? url.search : "", + hasHash ? url.hash : "" + ].join(""), + hasDataForQueryString ? {} : data + ]; +} +function urlWithoutHash(url) { + url = new URL(url.href); + url.hash = ""; + return url; +} +var setHashIfSameUrl = (originUrl, destinationUrl) => { + if (originUrl.hash && !destinationUrl.hash && urlWithoutHash(originUrl).href === destinationUrl.href) { + destinationUrl.hash = originUrl.hash; + } +}; +var isSameUrlWithoutHash = (url1, url2) => { + return urlWithoutHash(url1).href === urlWithoutHash(url2).href; +}; +var isSameUrlWithoutQueryOrHash = (url1, url2) => { + return url1.origin === url2.origin && url1.pathname === url2.pathname; +}; +function isUrlMethodPair(href) { + return href !== null && typeof href === "object" && href !== void 0 && "url" in href && "method" in href; +} +function urlHasProtocol(url) { + return /^([a-z][a-z0-9+.-]*:)?\/\/[^/]/i.test(url); +} +function urlToString(url, absolute) { + const urlObj = typeof url === "string" ? hrefToUrl(url) : url; + return absolute ? `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}${urlObj.search}${urlObj.hash}` : `${urlObj.pathname}${urlObj.search}${urlObj.hash}`; +} +var CurrentPage = class { + constructor() { + this.componentId = {}; + this.listeners = []; + this.isFirstPageLoad = true; + this.cleared = false; + this.pendingDeferredProps = null; + this.historyQuotaExceeded = false; + } + init({ + initialPage, + swapComponent: swapComponent2, + resolveComponent, + onFlash + }) { + this.page = { ...initialPage, flash: initialPage.flash ?? {} }; + this.swapComponent = swapComponent2; + this.resolveComponent = resolveComponent; + this.onFlashCallback = onFlash; + eventHandler.on("historyQuotaExceeded", () => { + this.historyQuotaExceeded = true; + }); + return this; + } + set(page2, { + replace = false, + preserveScroll = false, + preserveState = false, + viewTransition = false + } = {}) { + if (Object.keys(page2.deferredProps || {}).length) { + this.pendingDeferredProps = { + deferredProps: page2.deferredProps, + component: page2.component, + url: page2.url + }; + if (page2.initialDeferredProps === void 0) { + page2.initialDeferredProps = page2.deferredProps; + } + } + this.componentId = {}; + const componentId = this.componentId; + if (page2.clearHistory) { + history.clear(); + } + return this.resolve(page2.component).then((component) => { + if (componentId !== this.componentId) { + return; + } + page2.rememberedState ?? (page2.rememberedState = {}); + const isServer3 = typeof window === "undefined"; + const location = !isServer3 ? window.location : new URL(page2.url); + const scrollRegions = !isServer3 && preserveScroll ? Scroll.getScrollRegions() : []; + replace = replace || isSameUrlWithoutHash(hrefToUrl(page2.url), location); + const pageForHistory = { ...page2, flash: {} }; + return new Promise( + (resolve) => replace ? history.replaceState(pageForHistory, resolve) : history.pushState(pageForHistory, resolve) + ).then(() => { + const isNewComponent = !this.isTheSame(page2); + if (!isNewComponent && Object.keys(page2.props.errors || {}).length > 0) { + viewTransition = false; + } + this.page = page2; + this.cleared = false; + if (this.hasOnceProps()) { + prefetchedRequests.updateCachedOncePropsFromCurrentPage(); + } + if (isNewComponent) { + this.fireEventsFor("newComponent"); + } + if (this.isFirstPageLoad) { + this.fireEventsFor("firstLoad"); + } + this.isFirstPageLoad = false; + if (this.historyQuotaExceeded) { + this.historyQuotaExceeded = false; + return; + } + return this.swap({ + component, + page: page2, + preserveState, + viewTransition + }).then(() => { + if (preserveScroll) { + window.requestAnimationFrame(() => Scroll.restoreScrollRegions(scrollRegions)); + } else { + Scroll.reset(); + } + if (this.pendingDeferredProps && this.pendingDeferredProps.component === page2.component && this.pendingDeferredProps.url === page2.url) { + eventHandler.fireInternalEvent("loadDeferredProps", this.pendingDeferredProps.deferredProps); + } + this.pendingDeferredProps = null; + if (!replace) { + fireNavigateEvent(page2); + } + }); + }); + }); + } + setQuietly(page2, { + preserveState = false + } = {}) { + return this.resolve(page2.component).then((component) => { + this.page = page2; + this.cleared = false; + history.setCurrent(page2); + return this.swap({ component, page: page2, preserveState, viewTransition: false }); + }); + } + clear() { + this.cleared = true; + } + isCleared() { + return this.cleared; + } + get() { + return this.page; + } + getWithoutFlashData() { + return { ...this.page, flash: {} }; + } + hasOnceProps() { + return Object.keys(this.page.onceProps ?? {}).length > 0; + } + merge(data) { + this.page = { ...this.page, ...data }; + } + setFlash(flash) { + this.page = { ...this.page, flash }; + this.onFlashCallback?.(flash); + } + setUrlHash(hash) { + if (!this.page.url.includes(hash)) { + this.page.url += hash; + } + } + remember(data) { + this.page.rememberedState = data; + } + swap({ + component, + page: page2, + preserveState, + viewTransition + }) { + const doSwap = () => this.swapComponent({ component, page: page2, preserveState }); + if (!viewTransition || !document?.startViewTransition) { + return doSwap(); + } + const viewTransitionCallback = typeof viewTransition === "boolean" ? () => null : viewTransition; + return new Promise((resolve) => { + const transitionResult = document.startViewTransition(() => doSwap().then(resolve)); + viewTransitionCallback(transitionResult); + }); + } + resolve(component) { + return Promise.resolve(this.resolveComponent(component)); + } + isTheSame(page2) { + return this.page.component === page2.component; + } + on(event, callback) { + this.listeners.push({ event, callback }); + return () => { + this.listeners = this.listeners.filter((listener) => listener.event !== event && listener.callback !== callback); + }; + } + fireEventsFor(event) { + this.listeners.filter((listener) => listener.event === event).forEach((listener) => listener.callback()); + } + mergeOncePropsIntoResponse(response, { force = false } = {}) { + Object.entries(response.onceProps ?? {}).forEach(([key, onceProp]) => { + const existingOnceProp = this.page.onceProps?.[key]; + if (existingOnceProp === void 0) { + return; + } + if (force || response.props[onceProp.prop] === void 0) { + response.props[onceProp.prop] = this.page.props[existingOnceProp.prop]; + response.onceProps[key].expiresAt = existingOnceProp.expiresAt; + } + }); + } +}; +var page = new CurrentPage(); +var Queue = class { + constructor() { + this.items = []; + this.processingPromise = null; + } + add(item) { + this.items.push(item); + return this.process(); + } + process() { + this.processingPromise ?? (this.processingPromise = this.processNext().finally(() => { + this.processingPromise = null; + })); + return this.processingPromise; + } + processNext() { + const next = this.items.shift(); + if (next) { + return Promise.resolve(next()).then(() => this.processNext()); + } + return Promise.resolve(); + } +}; +var isServer2 = typeof window === "undefined"; +var queue = new Queue(); +var isChromeIOS = !isServer2 && /CriOS/.test(window.navigator.userAgent); +var History = class { + constructor() { + this.rememberedState = "rememberedState"; + this.scrollRegions = "scrollRegions"; + this.preserveUrl = false; + this.current = {}; + this.initialState = null; + } + remember(data, key) { + this.replaceState({ + ...page.getWithoutFlashData(), + rememberedState: { + ...page.get()?.rememberedState ?? {}, + [key]: data + } + }); + } + restore(key) { + if (!isServer2) { + return this.current[this.rememberedState]?.[key] !== void 0 ? this.current[this.rememberedState]?.[key] : this.initialState?.[this.rememberedState]?.[key]; + } + } + pushState(page2, cb = null) { + if (isServer2) { + return; + } + if (this.preserveUrl) { + cb && cb(); + return; + } + this.current = page2; + queue.add(() => { + return this.getPageData(page2).then((data) => { + const doPush = () => this.doPushState({ page: data }, page2.url).then(() => cb?.()); + if (isChromeIOS) { + return new Promise((resolve) => { + setTimeout(() => doPush().then(resolve)); + }); + } + return doPush(); + }); + }); + } + clonePageProps(page2) { + try { + structuredClone(page2.props); + return page2; + } catch { + return { + ...page2, + props: cloneDeep_default(page2.props) + }; + } + } + getPageData(page2) { + const pageWithClonedProps = this.clonePageProps(page2); + return new Promise((resolve) => { + return page2.encryptHistory ? encryptHistory(pageWithClonedProps).then(resolve) : resolve(pageWithClonedProps); + }); + } + processQueue() { + return queue.process(); + } + decrypt(page2 = null) { + if (isServer2) { + return Promise.resolve(page2 ?? page.get()); + } + const pageData = page2 ?? window.history.state?.page; + return this.decryptPageData(pageData).then((data) => { + if (!data) { + throw new Error("Unable to decrypt history"); + } + if (this.initialState === null) { + this.initialState = data ?? void 0; + } else { + this.current = data ?? {}; + } + return data; + }); + } + decryptPageData(pageData) { + return pageData instanceof ArrayBuffer ? decryptHistory(pageData) : Promise.resolve(pageData); + } + saveScrollPositions(scrollRegions) { + queue.add(() => { + return Promise.resolve().then(() => { + if (!window.history.state?.page) { + return; + } + if (isEqual_default(this.getScrollRegions(), scrollRegions)) { + return; + } + return this.doReplaceState({ + page: window.history.state.page, + scrollRegions + }); + }); + }); + } + saveDocumentScrollPosition(scrollRegion) { + queue.add(() => { + return Promise.resolve().then(() => { + if (!window.history.state?.page) { + return; + } + if (isEqual_default(this.getDocumentScrollPosition(), scrollRegion)) { + return; + } + return this.doReplaceState({ + page: window.history.state.page, + documentScrollPosition: scrollRegion + }); + }); + }); + } + getScrollRegions() { + return window.history.state?.scrollRegions || []; + } + getDocumentScrollPosition() { + return window.history.state?.documentScrollPosition || { top: 0, left: 0 }; + } + replaceState(page2, cb = null) { + if (isEqual_default(this.current, page2)) { + cb && cb(); + return; + } + const { flash, ...pageWithoutFlash } = page2; + page.merge(pageWithoutFlash); + if (isServer2) { + return; + } + if (this.preserveUrl) { + cb && cb(); + return; + } + this.current = page2; + queue.add(() => { + return this.getPageData(page2).then((data) => { + const doReplace = () => this.doReplaceState({ page: data }, page2.url).then(() => cb?.()); + if (isChromeIOS) { + return new Promise((resolve) => { + setTimeout(() => doReplace().then(resolve)); + }); + } + return doReplace(); + }); + }); + } + isHistoryThrottleError(error) { + return error instanceof Error && error.name === "SecurityError" && (error.message.includes("history.pushState") || error.message.includes("history.replaceState")); + } + isQuotaExceededError(error) { + return error instanceof Error && error.name === "QuotaExceededError"; + } + withThrottleProtection(cb) { + return Promise.resolve().then(() => { + try { + return cb(); + } catch (error) { + if (!this.isHistoryThrottleError(error)) { + throw error; + } + console.error(error.message); + } + }); + } + doReplaceState(data, url) { + return this.withThrottleProtection(() => { + window.history.replaceState( + { + ...data, + scrollRegions: data.scrollRegions ?? window.history.state?.scrollRegions, + documentScrollPosition: data.documentScrollPosition ?? window.history.state?.documentScrollPosition + }, + "", + url + ); + }); + } + doPushState(data, url) { + return this.withThrottleProtection(() => { + try { + window.history.pushState(data, "", url); + } catch (error) { + if (!this.isQuotaExceededError(error)) { + throw error; + } + eventHandler.fireInternalEvent("historyQuotaExceeded", url); + } + }); + } + getState(key, defaultValue) { + return this.current?.[key] ?? defaultValue; + } + deleteState(key) { + if (this.current[key] !== void 0) { + delete this.current[key]; + this.replaceState(this.current); + } + } + clearInitialState(key) { + if (this.initialState && this.initialState[key] !== void 0) { + delete this.initialState[key]; + } + } + browserHasHistoryEntry() { + return !isServer2 && !!window.history.state?.page; + } + clear() { + SessionStorage.remove(historySessionStorageKeys.key); + SessionStorage.remove(historySessionStorageKeys.iv); + } + setCurrent(page2) { + this.current = page2; + } + isValidState(state) { + return !!state.page; + } + getAllState() { + return this.current; + } +}; +if (typeof window !== "undefined" && window.history.scrollRestoration) { + window.history.scrollRestoration = "manual"; +} +var history = new History(); +var EventHandler = class { + constructor() { + this.internalListeners = []; + } + init() { + if (typeof window !== "undefined") { + window.addEventListener("popstate", this.handlePopstateEvent.bind(this)); + window.addEventListener("pageshow", this.handlePageshowEvent.bind(this)); + window.addEventListener("scroll", debounce2(Scroll.onWindowScroll.bind(Scroll), 100), true); + } + if (typeof document !== "undefined") { + document.addEventListener("scroll", debounce2(Scroll.onScroll.bind(Scroll), 100), true); + } + } + onGlobalEvent(type, callback) { + const listener = ((event) => { + const response = callback(event); + if (event.cancelable && !event.defaultPrevented && response === false) { + event.preventDefault(); + } + }); + return this.registerListener(`inertia:${type}`, listener); + } + on(event, callback) { + this.internalListeners.push({ event, listener: callback }); + return () => { + this.internalListeners = this.internalListeners.filter((listener) => listener.listener !== callback); + }; + } + onMissingHistoryItem() { + page.clear(); + this.fireInternalEvent("missingHistoryItem"); + } + fireInternalEvent(event, ...args) { + this.internalListeners.filter((listener) => listener.event === event).forEach((listener) => listener.listener(...args)); + } + registerListener(type, listener) { + document.addEventListener(type, listener); + return () => document.removeEventListener(type, listener); + } + // bfcache restores pages without firing `popstate`, so we use `pageshow` to + // re-validate encrypted history entries after `clearHistory` removed the keys. + // https://web.dev/articles/bfcache + handlePageshowEvent(event) { + if (event.persisted) { + history.decrypt().catch(() => this.onMissingHistoryItem()); + } + } + handlePopstateEvent(event) { + const state = event.state || null; + if (state === null) { + const url = hrefToUrl(page.get().url); + url.hash = window.location.hash; + history.replaceState({ ...page.getWithoutFlashData(), url: url.href }); + Scroll.reset(); + return; + } + if (!history.isValidState(state)) { + return this.onMissingHistoryItem(); + } + history.decrypt(state.page).then((data) => { + if (page.get().version !== data.version) { + this.onMissingHistoryItem(); + return; + } + router.cancelAll({ prefetch: false }); + page.setQuietly(data, { preserveState: false }).then(() => { + Scroll.restore(history.getScrollRegions()); + fireNavigateEvent(page.get()); + const pendingDeferred = {}; + const pageProps = page.get().props; + for (const [group, props] of Object.entries(data.initialDeferredProps ?? data.deferredProps ?? {})) { + const missing = props.filter((prop) => pageProps[prop] === void 0); + if (missing.length > 0) { + pendingDeferred[group] = missing; + } + } + if (Object.keys(pendingDeferred).length > 0) { + this.fireInternalEvent("loadDeferredProps", pendingDeferred); + } + }); + }).catch(() => { + this.onMissingHistoryItem(); + }); + } +}; +var eventHandler = new EventHandler(); +var NavigationType = class { + constructor() { + this.type = this.resolveType(); + } + resolveType() { + if (typeof window === "undefined") { + return "navigate"; + } + if (window.performance && window.performance.getEntriesByType && window.performance.getEntriesByType("navigation").length > 0) { + return window.performance.getEntriesByType("navigation")[0].type; + } + return "navigate"; + } + get() { + return this.type; + } + isBackForward() { + return this.type === "back_forward"; + } + isReload() { + return this.type === "reload"; + } +}; +var navigationType = new NavigationType(); +var InitialVisit = class { + static handle() { + this.clearRememberedStateOnReload(); + const scenarios = [this.handleBackForward, this.handleLocation, this.handleDefault]; + scenarios.find((handler) => handler.bind(this)()); + } + static clearRememberedStateOnReload() { + if (navigationType.isReload()) { + history.deleteState(history.rememberedState); + history.clearInitialState(history.rememberedState); + } + } + static handleBackForward() { + if (!navigationType.isBackForward() || !history.browserHasHistoryEntry()) { + return false; + } + const scrollRegions = history.getScrollRegions(); + history.decrypt().then((data) => { + page.set(data, { preserveScroll: true, preserveState: true }).then(() => { + Scroll.restore(scrollRegions); + fireNavigateEvent(page.get()); + }); + }).catch(() => { + eventHandler.onMissingHistoryItem(); + }); + return true; + } + /** + * @link https://inertiajs.com/redirects#external-redirects + */ + static handleLocation() { + if (!SessionStorage.exists(SessionStorage.locationVisitKey)) { + return false; + } + const locationVisit = SessionStorage.get(SessionStorage.locationVisitKey) || {}; + SessionStorage.remove(SessionStorage.locationVisitKey); + if (typeof window !== "undefined") { + page.setUrlHash(window.location.hash); + } + history.decrypt(page.get()).then(() => { + const rememberedState = history.getState(history.rememberedState, {}); + const scrollRegions = history.getScrollRegions(); + page.remember(rememberedState); + page.set(page.get(), { + preserveScroll: locationVisit.preserveScroll, + preserveState: true + }).then(() => { + if (locationVisit.preserveScroll) { + Scroll.restore(scrollRegions); + } + fireNavigateEvent(page.get()); + }); + }).catch(() => { + eventHandler.onMissingHistoryItem(); + }); + return true; + } + static handleDefault() { + if (typeof window !== "undefined") { + page.setUrlHash(window.location.hash); + } + page.set(page.get(), { preserveScroll: true, preserveState: true }).then(() => { + if (navigationType.isReload()) { + Scroll.restore(history.getScrollRegions()); + } else { + Scroll.scrollToAnchor(); + } + const page2 = page.get(); + fireNavigateEvent(page2); + const flash = page2.flash; + if (Object.keys(flash).length > 0) { + queueMicrotask(() => fireFlashEvent(flash)); + } + }); + } +}; +var Poll = class { + constructor(interval, cb, options) { + this.id = null; + this.throttle = false; + this.keepAlive = false; + this.cbCount = 0; + this.keepAlive = options.keepAlive ?? false; + this.cb = cb; + this.interval = interval; + if (options.autoStart ?? true) { + this.start(); + } + } + stop() { + if (this.id) { + clearInterval(this.id); + } + } + start() { + if (typeof window === "undefined") { + return; + } + this.stop(); + this.id = window.setInterval(() => { + if (!this.throttle || this.cbCount % 10 === 0) { + this.cb(); + } + if (this.throttle) { + this.cbCount++; + } + }, this.interval); + } + isInBackground(hidden) { + this.throttle = this.keepAlive ? false : hidden; + if (this.throttle) { + this.cbCount = 0; + } + } +}; +var Polls = class { + constructor() { + this.polls = []; + this.setupVisibilityListener(); + } + add(interval, cb, options) { + const poll = new Poll(interval, cb, options); + this.polls.push(poll); + return { + stop: () => poll.stop(), + start: () => poll.start() + }; + } + clear() { + this.polls.forEach((poll) => poll.stop()); + this.polls = []; + } + setupVisibilityListener() { + if (typeof document === "undefined") { + return; + } + document.addEventListener( + "visibilitychange", + () => { + this.polls.forEach((poll) => poll.isInBackground(document.hidden)); + }, + false + ); + } +}; +var polls = new Polls(); +var RequestParams = class _RequestParams { + constructor(params) { + this.callbacks = []; + if (!params.prefetch) { + this.params = params; + } else { + const wrappedCallbacks = { + onBefore: this.wrapCallback(params, "onBefore"), + onBeforeUpdate: this.wrapCallback(params, "onBeforeUpdate"), + onStart: this.wrapCallback(params, "onStart"), + onProgress: this.wrapCallback(params, "onProgress"), + onFinish: this.wrapCallback(params, "onFinish"), + onCancel: this.wrapCallback(params, "onCancel"), + onSuccess: this.wrapCallback(params, "onSuccess"), + onError: this.wrapCallback(params, "onError"), + onFlash: this.wrapCallback(params, "onFlash"), + onCancelToken: this.wrapCallback(params, "onCancelToken"), + onPrefetched: this.wrapCallback(params, "onPrefetched"), + onPrefetching: this.wrapCallback(params, "onPrefetching") + }; + this.params = { + ...params, + ...wrappedCallbacks, + onPrefetchResponse: params.onPrefetchResponse || (() => { + }), + onPrefetchError: params.onPrefetchError || (() => { + }) + }; + } + } + static create(params) { + return new _RequestParams(params); + } + data() { + return this.params.method === "get" ? null : this.params.data; + } + queryParams() { + return this.params.method === "get" ? this.params.data : {}; + } + isPartial() { + return this.params.only.length > 0 || this.params.except.length > 0 || this.params.reset.length > 0; + } + isPrefetch() { + return this.params.prefetch === true; + } + isDeferredPropsRequest() { + return this.params.deferredProps === true; + } + onCancelToken(cb) { + this.params.onCancelToken({ + cancel: cb + }); + } + markAsFinished() { + this.params.completed = true; + this.params.cancelled = false; + this.params.interrupted = false; + } + markAsCancelled({ cancelled = true, interrupted = false }) { + this.params.onCancel(); + this.params.completed = false; + this.params.cancelled = cancelled; + this.params.interrupted = interrupted; + } + wasCancelledAtAll() { + return this.params.cancelled || this.params.interrupted; + } + onFinish() { + this.params.onFinish(this.params); + } + onStart() { + this.params.onStart(this.params); + } + onPrefetching() { + this.params.onPrefetching(this.params); + } + onPrefetchResponse(response) { + if (this.params.onPrefetchResponse) { + this.params.onPrefetchResponse(response); + } + } + onPrefetchError(error) { + if (this.params.onPrefetchError) { + this.params.onPrefetchError(error); + } + } + all() { + return this.params; + } + headers() { + const headers = { + ...this.params.headers + }; + if (this.isPartial()) { + headers["X-Inertia-Partial-Component"] = page.get().component; + } + const only = this.params.only.concat(this.params.reset); + if (only.length > 0) { + headers["X-Inertia-Partial-Data"] = only.join(","); + } + if (this.params.except.length > 0) { + headers["X-Inertia-Partial-Except"] = this.params.except.join(","); + } + if (this.params.reset.length > 0) { + headers["X-Inertia-Reset"] = this.params.reset.join(","); + } + if (this.params.errorBag && this.params.errorBag.length > 0) { + headers["X-Inertia-Error-Bag"] = this.params.errorBag; + } + return headers; + } + setPreserveOptions(page2) { + this.params.preserveScroll = _RequestParams.resolvePreserveOption(this.params.preserveScroll, page2); + this.params.preserveState = _RequestParams.resolvePreserveOption(this.params.preserveState, page2); + } + runCallbacks() { + this.callbacks.forEach(({ name, args }) => { + this.params[name](...args); + }); + } + merge(toMerge) { + this.params = { + ...this.params, + ...toMerge + }; + } + wrapCallback(params, name) { + return (...args) => { + this.recordCallback(name, args); + params[name](...args); + }; + } + recordCallback(name, args) { + this.callbacks.push({ name, args }); + } + static resolvePreserveOption(value, page2) { + if (typeof value === "function") { + return value(page2); + } + if (value === "errors") { + return Object.keys(page2.props.errors || {}).length > 0; + } + return value; + } +}; +var modal_default = { + modal: null, + listener: null, + createIframeAndPage(html) { + if (typeof html === "object") { + html = `All Inertia requests must receive a valid Inertia response, however a plain JSON response was received.
      ${JSON.stringify( + html + )}`; + } + const page2 = document.createElement("html"); + page2.innerHTML = html; + page2.querySelectorAll("a").forEach((a) => a.setAttribute("target", "_top")); + const iframe = document.createElement("iframe"); + iframe.style.backgroundColor = "white"; + iframe.style.borderRadius = "5px"; + iframe.style.width = "100%"; + iframe.style.height = "100%"; + return { iframe, page: page2 }; + }, + show(html) { + const { iframe, page: page2 } = this.createIframeAndPage(html); + this.modal = document.createElement("div"); + this.modal.style.position = "fixed"; + this.modal.style.width = "100vw"; + this.modal.style.height = "100vh"; + this.modal.style.padding = "50px"; + this.modal.style.boxSizing = "border-box"; + this.modal.style.backgroundColor = "rgba(0, 0, 0, .6)"; + this.modal.style.zIndex = 2e5; + this.modal.addEventListener("click", () => this.hide()); + this.modal.appendChild(iframe); + document.body.prepend(this.modal); + document.body.style.overflow = "hidden"; + if (!iframe.contentWindow) { + throw new Error("iframe not yet ready."); + } + iframe.contentWindow.document.open(); + iframe.contentWindow.document.write(page2.outerHTML); + iframe.contentWindow.document.close(); + this.listener = this.hideOnEscape.bind(this); + document.addEventListener("keydown", this.listener); + }, + hide() { + this.modal.outerHTML = ""; + this.modal = null; + document.body.style.overflow = "visible"; + document.removeEventListener("keydown", this.listener); + }, + hideOnEscape(event) { + if (event.keyCode === 27) { + this.hide(); + } + } +}; +var dialog_default = { + show(html) { + const { iframe, page: page2 } = modal_default.createIframeAndPage(html); + iframe.style.boxSizing = "border-box"; + iframe.style.display = "block"; + const dialog = document.createElement("dialog"); + dialog.id = "inertia-error-dialog"; + Object.assign(dialog.style, { + width: "calc(100vw - 100px)", + height: "calc(100vh - 100px)", + padding: "0", + margin: "auto", + border: "none", + backgroundColor: "transparent" + }); + const dialogStyleElement = document.createElement("style"); + dialogStyleElement.textContent = ` + dialog#inertia-error-dialog::backdrop { + background-color: rgba(0, 0, 0, 0.6); + } + + dialog#inertia-error-dialog:focus { + outline: none; + } + `; + document.head.appendChild(dialogStyleElement); + dialog.addEventListener("click", (event) => { + if (event.target === dialog) { + dialog.close(); + } + }); + dialog.addEventListener("close", () => { + dialogStyleElement.remove(); + dialog.remove(); + }); + dialog.appendChild(iframe); + document.body.prepend(dialog); + dialog.showModal(); + dialog.focus(); + if (!iframe.contentWindow) { + throw new Error("iframe not yet ready."); + } + iframe.contentWindow.document.open(); + iframe.contentWindow.document.write(page2.outerHTML); + iframe.contentWindow.document.close(); + } +}; +var queue2 = new Queue(); +var Response = class _Response { + constructor(requestParams, response, originatingPage) { + this.requestParams = requestParams; + this.response = response; + this.originatingPage = originatingPage; + this.wasPrefetched = false; + } + static create(params, response, originatingPage) { + return new _Response(params, response, originatingPage); + } + async handlePrefetch() { + if (isSameUrlWithoutHash(this.requestParams.all().url, window.location)) { + this.handle(); + } + } + async handle() { + return queue2.add(() => this.process()); + } + async process() { + if (this.requestParams.all().prefetch) { + this.wasPrefetched = true; + this.requestParams.all().prefetch = false; + this.requestParams.all().onPrefetched(this.response, this.requestParams.all()); + firePrefetchedEvent(this.response, this.requestParams.all()); + return Promise.resolve(); + } + this.requestParams.runCallbacks(); + if (!this.isInertiaResponse()) { + return this.handleNonInertiaResponse(); + } + await history.processQueue(); + history.preserveUrl = this.requestParams.all().preserveUrl; + const previousFlash = page.get().flash; + await this.setPage(); + const errors = page.get().props.errors || {}; + if (Object.keys(errors).length > 0) { + const scopedErrors = this.getScopedErrors(errors); + fireErrorEvent(scopedErrors); + return this.requestParams.all().onError(scopedErrors); + } + router.flushByCacheTags(this.requestParams.all().invalidateCacheTags || []); + if (!this.wasPrefetched) { + router.flush(page.get().url); + } + const { flash } = page.get(); + if (Object.keys(flash).length > 0 && (!this.requestParams.isPartial() || !isEqual_default(flash, previousFlash))) { + fireFlashEvent(flash); + this.requestParams.all().onFlash(flash); + } + fireSuccessEvent(page.get()); + await this.requestParams.all().onSuccess(page.get()); + history.preserveUrl = false; + } + mergeParams(params) { + this.requestParams.merge(params); + } + getPageResponse() { + const data = this.getDataFromResponse(this.response.data); + if (typeof data === "object") { + return this.response.data = { ...data, flash: data.flash ?? {} }; + } + return this.response.data = data; + } + async handleNonInertiaResponse() { + if (this.isLocationVisit()) { + const locationUrl = hrefToUrl(this.getHeader("x-inertia-location")); + setHashIfSameUrl(this.requestParams.all().url, locationUrl); + return this.locationVisit(locationUrl); + } + const response = { + ...this.response, + data: this.getDataFromResponse(this.response.data) + }; + if (fireInvalidEvent(response)) { + return config.get("future.useDialogForErrorModal") ? dialog_default.show(response.data) : modal_default.show(response.data); + } + } + isInertiaResponse() { + return this.hasHeader("x-inertia"); + } + hasStatus(status2) { + return this.response.status === status2; + } + getHeader(header) { + return this.response.headers[header]; + } + hasHeader(header) { + return this.getHeader(header) !== void 0; + } + isLocationVisit() { + return this.hasStatus(409) && this.hasHeader("x-inertia-location"); + } + /** + * @link https://inertiajs.com/redirects#external-redirects + */ + locationVisit(url) { + try { + SessionStorage.set(SessionStorage.locationVisitKey, { + preserveScroll: this.requestParams.all().preserveScroll === true + }); + if (typeof window === "undefined") { + return; + } + if (isSameUrlWithoutHash(window.location, url)) { + window.location.reload(); + } else { + window.location.href = url.href; + } + } catch (error) { + return false; + } + } + async setPage() { + const pageResponse = this.getPageResponse(); + if (!this.shouldSetPage(pageResponse)) { + return Promise.resolve(); + } + this.mergeProps(pageResponse); + page.mergeOncePropsIntoResponse(pageResponse); + this.preserveEqualProps(pageResponse); + await this.setRememberedState(pageResponse); + this.requestParams.setPreserveOptions(pageResponse); + pageResponse.url = history.preserveUrl ? page.get().url : this.pageUrl(pageResponse); + this.requestParams.all().onBeforeUpdate(pageResponse); + fireBeforeUpdateEvent(pageResponse); + return page.set(pageResponse, { + replace: this.requestParams.all().replace, + preserveScroll: this.requestParams.all().preserveScroll, + preserveState: this.requestParams.all().preserveState, + viewTransition: this.requestParams.all().viewTransition + }); + } + getDataFromResponse(response) { + if (typeof response !== "string") { + return response; + } + try { + return JSON.parse(response); + } catch (error) { + return response; + } + } + shouldSetPage(pageResponse) { + if (!this.requestParams.all().async) { + return true; + } + if (this.originatingPage.component !== pageResponse.component) { + return true; + } + if (this.originatingPage.component !== page.get().component) { + return false; + } + const originatingUrl = hrefToUrl(this.originatingPage.url); + const currentPageUrl = hrefToUrl(page.get().url); + return originatingUrl.origin === currentPageUrl.origin && originatingUrl.pathname === currentPageUrl.pathname; + } + pageUrl(pageResponse) { + const responseUrl = hrefToUrl(pageResponse.url); + setHashIfSameUrl(this.requestParams.all().url, responseUrl); + return responseUrl.pathname + responseUrl.search + responseUrl.hash; + } + preserveEqualProps(pageResponse) { + if (pageResponse.component !== page.get().component || config.get("future.preserveEqualProps") !== true) { + return; + } + const currentPageProps = page.get().props; + Object.entries(pageResponse.props).forEach(([key, value]) => { + if (isEqual_default(value, currentPageProps[key])) { + pageResponse.props[key] = currentPageProps[key]; + } + }); + } + mergeProps(pageResponse) { + if (!this.requestParams.isPartial() || pageResponse.component !== page.get().component) { + return; + } + const propsToAppend = pageResponse.mergeProps || []; + const propsToPrepend = pageResponse.prependProps || []; + const propsToDeepMerge = pageResponse.deepMergeProps || []; + const matchPropsOn = pageResponse.matchPropsOn || []; + const mergeProp = (prop, shouldAppend) => { + const currentProp = get_default(page.get().props, prop); + const incomingProp = get_default(pageResponse.props, prop); + if (Array.isArray(incomingProp)) { + const newArray = this.mergeOrMatchItems( + currentProp || [], + incomingProp, + prop, + matchPropsOn, + shouldAppend + ); + set_default(pageResponse.props, prop, newArray); + } else if (typeof incomingProp === "object" && incomingProp !== null) { + const newObject = { + ...currentProp || {}, + ...incomingProp + }; + set_default(pageResponse.props, prop, newObject); + } + }; + propsToAppend.forEach((prop) => mergeProp(prop, true)); + propsToPrepend.forEach((prop) => mergeProp(prop, false)); + propsToDeepMerge.forEach((prop) => { + const currentProp = page.get().props[prop]; + const incomingProp = pageResponse.props[prop]; + const deepMerge = (target, source, matchProp) => { + if (Array.isArray(source)) { + return this.mergeOrMatchItems(target, source, matchProp, matchPropsOn); + } + if (typeof source === "object" && source !== null) { + return Object.keys(source).reduce( + (acc, key) => { + acc[key] = deepMerge(target ? target[key] : void 0, source[key], `${matchProp}.${key}`); + return acc; + }, + { ...target } + ); + } + return source; + }; + pageResponse.props[prop] = deepMerge(currentProp, incomingProp, prop); + }); + pageResponse.props = { ...page.get().props, ...pageResponse.props }; + if (this.requestParams.isDeferredPropsRequest()) { + const currentErrors = page.get().props.errors; + if (currentErrors && Object.keys(currentErrors).length > 0) { + pageResponse.props.errors = currentErrors; + } + } + if (page.get().scrollProps) { + pageResponse.scrollProps = { + ...page.get().scrollProps || {}, + ...pageResponse.scrollProps || {} + }; + } + if (page.hasOnceProps()) { + pageResponse.onceProps = { + ...page.get().onceProps || {}, + ...pageResponse.onceProps || {} + }; + } + pageResponse.flash = { + ...page.get().flash, + ...this.requestParams.isDeferredPropsRequest() ? {} : pageResponse.flash + }; + const currentOriginalDeferred = page.get().initialDeferredProps; + if (currentOriginalDeferred && Object.keys(currentOriginalDeferred).length > 0) { + pageResponse.initialDeferredProps = currentOriginalDeferred; + } + } + mergeOrMatchItems(existingItems, newItems, matchProp, matchPropsOn, shouldAppend = true) { + const items = Array.isArray(existingItems) ? existingItems : []; + const matchingKey = matchPropsOn.find((key) => { + const keyPath = key.split(".").slice(0, -1).join("."); + return keyPath === matchProp; + }); + if (!matchingKey) { + return shouldAppend ? [...items, ...newItems] : [...newItems, ...items]; + } + const uniqueProperty = matchingKey.split(".").pop() || ""; + const newItemsMap = /* @__PURE__ */ new Map(); + newItems.forEach((item) => { + if (this.hasUniqueProperty(item, uniqueProperty)) { + newItemsMap.set(item[uniqueProperty], item); + } + }); + return shouldAppend ? this.appendWithMatching(items, newItems, newItemsMap, uniqueProperty) : this.prependWithMatching(items, newItems, newItemsMap, uniqueProperty); + } + appendWithMatching(existingItems, newItems, newItemsMap, uniqueProperty) { + const updatedExisting = existingItems.map((item) => { + if (this.hasUniqueProperty(item, uniqueProperty) && newItemsMap.has(item[uniqueProperty])) { + return newItemsMap.get(item[uniqueProperty]); + } + return item; + }); + const newItemsToAdd = newItems.filter((item) => { + if (!this.hasUniqueProperty(item, uniqueProperty)) { + return true; + } + return !existingItems.some( + (existing) => this.hasUniqueProperty(existing, uniqueProperty) && existing[uniqueProperty] === item[uniqueProperty] + ); + }); + return [...updatedExisting, ...newItemsToAdd]; + } + prependWithMatching(existingItems, newItems, newItemsMap, uniqueProperty) { + const untouchedExisting = existingItems.filter((item) => { + if (this.hasUniqueProperty(item, uniqueProperty)) { + return !newItemsMap.has(item[uniqueProperty]); + } + return true; + }); + return [...newItems, ...untouchedExisting]; + } + hasUniqueProperty(item, property) { + return item && typeof item === "object" && property in item; + } + async setRememberedState(pageResponse) { + const rememberedState = await history.getState(history.rememberedState, {}); + if (this.requestParams.all().preserveState && rememberedState && pageResponse.component === page.get().component) { + pageResponse.rememberedState = rememberedState; + } + } + getScopedErrors(errors) { + if (!this.requestParams.all().errorBag) { + return errors; + } + return errors[this.requestParams.all().errorBag || ""] || {}; + } +}; +var Request = class _Request { + constructor(params, page2) { + this.page = page2; + this.requestHasFinished = false; + this.requestParams = RequestParams.create(params); + this.cancelToken = new AbortController(); + } + static create(params, page2) { + return new _Request(params, page2); + } + isPrefetch() { + return this.requestParams.isPrefetch(); + } + async send() { + this.requestParams.onCancelToken(() => this.cancel({ cancelled: true })); + fireStartEvent(this.requestParams.all()); + this.requestParams.onStart(); + if (this.requestParams.all().prefetch) { + this.requestParams.onPrefetching(); + firePrefetchingEvent(this.requestParams.all()); + } + const originallyPrefetch = this.requestParams.all().prefetch; + return axios_default({ + method: this.requestParams.all().method, + url: urlWithoutHash(this.requestParams.all().url).href, + data: this.requestParams.data(), + params: this.requestParams.queryParams(), + signal: this.cancelToken.signal, + headers: this.getHeaders(), + onUploadProgress: this.onProgress.bind(this), + // Why text? This allows us to delay JSON.parse until we're ready to use the response, + // helps with performance particularly on large responses + history encryption + responseType: "text" + }).then((response) => { + this.response = Response.create(this.requestParams, response, this.page); + return this.response.handle(); + }).catch((error) => { + if (error?.response) { + this.response = Response.create(this.requestParams, error.response, this.page); + return this.response.handle(); + } + return Promise.reject(error); + }).catch((error) => { + if (axios_default.isCancel(error)) { + return; + } + if (fireExceptionEvent(error)) { + if (originallyPrefetch) { + this.requestParams.onPrefetchError(error); + } + return Promise.reject(error); + } + }).finally(() => { + this.finish(); + if (originallyPrefetch && this.response) { + this.requestParams.onPrefetchResponse(this.response); + } + }); + } + finish() { + if (this.requestParams.wasCancelledAtAll()) { + return; + } + this.requestParams.markAsFinished(); + this.fireFinishEvents(); + } + fireFinishEvents() { + if (this.requestHasFinished) { + return; + } + this.requestHasFinished = true; + fireFinishEvent(this.requestParams.all()); + this.requestParams.onFinish(); + } + cancel({ cancelled = false, interrupted = false }) { + if (this.requestHasFinished) { + return; + } + this.cancelToken.abort(); + this.requestParams.markAsCancelled({ cancelled, interrupted }); + this.fireFinishEvents(); + } + onProgress(progress32) { + if (this.requestParams.data() instanceof FormData) { + progress32.percentage = progress32.progress ? Math.round(progress32.progress * 100) : 0; + fireProgressEvent(progress32); + this.requestParams.all().onProgress(progress32); + } + } + getHeaders() { + const headers = { + ...this.requestParams.headers(), + Accept: "text/html, application/xhtml+xml", + "X-Requested-With": "XMLHttpRequest", + "X-Inertia": true + }; + const page2 = page.get(); + if (page2.version) { + headers["X-Inertia-Version"] = page2.version; + } + const onceProps = Object.entries(page2.onceProps || {}).filter(([, onceProp]) => { + if (page2.props[onceProp.prop] === void 0) { + return false; + } + return !onceProp.expiresAt || onceProp.expiresAt > Date.now(); + }).map(([key]) => key); + if (onceProps.length > 0) { + headers["X-Inertia-Except-Once-Props"] = onceProps.join(","); + } + return headers; + } +}; +var RequestStream = class { + constructor({ maxConcurrent, interruptible }) { + this.requests = []; + this.maxConcurrent = maxConcurrent; + this.interruptible = interruptible; + } + send(request2) { + this.requests.push(request2); + request2.send().then(() => { + this.requests = this.requests.filter((r) => r !== request2); + }); + } + interruptInFlight() { + this.cancel({ interrupted: true }, false); + } + cancelInFlight({ prefetch = true } = {}) { + this.requests.filter((request2) => prefetch || !request2.isPrefetch()).forEach((request2) => request2.cancel({ cancelled: true })); + } + cancel({ cancelled = false, interrupted = false } = {}, force = false) { + if (!force && !this.shouldCancel()) { + return; + } + const request2 = this.requests.shift(); + request2?.cancel({ cancelled, interrupted }); + } + shouldCancel() { + return this.interruptible && this.requests.length >= this.maxConcurrent; + } +}; +var Router = class { + constructor() { + this.syncRequestStream = new RequestStream({ + maxConcurrent: 1, + interruptible: true + }); + this.asyncRequestStream = new RequestStream({ + maxConcurrent: Infinity, + interruptible: false + }); + this.clientVisitQueue = new Queue(); + } + init({ + initialPage, + resolveComponent, + swapComponent: swapComponent2, + onFlash + }) { + page.init({ + initialPage, + resolveComponent, + swapComponent: swapComponent2, + onFlash + }); + InitialVisit.handle(); + eventHandler.init(); + eventHandler.on("missingHistoryItem", () => { + if (typeof window !== "undefined") { + this.visit(window.location.href, { preserveState: true, preserveScroll: true, replace: true }); + } + }); + eventHandler.on("loadDeferredProps", (deferredProps) => { + this.loadDeferredProps(deferredProps); + }); + eventHandler.on("historyQuotaExceeded", (url) => { + window.location.href = url; + }); + } + get(url, data = {}, options = {}) { + return this.visit(url, { ...options, method: "get", data }); + } + post(url, data = {}, options = {}) { + return this.visit(url, { preserveState: true, ...options, method: "post", data }); + } + put(url, data = {}, options = {}) { + return this.visit(url, { preserveState: true, ...options, method: "put", data }); + } + patch(url, data = {}, options = {}) { + return this.visit(url, { preserveState: true, ...options, method: "patch", data }); + } + delete(url, options = {}) { + return this.visit(url, { preserveState: true, ...options, method: "delete" }); + } + reload(options = {}) { + return this.doReload(options); + } + doReload(options = {}) { + if (typeof window === "undefined") { + return; + } + return this.visit(window.location.href, { + ...options, + preserveScroll: true, + preserveState: true, + async: true, + headers: { + ...options.headers || {}, + "Cache-Control": "no-cache" + } + }); + } + remember(data, key = "default") { + history.remember(data, key); + } + restore(key = "default") { + return history.restore(key); + } + on(type, callback) { + if (typeof window === "undefined") { + return () => { + }; + } + return eventHandler.onGlobalEvent(type, callback); + } + /** + * @deprecated Use cancelAll() instead. + */ + cancel() { + this.syncRequestStream.cancelInFlight(); + } + cancelAll({ async = true, prefetch = true, sync = true } = {}) { + if (async) { + this.asyncRequestStream.cancelInFlight({ prefetch }); + } + if (sync) { + this.syncRequestStream.cancelInFlight(); + } + } + poll(interval, requestOptions = {}, options = {}) { + return polls.add(interval, () => this.reload(requestOptions), { + autoStart: options.autoStart ?? true, + keepAlive: options.keepAlive ?? false + }); + } + visit(href, options = {}) { + const visit = this.getPendingVisit(href, { + ...options, + showProgress: options.showProgress ?? !options.async + }); + const events = this.getVisitEvents(options); + if (events.onBefore(visit) === false || !fireBeforeEvent(visit)) { + return; + } + const currentPageUrl = hrefToUrl(page.get().url); + const isPartialReload = visit.only.length > 0 || visit.except.length > 0 || visit.reset.length > 0; + const isSamePage = isPartialReload ? isSameUrlWithoutQueryOrHash(visit.url, currentPageUrl) : isSameUrlWithoutHash(visit.url, currentPageUrl); + if (!isSamePage) { + this.asyncRequestStream.cancelInFlight({ prefetch: false }); + } + if (!visit.async) { + this.syncRequestStream.interruptInFlight(); + } + if (!page.isCleared() && !visit.preserveUrl) { + Scroll.save(); + } + const requestParams = { + ...visit, + ...events + }; + const prefetched = prefetchedRequests.get(requestParams); + if (prefetched) { + progress.reveal(prefetched.inFlight); + prefetchedRequests.use(prefetched, requestParams); + } else { + progress.reveal(true); + const requestStream = visit.async ? this.asyncRequestStream : this.syncRequestStream; + requestStream.send(Request.create(requestParams, page.get())); + } + } + getCached(href, options = {}) { + return prefetchedRequests.findCached(this.getPrefetchParams(href, options)); + } + flush(href, options = {}) { + prefetchedRequests.remove(this.getPrefetchParams(href, options)); + } + flushAll() { + prefetchedRequests.removeAll(); + } + flushByCacheTags(tags) { + prefetchedRequests.removeByTags(Array.isArray(tags) ? tags : [tags]); + } + getPrefetching(href, options = {}) { + return prefetchedRequests.findInFlight(this.getPrefetchParams(href, options)); + } + prefetch(href, options = {}, prefetchOptions = {}) { + const method = options.method ?? (isUrlMethodPair(href) ? href.method : "get"); + if (method !== "get") { + throw new Error("Prefetch requests must use the GET method"); + } + const visit = this.getPendingVisit(href, { + ...options, + async: true, + showProgress: false, + prefetch: true, + viewTransition: false + }); + const visitUrl = visit.url.origin + visit.url.pathname + visit.url.search; + const currentUrl = window.location.origin + window.location.pathname + window.location.search; + if (visitUrl === currentUrl) { + return; + } + const events = this.getVisitEvents(options); + if (events.onBefore(visit) === false || !fireBeforeEvent(visit)) { + return; + } + progress.hide(); + this.asyncRequestStream.interruptInFlight(); + const requestParams = { + ...visit, + ...events + }; + const ensureCurrentPageIsSet = () => { + return new Promise((resolve) => { + const checkIfPageIsDefined = () => { + if (page.get()) { + resolve(); + } else { + setTimeout(checkIfPageIsDefined, 50); + } + }; + checkIfPageIsDefined(); + }); + }; + ensureCurrentPageIsSet().then(() => { + prefetchedRequests.add( + requestParams, + (params) => { + this.asyncRequestStream.send(Request.create(params, page.get())); + }, + { + cacheFor: config.get("prefetch.cacheFor"), + cacheTags: [], + ...prefetchOptions + } + ); + }); + } + clearHistory() { + history.clear(); + } + decryptHistory() { + return history.decrypt(); + } + resolveComponent(component) { + return page.resolve(component); + } + replace(params) { + this.clientVisit(params, { replace: true }); + } + replaceProp(name, value, options) { + this.replace({ + preserveScroll: true, + preserveState: true, + props(currentProps) { + const newValue = typeof value === "function" ? value(get_default(currentProps, name), currentProps) : value; + return set_default(cloneDeep_default(currentProps), name, newValue); + }, + ...options || {} + }); + } + appendToProp(name, value, options) { + this.replaceProp( + name, + (currentValue, currentProps) => { + const newValue = typeof value === "function" ? value(currentValue, currentProps) : value; + if (!Array.isArray(currentValue)) { + currentValue = currentValue !== void 0 ? [currentValue] : []; + } + return [...currentValue, newValue]; + }, + options + ); + } + prependToProp(name, value, options) { + this.replaceProp( + name, + (currentValue, currentProps) => { + const newValue = typeof value === "function" ? value(currentValue, currentProps) : value; + if (!Array.isArray(currentValue)) { + currentValue = currentValue !== void 0 ? [currentValue] : []; + } + return [newValue, ...currentValue]; + }, + options + ); + } + push(params) { + this.clientVisit(params); + } + flash(keyOrData, value) { + const current = page.get().flash; + let flash; + if (typeof keyOrData === "function") { + flash = keyOrData(current); + } else if (typeof keyOrData === "string") { + flash = { ...current, [keyOrData]: value }; + } else if (keyOrData && Object.keys(keyOrData).length) { + flash = { ...current, ...keyOrData }; + } else { + return; + } + page.setFlash(flash); + if (Object.keys(flash).length) { + fireFlashEvent(flash); + } + } + clientVisit(params, { replace = false } = {}) { + this.clientVisitQueue.add(() => this.performClientVisit(params, { replace })); + } + performClientVisit(params, { replace = false } = {}) { + const current = page.get(); + const onceProps = typeof params.props === "function" ? Object.fromEntries( + Object.values(current.onceProps ?? {}).map((onceProp) => [onceProp.prop, current.props[onceProp.prop]]) + ) : {}; + const props = typeof params.props === "function" ? params.props(current.props, onceProps) : params.props ?? current.props; + const flash = typeof params.flash === "function" ? params.flash(current.flash) : params.flash; + const { viewTransition, onError, onFinish, onFlash, onSuccess, ...pageParams } = params; + const page2 = { + ...current, + ...pageParams, + flash: flash ?? {}, + props + }; + const preserveScroll = RequestParams.resolvePreserveOption(params.preserveScroll ?? false, page2); + const preserveState = RequestParams.resolvePreserveOption(params.preserveState ?? false, page2); + return page.set(page2, { + replace, + preserveScroll, + preserveState, + viewTransition + }).then(() => { + const currentFlash = page.get().flash; + if (Object.keys(currentFlash).length > 0) { + fireFlashEvent(currentFlash); + onFlash?.(currentFlash); + } + const errors = page.get().props.errors || {}; + if (Object.keys(errors).length === 0) { + onSuccess?.(page.get()); + return; + } + const scopedErrors = params.errorBag ? errors[params.errorBag || ""] || {} : errors; + onError?.(scopedErrors); + }).finally(() => onFinish?.(params)); + } + getPrefetchParams(href, options) { + return { + ...this.getPendingVisit(href, { + ...options, + async: true, + showProgress: false, + prefetch: true, + viewTransition: false + }), + ...this.getVisitEvents(options) + }; + } + getPendingVisit(href, options, pendingVisitOptions = {}) { + if (isUrlMethodPair(href)) { + const urlMethodPair = href; + href = urlMethodPair.url; + options.method = options.method ?? urlMethodPair.method; + } + const defaultVisitOptionsCallback = config.get("visitOptions"); + const configuredOptions = defaultVisitOptionsCallback ? defaultVisitOptionsCallback(href.toString(), cloneDeep_default(options)) || {} : {}; + const mergedOptions = { + method: "get", + data: {}, + replace: false, + preserveScroll: false, + preserveState: false, + only: [], + except: [], + headers: {}, + errorBag: "", + forceFormData: false, + queryStringArrayFormat: "brackets", + async: false, + showProgress: true, + fresh: false, + reset: [], + preserveUrl: false, + prefetch: false, + invalidateCacheTags: [], + viewTransition: false, + ...options, + ...configuredOptions + }; + const [url, _data] = transformUrlAndData( + href, + mergedOptions.data, + mergedOptions.method, + mergedOptions.forceFormData, + mergedOptions.queryStringArrayFormat + ); + const visit = { + cancelled: false, + completed: false, + interrupted: false, + ...mergedOptions, + ...pendingVisitOptions, + url, + data: _data + }; + if (visit.prefetch) { + visit.headers["Purpose"] = "prefetch"; + } + return visit; + } + getVisitEvents(options) { + return { + onCancelToken: options.onCancelToken || (() => { + }), + onBefore: options.onBefore || (() => { + }), + onBeforeUpdate: options.onBeforeUpdate || (() => { + }), + onStart: options.onStart || (() => { + }), + onProgress: options.onProgress || (() => { + }), + onFinish: options.onFinish || (() => { + }), + onCancel: options.onCancel || (() => { + }), + onSuccess: options.onSuccess || (() => { + }), + onError: options.onError || (() => { + }), + onFlash: options.onFlash || (() => { + }), + onPrefetched: options.onPrefetched || (() => { + }), + onPrefetching: options.onPrefetching || (() => { + }) + }; + } + loadDeferredProps(deferred) { + if (deferred) { + Object.entries(deferred).forEach(([_, group]) => { + this.doReload({ only: group, deferredProps: true }); + }); + } + } +}; +var UseFormUtils = class { + /** + * Creates a callback that returns a UrlMethodPair. + * + * createWayfinderCallback(urlMethodPair) + * createWayfinderCallback(method, url) + * createWayfinderCallback(() => urlMethodPair) + * createWayfinderCallback(() => method, () => url) + */ + static createWayfinderCallback(...args) { + return () => { + if (args.length === 1) { + return isUrlMethodPair(args[0]) ? args[0] : args[0](); + } + return { + method: typeof args[0] === "function" ? args[0]() : args[0], + url: typeof args[1] === "function" ? args[1]() : args[1] + }; + }; + } + /** + * Parses all useForm() arguments into { rememberKey, data, precognitionEndpoint }. + * + * useForm() + * useForm(data) + * useForm(rememberKey, data) + * useForm(method, url, data) + * useForm(urlMethodPair, data) + * + */ + static parseUseFormArguments(...args) { + if (args.length === 0) { + return { + rememberKey: null, + data: {}, + precognitionEndpoint: null + }; + } + if (args.length === 1) { + return { + rememberKey: null, + data: args[0], + precognitionEndpoint: null + }; + } + if (args.length === 2) { + if (typeof args[0] === "string") { + return { + rememberKey: args[0], + data: args[1], + precognitionEndpoint: null + }; + } + return { + rememberKey: null, + data: args[1], + precognitionEndpoint: this.createWayfinderCallback(args[0]) + }; + } + return { + rememberKey: null, + data: args[2], + precognitionEndpoint: this.createWayfinderCallback(args[0], args[1]) + }; + } + /** + * Parses all submission arguments into { method, url, options }. + * It uses the Precognition endpoint if no explicit method/url are provided. + * + * form.submit(method, url) + * form.submit(method, url, options) + * form.submit(urlMethodPair) + * form.submit(urlMethodPair, options) + * form.submit() + * form.submit(options) + */ + static parseSubmitArguments(args, precognitionEndpoint) { + if (args.length === 3 || args.length === 2 && typeof args[0] === "string") { + return { method: args[0], url: args[1], options: args[2] ?? {} }; + } + if (isUrlMethodPair(args[0])) { + return { ...args[0], options: args[1] ?? {} }; + } + return { ...precognitionEndpoint(), options: args[0] ?? {} }; + } + /** + * Merges headers into the Precognition validate() arguments. + */ + static mergeHeadersForValidation(field, config22, headers) { + const merge3 = (config3) => { + config3.headers = { + ...headers ?? {}, + ...config3.headers ?? {} + }; + return config3; + }; + if (field && typeof field === "object" && !("target" in field)) { + field = merge3(field); + } else if (config22 && typeof config22 === "object") { + config22 = merge3(config22); + } else if (typeof field === "string") { + config22 = merge3(config22 ?? {}); + } else { + field = merge3(field ?? {}); + } + return [field, config22]; + } +}; +function undotKey(key) { + if (!key.includes(".")) { + return key; + } + const transformSegment = (segment) => { + if (segment.startsWith("[") && segment.endsWith("]")) { + return segment; + } + return segment.split(".").reduce((result, part, index) => index === 0 ? part : `${result}[${part}]`); + }; + return key.replace(/\\\./g, "__ESCAPED_DOT__").split(/(\[[^\]]*\])/).filter(Boolean).map(transformSegment).join("").replace(/__ESCAPED_DOT__/g, "."); +} +function parseKey(key) { + const path = []; + const pattern = /([^\[\]]+)|\[(\d*)\]/g; + let match; + while ((match = pattern.exec(key)) !== null) { + if (match[1] !== void 0) { + path.push(match[1]); + } else if (match[2] !== void 0) { + path.push(match[2] === "" ? "" : Number(match[2])); + } + } + return path; +} +function setNestedObject(obj, path, value) { + let current = obj; + for (let i = 0; i < path.length - 1; i++) { + if (!(path[i] in current)) { + current[path[i]] = {}; + } + current = current[path[i]]; + } + current[path[path.length - 1]] = value; +} +function objectHasSequentialNumericKeys(value) { + const keys2 = Object.keys(value); + const numericKeys = keys2.filter((k) => /^\d+$/.test(k)).map(Number).sort((a, b) => a - b); + return keys2.length === numericKeys.length && numericKeys.length > 0 && numericKeys[0] === 0 && numericKeys.every((n, i) => n === i); +} +function convertSequentialObjectsToArrays(value) { + if (Array.isArray(value)) { + return value.map(convertSequentialObjectsToArrays); + } + if (typeof value !== "object" || value === null || isFile2(value)) { + return value; + } + if (objectHasSequentialNumericKeys(value)) { + const result2 = []; + for (let i = 0; i < Object.keys(value).length; i++) { + result2[i] = convertSequentialObjectsToArrays(value[i]); + } + return result2; + } + const result = {}; + for (const key in value) { + result[key] = convertSequentialObjectsToArrays(value[key]); + } + return result; +} +function formDataToObject(source) { + const form = {}; + for (const [key, value] of source.entries()) { + if (value instanceof File && value.size === 0 && value.name === "") { + continue; + } + const path = parseKey(undotKey(key)); + if (path[path.length - 1] === "") { + const arrayPath = path.slice(0, -1); + const existing = get_default(form, arrayPath); + if (Array.isArray(existing)) { + existing.push(value); + } else if (existing && typeof existing === "object" && !isFile2(existing)) { + const numericKeys = Object.keys(existing).filter((k) => /^\d+$/.test(k)).map(Number).sort((a, b) => a - b); + set_default(form, arrayPath, numericKeys.length > 0 ? [...numericKeys.map((k) => existing[k]), value] : [value]); + } else { + set_default(form, arrayPath, [value]); + } + continue; + } + setNestedObject(form, path.map(String), value); + } + return convertSequentialObjectsToArrays(form); +} +var Renderer = { + preferredAttribute() { + return config.get("future.useDataInertiaHeadAttribute") ? "data-inertia" : "inertia"; + }, + buildDOMElement(tag) { + const template = document.createElement("template"); + template.innerHTML = tag; + const node = template.content.firstChild; + if (!tag.startsWith(" - @code { diff --git a/src/SimpleModule.Host/Program.cs b/src/SimpleModule.Host/Program.cs index f60e9a8c..13f0fe5b 100644 --- a/src/SimpleModule.Host/Program.cs +++ b/src/SimpleModule.Host/Program.cs @@ -63,7 +63,10 @@ builder.Services.AddRazorComponents(); // Inertia page renderer (renders Inertia HTML shell via Blazor SSR) -builder.Services.AddSimpleModuleBlazor(); +builder.Services.AddSimpleModuleBlazor(options => +{ + options.ShellComponent = typeof(InertiaShell); +}); // Register event bus builder.Services.AddScoped(); From 5cb9726ff18513897449fbaa1293892158fd5146 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Fri, 13 Mar 2026 16:49:21 +0100 Subject: [PATCH 18/62] Refactor Products module to use new view structure - Moved existing product pages (Browse, Create, Edit, Manage) to a new Views directory. - Updated imports in index.ts to reflect new view paths. - Created new endpoint classes for each view to handle routing. - Removed old routing logic from ProductsModule and replaced it with new endpoint mappings. - Added a script to extract auto-generated Pages/index.ts from ViewPages_*.g.cs files. - Updated tests to ensure correct view discovery and routing behavior. --- .../Inertia/InertiaResult.cs | 4 +- src/SimpleModule.Core/ModuleAttribute.cs | 1 + .../ModuleDiscovererGenerator.cs | 193 +++++++++++- .../Products/src/Products/Pages/index.ts | 9 +- .../Products/src/Products/Products.csproj | 5 + .../Products/src/Products/ProductsModule.cs | 39 +-- .../src/Products/{Pages => Views}/Browse.tsx | 0 .../src/Products/Views/BrowseEndpoint.cs | 17 + .../src/Products/{Pages => Views}/Create.tsx | 0 .../src/Products/Views/CreateEndpoint.cs | 14 + .../src/Products/{Pages => Views}/Edit.tsx | 0 .../src/Products/Views/EditEndpoint.cs | 23 ++ .../src/Products/{Pages => Views}/Manage.tsx | 0 .../src/Products/Views/ManageEndpoint.cs | 17 + .../Helpers/GeneratorTestHelper.cs | 12 + .../SimpleModule.Generator.Tests.csproj | 3 + .../ViewDiscoveryTests.cs | 292 ++++++++++++++++++ tools/extract-view-pages.mjs | 35 +++ 18 files changed, 606 insertions(+), 58 deletions(-) rename src/modules/Products/src/Products/{Pages => Views}/Browse.tsx (100%) create mode 100644 src/modules/Products/src/Products/Views/BrowseEndpoint.cs rename src/modules/Products/src/Products/{Pages => Views}/Create.tsx (100%) create mode 100644 src/modules/Products/src/Products/Views/CreateEndpoint.cs rename src/modules/Products/src/Products/{Pages => Views}/Edit.tsx (100%) create mode 100644 src/modules/Products/src/Products/Views/EditEndpoint.cs rename src/modules/Products/src/Products/{Pages => Views}/Manage.tsx (100%) create mode 100644 src/modules/Products/src/Products/Views/ManageEndpoint.cs create mode 100644 tests/SimpleModule.Generator.Tests/ViewDiscoveryTests.cs create mode 100644 tools/extract-view-pages.mjs diff --git a/src/SimpleModule.Core/Inertia/InertiaResult.cs b/src/SimpleModule.Core/Inertia/InertiaResult.cs index 41a22198..a4d766bf 100644 --- a/src/SimpleModule.Core/Inertia/InertiaResult.cs +++ b/src/SimpleModule.Core/Inertia/InertiaResult.cs @@ -12,7 +12,7 @@ public static IResult Render(string component, object? props = null) => internal sealed class InertiaResult : IResult { - private static readonly JsonSerializerOptions CamelCaseOptions = new() + private static readonly JsonSerializerOptions _camelCaseOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, }; @@ -45,7 +45,7 @@ public async Task ExecuteAsync(HttpContext httpContext) return; } - var pageJson = JsonSerializer.Serialize(pageData, CamelCaseOptions); + var pageJson = JsonSerializer.Serialize(pageData, _camelCaseOptions); var renderer = httpContext.RequestServices.GetRequiredService(); await renderer.RenderPageAsync(httpContext, pageJson); diff --git a/src/SimpleModule.Core/ModuleAttribute.cs b/src/SimpleModule.Core/ModuleAttribute.cs index 667028cf..f545f403 100644 --- a/src/SimpleModule.Core/ModuleAttribute.cs +++ b/src/SimpleModule.Core/ModuleAttribute.cs @@ -8,6 +8,7 @@ public sealed class ModuleAttribute : Attribute public string Name { get; } public string Version { get; } public string RoutePrefix { get; set; } = ""; + public string ViewPrefix { get; set; } = ""; public ModuleAttribute(string name, string version = "1.0.0") { diff --git a/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs b/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs index b665aacb..330dd5dd 100644 --- a/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs +++ b/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs @@ -30,6 +30,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) GenerateEndpointExtensions(spc, data.Modules); GenerateMenuExtensions(spc, data.Modules); GenerateRazorComponentExtensions(spc, data.Modules); + GenerateViewPages(spc, data.Modules); if (data.DtoTypes.Length > 0) { @@ -74,7 +75,8 @@ is not IAssemblySymbol assemblySymbol if (modules.Count == 0) return DiscoveryData.Empty; - // Discover IEndpoint implementors per module assembly + // Discover IEndpoint implementors per module assembly. + // Endpoints whose FQN contains ".Views." are classified as view endpoints. if (endpointInterfaceSymbol is not null) { foreach (var module in modules) @@ -88,7 +90,9 @@ is not IAssemblySymbol assemblySymbol FindEndpointTypes( assembly.GlobalNamespace, endpointInterfaceSymbol, - module.Endpoints + module.ModuleName, + module.Endpoints, + module.Views ); } } @@ -148,8 +152,12 @@ typeSymbol is not null m.HasConfigureMenu, m.HasRazorComponents, m.RoutePrefix, + m.ViewPrefix, m.Endpoints .Select(e => new EndpointInfoRecord(e.FullyQualifiedName)) + .ToImmutableArray(), + m.Views + .Select(v => new ViewInfoRecord(v.FullyQualifiedName, v.Page)) .ToImmutableArray() )) .ToImmutableArray(), @@ -191,7 +199,11 @@ List modules ) ) { + var moduleName = attr.ConstructorArguments.Length > 0 + ? attr.ConstructorArguments[0].Value as string ?? "" + : ""; var routePrefix = ""; + var viewPrefix = ""; foreach (var namedArg in attr.NamedArguments) { if ( @@ -200,7 +212,13 @@ List modules ) { routePrefix = prefix; - break; + } + else if ( + namedArg.Key == "ViewPrefix" + && namedArg.Value.Value is string vPrefix + ) + { + viewPrefix = vPrefix; } } @@ -210,6 +228,7 @@ List modules FullyQualifiedName = typeSymbol.ToDisplayString( SymbolDisplayFormat.FullyQualifiedFormat ), + ModuleName = moduleName, HasConfigureServices = DeclaresMethod( typeSymbol, "ConfigureServices" @@ -220,6 +239,7 @@ List modules ), HasConfigureMenu = DeclaresMethod(typeSymbol, "ConfigureMenu"), RoutePrefix = routePrefix, + ViewPrefix = viewPrefix, } ); break; @@ -232,14 +252,22 @@ List modules private static void FindEndpointTypes( INamespaceSymbol namespaceSymbol, INamedTypeSymbol endpointInterfaceSymbol, - List endpoints + string moduleName, + List endpoints, + List views ) { foreach (var member in namespaceSymbol.GetMembers()) { if (member is INamespaceSymbol childNamespace) { - FindEndpointTypes(childNamespace, endpointInterfaceSymbol, endpoints); + FindEndpointTypes( + childNamespace, + endpointInterfaceSymbol, + moduleName, + endpoints, + views + ); } else if (member is INamedTypeSymbol typeSymbol) { @@ -249,14 +277,40 @@ List endpoints && ImplementsInterface(typeSymbol, endpointInterfaceSymbol) ) { - endpoints.Add( - new EndpointInfo - { - FullyQualifiedName = typeSymbol.ToDisplayString( - SymbolDisplayFormat.FullyQualifiedFormat - ), - } + var fqn = typeSymbol.ToDisplayString( + SymbolDisplayFormat.FullyQualifiedFormat ); + + // Check if this endpoint lives in a .Views. namespace + if (fqn.Contains(".Views.")) + { + var className = typeSymbol.Name; + // Strip Endpoint/View suffix + if (className.EndsWith("Endpoint", StringComparison.Ordinal)) + className = className.Substring( + 0, + className.Length - "Endpoint".Length + ); + else if (className.EndsWith("View", StringComparison.Ordinal)) + className = className.Substring( + 0, + className.Length - "View".Length + ); + + views.Add( + new ViewInfo + { + FullyQualifiedName = fqn, + Page = moduleName + "/" + className, + } + ); + } + else + { + endpoints.Add( + new EndpointInfo { FullyQualifiedName = fqn } + ); + } } } } @@ -474,6 +528,43 @@ ImmutableArray modules sb.AppendLine(" }"); } + // Auto-registered view endpoints (IEndpoint in *.Views.* namespace) + foreach (var module in modules) + { + if (module.Views.Length == 0) + continue; + + sb.AppendLine(); + sb.AppendLine( + $" // Auto-registered view endpoints for {module.FullyQualifiedName}" + ); + sb.AppendLine(" {"); + + if (!string.IsNullOrEmpty(module.ViewPrefix)) + { + sb.AppendLine( + $" var viewGroup = app.MapGroup(\"{module.ViewPrefix}\");" + ); + foreach (var view in module.Views) + { + sb.AppendLine( + $" new {view.FullyQualifiedName}().Map(viewGroup);" + ); + } + } + else + { + foreach (var view in module.Views) + { + sb.AppendLine( + $" new {view.FullyQualifiedName}().Map(app);" + ); + } + } + + sb.AppendLine(" }"); + } + // Manual ConfigureEndpoints (escape hatch) foreach (var module in modules.Where(m => m.HasConfigureEndpoints)) { @@ -643,6 +734,62 @@ ImmutableArray dtoTypes context.AddSource("DtoTypeScript.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); } + private static void GenerateViewPages( + SourceProductionContext context, + ImmutableArray modules + ) + { + foreach (var module in modules) + { + if (module.Views.Length == 0) + continue; + + // Extract module name from FQN (e.g., "global::SimpleModule.Products.ProductsModule" → "Products") + var fqn = module.FullyQualifiedName.Replace("global::", ""); + var moduleName = fqn.Contains(".") + ? fqn.Substring(fqn.LastIndexOf('.') + 1) + : fqn; + if (moduleName.EndsWith("Module", StringComparison.Ordinal)) + moduleName = moduleName.Substring(0, moduleName.Length - "Module".Length); + + var sb = new StringBuilder(); + sb.AppendLine("// "); + sb.AppendLine("#if SIMPLEMODULE_TS"); + sb.AppendLine("/*"); + + // Generate import statements — component name is the part after "/" + foreach (var view in module.Views) + { + var componentName = view.Page.Contains("/") + ? view.Page.Substring(view.Page.LastIndexOf('/') + 1) + : view.Page; + sb.AppendLine($"import {componentName} from '../Views/{componentName}';"); + } + + sb.AppendLine(); + sb.AppendLine("export const pages: Record = {"); + + for (var i = 0; i < module.Views.Length; i++) + { + var view = module.Views[i]; + var componentName = view.Page.Contains("/") + ? view.Page.Substring(view.Page.LastIndexOf('/') + 1) + : view.Page; + var comma = i < module.Views.Length - 1 ? "," : ""; + sb.AppendLine($" '{view.Page}': {componentName}{comma}"); + } + + sb.AppendLine("};"); + sb.AppendLine("*/"); + sb.AppendLine("#endif"); + + context.AddSource( + $"ViewPages_{moduleName}.g.cs", + SourceText.From(sb.ToString(), Encoding.UTF8) + ); + } + } + private static string MapCSharpTypeToTypeScript(string typeFqn) { var type = typeFqn.Replace("global::", ""); @@ -821,7 +968,9 @@ private readonly record struct ModuleInfoRecord( bool HasConfigureMenu, bool HasRazorComponents, string RoutePrefix, - ImmutableArray Endpoints + string ViewPrefix, + ImmutableArray Endpoints, + ImmutableArray Views ) { public bool Equals(ModuleInfoRecord other) @@ -832,7 +981,9 @@ public bool Equals(ModuleInfoRecord other) && HasConfigureMenu == other.HasConfigureMenu && HasRazorComponents == other.HasRazorComponents && RoutePrefix == other.RoutePrefix - && Endpoints.SequenceEqual(other.Endpoints); + && ViewPrefix == other.ViewPrefix + && Endpoints.SequenceEqual(other.Endpoints) + && Views.SequenceEqual(other.Views); } public override int GetHashCode() @@ -846,8 +997,11 @@ public override int GetHashCode() hash = hash * 31 + HasConfigureMenu.GetHashCode(); hash = hash * 31 + HasRazorComponents.GetHashCode(); hash = hash * 31 + (RoutePrefix ?? "").GetHashCode(); + hash = hash * 31 + (ViewPrefix ?? "").GetHashCode(); foreach (var e in Endpoints) hash = hash * 31 + e.GetHashCode(); + foreach (var v in Views) + hash = hash * 31 + v.GetHashCode(); return hash; } } @@ -855,6 +1009,8 @@ public override int GetHashCode() private readonly record struct EndpointInfoRecord(string FullyQualifiedName); + private readonly record struct ViewInfoRecord(string FullyQualifiedName, string Page); + private readonly record struct DtoTypeInfoRecord( string FullyQualifiedName, string SafeName, @@ -895,12 +1051,15 @@ bool HasSetter private sealed class ModuleInfo { public string FullyQualifiedName { get; set; } = ""; + public string ModuleName { get; set; } = ""; public bool HasConfigureServices { get; set; } public bool HasConfigureEndpoints { get; set; } public bool HasConfigureMenu { get; set; } public bool HasRazorComponents { get; set; } public string RoutePrefix { get; set; } = ""; + public string ViewPrefix { get; set; } = ""; public List Endpoints { get; set; } = new(); + public List Views { get; set; } = new(); } private sealed class EndpointInfo @@ -908,6 +1067,12 @@ private sealed class EndpointInfo public string FullyQualifiedName { get; set; } = ""; } + private sealed class ViewInfo + { + public string FullyQualifiedName { get; set; } = ""; + public string Page { get; set; } = ""; + } + private sealed class DtoTypeInfo { public string FullyQualifiedName { get; set; } = ""; diff --git a/src/modules/Products/src/Products/Pages/index.ts b/src/modules/Products/src/Products/Pages/index.ts index 74a5a9d7..d18407fe 100644 --- a/src/modules/Products/src/Products/Pages/index.ts +++ b/src/modules/Products/src/Products/Pages/index.ts @@ -1,7 +1,8 @@ -import Browse from './Browse'; -import Create from './Create'; -import Edit from './Edit'; -import Manage from './Manage'; +// Auto-generated from view endpoints — do not edit +import Browse from '../Views/Browse'; +import Create from '../Views/Create'; +import Edit from '../Views/Edit'; +import Manage from '../Views/Manage'; export const pages: Record = { 'Products/Browse': Browse, diff --git a/src/modules/Products/src/Products/Products.csproj b/src/modules/Products/src/Products/Products.csproj index 0b188b80..81ee207a 100644 --- a/src/modules/Products/src/Products/Products.csproj +++ b/src/modules/Products/src/Products/Products.csproj @@ -9,6 +9,11 @@ + + + %(Filename)Endpoint.cs + + diff --git a/src/modules/Products/src/Products/ProductsModule.cs b/src/modules/Products/src/Products/ProductsModule.cs index 345f9ef7..0e084ef0 100644 --- a/src/modules/Products/src/Products/ProductsModule.cs +++ b/src/modules/Products/src/Products/ProductsModule.cs @@ -5,14 +5,13 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using SimpleModule.Core; -using SimpleModule.Core.Inertia; using SimpleModule.Core.Menu; using SimpleModule.Database; using SimpleModule.Products.Contracts; namespace SimpleModule.Products; -[Module(ProductsConstants.ModuleName, RoutePrefix = ProductsConstants.RoutePrefix)] +[Module(ProductsConstants.ModuleName, RoutePrefix = ProductsConstants.RoutePrefix, ViewPrefix = "/products")] public class ProductsModule : IModule { public void ConfigureServices(IServiceCollection services, IConfiguration configuration) @@ -52,42 +51,6 @@ public void ConfigureEndpoints(IEndpointRouteBuilder endpoints) { var group = endpoints.MapGroup("/products"); - // Browse page (public) - group.MapGet( - "/browse", - async (IProductContracts products) => - Inertia.Render( - "Products/Browse", - new { products = await products.GetAllProductsAsync() } - ) - ); - - // Manage page - group.MapGet( - "/manage", - async (IProductContracts products) => - Inertia.Render( - "Products/Manage", - new { products = await products.GetAllProductsAsync() } - ) - ); - - // Create page - group.MapGet("/create", () => Inertia.Render("Products/Create")); - - // Edit page - group.MapGet( - "/{id}/edit", - async (int id, IProductContracts products) => - { - var product = await products.GetProductByIdAsync(id); - if (product is null) - return Results.NotFound(); - - return Inertia.Render("Products/Edit", new { product }); - } - ); - // Create product (POST) group.MapPost( "/", diff --git a/src/modules/Products/src/Products/Pages/Browse.tsx b/src/modules/Products/src/Products/Views/Browse.tsx similarity index 100% rename from src/modules/Products/src/Products/Pages/Browse.tsx rename to src/modules/Products/src/Products/Views/Browse.tsx diff --git a/src/modules/Products/src/Products/Views/BrowseEndpoint.cs b/src/modules/Products/src/Products/Views/BrowseEndpoint.cs new file mode 100644 index 00000000..6234287a --- /dev/null +++ b/src/modules/Products/src/Products/Views/BrowseEndpoint.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Routing; +using SimpleModule.Core; +using SimpleModule.Core.Inertia; +using SimpleModule.Products.Contracts; + +namespace SimpleModule.Products.Views; + +public class BrowseEndpoint : IEndpoint +{ + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/browse", async (IProductContracts products) => + Inertia.Render("Products/Browse", + new { products = await products.GetAllProductsAsync() })); + } +} diff --git a/src/modules/Products/src/Products/Pages/Create.tsx b/src/modules/Products/src/Products/Views/Create.tsx similarity index 100% rename from src/modules/Products/src/Products/Pages/Create.tsx rename to src/modules/Products/src/Products/Views/Create.tsx diff --git a/src/modules/Products/src/Products/Views/CreateEndpoint.cs b/src/modules/Products/src/Products/Views/CreateEndpoint.cs new file mode 100644 index 00000000..d74722e6 --- /dev/null +++ b/src/modules/Products/src/Products/Views/CreateEndpoint.cs @@ -0,0 +1,14 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Routing; +using SimpleModule.Core; +using SimpleModule.Core.Inertia; + +namespace SimpleModule.Products.Views; + +public class CreateEndpoint : IEndpoint +{ + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/create", () => Inertia.Render("Products/Create")); + } +} diff --git a/src/modules/Products/src/Products/Pages/Edit.tsx b/src/modules/Products/src/Products/Views/Edit.tsx similarity index 100% rename from src/modules/Products/src/Products/Pages/Edit.tsx rename to src/modules/Products/src/Products/Views/Edit.tsx diff --git a/src/modules/Products/src/Products/Views/EditEndpoint.cs b/src/modules/Products/src/Products/Views/EditEndpoint.cs new file mode 100644 index 00000000..020aa4d0 --- /dev/null +++ b/src/modules/Products/src/Products/Views/EditEndpoint.cs @@ -0,0 +1,23 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Routing; +using SimpleModule.Core; +using SimpleModule.Core.Inertia; +using SimpleModule.Products.Contracts; + +namespace SimpleModule.Products.Views; + +public class EditEndpoint : IEndpoint +{ + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/{id}/edit", async (int id, IProductContracts products) => + { + var product = await products.GetProductByIdAsync(id); + if (product is null) + return Results.NotFound(); + + return Inertia.Render("Products/Edit", new { product }); + }); + } +} diff --git a/src/modules/Products/src/Products/Pages/Manage.tsx b/src/modules/Products/src/Products/Views/Manage.tsx similarity index 100% rename from src/modules/Products/src/Products/Pages/Manage.tsx rename to src/modules/Products/src/Products/Views/Manage.tsx diff --git a/src/modules/Products/src/Products/Views/ManageEndpoint.cs b/src/modules/Products/src/Products/Views/ManageEndpoint.cs new file mode 100644 index 00000000..3c45a4d8 --- /dev/null +++ b/src/modules/Products/src/Products/Views/ManageEndpoint.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Routing; +using SimpleModule.Core; +using SimpleModule.Core.Inertia; +using SimpleModule.Products.Contracts; + +namespace SimpleModule.Products.Views; + +public class ManageEndpoint : IEndpoint +{ + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/manage", async (IProductContracts products) => + Inertia.Render("Products/Manage", + new { products = await products.GetAllProductsAsync() })); + } +} diff --git a/tests/SimpleModule.Generator.Tests/Helpers/GeneratorTestHelper.cs b/tests/SimpleModule.Generator.Tests/Helpers/GeneratorTestHelper.cs index a821ba29..09c1dce6 100644 --- a/tests/SimpleModule.Generator.Tests/Helpers/GeneratorTestHelper.cs +++ b/tests/SimpleModule.Generator.Tests/Helpers/GeneratorTestHelper.cs @@ -57,6 +57,18 @@ public static CSharpCompilation CreateCompilation(params string[] sources) if (File.Exists(configAbstractionsPath)) references.Add(MetadataReference.CreateFromFile(configAbstractionsPath)); + // Add ASP.NET Core HTTP abstractions (for IResult) + references.Add( + MetadataReference.CreateFromFile( + typeof(Microsoft.AspNetCore.Http.IResult).Assembly.Location + ) + ); + + // Add System.Threading.Tasks for Task + var tasksPath = Path.Combine(runtimeDir, "System.Threading.Tasks.dll"); + if (File.Exists(tasksPath)) + references.Add(MetadataReference.CreateFromFile(tasksPath)); + return CSharpCompilation.Create( "TestAssembly", syntaxTrees, diff --git a/tests/SimpleModule.Generator.Tests/SimpleModule.Generator.Tests.csproj b/tests/SimpleModule.Generator.Tests/SimpleModule.Generator.Tests.csproj index 6ad70e55..7bf821f3 100644 --- a/tests/SimpleModule.Generator.Tests/SimpleModule.Generator.Tests.csproj +++ b/tests/SimpleModule.Generator.Tests/SimpleModule.Generator.Tests.csproj @@ -4,6 +4,9 @@ false Exe + + + diff --git a/tests/SimpleModule.Generator.Tests/ViewDiscoveryTests.cs b/tests/SimpleModule.Generator.Tests/ViewDiscoveryTests.cs new file mode 100644 index 00000000..ef6cee1b --- /dev/null +++ b/tests/SimpleModule.Generator.Tests/ViewDiscoveryTests.cs @@ -0,0 +1,292 @@ +using FluentAssertions; +using SimpleModule.Generator.Tests.Helpers; + +namespace SimpleModule.Generator.Tests; + +public class ViewDiscoveryTests +{ + [Fact] + public void EndpointInViewsNamespace_DiscoveredAsView_RoutedUnderViewPrefix() + { + var source = """ + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Routing; + using SimpleModule.Core; + + namespace TestApp + { + [Module("Test", ViewPrefix = "/test")] + public class TestModule : IModule { } + } + + namespace TestApp.Views + { + public class CreateEndpoint : IEndpoint + { + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/create", () => "create"); + } + } + } + """; + + var compilation = GeneratorTestHelper.CreateCompilation(source); + var result = GeneratorTestHelper.RunGenerator(compilation); + + var endpointExt = result + .GeneratedTrees.First(t => + t.FilePath.EndsWith("EndpointExtensions.g.cs", StringComparison.Ordinal) + ) + .GetText() + .ToString(); + + endpointExt.Should().Contain("var viewGroup = app.MapGroup(\"/test\")"); + endpointExt.Should().Contain("new global::TestApp.Views.CreateEndpoint().Map(viewGroup)"); + } + + [Fact] + public void EndpointInNonViewsNamespace_DiscoveredAsEndpoint_RoutedUnderRoutePrefix() + { + var source = """ + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Routing; + using SimpleModule.Core; + + namespace TestApp + { + [Module("Test", RoutePrefix = "/api/test")] + public class TestModule : IModule { } + } + + namespace TestApp.Endpoints + { + public class ListEndpoint : IEndpoint + { + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/", () => "list"); + } + } + } + """; + + var compilation = GeneratorTestHelper.CreateCompilation(source); + var result = GeneratorTestHelper.RunGenerator(compilation); + + var endpointExt = result + .GeneratedTrees.First(t => + t.FilePath.EndsWith("EndpointExtensions.g.cs", StringComparison.Ordinal) + ) + .GetText() + .ToString(); + + endpointExt.Should().Contain("var group = app.MapGroup(\"/api/test\")"); + endpointExt.Should().Contain("new global::TestApp.Endpoints.ListEndpoint().Map(group)"); + endpointExt.Should().NotContain("viewGroup"); + } + + [Fact] + public void PageNameDerived_FromModuleNameAndClassName_StrippingEndpointSuffix() + { + var source = """ + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Routing; + using SimpleModule.Core; + + namespace TestApp + { + [Module("Products", ViewPrefix = "/products")] + public class ProductsModule : IModule { } + } + + namespace TestApp.Views + { + public class BrowseEndpoint : IEndpoint + { + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/browse", () => "browse"); + } + } + } + """; + + var compilation = GeneratorTestHelper.CreateCompilation(source); + var result = GeneratorTestHelper.RunGenerator(compilation); + + result + .GeneratedTrees.Should() + .Contain(t => + t.FilePath.EndsWith("ViewPages_Products.g.cs", StringComparison.Ordinal) + ); + + var viewPages = result + .GeneratedTrees.First(t => + t.FilePath.EndsWith("ViewPages_Products.g.cs", StringComparison.Ordinal) + ) + .GetText() + .ToString(); + + viewPages.Should().Contain("import Browse from '../Views/Browse'"); + viewPages.Should().Contain("'Products/Browse': Browse"); + } + + [Fact] + public void ViewPages_GeneratesTypeScriptIndex() + { + var source = """ + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Routing; + using SimpleModule.Core; + + namespace TestApp + { + [Module("Test", ViewPrefix = "/test")] + public class TestModule : IModule { } + } + + namespace TestApp.Views + { + public class BrowseEndpoint : IEndpoint + { + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/browse", () => "browse"); + } + } + + public class CreateEndpoint : IEndpoint + { + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/create", () => "create"); + } + } + } + """; + + var compilation = GeneratorTestHelper.CreateCompilation(source); + var result = GeneratorTestHelper.RunGenerator(compilation); + + result + .GeneratedTrees.Should() + .Contain(t => + t.FilePath.EndsWith("ViewPages_Test.g.cs", StringComparison.Ordinal) + ); + + var viewPages = result + .GeneratedTrees.First(t => + t.FilePath.EndsWith("ViewPages_Test.g.cs", StringComparison.Ordinal) + ) + .GetText() + .ToString(); + + viewPages.Should().Contain("import Browse from '../Views/Browse'"); + viewPages.Should().Contain("import Create from '../Views/Create'"); + viewPages.Should().Contain("'Test/Browse': Browse"); + viewPages.Should().Contain("'Test/Create': Create"); + } + + [Fact] + public void ModuleWithViewsAndEndpoints_BothCoexist() + { + var source = """ + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Routing; + using SimpleModule.Core; + + namespace TestApp + { + [Module("Test", RoutePrefix = "/api/test", ViewPrefix = "/test")] + public class TestModule : IModule + { + public void ConfigureEndpoints(IEndpointRouteBuilder endpoints) { } + } + } + + namespace TestApp.Endpoints + { + public class ListEndpoint : IEndpoint + { + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/", () => "list"); + } + } + } + + namespace TestApp.Views + { + public class BrowseEndpoint : IEndpoint + { + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/browse", () => "browse"); + } + } + } + """; + + var compilation = GeneratorTestHelper.CreateCompilation(source); + var result = GeneratorTestHelper.RunGenerator(compilation); + + var endpointExt = result + .GeneratedTrees.First(t => + t.FilePath.EndsWith("EndpointExtensions.g.cs", StringComparison.Ordinal) + ) + .GetText() + .ToString(); + + // Plain endpoints use RoutePrefix + endpointExt.Should().Contain("var group = app.MapGroup(\"/api/test\")"); + endpointExt.Should().Contain("new global::TestApp.Endpoints.ListEndpoint().Map(group)"); + + // Views use ViewPrefix + endpointExt.Should().Contain("var viewGroup = app.MapGroup(\"/test\")"); + endpointExt.Should().Contain("new global::TestApp.Views.BrowseEndpoint().Map(viewGroup)"); + + // ConfigureEndpoints still called + endpointExt.Should().Contain("s_TestApp_TestModule.ConfigureEndpoints(app)"); + } + + [Fact] + public void ViewClassName_WithViewSuffix_StrippedCorrectly() + { + var source = """ + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Routing; + using SimpleModule.Core; + + namespace TestApp + { + [Module("Test", ViewPrefix = "/test")] + public class TestModule : IModule { } + } + + namespace TestApp.Views + { + public class DetailView : IEndpoint + { + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/{id}", () => "detail"); + } + } + } + """; + + var compilation = GeneratorTestHelper.CreateCompilation(source); + var result = GeneratorTestHelper.RunGenerator(compilation); + + var viewPages = result + .GeneratedTrees.First(t => + t.FilePath.EndsWith("ViewPages_Test.g.cs", StringComparison.Ordinal) + ) + .GetText() + .ToString(); + + viewPages.Should().Contain("import Detail from '../Views/Detail'"); + viewPages.Should().Contain("'Test/Detail': Detail"); + } +} diff --git a/tools/extract-view-pages.mjs b/tools/extract-view-pages.mjs new file mode 100644 index 00000000..76bd57f8 --- /dev/null +++ b/tools/extract-view-pages.mjs @@ -0,0 +1,35 @@ +#!/usr/bin/env node +// Extracts auto-generated Pages/index.ts from ViewPages_*.g.cs files +// Usage: node tools/extract-view-pages.mjs +// Example: node tools/extract-view-pages.mjs obj/Debug/.../ViewPages_Products.g.cs src/modules/Products/src/Products/Pages + +import { readFileSync, writeFileSync, mkdirSync } from 'fs'; +import { dirname, resolve } from 'path'; + +const inputFile = process.argv[2]; +const outputDir = process.argv[3]; + +if (!inputFile || !outputDir) { + console.error( + 'Usage: node extract-view-pages.mjs ', + ); + process.exit(1); +} + +const content = readFileSync(inputFile, 'utf-8'); +const match = content.match(/\/\*\n([\s\S]*?)\*\//); + +if (!match) { + console.log('No view pages definitions found in generated file.'); + process.exit(0); +} + +const tsContent = match[1]; +const outPath = resolve(outputDir, 'index.ts'); + +mkdirSync(dirname(outPath), { recursive: true }); +writeFileSync( + outPath, + `// Auto-generated from [View] types — do not edit\n${tsContent}`, +); +console.log(`Wrote view pages to ${outPath}`); From 4649ff9198aa2e45c35c0bb581c03185b72ac7fb Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 16 Mar 2026 11:01:46 +0100 Subject: [PATCH 19/62] feat: add IViewEndpoint marker interface Co-Authored-By: Claude Opus 4.6 (1M context) --- src/SimpleModule.Core/IViewEndpoint.cs | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/SimpleModule.Core/IViewEndpoint.cs diff --git a/src/SimpleModule.Core/IViewEndpoint.cs b/src/SimpleModule.Core/IViewEndpoint.cs new file mode 100644 index 00000000..3dc32059 --- /dev/null +++ b/src/SimpleModule.Core/IViewEndpoint.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNetCore.Routing; + +namespace SimpleModule.Core; + +public interface IViewEndpoint +{ + void Map(IEndpointRouteBuilder app); +} From e7c1f1a46e8d265d0ef78a4b685f7fabd61be806 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 16 Mar 2026 11:03:28 +0100 Subject: [PATCH 20/62] feat: classify endpoints by IViewEndpoint interface, exclude views from Swagger Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ModuleDiscovererGenerator.cs | 94 ++++++++----------- 1 file changed, 41 insertions(+), 53 deletions(-) diff --git a/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs b/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs index 330dd5dd..c1512caa 100644 --- a/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs +++ b/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs @@ -57,6 +57,10 @@ private static DiscoveryData ExtractDiscoveryData(Compilation compilation) "SimpleModule.Core.IEndpoint" ); + var viewEndpointInterfaceSymbol = compilation.GetTypeByMetadataName( + "SimpleModule.Core.IViewEndpoint" + ); + var modules = new List(); foreach (var reference in compilation.References) @@ -76,7 +80,7 @@ is not IAssemblySymbol assemblySymbol return DiscoveryData.Empty; // Discover IEndpoint implementors per module assembly. - // Endpoints whose FQN contains ".Views." are classified as view endpoints. + // Classification is by interface type: IViewEndpoint → view, IEndpoint → API. if (endpointInterfaceSymbol is not null) { foreach (var module in modules) @@ -90,6 +94,7 @@ is not IAssemblySymbol assemblySymbol FindEndpointTypes( assembly.GlobalNamespace, endpointInterfaceSymbol, + viewEndpointInterfaceSymbol, module.ModuleName, module.Endpoints, module.Views @@ -147,17 +152,16 @@ typeSymbol is not null modules .Select(m => new ModuleInfoRecord( m.FullyQualifiedName, + m.ModuleName, m.HasConfigureServices, m.HasConfigureEndpoints, m.HasConfigureMenu, m.HasRazorComponents, m.RoutePrefix, m.ViewPrefix, - m.Endpoints - .Select(e => new EndpointInfoRecord(e.FullyQualifiedName)) + m.Endpoints.Select(e => new EndpointInfoRecord(e.FullyQualifiedName)) .ToImmutableArray(), - m.Views - .Select(v => new ViewInfoRecord(v.FullyQualifiedName, v.Page)) + m.Views.Select(v => new ViewInfoRecord(v.FullyQualifiedName, v.Page)) .ToImmutableArray() )) .ToImmutableArray(), @@ -199,9 +203,10 @@ List modules ) ) { - var moduleName = attr.ConstructorArguments.Length > 0 - ? attr.ConstructorArguments[0].Value as string ?? "" - : ""; + var moduleName = + attr.ConstructorArguments.Length > 0 + ? attr.ConstructorArguments[0].Value as string ?? "" + : ""; var routePrefix = ""; var viewPrefix = ""; foreach (var namedArg in attr.NamedArguments) @@ -252,6 +257,7 @@ List modules private static void FindEndpointTypes( INamespaceSymbol namespaceSymbol, INamedTypeSymbol endpointInterfaceSymbol, + INamedTypeSymbol? viewEndpointInterfaceSymbol, string moduleName, List endpoints, List views @@ -264,6 +270,7 @@ List views FindEndpointTypes( childNamespace, endpointInterfaceSymbol, + viewEndpointInterfaceSymbol, moduleName, endpoints, views @@ -274,42 +281,30 @@ List views if ( !typeSymbol.IsAbstract && !typeSymbol.IsStatic - && ImplementsInterface(typeSymbol, endpointInterfaceSymbol) ) { var fqn = typeSymbol.ToDisplayString( SymbolDisplayFormat.FullyQualifiedFormat ); - // Check if this endpoint lives in a .Views. namespace - if (fqn.Contains(".Views.")) + if (viewEndpointInterfaceSymbol is not null + && ImplementsInterface(typeSymbol, viewEndpointInterfaceSymbol)) { var className = typeSymbol.Name; - // Strip Endpoint/View suffix if (className.EndsWith("Endpoint", StringComparison.Ordinal)) - className = className.Substring( - 0, - className.Length - "Endpoint".Length - ); + className = className.Substring(0, className.Length - "Endpoint".Length); else if (className.EndsWith("View", StringComparison.Ordinal)) - className = className.Substring( - 0, - className.Length - "View".Length - ); + className = className.Substring(0, className.Length - "View".Length); - views.Add( - new ViewInfo - { - FullyQualifiedName = fqn, - Page = moduleName + "/" + className, - } - ); + views.Add(new ViewInfo + { + FullyQualifiedName = fqn, + Page = moduleName + "/" + className, + }); } - else + else if (ImplementsInterface(typeSymbol, endpointInterfaceSymbol)) { - endpoints.Add( - new EndpointInfo { FullyQualifiedName = fqn } - ); + endpoints.Add(new EndpointInfo { FullyQualifiedName = fqn }); } } } @@ -481,6 +476,7 @@ ImmutableArray modules sb.AppendLine("// "); sb.AppendLine("using Microsoft.AspNetCore.Builder;"); sb.AppendLine("using Microsoft.AspNetCore.Routing;"); + sb.AppendLine("using Microsoft.AspNetCore.Http;"); sb.AppendLine(); sb.AppendLine("namespace SimpleModule.Core;"); sb.AppendLine(); @@ -492,43 +488,38 @@ ImmutableArray modules sb.AppendLine(" {"); // Auto-registered endpoints (IEndpoint implementors) + // Skip modules that define ConfigureEndpoints — they manage their own registration. foreach (var module in modules) { - if (module.Endpoints.Length == 0) + if (module.Endpoints.Length == 0 || module.HasConfigureEndpoints) continue; sb.AppendLine(); - sb.AppendLine( - $" // Auto-registered endpoints for {module.FullyQualifiedName}" - ); + sb.AppendLine($" // Auto-registered endpoints for {module.FullyQualifiedName}"); sb.AppendLine(" {"); if (!string.IsNullOrEmpty(module.RoutePrefix)) { sb.AppendLine( - $" var group = app.MapGroup(\"{module.RoutePrefix}\");" + $" var group = app.MapGroup(\"{module.RoutePrefix}\").WithTags(\"{module.ModuleName}\");" ); foreach (var endpoint in module.Endpoints) { - sb.AppendLine( - $" new {endpoint.FullyQualifiedName}().Map(group);" - ); + sb.AppendLine($" new {endpoint.FullyQualifiedName}().Map(group);"); } } else { foreach (var endpoint in module.Endpoints) { - sb.AppendLine( - $" new {endpoint.FullyQualifiedName}().Map(app);" - ); + sb.AppendLine($" new {endpoint.FullyQualifiedName}().Map(app);"); } } sb.AppendLine(" }"); } - // Auto-registered view endpoints (IEndpoint in *.Views.* namespace) + // Auto-registered view endpoints (IViewEndpoint implementors) foreach (var module in modules) { if (module.Views.Length == 0) @@ -543,22 +534,18 @@ ImmutableArray modules if (!string.IsNullOrEmpty(module.ViewPrefix)) { sb.AppendLine( - $" var viewGroup = app.MapGroup(\"{module.ViewPrefix}\");" + $" var viewGroup = app.MapGroup(\"{module.ViewPrefix}\").WithTags(\"{module.ModuleName}\").ExcludeFromDescription();" ); foreach (var view in module.Views) { - sb.AppendLine( - $" new {view.FullyQualifiedName}().Map(viewGroup);" - ); + sb.AppendLine($" new {view.FullyQualifiedName}().Map(viewGroup);"); } } else { foreach (var view in module.Views) { - sb.AppendLine( - $" new {view.FullyQualifiedName}().Map(app);" - ); + sb.AppendLine($" new {view.FullyQualifiedName}().Map(app);"); } } @@ -746,9 +733,7 @@ ImmutableArray modules // Extract module name from FQN (e.g., "global::SimpleModule.Products.ProductsModule" → "Products") var fqn = module.FullyQualifiedName.Replace("global::", ""); - var moduleName = fqn.Contains(".") - ? fqn.Substring(fqn.LastIndexOf('.') + 1) - : fqn; + var moduleName = fqn.Contains(".") ? fqn.Substring(fqn.LastIndexOf('.') + 1) : fqn; if (moduleName.EndsWith("Module", StringComparison.Ordinal)) moduleName = moduleName.Substring(0, moduleName.Length - "Module".Length); @@ -963,6 +948,7 @@ public override int GetHashCode() private readonly record struct ModuleInfoRecord( string FullyQualifiedName, + string ModuleName, bool HasConfigureServices, bool HasConfigureEndpoints, bool HasConfigureMenu, @@ -976,6 +962,7 @@ ImmutableArray Views public bool Equals(ModuleInfoRecord other) { return FullyQualifiedName == other.FullyQualifiedName + && ModuleName == other.ModuleName && HasConfigureServices == other.HasConfigureServices && HasConfigureEndpoints == other.HasConfigureEndpoints && HasConfigureMenu == other.HasConfigureMenu @@ -992,6 +979,7 @@ public override int GetHashCode() { var hash = 17; hash = hash * 31 + FullyQualifiedName.GetHashCode(); + hash = hash * 31 + (ModuleName ?? "").GetHashCode(); hash = hash * 31 + HasConfigureServices.GetHashCode(); hash = hash * 31 + HasConfigureEndpoints.GetHashCode(); hash = hash * 31 + HasConfigureMenu.GetHashCode(); From 3584f750d31a36458998db1620eb5379f65bf6a6 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 16 Mar 2026 11:07:23 +0100 Subject: [PATCH 21/62] test: update view discovery tests for IViewEndpoint interface Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ViewDiscoveryTests.cs | 72 +++++++++++++------ 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/tests/SimpleModule.Generator.Tests/ViewDiscoveryTests.cs b/tests/SimpleModule.Generator.Tests/ViewDiscoveryTests.cs index ef6cee1b..37eca48b 100644 --- a/tests/SimpleModule.Generator.Tests/ViewDiscoveryTests.cs +++ b/tests/SimpleModule.Generator.Tests/ViewDiscoveryTests.cs @@ -21,7 +21,7 @@ public class TestModule : IModule { } namespace TestApp.Views { - public class CreateEndpoint : IEndpoint + public class CreateEndpoint : IViewEndpoint { public void Map(IEndpointRouteBuilder app) { @@ -41,7 +41,7 @@ public void Map(IEndpointRouteBuilder app) .GetText() .ToString(); - endpointExt.Should().Contain("var viewGroup = app.MapGroup(\"/test\")"); + endpointExt.Should().Contain("var viewGroup = app.MapGroup(\"/test\").WithTags(\"Test\").ExcludeFromDescription()"); endpointExt.Should().Contain("new global::TestApp.Views.CreateEndpoint().Map(viewGroup)"); } @@ -102,7 +102,7 @@ public class ProductsModule : IModule { } namespace TestApp.Views { - public class BrowseEndpoint : IEndpoint + public class BrowseEndpoint : IViewEndpoint { public void Map(IEndpointRouteBuilder app) { @@ -117,9 +117,7 @@ public void Map(IEndpointRouteBuilder app) result .GeneratedTrees.Should() - .Contain(t => - t.FilePath.EndsWith("ViewPages_Products.g.cs", StringComparison.Ordinal) - ); + .Contain(t => t.FilePath.EndsWith("ViewPages_Products.g.cs", StringComparison.Ordinal)); var viewPages = result .GeneratedTrees.First(t => @@ -148,7 +146,7 @@ public class TestModule : IModule { } namespace TestApp.Views { - public class BrowseEndpoint : IEndpoint + public class BrowseEndpoint : IViewEndpoint { public void Map(IEndpointRouteBuilder app) { @@ -156,7 +154,7 @@ public void Map(IEndpointRouteBuilder app) } } - public class CreateEndpoint : IEndpoint + public class CreateEndpoint : IViewEndpoint { public void Map(IEndpointRouteBuilder app) { @@ -171,9 +169,7 @@ public void Map(IEndpointRouteBuilder app) result .GeneratedTrees.Should() - .Contain(t => - t.FilePath.EndsWith("ViewPages_Test.g.cs", StringComparison.Ordinal) - ); + .Contain(t => t.FilePath.EndsWith("ViewPages_Test.g.cs", StringComparison.Ordinal)); var viewPages = result .GeneratedTrees.First(t => @@ -199,10 +195,7 @@ public void ModuleWithViewsAndEndpoints_BothCoexist() namespace TestApp { [Module("Test", RoutePrefix = "/api/test", ViewPrefix = "/test")] - public class TestModule : IModule - { - public void ConfigureEndpoints(IEndpointRouteBuilder endpoints) { } - } + public class TestModule : IModule { } } namespace TestApp.Endpoints @@ -218,7 +211,7 @@ public void Map(IEndpointRouteBuilder app) namespace TestApp.Views { - public class BrowseEndpoint : IEndpoint + public class BrowseEndpoint : IViewEndpoint { public void Map(IEndpointRouteBuilder app) { @@ -243,11 +236,8 @@ public void Map(IEndpointRouteBuilder app) endpointExt.Should().Contain("new global::TestApp.Endpoints.ListEndpoint().Map(group)"); // Views use ViewPrefix - endpointExt.Should().Contain("var viewGroup = app.MapGroup(\"/test\")"); + endpointExt.Should().Contain("var viewGroup = app.MapGroup(\"/test\").WithTags(\"Test\").ExcludeFromDescription()"); endpointExt.Should().Contain("new global::TestApp.Views.BrowseEndpoint().Map(viewGroup)"); - - // ConfigureEndpoints still called - endpointExt.Should().Contain("s_TestApp_TestModule.ConfigureEndpoints(app)"); } [Fact] @@ -266,7 +256,7 @@ public class TestModule : IModule { } namespace TestApp.Views { - public class DetailView : IEndpoint + public class DetailView : IViewEndpoint { public void Map(IEndpointRouteBuilder app) { @@ -289,4 +279,44 @@ public void Map(IEndpointRouteBuilder app) viewPages.Should().Contain("import Detail from '../Views/Detail'"); viewPages.Should().Contain("'Test/Detail': Detail"); } + + [Fact] + public void IEndpointInViewsNamespace_DiscoveredAsEndpoint_NotView() + { + var source = """ + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Routing; + using SimpleModule.Core; + + namespace TestApp + { + [Module("Test", RoutePrefix = "/api/test", ViewPrefix = "/test")] + public class TestModule : IModule { } + } + + namespace TestApp.Views + { + public class ListEndpoint : IEndpoint + { + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/", () => "list"); + } + } + } + """; + + var compilation = GeneratorTestHelper.CreateCompilation(source); + var result = GeneratorTestHelper.RunGenerator(compilation); + + var endpointExt = result + .GeneratedTrees.First(t => + t.FilePath.EndsWith("EndpointExtensions.g.cs", StringComparison.Ordinal) + ) + .GetText() + .ToString(); + + endpointExt.Should().Contain("new global::TestApp.Views.ListEndpoint().Map(group)"); + endpointExt.Should().NotContain("viewGroup"); + } } From 7f3b34dfd4bba2502bcf366ef88b4432728229b1 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 16 Mar 2026 11:08:38 +0100 Subject: [PATCH 22/62] refactor: migrate Products view endpoints to IViewEndpoint Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/Products/Views/BrowseEndpoint.cs | 13 +++++++++---- .../src/Products/Views/CreateEndpoint.cs | 2 +- .../src/Products/Views/EditEndpoint.cs | 19 +++++++++++-------- .../src/Products/Views/ManageEndpoint.cs | 13 +++++++++---- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/modules/Products/src/Products/Views/BrowseEndpoint.cs b/src/modules/Products/src/Products/Views/BrowseEndpoint.cs index 6234287a..99323e49 100644 --- a/src/modules/Products/src/Products/Views/BrowseEndpoint.cs +++ b/src/modules/Products/src/Products/Views/BrowseEndpoint.cs @@ -6,12 +6,17 @@ namespace SimpleModule.Products.Views; -public class BrowseEndpoint : IEndpoint +public class BrowseEndpoint : IViewEndpoint { public void Map(IEndpointRouteBuilder app) { - app.MapGet("/browse", async (IProductContracts products) => - Inertia.Render("Products/Browse", - new { products = await products.GetAllProductsAsync() })); + app.MapGet( + "/browse", + async (IProductContracts products) => + Inertia.Render( + "Products/Browse", + new { products = await products.GetAllProductsAsync() } + ) + ); } } diff --git a/src/modules/Products/src/Products/Views/CreateEndpoint.cs b/src/modules/Products/src/Products/Views/CreateEndpoint.cs index d74722e6..6ffaf82a 100644 --- a/src/modules/Products/src/Products/Views/CreateEndpoint.cs +++ b/src/modules/Products/src/Products/Views/CreateEndpoint.cs @@ -5,7 +5,7 @@ namespace SimpleModule.Products.Views; -public class CreateEndpoint : IEndpoint +public class CreateEndpoint : IViewEndpoint { public void Map(IEndpointRouteBuilder app) { diff --git a/src/modules/Products/src/Products/Views/EditEndpoint.cs b/src/modules/Products/src/Products/Views/EditEndpoint.cs index 020aa4d0..d1bcc69c 100644 --- a/src/modules/Products/src/Products/Views/EditEndpoint.cs +++ b/src/modules/Products/src/Products/Views/EditEndpoint.cs @@ -7,17 +7,20 @@ namespace SimpleModule.Products.Views; -public class EditEndpoint : IEndpoint +public class EditEndpoint : IViewEndpoint { public void Map(IEndpointRouteBuilder app) { - app.MapGet("/{id}/edit", async (int id, IProductContracts products) => - { - var product = await products.GetProductByIdAsync(id); - if (product is null) - return Results.NotFound(); + app.MapGet( + "/{id}/edit", + async (int id, IProductContracts products) => + { + var product = await products.GetProductByIdAsync(id); + if (product is null) + return Results.NotFound(); - return Inertia.Render("Products/Edit", new { product }); - }); + return Inertia.Render("Products/Edit", new { product }); + } + ); } } diff --git a/src/modules/Products/src/Products/Views/ManageEndpoint.cs b/src/modules/Products/src/Products/Views/ManageEndpoint.cs index 3c45a4d8..7291d73f 100644 --- a/src/modules/Products/src/Products/Views/ManageEndpoint.cs +++ b/src/modules/Products/src/Products/Views/ManageEndpoint.cs @@ -6,12 +6,17 @@ namespace SimpleModule.Products.Views; -public class ManageEndpoint : IEndpoint +public class ManageEndpoint : IViewEndpoint { public void Map(IEndpointRouteBuilder app) { - app.MapGet("/manage", async (IProductContracts products) => - Inertia.Render("Products/Manage", - new { products = await products.GetAllProductsAsync() })); + app.MapGet( + "/manage", + async (IProductContracts products) => + Inertia.Render( + "Products/Manage", + new { products = await products.GetAllProductsAsync() } + ) + ); } } From 7feb9c8757ffdaee888760c267ea01a83ff2f01a Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 16 Mar 2026 11:20:59 +0100 Subject: [PATCH 23/62] refactor: remove ConfigureEndpoints from ProductsModule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit API endpoints in Endpoints/ are now auto-registered by the generator. Form-based handlers removed — frontend should POST JSON to API endpoints. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Products/src/Products/ProductsModule.cs | 59 ++----------------- 1 file changed, 5 insertions(+), 54 deletions(-) diff --git a/src/modules/Products/src/Products/ProductsModule.cs b/src/modules/Products/src/Products/ProductsModule.cs index 0e084ef0..524ef345 100644 --- a/src/modules/Products/src/Products/ProductsModule.cs +++ b/src/modules/Products/src/Products/ProductsModule.cs @@ -1,7 +1,3 @@ -using System.Globalization; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using SimpleModule.Core; @@ -11,7 +7,11 @@ namespace SimpleModule.Products; -[Module(ProductsConstants.ModuleName, RoutePrefix = ProductsConstants.RoutePrefix, ViewPrefix = "/products")] +[Module( + ProductsConstants.ModuleName, + RoutePrefix = ProductsConstants.RoutePrefix, + ViewPrefix = "/products" +)] public class ProductsModule : IModule { public void ConfigureServices(IServiceCollection services, IConfiguration configuration) @@ -46,53 +46,4 @@ public void ConfigureMenu(IMenuBuilder menus) } ); } - - public void ConfigureEndpoints(IEndpointRouteBuilder endpoints) - { - var group = endpoints.MapGroup("/products"); - - // Create product (POST) - group.MapPost( - "/", - async (HttpContext context, IProductContracts products) => - { - var form = await context.Request.ReadFormAsync(); - var request = new CreateProductRequest - { - Name = form["name"].ToString(), - Price = decimal.Parse(form["price"].ToString(), CultureInfo.InvariantCulture), - }; - - await products.CreateProductAsync(request); - return Results.Redirect("/products/manage"); - } - ); - - // Update product (POST) - group.MapPost( - "/{id}", - async (int id, HttpContext context, IProductContracts products) => - { - var form = await context.Request.ReadFormAsync(); - var request = new UpdateProductRequest - { - Name = form["name"].ToString(), - Price = decimal.Parse(form["price"].ToString(), CultureInfo.InvariantCulture), - }; - - await products.UpdateProductAsync(id, request); - return Results.Redirect($"/products/{id}/edit"); - } - ); - - // Delete product - group.MapDelete( - "/{id}", - async (int id, IProductContracts products) => - { - await products.DeleteProductAsync(id); - return Results.Redirect("/products/manage"); - } - ); - } } From 06da695f735f347c7971d98c849264f4945bd1f4 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 16 Mar 2026 11:24:56 +0100 Subject: [PATCH 24/62] refactor: apply code style improvements and formatting across multiple files --- docs/plans/2026-03-16-iviewendpoint-design.md | 38 +++ docs/plans/2026-03-16-iviewendpoint-plan.md | 313 ++++++++++++++++++ .../Inertia/InertiaPageRenderer.cs | 4 +- .../ServiceCollectionExtensions.cs | 3 +- .../Templates/FeatureTemplates.cs | 11 +- .../Templates/ModuleTemplates.cs | 4 +- src/SimpleModule.Host/Program.cs | 2 +- .../SimpleModule.Host.csproj | 20 +- .../Dashboard/src/Dashboard/Dashboard.csproj | 6 +- .../src/Dashboard/DashboardModule.cs | 18 +- src/modules/Orders/src/Orders/Orders.csproj | 8 +- src/modules/Orders/src/Orders/OrdersModule.cs | 35 +- .../Orders.Tests/Unit/OrderServiceTests.cs | 14 +- .../Products/src/Products/Products.csproj | 6 +- .../Unit/ProductServiceTests.cs | 8 +- .../Endpoints/Admin/AdminRolesEndpoint.cs | 1 + .../Endpoints/Admin/AdminUsersEndpoint.cs | 1 + src/modules/Users/src/Users/UserService.cs | 5 +- src/modules/Users/src/Users/Users.csproj | 5 +- src/modules/Users/src/Users/UsersModule.cs | 4 +- .../Integration/UsersEndpointTests.cs | 8 +- .../Users.Tests/Unit/UserServiceTests.cs | 26 +- 22 files changed, 463 insertions(+), 77 deletions(-) create mode 100644 docs/plans/2026-03-16-iviewendpoint-design.md create mode 100644 docs/plans/2026-03-16-iviewendpoint-plan.md diff --git a/docs/plans/2026-03-16-iviewendpoint-design.md b/docs/plans/2026-03-16-iviewendpoint-design.md new file mode 100644 index 00000000..b802dd63 --- /dev/null +++ b/docs/plans/2026-03-16-iviewendpoint-design.md @@ -0,0 +1,38 @@ +# IViewEndpoint Interface Design + +## Goal + +Separate view endpoints (Inertia pages) from API endpoints by introducing an `IViewEndpoint` interface. View endpoints should be excluded from Swagger/OpenAPI documentation automatically. + +## Design + +### New Interface — `SimpleModule.Core.IViewEndpoint` + +```csharp +public interface IViewEndpoint +{ + void Map(IEndpointRouteBuilder app); +} +``` + +Independent from `IEndpoint` (no inheritance). Same signature — acts as a marker for the source generator. + +### Source Generator Changes (`ModuleDiscovererGenerator`) + +1. Resolve `SimpleModule.Core.IViewEndpoint` symbol alongside `IEndpoint` +2. Replace namespace-based classification (`.Views.` check) with interface-based: + - `IEndpoint` implementors → API endpoints + - `IViewEndpoint` implementors → view endpoints +3. Page name derivation unchanged (strip `Endpoint`/`View` suffix from class name) +4. Generated `MapModuleEndpoints()`: view endpoint route groups get `.ExcludeFromDescription()` to hide from Swagger + +### Module Migration + +All existing view endpoints (in `Views/` folders across Products, Users, Dashboard, Orders) change from `IEndpoint` to `IViewEndpoint`. + +### Unchanged + +- `Inertia.Render()` usage +- Route grouping with `ViewPrefix` +- `ConfigureEndpoints()` escape hatch +- `GenerateViewPages()` output diff --git a/docs/plans/2026-03-16-iviewendpoint-plan.md b/docs/plans/2026-03-16-iviewendpoint-plan.md new file mode 100644 index 00000000..51c2c8dc --- /dev/null +++ b/docs/plans/2026-03-16-iviewendpoint-plan.md @@ -0,0 +1,313 @@ +# IViewEndpoint Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Separate view endpoints from API endpoints via a new `IViewEndpoint` marker interface, with automatic Swagger exclusion for views. + +**Architecture:** Add `IViewEndpoint` to Core with identical signature to `IEndpoint`. Update the source generator to classify endpoints by interface type instead of namespace convention. View route groups get `.ExcludeFromDescription()` in generated code. + +**Tech Stack:** C# / Roslyn IIncrementalGenerator / ASP.NET Core Minimal APIs / xUnit + FluentAssertions + +--- + +### Task 1: Add IViewEndpoint interface to Core + +**Files:** +- Create: `src/SimpleModule.Core/IViewEndpoint.cs` + +**Step 1: Create the interface** + +```csharp +using Microsoft.AspNetCore.Routing; + +namespace SimpleModule.Core; + +public interface IViewEndpoint +{ + void Map(IEndpointRouteBuilder app); +} +``` + +**Step 2: Verify build** + +Run: `dotnet build src/SimpleModule.Core` +Expected: Build succeeded + +**Step 3: Commit** + +```bash +git add src/SimpleModule.Core/IViewEndpoint.cs +git commit -m "feat: add IViewEndpoint marker interface" +``` + +--- + +### Task 2: Update source generator to use interface-based classification + +**Files:** +- Modify: `src/SimpleModule.Generator/ModuleDiscovererGenerator.cs` + +**Step 1: Resolve the IViewEndpoint symbol** + +In `ExtractDiscoveryData`, after resolving `IEndpoint` (line ~56), add: + +```csharp +var viewEndpointInterfaceSymbol = compilation.GetTypeByMetadataName( + "SimpleModule.Core.IViewEndpoint" +); +``` + +**Step 2: Update FindEndpointTypes to accept both interface symbols** + +Change the signature to: + +```csharp +private static void FindEndpointTypes( + INamespaceSymbol namespaceSymbol, + INamedTypeSymbol endpointInterfaceSymbol, + INamedTypeSymbol? viewEndpointInterfaceSymbol, + string moduleName, + List endpoints, + List views +) +``` + +**Step 3: Replace namespace-based classification with interface check** + +Replace the body of the type classification (lines 275-314) with: + +```csharp +if ( + !typeSymbol.IsAbstract + && !typeSymbol.IsStatic +) +{ + var fqn = typeSymbol.ToDisplayString( + SymbolDisplayFormat.FullyQualifiedFormat + ); + + if (viewEndpointInterfaceSymbol is not null + && ImplementsInterface(typeSymbol, viewEndpointInterfaceSymbol)) + { + var className = typeSymbol.Name; + if (className.EndsWith("Endpoint", StringComparison.Ordinal)) + className = className.Substring( + 0, + className.Length - "Endpoint".Length + ); + else if (className.EndsWith("View", StringComparison.Ordinal)) + className = className.Substring( + 0, + className.Length - "View".Length + ); + + views.Add( + new ViewInfo + { + FullyQualifiedName = fqn, + Page = moduleName + "/" + className, + } + ); + } + else if (ImplementsInterface(typeSymbol, endpointInterfaceSymbol)) + { + endpoints.Add( + new EndpointInfo { FullyQualifiedName = fqn } + ); + } +} +``` + +**Step 4: Update the call site in ExtractDiscoveryData** + +Pass `viewEndpointInterfaceSymbol` to `FindEndpointTypes`: + +```csharp +FindEndpointTypes( + assembly.GlobalNamespace, + endpointInterfaceSymbol, + viewEndpointInterfaceSymbol, + module.ModuleName, + module.Endpoints, + module.Views +); +``` + +**Step 5: Add `.ExcludeFromDescription()` to view route groups in GenerateEndpointExtensions** + +In the generated view group line (currently line 548), change from: + +```csharp +$" var viewGroup = app.MapGroup(\"{module.ViewPrefix}\").WithTags(\"{module.ModuleName}\");" +``` + +to: + +```csharp +$" var viewGroup = app.MapGroup(\"{module.ViewPrefix}\").WithTags(\"{module.ModuleName}\").ExcludeFromDescription();" +``` + +Also add the `using Microsoft.AspNetCore.Http;` import at the top of the generated file (for `ExcludeFromDescription`). Add after the existing `using Microsoft.AspNetCore.Routing;` line: + +```csharp +sb.AppendLine("using Microsoft.AspNetCore.Http;"); +``` + +For views without a ViewPrefix (the else branch), add `.ExcludeFromDescription()` on the individual endpoint mappings isn't possible directly — but this case means views are mapped directly on `app`, which is unusual. Leave as-is for now since all modules use ViewPrefix. + +**Step 6: Verify build** + +Run: `dotnet build src/SimpleModule.Generator` +Expected: Build succeeded + +**Step 7: Commit** + +```bash +git add src/SimpleModule.Generator/ModuleDiscovererGenerator.cs +git commit -m "feat: classify endpoints by IViewEndpoint interface, exclude views from Swagger" +``` + +--- + +### Task 3: Update generator tests for IViewEndpoint + +**Files:** +- Modify: `tests/SimpleModule.Generator.Tests/ViewDiscoveryTests.cs` + +**Step 1: Update all test sources to use IViewEndpoint instead of IEndpoint in Views namespace** + +In every test that has view endpoints in a `.Views.` namespace, change `IEndpoint` to `IViewEndpoint`. For example, in `EndpointInViewsNamespace_DiscoveredAsView_RoutedUnderViewPrefix`: + +```csharp +namespace TestApp.Views +{ + public class CreateEndpoint : IViewEndpoint + { + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/create", () => "create"); + } + } +} +``` + +Apply this to all 5 tests that use view endpoints: +- `EndpointInViewsNamespace_DiscoveredAsView_RoutedUnderViewPrefix` +- `PageNameDerived_FromModuleNameAndClassName_StrippingEndpointSuffix` +- `ViewPages_GeneratesTypeScriptIndex` +- `ModuleWithViewsAndEndpoints_BothCoexist` +- `ViewClassName_WithViewSuffix_StrippedCorrectly` + +**Step 2: Update assertions to expect `.ExcludeFromDescription()`** + +In tests that check for `viewGroup`, update the assertion: + +```csharp +endpointExt.Should().Contain("var viewGroup = app.MapGroup(\"/test\").WithTags(\"Test\").ExcludeFromDescription()"); +``` + +**Step 3: Add a new test — IEndpoint in Views namespace is NOT discovered as view** + +```csharp +[Fact] +public void IEndpointInViewsNamespace_DiscoveredAsEndpoint_NotView() +{ + var source = """ + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Routing; + using SimpleModule.Core; + + namespace TestApp + { + [Module("Test", RoutePrefix = "/api/test", ViewPrefix = "/test")] + public class TestModule : IModule { } + } + + namespace TestApp.Views + { + public class ListEndpoint : IEndpoint + { + public void Map(IEndpointRouteBuilder app) + { + app.MapGet("/", () => "list"); + } + } + } + """; + + var compilation = GeneratorTestHelper.CreateCompilation(source); + var result = GeneratorTestHelper.RunGenerator(compilation); + + var endpointExt = result + .GeneratedTrees.First(t => + t.FilePath.EndsWith("EndpointExtensions.g.cs", StringComparison.Ordinal) + ) + .GetText() + .ToString(); + + endpointExt.Should().Contain("new global::TestApp.Views.ListEndpoint().Map(group)"); + endpointExt.Should().NotContain("viewGroup"); +} +``` + +**Step 4: Run tests** + +Run: `dotnet test tests/SimpleModule.Generator.Tests` +Expected: All tests pass + +**Step 5: Commit** + +```bash +git add tests/SimpleModule.Generator.Tests/ViewDiscoveryTests.cs +git commit -m "test: update view discovery tests for IViewEndpoint interface" +``` + +--- + +### Task 4: Migrate Products view endpoints to IViewEndpoint + +**Files:** +- Modify: `src/modules/Products/src/Products/Views/BrowseEndpoint.cs` +- Modify: `src/modules/Products/src/Products/Views/ManageEndpoint.cs` +- Modify: `src/modules/Products/src/Products/Views/CreateEndpoint.cs` +- Modify: `src/modules/Products/src/Products/Views/EditEndpoint.cs` + +**Step 1: In each file, change `IEndpoint` to `IViewEndpoint`** + +Example for BrowseEndpoint.cs: + +```csharp +public class BrowseEndpoint : IViewEndpoint +``` + +Same for ManageEndpoint, CreateEndpoint, EditEndpoint. + +**Step 2: Verify build** + +Run: `dotnet build src/modules/Products/src/Products` +Expected: Build succeeded + +**Step 3: Commit** + +```bash +git add src/modules/Products/src/Products/Views/ +git commit -m "refactor: migrate Products view endpoints to IViewEndpoint" +``` + +--- + +### Task 5: Full build and verify + +**Step 1: Build the whole solution** + +Run: `dotnet build` +Expected: Build succeeded + +**Step 2: Run all tests** + +Run: `dotnet test` +Expected: All tests pass + +**Step 3: Commit (if any remaining changes)** + +Only if needed. diff --git a/src/SimpleModule.Blazor/Inertia/InertiaPageRenderer.cs b/src/SimpleModule.Blazor/Inertia/InertiaPageRenderer.cs index 1453f60c..2066d79f 100644 --- a/src/SimpleModule.Blazor/Inertia/InertiaPageRenderer.cs +++ b/src/SimpleModule.Blazor/Inertia/InertiaPageRenderer.cs @@ -10,8 +10,8 @@ namespace SimpleModule.Blazor.Inertia; public sealed class InertiaPageRenderer( IServiceProvider services, ILoggerFactory loggerFactory, - IOptions options) - : IInertiaPageRenderer + IOptions options +) : IInertiaPageRenderer { public async Task RenderPageAsync(HttpContext httpContext, string pageJson) { diff --git a/src/SimpleModule.Blazor/ServiceCollectionExtensions.cs b/src/SimpleModule.Blazor/ServiceCollectionExtensions.cs index a658bc2a..182b94c4 100644 --- a/src/SimpleModule.Blazor/ServiceCollectionExtensions.cs +++ b/src/SimpleModule.Blazor/ServiceCollectionExtensions.cs @@ -8,7 +8,8 @@ public static class ServiceCollectionExtensions { public static IServiceCollection AddSimpleModuleBlazor( this IServiceCollection services, - Action? configure = null) + Action? configure = null + ) { services.AddScoped(); if (configure is not null) diff --git a/src/SimpleModule.Cli/Templates/FeatureTemplates.cs b/src/SimpleModule.Cli/Templates/FeatureTemplates.cs index 099c2cff..41f80e53 100644 --- a/src/SimpleModule.Cli/Templates/FeatureTemplates.cs +++ b/src/SimpleModule.Cli/Templates/FeatureTemplates.cs @@ -233,9 +233,16 @@ string singularName ) { // Extract the namespace prefix and replace the endpoint namespace - var nsPrefix = lines[i][..lines[i].IndexOf(".Endpoints.", StringComparison.Ordinal)]; + var nsPrefix = lines[i][ + ..lines[i].IndexOf(".Endpoints.", StringComparison.Ordinal) + ]; var moduleSuffix = lines[i].Contains(';', StringComparison.Ordinal) - ? lines[i][(lines[i].IndexOf(".Endpoints.", StringComparison.Ordinal) + ".Endpoints.".Length)..lines[i].IndexOf(';', StringComparison.Ordinal)] + ? lines[i][ + ( + lines[i].IndexOf(".Endpoints.", StringComparison.Ordinal) + + ".Endpoints.".Length + )..lines[i].IndexOf(';', StringComparison.Ordinal) + ] : moduleName; lines[i] = $"{nsPrefix}.Endpoints.{moduleSuffix};"; } diff --git a/src/SimpleModule.Cli/Templates/ModuleTemplates.cs b/src/SimpleModule.Cli/Templates/ModuleTemplates.cs index 698de0c4..52c0925f 100644 --- a/src/SimpleModule.Cli/Templates/ModuleTemplates.cs +++ b/src/SimpleModule.Cli/Templates/ModuleTemplates.cs @@ -156,9 +156,7 @@ public string EventClass(string moduleName, string singularName) public string GetAllEndpoint(string moduleName, string singularName) { - var refPath = RefModulePath( - Path.Combine("Endpoints", _refModule!, $"GetAllEndpoint.cs") - ); + var refPath = RefModulePath(Path.Combine("Endpoints", _refModule!, $"GetAllEndpoint.cs")); if (refPath is null) { return FallbackGetAllEndpoint(moduleName, singularName); diff --git a/src/SimpleModule.Host/Program.cs b/src/SimpleModule.Host/Program.cs index 13f0fe5b..b987ec19 100644 --- a/src/SimpleModule.Host/Program.cs +++ b/src/SimpleModule.Host/Program.cs @@ -2,7 +2,6 @@ using Microsoft.AspNetCore.Identity; using Microsoft.OpenApi; using OpenIddict.Validation.AspNetCore; -using SimpleModule.Host.Components; using SimpleModule.Blazor; using SimpleModule.Core; using SimpleModule.Core.Constants; @@ -11,6 +10,7 @@ using SimpleModule.Core.Inertia; using SimpleModule.Database; using SimpleModule.Database.Health; +using SimpleModule.Host.Components; var builder = WebApplication.CreateBuilder(args); diff --git a/src/SimpleModule.Host/SimpleModule.Host.csproj b/src/SimpleModule.Host/SimpleModule.Host.csproj index 510b99f8..33508ec9 100644 --- a/src/SimpleModule.Host/SimpleModule.Host.csproj +++ b/src/SimpleModule.Host/SimpleModule.Host.csproj @@ -27,12 +27,8 @@ - $(RepoRoot)tools\tailwindcss.exe - $(RepoRoot)tools/tailwindcss + $(RepoRoot)tools\tailwindcss.exe + $(RepoRoot)tools/tailwindcss $(MSBuildProjectDirectory)/Styles/app.css $(MSBuildProjectDirectory)/wwwroot/css/app.css @@ -44,11 +40,19 @@ - + - + - +
      diff --git a/src/modules/Dashboard/src/Dashboard/DashboardModule.cs b/src/modules/Dashboard/src/Dashboard/DashboardModule.cs index 85955e49..c5e576ac 100644 --- a/src/modules/Dashboard/src/Dashboard/DashboardModule.cs +++ b/src/modules/Dashboard/src/Dashboard/DashboardModule.cs @@ -12,13 +12,9 @@ namespace SimpleModule.Dashboard; [Module(DashboardConstants.ModuleName, RoutePrefix = DashboardConstants.RoutePrefix)] public class DashboardModule : IModule { - public void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - } + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { } - public void ConfigureMenu(IMenuBuilder menus) - { - } + public void ConfigureMenu(IMenuBuilder menus) { } public void ConfigureEndpoints(IEndpointRouteBuilder endpoints) { @@ -28,11 +24,17 @@ public void ConfigureEndpoints(IEndpointRouteBuilder endpoints) { var isAuthenticated = context.User?.Identity?.IsAuthenticated == true; var displayName = context.User?.Identity?.Name ?? "User"; - var isDevelopment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development"; + var isDevelopment = + Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development"; return Inertia.Render( "Dashboard/Home", - new { isAuthenticated, displayName, isDevelopment } + new + { + isAuthenticated, + displayName, + isDevelopment, + } ); } ); diff --git a/src/modules/Orders/src/Orders/Orders.csproj b/src/modules/Orders/src/Orders/Orders.csproj index 8485ebe6..f53b03e8 100644 --- a/src/modules/Orders/src/Orders/Orders.csproj +++ b/src/modules/Orders/src/Orders/Orders.csproj @@ -10,8 +10,12 @@ - - + +
      diff --git a/src/modules/Orders/src/Orders/OrdersModule.cs b/src/modules/Orders/src/Orders/OrdersModule.cs index 8fba5678..f2d18897 100644 --- a/src/modules/Orders/src/Orders/OrdersModule.cs +++ b/src/modules/Orders/src/Orders/OrdersModule.cs @@ -16,7 +16,11 @@ namespace SimpleModule.Orders; [Module(OrdersConstants.ModuleName, RoutePrefix = OrdersConstants.RoutePrefix)] public class OrdersModule : IModule { - private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive = true }; + private static readonly JsonSerializerOptions JsonOptions = new() + { + PropertyNameCaseInsensitive = true, + }; + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) { services.AddModuleDbContext(configuration, OrdersConstants.ModuleName); @@ -40,16 +44,13 @@ public void ConfigureMenu(IMenuBuilder menus) public void ConfigureEndpoints(IEndpointRouteBuilder endpoints) { - var group = endpoints.MapGroup("/orders"); + var group = endpoints.MapGroup("/orders").WithTags(OrdersConstants.ModuleName); // List orders group.MapGet( "/", async (IOrderContracts orders) => - Inertia.Render( - "Orders/List", - new { orders = await orders.GetAllOrdersAsync() } - ) + Inertia.Render("Orders/List", new { orders = await orders.GetAllOrdersAsync() }) ); // Create order page @@ -79,7 +80,11 @@ public void ConfigureEndpoints(IEndpointRouteBuilder endpoints) { id = order.Id, userId = order.UserId, - items = order.Items.Select(i => new { productId = i.ProductId, quantity = i.Quantity }), + items = order.Items.Select(i => new + { + productId = i.ProductId, + quantity = i.Quantity, + }), total = order.Total, createdAt = order.CreatedAt.ToString("O"), }, @@ -102,8 +107,12 @@ public void ConfigureEndpoints(IEndpointRouteBuilder endpoints) var request = new CreateOrderRequest { UserId = body!.UserId, - Items = body.Items - .Select(i => new OrderItem { ProductId = i.ProductId, Quantity = i.Quantity }) + Items = body + .Items.Select(i => new OrderItem + { + ProductId = i.ProductId, + Quantity = i.Quantity, + }) .ToList(), }; @@ -125,8 +134,12 @@ public void ConfigureEndpoints(IEndpointRouteBuilder endpoints) var request = new UpdateOrderRequest { UserId = body!.UserId, - Items = body.Items - .Select(i => new OrderItem { ProductId = i.ProductId, Quantity = i.Quantity }) + Items = body + .Items.Select(i => new OrderItem + { + ProductId = i.ProductId, + Quantity = i.Quantity, + }) .ToList(), }; diff --git a/src/modules/Orders/tests/Orders.Tests/Unit/OrderServiceTests.cs b/src/modules/Orders/tests/Orders.Tests/Unit/OrderServiceTests.cs index 304061cf..e22934a6 100644 --- a/src/modules/Orders/tests/Orders.Tests/Unit/OrderServiceTests.cs +++ b/src/modules/Orders/tests/Orders.Tests/Unit/OrderServiceTests.cs @@ -162,7 +162,12 @@ public async Task GetOrderByIdAsync_ReturnsMatchingOrder() public async Task UpdateOrderAsync_WithValidData_UpdatesOrder() { _users.GetUserByIdAsync("1").Returns(new UserDto { Id = "1", DisplayName = "Test" }); - var widget = new Product { Id = 1, Name = "Widget", Price = 10.00m }; + var widget = new Product + { + Id = 1, + Name = "Widget", + Price = 10.00m, + }; _products .GetProductsByIdsAsync(Arg.Any>()) .Returns(callInfo => @@ -210,7 +215,12 @@ public async Task UpdateOrderAsync_WithNonExistentOrder_ThrowsNotFoundException( public async Task DeleteOrderAsync_WithExistingOrder_RemovesOrder() { _users.GetUserByIdAsync("1").Returns(new UserDto { Id = "1", DisplayName = "Test" }); - var widget = new Product { Id = 1, Name = "Widget", Price = 10.00m }; + var widget = new Product + { + Id = 1, + Name = "Widget", + Price = 10.00m, + }; _products .GetProductsByIdsAsync(Arg.Any>()) .Returns(callInfo => diff --git a/src/modules/Products/src/Products/Products.csproj b/src/modules/Products/src/Products/Products.csproj index 81ee207a..940e99c6 100644 --- a/src/modules/Products/src/Products/Products.csproj +++ b/src/modules/Products/src/Products/Products.csproj @@ -14,7 +14,11 @@ %(Filename)Endpoint.cs - +
      diff --git a/src/modules/Products/tests/Products.Tests/Unit/ProductServiceTests.cs b/src/modules/Products/tests/Products.Tests/Unit/ProductServiceTests.cs index 67ceffba..e8551802 100644 --- a/src/modules/Products/tests/Products.Tests/Unit/ProductServiceTests.cs +++ b/src/modules/Products/tests/Products.Tests/Unit/ProductServiceTests.cs @@ -102,9 +102,7 @@ public async Task UpdateProductAsync_WithNonExistentId_ThrowsNotFoundException() var act = () => _sut.UpdateProductAsync(99999, request); - await act.Should() - .ThrowAsync() - .WithMessage("*Product*99999*not found*"); + await act.Should().ThrowAsync().WithMessage("*Product*99999*not found*"); } [Fact] @@ -124,8 +122,6 @@ public async Task DeleteProductAsync_WithNonExistentId_ThrowsNotFoundException() { var act = () => _sut.DeleteProductAsync(99999); - await act.Should() - .ThrowAsync() - .WithMessage("*Product*99999*not found*"); + await act.Should().ThrowAsync().WithMessage("*Product*99999*not found*"); } } diff --git a/src/modules/Users/src/Users/Endpoints/Admin/AdminRolesEndpoint.cs b/src/modules/Users/src/Users/Endpoints/Admin/AdminRolesEndpoint.cs index d16e66ba..5ad55cef 100644 --- a/src/modules/Users/src/Users/Endpoints/Admin/AdminRolesEndpoint.cs +++ b/src/modules/Users/src/Users/Endpoints/Admin/AdminRolesEndpoint.cs @@ -14,6 +14,7 @@ public static void Map(IEndpointRouteBuilder endpoints) { var group = endpoints .MapGroup("/admin/roles") + .WithTags(UsersConstants.ModuleName) .RequireAuthorization(policy => policy.RequireRole("Admin")); // List roles diff --git a/src/modules/Users/src/Users/Endpoints/Admin/AdminUsersEndpoint.cs b/src/modules/Users/src/Users/Endpoints/Admin/AdminUsersEndpoint.cs index 99bac028..805777c5 100644 --- a/src/modules/Users/src/Users/Endpoints/Admin/AdminUsersEndpoint.cs +++ b/src/modules/Users/src/Users/Endpoints/Admin/AdminUsersEndpoint.cs @@ -16,6 +16,7 @@ public static void Map(IEndpointRouteBuilder endpoints) { var group = endpoints .MapGroup("/admin/users") + .WithTags(UsersConstants.ModuleName) .RequireAuthorization(policy => policy.RequireRole("Admin")); // List users diff --git a/src/modules/Users/src/Users/UserService.cs b/src/modules/Users/src/Users/UserService.cs index 7fab3c94..bb23bebc 100644 --- a/src/modules/Users/src/Users/UserService.cs +++ b/src/modules/Users/src/Users/UserService.cs @@ -56,10 +56,7 @@ public async Task CreateUserAsync(CreateUserRequest request) var result = await userManager.CreateAsync(user, request.Password); if (!result.Succeeded) { - var errors = result.Errors.ToDictionary( - e => e.Code, - e => new[] { e.Description } - ); + var errors = result.Errors.ToDictionary(e => e.Code, e => new[] { e.Description }); throw new Core.Exceptions.ValidationException(errors); } diff --git a/src/modules/Users/src/Users/Users.csproj b/src/modules/Users/src/Users/Users.csproj index 2c106d2d..30ea58da 100644 --- a/src/modules/Users/src/Users/Users.csproj +++ b/src/modules/Users/src/Users/Users.csproj @@ -16,6 +16,9 @@ BeforeTargets="Build" Condition="Exists('package.json') And (Exists('node_modules') Or Exists('$(RepoRoot)node_modules'))" > - +
      diff --git a/src/modules/Users/src/Users/UsersModule.cs b/src/modules/Users/src/Users/UsersModule.cs index 15b6fe57..3370356f 100644 --- a/src/modules/Users/src/Users/UsersModule.cs +++ b/src/modules/Users/src/Users/UsersModule.cs @@ -225,7 +225,9 @@ public void ConfigureEndpoints(IEndpointRouteBuilder endpoints) UserinfoEndpoint.Map(endpoints); // User API endpoints - var usersGroup = endpoints.MapGroup(UsersConstants.RoutePrefix); + var usersGroup = endpoints + .MapGroup(UsersConstants.RoutePrefix) + .WithTags(UsersConstants.ModuleName); GetAllEndpoint.Map(usersGroup); GetByIdEndpoint.Map(usersGroup); GetCurrentEndpoint.Map(usersGroup); diff --git a/src/modules/Users/tests/Users.Tests/Integration/UsersEndpointTests.cs b/src/modules/Users/tests/Users.Tests/Integration/UsersEndpointTests.cs index ac606bdb..edb2801e 100644 --- a/src/modules/Users/tests/Users.Tests/Integration/UsersEndpointTests.cs +++ b/src/modules/Users/tests/Users.Tests/Integration/UsersEndpointTests.cs @@ -2,9 +2,9 @@ using System.Net.Http.Json; using System.Security.Claims; using FluentAssertions; +using SimpleModule.Tests.Shared.Fakes; using SimpleModule.Tests.Shared.Fixtures; using SimpleModule.Users.Contracts; -using SimpleModule.Tests.Shared.Fakes; namespace Users.Tests.Integration; @@ -109,11 +109,7 @@ public async Task CreateUser_Authenticated_Returns201() [Fact] public async Task UpdateUser_Unauthenticated_ReturnsUnauthorized() { - var request = new UpdateUserRequest - { - Email = "updated@test.com", - DisplayName = "Updated", - }; + var request = new UpdateUserRequest { Email = "updated@test.com", DisplayName = "Updated" }; var response = await _unauthenticatedClient.PutAsJsonAsync("/api/users/some-id", request); diff --git a/src/modules/Users/tests/Users.Tests/Unit/UserServiceTests.cs b/src/modules/Users/tests/Users.Tests/Unit/UserServiceTests.cs index 806050f9..72fa5376 100644 --- a/src/modules/Users/tests/Users.Tests/Unit/UserServiceTests.cs +++ b/src/modules/Users/tests/Users.Tests/Unit/UserServiceTests.cs @@ -116,7 +116,11 @@ public async Task CreateUserAsync_WithDuplicateEmail_ThrowsValidationException() .CreateAsync(Arg.Any(), Arg.Any()) .Returns( IdentityResult.Failed( - new IdentityError { Code = "DuplicateEmail", Description = "Email already taken" } + new IdentityError + { + Code = "DuplicateEmail", + Description = "Email already taken", + } ) ); @@ -142,15 +146,9 @@ public async Task UpdateUserAsync_WithValidData_UpdatesUser() DisplayName = "Old Name", }; _userManager.FindByIdAsync("1").Returns(appUser); - _userManager - .UpdateAsync(Arg.Any()) - .Returns(IdentityResult.Success); + _userManager.UpdateAsync(Arg.Any()).Returns(IdentityResult.Success); - var request = new UpdateUserRequest - { - Email = "new@test.com", - DisplayName = "New Name", - }; + var request = new UpdateUserRequest { Email = "new@test.com", DisplayName = "New Name" }; var user = await _sut.UpdateUserAsync("1", request); @@ -164,11 +162,7 @@ public async Task UpdateUserAsync_WithNonExistentUser_ThrowsNotFoundException() { _userManager.FindByIdAsync("999").Returns((ApplicationUser?)null); - var request = new UpdateUserRequest - { - Email = "test@test.com", - DisplayName = "Test", - }; + var request = new UpdateUserRequest { Email = "test@test.com", DisplayName = "Test" }; var act = () => _sut.UpdateUserAsync("999", request); @@ -185,9 +179,7 @@ public async Task DeleteUserAsync_WithExistingUser_DeletesUser() DisplayName = "Test", }; _userManager.FindByIdAsync("1").Returns(appUser); - _userManager - .DeleteAsync(Arg.Any()) - .Returns(IdentityResult.Success); + _userManager.DeleteAsync(Arg.Any()).Returns(IdentityResult.Success); await _sut.DeleteUserAsync("1"); From 76a79d4d07abb7bceb2250aa2fe8d1721f129957 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 16 Mar 2026 11:29:01 +0100 Subject: [PATCH 25/62] refactor: extract data models from ModuleDiscovererGenerator into partial class Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ModuleDiscovererGenerator.Models.cs | 173 ++++++++++++++++++ .../ModuleDiscovererGenerator.cs | 167 +---------------- 2 files changed, 174 insertions(+), 166 deletions(-) create mode 100644 src/SimpleModule.Generator/ModuleDiscovererGenerator.Models.cs diff --git a/src/SimpleModule.Generator/ModuleDiscovererGenerator.Models.cs b/src/SimpleModule.Generator/ModuleDiscovererGenerator.Models.cs new file mode 100644 index 00000000..10d8667e --- /dev/null +++ b/src/SimpleModule.Generator/ModuleDiscovererGenerator.Models.cs @@ -0,0 +1,173 @@ +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace SimpleModule.Generator; + +public partial class ModuleDiscovererGenerator +{ + #region Equatable data model for incremental caching + + // These record types implement value equality so the incremental generator + // pipeline can detect when the extracted data hasn't changed and skip + // re-generating source files. + + private readonly record struct DiscoveryData( + ImmutableArray Modules, + ImmutableArray DtoTypes + ) + { + public static readonly DiscoveryData Empty = new( + ImmutableArray.Empty, + ImmutableArray.Empty + ); + + public bool Equals(DiscoveryData other) + { + return Modules.SequenceEqual(other.Modules) && DtoTypes.SequenceEqual(other.DtoTypes); + } + + public override int GetHashCode() + { + unchecked + { + var hash = 17; + foreach (var m in Modules) + hash = hash * 31 + m.GetHashCode(); + foreach (var d in DtoTypes) + hash = hash * 31 + d.GetHashCode(); + return hash; + } + } + } + + private readonly record struct ModuleInfoRecord( + string FullyQualifiedName, + string ModuleName, + bool HasConfigureServices, + bool HasConfigureEndpoints, + bool HasConfigureMenu, + bool HasRazorComponents, + string RoutePrefix, + string ViewPrefix, + ImmutableArray Endpoints, + ImmutableArray Views + ) + { + public bool Equals(ModuleInfoRecord other) + { + return FullyQualifiedName == other.FullyQualifiedName + && ModuleName == other.ModuleName + && HasConfigureServices == other.HasConfigureServices + && HasConfigureEndpoints == other.HasConfigureEndpoints + && HasConfigureMenu == other.HasConfigureMenu + && HasRazorComponents == other.HasRazorComponents + && RoutePrefix == other.RoutePrefix + && ViewPrefix == other.ViewPrefix + && Endpoints.SequenceEqual(other.Endpoints) + && Views.SequenceEqual(other.Views); + } + + public override int GetHashCode() + { + unchecked + { + var hash = 17; + hash = hash * 31 + FullyQualifiedName.GetHashCode(); + hash = hash * 31 + (ModuleName ?? "").GetHashCode(); + hash = hash * 31 + HasConfigureServices.GetHashCode(); + hash = hash * 31 + HasConfigureEndpoints.GetHashCode(); + hash = hash * 31 + HasConfigureMenu.GetHashCode(); + hash = hash * 31 + HasRazorComponents.GetHashCode(); + hash = hash * 31 + (RoutePrefix ?? "").GetHashCode(); + hash = hash * 31 + (ViewPrefix ?? "").GetHashCode(); + foreach (var e in Endpoints) + hash = hash * 31 + e.GetHashCode(); + foreach (var v in Views) + hash = hash * 31 + v.GetHashCode(); + return hash; + } + } + } + + private readonly record struct EndpointInfoRecord(string FullyQualifiedName); + + private readonly record struct ViewInfoRecord(string FullyQualifiedName, string Page); + + private readonly record struct DtoTypeInfoRecord( + string FullyQualifiedName, + string SafeName, + ImmutableArray Properties + ) + { + public bool Equals(DtoTypeInfoRecord other) + { + return FullyQualifiedName == other.FullyQualifiedName + && SafeName == other.SafeName + && Properties.SequenceEqual(other.Properties); + } + + public override int GetHashCode() + { + unchecked + { + var hash = 17; + hash = hash * 31 + FullyQualifiedName.GetHashCode(); + hash = hash * 31 + SafeName.GetHashCode(); + foreach (var p in Properties) + hash = hash * 31 + p.GetHashCode(); + return hash; + } + } + } + + private readonly record struct DtoPropertyInfoRecord( + string Name, + string TypeFqn, + bool HasSetter + ); + + #endregion + + #region Mutable working types (used during symbol traversal only) + + private sealed class ModuleInfo + { + public string FullyQualifiedName { get; set; } = ""; + public string ModuleName { get; set; } = ""; + public bool HasConfigureServices { get; set; } + public bool HasConfigureEndpoints { get; set; } + public bool HasConfigureMenu { get; set; } + public bool HasRazorComponents { get; set; } + public string RoutePrefix { get; set; } = ""; + public string ViewPrefix { get; set; } = ""; + public List Endpoints { get; set; } = new(); + public List Views { get; set; } = new(); + } + + private sealed class EndpointInfo + { + public string FullyQualifiedName { get; set; } = ""; + } + + private sealed class ViewInfo + { + public string FullyQualifiedName { get; set; } = ""; + public string Page { get; set; } = ""; + } + + private sealed class DtoTypeInfo + { + public string FullyQualifiedName { get; set; } = ""; + public string SafeName { get; set; } = ""; + public List Properties { get; set; } = new(); + } + + private sealed class DtoPropertyInfo + { + public string Name { get; set; } = ""; + public string TypeFqn { get; set; } = ""; + public bool HasSetter { get; set; } + } + + #endregion +} diff --git a/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs b/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs index c1512caa..20adfb73 100644 --- a/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs +++ b/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs @@ -9,7 +9,7 @@ namespace SimpleModule.Generator; [Generator] -public class ModuleDiscovererGenerator : IIncrementalGenerator +public partial class ModuleDiscovererGenerator : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext context) { @@ -911,169 +911,4 @@ private static string GetModuleFieldName(string fullyQualifiedName) return $"s_{name}"; } - #region Equatable data model for incremental caching - - // These record types implement value equality so the incremental generator - // pipeline can detect when the extracted data hasn't changed and skip - // re-generating source files. - - private readonly record struct DiscoveryData( - ImmutableArray Modules, - ImmutableArray DtoTypes - ) - { - public static readonly DiscoveryData Empty = new( - ImmutableArray.Empty, - ImmutableArray.Empty - ); - - public bool Equals(DiscoveryData other) - { - return Modules.SequenceEqual(other.Modules) && DtoTypes.SequenceEqual(other.DtoTypes); - } - - public override int GetHashCode() - { - unchecked - { - var hash = 17; - foreach (var m in Modules) - hash = hash * 31 + m.GetHashCode(); - foreach (var d in DtoTypes) - hash = hash * 31 + d.GetHashCode(); - return hash; - } - } - } - - private readonly record struct ModuleInfoRecord( - string FullyQualifiedName, - string ModuleName, - bool HasConfigureServices, - bool HasConfigureEndpoints, - bool HasConfigureMenu, - bool HasRazorComponents, - string RoutePrefix, - string ViewPrefix, - ImmutableArray Endpoints, - ImmutableArray Views - ) - { - public bool Equals(ModuleInfoRecord other) - { - return FullyQualifiedName == other.FullyQualifiedName - && ModuleName == other.ModuleName - && HasConfigureServices == other.HasConfigureServices - && HasConfigureEndpoints == other.HasConfigureEndpoints - && HasConfigureMenu == other.HasConfigureMenu - && HasRazorComponents == other.HasRazorComponents - && RoutePrefix == other.RoutePrefix - && ViewPrefix == other.ViewPrefix - && Endpoints.SequenceEqual(other.Endpoints) - && Views.SequenceEqual(other.Views); - } - - public override int GetHashCode() - { - unchecked - { - var hash = 17; - hash = hash * 31 + FullyQualifiedName.GetHashCode(); - hash = hash * 31 + (ModuleName ?? "").GetHashCode(); - hash = hash * 31 + HasConfigureServices.GetHashCode(); - hash = hash * 31 + HasConfigureEndpoints.GetHashCode(); - hash = hash * 31 + HasConfigureMenu.GetHashCode(); - hash = hash * 31 + HasRazorComponents.GetHashCode(); - hash = hash * 31 + (RoutePrefix ?? "").GetHashCode(); - hash = hash * 31 + (ViewPrefix ?? "").GetHashCode(); - foreach (var e in Endpoints) - hash = hash * 31 + e.GetHashCode(); - foreach (var v in Views) - hash = hash * 31 + v.GetHashCode(); - return hash; - } - } - } - - private readonly record struct EndpointInfoRecord(string FullyQualifiedName); - - private readonly record struct ViewInfoRecord(string FullyQualifiedName, string Page); - - private readonly record struct DtoTypeInfoRecord( - string FullyQualifiedName, - string SafeName, - ImmutableArray Properties - ) - { - public bool Equals(DtoTypeInfoRecord other) - { - return FullyQualifiedName == other.FullyQualifiedName - && SafeName == other.SafeName - && Properties.SequenceEqual(other.Properties); - } - - public override int GetHashCode() - { - unchecked - { - var hash = 17; - hash = hash * 31 + FullyQualifiedName.GetHashCode(); - hash = hash * 31 + SafeName.GetHashCode(); - foreach (var p in Properties) - hash = hash * 31 + p.GetHashCode(); - return hash; - } - } - } - - private readonly record struct DtoPropertyInfoRecord( - string Name, - string TypeFqn, - bool HasSetter - ); - - #endregion - - #region Mutable working types (used during symbol traversal only) - - private sealed class ModuleInfo - { - public string FullyQualifiedName { get; set; } = ""; - public string ModuleName { get; set; } = ""; - public bool HasConfigureServices { get; set; } - public bool HasConfigureEndpoints { get; set; } - public bool HasConfigureMenu { get; set; } - public bool HasRazorComponents { get; set; } - public string RoutePrefix { get; set; } = ""; - public string ViewPrefix { get; set; } = ""; - public List Endpoints { get; set; } = new(); - public List Views { get; set; } = new(); - } - - private sealed class EndpointInfo - { - public string FullyQualifiedName { get; set; } = ""; - } - - private sealed class ViewInfo - { - public string FullyQualifiedName { get; set; } = ""; - public string Page { get; set; } = ""; - } - - private sealed class DtoTypeInfo - { - public string FullyQualifiedName { get; set; } = ""; - public string SafeName { get; set; } = ""; - public List Properties { get; set; } = new(); - } - - private sealed class DtoPropertyInfo - { - public string Name { get; set; } = ""; - public string TypeFqn { get; set; } = ""; - public bool HasSetter { get; set; } - } - - #endregion } From bcc32c04b498b668cfcb305863ed85b8207290ff Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 16 Mar 2026 11:33:32 +0100 Subject: [PATCH 26/62] refactor: extract code emitters from ModuleDiscovererGenerator into partial class Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ModuleDiscovererGenerator.Emitters.cs | 485 ++++++++++++++++++ .../ModuleDiscovererGenerator.cs | 479 +---------------- 2 files changed, 486 insertions(+), 478 deletions(-) create mode 100644 src/SimpleModule.Generator/ModuleDiscovererGenerator.Emitters.cs diff --git a/src/SimpleModule.Generator/ModuleDiscovererGenerator.Emitters.cs b/src/SimpleModule.Generator/ModuleDiscovererGenerator.Emitters.cs new file mode 100644 index 00000000..2e5c961d --- /dev/null +++ b/src/SimpleModule.Generator/ModuleDiscovererGenerator.Emitters.cs @@ -0,0 +1,485 @@ +using System; +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; + +namespace SimpleModule.Generator; + +public partial class ModuleDiscovererGenerator +{ + private static void GenerateModuleExtensions( + SourceProductionContext context, + ImmutableArray modules, + bool hasDtoTypes + ) + { + var sb = new StringBuilder(); + sb.AppendLine("// "); + sb.AppendLine("#pragma warning disable IL2026"); + sb.AppendLine("#pragma warning disable IL3050"); + sb.AppendLine("using Microsoft.AspNetCore.Http.Json;"); + sb.AppendLine("using Microsoft.Extensions.Configuration;"); + sb.AppendLine("using Microsoft.Extensions.DependencyInjection;"); + sb.AppendLine(); + sb.AppendLine("namespace SimpleModule.Core;"); + sb.AppendLine(); + sb.AppendLine("public static class ModuleExtensions"); + sb.AppendLine("{"); + + // Generate shared module instances + foreach (var module in modules) + { + var fieldName = GetModuleFieldName(module.FullyQualifiedName); + sb.AppendLine( + $" internal static readonly {module.FullyQualifiedName} {fieldName} = new();" + ); + } + + sb.AppendLine(); + sb.AppendLine( + " public static IServiceCollection AddModules(this IServiceCollection services, IConfiguration configuration)" + ); + sb.AppendLine(" {"); + + foreach (var module in modules.Where(m => m.HasConfigureServices)) + { + var fieldName = GetModuleFieldName(module.FullyQualifiedName); + sb.AppendLine($" {fieldName}.ConfigureServices(services, configuration);"); + } + + if (hasDtoTypes) + { + sb.AppendLine(); + sb.AppendLine(" services.ConfigureHttpJsonOptions(options =>"); + sb.AppendLine(" {"); + sb.AppendLine( + " options.SerializerOptions.TypeInfoResolver = System.Text.Json.Serialization.Metadata.JsonTypeInfoResolver.Combine(" + ); + sb.AppendLine(" ModulesJsonResolver.Instance,"); + sb.AppendLine( + " new System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver());" + ); + sb.AppendLine(" });"); + } + + sb.AppendLine(); + sb.AppendLine(" return services;"); + sb.AppendLine(" }"); + sb.AppendLine("}"); + + context.AddSource("ModuleExtensions.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); + } + + private static void GenerateEndpointExtensions( + SourceProductionContext context, + ImmutableArray modules + ) + { + var sb = new StringBuilder(); + sb.AppendLine("// "); + sb.AppendLine("using Microsoft.AspNetCore.Builder;"); + sb.AppendLine("using Microsoft.AspNetCore.Routing;"); + sb.AppendLine("using Microsoft.AspNetCore.Http;"); + sb.AppendLine(); + sb.AppendLine("namespace SimpleModule.Core;"); + sb.AppendLine(); + sb.AppendLine("public static class EndpointExtensions"); + sb.AppendLine("{"); + sb.AppendLine( + " public static WebApplication MapModuleEndpoints(this WebApplication app)" + ); + sb.AppendLine(" {"); + + // Auto-registered endpoints (IEndpoint implementors) + // Skip modules that define ConfigureEndpoints — they manage their own registration. + foreach (var module in modules) + { + if (module.Endpoints.Length == 0 || module.HasConfigureEndpoints) + continue; + + sb.AppendLine(); + sb.AppendLine($" // Auto-registered endpoints for {module.FullyQualifiedName}"); + sb.AppendLine(" {"); + + if (!string.IsNullOrEmpty(module.RoutePrefix)) + { + sb.AppendLine( + $" var group = app.MapGroup(\"{module.RoutePrefix}\").WithTags(\"{module.ModuleName}\");" + ); + foreach (var endpoint in module.Endpoints) + { + sb.AppendLine($" new {endpoint.FullyQualifiedName}().Map(group);"); + } + } + else + { + foreach (var endpoint in module.Endpoints) + { + sb.AppendLine($" new {endpoint.FullyQualifiedName}().Map(app);"); + } + } + + sb.AppendLine(" }"); + } + + // Auto-registered view endpoints (IViewEndpoint implementors) + foreach (var module in modules) + { + if (module.Views.Length == 0) + continue; + + sb.AppendLine(); + sb.AppendLine( + $" // Auto-registered view endpoints for {module.FullyQualifiedName}" + ); + sb.AppendLine(" {"); + + if (!string.IsNullOrEmpty(module.ViewPrefix)) + { + sb.AppendLine( + $" var viewGroup = app.MapGroup(\"{module.ViewPrefix}\").WithTags(\"{module.ModuleName}\").ExcludeFromDescription();" + ); + foreach (var view in module.Views) + { + sb.AppendLine($" new {view.FullyQualifiedName}().Map(viewGroup);"); + } + } + else + { + foreach (var view in module.Views) + { + sb.AppendLine($" new {view.FullyQualifiedName}().Map(app);"); + } + } + + sb.AppendLine(" }"); + } + + // Manual ConfigureEndpoints (escape hatch) + foreach (var module in modules.Where(m => m.HasConfigureEndpoints)) + { + var fieldName = GetModuleFieldName(module.FullyQualifiedName); + sb.AppendLine(); + sb.AppendLine($" ModuleExtensions.{fieldName}.ConfigureEndpoints(app);"); + } + + sb.AppendLine(); + sb.AppendLine(" return app;"); + sb.AppendLine(" }"); + sb.AppendLine("}"); + + context.AddSource("EndpointExtensions.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); + } + + private static void GenerateMenuExtensions( + SourceProductionContext context, + ImmutableArray modules + ) + { + var sb = new StringBuilder(); + sb.AppendLine("// "); + sb.AppendLine("using Microsoft.Extensions.DependencyInjection;"); + sb.AppendLine("using SimpleModule.Core.Menu;"); + sb.AppendLine(); + sb.AppendLine("namespace SimpleModule.Core;"); + sb.AppendLine(); + sb.AppendLine("public static class MenuExtensions"); + sb.AppendLine("{"); + sb.AppendLine( + " public static IServiceCollection CollectModuleMenuItems(this IServiceCollection services)" + ); + sb.AppendLine(" {"); + sb.AppendLine(" var menus = new MenuBuilder();"); + + foreach (var module in modules.Where(m => m.HasConfigureMenu)) + { + var fieldName = GetModuleFieldName(module.FullyQualifiedName); + sb.AppendLine($" ModuleExtensions.{fieldName}.ConfigureMenu(menus);"); + } + + sb.AppendLine( + " services.AddSingleton(new MenuRegistry(menus.ToList()));" + ); + sb.AppendLine(" return services;"); + sb.AppendLine(" }"); + sb.AppendLine("}"); + + context.AddSource("MenuExtensions.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); + } + + private static void GenerateJsonResolver( + SourceProductionContext context, + ImmutableArray dtoTypes + ) + { + var sb = new StringBuilder(); + sb.AppendLine("// "); + sb.AppendLine("#nullable enable"); + sb.AppendLine("#pragma warning disable IL2026"); + sb.AppendLine("#pragma warning disable IL3050"); + sb.AppendLine("using System;"); + sb.AppendLine("using System.Text.Json;"); + sb.AppendLine("using System.Text.Json.Serialization.Metadata;"); + sb.AppendLine(); + sb.AppendLine("namespace SimpleModule.Core;"); + sb.AppendLine(); + sb.AppendLine("public sealed class ModulesJsonResolver : IJsonTypeInfoResolver"); + sb.AppendLine("{"); + sb.AppendLine(" public static readonly ModulesJsonResolver Instance = new();"); + sb.AppendLine(); + sb.AppendLine( + " public JsonTypeInfo? GetTypeInfo(Type type, JsonSerializerOptions options)" + ); + sb.AppendLine(" {"); + + foreach (var dto in dtoTypes) + { + sb.AppendLine($" if (type == typeof({dto.FullyQualifiedName}))"); + sb.AppendLine($" return Create_{dto.SafeName}(options);"); + } + + sb.AppendLine(" return null;"); + sb.AppendLine(" }"); + + foreach (var dto in dtoTypes) + { + sb.AppendLine(); + sb.AppendLine( + $" private static JsonTypeInfo Create_{dto.SafeName}(JsonSerializerOptions options)" + ); + sb.AppendLine(" {"); + sb.AppendLine( + $" var info = JsonTypeInfo.CreateJsonTypeInfo<{dto.FullyQualifiedName}>(options);" + ); + sb.AppendLine( + $" info.CreateObject = static () => new {dto.FullyQualifiedName}();" + ); + + foreach (var prop in dto.Properties) + { + var jsonName = char.ToLowerInvariant(prop.Name[0]) + prop.Name.Substring(1); + sb.AppendLine( + $" var prop_{prop.Name} = info.CreateJsonPropertyInfo(typeof({prop.TypeFqn}), \"{jsonName}\");" + ); + sb.AppendLine( + $" prop_{prop.Name}.Get = static obj => (({dto.FullyQualifiedName})obj).{prop.Name};" + ); + + if (prop.HasSetter) + { + sb.AppendLine( + $" prop_{prop.Name}.Set = static (obj, val) => (({dto.FullyQualifiedName})obj).{prop.Name} = ({prop.TypeFqn})val!;" + ); + } + + sb.AppendLine($" info.Properties.Add(prop_{prop.Name});"); + } + + sb.AppendLine(" return info;"); + sb.AppendLine(" }"); + } + + sb.AppendLine("}"); + + context.AddSource( + "ModulesJsonResolver.g.cs", + SourceText.From(sb.ToString(), Encoding.UTF8) + ); + } + + private static void GenerateTypeScriptDefinitions( + SourceProductionContext context, + ImmutableArray dtoTypes + ) + { + var sb = new StringBuilder(); + sb.AppendLine("// "); + sb.AppendLine("#if SIMPLEMODULE_TS"); + sb.AppendLine("/*"); + sb.AppendLine("// TypeScript interfaces generated from [Dto] types"); + sb.AppendLine(); + + foreach (var dto in dtoTypes) + { + var typeName = dto.FullyQualifiedName; + var shortName = typeName.Contains(".") + ? typeName.Substring(typeName.LastIndexOf('.') + 1) + : typeName; + shortName = shortName.Replace("global::", ""); + + sb.AppendLine($"export interface {shortName} {{"); + foreach (var prop in dto.Properties) + { + var tsType = MapCSharpTypeToTypeScript(prop.TypeFqn); + var camelName = char.ToLowerInvariant(prop.Name[0]) + prop.Name.Substring(1); + sb.AppendLine($" {camelName}: {tsType};"); + } + sb.AppendLine("}"); + sb.AppendLine(); + } + + sb.AppendLine("*/"); + sb.AppendLine("#endif"); + + context.AddSource("DtoTypeScript.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); + } + + private static void GenerateViewPages( + SourceProductionContext context, + ImmutableArray modules + ) + { + foreach (var module in modules) + { + if (module.Views.Length == 0) + continue; + + // Extract module name from FQN (e.g., "global::SimpleModule.Products.ProductsModule" -> "Products") + var fqn = module.FullyQualifiedName.Replace("global::", ""); + var moduleName = fqn.Contains(".") ? fqn.Substring(fqn.LastIndexOf('.') + 1) : fqn; + if (moduleName.EndsWith("Module", StringComparison.Ordinal)) + moduleName = moduleName.Substring(0, moduleName.Length - "Module".Length); + + var sb = new StringBuilder(); + sb.AppendLine("// "); + sb.AppendLine("#if SIMPLEMODULE_TS"); + sb.AppendLine("/*"); + + // Generate import statements — component name is the part after "/" + foreach (var view in module.Views) + { + var componentName = view.Page.Contains("/") + ? view.Page.Substring(view.Page.LastIndexOf('/') + 1) + : view.Page; + sb.AppendLine($"import {componentName} from '../Views/{componentName}';"); + } + + sb.AppendLine(); + sb.AppendLine("export const pages: Record = {"); + + for (var i = 0; i < module.Views.Length; i++) + { + var view = module.Views[i]; + var componentName = view.Page.Contains("/") + ? view.Page.Substring(view.Page.LastIndexOf('/') + 1) + : view.Page; + var comma = i < module.Views.Length - 1 ? "," : ""; + sb.AppendLine($" '{view.Page}': {componentName}{comma}"); + } + + sb.AppendLine("};"); + sb.AppendLine("*/"); + sb.AppendLine("#endif"); + + context.AddSource( + $"ViewPages_{moduleName}.g.cs", + SourceText.From(sb.ToString(), Encoding.UTF8) + ); + } + } + + private static void GenerateRazorComponentExtensions( + SourceProductionContext context, + ImmutableArray modules + ) + { + var razorModules = modules.Where(m => m.HasRazorComponents).ToList(); + + var sb = new StringBuilder(); + sb.AppendLine("// "); + sb.AppendLine("using Microsoft.AspNetCore.Builder;"); + sb.AppendLine(); + sb.AppendLine("namespace SimpleModule.Core;"); + sb.AppendLine(); + sb.AppendLine("public static class RazorComponentExtensions"); + sb.AppendLine("{"); + sb.AppendLine( + " public static RazorComponentsEndpointConventionBuilder AddModuleAssemblies(" + ); + sb.AppendLine(" this RazorComponentsEndpointConventionBuilder builder)"); + sb.AppendLine(" {"); + + if (razorModules.Count > 0) + { + sb.AppendLine(" builder.AddAdditionalAssemblies("); + for (var i = 0; i < razorModules.Count; i++) + { + var suffix = i < razorModules.Count - 1 ? "," : ");"; + sb.AppendLine( + $" typeof({razorModules[i].FullyQualifiedName}).Assembly{suffix}" + ); + } + } + + sb.AppendLine(" return builder;"); + sb.AppendLine(" }"); + sb.AppendLine("}"); + + context.AddSource( + "RazorComponentExtensions.g.cs", + SourceText.From(sb.ToString(), Encoding.UTF8) + ); + } + + private static string MapCSharpTypeToTypeScript(string typeFqn) + { + var type = typeFqn.Replace("global::", ""); + + // Nullable -> T | null + if ( + type.StartsWith("System.Nullable<", StringComparison.Ordinal) + && type.EndsWith(">", StringComparison.Ordinal) + ) + { + var inner = type.Substring( + "System.Nullable<".Length, + type.Length - "System.Nullable<".Length - 1 + ); + return MapCSharpTypeToTypeScript(inner) + " | null"; + } + + // Collection types + if ( + type.StartsWith("System.Collections.Generic.List<", StringComparison.Ordinal) + || type.StartsWith("System.Collections.Generic.IList<", StringComparison.Ordinal) + || type.StartsWith("System.Collections.Generic.IEnumerable<", StringComparison.Ordinal) + || type.StartsWith( + "System.Collections.Generic.IReadOnlyList<", + StringComparison.Ordinal + ) + || type.StartsWith("System.Collections.Generic.ICollection<", StringComparison.Ordinal) + ) + { + var start = type.IndexOf('<') + 1; + var inner = type.Substring(start, type.Length - start - 1); + return MapCSharpTypeToTypeScript(inner) + "[]"; + } + + return type switch + { + "string" or "System.String" => "string", + "int" or "System.Int32" => "number", + "long" or "System.Int64" => "number", + "short" or "System.Int16" => "number", + "byte" or "System.Byte" => "number", + "float" or "System.Single" => "number", + "double" or "System.Double" => "number", + "decimal" or "System.Decimal" => "number", + "bool" or "System.Boolean" => "boolean", + "System.DateTime" + or "System.DateTimeOffset" + or "System.DateOnly" + or "System.TimeOnly" => "string", + "System.Guid" => "string", + _ => "any", + }; + } + + private static string GetModuleFieldName(string fullyQualifiedName) + { + var name = fullyQualifiedName.Replace("global::", "").Replace(".", "_"); + return $"s_{name}"; + } +} diff --git a/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs b/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs index 20adfb73..5a71306c 100644 --- a/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs +++ b/src/SimpleModule.Generator/ModuleDiscovererGenerator.cs @@ -2,9 +2,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Text; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Text; namespace SimpleModule.Generator; @@ -80,7 +78,7 @@ is not IAssemblySymbol assemblySymbol return DiscoveryData.Empty; // Discover IEndpoint implementors per module assembly. - // Classification is by interface type: IViewEndpoint → view, IEndpoint → API. + // Classification is by interface type: IViewEndpoint -> view, IEndpoint -> API. if (endpointInterfaceSymbol is not null) { foreach (var module in modules) @@ -404,431 +402,6 @@ prop.SetMethod is not null } } - private static void GenerateModuleExtensions( - SourceProductionContext context, - ImmutableArray modules, - bool hasDtoTypes - ) - { - var sb = new StringBuilder(); - sb.AppendLine("// "); - sb.AppendLine("#pragma warning disable IL2026"); - sb.AppendLine("#pragma warning disable IL3050"); - sb.AppendLine("using Microsoft.AspNetCore.Http.Json;"); - sb.AppendLine("using Microsoft.Extensions.Configuration;"); - sb.AppendLine("using Microsoft.Extensions.DependencyInjection;"); - sb.AppendLine(); - sb.AppendLine("namespace SimpleModule.Core;"); - sb.AppendLine(); - sb.AppendLine("public static class ModuleExtensions"); - sb.AppendLine("{"); - - // Generate shared module instances - foreach (var module in modules) - { - var fieldName = GetModuleFieldName(module.FullyQualifiedName); - sb.AppendLine( - $" internal static readonly {module.FullyQualifiedName} {fieldName} = new();" - ); - } - - sb.AppendLine(); - sb.AppendLine( - " public static IServiceCollection AddModules(this IServiceCollection services, IConfiguration configuration)" - ); - sb.AppendLine(" {"); - - foreach (var module in modules.Where(m => m.HasConfigureServices)) - { - var fieldName = GetModuleFieldName(module.FullyQualifiedName); - sb.AppendLine($" {fieldName}.ConfigureServices(services, configuration);"); - } - - if (hasDtoTypes) - { - sb.AppendLine(); - sb.AppendLine(" services.ConfigureHttpJsonOptions(options =>"); - sb.AppendLine(" {"); - sb.AppendLine( - " options.SerializerOptions.TypeInfoResolver = System.Text.Json.Serialization.Metadata.JsonTypeInfoResolver.Combine(" - ); - sb.AppendLine(" ModulesJsonResolver.Instance,"); - sb.AppendLine( - " new System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver());" - ); - sb.AppendLine(" });"); - } - - sb.AppendLine(); - sb.AppendLine(" return services;"); - sb.AppendLine(" }"); - sb.AppendLine("}"); - - context.AddSource("ModuleExtensions.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); - } - - private static void GenerateEndpointExtensions( - SourceProductionContext context, - ImmutableArray modules - ) - { - var sb = new StringBuilder(); - sb.AppendLine("// "); - sb.AppendLine("using Microsoft.AspNetCore.Builder;"); - sb.AppendLine("using Microsoft.AspNetCore.Routing;"); - sb.AppendLine("using Microsoft.AspNetCore.Http;"); - sb.AppendLine(); - sb.AppendLine("namespace SimpleModule.Core;"); - sb.AppendLine(); - sb.AppendLine("public static class EndpointExtensions"); - sb.AppendLine("{"); - sb.AppendLine( - " public static WebApplication MapModuleEndpoints(this WebApplication app)" - ); - sb.AppendLine(" {"); - - // Auto-registered endpoints (IEndpoint implementors) - // Skip modules that define ConfigureEndpoints — they manage their own registration. - foreach (var module in modules) - { - if (module.Endpoints.Length == 0 || module.HasConfigureEndpoints) - continue; - - sb.AppendLine(); - sb.AppendLine($" // Auto-registered endpoints for {module.FullyQualifiedName}"); - sb.AppendLine(" {"); - - if (!string.IsNullOrEmpty(module.RoutePrefix)) - { - sb.AppendLine( - $" var group = app.MapGroup(\"{module.RoutePrefix}\").WithTags(\"{module.ModuleName}\");" - ); - foreach (var endpoint in module.Endpoints) - { - sb.AppendLine($" new {endpoint.FullyQualifiedName}().Map(group);"); - } - } - else - { - foreach (var endpoint in module.Endpoints) - { - sb.AppendLine($" new {endpoint.FullyQualifiedName}().Map(app);"); - } - } - - sb.AppendLine(" }"); - } - - // Auto-registered view endpoints (IViewEndpoint implementors) - foreach (var module in modules) - { - if (module.Views.Length == 0) - continue; - - sb.AppendLine(); - sb.AppendLine( - $" // Auto-registered view endpoints for {module.FullyQualifiedName}" - ); - sb.AppendLine(" {"); - - if (!string.IsNullOrEmpty(module.ViewPrefix)) - { - sb.AppendLine( - $" var viewGroup = app.MapGroup(\"{module.ViewPrefix}\").WithTags(\"{module.ModuleName}\").ExcludeFromDescription();" - ); - foreach (var view in module.Views) - { - sb.AppendLine($" new {view.FullyQualifiedName}().Map(viewGroup);"); - } - } - else - { - foreach (var view in module.Views) - { - sb.AppendLine($" new {view.FullyQualifiedName}().Map(app);"); - } - } - - sb.AppendLine(" }"); - } - - // Manual ConfigureEndpoints (escape hatch) - foreach (var module in modules.Where(m => m.HasConfigureEndpoints)) - { - var fieldName = GetModuleFieldName(module.FullyQualifiedName); - sb.AppendLine(); - sb.AppendLine($" ModuleExtensions.{fieldName}.ConfigureEndpoints(app);"); - } - - sb.AppendLine(); - sb.AppendLine(" return app;"); - sb.AppendLine(" }"); - sb.AppendLine("}"); - - context.AddSource("EndpointExtensions.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); - } - - private static void GenerateMenuExtensions( - SourceProductionContext context, - ImmutableArray modules - ) - { - var sb = new StringBuilder(); - sb.AppendLine("// "); - sb.AppendLine("using Microsoft.Extensions.DependencyInjection;"); - sb.AppendLine("using SimpleModule.Core.Menu;"); - sb.AppendLine(); - sb.AppendLine("namespace SimpleModule.Core;"); - sb.AppendLine(); - sb.AppendLine("public static class MenuExtensions"); - sb.AppendLine("{"); - sb.AppendLine( - " public static IServiceCollection CollectModuleMenuItems(this IServiceCollection services)" - ); - sb.AppendLine(" {"); - sb.AppendLine(" var menus = new MenuBuilder();"); - - foreach (var module in modules.Where(m => m.HasConfigureMenu)) - { - var fieldName = GetModuleFieldName(module.FullyQualifiedName); - sb.AppendLine($" ModuleExtensions.{fieldName}.ConfigureMenu(menus);"); - } - - sb.AppendLine( - " services.AddSingleton(new MenuRegistry(menus.ToList()));" - ); - sb.AppendLine(" return services;"); - sb.AppendLine(" }"); - sb.AppendLine("}"); - - context.AddSource("MenuExtensions.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); - } - - private static void GenerateJsonResolver( - SourceProductionContext context, - ImmutableArray dtoTypes - ) - { - var sb = new StringBuilder(); - sb.AppendLine("// "); - sb.AppendLine("#nullable enable"); - sb.AppendLine("#pragma warning disable IL2026"); - sb.AppendLine("#pragma warning disable IL3050"); - sb.AppendLine("using System;"); - sb.AppendLine("using System.Text.Json;"); - sb.AppendLine("using System.Text.Json.Serialization.Metadata;"); - sb.AppendLine(); - sb.AppendLine("namespace SimpleModule.Core;"); - sb.AppendLine(); - sb.AppendLine("public sealed class ModulesJsonResolver : IJsonTypeInfoResolver"); - sb.AppendLine("{"); - sb.AppendLine(" public static readonly ModulesJsonResolver Instance = new();"); - sb.AppendLine(); - sb.AppendLine( - " public JsonTypeInfo? GetTypeInfo(Type type, JsonSerializerOptions options)" - ); - sb.AppendLine(" {"); - - foreach (var dto in dtoTypes) - { - sb.AppendLine($" if (type == typeof({dto.FullyQualifiedName}))"); - sb.AppendLine($" return Create_{dto.SafeName}(options);"); - } - - sb.AppendLine(" return null;"); - sb.AppendLine(" }"); - - foreach (var dto in dtoTypes) - { - sb.AppendLine(); - sb.AppendLine( - $" private static JsonTypeInfo Create_{dto.SafeName}(JsonSerializerOptions options)" - ); - sb.AppendLine(" {"); - sb.AppendLine( - $" var info = JsonTypeInfo.CreateJsonTypeInfo<{dto.FullyQualifiedName}>(options);" - ); - sb.AppendLine( - $" info.CreateObject = static () => new {dto.FullyQualifiedName}();" - ); - - foreach (var prop in dto.Properties) - { - var jsonName = char.ToLowerInvariant(prop.Name[0]) + prop.Name.Substring(1); - sb.AppendLine( - $" var prop_{prop.Name} = info.CreateJsonPropertyInfo(typeof({prop.TypeFqn}), \"{jsonName}\");" - ); - sb.AppendLine( - $" prop_{prop.Name}.Get = static obj => (({dto.FullyQualifiedName})obj).{prop.Name};" - ); - - if (prop.HasSetter) - { - sb.AppendLine( - $" prop_{prop.Name}.Set = static (obj, val) => (({dto.FullyQualifiedName})obj).{prop.Name} = ({prop.TypeFqn})val!;" - ); - } - - sb.AppendLine($" info.Properties.Add(prop_{prop.Name});"); - } - - sb.AppendLine(" return info;"); - sb.AppendLine(" }"); - } - - sb.AppendLine("}"); - - context.AddSource( - "ModulesJsonResolver.g.cs", - SourceText.From(sb.ToString(), Encoding.UTF8) - ); - } - - private static void GenerateTypeScriptDefinitions( - SourceProductionContext context, - ImmutableArray dtoTypes - ) - { - var sb = new StringBuilder(); - sb.AppendLine("// "); - sb.AppendLine("#if SIMPLEMODULE_TS"); - sb.AppendLine("/*"); - sb.AppendLine("// TypeScript interfaces generated from [Dto] types"); - sb.AppendLine(); - - foreach (var dto in dtoTypes) - { - var typeName = dto.FullyQualifiedName; - var shortName = typeName.Contains(".") - ? typeName.Substring(typeName.LastIndexOf('.') + 1) - : typeName; - shortName = shortName.Replace("global::", ""); - - sb.AppendLine($"export interface {shortName} {{"); - foreach (var prop in dto.Properties) - { - var tsType = MapCSharpTypeToTypeScript(prop.TypeFqn); - var camelName = char.ToLowerInvariant(prop.Name[0]) + prop.Name.Substring(1); - sb.AppendLine($" {camelName}: {tsType};"); - } - sb.AppendLine("}"); - sb.AppendLine(); - } - - sb.AppendLine("*/"); - sb.AppendLine("#endif"); - - context.AddSource("DtoTypeScript.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); - } - - private static void GenerateViewPages( - SourceProductionContext context, - ImmutableArray modules - ) - { - foreach (var module in modules) - { - if (module.Views.Length == 0) - continue; - - // Extract module name from FQN (e.g., "global::SimpleModule.Products.ProductsModule" → "Products") - var fqn = module.FullyQualifiedName.Replace("global::", ""); - var moduleName = fqn.Contains(".") ? fqn.Substring(fqn.LastIndexOf('.') + 1) : fqn; - if (moduleName.EndsWith("Module", StringComparison.Ordinal)) - moduleName = moduleName.Substring(0, moduleName.Length - "Module".Length); - - var sb = new StringBuilder(); - sb.AppendLine("// "); - sb.AppendLine("#if SIMPLEMODULE_TS"); - sb.AppendLine("/*"); - - // Generate import statements — component name is the part after "/" - foreach (var view in module.Views) - { - var componentName = view.Page.Contains("/") - ? view.Page.Substring(view.Page.LastIndexOf('/') + 1) - : view.Page; - sb.AppendLine($"import {componentName} from '../Views/{componentName}';"); - } - - sb.AppendLine(); - sb.AppendLine("export const pages: Record = {"); - - for (var i = 0; i < module.Views.Length; i++) - { - var view = module.Views[i]; - var componentName = view.Page.Contains("/") - ? view.Page.Substring(view.Page.LastIndexOf('/') + 1) - : view.Page; - var comma = i < module.Views.Length - 1 ? "," : ""; - sb.AppendLine($" '{view.Page}': {componentName}{comma}"); - } - - sb.AppendLine("};"); - sb.AppendLine("*/"); - sb.AppendLine("#endif"); - - context.AddSource( - $"ViewPages_{moduleName}.g.cs", - SourceText.From(sb.ToString(), Encoding.UTF8) - ); - } - } - - private static string MapCSharpTypeToTypeScript(string typeFqn) - { - var type = typeFqn.Replace("global::", ""); - - // Nullable → T | null - if ( - type.StartsWith("System.Nullable<", StringComparison.Ordinal) - && type.EndsWith(">", StringComparison.Ordinal) - ) - { - var inner = type.Substring( - "System.Nullable<".Length, - type.Length - "System.Nullable<".Length - 1 - ); - return MapCSharpTypeToTypeScript(inner) + " | null"; - } - - // Collection types - if ( - type.StartsWith("System.Collections.Generic.List<", StringComparison.Ordinal) - || type.StartsWith("System.Collections.Generic.IList<", StringComparison.Ordinal) - || type.StartsWith("System.Collections.Generic.IEnumerable<", StringComparison.Ordinal) - || type.StartsWith( - "System.Collections.Generic.IReadOnlyList<", - StringComparison.Ordinal - ) - || type.StartsWith("System.Collections.Generic.ICollection<", StringComparison.Ordinal) - ) - { - var start = type.IndexOf('<') + 1; - var inner = type.Substring(start, type.Length - start - 1); - return MapCSharpTypeToTypeScript(inner) + "[]"; - } - - return type switch - { - "string" or "System.String" => "string", - "int" or "System.Int32" => "number", - "long" or "System.Int64" => "number", - "short" or "System.Int16" => "number", - "byte" or "System.Byte" => "number", - "float" or "System.Single" => "number", - "double" or "System.Double" => "number", - "decimal" or "System.Decimal" => "number", - "bool" or "System.Boolean" => "boolean", - "System.DateTime" - or "System.DateTimeOffset" - or "System.DateOnly" - or "System.TimeOnly" => "string", - "System.Guid" => "string", - _ => "any", - }; - } - private static bool HasComponentBaseDescendant( INamespaceSymbol namespaceSymbol, INamedTypeSymbol componentBaseSymbol @@ -861,54 +434,4 @@ private static bool InheritsFrom(INamedTypeSymbol typeSymbol, INamedTypeSymbol b } return false; } - - private static void GenerateRazorComponentExtensions( - SourceProductionContext context, - ImmutableArray modules - ) - { - var razorModules = modules.Where(m => m.HasRazorComponents).ToList(); - - var sb = new StringBuilder(); - sb.AppendLine("// "); - sb.AppendLine("using Microsoft.AspNetCore.Builder;"); - sb.AppendLine(); - sb.AppendLine("namespace SimpleModule.Core;"); - sb.AppendLine(); - sb.AppendLine("public static class RazorComponentExtensions"); - sb.AppendLine("{"); - sb.AppendLine( - " public static RazorComponentsEndpointConventionBuilder AddModuleAssemblies(" - ); - sb.AppendLine(" this RazorComponentsEndpointConventionBuilder builder)"); - sb.AppendLine(" {"); - - if (razorModules.Count > 0) - { - sb.AppendLine(" builder.AddAdditionalAssemblies("); - for (var i = 0; i < razorModules.Count; i++) - { - var suffix = i < razorModules.Count - 1 ? "," : ");"; - sb.AppendLine( - $" typeof({razorModules[i].FullyQualifiedName}).Assembly{suffix}" - ); - } - } - - sb.AppendLine(" return builder;"); - sb.AppendLine(" }"); - sb.AppendLine("}"); - - context.AddSource( - "RazorComponentExtensions.g.cs", - SourceText.From(sb.ToString(), Encoding.UTF8) - ); - } - - private static string GetModuleFieldName(string fullyQualifiedName) - { - var name = fullyQualifiedName.Replace("global::", "").Replace(".", "_"); - return $"s_{name}"; - } - } From 1ab8b7e0d09e372bde88fdc76a4f81113b9b051b Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 16 Mar 2026 12:00:32 +0100 Subject: [PATCH 27/62] docs: add design for @simplemodule/ui shared component library Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/plans/2026-03-16-ui-library-design.md | 164 +++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 docs/plans/2026-03-16-ui-library-design.md diff --git a/docs/plans/2026-03-16-ui-library-design.md b/docs/plans/2026-03-16-ui-library-design.md new file mode 100644 index 00000000..a512e883 --- /dev/null +++ b/docs/plans/2026-03-16-ui-library-design.md @@ -0,0 +1,164 @@ +# Design: `@simplemodule/ui` — Shared Component Library + +**Date:** 2026-03-16 +**Status:** Approved + +## Overview + +A shadcn-style shared React component library for SimpleModule. Components are source files owned by the project (not a compiled npm package), built on Radix UI headless primitives and styled with cva + Tailwind referencing theme CSS variables. + +## Architecture + +- **Package:** `src/SimpleModule.UI/` as npm workspace `@simplemodule/ui` +- **Stack:** Radix UI (headless), class-variance-authority (cva), tailwind-merge + clsx via `cn()` +- **Design tokens:** Stay in `@simplemodule/theme-default` as CSS variables. Components reference them via Tailwind classes (`bg-primary`, `text-danger`, etc.) +- **No pre-build step:** Modules import source TSX directly; Vite handles transpilation + +### File Structure + +``` +src/SimpleModule.UI/ +├── package.json +├── components/ # active components (added via CLI) +│ └── index.ts # barrel re-export +├── lib/ +│ └── utils.ts # cn() helper +└── registry/ + ├── registry.json # component metadata + └── templates/ # all available component templates + ├── button.tsx + ├── input.tsx + ├── dialog.tsx + └── ... +``` + +### Module Consumption + +```tsx +import { Button, Card, Input, Badge } from '@simplemodule/ui'; +``` + +## Component List (Starter Set — ~18 components) + +| Component | Radix Primitive | Key Variants | +|-----------|----------------|--------------| +| Button | Slot (asChild) | variant: primary, secondary, ghost, danger, outline / size: sm, default, lg | +| Input | — | variant: default, error | +| Textarea | — | — | +| Label | @radix-ui/react-label | — | +| Select | @radix-ui/react-select | — | +| Checkbox | @radix-ui/react-checkbox | — | +| Radio Group | @radix-ui/react-radio-group | — | +| Switch | @radix-ui/react-switch | — | +| Dialog | @radix-ui/react-dialog | — | +| Dropdown Menu | @radix-ui/react-dropdown-menu | — | +| Popover | @radix-ui/react-popover | — | +| Tabs | @radix-ui/react-tabs | — | +| Table | — | — | +| Card | — | — | +| Badge | — | variant: success, danger, warning, info, default | +| Alert | — | variant: success, danger, warning, info | +| Separator | @radix-ui/react-separator | — | +| Spinner | — | size: sm, default, lg | + +## Styling Approach + +Components use cva for variant-driven styling with Tailwind classes that resolve to theme CSS variables. + +Example (Button): +```tsx +const buttonVariants = cva( + 'inline-flex items-center justify-center gap-2 rounded-xl text-sm font-semibold transition-all duration-200 active:scale-[0.97] cursor-pointer', + { + variants: { + variant: { + primary: 'text-white bg-gradient-to-br from-primary to-accent shadow-(--shadow-primary) hover:shadow-(--shadow-primary-hover) hover:-translate-y-px', + secondary: 'bg-surface text-text border border-border hover:bg-surface-raised hover:border-border-strong', + ghost: 'bg-transparent text-text-secondary hover:bg-primary-subtle hover:text-primary', + danger: 'text-white bg-danger shadow-(--shadow-danger) hover:bg-danger-hover hover:shadow-(--shadow-danger-hover) hover:-translate-y-px', + outline: 'bg-transparent text-primary border-2 border-primary/30 hover:bg-primary-subtle hover:border-primary', + }, + size: { + sm: 'px-3.5 py-1.5 text-xs rounded-lg', + default: 'px-5 py-2.5', + lg: 'px-8 py-3.5 text-base', + }, + }, + defaultVariants: { variant: 'primary', size: 'default' }, + } +); +``` + +## Theming + +Components are fully theme-aware through CSS variables: + +``` +@simplemodule/theme-default (theme.css) + defines: --color-primary, --shadow-primary, etc. + ↓ +Tailwind @theme block + maps: bg-primary → var(--color-primary) + ↓ +@simplemodule/ui components + uses: Tailwind classes like 'bg-primary', 'text-danger' + ↓ +Browser renders current variable values +``` + +To create a new theme, create a new theme package with the same CSS variable names and different values. Swap the import in `app.css`. All components update automatically. + +### Shadow Tokens (new, added to theme) + +```css +@theme { + --shadow-primary: 0 4px 14px rgba(13, 148, 136, 0.35); + --shadow-primary-hover: 0 6px 20px rgba(13, 148, 136, 0.5); + --shadow-danger: 0 4px 14px rgba(225, 29, 72, 0.25); + --shadow-danger-hover: 0 6px 20px rgba(225, 29, 72, 0.4); +} +``` + +## CLI Tool + +**Location:** `tools/add-component.mjs` + npm script alias `npm run ui:add` + +**Usage:** +```bash +npm run ui:add -- button # add single component +npm run ui:add -- dialog badge # add multiple +npm run ui:add -- --list # show available components +``` + +**Behavior:** +1. Reads `registry/registry.json` for component metadata +2. Copies template from `registry/templates/.tsx` → `components/.tsx` +3. Auto-installs Radix packages if needed +4. Resolves dependencies (e.g., dialog pulls in button) +5. Updates `components/index.ts` barrel export + +### Registry Format + +```json +{ + "button": { + "name": "Button", + "file": "button.tsx", + "dependencies": [], + "radixPackage": null + }, + "dialog": { + "name": "Dialog", + "file": "dialog.tsx", + "dependencies": ["button"], + "radixPackage": "@radix-ui/react-dialog" + } +} +``` + +## Migration + +- **No breaking changes.** Existing CSS classes (`btn-primary`, `glass-card`, etc.) stay in theme +- Modules adopt `@simplemodule/ui` components incrementally +- CSS classes can be retired once all modules have migrated off them +- No module Vite config changes needed — UI source gets bundled into each module's `.pages.js` From aa718cfd275808e7e56033d0b48244f290629743 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 16 Mar 2026 12:07:15 +0100 Subject: [PATCH 28/62] docs: add implementation plan for @simplemodule/ui library Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/plans/2026-03-16-ui-library-plan.md | 1707 ++++++++++++++++++++++ 1 file changed, 1707 insertions(+) create mode 100644 docs/plans/2026-03-16-ui-library-plan.md diff --git a/docs/plans/2026-03-16-ui-library-plan.md b/docs/plans/2026-03-16-ui-library-plan.md new file mode 100644 index 00000000..4a0d7f54 --- /dev/null +++ b/docs/plans/2026-03-16-ui-library-plan.md @@ -0,0 +1,1707 @@ +# @simplemodule/ui Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Create a shadcn-style shared React component library with ~18 components, a CLI tool, and Radix UI primitives — all themed via CSS variables. + +**Architecture:** New npm workspace `@simplemodule/ui` at `src/SimpleModule.UI/`. Components are source TSX files styled with cva + Tailwind classes referencing `@simplemodule/theme-default` CSS variables. A CLI tool (`tools/add-component.mjs`) copies component templates into the active components directory. + +**Tech Stack:** Radix UI, class-variance-authority (cva), clsx, tailwind-merge, React 19 + +**Design doc:** `docs/plans/2026-03-16-ui-library-design.md` + +--- + +### Task 1: Scaffold `@simplemodule/ui` package and install dependencies + +**Files:** +- Create: `src/SimpleModule.UI/package.json` +- Create: `src/SimpleModule.UI/lib/utils.ts` +- Create: `src/SimpleModule.UI/components/index.ts` +- Create: `src/SimpleModule.UI/registry/registry.json` +- Modify: `package.json` (root — add workspace) + +**Step 1: Create package.json** + +```json +{ + "private": true, + "name": "@simplemodule/ui", + "type": "module", + "main": "components/index.ts", + "exports": { + ".": "./components/index.ts", + "./lib/utils": "./lib/utils.ts" + }, + "peerDependencies": { + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "dependencies": { + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "tailwind-merge": "^3.0.0", + "@radix-ui/react-slot": "^1.2.0" + } +} +``` + +**Step 2: Add workspace to root package.json** + +Add `"src/SimpleModule.UI"` to the `workspaces` array in `package.json`: + +```json +"workspaces": [ + "src/modules/*/src/*", + "src/SimpleModule.Client", + "src/SimpleModule.Theme.Default", + "src/SimpleModule.UI", + "src/SimpleModule.Host/ClientApp" +] +``` + +**Step 3: Create `cn()` utility** + +Create `src/SimpleModule.UI/lib/utils.ts`: + +```ts +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} +``` + +**Step 4: Create empty barrel export** + +Create `src/SimpleModule.UI/components/index.ts`: + +```ts +// Components are added here by the CLI tool (npm run ui:add) +``` + +**Step 5: Create empty registry** + +Create `src/SimpleModule.UI/registry/registry.json`: + +```json +{} +``` + +**Step 6: Install dependencies** + +Run: `npm install` +Expected: Clean install with new workspace resolved + +**Step 7: Verify TypeScript resolves the package** + +Run: `npx tsc --noEmit --project tsconfig.json 2>&1 | head -5` +Expected: No errors related to `@simplemodule/ui` + +**Step 8: Commit** + +```bash +git add src/SimpleModule.UI/ package.json package-lock.json +git commit -m "feat: scaffold @simplemodule/ui workspace with cn() utility" +``` + +--- + +### Task 2: Add shadow tokens to theme + +**Files:** +- Modify: `src/SimpleModule.Theme.Default/theme.css:6-64` (inside `@theme` block) + +**Step 1: Add shadow tokens** + +Add these lines at the end of the `@theme` block (before the closing `}`), after the `--color-muted` line: + +```css + /* --- Shadows (themeable) --- */ + --shadow-primary: 0 4px 14px rgba(13, 148, 136, 0.35); + --shadow-primary-hover: 0 6px 20px rgba(13, 148, 136, 0.5); + --shadow-danger: 0 4px 14px rgba(225, 29, 72, 0.25); + --shadow-danger-hover: 0 6px 20px rgba(225, 29, 72, 0.4); +``` + +**Step 2: Verify the host app builds CSS** + +Run: `cd src/SimpleModule.Host && dotnet build 2>&1 | tail -3` +Expected: Build succeeded + +**Step 3: Commit** + +```bash +git add src/SimpleModule.Theme.Default/theme.css +git commit -m "feat: add shadow tokens to theme for themeable button/danger shadows" +``` + +--- + +### Task 3: Create Button component template + +**Files:** +- Create: `src/SimpleModule.UI/registry/templates/button.tsx` +- Modify: `src/SimpleModule.UI/registry/registry.json` + +**Step 1: Create button template** + +Create `src/SimpleModule.UI/registry/templates/button.tsx`: + +```tsx +import * as React from 'react'; +import { Slot } from '@radix-ui/react-slot'; +import { cva, type VariantProps } from 'class-variance-authority'; +import { cn } from '../lib/utils'; + +const buttonVariants = cva( + 'inline-flex items-center justify-center gap-2 rounded-xl text-sm font-semibold transition-all duration-200 active:scale-[0.97] cursor-pointer disabled:pointer-events-none disabled:opacity-50', + { + variants: { + variant: { + primary: + 'text-white bg-gradient-to-br from-primary to-accent shadow-(--shadow-primary) hover:shadow-(--shadow-primary-hover) hover:-translate-y-px', + secondary: + 'bg-surface text-text border border-border hover:bg-surface-raised hover:border-border-strong', + ghost: 'bg-transparent text-text-secondary hover:bg-primary-subtle hover:text-primary', + danger: + 'text-white bg-danger shadow-(--shadow-danger) hover:bg-danger-hover hover:shadow-(--shadow-danger-hover) hover:-translate-y-px', + outline: + 'bg-transparent text-primary border-2 border-primary/30 hover:bg-primary-subtle hover:border-primary', + }, + size: { + sm: 'px-3.5 py-1.5 text-xs rounded-lg', + default: 'px-5 py-2.5', + lg: 'px-8 py-3.5 text-base', + }, + }, + defaultVariants: { + variant: 'primary', + size: 'default', + }, + }, +); + +interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : 'button'; + return ; + }, +); +Button.displayName = 'Button'; + +export { Button, buttonVariants }; +export type { ButtonProps }; +``` + +**Step 2: Add button to registry** + +Update `src/SimpleModule.UI/registry/registry.json`: + +```json +{ + "button": { + "name": "Button", + "file": "button.tsx", + "dependencies": [], + "radixPackages": ["@radix-ui/react-slot"], + "exports": ["Button", "buttonVariants"] + } +} +``` + +**Step 3: Commit** + +```bash +git add src/SimpleModule.UI/registry/ +git commit -m "feat: add Button component template to registry" +``` + +--- + +### Task 4: Create Input, Textarea, Label component templates + +**Files:** +- Create: `src/SimpleModule.UI/registry/templates/input.tsx` +- Create: `src/SimpleModule.UI/registry/templates/textarea.tsx` +- Create: `src/SimpleModule.UI/registry/templates/label.tsx` +- Modify: `src/SimpleModule.UI/registry/registry.json` + +**Step 1: Create input template** + +Create `src/SimpleModule.UI/registry/templates/input.tsx`: + +```tsx +import * as React from 'react'; +import { cva, type VariantProps } from 'class-variance-authority'; +import { cn } from '../lib/utils'; + +const inputVariants = cva( + 'w-full px-4 py-3 bg-surface border rounded-xl text-sm text-text transition-all duration-200 placeholder:text-text-muted outline-none focus:border-primary focus:ring-4 focus:ring-primary-ring', + { + variants: { + variant: { + default: 'border-border', + error: 'border-danger focus:border-danger focus:ring-danger-bg', + }, + }, + defaultVariants: { + variant: 'default', + }, + }, +); + +interface InputProps extends React.InputHTMLAttributes, VariantProps {} + +const Input = React.forwardRef(({ className, variant, type, ...props }, ref) => { + return ; +}); +Input.displayName = 'Input'; + +export { Input, inputVariants }; +export type { InputProps }; +``` + +**Step 2: Create textarea template** + +Create `src/SimpleModule.UI/registry/templates/textarea.tsx`: + +```tsx +import * as React from 'react'; +import { cn } from '../lib/utils'; + +interface TextareaProps extends React.TextareaHTMLAttributes {} + +const Textarea = React.forwardRef(({ className, ...props }, ref) => { + return ( +