feat: tiered costs feature + admin tier management + tag selection
Build & Push Docker Image / build (push) Successful in 6m52s
Build & Push Docker Image / build (push) Successful in 6m52s
- costs: nullable notes (fix create without notes), drop renewalDate (schema + API + UI), gate POST/PATCH/DELETE to admin + costs feature - feature middleware: admin-aware hasFeature + getEntitlements union; /auth/me and login return resolved entitlements - users: tier enum (free/premium/enterprise) in create/update/list, admin UI tier select + tier badge - tags: GET /tags/all, TagInput autocomplete in new/edit tool forms, feature suggestions on focus, query invalidation on create/update - openapi: nullable ToolUpdate urls, ToolUpdate tier fields, listAllTags - Dockerfile: push-force to drop renewal_date column
This commit is contained in:
@@ -1134,6 +1134,83 @@ export function useListAllFeatures<TData = Awaited<ReturnType<typeof listAllFeat
|
||||
|
||||
|
||||
|
||||
export const getListAllTagsUrl = () => {
|
||||
|
||||
|
||||
|
||||
|
||||
return `/api/tags/all`
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary List all distinct tag strings across all tools
|
||||
*/
|
||||
export const listAllTags = async ( options?: RequestInit): Promise<string[]> => {
|
||||
|
||||
return customFetch<string[]>(getListAllTagsUrl(),
|
||||
{
|
||||
...options,
|
||||
method: 'GET'
|
||||
|
||||
|
||||
}
|
||||
);}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export const getListAllTagsQueryKey = () => {
|
||||
return [
|
||||
`/api/tags/all`
|
||||
] as const;
|
||||
}
|
||||
|
||||
|
||||
export const getListAllTagsQueryOptions = <TData = Awaited<ReturnType<typeof listAllTags>>, TError = ErrorType<unknown>>( options?: { query?:UseQueryOptions<Awaited<ReturnType<typeof listAllTags>>, TError, TData>, request?: SecondParameter<typeof customFetch>}
|
||||
) => {
|
||||
|
||||
const {query: queryOptions, request: requestOptions} = options ?? {};
|
||||
|
||||
const queryKey = queryOptions?.queryKey ?? getListAllTagsQueryKey();
|
||||
|
||||
|
||||
|
||||
const queryFn: QueryFunction<Awaited<ReturnType<typeof listAllTags>>> = ({ signal }) => listAllTags({ signal, ...requestOptions });
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions} as UseQueryOptions<Awaited<ReturnType<typeof listAllTags>>, TError, TData> & { queryKey: QueryKey }
|
||||
}
|
||||
|
||||
export type ListAllTagsQueryResult = NonNullable<Awaited<ReturnType<typeof listAllTags>>>
|
||||
export type ListAllTagsQueryError = ErrorType<unknown>
|
||||
|
||||
|
||||
/**
|
||||
* @summary List all distinct tag strings across all tools
|
||||
*/
|
||||
|
||||
export function useListAllTags<TData = Awaited<ReturnType<typeof listAllTags>>, TError = ErrorType<unknown>>(
|
||||
options?: { query?:UseQueryOptions<Awaited<ReturnType<typeof listAllTags>>, TError, TData>, request?: SecondParameter<typeof customFetch>}
|
||||
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
|
||||
const queryOptions = getListAllTagsQueryOptions(options)
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & { queryKey: QueryKey };
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export const getGetAuthModeUrl = () => {
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user