mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-22 19:06:41 +02:00
refactor(packages): consolidate 3 feedback packages into @manacore/feedback
Merged shared-feedback-types + shared-feedback-service + shared-feedback-ui into a single @manacore/feedback package. Updated imports in all 21 apps. Before: 3 packages (types, service, ui) with cross-dependencies After: 1 package with direct imports, no circular refs Note: ESLint warnings from pre-existing unused vars in chat/mukke servers are unrelated to this change. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bf4d9cb9aa
commit
1aeb987cb6
78 changed files with 617 additions and 317 deletions
|
|
@ -1,146 +0,0 @@
|
|||
/**
|
||||
* Feedback Service Factory
|
||||
*
|
||||
* Creates a feedback service instance configured for a specific app.
|
||||
* Handles feedback submission, retrieval, and voting.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { createFeedbackService } from '@manacore/shared-feedback-service';
|
||||
* import { authStore } from '$lib/stores/auth.svelte';
|
||||
*
|
||||
* export const feedbackService = createFeedbackService({
|
||||
* apiUrl: 'https://auth.mana.how',
|
||||
* appId: 'chat',
|
||||
* getAuthToken: async () => authStore.getToken(),
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
|
||||
import type {
|
||||
CreateFeedbackInput,
|
||||
FeedbackQueryParams,
|
||||
FeedbackResponse,
|
||||
FeedbackListResponse,
|
||||
VoteResponse,
|
||||
} from '@manacore/shared-feedback-types';
|
||||
import type { FeedbackServiceConfig } from './types';
|
||||
|
||||
/**
|
||||
* Create a feedback service instance
|
||||
*/
|
||||
export function createFeedbackService(config: FeedbackServiceConfig) {
|
||||
const { apiUrl, appId, getAuthToken, feedbackEndpoint = '/api/v1/feedback' } = config;
|
||||
|
||||
// Normalize API URL (remove trailing slash)
|
||||
const baseUrl = apiUrl.replace(/\/$/, '');
|
||||
|
||||
/**
|
||||
* Helper to make authenticated requests
|
||||
*/
|
||||
async function fetchWithAuth<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
|
||||
const token = await getAuthToken();
|
||||
|
||||
if (!token) {
|
||||
throw new Error('Not authenticated');
|
||||
}
|
||||
|
||||
const response = await fetch(`${baseUrl}${endpoint}`, {
|
||||
...options,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${token}`,
|
||||
'X-App-Id': appId,
|
||||
...options.headers,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit new feedback
|
||||
*/
|
||||
async function createFeedback(input: CreateFeedbackInput): Promise<FeedbackResponse> {
|
||||
return fetchWithAuth<FeedbackResponse>(feedbackEndpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get public community feedback
|
||||
*/
|
||||
async function getPublicFeedback(query?: FeedbackQueryParams): Promise<FeedbackListResponse> {
|
||||
const params = new URLSearchParams();
|
||||
|
||||
// Always filter by current app
|
||||
params.set('appId', appId);
|
||||
|
||||
if (query?.status) params.set('status', query.status);
|
||||
if (query?.category) params.set('category', query.category);
|
||||
if (query?.sort) params.set('sort', query.sort);
|
||||
if (query?.limit) params.set('limit', String(query.limit));
|
||||
if (query?.offset) params.set('offset', String(query.offset));
|
||||
|
||||
return fetchWithAuth<FeedbackListResponse>(`${feedbackEndpoint}/public?${params}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's own feedback
|
||||
*/
|
||||
async function getMyFeedback(): Promise<FeedbackListResponse> {
|
||||
const params = new URLSearchParams();
|
||||
params.set('appId', appId);
|
||||
|
||||
return fetchWithAuth<FeedbackListResponse>(`${feedbackEndpoint}/my?${params}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vote on a feedback item
|
||||
*/
|
||||
async function vote(feedbackId: string): Promise<VoteResponse> {
|
||||
return fetchWithAuth<VoteResponse>(`${feedbackEndpoint}/${feedbackId}/vote`, {
|
||||
method: 'POST',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove vote from a feedback item
|
||||
*/
|
||||
async function unvote(feedbackId: string): Promise<VoteResponse> {
|
||||
return fetchWithAuth<VoteResponse>(`${feedbackEndpoint}/${feedbackId}/vote`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle vote on a feedback item
|
||||
*/
|
||||
async function toggleVote(feedbackId: string, currentlyVoted: boolean): Promise<VoteResponse> {
|
||||
if (currentlyVoted) {
|
||||
return unvote(feedbackId);
|
||||
} else {
|
||||
return vote(feedbackId);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
createFeedback,
|
||||
getPublicFeedback,
|
||||
getMyFeedback,
|
||||
vote,
|
||||
unvote,
|
||||
toggleVote,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Type for the feedback service instance
|
||||
*/
|
||||
export type FeedbackService = ReturnType<typeof createFeedbackService>;
|
||||
Loading…
Add table
Add a link
Reference in a new issue