@burdenoff/microfe-vibecontrols 2026.601.11 → 2026.601.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,24 +9,19 @@ var t = e`
9
9
  }
10
10
  }
11
11
  `, n = e`
12
- query GetAiCreditsQuotaSummary($billingAccountId: ID!) {
13
- getBillingAccountQuotasSummary(
12
+ query GetAiCreditsBalance($billingAccountId: ID!) {
13
+ getQuotaUsageAndLimit(
14
14
  billingAccountId: $billingAccountId
15
+ quotaName: "vibecontrols.ai.credits"
15
16
  productId: "vibecontrols"
16
17
  ) {
17
- billingAccountId
18
- subscriptionQuotas {
19
- name
20
- limit
21
- limitLeft
22
- used
23
- noLimit
24
- usagePercentage
25
- }
18
+ limit
19
+ limitLeft
20
+ noLimit
26
21
  }
27
22
  }
28
23
  `;
29
24
  //#endregion
30
- export { n as GetAiCreditsQuotaSummaryDocument, t as GetMyBillingAccountsDocument };
25
+ export { n as GetAiCreditsBalanceDocument, t as GetMyBillingAccountsDocument };
31
26
 
32
27
  //# sourceMappingURL=global-operations.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"global-operations.js","names":[],"sources":["../../src/generated/global-operations.ts"],"sourcesContent":["// @ts-nocheck\nimport * as Types from './global-types';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nimport * as ApolloReactHooks from '@apollo/client/react';\nconst defaultOptions = {} as const;\nexport type GetMyBillingAccountsQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type GetMyBillingAccountsQuery = { __typename?: 'Query', getBillingAccountsByOrg: Array<{ __typename?: 'BillingAccount', id?: string | null, isDefault?: boolean | null }> };\n\nexport type GetAiCreditsQuotaSummaryQueryVariables = Types.Exact<{\n billingAccountId: Types.Scalars['ID']['input'];\n}>;\n\n\nexport type GetAiCreditsQuotaSummaryQuery = { __typename?: 'Query', getBillingAccountQuotasSummary: { __typename?: 'BillingAccountQuotasSummary', billingAccountId: string, subscriptionQuotas: Array<{ __typename?: 'QuotaAssignmentUsageSummary', name: string, limit: number, limitLeft: number, used: number, noLimit: boolean, usagePercentage: number }> } };\n\n\nexport const GetMyBillingAccountsDocument = gql`\n query GetMyBillingAccounts {\n getBillingAccountsByOrg {\n id\n isDefault\n }\n}\n `;\n\n/**\n * __useGetMyBillingAccountsQuery__\n *\n * To run a query within a React component, call `useGetMyBillingAccountsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMyBillingAccountsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMyBillingAccountsQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetMyBillingAccountsQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>) {\n const options = {...defaultOptions, ...baseOptions}\n return ApolloReactHooks.useQuery<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>(GetMyBillingAccountsDocument, options);\n }\nexport function useGetMyBillingAccountsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>) {\n const options = {...defaultOptions, ...baseOptions}\n return ApolloReactHooks.useLazyQuery<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>(GetMyBillingAccountsDocument, options);\n }\n// @ts-ignore\nexport function useGetMyBillingAccountsSuspenseQuery(baseOptions?: ApolloReactHooks.SuspenseQueryHookOptions<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>): ApolloReactHooks.UseSuspenseQueryResult<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>;\nexport function useGetMyBillingAccountsSuspenseQuery(baseOptions?: ApolloReactHooks.SkipToken | ApolloReactHooks.SuspenseQueryHookOptions<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>): ApolloReactHooks.UseSuspenseQueryResult<Types.GetMyBillingAccountsQuery | undefined, Types.GetMyBillingAccountsQueryVariables>;\nexport function useGetMyBillingAccountsSuspenseQuery(baseOptions?: ApolloReactHooks.SkipToken | ApolloReactHooks.SuspenseQueryHookOptions<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>) {\n const options = baseOptions === ApolloReactHooks.skipToken ? baseOptions : {...defaultOptions, ...baseOptions}\n return ApolloReactHooks.useSuspenseQuery<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>(GetMyBillingAccountsDocument, options);\n }\nexport type GetMyBillingAccountsQueryHookResult = ReturnType<typeof useGetMyBillingAccountsQuery>;\nexport type GetMyBillingAccountsLazyQueryHookResult = ReturnType<typeof useGetMyBillingAccountsLazyQuery>;\nexport type GetMyBillingAccountsSuspenseQueryHookResult = ReturnType<typeof useGetMyBillingAccountsSuspenseQuery>;\nexport type GetMyBillingAccountsQueryResult = Apollo.QueryResult<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>;\nexport const GetAiCreditsQuotaSummaryDocument = gql`\n query GetAiCreditsQuotaSummary($billingAccountId: ID!) {\n getBillingAccountQuotasSummary(\n billingAccountId: $billingAccountId\n productId: \"vibecontrols\"\n ) {\n billingAccountId\n subscriptionQuotas {\n name\n limit\n limitLeft\n used\n noLimit\n usagePercentage\n }\n }\n}\n `;\n\n/**\n * __useGetAiCreditsQuotaSummaryQuery__\n *\n * To run a query within a React component, call `useGetAiCreditsQuotaSummaryQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetAiCreditsQuotaSummaryQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetAiCreditsQuotaSummaryQuery({\n * variables: {\n * billingAccountId: // value for 'billingAccountId'\n * },\n * });\n */\nexport function useGetAiCreditsQuotaSummaryQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types.GetAiCreditsQuotaSummaryQuery, Types.GetAiCreditsQuotaSummaryQueryVariables> & ({ variables: Types.GetAiCreditsQuotaSummaryQueryVariables; skip?: boolean; } | { skip: boolean; }) ) {\n const options = {...defaultOptions, ...baseOptions}\n return ApolloReactHooks.useQuery<Types.GetAiCreditsQuotaSummaryQuery, Types.GetAiCreditsQuotaSummaryQueryVariables>(GetAiCreditsQuotaSummaryDocument, options);\n }\nexport function useGetAiCreditsQuotaSummaryLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.GetAiCreditsQuotaSummaryQuery, Types.GetAiCreditsQuotaSummaryQueryVariables>) {\n const options = {...defaultOptions, ...baseOptions}\n return ApolloReactHooks.useLazyQuery<Types.GetAiCreditsQuotaSummaryQuery, Types.GetAiCreditsQuotaSummaryQueryVariables>(GetAiCreditsQuotaSummaryDocument, options);\n }\n// @ts-ignore\nexport function useGetAiCreditsQuotaSummarySuspenseQuery(baseOptions?: ApolloReactHooks.SuspenseQueryHookOptions<Types.GetAiCreditsQuotaSummaryQuery, Types.GetAiCreditsQuotaSummaryQueryVariables>): ApolloReactHooks.UseSuspenseQueryResult<Types.GetAiCreditsQuotaSummaryQuery, Types.GetAiCreditsQuotaSummaryQueryVariables>;\nexport function useGetAiCreditsQuotaSummarySuspenseQuery(baseOptions?: ApolloReactHooks.SkipToken | ApolloReactHooks.SuspenseQueryHookOptions<Types.GetAiCreditsQuotaSummaryQuery, Types.GetAiCreditsQuotaSummaryQueryVariables>): ApolloReactHooks.UseSuspenseQueryResult<Types.GetAiCreditsQuotaSummaryQuery | undefined, Types.GetAiCreditsQuotaSummaryQueryVariables>;\nexport function useGetAiCreditsQuotaSummarySuspenseQuery(baseOptions?: ApolloReactHooks.SkipToken | ApolloReactHooks.SuspenseQueryHookOptions<Types.GetAiCreditsQuotaSummaryQuery, Types.GetAiCreditsQuotaSummaryQueryVariables>) {\n const options = baseOptions === ApolloReactHooks.skipToken ? baseOptions : {...defaultOptions, ...baseOptions}\n return ApolloReactHooks.useSuspenseQuery<Types.GetAiCreditsQuotaSummaryQuery, Types.GetAiCreditsQuotaSummaryQueryVariables>(GetAiCreditsQuotaSummaryDocument, options);\n }\nexport type GetAiCreditsQuotaSummaryQueryHookResult = ReturnType<typeof useGetAiCreditsQuotaSummaryQuery>;\nexport type GetAiCreditsQuotaSummaryLazyQueryHookResult = ReturnType<typeof useGetAiCreditsQuotaSummaryLazyQuery>;\nexport type GetAiCreditsQuotaSummarySuspenseQueryHookResult = ReturnType<typeof useGetAiCreditsQuotaSummarySuspenseQuery>;\nexport type GetAiCreditsQuotaSummaryQueryResult = Apollo.QueryResult<Types.GetAiCreditsQuotaSummaryQuery, Types.GetAiCreditsQuotaSummaryQueryVariables>;"],"mappings":";;;AAoBA,IAAa,IAA+B,CAAG;;;;;;;OA2ClC,IAAmC,CAAG"}
1
+ {"version":3,"file":"global-operations.js","names":[],"sources":["../../src/generated/global-operations.ts"],"sourcesContent":["// @ts-nocheck\nimport * as Types from './global-types';\n\nimport { gql } from '@apollo/client';\nimport * as Apollo from '@apollo/client';\nimport * as ApolloReactHooks from '@apollo/client/react';\nconst defaultOptions = {} as const;\nexport type GetMyBillingAccountsQueryVariables = Types.Exact<{ [key: string]: never; }>;\n\n\nexport type GetMyBillingAccountsQuery = { __typename?: 'Query', getBillingAccountsByOrg: Array<{ __typename?: 'BillingAccount', id?: string | null, isDefault?: boolean | null }> };\n\nexport type GetAiCreditsBalanceQueryVariables = Types.Exact<{\n billingAccountId: Types.Scalars['ID']['input'];\n}>;\n\n\nexport type GetAiCreditsBalanceQuery = { __typename?: 'Query', getQuotaUsageAndLimit: { __typename?: 'QuotaUsageAndLimit', limit: number, limitLeft: number, noLimit: boolean } };\n\n\nexport const GetMyBillingAccountsDocument = gql`\n query GetMyBillingAccounts {\n getBillingAccountsByOrg {\n id\n isDefault\n }\n}\n `;\n\n/**\n * __useGetMyBillingAccountsQuery__\n *\n * To run a query within a React component, call `useGetMyBillingAccountsQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetMyBillingAccountsQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetMyBillingAccountsQuery({\n * variables: {\n * },\n * });\n */\nexport function useGetMyBillingAccountsQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>) {\n const options = {...defaultOptions, ...baseOptions}\n return ApolloReactHooks.useQuery<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>(GetMyBillingAccountsDocument, options);\n }\nexport function useGetMyBillingAccountsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>) {\n const options = {...defaultOptions, ...baseOptions}\n return ApolloReactHooks.useLazyQuery<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>(GetMyBillingAccountsDocument, options);\n }\n// @ts-ignore\nexport function useGetMyBillingAccountsSuspenseQuery(baseOptions?: ApolloReactHooks.SuspenseQueryHookOptions<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>): ApolloReactHooks.UseSuspenseQueryResult<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>;\nexport function useGetMyBillingAccountsSuspenseQuery(baseOptions?: ApolloReactHooks.SkipToken | ApolloReactHooks.SuspenseQueryHookOptions<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>): ApolloReactHooks.UseSuspenseQueryResult<Types.GetMyBillingAccountsQuery | undefined, Types.GetMyBillingAccountsQueryVariables>;\nexport function useGetMyBillingAccountsSuspenseQuery(baseOptions?: ApolloReactHooks.SkipToken | ApolloReactHooks.SuspenseQueryHookOptions<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>) {\n const options = baseOptions === ApolloReactHooks.skipToken ? baseOptions : {...defaultOptions, ...baseOptions}\n return ApolloReactHooks.useSuspenseQuery<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>(GetMyBillingAccountsDocument, options);\n }\nexport type GetMyBillingAccountsQueryHookResult = ReturnType<typeof useGetMyBillingAccountsQuery>;\nexport type GetMyBillingAccountsLazyQueryHookResult = ReturnType<typeof useGetMyBillingAccountsLazyQuery>;\nexport type GetMyBillingAccountsSuspenseQueryHookResult = ReturnType<typeof useGetMyBillingAccountsSuspenseQuery>;\nexport type GetMyBillingAccountsQueryResult = Apollo.QueryResult<Types.GetMyBillingAccountsQuery, Types.GetMyBillingAccountsQueryVariables>;\nexport const GetAiCreditsBalanceDocument = gql`\n query GetAiCreditsBalance($billingAccountId: ID!) {\n getQuotaUsageAndLimit(\n billingAccountId: $billingAccountId\n quotaName: \"vibecontrols.ai.credits\"\n productId: \"vibecontrols\"\n ) {\n limit\n limitLeft\n noLimit\n }\n}\n `;\n\n/**\n * __useGetAiCreditsBalanceQuery__\n *\n * To run a query within a React component, call `useGetAiCreditsBalanceQuery` and pass it any options that fit your needs.\n * When your component renders, `useGetAiCreditsBalanceQuery` returns an object from Apollo Client that contains loading, error, and data properties\n * you can use to render your UI.\n *\n * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;\n *\n * @example\n * const { data, loading, error } = useGetAiCreditsBalanceQuery({\n * variables: {\n * billingAccountId: // value for 'billingAccountId'\n * },\n * });\n */\nexport function useGetAiCreditsBalanceQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types.GetAiCreditsBalanceQuery, Types.GetAiCreditsBalanceQueryVariables> & ({ variables: Types.GetAiCreditsBalanceQueryVariables; skip?: boolean; } | { skip: boolean; }) ) {\n const options = {...defaultOptions, ...baseOptions}\n return ApolloReactHooks.useQuery<Types.GetAiCreditsBalanceQuery, Types.GetAiCreditsBalanceQueryVariables>(GetAiCreditsBalanceDocument, options);\n }\nexport function useGetAiCreditsBalanceLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.GetAiCreditsBalanceQuery, Types.GetAiCreditsBalanceQueryVariables>) {\n const options = {...defaultOptions, ...baseOptions}\n return ApolloReactHooks.useLazyQuery<Types.GetAiCreditsBalanceQuery, Types.GetAiCreditsBalanceQueryVariables>(GetAiCreditsBalanceDocument, options);\n }\n// @ts-ignore\nexport function useGetAiCreditsBalanceSuspenseQuery(baseOptions?: ApolloReactHooks.SuspenseQueryHookOptions<Types.GetAiCreditsBalanceQuery, Types.GetAiCreditsBalanceQueryVariables>): ApolloReactHooks.UseSuspenseQueryResult<Types.GetAiCreditsBalanceQuery, Types.GetAiCreditsBalanceQueryVariables>;\nexport function useGetAiCreditsBalanceSuspenseQuery(baseOptions?: ApolloReactHooks.SkipToken | ApolloReactHooks.SuspenseQueryHookOptions<Types.GetAiCreditsBalanceQuery, Types.GetAiCreditsBalanceQueryVariables>): ApolloReactHooks.UseSuspenseQueryResult<Types.GetAiCreditsBalanceQuery | undefined, Types.GetAiCreditsBalanceQueryVariables>;\nexport function useGetAiCreditsBalanceSuspenseQuery(baseOptions?: ApolloReactHooks.SkipToken | ApolloReactHooks.SuspenseQueryHookOptions<Types.GetAiCreditsBalanceQuery, Types.GetAiCreditsBalanceQueryVariables>) {\n const options = baseOptions === ApolloReactHooks.skipToken ? baseOptions : {...defaultOptions, ...baseOptions}\n return ApolloReactHooks.useSuspenseQuery<Types.GetAiCreditsBalanceQuery, Types.GetAiCreditsBalanceQueryVariables>(GetAiCreditsBalanceDocument, options);\n }\nexport type GetAiCreditsBalanceQueryHookResult = ReturnType<typeof useGetAiCreditsBalanceQuery>;\nexport type GetAiCreditsBalanceLazyQueryHookResult = ReturnType<typeof useGetAiCreditsBalanceLazyQuery>;\nexport type GetAiCreditsBalanceSuspenseQueryHookResult = ReturnType<typeof useGetAiCreditsBalanceSuspenseQuery>;\nexport type GetAiCreditsBalanceQueryResult = Apollo.QueryResult<Types.GetAiCreditsBalanceQuery, Types.GetAiCreditsBalanceQueryVariables>;"],"mappings":";;;AAoBA,IAAa,IAA+B,CAAG;;;;;;;OA2ClC,IAA8B,CAAG"}
@@ -1,47 +1,54 @@
1
1
  import { AI_CREDITS_UPDATED_EVENT as e } from "../utils/aiCredits.js";
2
- import { GetAiCreditsQuotaSummaryDocument as t, GetMyBillingAccountsDocument as n } from "../generated/global-operations.js";
2
+ import { GetAiCreditsBalanceDocument as t, GetMyBillingAccountsDocument as n } from "../generated/global-operations.js";
3
3
  import { useEffect as r } from "react";
4
4
  import { useQuery as i, useQueryClient as a } from "@tanstack/react-query";
5
5
  import { useSafeGatewayClient as o } from "@burdenoff/fe-libs/shared/graphql";
6
6
  //#region src/hooks/useAiCreditsQuota.ts
7
- var s = "vibecontrols.ai.credits", c = ["vibecontrols", "ai-credits-quota"];
8
- function l() {
9
- let l = o("global"), u = a(), d = i({
10
- queryKey: c,
11
- enabled: !!l,
7
+ var s = ["vibecontrols", "ai-credits-quota"];
8
+ function c() {
9
+ let c = o("global"), l = a(), u = i({
10
+ queryKey: s,
11
+ enabled: !!c,
12
12
  staleTime: 3e4,
13
13
  queryFn: async () => {
14
- if (!l) return null;
15
- let e = (await l.query({
14
+ if (!c) return null;
15
+ let e = (await c.query({
16
16
  query: n,
17
17
  fetchPolicy: "network-only",
18
18
  errorPolicy: "all"
19
19
  })).data?.getBillingAccountsByOrg ?? [], r = e.find((e) => e?.isDefault) ?? e[0];
20
20
  if (!r?.id) return null;
21
- let i = ((await l.query({
21
+ let i = (await c.query({
22
22
  query: t,
23
23
  variables: { billingAccountId: r.id },
24
24
  fetchPolicy: "network-only",
25
25
  errorPolicy: "all"
26
- })).data?.getBillingAccountQuotasSummary?.subscriptionQuotas ?? []).find((e) => e?.name === s);
27
- return i ? {
28
- used: i.used ?? 0,
29
- limit: i.noLimit ? null : i.limit ?? null,
30
- noLimit: !!i.noLimit
31
- } : null;
26
+ })).data?.getQuotaUsageAndLimit;
27
+ if (!i) return null;
28
+ if (i.noLimit) return {
29
+ used: 0,
30
+ limit: null,
31
+ noLimit: !0
32
+ };
33
+ let a = i.limit ?? 0, o = i.limitLeft ?? 0;
34
+ return {
35
+ used: Math.max(0, a - o),
36
+ limit: a,
37
+ noLimit: !1
38
+ };
32
39
  }
33
40
  });
34
41
  return r(() => {
35
42
  let t = () => {
36
- u.invalidateQueries({ queryKey: c });
43
+ l.invalidateQueries({ queryKey: s });
37
44
  };
38
45
  return window.addEventListener(e, t), () => window.removeEventListener(e, t);
39
- }, [u]), {
40
- data: d.data ?? null,
41
- loading: d.isLoading
46
+ }, [l]), {
47
+ data: u.data ?? null,
48
+ loading: u.isLoading
42
49
  };
43
50
  }
44
51
  //#endregion
45
- export { l as useAiCreditsQuota };
52
+ export { c as useAiCreditsQuota };
46
53
 
47
54
  //# sourceMappingURL=useAiCreditsQuota.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAiCreditsQuota.js","names":[],"sources":["../../src/hooks/useAiCreditsQuota.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\nimport { useSafeGatewayClient } from '@burdenoff/fe-libs/shared/graphql';\nimport {\n GetMyBillingAccountsDocument,\n GetAiCreditsQuotaSummaryDocument,\n type GetMyBillingAccountsQuery,\n type GetAiCreditsQuotaSummaryQuery,\n} from '@/generated/global-operations';\nimport { AI_CREDITS_UPDATED_EVENT } from '@/utils/aiCredits';\n\nconst AI_CREDITS_QUOTA_NAME = 'vibecontrols.ai.credits';\nconst QUERY_KEY = ['vibecontrols', 'ai-credits-quota'] as const;\n\n// Minimal shapes for the fields we read. The generated global-operations are\n// emitted with `// @ts-nocheck`, so the query result is effectively untyped at\n// the call site — these narrow it back to just what the meter consumes.\ninterface BillingAccountLite {\n id?: string | null;\n isDefault?: boolean | null;\n}\n\ninterface QuotaSummaryLite {\n name?: string | null;\n used?: number | null;\n limit?: number | null;\n noLimit?: boolean | null;\n}\n\nexport interface AiCreditsQuota {\n /** Tokens consumed this billing cycle. */\n used: number;\n /** Plan limit in tokens, or null when the plan grants unlimited credits. */\n limit: number | null;\n noLimit: boolean;\n}\n\n/**\n * Live AI-credits balance for the org's default billing account, read from\n * billing's real-time `getBillingAccountQuotasSummary` (NOT the periodic\n * quota scraper, which only tracks countable resources). Returns null when\n * there's no global gateway (standalone preview), no billing account, or no\n * ai-credits quota assigned — callers should hide the meter in that case.\n *\n * Refetches when an assistant turn charges credits (AI_CREDITS_UPDATED_EVENT).\n */\nexport function useAiCreditsQuota(): { data: AiCreditsQuota | null; loading: boolean } {\n const globalClient = useSafeGatewayClient('global');\n const queryClient = useQueryClient();\n\n const query = useQuery<AiCreditsQuota | null>({\n queryKey: QUERY_KEY,\n enabled: !!globalClient,\n staleTime: 30_000,\n queryFn: async () => {\n if (!globalClient) return null;\n\n // 1. Resolve the org's default billing account (gateway infers the org).\n const accountsRes = await globalClient.query<GetMyBillingAccountsQuery>({\n query: GetMyBillingAccountsDocument,\n fetchPolicy: 'network-only',\n errorPolicy: 'all',\n });\n const accounts = (accountsRes.data?.getBillingAccountsByOrg ?? []) as BillingAccountLite[];\n const account = accounts.find((a) => a?.isDefault) ?? accounts[0];\n if (!account?.id) return null;\n\n // 2. Read the real-time quota summary; pick the ai-credits quota.\n const summaryRes = await globalClient.query<GetAiCreditsQuotaSummaryQuery>({\n query: GetAiCreditsQuotaSummaryDocument,\n variables: { billingAccountId: account.id },\n fetchPolicy: 'network-only',\n errorPolicy: 'all',\n });\n const quotas = (summaryRes.data?.getBillingAccountQuotasSummary?.subscriptionQuotas ??\n []) as QuotaSummaryLite[];\n const credit = quotas.find((q) => q?.name === AI_CREDITS_QUOTA_NAME);\n if (!credit) return null;\n\n return {\n used: credit.used ?? 0,\n limit: credit.noLimit ? null : (credit.limit ?? null),\n noLimit: !!credit.noLimit,\n };\n },\n });\n\n useEffect(() => {\n const handler = () => {\n void queryClient.invalidateQueries({ queryKey: QUERY_KEY });\n };\n window.addEventListener(AI_CREDITS_UPDATED_EVENT, handler);\n return () => window.removeEventListener(AI_CREDITS_UPDATED_EVENT, handler);\n }, [queryClient]);\n\n return { data: query.data ?? null, loading: query.isLoading };\n}\n"],"mappings":";;;;;;AAWA,IAAM,IAAwB,2BACxB,IAAY,CAAC,gBAAgB,mBAAmB;AAkCtD,SAAgB,IAAuE;CACrF,IAAM,IAAe,EAAqB,SAAS,EAC7C,IAAc,GAAgB,EAE9B,IAAQ,EAAgC;EAC5C,UAAU;EACV,SAAS,CAAC,CAAC;EACX,WAAW;EACX,SAAS,YAAY;AACnB,OAAI,CAAC,EAAc,QAAO;GAQ1B,IAAM,KALc,MAAM,EAAa,MAAiC;IACtE,OAAO;IACP,aAAa;IACb,aAAa;IACd,CAAC,EAC4B,MAAM,2BAA2B,EAAE,EAC3D,IAAU,EAAS,MAAM,MAAM,GAAG,UAAU,IAAI,EAAS;AAC/D,OAAI,CAAC,GAAS,GAAI,QAAO;GAWzB,IAAM,MARa,MAAM,EAAa,MAAqC;IACzE,OAAO;IACP,WAAW,EAAE,kBAAkB,EAAQ,IAAI;IAC3C,aAAa;IACb,aAAa;IACd,CAAC,EACyB,MAAM,gCAAgC,sBAC/D,EAAE,EACkB,MAAM,MAAM,GAAG,SAAS,EAAsB;AAGpE,UAFK,IAEE;IACL,MAAM,EAAO,QAAQ;IACrB,OAAO,EAAO,UAAU,OAAQ,EAAO,SAAS;IAChD,SAAS,CAAC,CAAC,EAAO;IACnB,GANmB;;EAQvB,CAAC;AAUF,QARA,QAAgB;EACd,IAAM,UAAgB;AACf,KAAY,kBAAkB,EAAE,UAAU,GAAW,CAAC;;AAG7D,SADA,OAAO,iBAAiB,GAA0B,EAAQ,QAC7C,OAAO,oBAAoB,GAA0B,EAAQ;IACzE,CAAC,EAAY,CAAC,EAEV;EAAE,MAAM,EAAM,QAAQ;EAAM,SAAS,EAAM;EAAW"}
1
+ {"version":3,"file":"useAiCreditsQuota.js","names":[],"sources":["../../src/hooks/useAiCreditsQuota.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\nimport { useSafeGatewayClient } from '@burdenoff/fe-libs/shared/graphql';\nimport {\n GetMyBillingAccountsDocument,\n GetAiCreditsBalanceDocument,\n type GetMyBillingAccountsQuery,\n type GetAiCreditsBalanceQuery,\n} from '@/generated/global-operations';\nimport { AI_CREDITS_UPDATED_EVENT } from '@/utils/aiCredits';\n\nconst QUERY_KEY = ['vibecontrols', 'ai-credits-quota'] as const;\n\n// Minimal shapes for the fields we read. The generated global-operations are\n// emitted with `// @ts-nocheck`, so the query result is effectively untyped at\n// the call site — these narrow it back to just what the meter consumes.\ninterface BillingAccountLite {\n id?: string | null;\n isDefault?: boolean | null;\n}\n\ninterface QuotaBalanceLite {\n /** Original granted limit (= assignment `originalValue`). */\n limit?: number | null;\n /** Spendable balance remaining (= assignment current `value`). */\n limitLeft?: number | null;\n noLimit?: boolean | null;\n}\n\nexport interface AiCreditsQuota {\n /** Tokens consumed this billing cycle. */\n used: number;\n /** Plan limit in tokens, or null when the plan grants unlimited credits. */\n limit: number | null;\n noLimit: boolean;\n}\n\n/**\n * Live AI-credits balance for the org's default billing account.\n *\n * Reads `getQuotaUsageAndLimit`, which returns the SAME decrementing quota\n * assignment balance the gateway `@usage` check enforces against — so the meter\n * matches the real spendable budget and the block dialog. `used` is derived as\n * `limit - limitLeft`.\n *\n * We intentionally avoid `getBillingAccountQuotasSummary`: its `used`/`limitLeft`\n * come from the activity-service usage rollup, which does not capture the\n * `@usage(trackUsage)` token charges, so it reported `used: 0` while the balance\n * was correctly debited.\n *\n * Returns null when there's no global gateway (standalone preview), no billing\n * account, or no ai-credits quota assigned — callers should hide the meter.\n * Refetches when an assistant turn charges credits (AI_CREDITS_UPDATED_EVENT).\n */\nexport function useAiCreditsQuota(): { data: AiCreditsQuota | null; loading: boolean } {\n const globalClient = useSafeGatewayClient('global');\n const queryClient = useQueryClient();\n\n const query = useQuery<AiCreditsQuota | null>({\n queryKey: QUERY_KEY,\n enabled: !!globalClient,\n staleTime: 30_000,\n queryFn: async () => {\n if (!globalClient) return null;\n\n // 1. Resolve the org's default billing account (gateway infers the org).\n const accountsRes = await globalClient.query<GetMyBillingAccountsQuery>({\n query: GetMyBillingAccountsDocument,\n fetchPolicy: 'network-only',\n errorPolicy: 'all',\n });\n const accounts = (accountsRes.data?.getBillingAccountsByOrg ?? []) as BillingAccountLite[];\n const account = accounts.find((a) => a?.isDefault) ?? accounts[0];\n if (!account?.id) return null;\n\n // 2. Read the real spendable balance for the ai-credits quota (same source\n // the enforcement gate uses). Throws server-side when the account has no\n // assignment → errorPolicy:'all' surfaces null data → meter hidden.\n const balanceRes = await globalClient.query<GetAiCreditsBalanceQuery>({\n query: GetAiCreditsBalanceDocument,\n variables: { billingAccountId: account.id },\n fetchPolicy: 'network-only',\n errorPolicy: 'all',\n });\n const balance = balanceRes.data?.getQuotaUsageAndLimit as QuotaBalanceLite | null | undefined;\n if (!balance) return null;\n\n if (balance.noLimit) {\n return { used: 0, limit: null, noLimit: true };\n }\n\n const limit = balance.limit ?? 0;\n const limitLeft = balance.limitLeft ?? 0;\n return {\n used: Math.max(0, limit - limitLeft),\n limit,\n noLimit: false,\n };\n },\n });\n\n useEffect(() => {\n const handler = () => {\n void queryClient.invalidateQueries({ queryKey: QUERY_KEY });\n };\n window.addEventListener(AI_CREDITS_UPDATED_EVENT, handler);\n return () => window.removeEventListener(AI_CREDITS_UPDATED_EVENT, handler);\n }, [queryClient]);\n\n return { data: query.data ?? null, loading: query.isLoading };\n}\n"],"mappings":";;;;;;AAWA,IAAM,IAAY,CAAC,gBAAgB,mBAAmB;AA2CtD,SAAgB,IAAuE;CACrF,IAAM,IAAe,EAAqB,SAAS,EAC7C,IAAc,GAAgB,EAE9B,IAAQ,EAAgC;EAC5C,UAAU;EACV,SAAS,CAAC,CAAC;EACX,WAAW;EACX,SAAS,YAAY;AACnB,OAAI,CAAC,EAAc,QAAO;GAQ1B,IAAM,KALc,MAAM,EAAa,MAAiC;IACtE,OAAO;IACP,aAAa;IACb,aAAa;IACd,CAAC,EAC4B,MAAM,2BAA2B,EAAE,EAC3D,IAAU,EAAS,MAAM,MAAM,GAAG,UAAU,IAAI,EAAS;AAC/D,OAAI,CAAC,GAAS,GAAI,QAAO;GAWzB,IAAM,KANa,MAAM,EAAa,MAAgC;IACpE,OAAO;IACP,WAAW,EAAE,kBAAkB,EAAQ,IAAI;IAC3C,aAAa;IACb,aAAa;IACd,CAAC,EACyB,MAAM;AACjC,OAAI,CAAC,EAAS,QAAO;AAErB,OAAI,EAAQ,QACV,QAAO;IAAE,MAAM;IAAG,OAAO;IAAM,SAAS;IAAM;GAGhD,IAAM,IAAQ,EAAQ,SAAS,GACzB,IAAY,EAAQ,aAAa;AACvC,UAAO;IACL,MAAM,KAAK,IAAI,GAAG,IAAQ,EAAU;IACpC;IACA,SAAS;IACV;;EAEJ,CAAC;AAUF,QARA,QAAgB;EACd,IAAM,UAAgB;AACf,KAAY,kBAAkB,EAAE,UAAU,GAAW,CAAC;;AAG7D,SADA,OAAO,iBAAiB,GAA0B,EAAQ,QAC7C,OAAO,oBAAoB,GAA0B,EAAQ;IACzE,CAAC,EAAY,CAAC,EAEV;EAAE,MAAM,EAAM,QAAQ;EAAM,SAAS,EAAM;EAAW"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-vibecontrols",
3
- "version": "2026.601.11",
3
+ "version": "2026.601.12",
4
4
  "description": "VibeControls microfrontend for Burdenoff products",
5
5
  "type": "module",
6
6
  "files": [