From 424793f558d8d32a446cf1605446582e3ac6dee2 Mon Sep 17 00:00:00 2001 From: "fuzeone-bot[bot]" Date: Thu, 30 Jul 2026 00:13:46 +0300 Subject: [PATCH 1/8] chore(auth-ui): scaffold @fuzefront/auth-ui package skeleton [skip ci] Safety checkpoint before implementation: package.json, tsconfig*.json, vite.config.ts, README, stub src/index.ts. Mirrors packages/identity-ui's build setup. Co-Authored-By: Claude Opus 4.8 Claude-Session-Id: 548a2d55-e1cd-4b5e-bfc4-b6e102bf4695 --- packages/auth-ui/README.md | 60 ++++++++++++++++++++++++++++ packages/auth-ui/package.json | 46 +++++++++++++++++++++ packages/auth-ui/src/index.ts | 1 + packages/auth-ui/tsconfig.build.json | 11 +++++ packages/auth-ui/tsconfig.json | 24 +++++++++++ packages/auth-ui/vite.config.ts | 40 +++++++++++++++++++ 6 files changed, 182 insertions(+) create mode 100644 packages/auth-ui/README.md create mode 100644 packages/auth-ui/package.json create mode 100644 packages/auth-ui/src/index.ts create mode 100644 packages/auth-ui/tsconfig.build.json create mode 100644 packages/auth-ui/tsconfig.json create mode 100644 packages/auth-ui/vite.config.ts diff --git a/packages/auth-ui/README.md b/packages/auth-ui/README.md new file mode 100644 index 00000000..c0794659 --- /dev/null +++ b/packages/auth-ui/README.md @@ -0,0 +1,60 @@ +# @fuzefront/auth-ui + +Reusable sign-in / sign-up UI for FuzeFront — the `AuthPanel` React component plus a +zero-dependency vanilla (non-React) mount, both built design-system-first on +`@fuzefront/design-system` and typed against the frozen `@fuzefront/security-client` +contract. + +## Why + +`frontend/src/pages/LoginPage.tsx` implements sign-in/sign-up inline, coupled to the +host app's `LanguageContext`, `useCurrentUser`, and asset imports. This package +extracts the same behavior into an injectable, framework-boundary-clean component so +it can be reused by other FuzeFront-family apps (and, via the vanilla build, by +non-React hosts) without pulling in the host's context providers. + +## Usage (React) + +```tsx +import { AuthPanel } from '@fuzefront/auth-ui' +import '@fuzefront/auth-ui/styles.css' + + securityClient.login(req), + signup: (req) => securityClient.signup(req), + getAuthMethods: () => securityClient.getAuthMethods(), + startSocial: (provider) => securityClient.startSocial(provider), + }} + onAuthenticated={(session) => { /* hydrate + redirect */ }} + onMfaRequired={(challenge) => { /* show step-up UI */ }} + social +/> +``` + +`transport` is the injection seam: this package never imports `useLanguage`, +`useCurrentUser`, `window.location`, or any asset — the host wires those in via the +transport + `onAuthenticated`/`onMfaRequired` callbacks. + +## Usage (vanilla / non-React host) + +```html + +
+ + +``` + +The vanilla build is a zero-dependency IIFE — it does not bundle React or React-DOM. + +## Design system + +Built only from `@fuzefront/design-system` tokens/components (`Button`, `Input`, +`Alert`, `SeamDivider`, `CenteredCard`). No hard-coded color/spacing/type. diff --git a/packages/auth-ui/package.json b/packages/auth-ui/package.json new file mode 100644 index 00000000..225ef8d0 --- /dev/null +++ b/packages/auth-ui/package.json @@ -0,0 +1,46 @@ +{ + "name": "@fuzefront/auth-ui", + "version": "0.1.0", + "description": "Reusable sign-in / sign-up AuthPanel UI for FuzeFront, on the fuse-seam design system — React component + zero-dep vanilla mount", + "type": "module", + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js", "require": "./dist/index.cjs" }, + "./vanilla": { "default": "./dist/auth-ui.vanilla.js" }, + "./styles.css": "./dist/styles.css" + }, + "files": ["dist"], + "sideEffects": false, + "scripts": { + "build": "vite build && tsc -p tsconfig.build.json --emitDeclarationOnly && node esbuild.vanilla.mjs", + "type-check": "tsc --noEmit", + "test": "vitest run" + }, + "peerDependencies": { + "@fuzefront/design-system": "^1.0.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@fuzefront/design-system": "1.0.0", + "@fuzefront/security-client": "0.2.0", + "@testing-library/jest-dom": "^6.4.0", + "@testing-library/react": "^16.3.2", + "@testing-library/user-event": "^14.5.0", + "@types/react": "^19.2.0", + "@types/react-dom": "^19.2.0", + "@vitejs/plugin-react": "^4.3.0", + "esbuild": "^0.24.0", + "jsdom": "^25.0.0", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "typescript": "^5.5.0", + "vite": "^5.4.0", + "vite-plugin-dts": "^4.0.0", + "vitest": "^2.1.0" + }, + "publishConfig": { "registry": "https://npm.pkg.github.com", "access": "restricted" }, + "repository": { "type": "git", "url": "https://github.com/fuzefront/FuzeFront.git", "directory": "packages/auth-ui" } +} diff --git a/packages/auth-ui/src/index.ts b/packages/auth-ui/src/index.ts new file mode 100644 index 00000000..336ce12b --- /dev/null +++ b/packages/auth-ui/src/index.ts @@ -0,0 +1 @@ +export {} diff --git a/packages/auth-ui/tsconfig.build.json b/packages/auth-ui/tsconfig.build.json new file mode 100644 index 00000000..53009315 --- /dev/null +++ b/packages/auth-ui/tsconfig.build.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": false, + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "dist" + }, + "include": ["src"], + "exclude": ["src/**/*.test.*", "src/**/*.spec.*", "src/test", "src/vanilla/**"] +} diff --git a/packages/auth-ui/tsconfig.json b/packages/auth-ui/tsconfig.json new file mode 100644 index 00000000..9bc786b1 --- /dev/null +++ b/packages/auth-ui/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "Bundler", + "jsx": "react-jsx", + "strict": true, + "declaration": true, + "outDir": "dist", + "skipLibCheck": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "paths": { + "vitest": ["./node_modules/vitest"], + "vitest/*": ["./node_modules/vitest/*"], + "@vitest/expect": ["./node_modules/@vitest/expect"], + "@vitest/expect/*": ["./node_modules/@vitest/expect/*"] + } + }, + "include": ["src"] +} diff --git a/packages/auth-ui/vite.config.ts b/packages/auth-ui/vite.config.ts new file mode 100644 index 00000000..62cc609a --- /dev/null +++ b/packages/auth-ui/vite.config.ts @@ -0,0 +1,40 @@ +import { defineConfig } from 'vite' +import { fileURLToPath } from 'node:url' +import react from '@vitejs/plugin-react' +import dts from 'vite-plugin-dts' + +const dsRoot = fileURLToPath(new URL('../../design-system', import.meta.url)) + +export default defineConfig({ + plugins: [ + react(), + dts({ insertTypesEntry: true }), + ], + build: { + lib: { + entry: 'src/index.ts', + formats: ['es', 'cjs'], + fileName: (fmt) => fmt === 'cjs' ? 'index.cjs' : 'index.js', + }, + rollupOptions: { + external: [ + 'react', + 'react-dom', + 'react/jsx-runtime', + '@fuzefront/design-system', + /^@fuzefront\/design-system\/.*/, + ], + }, + }, + test: { + environment: 'jsdom', + globals: true, + setupFiles: ['./src/test/setup.ts'], + css: false, + // Resolve the design-system to its source folder so unit tests don't depend + // on the npm workspace symlink (which requires GitHub Packages auth to link). + alias: { + '@fuzefront/design-system': dsRoot + '/index.js', + }, + }, +}) From fbf05514b6e22f1eb180e76a43eac26cb13f54e7 Mon Sep 17 00:00:00 2001 From: "fuzeone-bot[bot]" Date: Thu, 30 Jul 2026 00:15:25 +0300 Subject: [PATCH 2/8] feat(auth-ui): add AuthTransport/AuthPanelProps contract types [skip ci] Types derived from @fuzefront/security-client's SessionResult union rather than hand-redefined. Co-Authored-By: Claude Opus 4.8 Claude-Session-Id: 548a2d55-e1cd-4b5e-bfc4-b6e102bf4695 --- packages/auth-ui/src/types.ts | 117 ++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 packages/auth-ui/src/types.ts diff --git a/packages/auth-ui/src/types.ts b/packages/auth-ui/src/types.ts new file mode 100644 index 00000000..65849bee --- /dev/null +++ b/packages/auth-ui/src/types.ts @@ -0,0 +1,117 @@ +/** + * Auth contract types — re-exported from the frozen `@fuzefront/security-client` + * contract (never hand-redefined here). `AuthenticatedSession` and + * `MfaRequiredChallenge` are the two variants of the generated `SessionResult` + * discriminated union; the security-client only exports the hand-authored + * union at the top level, so the variants are derived via `Extract` against + * that same union rather than reached for separately from `components`. + */ +import type { SessionResult, AuthMethods } from '@fuzefront/security-client' + +export type { SessionResult, AuthMethods } + +export type AuthenticatedSession = Extract +export type MfaRequiredChallenge = Extract + +/** Request shape for a password sign-in. Shape-compatible with the contract's `LoginRequest`. */ +export interface LoginRequest { + email: string + password: string +} + +/** Request shape for account creation. Shape-compatible with the contract's `SignupRequest` (minus `tenantName`, not surfaced by this UI). */ +export interface SignupRequest { + email: string + password: string + firstName?: string + lastName?: string +} + +/** + * The injection seam between `AuthPanel` and a host app's real transport + * (HTTP client, mock server, or anything else). `AuthPanel` never imports an + * HTTP client, routing, or host state directly — every side effect goes + * through this interface, and every outcome comes back via the component's + * `onAuthenticated` / `onMfaRequired` callbacks. + */ +export interface AuthTransport { + login(req: LoginRequest): Promise + signup(req: SignupRequest): Promise + getAuthMethods(): Promise + /** Only called when present — the Google button is hidden entirely otherwise. */ + startSocial?(provider: 'google'): Promise +} + +/** Which sign-in mode the panel starts in / can toggle to. */ +export type AuthPanelMode = 'signin' | 'signup' + +/** `full` wraps the form in a `CenteredCard` (a standalone page); `compact` renders just the form (embeddable in a modal/panel). */ +export type AuthPanelVariant = 'compact' | 'full' + +/** Every user-facing string the panel renders. All overridable via `labels`. */ +export interface AuthLabels { + heading: string + signInSubtitle: string + signUpSubtitle: string + emailLabel: string + passwordLabel: string + firstNameLabel: string + lastNameLabel: string + signInCta: string + signInPending: string + signUpCta: string + signUpPending: string + googleCta: string + googlePending: string + orDivider: string + toggleToSignUpPrompt: string + toggleToSignUpCta: string + toggleToSignInPrompt: string + toggleToSignInCta: string + mfaNotice: string + genericError: string +} + +export const DEFAULT_AUTH_LABELS: AuthLabels = { + heading: 'Welcome to FuzeFront', + signInSubtitle: 'Sign in to access your microfrontend platform', + signUpSubtitle: 'Create your account to get started', + emailLabel: 'Email', + passwordLabel: 'Password', + firstNameLabel: 'First name', + lastNameLabel: 'Last name', + signInCta: 'Sign In', + signInPending: 'Signing in…', + signUpCta: 'Create account', + signUpPending: 'Creating account…', + googleCta: 'Sign in with Google', + googlePending: 'Redirecting to Google…', + orDivider: 'or', + toggleToSignUpPrompt: "Don't have an account?", + toggleToSignUpCta: 'Sign up', + toggleToSignInPrompt: 'Already have an account?', + toggleToSignInCta: 'Back to sign in', + mfaNotice: + 'Additional verification is required to finish signing in. Please complete the verification step to continue.', + genericError: 'Authentication failed. Please try again.', +} + +/** Which sign-in action is in flight — per-action so only the clicked control shows its own pending label. */ +export type PendingAction = 'credentials' | 'google' | null + +export interface AuthPanelProps { + /** `full` (default) wraps in `CenteredCard` for a standalone page; `compact` renders just the form. */ + variant?: AuthPanelVariant + /** Initial mode. Defaults to `signin`. The panel owns mode-toggle state internally. */ + mode?: AuthPanelMode + /** The injection seam — see `AuthTransport`. */ + transport: AuthTransport + /** Called with the established session once sign-in or sign-up succeeds. */ + onAuthenticated: (session: AuthenticatedSession) => void + /** Called when `login` resolves to an MFA challenge instead of a session. */ + onMfaRequired?: (challenge: MfaRequiredChallenge) => void + /** Show the Google button. Only rendered when this is true AND `transport.startSocial` is present AND `getAuthMethods()` advertises `google` in `social`. Defaults to `true`. */ + social?: boolean + /** Override any subset of the default copy. */ + labels?: Partial +} From daee74651796e8d11bf580cad730b664f86b0b8b Mon Sep 17 00:00:00 2001 From: "fuzeone-bot[bot]" Date: Thu, 30 Jul 2026 00:17:08 +0300 Subject: [PATCH 3/8] feat(auth-ui): implement AuthPanel React component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sign-in/sign-up form with mode toggle, per-action pending labels, error/mfa notice, and optional Google button — design-system-first (Button, Input, Alert, SeamDivider, CenteredCard only), transport-injected (no useLanguage/ useCurrentUser/window.location/asset imports). Co-Authored-By: Claude Opus 4.8 Claude-Session-Id: 548a2d55-e1cd-4b5e-bfc4-b6e102bf4695 --- packages/auth-ui/src/components/AuthPanel.tsx | 229 ++++++++++++++++++ .../auth-ui/src/components/GoogleGlyph.tsx | 24 ++ packages/auth-ui/src/index.ts | 18 +- packages/auth-ui/src/styles.css | 94 +++++++ 4 files changed, 364 insertions(+), 1 deletion(-) create mode 100644 packages/auth-ui/src/components/AuthPanel.tsx create mode 100644 packages/auth-ui/src/components/GoogleGlyph.tsx create mode 100644 packages/auth-ui/src/styles.css diff --git a/packages/auth-ui/src/components/AuthPanel.tsx b/packages/auth-ui/src/components/AuthPanel.tsx new file mode 100644 index 00000000..89b1ee4c --- /dev/null +++ b/packages/auth-ui/src/components/AuthPanel.tsx @@ -0,0 +1,229 @@ +import React, { useEffect, useState } from 'react' +import { Button, Input, Alert, SeamDivider, CenteredCard } from '@fuzefront/design-system' +import type { + AuthPanelProps, + AuthMethods, + PendingAction, + AuthPanelMode, +} from '../types' +import { DEFAULT_AUTH_LABELS } from '../types' +import { GoogleGlyph } from './GoogleGlyph' + +/** Password-only, no-social fallback — rendered immediately so the form is never + * gated on the `getAuthMethods()` round trip. Mirrors LoginPage's fail-open + * posture: a slow/failed capability fetch degrades to the password form, + * never to a blank screen. */ +const FALLBACK_METHODS: AuthMethods = { + password: true, + social: [], + mfa: { enabled: false, types: [] }, + verification: { email: false, sms: false }, +} + +/** + * `AuthPanel` — the reusable sign-in / sign-up form. Behavior parity with + * `frontend/src/pages/LoginPage.tsx`, minus every host-specific dependency + * (`useLanguage`, `useCurrentUser`, `window.location`, asset imports): every + * side effect goes through the injected `transport`, every outcome comes back + * via `onAuthenticated` / `onMfaRequired`. + */ +export function AuthPanel({ + variant = 'full', + mode: initialMode = 'signin', + transport, + onAuthenticated, + onMfaRequired, + social = true, + labels: labelOverrides, +}: AuthPanelProps) { + const labels = { ...DEFAULT_AUTH_LABELS, ...labelOverrides } + const [mode, setMode] = useState(initialMode) + const [email, setEmail] = useState('') + const [password, setPassword] = useState('') + const [firstName, setFirstName] = useState('') + const [lastName, setLastName] = useState('') + const [pending, setPending] = useState(null) + const loading = pending !== null + const [error, setError] = useState('') + const [notice, setNotice] = useState('') + const [authMethods, setAuthMethods] = useState(FALLBACK_METHODS) + + useEffect(() => { + let cancelled = false + transport + .getAuthMethods() + .then((methods) => { + if (!cancelled) setAuthMethods(methods) + }) + .catch(() => { + if (!cancelled) setAuthMethods(FALLBACK_METHODS) + }) + return () => { + cancelled = true + } + // Runs once per mount, mirroring LoginPage's page-load capability fetch. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + const passwordEnabled = authMethods.password !== false + const socialEnabled = social && Boolean(transport.startSocial) && authMethods.social.includes('google') + + const toggleMode = () => { + setMode((m) => (m === 'signin' ? 'signup' : 'signin')) + setError('') + setNotice('') + } + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + setPending('credentials') + setError('') + setNotice('') + try { + if (mode === 'signup') { + const session = await transport.signup({ + email, + password, + firstName: firstName || undefined, + lastName: lastName || undefined, + }) + onAuthenticated(session) + return + } + + const result = await transport.login({ email, password }) + if (result.status === 'mfa_required') { + setNotice(labels.mfaNotice) + onMfaRequired?.(result) + return + } + onAuthenticated(result) + } catch (err: unknown) { + const message = err instanceof Error ? err.message : undefined + setError(message || labels.genericError) + } finally { + setPending(null) + } + } + + const handleGoogle = () => { + if (!transport.startSocial) return + setPending('google') + setError('') + setNotice('') + transport + .startSocial('google') + .catch((err: unknown) => { + const message = err instanceof Error ? err.message : undefined + setError(message || 'Failed to start sign-in') + }) + .finally(() => setPending(null)) + } + + const form = ( +
+

{labels.heading}

+

+ {mode === 'signin' ? labels.signInSubtitle : labels.signUpSubtitle} +

+ + {error && ( + + {error} + + )} + {notice && ( + + {notice} + + )} + + {passwordEnabled && ( +
+ {mode === 'signup' && ( +
+ ) => setFirstName(e.target.value)} + autoComplete="given-name" + style={{ flex: 1 }} + /> + ) => setLastName(e.target.value)} + autoComplete="family-name" + style={{ flex: 1 }} + /> +
+ )} + + ) => setEmail(e.target.value)} + autoComplete="email" + required + /> + + ) => setPassword(e.target.value)} + autoComplete={mode === 'signup' ? 'new-password' : 'current-password'} + required + /> + + +
+ )} + + {socialEnabled && ( +
+
+ + {labels.orDivider} + +
+ +
+ )} + +
+

+ {mode === 'signin' ? labels.toggleToSignUpPrompt : labels.toggleToSignInPrompt} +

+ +
+
+ ) + + if (variant === 'compact') return form + return {form} +} diff --git a/packages/auth-ui/src/components/GoogleGlyph.tsx b/packages/auth-ui/src/components/GoogleGlyph.tsx new file mode 100644 index 00000000..85ba326b --- /dev/null +++ b/packages/auth-ui/src/components/GoogleGlyph.tsx @@ -0,0 +1,24 @@ +import React from 'react' + +// Official Google "G" mark palette — these exact values are mandated by +// Google's brand identity guidelines for third-party sign-in buttons and must +// NOT be themed or tokenized (they are a trademark asset, not UI styling). +// Mirrors the same allow-marked constant in frontend/src/pages/LoginPage.tsx. +const GOOGLE_BRAND = { + red: '#EA4335', // ds-conformance-allow: third-party brand mark (Google identity guidelines) + blue: '#4285F4', // ds-conformance-allow: third-party brand mark (Google identity guidelines) + yellow: '#FBBC05', // ds-conformance-allow: third-party brand mark (Google identity guidelines) + green: '#34A853', // ds-conformance-allow: third-party brand mark (Google identity guidelines) +} + +/** The official Google "G" mark, inlined so the vanilla build stays zero-dependency. */ +export function GoogleGlyph() { + return ( + + ) +} diff --git a/packages/auth-ui/src/index.ts b/packages/auth-ui/src/index.ts index 336ce12b..2b10dbe3 100644 --- a/packages/auth-ui/src/index.ts +++ b/packages/auth-ui/src/index.ts @@ -1 +1,17 @@ -export {} +export { AuthPanel } from './components/AuthPanel' + +export type { + AuthPanelProps, + AuthPanelMode, + AuthPanelVariant, + AuthTransport, + AuthLabels, + PendingAction, + SessionResult, + AuthenticatedSession, + MfaRequiredChallenge, + AuthMethods, + LoginRequest, + SignupRequest, +} from './types' +export { DEFAULT_AUTH_LABELS } from './types' diff --git a/packages/auth-ui/src/styles.css b/packages/auth-ui/src/styles.css new file mode 100644 index 00000000..020f703f --- /dev/null +++ b/packages/auth-ui/src/styles.css @@ -0,0 +1,94 @@ +/* + * @fuzefront/auth-ui — layout styles for AuthPanel / the vanilla mount. + * + * Every value here is a design-system token (`var(--*)` from + * `@fuzefront/design-system`). The DS primitives (Button, Input, Alert, + * SeamDivider, CenteredCard) own their own presentation inline; these rules + * only lay out the wrapper markup around them. Logical properties throughout + * so the panel mirrors automatically under RTL locales. + */ + +.fzf-auth-panel { + display: flex; + flex-direction: column; + font-family: var(--font-sans); +} + +.fzf-auth-panel__heading { + margin-block: 0 var(--space-2); + font-size: var(--text-lg); + font-weight: var(--weight-semibold); + color: var(--text-primary); +} + +.fzf-auth-panel__subtitle { + margin-block: 0 var(--space-4); + color: var(--text-secondary); + font-size: var(--text-sm); +} + +.fzf-auth-panel__alert { + margin-block-end: var(--space-4); +} + +.fzf-auth-panel__form { + display: flex; + flex-direction: column; + gap: var(--space-4); +} + +.fzf-auth-panel__name-row { + display: flex; + gap: var(--space-3); +} + +.fzf-auth-panel__social { + margin-block-start: var(--space-4); +} + +.fzf-auth-panel__divider { + display: flex; + align-items: center; + gap: var(--space-3); + margin-block: var(--space-4); +} + +.fzf-auth-panel__divider-label { + color: var(--text-tertiary); + font-size: var(--text-sm); +} + +.fzf-auth-panel__google-button { + width: 100%; + display: flex; + align-items: center; + justify-content: center; + gap: var(--space-2); + padding: var(--space-3); + background-color: var(--bg-primary); + color: var(--text-primary); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + font-family: var(--font-sans); + font-size: var(--text-md); + font-weight: var(--weight-semibold); + cursor: pointer; +} + +.fzf-auth-panel__google-button:disabled { + cursor: not-allowed; + opacity: 0.6; +} + +.fzf-auth-panel__toggle { + margin-block-start: var(--space-6); + padding-block-start: var(--space-6); + border-block-start: 1px solid var(--border-color); + text-align: center; +} + +.fzf-auth-panel__toggle-prompt { + margin-block: 0 var(--space-3); + color: var(--text-secondary); + font-size: var(--text-base, 0.9rem); +} From 56950bc9ca3bbfa1a4ef1abebcb0e9ab52c94fa3 Mon Sep 17 00:00:00 2001 From: "fuzeone-bot[bot]" Date: Thu, 30 Jul 2026 00:18:47 +0300 Subject: [PATCH 4/8] feat(auth-ui): add zero-dep vanilla mount + esbuild IIFE script window.FuzeFrontAuthUI.mount(container, opts) reimplements the same behavior/CSS classes as plain DOM, no React/React-DOM in the bundle. social defaults OFF for the vanilla entry point (React AuthPanel defaults social on). Co-Authored-By: Claude Opus 4.8 Claude-Session-Id: 548a2d55-e1cd-4b5e-bfc4-b6e102bf4695 --- packages/auth-ui/esbuild.vanilla.mjs | 27 +++ packages/auth-ui/src/test/setup.ts | 19 ++ packages/auth-ui/src/vanilla/entry.ts | 5 + packages/auth-ui/src/vanilla/mount.ts | 283 ++++++++++++++++++++++++++ 4 files changed, 334 insertions(+) create mode 100644 packages/auth-ui/esbuild.vanilla.mjs create mode 100644 packages/auth-ui/src/test/setup.ts create mode 100644 packages/auth-ui/src/vanilla/entry.ts create mode 100644 packages/auth-ui/src/vanilla/mount.ts diff --git a/packages/auth-ui/esbuild.vanilla.mjs b/packages/auth-ui/esbuild.vanilla.mjs new file mode 100644 index 00000000..3b3087bb --- /dev/null +++ b/packages/auth-ui/esbuild.vanilla.mjs @@ -0,0 +1,27 @@ +#!/usr/bin/env node +// Builds dist/auth-ui.vanilla.js — a zero-dependency IIFE (no React/React-DOM +// in the bundle) exposing `window.FuzeFrontAuthUI.mount(container, opts)`. +// Run after the main `vite build` (see package.json `build` script); also +// copies styles.css into dist so `@fuzefront/auth-ui/styles.css` resolves. +import { build } from 'esbuild' +import { copyFileSync, mkdirSync } from 'node:fs' +import { fileURLToPath } from 'node:url' +import { dirname, join } from 'node:path' + +const ROOT = dirname(fileURLToPath(import.meta.url)) + +await build({ + entryPoints: [join(ROOT, 'src/vanilla/entry.ts')], + outfile: join(ROOT, 'dist/auth-ui.vanilla.js'), + bundle: true, + format: 'iife', + globalName: 'FuzeFrontAuthUI', + target: 'es2020', + minify: true, + platform: 'browser', +}) + +mkdirSync(join(ROOT, 'dist'), { recursive: true }) +copyFileSync(join(ROOT, 'src/styles.css'), join(ROOT, 'dist/styles.css')) + +console.log('[auth-ui] vanilla IIFE + styles.css written to dist/') diff --git a/packages/auth-ui/src/test/setup.ts b/packages/auth-ui/src/test/setup.ts new file mode 100644 index 00000000..b04105e2 --- /dev/null +++ b/packages/auth-ui/src/test/setup.ts @@ -0,0 +1,19 @@ +// @testing-library/jest-dom lives in root node_modules; its /vitest entry +// does `import { expect } from 'vitest'` which resolves to the ROOT +// vitest@1.x from that package's location — a different module instance +// than the LOCAL vitest@2.x that test files import. Calling expect.extend() +// on the wrong instance means the matchers are never visible to tests. +// +// Fix: import `expect` from vitest HERE (Vite resolves this file's imports +// from packages/identity-ui/node_modules → local vitest@2.x), then extend +// that expect with the matchers object from jest-dom/matchers directly. +// +// The triple-slash reference brings jest-dom's vitest.d.ts into THIS +// compilation unit so TypeScript's `paths` override (tsconfig.json) redirects +// its `import 'vitest'` to local vitest@2.x, making the type augmentation +// (Assertion extends TestingLibraryMatchers) land on the right module. +/// +import { expect } from 'vitest' +import * as matchers from '@testing-library/jest-dom/matchers' + +expect.extend(matchers) diff --git a/packages/auth-ui/src/vanilla/entry.ts b/packages/auth-ui/src/vanilla/entry.ts new file mode 100644 index 00000000..4b20d59e --- /dev/null +++ b/packages/auth-ui/src/vanilla/entry.ts @@ -0,0 +1,5 @@ +// IIFE entry point for the vanilla build. esbuild bundles this with +// `format: 'iife', globalName: 'FuzeFrontAuthUI'`, so this module's exports +// become `window.FuzeFrontAuthUI`. +export { mount } from './mount' +export type { VanillaMountOptions, VanillaMountHandle } from './mount' diff --git a/packages/auth-ui/src/vanilla/mount.ts b/packages/auth-ui/src/vanilla/mount.ts new file mode 100644 index 00000000..1629d522 --- /dev/null +++ b/packages/auth-ui/src/vanilla/mount.ts @@ -0,0 +1,283 @@ +/** + * Zero-dependency vanilla mount for `AuthPanel` — no React, no React-DOM. + * Reimplements the same behavior and the same `.fzf-auth-panel*` CSS classes + * (see `../styles.css`) as plain DOM, for non-React hosts. Bundled as a + * standalone IIFE (`dist/auth-ui.vanilla.js`) exposing + * `window.FuzeFrontAuthUI.mount(container, opts)`. + */ +import type { + AuthTransport, + AuthMethods, + AuthLabels, + AuthPanelMode, + AuthPanelVariant, + AuthenticatedSession, + MfaRequiredChallenge, + PendingAction, +} from '../types' +import { DEFAULT_AUTH_LABELS } from '../types' + +const FALLBACK_METHODS: AuthMethods = { + password: true, + social: [], + mfa: { enabled: false, types: [] }, + verification: { email: false, sms: false }, +} + +export interface VanillaMountOptions { + variant?: AuthPanelVariant + mode?: AuthPanelMode + transport: AuthTransport + onAuthenticated: (session: AuthenticatedSession) => void + onMfaRequired?: (challenge: MfaRequiredChallenge) => void + /** Unlike the React `AuthPanel`, defaults OFF here — an explicit opt-in for + * non-React hosts that may not want the Google button rendered at all. */ + social?: boolean + labels?: Partial +} + +export interface VanillaMountHandle { + unmount(): void +} + +function el( + tag: K, + className?: string, + text?: string, +): HTMLElementTagNameMap[K] { + const node = document.createElement(tag) + if (className) node.className = className + if (text !== undefined) node.textContent = text + return node +} + +function field( + id: string, + labelText: string, + type: string, + autoComplete: string, +): { wrap: HTMLDivElement; input: HTMLInputElement } { + const wrap = el('div') + wrap.style.display = 'flex' + wrap.style.flexDirection = 'column' + wrap.style.gap = 'var(--space-2)' + wrap.style.width = '100%' + const label = el('label', undefined, labelText) + label.htmlFor = id + label.style.fontFamily = 'var(--font-sans)' + label.style.fontSize = 'var(--text-sm)' + label.style.fontWeight = 'var(--weight-medium)' + label.style.color = 'var(--text-secondary)' + const input = el('input') + input.id = id + input.type = type + input.autocomplete = autoComplete + input.style.width = '100%' + input.style.boxSizing = 'border-box' + input.style.padding = 'var(--space-3)' + input.style.fontFamily = 'var(--font-sans)' + input.style.fontSize = 'var(--text-sm)' + input.style.color = 'var(--text-primary)' + input.style.background = 'var(--bg-secondary)' + input.style.border = '1px solid var(--border-color)' + input.style.borderRadius = 'var(--radius-md)' + wrap.appendChild(label) + wrap.appendChild(input) + return { wrap, input } +} + +/** + * Mount an AuthPanel into `container`, plain-DOM. Returns a handle whose + * `unmount()` removes all rendered markup and listeners. + */ +export function mount(container: HTMLElement, opts: VanillaMountOptions): VanillaMountHandle { + const labels: AuthLabels = { ...DEFAULT_AUTH_LABELS, ...opts.labels } + const social = opts.social === true + let mode: AuthPanelMode = opts.mode ?? 'signin' + let pending: PendingAction = null + let authMethods: AuthMethods = FALLBACK_METHODS + let destroyed = false + + const root = el('div', 'fzf-auth-panel') + + const heading = el('h2', 'fzf-auth-panel__heading', labels.heading) + const subtitle = el('p', 'fzf-auth-panel__subtitle') + const alertHost = el('div') + const form = el('form', 'fzf-auth-panel__form') + const nameRow = el('div', 'fzf-auth-panel__name-row') + const firstNameField = field('fzf-auth-vanilla-firstName', labels.firstNameLabel, 'text', 'given-name') + const lastNameField = field('fzf-auth-vanilla-lastName', labels.lastNameLabel, 'text', 'family-name') + const emailField = field('fzf-auth-vanilla-email', labels.emailLabel, 'email', 'email') + const passwordField = field('fzf-auth-vanilla-password', labels.passwordLabel, 'password', 'current-password') + const submitBtn = el('button') + submitBtn.type = 'submit' + const socialWrap = el('div', 'fzf-auth-panel__social') + const toggleWrap = el('div', 'fzf-auth-panel__toggle') + const togglePrompt = el('p', 'fzf-auth-panel__toggle-prompt') + const toggleBtn = el('button') + toggleBtn.type = 'button' + + firstNameField.wrap.style.flex = '1' + lastNameField.wrap.style.flex = '1' + nameRow.appendChild(firstNameField.wrap) + nameRow.appendChild(lastNameField.wrap) + + applyButtonStyle(submitBtn, 'primary') + applyButtonStyle(toggleBtn, 'secondary') + + form.appendChild(nameRow) + form.appendChild(emailField.wrap) + form.appendChild(passwordField.wrap) + form.appendChild(submitBtn) + + toggleWrap.appendChild(togglePrompt) + toggleWrap.appendChild(toggleBtn) + + root.appendChild(heading) + root.appendChild(subtitle) + root.appendChild(alertHost) + root.appendChild(form) + root.appendChild(socialWrap) + root.appendChild(toggleWrap) + + function applyButtonStyle(btn: HTMLButtonElement, variant: 'primary' | 'secondary') { + btn.style.display = 'flex' + btn.style.width = '100%' + btn.style.alignItems = 'center' + btn.style.justifyContent = 'center' + btn.style.gap = '8px' + btn.style.padding = '12px 24px' + btn.style.fontFamily = 'var(--font-sans)' + btn.style.fontSize = 'var(--text-sm)' + btn.style.fontWeight = 'var(--weight-semibold)' + btn.style.borderRadius = 'var(--radius-md)' + btn.style.cursor = 'pointer' + if (variant === 'primary') { + btn.style.background = 'var(--accent-color)' + btn.style.color = '#fff' + btn.style.border = '1px solid transparent' + } else { + btn.style.background = 'var(--bg-quaternary)' + btn.style.color = 'var(--text-primary)' + btn.style.border = '1px solid var(--border-color)' + } + } + + function setAlert(kind: 'error' | 'info' | null, message: string) { + alertHost.innerHTML = '' + if (!kind) return + const box = el('div', 'fzf-auth-panel__alert') + box.setAttribute('role', 'alert') + box.style.padding = 'var(--space-3) var(--space-4)' + box.style.borderRadius = 'var(--radius-md)' + box.style.fontFamily = 'var(--font-sans)' + box.style.fontSize = 'var(--text-sm)' + if (kind === 'error') { + box.style.color = 'var(--error-color)' + box.style.border = '1px solid var(--error-color)' + box.style.background = 'rgba(231, 76, 60, 0.08)' + } else { + box.style.color = 'var(--accent-2)' + box.style.border = '1px solid var(--accent-2)' + box.style.background = 'rgba(41, 211, 230, 0.08)' + } + box.textContent = message + alertHost.appendChild(box) + } + + function render() { + subtitle.textContent = mode === 'signin' ? labels.signInSubtitle : labels.signUpSubtitle + nameRow.style.display = mode === 'signup' ? 'flex' : 'none' + nameRow.style.gap = 'var(--space-3)' + const disabled = pending !== null + submitBtn.disabled = disabled + submitBtn.style.opacity = disabled ? '0.5' : '1' + submitBtn.textContent = + pending === 'credentials' + ? mode === 'signup' + ? labels.signUpPending + : labels.signInPending + : mode === 'signup' + ? labels.signUpCta + : labels.signInCta + + toggleBtn.disabled = disabled + toggleBtn.style.opacity = disabled ? '0.5' : '1' + togglePrompt.textContent = mode === 'signin' ? labels.toggleToSignUpPrompt : labels.toggleToSignInPrompt + toggleBtn.textContent = mode === 'signin' ? labels.toggleToSignUpCta : labels.toggleToSignInCta + + const socialEnabled = social && Boolean(opts.transport.startSocial) && authMethods.social.includes('google') + socialWrap.style.display = socialEnabled ? 'block' : 'none' + } + + async function handleSubmit(e: Event) { + e.preventDefault() + pending = 'credentials' + setAlert(null, '') + render() + try { + if (mode === 'signup') { + const session = await opts.transport.signup({ + email: emailField.input.value, + password: passwordField.input.value, + firstName: firstNameField.input.value || undefined, + lastName: lastNameField.input.value || undefined, + }) + opts.onAuthenticated(session) + return + } + const result = await opts.transport.login({ + email: emailField.input.value, + password: passwordField.input.value, + }) + if (result.status === 'mfa_required') { + setAlert('info', labels.mfaNotice) + opts.onMfaRequired?.(result) + return + } + opts.onAuthenticated(result) + } catch (err) { + const message = err instanceof Error ? err.message : undefined + setAlert('error', message || labels.genericError) + } finally { + if (!destroyed) { + pending = null + render() + } + } + } + + function handleToggle() { + mode = mode === 'signin' ? 'signup' : 'signin' + setAlert(null, '') + render() + } + + form.addEventListener('submit', handleSubmit) + toggleBtn.addEventListener('click', handleToggle) + + render() + container.appendChild(root) + + opts.transport + .getAuthMethods() + .then((methods) => { + if (destroyed) return + authMethods = methods + render() + }) + .catch(() => { + if (destroyed) return + authMethods = FALLBACK_METHODS + render() + }) + + return { + unmount() { + destroyed = true + form.removeEventListener('submit', handleSubmit) + toggleBtn.removeEventListener('click', handleToggle) + container.removeChild(root) + }, + } +} From f2774fecbe0cced00145ac14345bd2275d3b42e5 Mon Sep 17 00:00:00 2001 From: "fuzeone-bot[bot]" Date: Thu, 30 Jul 2026 00:20:16 +0300 Subject: [PATCH 5/8] test(auth-ui): unit tests for AuthPanel + vanilla mount Covers sign-in/signup submit, mode toggle, pending labels, mfa_required notice/callback, error alert, and Google button visibility gating (present only with startSocial AND methods.social advertising it; vanilla defaults social off even when startSocial is supplied). Co-Authored-By: Claude Opus 4.8 Claude-Session-Id: 548a2d55-e1cd-4b5e-bfc4-b6e102bf4695 --- .../auth-ui/src/components/AuthPanel.test.tsx | 197 ++++++++++++++++++ packages/auth-ui/src/vanilla/mount.test.ts | 96 +++++++++ 2 files changed, 293 insertions(+) create mode 100644 packages/auth-ui/src/components/AuthPanel.test.tsx create mode 100644 packages/auth-ui/src/vanilla/mount.test.ts diff --git a/packages/auth-ui/src/components/AuthPanel.test.tsx b/packages/auth-ui/src/components/AuthPanel.test.tsx new file mode 100644 index 00000000..59cbf15d --- /dev/null +++ b/packages/auth-ui/src/components/AuthPanel.test.tsx @@ -0,0 +1,197 @@ +import { describe, it, expect, vi } from 'vitest' +import { render, screen, fireEvent, waitFor } from '@testing-library/react' +import { AuthPanel } from './AuthPanel' +import type { AuthTransport, AuthMethods, AuthenticatedSession, MfaRequiredChallenge } from '../types' + +const AUTHENTICATED: AuthenticatedSession = { + status: 'authenticated', + token: 'tok-123', + user: { id: 'u1' }, +} + +const MFA_CHALLENGE: MfaRequiredChallenge = { + status: 'mfa_required', + challengeId: 'chal-1', + factors: [{ factorId: 'f1', type: 'totp' }], +} + +function baseMethods(overrides: Partial = {}): AuthMethods { + return { + password: true, + social: [], + mfa: { enabled: false, types: [] }, + verification: { email: false, sms: false }, + ...overrides, + } +} + +function makeTransport(overrides: Partial = {}): AuthTransport { + return { + login: vi.fn().mockResolvedValue(AUTHENTICATED), + signup: vi.fn().mockResolvedValue(AUTHENTICATED), + getAuthMethods: vi.fn().mockResolvedValue(baseMethods()), + ...overrides, + } +} + +describe('AuthPanel', () => { + it('submits sign-in credentials and calls onAuthenticated', async () => { + const transport = makeTransport() + const onAuthenticated = vi.fn() + render() + + fireEvent.change(screen.getByLabelText('Email'), { target: { value: 'a@b.com' } }) + fireEvent.change(screen.getByLabelText('Password'), { target: { value: 'hunter2' } }) + fireEvent.click(screen.getByRole('button', { name: 'Sign In' })) + + await waitFor(() => + expect(transport.login).toHaveBeenCalledWith({ email: 'a@b.com', password: 'hunter2' }), + ) + expect(onAuthenticated).toHaveBeenCalledWith(AUTHENTICATED) + }) + + it('submits signup with first/last name only in signup mode', async () => { + const transport = makeTransport() + const onAuthenticated = vi.fn() + render( + , + ) + + expect(screen.getByLabelText('First name')).toBeInTheDocument() + expect(screen.getByLabelText('Last name')).toBeInTheDocument() + + fireEvent.change(screen.getByLabelText('First name'), { target: { value: 'Ada' } }) + fireEvent.change(screen.getByLabelText('Last name'), { target: { value: 'Lovelace' } }) + fireEvent.change(screen.getByLabelText('Email'), { target: { value: 'ada@ex.com' } }) + fireEvent.change(screen.getByLabelText('Password'), { target: { value: 'S3cret!!!!' } }) + fireEvent.click(screen.getByRole('button', { name: 'Create account' })) + + await waitFor(() => + expect(transport.signup).toHaveBeenCalledWith({ + email: 'ada@ex.com', + password: 'S3cret!!!!', + firstName: 'Ada', + lastName: 'Lovelace', + }), + ) + expect(onAuthenticated).toHaveBeenCalledWith(AUTHENTICATED) + }) + + it('does not render first/last name fields in sign-in mode', () => { + render() + expect(screen.queryByLabelText('First name')).not.toBeInTheDocument() + expect(screen.queryByLabelText('Last name')).not.toBeInTheDocument() + }) + + it('surfaces an mfa_required result via onMfaRequired and a notice, without calling onAuthenticated', async () => { + const transport = makeTransport({ login: vi.fn().mockResolvedValue(MFA_CHALLENGE) }) + const onAuthenticated = vi.fn() + const onMfaRequired = vi.fn() + render( + , + ) + + fireEvent.change(screen.getByLabelText('Email'), { target: { value: 'a@b.com' } }) + fireEvent.change(screen.getByLabelText('Password'), { target: { value: 'hunter2' } }) + fireEvent.click(screen.getByRole('button', { name: 'Sign In' })) + + await waitFor(() => expect(onMfaRequired).toHaveBeenCalledWith(MFA_CHALLENGE)) + expect(onAuthenticated).not.toHaveBeenCalled() + expect(screen.getByRole('alert')).toHaveTextContent(/additional verification/i) + }) + + it('shows an error alert when login rejects', async () => { + const transport = makeTransport({ login: vi.fn().mockRejectedValue(new Error('Incorrect email or password')) }) + render() + + fireEvent.change(screen.getByLabelText('Email'), { target: { value: 'a@b.com' } }) + fireEvent.change(screen.getByLabelText('Password'), { target: { value: 'wrong' } }) + fireEvent.click(screen.getByRole('button', { name: 'Sign In' })) + + await waitFor(() => expect(screen.getByRole('alert')).toHaveTextContent('Incorrect email or password')) + }) + + it('hides the Google button when transport has no startSocial, even if methods advertise it', async () => { + const transport = makeTransport({ + getAuthMethods: vi.fn().mockResolvedValue(baseMethods({ social: ['google'] })), + }) + render() + await waitFor(() => expect(transport.getAuthMethods).toHaveBeenCalled()) + expect(screen.queryByRole('button', { name: /sign in with google/i })).not.toBeInTheDocument() + }) + + it('shows the Google button only when startSocial is present AND methods advertise google', async () => { + const transport = makeTransport({ + startSocial: vi.fn().mockResolvedValue(undefined), + getAuthMethods: vi.fn().mockResolvedValue(baseMethods({ social: ['google'] })), + }) + render() + await waitFor(() => + expect(screen.getByRole('button', { name: /sign in with google/i })).toBeInTheDocument(), + ) + + fireEvent.click(screen.getByRole('button', { name: /sign in with google/i })) + await waitFor(() => expect(transport.startSocial).toHaveBeenCalledWith('google')) + }) + + it('does not render the Google button when startSocial is present but methods do not advertise it', async () => { + const transport = makeTransport({ startSocial: vi.fn().mockResolvedValue(undefined) }) + render() + await waitFor(() => expect(transport.getAuthMethods).toHaveBeenCalled()) + expect(screen.queryByRole('button', { name: /sign in with google/i })).not.toBeInTheDocument() + }) + + it('toggles between sign-in and sign-up labels and clears the name fields context', async () => { + render() + expect(screen.getByRole('button', { name: 'Sign In' })).toBeInTheDocument() + + fireEvent.click(screen.getByRole('button', { name: 'Sign up' })) + expect(screen.getByRole('button', { name: 'Create account' })).toBeInTheDocument() + expect(screen.getByLabelText('First name')).toBeInTheDocument() + + fireEvent.click(screen.getByRole('button', { name: 'Back to sign in' })) + expect(screen.getByRole('button', { name: 'Sign In' })).toBeInTheDocument() + expect(screen.queryByLabelText('First name')).not.toBeInTheDocument() + }) + + it('shows per-action pending labels while a submit is in flight', async () => { + let resolveLogin: (v: AuthenticatedSession) => void = () => {} + const transport = makeTransport({ + login: vi.fn(() => new Promise((resolve) => { resolveLogin = resolve })), + }) + render() + + fireEvent.change(screen.getByLabelText('Email'), { target: { value: 'a@b.com' } }) + fireEvent.change(screen.getByLabelText('Password'), { target: { value: 'hunter2' } }) + fireEvent.click(screen.getByRole('button', { name: 'Sign In' })) + + expect(await screen.findByRole('button', { name: 'Signing in…' })).toBeDisabled() + resolveLogin(AUTHENTICATED) + await waitFor(() => expect(screen.getByRole('button', { name: 'Sign In' })).not.toBeDisabled()) + }) + + it('wraps in a CenteredCard for variant="full" (default)', () => { + const { container } = render() + expect(container.querySelector('.fzf-auth-panel')).toBeInTheDocument() + // CenteredCard renders a full-viewport flex wrapper around the card. + expect(container.firstElementChild?.tagName).toBe('DIV') + expect((container.firstElementChild as HTMLElement).style.minHeight).toBe('100vh') + }) + + it('applies label overrides', () => { + render( + , + ) + expect(screen.getByRole('button', { name: 'Enter' })).toBeInTheDocument() + }) +}) diff --git a/packages/auth-ui/src/vanilla/mount.test.ts b/packages/auth-ui/src/vanilla/mount.test.ts new file mode 100644 index 00000000..b92182bc --- /dev/null +++ b/packages/auth-ui/src/vanilla/mount.test.ts @@ -0,0 +1,96 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' +import { mount } from './mount' +import type { AuthTransport, AuthenticatedSession } from '../types' + +const AUTHENTICATED: AuthenticatedSession = { + status: 'authenticated', + token: 'tok-123', + user: { id: 'u1' }, +} + +function makeTransport(overrides: Partial = {}): AuthTransport { + return { + login: vi.fn().mockResolvedValue(AUTHENTICATED), + signup: vi.fn().mockResolvedValue(AUTHENTICATED), + getAuthMethods: vi.fn().mockResolvedValue({ + password: true, + social: [], + mfa: { enabled: false, types: [] }, + verification: { email: false, sms: false }, + }), + ...overrides, + } +} + +describe('vanilla mount()', () => { + let container: HTMLDivElement + + beforeEach(() => { + container = document.createElement('div') + document.body.appendChild(container) + }) + + it('renders email/password inputs and a submit button', () => { + mount(container, { transport: makeTransport(), onAuthenticated: vi.fn() }) + expect(container.querySelector('#fzf-auth-vanilla-email')).toBeTruthy() + expect(container.querySelector('#fzf-auth-vanilla-password')).toBeTruthy() + expect(container.querySelector('button[type="submit"]')?.textContent).toBe('Sign In') + }) + + it('calls transport.login on submit and onAuthenticated with the result', async () => { + const transport = makeTransport() + const onAuthenticated = vi.fn() + mount(container, { transport, onAuthenticated }) + + const email = container.querySelector('#fzf-auth-vanilla-email')! + const password = container.querySelector('#fzf-auth-vanilla-password')! + email.value = 'a@b.com' + password.value = 'hunter2' + + const form = container.querySelector('form')! + form.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true })) + + await new Promise((r) => setTimeout(r, 0)) + expect(transport.login).toHaveBeenCalledWith({ email: 'a@b.com', password: 'hunter2' }) + expect(onAuthenticated).toHaveBeenCalledWith(AUTHENTICATED) + }) + + it('defaults social to OFF even when startSocial is provided', async () => { + const transport = makeTransport({ + startSocial: vi.fn().mockResolvedValue(undefined), + getAuthMethods: vi.fn().mockResolvedValue({ + password: true, + social: ['google'], + mfa: { enabled: false, types: [] }, + verification: { email: false, sms: false }, + }), + }) + mount(container, { transport, onAuthenticated: vi.fn() }) + await new Promise((r) => setTimeout(r, 0)) + const socialWrap = container.querySelector('.fzf-auth-panel__social') as HTMLElement + expect(socialWrap.style.display).toBe('none') + }) + + it('renders the Google button when social: true is explicitly opted in', async () => { + const transport = makeTransport({ + startSocial: vi.fn().mockResolvedValue(undefined), + getAuthMethods: vi.fn().mockResolvedValue({ + password: true, + social: ['google'], + mfa: { enabled: false, types: [] }, + verification: { email: false, sms: false }, + }), + }) + mount(container, { transport, onAuthenticated: vi.fn(), social: true }) + await new Promise((r) => setTimeout(r, 0)) + const socialWrap = container.querySelector('.fzf-auth-panel__social') as HTMLElement + expect(socialWrap.style.display).toBe('block') + }) + + it('unmount() removes the rendered markup', () => { + const handle = mount(container, { transport: makeTransport(), onAuthenticated: vi.fn() }) + expect(container.querySelector('.fzf-auth-panel')).toBeTruthy() + handle.unmount() + expect(container.querySelector('.fzf-auth-panel')).toBeFalsy() + }) +}) From cfc2760135c2c1434b9306662889ae9bcd9fa005 Mon Sep 17 00:00:00 2001 From: "fuzeone-bot[bot]" Date: Thu, 30 Jul 2026 00:21:41 +0300 Subject: [PATCH 6/8] ci(auth-ui,design-system): add owner-scope alias-publish workflows Mirrors .github/workflows/security-packages-publish.yml: idempotent, owner-gated (izzywdev), no git push/tag. Adds packages/auth-ui to the root workspaces list. Co-Authored-By: Claude Opus 4.8 Claude-Session-Id: 548a2d55-e1cd-4b5e-bfc4-b6e102bf4695 --- .../workflows/auth-ui-packages-publish.yml | 73 +++++++++++++++++++ .../design-system-packages-publish.yml | 73 +++++++++++++++++++ package.json | 1 + 3 files changed, 147 insertions(+) create mode 100644 .github/workflows/auth-ui-packages-publish.yml create mode 100644 .github/workflows/design-system-packages-publish.yml diff --git a/.github/workflows/auth-ui-packages-publish.yml b/.github/workflows/auth-ui-packages-publish.yml new file mode 100644 index 00000000..004a6497 --- /dev/null +++ b/.github/workflows/auth-ui-packages-publish.yml @@ -0,0 +1,73 @@ +# Publish the auth-ui package to GitHub Packages under the @izzywdev scope. +# +# GitHub Packages requires the npm scope to match the repository owner, so the +# canonical @fuzefront/auth-ui name cannot publish until the org transfer +# completes (see packages-publish.yml, which stays the long-term path and no-ops +# until then). Consuming apps need auth-ui TODAY, so this workflow publishes the +# same build under an owner-scoped alias name: +# +# @fuzefront/auth-ui -> @izzywdev/fuzefront-auth-ui +# +# Consumers install via an npm alias so their imports keep the canonical name: +# +# "@fuzefront/auth-ui": "npm:@izzywdev/fuzefront-auth-ui@^0.1.0" +# +# Once the org transfer lands and packages-publish.yml activates, consumers drop +# the alias and this workflow is deleted. Publishing is idempotent: a version that +# already exists in the registry is skipped, not overwritten. No git push / tag is +# made, so master's required_signatures protection is never involved. +name: Publish auth-ui (alias scope) + +on: + workflow_dispatch: + push: + branches: [master] + paths: + - 'packages/auth-ui/**' + +concurrency: + group: auth-ui-packages-publish + cancel-in-progress: false + +jobs: + publish: + if: github.repository_owner == 'izzywdev' + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + with: + node-version: '24.x' + registry-url: 'https://npm.pkg.github.com' + scope: '@izzywdev' + + - name: Build the design-system dependency + working-directory: design-system + run: npm install --workspaces=false --no-audit --no-fund && npm run build + + - name: Build the security-client dependency (types only) + working-directory: packages/security + run: npm install --workspaces=false --no-audit --no-fund && npm run build + + - name: Build auth-ui + working-directory: packages/auth-ui + run: | + npm install --workspaces=false --no-audit --no-fund + npm run build + + - name: Publish @izzywdev/fuzefront-auth-ui + working-directory: packages/auth-ui + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + VERSION=$(npm pkg get version | tr -d '"') + npm pkg set name=@izzywdev/fuzefront-auth-ui + if npm view "@izzywdev/fuzefront-auth-ui@${VERSION}" version --registry=https://npm.pkg.github.com >/dev/null 2>&1; then + echo "@izzywdev/fuzefront-auth-ui@${VERSION} already published — skipping." + else + npm publish --registry=https://npm.pkg.github.com + fi diff --git a/.github/workflows/design-system-packages-publish.yml b/.github/workflows/design-system-packages-publish.yml new file mode 100644 index 00000000..b3ee033f --- /dev/null +++ b/.github/workflows/design-system-packages-publish.yml @@ -0,0 +1,73 @@ +# Publish the design system to GitHub Packages under the @izzywdev scope. +# +# GitHub Packages requires the npm scope to match the repository owner, so the +# canonical @fuzefront/design-system name cannot publish until the org transfer +# completes (see packages-publish.yml, which stays the long-term path and no-ops +# until then). Consuming apps need the design system TODAY, so this workflow +# publishes the same build under an owner-scoped alias name: +# +# @fuzefront/design-system -> @izzywdev/fuzefront-design-system +# +# Consumers install via an npm alias so their imports keep the canonical name: +# +# "@fuzefront/design-system": "npm:@izzywdev/fuzefront-design-system@^1.0.0" +# +# Unlike packages/security (a tsup dist/ build), design-system has no bundler — +# `node build.mjs` (re)generates index.js / index.d.ts / _ds_manifest.json in +# place from the components/tokens/guidelines folders, and `package.json` +# "files" ships those plus components/ and tokens/ directly (CSS-only +# consumption of `./styles.css` and `./tokens/*`, no bundler required by +# consumers). This workflow keeps that shape faithfully — it does not +# restructure the design system into a dist/ layout. +# +# Once the org transfer lands and packages-publish.yml activates, consumers drop +# the alias and this workflow is deleted. Publishing is idempotent: a version that +# already exists in the registry is skipped, not overwritten. No git push / tag is +# made, so master's required_signatures protection is never involved. +name: Publish design system (alias scope) + +on: + workflow_dispatch: + push: + branches: [master] + paths: + - 'design-system/**' + +concurrency: + group: design-system-packages-publish + cancel-in-progress: false + +jobs: + publish: + if: github.repository_owner == 'izzywdev' + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + with: + node-version: '24.x' + registry-url: 'https://npm.pkg.github.com' + scope: '@izzywdev' + + - name: Build design system + working-directory: design-system + run: | + npm install --workspaces=false --no-audit --no-fund + npm run build + + - name: Publish @izzywdev/fuzefront-design-system + working-directory: design-system + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + VERSION=$(npm pkg get version | tr -d '"') + npm pkg set name=@izzywdev/fuzefront-design-system + if npm view "@izzywdev/fuzefront-design-system@${VERSION}" version --registry=https://npm.pkg.github.com >/dev/null 2>&1; then + echo "@izzywdev/fuzefront-design-system@${VERSION} already published — skipping." + else + npm publish --registry=https://npm.pkg.github.com + fi diff --git a/package.json b/package.json index 1f2c1d66..7aca831b 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "packages/chat-client", "packages/chat-ui", "packages/identity-ui", + "packages/auth-ui", "packages/account-security-ui", "packages/portal-branding-ui", "portal-client", From 1dd6d2b5c0991d9806c7d9ef1220c754f8d2ff3f Mon Sep 17 00:00:00 2001 From: "fuzeone-bot[bot]" Date: Thu, 30 Jul 2026 00:40:32 +0300 Subject: [PATCH 7/8] fix(auth-ui): sync package-lock for new @fuzefront/auth-ui workspace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI runs `npm ci`, which requires package-lock.json to be in sync. The new package's devDeps (esbuild, vite, vitest, jsdom) were never added to the root lock, so `npm ci` failed at install — cascading to every downstream gate (frontend-build, unit tests, audit). Regenerated with `npm install --package-lock-only` (metadata only; no native-binary fetch, so unaffected by the os=linux .npmrc pin). Co-Authored-By: Claude Opus 4.8 Claude-Session-Id: 548a2d55-e1cd-4b5e-bfc4-b6e102bf4695 --- package-lock.json | 2158 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 1922 insertions(+), 236 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7e040087..6f3d1875 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "packages/chat-client", "packages/chat-ui", "packages/identity-ui", + "packages/auth-ui", "packages/account-security-ui", "packages/portal-branding-ui", "portal-client", @@ -596,16 +597,6 @@ "pretty-format": "^29.0.0" } }, - "billing-client/node_modules/@types/node": { - "version": "18.19.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.0.tgz", - "integrity": "sha512-667KNhaD7U29mT5wf+TZUnrzPrlL2GNQ5N0BMjO2oNULhBxX0/FKCkm6JMu0Jh7Z+1LwUlR21ekd7KhIboNFNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, "billing-client/node_modules/glob": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", @@ -2972,6 +2963,7 @@ "os": [ "aix" ], + "peer": true, "engines": { "node": ">=18" } @@ -2989,6 +2981,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=18" } @@ -3006,6 +2999,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=18" } @@ -3023,6 +3017,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=18" } @@ -3040,6 +3035,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=18" } @@ -3057,6 +3053,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=18" } @@ -3074,6 +3071,7 @@ "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">=18" } @@ -3091,6 +3089,7 @@ "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">=18" } @@ -3108,6 +3107,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -3125,6 +3125,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -3142,6 +3143,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -3159,6 +3161,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -3176,6 +3179,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -3193,6 +3197,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -3210,6 +3215,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -3227,6 +3233,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -3244,6 +3251,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } @@ -3261,6 +3269,7 @@ "os": [ "netbsd" ], + "peer": true, "engines": { "node": ">=18" } @@ -3278,6 +3287,7 @@ "os": [ "netbsd" ], + "peer": true, "engines": { "node": ">=18" } @@ -3295,6 +3305,7 @@ "os": [ "openbsd" ], + "peer": true, "engines": { "node": ">=18" } @@ -3312,6 +3323,7 @@ "os": [ "openbsd" ], + "peer": true, "engines": { "node": ">=18" } @@ -3329,6 +3341,7 @@ "os": [ "openharmony" ], + "peer": true, "engines": { "node": ">=18" } @@ -3346,6 +3359,7 @@ "os": [ "sunos" ], + "peer": true, "engines": { "node": ">=18" } @@ -3363,6 +3377,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=18" } @@ -3380,6 +3395,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=18" } @@ -3397,6 +3413,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=18" } @@ -3554,6 +3571,10 @@ "resolved": "backend/applications", "link": true }, + "node_modules/@fuzefront/auth-ui": { + "resolved": "packages/auth-ui", + "link": true + }, "node_modules/@fuzefront/backend": { "resolved": "backend", "link": true @@ -20449,13 +20470,6 @@ "node": ">=20.18.1" } }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true, - "license": "MIT" - }, "node_modules/unenv": { "version": "2.0.0-rc.24", "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", @@ -24398,192 +24412,1934 @@ } } }, - "packages/billing-ui": { - "name": "@fuzefront/billing-ui", - "version": "1.0.0", - "license": "UNLICENSED", + "packages/auth-ui": { + "name": "@fuzefront/auth-ui", + "version": "0.1.0", "devDependencies": { - "@fuzefront/billing-client": "file:../../billing-client", - "@stripe/react-stripe-js": "^3.10.0", - "@stripe/stripe-js": "^3.5.0", - "@testing-library/jest-dom": "^6.4.2", + "@fuzefront/design-system": "1.0.0", + "@fuzefront/security-client": "0.2.0", + "@testing-library/jest-dom": "^6.4.0", "@testing-library/react": "^16.3.2", - "@testing-library/user-event": "^14.5.2", + "@testing-library/user-event": "^14.5.0", "@types/react": "^19.2.0", "@types/react-dom": "^19.2.0", - "@vitejs/plugin-react": "^4.3.1", - "jsdom": "^24.0.0", + "@vitejs/plugin-react": "^4.3.0", + "esbuild": "^0.24.0", + "jsdom": "^25.0.0", "react": "^19.2.0", "react-dom": "^19.2.0", - "tsup": "^8.0.2", - "typescript": "5.1.6", - "vitest": "^1.6.0" + "typescript": "^5.5.0", + "vite": "^5.4.0", + "vite-plugin-dts": "^4.0.0", + "vitest": "^2.1.0" }, "peerDependencies": { - "@fuzefront/billing-client": "^1.0.0", - "@stripe/react-stripe-js": "^3.10.0", - "@stripe/stripe-js": "^3.5.0", + "@fuzefront/design-system": "^1.0.0", "react": "^19.0.0", "react-dom": "^19.0.0" } }, - "packages/billing-ui/node_modules/typescript": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", - "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "packages/auth-ui/node_modules/@esbuild/aix-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=14.17" + "node": ">=18" } }, - "packages/chat-client": { - "name": "@fuzefront/chat-client", - "version": "1.1.0", + "packages/auth-ui/node_modules/@esbuild/android-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "dependencies": { - "eventsource-parser": "^1.1.2" - }, - "devDependencies": { - "@types/jest": "^29.5.12", - "@types/node": "^24.13.3", - "jest": "29.7.0", - "ts-jest": "29.1.1", - "tsup": "^8.0.2", - "typescript": "5.1.6" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "packages/chat-client/node_modules/@types/node": { - "version": "18.19.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.0.tgz", - "integrity": "sha512-667KNhaD7U29mT5wf+TZUnrzPrlL2GNQ5N0BMjO2oNULhBxX0/FKCkm6JMu0Jh7Z+1LwUlR21ekd7KhIboNFNw==", + "packages/auth-ui/node_modules/@esbuild/android-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "packages/chat-client/node_modules/ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "packages/auth-ui/node_modules/@esbuild/android-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" - }, - "bin": { - "ts-jest": "cli.js" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", - "typescript": ">=4.3 <6" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } + "node": ">=18" } }, - "packages/chat-client/node_modules/typescript": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", - "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "packages/auth-ui/node_modules/@esbuild/darwin-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14.17" + "node": ">=18" } }, - "packages/chat-ui": { - "name": "@fuzefront/chat-ui", - "version": "1.1.0", + "packages/auth-ui/node_modules/@esbuild/darwin-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "devDependencies": { - "@fuzefront/chat-client": "file:../chat-client", - "@testing-library/jest-dom": "^6.4.2", - "@testing-library/react": "^16.3.2", - "@testing-library/user-event": "^14.5.2", - "@types/react": "^19.2.0", - "@types/react-dom": "^19.2.0", - "@vitejs/plugin-react": "^4.3.1", - "jsdom": "^24.0.0", - "react": "^19.2.0", - "react-dom": "^19.2.0", - "tsup": "^8.0.2", - "typescript": "5.1.6", - "vitest": "^1.6.0" - }, - "peerDependencies": { - "@fuzefront/chat-client": "^1.1.0", - "react": "^19.0.0", - "react-dom": "^19.0.0" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" } }, - "packages/chat-ui/node_modules/typescript": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", - "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "packages/auth-ui/node_modules/@esbuild/freebsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=14.17" - } - }, - "packages/feature-flags": { - "name": "@fuzefront/feature-flags", - "version": "1.0.0", - "license": "UNLICENSED", - "dependencies": { - "@openfeature/server-sdk": "^1.18.0", - "@openfeature/web-sdk": "^1.5.0", - "unleash-client": "^6.11.1" - }, - "devDependencies": { - "@types/jest": "29.5.12", - "@types/node": "^24.13.3", - "jest": "29.7.0", - "rimraf": "^5.0.1", - "ts-jest": "29.1.1", - "tsup": "^8.0.2", - "typescript": "5.1.6" - }, - "optionalDependencies": { - "@openfeature/unleash-web-provider": "^0.1.1" + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/freebsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/linux-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/linux-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/linux-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/linux-loong64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/linux-mips64el": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/linux-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/linux-riscv64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/linux-s390x": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/linux-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", + "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/netbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", + "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/netbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/openbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/sunos-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/win32-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/win32-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@esbuild/win32-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.3.tgz", + "integrity": "sha512-c0wdcekXtQvvn5Tsrk/+op/gUArrbWaFduBnTLP2l1cKLSQs4diMWjJw3m6A0DdzT8dAAX95KpkJ3qynCePbmw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.3.tgz", + "integrity": "sha512-3YjElDdWN+qXAFbJ/CzPV+0wspLqh54k/I6GfdYtEJRqg7buSgc1yPM3B+93j1M4neobtkATHZTmxK2AMVGfnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.3.tgz", + "integrity": "sha512-Pch2pFNOxxz1hTjypIdPyRTR6riiwRl84+VcN9djS680fw+Co1nAJINrdpqp7KV0NvyuU8ilZXZCjd7ykJl1GQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.3.tgz", + "integrity": "sha512-LEuncFUHFiF8t4yZVZvvZA1wk0pjAscRnsrn1EfTEmN4HXotBi2YtcnLRyaK6UbuczW7xZS5ES+81Rdz8Z0T6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.3.tgz", + "integrity": "sha512-zvBUvsQUpOWALdDsk6qbS8bXf2VxmPisuudNDrY7x0p0jBdsoZl8HsHczIOgkQiZldmcacMKtBzpoGVNeIe2bQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.3.tgz", + "integrity": "sha512-C2KmNrcSem/AMg984H/dev+si0lieQGdXdR/lYGJnuumXnFb9Y7QdiI62obFdLlxRYLBv4P0eUVIDbD4c1vVvw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.3.tgz", + "integrity": "sha512-ggXnsTAEzNQx74XpunRsiZ9aBZDsI7XIa0hm2nzR9f4WzH5/f/d73ZSDaC5ejJ8YLY4NW+V3wr0tjOaeCq8hqA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.3.tgz", + "integrity": "sha512-2vng+FlzNUhKZxtej3IUqJgbZoQk2M/dwQM20+ULV0R/E/8tr9/P6uEf2iiGIk4HL0zMKh5Jry7mUHdUOvyGgA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.3.tgz", + "integrity": "sha512-LLLFZKt4/Nraf9rxDkhiU8QVgLF4WmCkfr0L4fj0fPfIZFBib0DeiFk1hhaYKd03LFAFJcxHslhDFlNJLylf5Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.3.tgz", + "integrity": "sha512-WJkdQCvS9sWNOUBJZfQRKpZGFBztRzcowI+nndmflKgU4XY+3a420FgTOSKTsVqJbnzSxeT4vaJalpOaPo2YCQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.3.tgz", + "integrity": "sha512-PwHXCCS2n64/1Ot6rP1YEYA02MGYBcQlr8CSZZyrUG2O7NH6NklYmvr9v3Jy+5e/eDeNchc/ukmKJi9LuflMIQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.3.tgz", + "integrity": "sha512-vUjxINQu3RC8NZS3ykk1gN65gIz8pAopOq2HXuZhiIxHdx7TFvDG+jgrdSgInu1Eza4/Rfi2VzZgyIgEH4WOaw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.3.tgz", + "integrity": "sha512-wzko4aJ13+0G3kGnviCg5gnXFKd40izKsrf2uOw12US4XqprkDrmwOpeW14aSNa37V8bfPcz5Fkob6LZ3BAPmA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.3.tgz", + "integrity": "sha512-8120ue0JUMSwy11stlwnfdX3pPd+WZYGCDBwEHWtIHi6pOpZmsEF5QKB7a/UN+XFdqvobxz98kv8RTqikyCEBw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.3.tgz", + "integrity": "sha512-XLFHnR3tXMjbOCh2vtVJHmxt+995uJsTERQyseFDRA0xxMxyTZPLa3OIUlyFaO4mF/Lu0FjmWHCuPXJT1n/IOg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.3.tgz", + "integrity": "sha512-se6yXvNGMIl0f+RQzyh7XAmia8/9kplQx424wnG2w0C1oi6XgO6Y8otKhdXFHbHs88Ihavzmvh1NWjuovE76BQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.3.tgz", + "integrity": "sha512-gNoxRefktVIiGflpONuxWWXZAzIQG++z9qHO3xKwk4WdDMuQja3JHGfE1u0i3PfPDyvhypdk+WrgIJqLhGG7sg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.3.tgz", + "integrity": "sha512-V4KtWtQfAFMU7+9/A/VDps/VI8CHd3cYz0L8sgJzz8qK7eY7wI4ruFD82UYIYvW9Z4DtlTfhQcsl4XyPHW5uSg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.3.tgz", + "integrity": "sha512-LBx9LYXvj2CBkMkjLdNAWLwH0MLMin7do2VcVo9kVPibGLkY0BQQut2fv7NVqkXqZ/CrAu9LqDHVV1xHCMpCPw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.3.tgz", + "integrity": "sha512-ABVf3Q0RCu7NcyCCOZQI0pJ3GuSdfSl8EXcy88QtdceIMIoCUdfhsJChZ64L9zVM2aJHjde1Bhn5uqSRcX9ySA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.3.tgz", + "integrity": "sha512-+2Cy/ldweGBLlPIKsQLF8U5N44a0KDdbrk1rAjHOM9M2K+kGdIVjHLmmrZIcx+9Ny3ke/1JomCsDI1ocb11+sg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.3.tgz", + "integrity": "sha512-dtZvzc8BedpSaFNy75x6uiWwAGTH+aZHDtdrqP6qk+WcLJrfti6sGje1ZJ9UxyzDLF23d/mV+PaMwuC0hL7UVA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.3.tgz", + "integrity": "sha512-Rj8Ra4noo+aYy7sKBggCx0407mws34kAb1ySyWuq5DAtFBQdkSwnsjCgPrhPe9cvgBKZIukpE+CVHvORCS93kQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.3.tgz", + "integrity": "sha512-vp7N084ew/odXn2gi/mzm9mUkQu9l6AiN6dt4IeUM2Uvm9o+cVmP+YkqbMOteLbiGgqBBlJZjIMYVCfOOIVbVQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "packages/auth-ui/node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.3.tgz", + "integrity": "sha512-MOG/3gTOn4Fwf574RVOaY61I5o6P90legkFADiTyn1hyjNydT+cerU2rLUwPdZkKKyJ+iT+K9p7WXK4LM1Ka6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "packages/auth-ui/node_modules/@vitest/expect": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", + "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", + "chai": "^5.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/auth-ui/node_modules/@vitest/pretty-format": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", + "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/auth-ui/node_modules/@vitest/runner": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz", + "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "2.1.9", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/auth-ui/node_modules/@vitest/snapshot": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", + "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "magic-string": "^0.30.12", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/auth-ui/node_modules/@vitest/spy": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", + "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/auth-ui/node_modules/@vitest/utils": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", + "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "loupe": "^3.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/auth-ui/node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "packages/auth-ui/node_modules/check-error": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, + "packages/auth-ui/node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "packages/auth-ui/node_modules/esbuild": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" + } + }, + "packages/auth-ui/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "packages/auth-ui/node_modules/jsdom": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.1.0", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "packages/auth-ui/node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, + "packages/auth-ui/node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "packages/auth-ui/node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, + "packages/auth-ui/node_modules/rollup": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.3.tgz", + "integrity": "sha512-Gu0c0iH9FzgX1L1t7ByIbbS3Vmdz+6KHm/EsqmmC71gUQ82yvZRkTK6XzrFObSka91WUVdynqp6nsfilzr5k6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.3", + "@rollup/rollup-android-arm64": "4.62.3", + "@rollup/rollup-darwin-arm64": "4.62.3", + "@rollup/rollup-darwin-x64": "4.62.3", + "@rollup/rollup-freebsd-arm64": "4.62.3", + "@rollup/rollup-freebsd-x64": "4.62.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.3", + "@rollup/rollup-linux-arm-musleabihf": "4.62.3", + "@rollup/rollup-linux-arm64-gnu": "4.62.3", + "@rollup/rollup-linux-arm64-musl": "4.62.3", + "@rollup/rollup-linux-loong64-gnu": "4.62.3", + "@rollup/rollup-linux-loong64-musl": "4.62.3", + "@rollup/rollup-linux-ppc64-gnu": "4.62.3", + "@rollup/rollup-linux-ppc64-musl": "4.62.3", + "@rollup/rollup-linux-riscv64-gnu": "4.62.3", + "@rollup/rollup-linux-riscv64-musl": "4.62.3", + "@rollup/rollup-linux-s390x-gnu": "4.62.3", + "@rollup/rollup-linux-x64-gnu": "4.62.3", + "@rollup/rollup-linux-x64-musl": "4.62.3", + "@rollup/rollup-openbsd-x64": "4.62.3", + "@rollup/rollup-openharmony-arm64": "4.62.3", + "@rollup/rollup-win32-arm64-msvc": "4.62.3", + "@rollup/rollup-win32-ia32-msvc": "4.62.3", + "@rollup/rollup-win32-x64-gnu": "4.62.3", + "@rollup/rollup-win32-x64-msvc": "4.62.3", + "fsevents": "~2.3.2" + } + }, + "packages/auth-ui/node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "packages/auth-ui/node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "packages/auth-ui/node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "packages/auth-ui/node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "packages/auth-ui/node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "packages/auth-ui/node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "packages/auth-ui/node_modules/vite-node": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", + "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.7", + "es-module-lexer": "^1.5.4", + "pathe": "^1.1.2", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "packages/auth-ui/node_modules/vite/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "packages/auth-ui/node_modules/vitest": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", + "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "2.1.9", + "@vitest/mocker": "2.1.9", + "@vitest/pretty-format": "^2.1.9", + "@vitest/runner": "2.1.9", + "@vitest/snapshot": "2.1.9", + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", + "chai": "^5.1.2", + "debug": "^4.3.7", + "expect-type": "^1.1.0", + "magic-string": "^0.30.12", + "pathe": "^1.1.2", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.1", + "tinypool": "^1.0.1", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0", + "vite-node": "2.1.9", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.1.9", + "@vitest/ui": "2.1.9", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "packages/auth-ui/node_modules/vitest/node_modules/@vitest/mocker": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", + "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.9", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.12" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "packages/billing-ui": { + "name": "@fuzefront/billing-ui", + "version": "1.0.0", + "license": "UNLICENSED", + "devDependencies": { + "@fuzefront/billing-client": "file:../../billing-client", + "@stripe/react-stripe-js": "^3.10.0", + "@stripe/stripe-js": "^3.5.0", + "@testing-library/jest-dom": "^6.4.2", + "@testing-library/react": "^16.3.2", + "@testing-library/user-event": "^14.5.2", + "@types/react": "^19.2.0", + "@types/react-dom": "^19.2.0", + "@vitejs/plugin-react": "^4.3.1", + "jsdom": "^24.0.0", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "tsup": "^8.0.2", + "typescript": "5.1.6", + "vitest": "^1.6.0" + }, + "peerDependencies": { + "@fuzefront/billing-client": "^1.0.0", + "@stripe/react-stripe-js": "^3.10.0", + "@stripe/stripe-js": "^3.5.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + } + }, + "packages/billing-ui/node_modules/typescript": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/chat-client": { + "name": "@fuzefront/chat-client", + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "eventsource-parser": "^1.1.2" + }, + "devDependencies": { + "@types/jest": "^29.5.12", + "@types/node": "^24.13.3", + "jest": "29.7.0", + "ts-jest": "29.1.1", + "tsup": "^8.0.2", + "typescript": "5.1.6" + } + }, + "packages/chat-client/node_modules/ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "packages/chat-client/node_modules/typescript": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/chat-ui": { + "name": "@fuzefront/chat-ui", + "version": "1.1.0", + "license": "MIT", + "devDependencies": { + "@fuzefront/chat-client": "file:../chat-client", + "@testing-library/jest-dom": "^6.4.2", + "@testing-library/react": "^16.3.2", + "@testing-library/user-event": "^14.5.2", + "@types/react": "^19.2.0", + "@types/react-dom": "^19.2.0", + "@vitejs/plugin-react": "^4.3.1", + "jsdom": "^24.0.0", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "tsup": "^8.0.2", + "typescript": "5.1.6", + "vitest": "^1.6.0" + }, + "peerDependencies": { + "@fuzefront/chat-client": "^1.1.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + } + }, + "packages/chat-ui/node_modules/typescript": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/feature-flags": { + "name": "@fuzefront/feature-flags", + "version": "1.0.0", + "license": "UNLICENSED", + "dependencies": { + "@openfeature/server-sdk": "^1.18.0", + "@openfeature/web-sdk": "^1.5.0", + "unleash-client": "^6.11.1" + }, + "devDependencies": { + "@types/jest": "29.5.12", + "@types/node": "^24.13.3", + "jest": "29.7.0", + "rimraf": "^5.0.1", + "ts-jest": "29.1.1", + "tsup": "^8.0.2", + "typescript": "5.1.6" + }, + "optionalDependencies": { + "@openfeature/unleash-web-provider": "^0.1.1" } }, "packages/feature-flags/node_modules/@types/jest": { @@ -24597,16 +26353,6 @@ "pretty-format": "^29.0.0" } }, - "packages/feature-flags/node_modules/@types/node": { - "version": "18.19.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.0.tgz", - "integrity": "sha512-667KNhaD7U29mT5wf+TZUnrzPrlL2GNQ5N0BMjO2oNULhBxX0/FKCkm6JMu0Jh7Z+1LwUlR21ekd7KhIboNFNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, "packages/feature-flags/node_modules/glob": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", @@ -24766,16 +26512,6 @@ "vitest": "^3.2.4" } }, - "packages/i18n-translate/node_modules/@types/node": { - "version": "18.19.130", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", - "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, "packages/i18n-translate/node_modules/@vitest/expect": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.6.tgz", @@ -27762,16 +29498,6 @@ "typescript": "5.1.6" } }, - "packages/security/node_modules/@types/node": { - "version": "18.19.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.0.tgz", - "integrity": "sha512-667KNhaD7U29mT5wf+TZUnrzPrlL2GNQ5N0BMjO2oNULhBxX0/FKCkm6JMu0Jh7Z+1LwUlR21ekd7KhIboNFNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, "packages/security/node_modules/typescript": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", @@ -27802,16 +29528,6 @@ "typescript": "5.1.6" } }, - "portal-client/node_modules/@types/node": { - "version": "18.19.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.0.tgz", - "integrity": "sha512-667KNhaD7U29mT5wf+TZUnrzPrlL2GNQ5N0BMjO2oNULhBxX0/FKCkm6JMu0Jh7Z+1LwUlR21ekd7KhIboNFNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, "portal-client/node_modules/glob": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", @@ -27909,16 +29625,6 @@ "typescript": "5.1.6" } }, - "services/chat-service/node_modules/@types/node": { - "version": "18.19.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.0.tgz", - "integrity": "sha512-667KNhaD7U29mT5wf+TZUnrzPrlL2GNQ5N0BMjO2oNULhBxX0/FKCkm6JMu0Jh7Z+1LwUlR21ekd7KhIboNFNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, "services/chat-service/node_modules/@types/supertest": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", @@ -28320,16 +30026,6 @@ "uuid": "9.0.1" } }, - "services/email-service/node_modules/@types/node": { - "version": "18.19.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.0.tgz", - "integrity": "sha512-667KNhaD7U29mT5wf+TZUnrzPrlL2GNQ5N0BMjO2oNULhBxX0/FKCkm6JMu0Jh7Z+1LwUlR21ekd7KhIboNFNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, "services/email-service/node_modules/@types/supertest": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", @@ -28744,16 +30440,6 @@ "pretty-format": "^29.0.0" } }, - "shared/node_modules/@types/node": { - "version": "18.19.130", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", - "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, "shared/node_modules/ts-jest": { "version": "29.1.1", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", From 0633b5e8cd3f9f339008d827e250bebbc2711765 Mon Sep 17 00:00:00 2001 From: "fuzeone-bot[bot]" Date: Thu, 30 Jul 2026 01:21:04 +0300 Subject: [PATCH 8/8] fix(chat-service): infer readdir Dirent type (survive @types/node 24) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collateral from this PR's lockfile update: regenerating package-lock.json deduped @types/node, so chat-service now resolves 24.x, where `Dirent` became generic. The annotation `Awaited>` selected the Buffer overload, typing `entry.name` as Buffer and breaking `.startsWith` / `.toLowerCase` (index-docs.ts type-check, TS2322/2345/2367/2339). Drop the fragile annotation and infer the element type from the default (utf8) readdir call → Dirent. Version-robust (compiles under @types/node 18 and 24) and behavior-identical. Verified locally: the index-docs Dirent errors are gone (remaining local tsc noise is this worktree's partial install, absent in CI). Co-Authored-By: Claude Opus 4.8 Claude-Session-Id: 548a2d55-e1cd-4b5e-bfc4-b6e102bf4695 --- services/chat-service/src/rag/index-docs.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/services/chat-service/src/rag/index-docs.ts b/services/chat-service/src/rag/index-docs.ts index c6e0b2f1..e28492ec 100644 --- a/services/chat-service/src/rag/index-docs.ts +++ b/services/chat-service/src/rag/index-docs.ts @@ -21,12 +21,11 @@ import { GLOBAL_DOCS_COLLECTION } from '../rag/retriever'; /** Recursively collect Markdown files under `dir`. */ async function collectMarkdown(dir: string): Promise { const out: string[] = []; - let entries: Awaited>; - try { - entries = await fs.readdir(dir, { withFileTypes: true }); - } catch { - return out; - } + // Infer the element type from the call rather than annotating with + // `Awaited>` — that resolves to readdir's Buffer + // overload under @types/node 24 (Dirent became generic), typing entry.name as + // Buffer. Inferring from the default (utf8) call yields Dirent. + const entries = await fs.readdir(dir, { withFileTypes: true }).catch(() => []); for (const entry of entries) { const full = path.join(dir, entry.name); if (entry.isDirectory()) {