mirror of
https://github.com/moeru-ai/airi.git
synced 2026-07-09 15:58:27 +00:00
fix(server): make analytics best-effort
Remove server-side PostHog wiring so request handlers no longer wait on third-party analytics delivery. Keep auth activity and product event writes best-effort so degraded analytics do not fail session creation. Signed-off-by: RainbowBird <git@luoling.moe> Commit-Message-Assisted-by: Codex (via Codex)
This commit is contained in:
parent
f6b53a37fa
commit
cf5ed0766b
15 changed files with 59 additions and 601 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# Metrics Ownership
|
||||
|
||||
这份文档定义 AIRI 团队的指标分层规则:什么指标该走 Grafana / Prometheus(OTel server-side),什么该走 PostHog(前后端混合 product analytics),同名指标怎么处理。落地这份是为了避免后期"同一个 KPI 三处不同数"的漂移。
|
||||
这份文档定义 AIRI 团队的指标分层规则:什么指标该走 Grafana / Prometheus(OTel server-side),什么该走 PostHog(frontend/external product analytics),同名指标怎么处理。落地这份是为了避免后期"同一个 KPI 三处不同数"的漂移。
|
||||
|
||||
## 总原则
|
||||
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
| 层 | 工具 | 关键属性 |
|
||||
|---|---|---|
|
||||
| **System / API observability** | Grafana Cloud + Prometheus + OTel | 系统健康、延迟、错误率、SRE on-call 告警 |
|
||||
| **Product analytics** | PostHog Cloud | 用户行为、漏斗、retention、cohort、A/B、feature adoption |
|
||||
| **Product analytics** | PostHog Cloud | 前端用户行为、漏斗、retention、cohort、A/B、feature adoption |
|
||||
| **Financial truth source** | Postgres (`flux_transaction` / Stripe webhook 持久化) | 收入与扣费 ledger,任何展示都视作近似 |
|
||||
| **LLM-native observability** | Langfuse Cloud(已接入:chat completion + TTS speech) | 逐条 prompt/completion trace、TTS text trace、token/字符用量、按 user/session 成本归因、eval。真实 staging HTTP E2E 与 model 定价匹配待做 |
|
||||
|
||||
|
|
@ -45,11 +45,11 @@
|
|||
|---|---|---|
|
||||
| 计费 ledger(每一分钱可审计) | **Postgres** | Grafana / PostHog 都视作近似展示,争议查 SQL |
|
||||
| HTTP / WS / DB / Stripe webhook **计数** | **Grafana**(OTel counter) | 系统事件,PostHog 看不到 |
|
||||
| 用户去重 DAU / WAU / retention | **PostHog** | 需要 distinctId 去重,session table 计数不准 |
|
||||
| 用户去重 DAU / WAU / retention | **Postgres → Grafana** for server truth; **PostHog** for frontend journey | Server 不直接发 PostHog;后端事实查 `product_events` / `user.last_seen_at` |
|
||||
| 收入展示(MRR / ARR / churn revenue) | **Postgres → 两边展示** | 真相在 Postgres,Grafana 取系统侧切片(panel-30),PostHog 取用户维度切片 |
|
||||
| LLM token / cost(聚合速率、按模型) | **Grafana**(OTel counter) | 系统侧聚合,SRE 视角 |
|
||||
| LLM 逐条 prompt / completion / TTS text / eval / 按 user-session 成本 | **Langfuse** | 已接入 chat completion + TTS speech,正文级 trace + eval |
|
||||
| 用户行为漏斗各步骤 | **PostHog**(必须) | 第一步通常是前端事件,Grafana 拿不到 |
|
||||
| 用户行为漏斗各步骤 | **PostHog** for frontend steps; **Postgres/Grafana** for server steps | Server-side facts 不在请求路径发 PostHog |
|
||||
|
||||
### Better Auth session table 与活跃用户
|
||||
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
| properties 用 `snake_case` | `{ plan_id, price_usd, checkout_session_id }` |
|
||||
| 跟外部系统串联的 ID 用原平台命名 | `stripe_customer_id`、`stripe_subscription_id`、`checkout_session_id` |
|
||||
|
||||
`distinctId` 在登录后必须调 `posthog.identify(userId)`,userId 用 Better Auth 的 user id(跟 server 里的 `c.get('user').id` 一致)。后端 `posthog-node` 上报支付事件时用 fallback 链 `userId` (`session.metadata.userId`) > `email` (`session.customer_email`) > `session.id`——第一项跟前端 `identify` 一致,PostHog person merge 在这里完成。前端 wiring 由 `useSharedAnalyticsStore.initialize()` 自动处理,不需要每个 caller 手动 identify。
|
||||
`distinctId` 在登录后必须调 `posthog.identify(userId)`,userId 用 Better Auth 的 user id(跟 server 里的 `c.get('user').id` 一致)。AIRI server 不直接接入 `posthog-node`,后端事实事件写入 Postgres `product_events` 并通过 `airi_product_events_total` 暴露到 Grafana。前端 wiring 由 `useSharedAnalyticsStore.initialize()` 自动处理,不需要每个 caller 手动 identify。
|
||||
|
||||
参考来源:[PostHog: 5 events all teams should track](https://posthog.com/blog/events-you-should-track-with-posthog)。
|
||||
|
||||
|
|
@ -109,23 +109,23 @@
|
|||
| Runtime | `v8js_memory_*` / `nodejs_eventloop_delay_*` | Grafana | per `service_instance_id` |
|
||||
| Rate-limit | `airi_rate_limit_blocked_total` | Grafana | in-memory per replica |
|
||||
|
||||
### PostHog(前后端混合,产品侧)
|
||||
### PostHog(前端 / 外部数据源,产品侧)
|
||||
|
||||
已接入:
|
||||
- 前端 `posthog-js` 通过 `packages/stage-ui/src/stores/analytics/posthog.ts` 初始化,三个 app(web / desktop / pocket)按 `isStageTamagotchi()` 等选 project key
|
||||
- 后端 `posthog-node` 通过 `apps/server/src/services/adapters/posthog.ts` + injeca provider `services:posthog`
|
||||
- 前端↔后端 identity merge:`useSharedAnalyticsStore.initialize()` watch `authStore.isAuthenticated` 自动调 `posthog.identify(user.id)` / `reset()`
|
||||
- Server 不接入 `posthog-node`。后端产品事件写 `product_events`,Grafana 展示低基数聚合;需要 PostHog revenue/person analytics 时优先用 PostHog Stripe source connector 或离线导入,不允许在 API 请求路径同步发 PostHog。
|
||||
- 前端 identity:`useSharedAnalyticsStore.initialize()` watch `authStore.isAuthenticated` 自动调 `posthog.identify(user.id)` / `reset()`
|
||||
|
||||
已埋点:
|
||||
|
||||
| 域 | 事件 | 来源 | 落点 | Truth |
|
||||
|---|---|---|---|---|
|
||||
| 付费漏斗 | `pricing_page_viewed` / `plan_selected` / `checkout_started` | 前端 | `packages/stage-pages/src/pages/settings/flux.vue` | PostHog |
|
||||
| 付费漏斗终点 | `payment_completed` | 后端 webhook | `apps/server/src/routes/stripe/index.ts` | PostHog |
|
||||
| 付费漏斗终点 | `payment_completed` | 后端 webhook | `product_events` + Grafana;PostHog 走 Stripe source connector/离线导入 | Postgres |
|
||||
| Activation / Retention | `first_model_selected` / `model_switched` | 前端(consciousness store watcher) | `packages/stage-ui/src/stores/analytics/index.ts` | PostHog |
|
||||
| Retention | `character_created` | 前端 | `apps/stage-web/src/pages/settings/characters/components/CharacterDialog.vue` | PostHog |
|
||||
| Retention | `chat_session_started` | 前端 | `packages/stage-ui/src/components/scenarios/chat/components/sessions-drawer.vue` | PostHog |
|
||||
| Churn | `subscription_cancelled`(带 cancellation_reason) | 后端 webhook | `apps/server/src/routes/stripe/index.ts` | PostHog |
|
||||
| Churn | `subscription_cancelled`(带 cancellation_reason) | 外部 Stripe 数据源 | PostHog Stripe source connector | Stripe/Postgres |
|
||||
| 老事件 | `provider_card_clicked` / `first_message_sent` | 前端 | `packages/stage-ui/src/composables/use-analytics.ts` | PostHog |
|
||||
|
||||
待埋点(API 已在 `use-analytics.ts` 暴露但调用点未接入):
|
||||
|
|
@ -140,34 +140,16 @@
|
|||
|
||||
| 指标 | Grafana | PostHog | Truth | 语义差异 |
|
||||
|---|---|---|---|---|
|
||||
| 活跃用户数 | `user_active_sessions`(Postgres session 计数) | DAU = 去重 distinctId | **PostHog** | Grafana 是 active **sessions**,PostHog 是 active **users** |
|
||||
| Checkout 完成数 | `stripe_checkout_completed_total` | `payment_completed` event | **Postgres** | 两边都展示,Grafana 是 webhook 计数,PostHog 是漏斗终点 |
|
||||
| 活跃用户数 | `user_active_rolling` / `user_distinct_active` | DAU = 前端 journey 去重 distinctId | **Postgres/Grafana** for server truth | Grafana 是服务端可验证活跃,PostHog 是前端产品旅程 |
|
||||
| Checkout 完成数 | `stripe_checkout_completed_total` + `product_events.payment_completed` | Stripe source connector / offline import | **Postgres** | Grafana 是 webhook 计数,PostHog 是产品漏斗展示 |
|
||||
| LLM 请求 | `gen_ai_client_operation_count_total` | `chat_session_started` 等 | **Grafana**(系统计数) | PostHog 是用户维度切片,会少于 Grafana(PostHog 只覆盖 logged-in user) |
|
||||
|
||||
## PostHog 接入路线图
|
||||
|
||||
落地分两步,**不要一次性埋全部事件**,否则 schema 漂移会很快出现。
|
||||
落地分两步,**不要一次性埋全部事件**,否则 schema 漂移会很快出现。PostHog 采集只发生在前端或外部 source connector;server 请求路径只写 Postgres/Grafana。
|
||||
|
||||
### 阶段 1(P0 — 付费漏斗 + activation)
|
||||
|
||||
`apps/server`:
|
||||
|
||||
```ts
|
||||
// services/adapters/posthog.ts(新增)
|
||||
import { PostHog } from 'posthog-node'
|
||||
|
||||
export function createPostHog(env: ServerEnv) {
|
||||
return new PostHog(env.POSTHOG_KEY, { host: 'https://us.i.posthog.com' })
|
||||
}
|
||||
|
||||
// 在 Stripe webhook handler 里
|
||||
posthog.capture({
|
||||
distinctId: stripeCustomerEmail,
|
||||
event: 'payment_completed',
|
||||
properties: { plan_id, amount_usd, stripe_customer_id, stripe_subscription_id }
|
||||
})
|
||||
```
|
||||
|
||||
`apps/stage-web`:
|
||||
|
||||
```ts
|
||||
|
|
@ -199,12 +181,12 @@ posthog.init(import.meta.env.VITE_POSTHOG_KEY, {
|
|||
埋点事件清单(P0):
|
||||
|
||||
- 前端:`pricing_page_viewed`、`plan_selected`、`checkout_started`、`user_signed_up`、`first_message_sent`、`first_model_selected`
|
||||
- 后端:`payment_completed`
|
||||
- 后端:不直接发 PostHog;`payment_completed` 写入 `product_events`,PostHog 侧通过 Stripe source connector 或离线导入展示
|
||||
|
||||
PostHog UI 配两个 funnel:
|
||||
|
||||
- **付费漏斗** (7d 窗口):`pricing_page_viewed → plan_selected → checkout_started → payment_completed`
|
||||
- **激活漏斗** (14d 窗口):`user_signed_up → first_message_sent → first_model_selected → payment_completed`
|
||||
- **付费漏斗** (7d 窗口):`pricing_page_viewed → plan_selected → checkout_started → payment_completed`(最后一步来自 Stripe source connector / 离线导入)
|
||||
- **激活漏斗** (14d 窗口):`user_signed_up → first_message_sent → first_model_selected → payment_completed`(最后一步同上)
|
||||
|
||||
### 阶段 2(P1 — retention / feature adoption / churn)
|
||||
|
||||
|
|
@ -217,14 +199,14 @@ PostHog UI 配 cohort:
|
|||
|
||||
### Stripe → PostHog 集成路径
|
||||
|
||||
**两条路径都接**:
|
||||
**不在 server webhook 里手动 capture**:
|
||||
|
||||
| 路径 | 用途 |
|
||||
|---|---|
|
||||
| PostHog Stripe **source connector** | MRR / ARR / churn revenue dashboard(PostHog 原生 Revenue analytics) |
|
||||
| **手动 capture** `payment_completed`(后端 webhook) | 漏斗终点 event,跟前端 `checkout_started` 串联 |
|
||||
| 离线导入 `product_events.payment_completed`(可选) | 漏斗终点 event,跟前端 `checkout_started` 串联 |
|
||||
|
||||
不能只用 source connector:它是 data warehouse 层,**不生成 person event,做不了漏斗**。
|
||||
不要在 API 请求路径同步发 PostHog:PostHog 网络尾延迟会污染 auth / billing / chat route latency。需要 person-level funnel endpoint 时,用后台导入或 connector,不阻塞用户请求。
|
||||
|
||||
## 5xx Triage 路径
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@
|
|||
"nanoid": "catalog:",
|
||||
"ofetch": "catalog:",
|
||||
"pg": "catalog:",
|
||||
"posthog-node": "catalog:",
|
||||
"resend": "catalog:",
|
||||
"stripe": "catalog:",
|
||||
"unspeech": "catalog:xsai",
|
||||
|
|
|
|||
|
|
@ -81,7 +81,6 @@ function createTestDeps() {
|
|||
encryptKey: vi.fn(),
|
||||
decryptKey: vi.fn(),
|
||||
} as any,
|
||||
posthog: null,
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import type Redis from 'ioredis'
|
||||
import type { PostHog } from 'posthog-node'
|
||||
|
||||
import type { AuthInstance } from './libs/auth'
|
||||
import type { Database } from './libs/db'
|
||||
|
|
@ -67,7 +66,6 @@ import { createProviderRoutes } from './routes/providers'
|
|||
import { createStripeRoutes } from './routes/stripe'
|
||||
import { createConfigKVService } from './services/adapters/config-kv'
|
||||
import { createEmailService } from './services/adapters/email'
|
||||
import { createPostHogClient } from './services/adapters/posthog'
|
||||
import { createAdminFluxGrantsService } from './services/domain/admin/flux-grants'
|
||||
import { createAdminRouterConfigService } from './services/domain/admin/router-config'
|
||||
import { createAdminUsersService } from './services/domain/admin/users'
|
||||
|
|
@ -111,7 +109,6 @@ interface AppDeps {
|
|||
otel: OtelInstance | null
|
||||
userDeletionService: UserDeletionService
|
||||
llmRouter: LlmRouterService
|
||||
posthog: PostHog | null
|
||||
}
|
||||
|
||||
export async function buildApp(deps: AppDeps) {
|
||||
|
|
@ -233,7 +230,6 @@ export async function buildApp(deps: AppDeps) {
|
|||
genAi: deps.otel?.genAi,
|
||||
revenue: deps.otel?.revenue,
|
||||
rateLimitMetrics: deps.otel?.rateLimit,
|
||||
posthog: deps.posthog,
|
||||
})
|
||||
|
||||
const builtApp = app
|
||||
|
|
@ -365,7 +361,7 @@ export async function buildApp(deps: AppDeps) {
|
|||
/**
|
||||
* Stripe routes.
|
||||
*/
|
||||
.route('/api/v1/stripe', createStripeRoutes(deps.fluxService, deps.stripeService, deps.billingService, deps.configKV, deps.env, deps.redis, deps.otel?.revenue, deps.otel?.rateLimit, deps.posthog, deps.productEventService))
|
||||
.route('/api/v1/stripe', createStripeRoutes(deps.fluxService, deps.stripeService, deps.billingService, deps.configKV, deps.env, deps.redis, deps.otel?.revenue, deps.otel?.rateLimit, deps.productEventService))
|
||||
|
||||
/**
|
||||
* Admin routes — guarded by the `adminGuard` role check (`role === 'admin'`,
|
||||
|
|
@ -505,44 +501,6 @@ export async function createApp() {
|
|||
}, undefined, dependsOn.otel?.email),
|
||||
})
|
||||
|
||||
// Webhook capture path goes through `captureSafe` → `captureImmediate`,
|
||||
// which awaits the HTTP send inline, so individual events never sit in
|
||||
// the background queue. `flush()` + `_shutdown()` on SIGTERM is the belt-
|
||||
// and-suspenders drain for any future call site that uses the regular
|
||||
// `capture()` (which only enqueues).
|
||||
//
|
||||
// NOTICE:
|
||||
// We use the underscore-prefixed `_shutdown` despite its "internal" naming
|
||||
// because the public `shutdown(timeoutMs)` returns void (`types.d.ts:580`)
|
||||
// — there is no way to await its completion. `_shutdown(timeoutMs)` returns
|
||||
// `Promise<void>` (`client.d.ts:934`) and is the only way to ensure the
|
||||
// process doesn't exit while PostHog cleanup is still running. Posthog's
|
||||
// own examples show `await client._shutdown()` as the recommended pattern.
|
||||
const posthog = injeca.provide('services:posthog', {
|
||||
dependsOn: { env: parsedEnv, lifecycle },
|
||||
build: ({ dependsOn }) => {
|
||||
const client = createPostHogClient(dependsOn.env)
|
||||
if (client) {
|
||||
dependsOn.lifecycle.appHooks.onStop(async () => {
|
||||
try {
|
||||
await client.flush()
|
||||
}
|
||||
catch {
|
||||
// Flush failures on shutdown are non-fatal; we lose at most a
|
||||
// few queued events. Fall through to shutdown anyway.
|
||||
}
|
||||
try {
|
||||
await client._shutdown(5000)
|
||||
}
|
||||
catch {
|
||||
// Shutdown errors are also non-fatal during process exit.
|
||||
}
|
||||
})
|
||||
}
|
||||
return client
|
||||
},
|
||||
})
|
||||
|
||||
const productEventService = injeca.provide('services:productEvents', {
|
||||
dependsOn: { db, otel },
|
||||
build: ({ dependsOn }) => createProductEventService(dependsOn.db, dependsOn.otel?.product),
|
||||
|
|
@ -608,7 +566,7 @@ export async function createApp() {
|
|||
})
|
||||
|
||||
const auth = injeca.provide('services:auth', {
|
||||
dependsOn: { db, env: parsedEnv, otel, email: emailService, userDeletionService, posthog, productEventService },
|
||||
dependsOn: { db, env: parsedEnv, otel, email: emailService, userDeletionService, productEventService },
|
||||
build: async ({ dependsOn }) => {
|
||||
// Seed trusted OIDC clients into DB so FK constraints on oauth_access_token are satisfied
|
||||
await seedTrustedClients(dependsOn.db, dependsOn.env)
|
||||
|
|
@ -621,7 +579,7 @@ export async function createApp() {
|
|||
redirectUris: client.redirectUris.join(', '),
|
||||
}).log('OIDC trusted client ready')
|
||||
}
|
||||
return createAuth(dependsOn.db, dependsOn.env, dependsOn.email, dependsOn.otel?.auth, dependsOn.userDeletionService, dependsOn.posthog, dependsOn.productEventService)
|
||||
return createAuth(dependsOn.db, dependsOn.env, dependsOn.email, dependsOn.otel?.auth, dependsOn.userDeletionService, dependsOn.productEventService)
|
||||
},
|
||||
})
|
||||
|
||||
|
|
@ -731,7 +689,6 @@ export async function createApp() {
|
|||
otel,
|
||||
userDeletionService,
|
||||
llmRouter,
|
||||
posthog,
|
||||
})
|
||||
// Register the cluster-wide ObservableGauges for sessions / users. Each
|
||||
// replica polls the same DB (cached inside each gauge, in-flight coalesced);
|
||||
|
|
@ -773,7 +730,6 @@ export async function createApp() {
|
|||
otel: resolved.otel,
|
||||
userDeletionService: resolved.userDeletionService,
|
||||
llmRouter: resolved.llmRouter,
|
||||
posthog: resolved.posthog,
|
||||
})
|
||||
|
||||
logger.withFields({ hostname: resolved.env.HOST, port: resolved.env.PORT }).log('Server started')
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import type { PostHog } from 'posthog-node'
|
||||
|
||||
import type { AuthMetrics } from '../otel'
|
||||
import type { EmailService } from '../services/adapters/email'
|
||||
import type { ProductEventService } from '../services/domain/product-events'
|
||||
|
|
@ -10,6 +8,7 @@ import type { Env } from './env'
|
|||
import { Buffer } from 'node:buffer'
|
||||
|
||||
import { oauthProvider } from '@better-auth/oauth-provider'
|
||||
import { useLogger } from '@guiiai/logg'
|
||||
import { betterAuth } from 'better-auth'
|
||||
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
|
||||
import { createAuthMiddleware } from 'better-auth/api'
|
||||
|
|
@ -17,13 +16,14 @@ import { deleteSessionCookie } from 'better-auth/cookies'
|
|||
import { admin, bearer, jwt, magicLink } from 'better-auth/plugins'
|
||||
import { eq } from 'drizzle-orm'
|
||||
|
||||
import { captureSafe } from '../services/adapters/posthog'
|
||||
import { ApiError } from '../utils/error'
|
||||
import { getAuthTrustedOrigins, getTrustedOrigin } from '../utils/origin'
|
||||
import { oidcJwtBearer } from './auth-plugins/oidc-jwt-bearer'
|
||||
|
||||
import * as authSchema from '../schemas/accounts'
|
||||
|
||||
const logger = useLogger('auth').useGlobalConfig()
|
||||
|
||||
interface TrustedClientSeed {
|
||||
clientId: string
|
||||
/** Omit for public clients — only confidential clients need a secret. */
|
||||
|
|
@ -365,7 +365,6 @@ export function createAuth(
|
|||
email?: EmailService,
|
||||
metrics?: AuthMetrics | null,
|
||||
userDeletionService?: UserDeletionService,
|
||||
posthog?: PostHog | null,
|
||||
productEventService?: ProductEventService,
|
||||
) {
|
||||
return betterAuth({
|
||||
|
|
@ -665,17 +664,13 @@ export function createAuth(
|
|||
create: {
|
||||
after: async (user) => {
|
||||
metrics?.userRegistered.add(1)
|
||||
await productEventService?.track({
|
||||
void productEventService?.track({
|
||||
userId: user.id,
|
||||
feature: 'auth',
|
||||
action: 'user_signed_up',
|
||||
status: 'succeeded',
|
||||
source: 'better-auth.user.create',
|
||||
})
|
||||
await captureSafe(posthog ?? null, {
|
||||
event: 'user_signed_up',
|
||||
distinctId: user.id,
|
||||
})
|
||||
},
|
||||
},
|
||||
update: {
|
||||
|
|
@ -706,21 +701,20 @@ export function createAuth(
|
|||
// `after` hook for last-seen / analytics.
|
||||
after: async (session) => {
|
||||
metrics?.userLogin.add(1)
|
||||
await db
|
||||
// Best-effort analytics: session creation must not fail because
|
||||
// active-user reporting is degraded.
|
||||
void db
|
||||
.update(authSchema.user)
|
||||
.set({ lastSeenAt: new Date() })
|
||||
.where(eq(authSchema.user.id, session.userId))
|
||||
await productEventService?.track({
|
||||
.catch(err => logger.withError(err).withFields({ userId: session.userId }).warn('Failed to update user lastSeenAt; continuing session create'))
|
||||
void productEventService?.track({
|
||||
userId: session.userId,
|
||||
feature: 'auth',
|
||||
action: 'session_started',
|
||||
status: 'succeeded',
|
||||
source: 'better-auth.session.create',
|
||||
})
|
||||
await captureSafe(posthog ?? null, {
|
||||
event: 'session_started',
|
||||
distinctId: session.userId,
|
||||
})
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -131,11 +131,6 @@ const EnvSchema = object({
|
|||
STRIPE_SECRET_KEY: optional(string()),
|
||||
STRIPE_WEBHOOK_SECRET: optional(string()),
|
||||
|
||||
// PostHog server-side analytics. Optional — when unset the client is null
|
||||
// and `captureSafe(...)` is a no-op so webhooks still complete.
|
||||
POSTHOG_API_KEY: optional(string(), ''),
|
||||
POSTHOG_HOST: optional(string(), 'https://us.i.posthog.com'),
|
||||
|
||||
// LLM/TTS gateway is fully internalised by the in-process router; provider
|
||||
// baseURLs live per-upstream inside LLM_ROUTER_CONFIG, and the default chat /
|
||||
// tts model aliases moved to configKV (DEFAULT_CHAT_MODEL / DEFAULT_TTS_MODEL)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import type { V1RouteDeps } from '../../types'
|
|||
|
||||
import { useLogger } from '@guiiai/logg'
|
||||
|
||||
import { captureSafe } from '../../../../../services/adapters/posthog'
|
||||
import { extractUsageFromBody } from '../../../../../services/domain/billing/billing'
|
||||
import { nanoid } from '../../../../../utils/id'
|
||||
import { buildSafeResponseHeaders } from '../../http/response'
|
||||
|
|
@ -156,19 +155,6 @@ export function chatCompletions(deps: V1RouteDeps): GatewayCallback<'chat.comple
|
|||
stream,
|
||||
},
|
||||
})
|
||||
// Emit server-side so funnels see real HTTP status — the client only
|
||||
// ever observes "stream closed" and cannot tell 401 / 429 / 5xx apart.
|
||||
void captureSafe(deps.posthog ?? null, {
|
||||
distinctId: input.userId,
|
||||
event: 'llm_request_failed',
|
||||
properties: {
|
||||
model: requestModel,
|
||||
http_status: response.status,
|
||||
duration_ms: durationMs,
|
||||
stream: !!body.stream,
|
||||
},
|
||||
})
|
||||
|
||||
logger.withFields({ requestId, userId: input.userId, model: requestModel, status: response.status, durationMs })
|
||||
.warn('chat completion delivered with upstream error status')
|
||||
|
||||
|
|
@ -400,21 +386,6 @@ function streamChatCompletion(input: {
|
|||
},
|
||||
})
|
||||
|
||||
void captureSafe(input.deps.posthog ?? null, {
|
||||
distinctId: input.userId,
|
||||
event: 'llm_request_succeeded',
|
||||
properties: {
|
||||
model: input.requestModel,
|
||||
http_status: input.response.status,
|
||||
duration_ms: input.durationMs,
|
||||
prompt_tokens: usage.promptTokens ?? 0,
|
||||
completion_tokens: usage.completionTokens ?? 0,
|
||||
flux_consumed: actualCharged,
|
||||
stream: true,
|
||||
stream_interrupted: streamInterrupted,
|
||||
},
|
||||
})
|
||||
|
||||
input.logger.withFields({
|
||||
requestId: input.requestId,
|
||||
userId: input.userId,
|
||||
|
|
@ -534,20 +505,6 @@ async function completeNonStreamingChat(input: {
|
|||
},
|
||||
})
|
||||
|
||||
void captureSafe(input.deps.posthog ?? null, {
|
||||
distinctId: input.userId,
|
||||
event: 'llm_request_succeeded',
|
||||
properties: {
|
||||
model: input.requestModel,
|
||||
http_status: input.response.status,
|
||||
duration_ms: input.durationMs,
|
||||
prompt_tokens: usage.promptTokens ?? 0,
|
||||
completion_tokens: usage.completionTokens ?? 0,
|
||||
flux_consumed: actualCharged,
|
||||
stream: false,
|
||||
},
|
||||
})
|
||||
|
||||
input.logger.withFields({
|
||||
requestId: input.requestId,
|
||||
userId: input.userId,
|
||||
|
|
|
|||
|
|
@ -151,7 +151,6 @@ function createTestApp(
|
|||
genAi: null,
|
||||
revenue: null,
|
||||
rateLimitMetrics: null,
|
||||
posthog: null,
|
||||
llmTracing,
|
||||
})
|
||||
const app = new Hono<HonoEnv>()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import type { PostHog } from 'posthog-node'
|
||||
|
||||
import type { GenAiMetrics, RateLimitMetrics, RevenueMetrics } from '../../../otel'
|
||||
import type { ConfigKVService } from '../../../services/adapters/config-kv'
|
||||
import type { BillingService } from '../../../services/domain/billing/billing-service'
|
||||
|
|
@ -28,7 +26,6 @@ export interface V1RouteDeps {
|
|||
genAi?: GenAiMetrics | null
|
||||
revenue?: RevenueMetrics | null
|
||||
rateLimitMetrics?: RateLimitMetrics | null
|
||||
posthog?: PostHog | null
|
||||
llmTracing: LlmTracingDeps
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import type Redis from 'ioredis'
|
||||
import type { PostHog } from 'posthog-node'
|
||||
|
||||
import type { Env } from '../../libs/env'
|
||||
import type { RateLimitMetrics, RevenueMetrics } from '../../otel'
|
||||
|
|
@ -47,7 +46,6 @@ export function createStripeRoutes(
|
|||
redis: Redis,
|
||||
metrics?: RevenueMetrics | null,
|
||||
rateLimitMetrics?: RateLimitMetrics | null,
|
||||
posthog?: PostHog | null,
|
||||
productEventService?: ProductEventService,
|
||||
) {
|
||||
const stripe = env.STRIPE_SECRET_KEY ? new Stripe(env.STRIPE_SECRET_KEY) : null
|
||||
|
|
@ -60,7 +58,6 @@ export function createStripeRoutes(
|
|||
stripeService,
|
||||
billingService,
|
||||
metrics,
|
||||
posthog,
|
||||
productEventService,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import type { PostHog } from 'posthog-node'
|
||||
import type Stripe from 'stripe'
|
||||
|
||||
import type { RevenueMetrics } from '../../../otel'
|
||||
|
|
@ -9,7 +8,6 @@ import type { StripeService } from '../../../services/domain/stripe'
|
|||
|
||||
import { useLogger } from '@guiiai/logg'
|
||||
|
||||
import { captureSafe } from '../../../services/adapters/posthog'
|
||||
import { createBadRequestError, createServiceUnavailableError } from '../../../utils/error'
|
||||
import { errorMessageFromUnknown } from '../../../utils/error-message'
|
||||
|
||||
|
|
@ -22,7 +20,6 @@ export interface WebhookOperationDeps {
|
|||
stripeService: StripeService
|
||||
billingService: BillingService
|
||||
metrics?: RevenueMetrics | null
|
||||
posthog?: PostHog | null
|
||||
productEventService?: ProductEventService
|
||||
}
|
||||
|
||||
|
|
@ -75,13 +72,9 @@ export function createWebhookOperation(deps: WebhookOperationDeps) {
|
|||
source: 'checkout',
|
||||
})
|
||||
}
|
||||
// PostHog: funnel terminator. Only fire when the handler actually
|
||||
// processed the checkout — malformed sessions (missing userId,
|
||||
// invalid fluxAmount) take the early-return path above and would
|
||||
// otherwise poison the funnel with phantom conversions. distinctId
|
||||
// is the Better Auth user id so it merges with the browser's
|
||||
// `posthog.identify(userId)` and the prior `checkout_started`
|
||||
// event lines up. See docs/ai-context/metrics-ownership.md.
|
||||
// Record the product conversion only after the handler actually
|
||||
// processed the checkout. Malformed sessions (missing userId,
|
||||
// invalid fluxAmount) take the early-return path above.
|
||||
if (result.processed) {
|
||||
const userId = event.data.object.metadata?.userId
|
||||
if (userId) {
|
||||
|
|
@ -99,7 +92,6 @@ export function createWebhookOperation(deps: WebhookOperationDeps) {
|
|||
},
|
||||
})
|
||||
}
|
||||
await capturePaymentCompleted(deps.posthog, event.data.object)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
|
@ -113,8 +105,6 @@ export function createWebhookOperation(deps: WebhookOperationDeps) {
|
|||
case 'customer.subscription.deleted': {
|
||||
await handleSubscriptionEvent(event.data.object, deps.stripeService)
|
||||
deps.metrics?.stripeSubscriptionEvent.add(1, { event_type: event.type.replace('customer.subscription.', '') })
|
||||
if (event.type === 'customer.subscription.deleted')
|
||||
await captureSubscriptionCancelled(deps.posthog, deps.stripeService, event.data.object)
|
||||
break
|
||||
}
|
||||
case 'invoice.created':
|
||||
|
|
@ -226,73 +216,6 @@ async function handleCheckoutSessionCompleted(
|
|||
return { processed: true }
|
||||
}
|
||||
|
||||
async function capturePaymentCompleted(
|
||||
posthog: PostHog | null | undefined,
|
||||
session: Stripe.Checkout.Session,
|
||||
): Promise<void> {
|
||||
if (!posthog)
|
||||
return
|
||||
|
||||
const userId = session.metadata?.userId
|
||||
const email = session.customer_email
|
||||
|| (typeof session.customer_details?.email === 'string' ? session.customer_details.email : null)
|
||||
|| null
|
||||
|
||||
// distinctId fallback chain: userId (Better Auth, matches browser identify())
|
||||
// > email (PostHog will merge on identify later) > stripe session id (last
|
||||
// resort — orphan event but at least we count it).
|
||||
const distinctId = userId || email || session.id
|
||||
|
||||
const fluxAmount = Number(session.metadata?.fluxAmount)
|
||||
const stripeCustomerId = typeof session.customer === 'string' ? session.customer : session.customer?.id
|
||||
|
||||
await captureSafe(posthog, {
|
||||
distinctId,
|
||||
event: 'payment_completed',
|
||||
properties: {
|
||||
amount_total: session.amount_total,
|
||||
currency: session.currency,
|
||||
flux_amount: Number.isFinite(fluxAmount) ? fluxAmount : null,
|
||||
mode: session.mode,
|
||||
stripe_session_id: session.id,
|
||||
stripe_customer_id: stripeCustomerId,
|
||||
stripe_subscription_id: typeof session.subscription === 'string' ? session.subscription : session.subscription?.id,
|
||||
...(userId ? { user_id: userId } : {}),
|
||||
// $set populates the PostHog person profile so funnel joins work even
|
||||
// when a user pays via direct checkout link before ever loading the SPA.
|
||||
...(email ? { $set: { email } } : {}),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async function captureSubscriptionCancelled(
|
||||
posthog: PostHog | null | undefined,
|
||||
stripeService: StripeService,
|
||||
subscription: Stripe.Subscription,
|
||||
): Promise<void> {
|
||||
if (!posthog)
|
||||
return
|
||||
|
||||
const stripeCustomerId = typeof subscription.customer === 'string' ? subscription.customer : subscription.customer.id
|
||||
const customer = await stripeService.getCustomerByStripeId(stripeCustomerId)
|
||||
const distinctId = customer?.userId || stripeCustomerId
|
||||
|
||||
await captureSafe(posthog, {
|
||||
distinctId,
|
||||
event: 'subscription_cancelled',
|
||||
properties: {
|
||||
stripe_subscription_id: subscription.id,
|
||||
stripe_customer_id: stripeCustomerId,
|
||||
cancel_at_period_end: subscription.cancel_at_period_end,
|
||||
cancellation_reason: subscription.cancellation_details?.reason ?? null,
|
||||
cancellation_comment: subscription.cancellation_details?.comment ?? null,
|
||||
canceled_at: subscription.canceled_at,
|
||||
ended_at: subscription.ended_at,
|
||||
...(customer?.userId ? { user_id: customer.userId } : {}),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async function handleCustomerEvent(
|
||||
customer: Stripe.Customer | Stripe.DeletedCustomer,
|
||||
stripeService: StripeService,
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
import type { Env } from '../../libs/env'
|
||||
|
||||
import { useLogger } from '@guiiai/logg'
|
||||
import { PostHog } from 'posthog-node'
|
||||
|
||||
const logger = useLogger('posthog')
|
||||
|
||||
/**
|
||||
* Server-side PostHog client. Used to capture authoritative business events
|
||||
* the browser cannot see (Stripe webhooks, subscription state changes,
|
||||
* admin actions). Pairs with the browser-side PostHog already wired up in
|
||||
* `packages/stage-ui/src/stores/analytics/posthog.ts`.
|
||||
*
|
||||
* Use when:
|
||||
* - You're inside a server-side handler (Stripe webhook, admin route) and
|
||||
* need to emit an event that will be analysed in PostHog funnels or
|
||||
* cohorts (e.g. `payment_completed`, `subscription_cancelled`).
|
||||
*
|
||||
* Expects:
|
||||
* - `POSTHOG_API_KEY` env var. When unset (dev/CI) this returns `null` so
|
||||
* callers degrade gracefully with `posthog?.capture(...)`.
|
||||
* - `distinctId` must match the browser's `posthog.identify(userId)` — we
|
||||
* use the Better Auth `user.id` for that everywhere. Stripe webhooks
|
||||
* that only have an email use the email as a fallback `distinctId` and
|
||||
* include `userId` in the event properties so PostHog's merge resolves
|
||||
* the person.
|
||||
*
|
||||
* Returns:
|
||||
* - A `PostHog` client configured for low-latency immediate sends, or
|
||||
* `null` when key is unset. Callers must use `captureSafe()` (which
|
||||
* wraps `captureImmediate`) — the regular `capture()` only enqueues
|
||||
* and would let webhook responses race ahead of the HTTP send.
|
||||
*/
|
||||
export function createPostHogClient(env: Env): PostHog | null {
|
||||
if (!env.POSTHOG_API_KEY) {
|
||||
logger.warn('POSTHOG_API_KEY is unset — server-side analytics disabled')
|
||||
return null
|
||||
}
|
||||
|
||||
// NOTICE:
|
||||
// `flushAt: 1` keeps the background-batch threshold low so any stray
|
||||
// `posthog.capture()` (non-immediate path) flushes promptly. Real send-
|
||||
// path for webhook events goes through `captureImmediate()` in
|
||||
// `captureSafe`, which bypasses the queue entirely and resolves only
|
||||
// after the HTTP round-trip. We also rely on `shutdown(timeoutMs)` from
|
||||
// app.ts to drain any residual queue on SIGTERM.
|
||||
return new PostHog(env.POSTHOG_API_KEY, {
|
||||
host: env.POSTHOG_HOST || 'https://us.i.posthog.com',
|
||||
flushAt: 1,
|
||||
flushInterval: 0,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe capture wrapper. PostHog must never block or fail a webhook /
|
||||
* billing path — any error here is logged and swallowed.
|
||||
*
|
||||
* Use when:
|
||||
* - Inside a server-side handler that has business work to finish even
|
||||
* if PostHog is down. The handler already wrote to Postgres and
|
||||
* updated metrics; PostHog is the optional last step.
|
||||
*
|
||||
* Expects:
|
||||
* - Caller awaits the returned promise. We use `captureImmediate` (not
|
||||
* `capture`) because PostHog Node SDK's regular `capture` only enqueues
|
||||
* — `flushAt: 1` triggers a *background* flush, which means the webhook
|
||||
* handler can return before the event reaches PostHog and SIGTERM may
|
||||
* strand the queued event. `captureImmediate` does the HTTP send inline
|
||||
* and resolves only after the network round-trip.
|
||||
*
|
||||
* Consent boundary:
|
||||
* - Browser-side capture is gated by `useAnalytics().canCapture()` (user
|
||||
* toggle in Settings → Analytics).
|
||||
* - Server-side events here are operational telemetry tied to business
|
||||
* facts that already occurred (auth records the user, Stripe records
|
||||
* the payment, the LLM router records the request). They are emitted
|
||||
* regardless of the browser toggle on legitimate-interest grounds —
|
||||
* the user cannot opt out of the server knowing they signed up or
|
||||
* paid, only out of additional product analytics on top. Surface this
|
||||
* distinction in the privacy policy.
|
||||
*/
|
||||
export async function captureSafe(
|
||||
posthog: PostHog | null,
|
||||
event: { distinctId: string, event: string, properties?: Record<string, unknown> },
|
||||
): Promise<void> {
|
||||
if (!posthog)
|
||||
return
|
||||
|
||||
try {
|
||||
await posthog.captureImmediate(event)
|
||||
}
|
||||
catch (err) {
|
||||
logger.withError(err).withFields({ event: event.event, distinctId: event.distinctId }).warn('PostHog captureImmediate failed; swallowing to protect caller')
|
||||
}
|
||||
}
|
||||
|
|
@ -199,7 +199,6 @@ export async function startVerificationContext() {
|
|||
route: vi.fn(async () => new Response('{}', { status: 200 })),
|
||||
invalidateConfig: vi.fn(),
|
||||
} as any,
|
||||
posthog: null,
|
||||
})
|
||||
|
||||
return {
|
||||
|
|
|
|||
293
pnpm-lock.yaml
generated
293
pnpm-lock.yaml
generated
|
|
@ -880,9 +880,6 @@ catalogs:
|
|||
posthog-js:
|
||||
specifier: 1.306.1
|
||||
version: 1.306.1
|
||||
posthog-node:
|
||||
specifier: ^5.34.1
|
||||
version: 5.34.1
|
||||
postprocessing:
|
||||
specifier: ^6.39.1
|
||||
version: 6.39.1
|
||||
|
|
@ -1608,9 +1605,6 @@ importers:
|
|||
pg:
|
||||
specifier: 'catalog:'
|
||||
version: 8.20.0
|
||||
posthog-node:
|
||||
specifier: 'catalog:'
|
||||
version: 5.34.1(rxjs@7.8.2)
|
||||
resend:
|
||||
specifier: 'catalog:'
|
||||
version: 6.12.2
|
||||
|
|
@ -2345,7 +2339,7 @@ importers:
|
|||
version: 3.0.2(electron@41.2.1)
|
||||
'@electron-toolkit/tsconfig':
|
||||
specifier: 'catalog:'
|
||||
version: 2.0.0(@types/node@24.12.2)
|
||||
version: 2.0.0(@types/node@25.6.0)
|
||||
'@electron-toolkit/utils':
|
||||
specifier: 'catalog:'
|
||||
version: 4.0.0(electron@41.2.1)
|
||||
|
|
@ -2384,7 +2378,7 @@ importers:
|
|||
version: 3.1.0
|
||||
'@intlify/unplugin-vue-i18n':
|
||||
specifier: 'catalog:'
|
||||
version: 11.0.7(@vue/compiler-dom@3.5.32)(eslint@10.2.1(jiti@2.6.1))(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 11.0.7(@vue/compiler-dom@3.5.32)(eslint@10.2.1(jiti@2.6.1))(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
'@modelcontextprotocol/sdk':
|
||||
specifier: 'catalog:'
|
||||
version: 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6)
|
||||
|
|
@ -2420,10 +2414,10 @@ importers:
|
|||
version: link:../../packages/ui-transitions
|
||||
'@proj-airi/unplugin-fetch':
|
||||
specifier: 'catalog:'
|
||||
version: 0.2.3(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 0.2.3(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
'@proj-airi/unplugin-live2d-sdk':
|
||||
specifier: 'catalog:'
|
||||
version: 0.1.7(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
version: 0.1.7(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
'@types/audioworklet':
|
||||
specifier: 'catalog:'
|
||||
version: 0.0.97
|
||||
|
|
@ -2450,7 +2444,7 @@ importers:
|
|||
version: 2.10.3
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: 'catalog:'
|
||||
version: 6.0.6(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 6.0.6(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/volar':
|
||||
specifier: 'catalog:'
|
||||
version: 3.1.2(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3))
|
||||
|
|
@ -2483,7 +2477,7 @@ importers:
|
|||
version: 6.8.3
|
||||
electron-vite:
|
||||
specifier: 'catalog:'
|
||||
version: 5.0.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 5.0.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
get-port-please:
|
||||
specifier: 'catalog:'
|
||||
version: 3.2.0
|
||||
|
|
@ -2504,31 +2498,31 @@ importers:
|
|||
version: 2.2.6
|
||||
unocss-preset-scrollbar:
|
||||
specifier: 'catalog:'
|
||||
version: 4.0.0(unocss@66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)))
|
||||
version: 4.0.0(unocss@66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)))
|
||||
unplugin-info:
|
||||
specifier: 'catalog:'
|
||||
version: 1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
unplugin-yaml:
|
||||
specifier: 'catalog:'
|
||||
version: 4.1.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 4.1.0(@nuxt/kit@3.20.2(magicast@0.5.2))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
vite:
|
||||
specifier: 'catalog:'
|
||||
version: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
version: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-bundle-visualizer:
|
||||
specifier: 'catalog:'
|
||||
version: 1.2.1(rolldown@1.0.0-rc.16)(rollup@4.60.1)
|
||||
vite-plugin-mkcert:
|
||||
specifier: 'catalog:'
|
||||
version: 2.0.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 2.0.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
vite-plugin-vue-devtools:
|
||||
specifier: 'catalog:'
|
||||
version: 8.1.1(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 8.1.1(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))
|
||||
vite-plugin-vue-layouts:
|
||||
specifier: 'catalog:'
|
||||
version: 0.11.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-router@5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 0.11.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-router@5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
vue-macros:
|
||||
specifier: 'catalog:'
|
||||
version: 3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3))
|
||||
vue-tsc:
|
||||
specifier: 'catalog:'
|
||||
version: 3.2.6(typescript@5.9.3)
|
||||
|
|
@ -9654,15 +9648,9 @@ packages:
|
|||
'@polka/url@1.0.0-next.29':
|
||||
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
|
||||
|
||||
'@posthog/core@1.29.1':
|
||||
resolution: {integrity: sha512-q+/t/DZALr50YTE0dFgfGSS9EgwcyAlqsn+JS61wLkwdcDM5yu/YTDM8oMKmJupsyjSZlVkDuHZAMd4ab7AxzQ==}
|
||||
|
||||
'@posthog/core@1.7.1':
|
||||
resolution: {integrity: sha512-kjK0eFMIpKo9GXIbts8VtAknsoZ18oZorANdtuTj1CbgS28t4ZVq//HAWhnxEuXRTrtkd+SUJ6Ux3j2Af8NCuA==}
|
||||
|
||||
'@posthog/types@1.373.4':
|
||||
resolution: {integrity: sha512-n+0AbGRYYsbi+CQXQi2rF1lwTSyASlaogcw4YSkzB5KeMa4Y6nhNb7+TTnu9aVor+BycsQYCa2OsBrMMbaTekw==}
|
||||
|
||||
'@prisma/client@5.22.0':
|
||||
resolution: {integrity: sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==}
|
||||
engines: {node: '>=16.13'}
|
||||
|
|
@ -16684,15 +16672,6 @@ packages:
|
|||
posthog-js@1.306.1:
|
||||
resolution: {integrity: sha512-wO7bliv/5tlAlfoKCUzwkGXZVNexk0dHigMf9tNp0q1rzs62wThogREY7Tz7h/iWKYiuXy1RumtVlTmHuBXa1w==}
|
||||
|
||||
posthog-node@5.34.1:
|
||||
resolution: {integrity: sha512-kGl0kSfh2+Ey3KL5Sji3yv9W5xwPK9sTkINRoFqCh9fbYXWWY6Zwi5Psv2QmRcbYiMJBk/iecnoOKVDRRga6PA==}
|
||||
engines: {node: ^20.20.0 || >=22.22.0}
|
||||
peerDependencies:
|
||||
rxjs: ^7.0.0
|
||||
peerDependenciesMeta:
|
||||
rxjs:
|
||||
optional: true
|
||||
|
||||
postject@1.0.0-alpha.6:
|
||||
resolution: {integrity: sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
|
@ -20909,9 +20888,9 @@ snapshots:
|
|||
dependencies:
|
||||
electron: 41.2.1
|
||||
|
||||
'@electron-toolkit/tsconfig@2.0.0(@types/node@24.12.2)':
|
||||
'@electron-toolkit/tsconfig@2.0.0(@types/node@25.6.0)':
|
||||
dependencies:
|
||||
'@types/node': 24.12.2
|
||||
'@types/node': 25.6.0
|
||||
|
||||
'@electron-toolkit/utils@4.0.0(electron@41.2.1)':
|
||||
dependencies:
|
||||
|
|
@ -21823,31 +21802,6 @@ snapshots:
|
|||
- supports-color
|
||||
- typescript
|
||||
|
||||
'@intlify/unplugin-vue-i18n@11.0.7(@vue/compiler-dom@3.5.32)(eslint@10.2.1(jiti@2.6.1))(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1))
|
||||
'@intlify/bundle-utils': 11.0.7(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))
|
||||
'@intlify/shared': 11.3.2
|
||||
'@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.3.2)(@vue/compiler-dom@3.5.32)(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.60.1)
|
||||
'@typescript-eslint/scope-manager': 8.58.1
|
||||
'@typescript-eslint/typescript-estree': 8.58.1(typescript@5.9.3)
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
fast-glob: 3.3.3
|
||||
pathe: 2.0.3
|
||||
picocolors: 1.1.1
|
||||
unplugin: 2.3.11
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
optionalDependencies:
|
||||
vue-i18n: 11.3.2(vue@3.5.32(typescript@5.9.3))
|
||||
transitivePeerDependencies:
|
||||
- '@vue/compiler-dom'
|
||||
- eslint
|
||||
- rollup
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
'@intlify/unplugin-vue-i18n@11.0.7(@vue/compiler-dom@3.5.32)(eslint@10.2.1(jiti@2.6.1))(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1))
|
||||
|
|
@ -23789,16 +23743,10 @@ snapshots:
|
|||
|
||||
'@polka/url@1.0.0-next.29': {}
|
||||
|
||||
'@posthog/core@1.29.1':
|
||||
dependencies:
|
||||
'@posthog/types': 1.373.4
|
||||
|
||||
'@posthog/core@1.7.1':
|
||||
dependencies:
|
||||
cross-spawn: 7.0.6
|
||||
|
||||
'@posthog/types@1.373.4': {}
|
||||
|
||||
'@prisma/client@5.22.0': {}
|
||||
|
||||
'@proj-airi/chromatic@1.1.1':
|
||||
|
|
@ -23856,35 +23804,11 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- magicast
|
||||
|
||||
'@proj-airi/unplugin-fetch@0.2.3(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
ofetch: 1.5.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
'@proj-airi/unplugin-fetch@0.2.3(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
ofetch: 1.5.1
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
'@proj-airi/unplugin-live2d-sdk@0.1.7(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)':
|
||||
dependencies:
|
||||
ofetch: 1.5.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
yauzl: 3.3.0
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- '@vitejs/devtools'
|
||||
- esbuild
|
||||
- jiti
|
||||
- less
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- terser
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
'@proj-airi/unplugin-live2d-sdk@0.1.7(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)':
|
||||
dependencies:
|
||||
ofetch: 1.5.1
|
||||
|
|
@ -25450,12 +25374,6 @@ snapshots:
|
|||
vite: 6.4.2(@types/node@25.6.0)(jiti@2.6.1)(less@4.6.4)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
|
||||
'@vitejs/plugin-vue@6.0.6(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@rolldown/pluginutils': 1.0.0-rc.13
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
|
||||
'@vitejs/plugin-vue@6.0.6(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@rolldown/pluginutils': 1.0.0-rc.13
|
||||
|
|
@ -25536,9 +25454,9 @@ snapshots:
|
|||
obug: 2.1.1
|
||||
std-env: 4.1.0
|
||||
tinyrainbow: 3.1.0
|
||||
vitest: 4.1.4(@opentelemetry/api@1.9.1)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1(@noble/hashes@2.0.1)(canvas@3.2.3))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
vitest: 4.1.4(@opentelemetry/api@1.9.1)(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1(@noble/hashes@2.0.1)(canvas@3.2.3))(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
optionalDependencies:
|
||||
'@vitest/browser': 4.1.4(bufferutil@4.1.0)(utf-8-validate@5.0.10)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)
|
||||
'@vitest/browser': 4.1.4(bufferutil@4.1.0)(utf-8-validate@5.0.10)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)
|
||||
|
||||
'@vitest/eslint-plugin@1.6.15(@typescript-eslint/eslint-plugin@8.58.1(@typescript-eslint/parser@8.58.1(eslint@10.2.1(jiti@2.6.1))(typescript@5.9.3))(eslint@10.2.1(jiti@2.6.1))(typescript@5.9.3))(eslint@10.2.1(jiti@2.6.1))(typescript@5.9.3)(vitest@4.1.4)':
|
||||
dependencies:
|
||||
|
|
@ -25758,15 +25676,6 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- vue
|
||||
|
||||
'@vue-macros/devtools@3.1.2(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
sirv: 3.0.2
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
optionalDependencies:
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
|
||||
'@vue-macros/devtools@3.1.2(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
sirv: 3.0.2
|
||||
|
|
@ -27908,7 +27817,7 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
electron-vite@5.0.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
electron-vite@5.0.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0)
|
||||
|
|
@ -27916,7 +27825,7 @@ snapshots:
|
|||
esbuild: 0.25.12
|
||||
magic-string: 0.30.21
|
||||
picocolors: 1.1.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
|
@ -31983,12 +31892,6 @@ snapshots:
|
|||
preact: 10.28.1
|
||||
web-vitals: 4.2.4
|
||||
|
||||
posthog-node@5.34.1(rxjs@7.8.2):
|
||||
dependencies:
|
||||
'@posthog/core': 1.29.1
|
||||
optionalDependencies:
|
||||
rxjs: 7.8.2
|
||||
|
||||
postject@1.0.0-alpha.6:
|
||||
dependencies:
|
||||
commander: 9.5.0
|
||||
|
|
@ -33944,6 +33847,11 @@ snapshots:
|
|||
'@unocss/preset-mini': 66.6.8
|
||||
unocss: 66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
|
||||
unocss-preset-scrollbar@4.0.0(unocss@66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))):
|
||||
dependencies:
|
||||
'@unocss/preset-mini': 66.6.8
|
||||
unocss: 66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
|
||||
unocss@66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@6.4.2(@types/node@25.6.0)(jiti@2.6.1)(less@4.6.4)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@unocss/cli': 66.6.8
|
||||
|
|
@ -34040,14 +33948,6 @@ snapshots:
|
|||
unplugin: 2.3.11
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
unplugin-combine@2.3.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(unplugin@2.3.11)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
optionalDependencies:
|
||||
esbuild: 0.27.2
|
||||
rolldown: 1.0.0-rc.16
|
||||
rollup: 4.60.1
|
||||
unplugin: 2.3.11
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
unplugin-combine@2.3.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(unplugin@2.3.11)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
optionalDependencies:
|
||||
esbuild: 0.27.2
|
||||
|
|
@ -34082,19 +33982,6 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
unplugin-info@1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
ci-info: 4.4.0
|
||||
git-url-parse: 16.1.0
|
||||
simple-git: 3.36.0
|
||||
unplugin: 2.3.11
|
||||
optionalDependencies:
|
||||
esbuild: 0.27.2
|
||||
rollup: 4.60.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
unplugin-info@1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
ci-info: 4.4.0
|
||||
|
|
@ -34204,17 +34091,6 @@ snapshots:
|
|||
rollup: 4.60.1
|
||||
vite: 6.4.2(@types/node@25.6.0)(jiti@2.6.1)(less@4.6.4)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
unplugin-yaml@4.1.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.60.1)
|
||||
unplugin: 3.0.0
|
||||
yaml: 2.8.3
|
||||
optionalDependencies:
|
||||
esbuild: 0.27.2
|
||||
rolldown: 1.0.0-rc.16
|
||||
rollup: 4.60.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
unplugin@2.3.11:
|
||||
dependencies:
|
||||
'@jridgewell/remapping': 2.3.5
|
||||
|
|
@ -34446,22 +34322,12 @@ snapshots:
|
|||
- rollup
|
||||
- supports-color
|
||||
|
||||
vite-dev-rpc@1.1.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
birpc: 2.9.0
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-hot-client: 2.1.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
|
||||
vite-dev-rpc@1.1.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
birpc: 2.9.0
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-hot-client: 2.1.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
|
||||
vite-hot-client@2.1.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
vite-hot-client@2.1.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
|
@ -34507,21 +34373,6 @@ snapshots:
|
|||
- tsx
|
||||
- yaml
|
||||
|
||||
vite-plugin-inspect@11.3.3(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
ansis: 4.2.0
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
error-stack-parser-es: 1.0.5
|
||||
ohash: 2.0.11
|
||||
open: 10.2.0
|
||||
perfect-debounce: 2.1.0
|
||||
sirv: 3.0.2
|
||||
unplugin-utils: 0.3.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-dev-rpc: 1.1.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-inspect@11.3.3(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
ansis: 4.2.0
|
||||
|
|
@ -34553,13 +34404,6 @@ snapshots:
|
|||
- typescript
|
||||
- ws
|
||||
|
||||
vite-plugin-mkcert@2.0.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
supports-color: 10.2.2
|
||||
undici: 8.1.0
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
vite-plugin-mkcert@2.0.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
|
|
@ -34578,20 +34422,6 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-vue-devtools@8.1.1(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@vue/devtools-core': 8.1.1(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue/devtools-kit': 8.1.1
|
||||
'@vue/devtools-shared': 8.1.1
|
||||
sirv: 3.0.2
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-plugin-inspect: 11.3.3(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
vite-plugin-vue-inspector: 5.3.2(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
transitivePeerDependencies:
|
||||
- '@nuxt/kit'
|
||||
- supports-color
|
||||
- vue
|
||||
|
||||
vite-plugin-vue-devtools@8.1.1(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@vue/devtools-core': 8.1.1(vue@3.5.32(typescript@5.9.3))
|
||||
|
|
@ -34606,21 +34436,6 @@ snapshots:
|
|||
- supports-color
|
||||
- vue
|
||||
|
||||
vite-plugin-vue-inspector@5.3.2(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@babel/plugin-proposal-decorators': 7.28.0(@babel/core@7.29.0)
|
||||
'@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0)
|
||||
'@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.0)
|
||||
'@babel/plugin-transform-typescript': 7.28.5(@babel/core@7.29.0)
|
||||
'@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.29.0)
|
||||
'@vue/compiler-dom': 3.5.32
|
||||
kolorist: 1.8.0
|
||||
magic-string: 0.30.21
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-vue-inspector@5.3.2(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
|
|
@ -34636,16 +34451,6 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-vue-layouts@0.11.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-router@5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
fast-glob: 3.3.3
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
vue-router: 5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-vue-layouts@0.11.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-router@5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
|
|
@ -34912,54 +34717,6 @@ snapshots:
|
|||
- vue-tsc
|
||||
- webpack
|
||||
|
||||
vue-macros@3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@vue-macros/better-define': 3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/boolean-prop': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/chain-call': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/common': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/config': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-emit': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-models': 3.1.2(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-prop': 3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-props': 3.1.2(@vue-macros/reactivity-transform@3.1.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-props-refs': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-render': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-slots': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-stylex': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/devtools': 3.1.2(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
'@vue-macros/export-expose': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/export-props': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/export-render': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/hoist-static': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/jsx-directive': 3.1.2(typescript@5.9.3)
|
||||
'@vue-macros/named-template': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/reactivity-transform': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/script-lang': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/setup-block': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/setup-component': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/setup-sfc': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/short-bind': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/short-emits': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/short-vmodel': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/volar': 3.1.2(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3))
|
||||
unplugin: 2.3.11
|
||||
unplugin-combine: 2.3.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(unplugin@2.3.11)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
unplugin-vue-define-options: 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
transitivePeerDependencies:
|
||||
- '@emnapi/core'
|
||||
- '@emnapi/runtime'
|
||||
- '@rspack/core'
|
||||
- '@vueuse/core'
|
||||
- esbuild
|
||||
- rolldown
|
||||
- rollup
|
||||
- typescript
|
||||
- vite
|
||||
- vue-tsc
|
||||
- webpack
|
||||
|
||||
vue-macros@3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@vue-macros/better-define': 3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vue@3.5.32(typescript@5.9.3))
|
||||
|
|
|
|||
|
|
@ -321,7 +321,6 @@ catalog:
|
|||
postcss: ^8.5.10
|
||||
postgres: ^3.4.9
|
||||
posthog-js: 1.306.1
|
||||
posthog-node: ^5.34.1
|
||||
postprocessing: ^6.39.1
|
||||
prismarine-block: ^1.23.0
|
||||
prismarine-entity: ^2.6.0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue