@alliance-droid/status-feedback-system 0.1.0 → 0.2.0

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.
Files changed (54) hide show
  1. package/dist/api.d.ts +94 -0
  2. package/dist/api.js +100 -0
  3. package/dist/components/FeedbackBoard.svelte +842 -0
  4. package/dist/components/FeedbackBoard.svelte.d.ts +19 -0
  5. package/dist/components/FeedbackButton.svelte +3 -3
  6. package/dist/components/FeedbackButton.svelte.d.ts +1 -1
  7. package/dist/components/FeedbackForm.svelte +3 -3
  8. package/dist/components/FeedbackForm.svelte.d.ts +1 -1
  9. package/dist/components/StatusBanner.svelte +36 -3
  10. package/dist/components/StatusBanner.svelte.d.ts +7 -1
  11. package/dist/components/StatusPage.svelte +150 -83
  12. package/dist/components/StatusPage.svelte.d.ts +10 -3
  13. package/dist/index.d.ts +7 -9
  14. package/dist/index.js +6 -8
  15. package/dist/types.d.ts +13 -6
  16. package/package.json +2 -13
  17. package/dist/components/admin/AdminDashboard.svelte +0 -274
  18. package/dist/components/admin/AdminDashboard.svelte.d.ts +0 -9
  19. package/dist/components/admin/ApiKeyManager.svelte +0 -68
  20. package/dist/components/admin/ApiKeyManager.svelte.d.ts +0 -7
  21. package/dist/components/admin/FeedbackList.svelte +0 -160
  22. package/dist/components/admin/FeedbackList.svelte.d.ts +0 -17
  23. package/dist/components/admin/IncidentForm.svelte +0 -135
  24. package/dist/components/admin/IncidentForm.svelte.d.ts +0 -14
  25. package/dist/components/admin/IncidentManager.svelte +0 -153
  26. package/dist/components/admin/IncidentManager.svelte.d.ts +0 -13
  27. package/dist/components/admin/ProjectForm.svelte +0 -106
  28. package/dist/components/admin/ProjectForm.svelte.d.ts +0 -13
  29. package/dist/components/admin/ProjectList.svelte +0 -57
  30. package/dist/components/admin/ProjectList.svelte.d.ts +0 -10
  31. package/dist/components/admin/StatusControl.svelte +0 -62
  32. package/dist/components/admin/StatusControl.svelte.d.ts +0 -8
  33. package/dist/components/admin/SystemManager.svelte +0 -119
  34. package/dist/components/admin/SystemManager.svelte.d.ts +0 -13
  35. package/dist/components/admin/index.d.ts +0 -9
  36. package/dist/components/admin/index.js +0 -9
  37. package/dist/server/db.d.ts +0 -17
  38. package/dist/server/db.js +0 -68
  39. package/dist/server/feedback.d.ts +0 -27
  40. package/dist/server/feedback.js +0 -124
  41. package/dist/server/handlers.d.ts +0 -41
  42. package/dist/server/handlers.js +0 -251
  43. package/dist/server/incidents.d.ts +0 -27
  44. package/dist/server/incidents.js +0 -180
  45. package/dist/server/index.d.ts +0 -101
  46. package/dist/server/index.js +0 -71
  47. package/dist/server/projects.d.ts +0 -45
  48. package/dist/server/projects.js +0 -156
  49. package/dist/server/schema.d.ts +0 -9
  50. package/dist/server/schema.js +0 -94
  51. package/dist/server/systems.d.ts +0 -20
  52. package/dist/server/systems.js +0 -146
  53. package/dist/server/types.d.ts +0 -4
  54. package/dist/server/types.js +0 -4
@@ -0,0 +1,19 @@
1
+ interface Props {
2
+ apiUrl: string;
3
+ apiKey: string;
4
+ /** Category labels and icons — order determines sidebar order */
5
+ categoryConfig?: Record<string, {
6
+ label?: string;
7
+ icon?: string;
8
+ description?: string;
9
+ }>;
10
+ /** Title shown at the top */
11
+ title?: string;
12
+ /** Show the submit form inline */
13
+ showSubmit?: boolean;
14
+ /** Available categories for the submit form */
15
+ submitCategories?: string[];
16
+ }
17
+ declare const FeedbackBoard: import("svelte").Component<Props, {}, "">;
18
+ type FeedbackBoard = ReturnType<typeof FeedbackBoard>;
19
+ export default FeedbackBoard;
@@ -3,7 +3,7 @@
3
3
 
4
4
  interface Props {
5
5
  apiKey: string;
6
- endpoint: string;
6
+ apiUrl: string;
7
7
  categories?: string[];
8
8
  userEmail?: string;
9
9
  position?: 'bottom-right' | 'bottom-left';
@@ -11,7 +11,7 @@
11
11
 
12
12
  let {
13
13
  apiKey,
14
- endpoint,
14
+ apiUrl,
15
15
  categories,
16
16
  userEmail,
17
17
  position = 'bottom-right',
@@ -51,7 +51,7 @@
51
51
  <div class="p-4">
52
52
  <FeedbackForm
53
53
  {apiKey}
54
- {endpoint}
54
+ {apiUrl}
55
55
  {categories}
56
56
  {userEmail}
57
57
  onSuccess={() => {
@@ -1,6 +1,6 @@
1
1
  interface Props {
2
2
  apiKey: string;
3
- endpoint: string;
3
+ apiUrl: string;
4
4
  categories?: string[];
5
5
  userEmail?: string;
6
6
  position?: 'bottom-right' | 'bottom-left';
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  interface Props {
3
3
  apiKey: string;
4
- endpoint: string;
4
+ apiUrl: string;
5
5
  categories?: string[];
6
6
  userEmail?: string;
7
7
  onSuccess?: () => void;
@@ -10,7 +10,7 @@
10
10
 
11
11
  let {
12
12
  apiKey,
13
- endpoint,
13
+ apiUrl,
14
14
  categories = ['Bug', 'Feature Request', 'General'],
15
15
  userEmail,
16
16
  onSuccess,
@@ -32,7 +32,7 @@
32
32
  errorMsg = '';
33
33
 
34
34
  try {
35
- const res = await fetch(`${endpoint}/feedback`, {
35
+ const res = await fetch(`${apiUrl.replace(/\/$/, '')}/api/feedback`, {
36
36
  method: 'POST',
37
37
  headers: {
38
38
  'Content-Type': 'application/json',
@@ -1,6 +1,6 @@
1
1
  interface Props {
2
2
  apiKey: string;
3
- endpoint: string;
3
+ apiUrl: string;
4
4
  categories?: string[];
5
5
  userEmail?: string;
6
6
  onSuccess?: () => void;
@@ -1,13 +1,41 @@
1
1
  <script lang="ts">
2
+ import { onMount } from 'svelte';
2
3
  import type { System, SystemStatus } from '../types.js';
4
+ import { createStatusClient } from '../api.js';
3
5
  import StatusIndicator from './shared/StatusIndicator.svelte';
4
6
 
5
7
  interface Props {
6
- systems: System[];
8
+ /** Systems data (pass-through mode) */
9
+ systems?: System[];
10
+ /** API URL for self-fetching mode */
11
+ apiUrl?: string;
12
+ /** API key for self-fetching mode */
13
+ apiKey?: string;
14
+ /** Link to full status page */
7
15
  statusUrl?: string;
8
16
  }
9
17
 
10
- let { systems, statusUrl }: Props = $props();
18
+ let { systems: systemsProp, apiUrl, apiKey, statusUrl }: Props = $props();
19
+
20
+ let systems: System[] = $state(systemsProp ?? []);
21
+ let loading = $state(!systemsProp && !!apiUrl && !!apiKey);
22
+
23
+ onMount(async () => {
24
+ if (systemsProp || !apiUrl || !apiKey) return;
25
+ try {
26
+ const client = createStatusClient({ apiUrl, apiKey });
27
+ const data = await client.getStatus();
28
+ systems = data.systems;
29
+ } catch (err) {
30
+ console.error('StatusBanner fetch error:', err);
31
+ } finally {
32
+ loading = false;
33
+ }
34
+ });
35
+
36
+ $effect(() => {
37
+ if (systemsProp) systems = systemsProp;
38
+ });
11
39
 
12
40
  let overallStatus = $derived.by((): SystemStatus => {
13
41
  if (systems.length === 0) return 'operational';
@@ -25,7 +53,12 @@
25
53
  };
26
54
  </script>
27
55
 
28
- {#if statusUrl}
56
+ {#if loading}
57
+ <div class="inline-flex items-center gap-2 rounded-full border border-border px-3 py-1.5 text-xs text-foreground-tertiary">
58
+ <div class="h-2 w-2 animate-pulse rounded-full bg-foreground-tertiary"></div>
59
+ <span>Loading...</span>
60
+ </div>
61
+ {:else if statusUrl}
29
62
  <a
30
63
  href={statusUrl}
31
64
  class="inline-flex items-center gap-2 rounded-full border border-border px-3 py-1.5 text-xs text-foreground-secondary transition-colors hover:bg-surface-hover"
@@ -1,6 +1,12 @@
1
1
  import type { System } from '../types.js';
2
2
  interface Props {
3
- systems: System[];
3
+ /** Systems data (pass-through mode) */
4
+ systems?: System[];
5
+ /** API URL for self-fetching mode */
6
+ apiUrl?: string;
7
+ /** API key for self-fetching mode */
8
+ apiKey?: string;
9
+ /** Link to full status page */
4
10
  statusUrl?: string;
5
11
  }
6
12
  declare const StatusBanner: import("svelte").Component<Props, {}, "">;
@@ -1,26 +1,81 @@
1
1
  <script lang="ts">
2
+ import { onMount } from 'svelte';
2
3
  import type { System, Incident, StatusHistoryEntry, SystemStatus } from '../types.js';
4
+ import { createStatusClient } from '../api.js';
3
5
  import StatusIndicator from './shared/StatusIndicator.svelte';
4
6
  import SystemCard from './shared/SystemCard.svelte';
5
7
  import IncidentTimeline from './shared/IncidentTimeline.svelte';
6
8
 
7
9
  interface Props {
10
+ /** Project display name */
8
11
  projectName: string;
9
- systems: System[];
10
- incidents: Incident[];
11
- /** Map of systemId → StatusHistoryEntry[] for uptime bars */
12
+ /** API URL for fetching data (self-fetching mode) */
13
+ apiUrl?: string;
14
+ /** API key for fetching data (self-fetching mode) */
15
+ apiKey?: string;
16
+ /** Systems data (pass-through mode — overrides API fetching) */
17
+ systems?: System[];
18
+ /** Incidents data (pass-through mode) */
19
+ incidents?: Incident[];
20
+ /** Map of systemId → StatusHistoryEntry[] for uptime bars (pass-through mode) */
12
21
  statusHistory?: Record<string, StatusHistoryEntry[]>;
13
22
  showUptime?: boolean;
14
23
  }
15
24
 
16
25
  let {
17
26
  projectName,
18
- systems,
19
- incidents,
20
- statusHistory = {},
27
+ apiUrl,
28
+ apiKey,
29
+ systems: systemsProp,
30
+ incidents: incidentsProp,
31
+ statusHistory: statusHistoryProp,
21
32
  showUptime = true,
22
33
  }: Props = $props();
23
34
 
35
+ // ── State ──
36
+ let systems: System[] = $state(systemsProp ?? []);
37
+ let incidents: Incident[] = $state(incidentsProp ?? []);
38
+ let statusHistory: Record<string, StatusHistoryEntry[]> = $state(statusHistoryProp ?? {});
39
+ let loading = $state(!systemsProp);
40
+ let error = $state('');
41
+
42
+ // ── Self-fetching mode ──
43
+ const usesApi = $derived(!!apiUrl && !!apiKey && !systemsProp);
44
+
45
+ onMount(async () => {
46
+ if (!usesApi) return;
47
+
48
+ try {
49
+ const client = createStatusClient({ apiUrl: apiUrl!, apiKey: apiKey! });
50
+
51
+ const [statusData, incidentData, uptimeData] = await Promise.all([
52
+ client.getStatus(),
53
+ client.getIncidents(),
54
+ client.getUptime(),
55
+ ]);
56
+
57
+ systems = statusData.systems;
58
+ incidents = incidentData.incidents;
59
+ statusHistory = uptimeData.history;
60
+ } catch (err) {
61
+ error = err instanceof Error ? err.message : 'Failed to load status data';
62
+ console.error('StatusPage fetch error:', err);
63
+ } finally {
64
+ loading = false;
65
+ }
66
+ });
67
+
68
+ // ── Sync props when in pass-through mode ──
69
+ $effect(() => {
70
+ if (systemsProp) systems = systemsProp;
71
+ });
72
+ $effect(() => {
73
+ if (incidentsProp) incidents = incidentsProp;
74
+ });
75
+ $effect(() => {
76
+ if (statusHistoryProp) statusHistory = statusHistoryProp;
77
+ });
78
+
24
79
  // ── Derived state ──
25
80
 
26
81
  let overallStatus = $derived.by((): SystemStatus => {
@@ -65,92 +120,104 @@
65
120
  <h1 class="text-2xl font-semibold text-foreground">{projectName} Status</h1>
66
121
  </div>
67
122
 
68
- <!-- Overall Status Banner -->
69
- <div class="rounded-lg border p-4 text-center {overallBgClasses[overallStatus]}">
70
- <div class="flex items-center justify-center gap-2">
71
- <StatusIndicator status={overallStatus} size="lg" />
72
- <span class="text-lg font-semibold text-foreground">{overallMessages[overallStatus]}</span>
123
+ {#if loading}
124
+ <div class="rounded-lg border border-border bg-surface p-12 text-center">
125
+ <div class="mx-auto mb-3 h-8 w-8 animate-spin rounded-full border-2 border-foreground-tertiary border-t-primary"></div>
126
+ <p class="text-sm text-foreground-secondary">Loading status...</p>
73
127
  </div>
74
- </div>
75
-
76
- <!-- Systems -->
77
- {#if systems.length > 0}
78
- <section>
79
- <h2 class="mb-4 text-lg font-semibold text-foreground">Systems</h2>
80
- <div class="space-y-3">
81
- {#each systems as system}
82
- <SystemCard
83
- {system}
84
- history={statusHistory[system.id] || []}
85
- {showUptime}
86
- />
87
- {/each}
128
+ {:else if error}
129
+ <div class="rounded-lg border border-red-500/30 bg-red-500/10 p-6 text-center">
130
+ <i class="fa-solid fa-circle-exclamation mb-2 text-2xl text-red-500"></i>
131
+ <p class="text-sm text-red-400">{error}</p>
132
+ </div>
133
+ {:else}
134
+ <!-- Overall Status Banner -->
135
+ <div class="rounded-lg border p-4 text-center {overallBgClasses[overallStatus]}">
136
+ <div class="flex items-center justify-center gap-2">
137
+ <StatusIndicator status={overallStatus} size="lg" />
138
+ <span class="text-lg font-semibold text-foreground">{overallMessages[overallStatus]}</span>
88
139
  </div>
89
- </section>
90
- {/if}
140
+ </div>
91
141
 
92
- <!-- Active Incidents -->
93
- {#if activeIncidents.length > 0}
94
- <section>
95
- <h2 class="mb-4 text-lg font-semibold text-foreground">Active Incidents</h2>
96
- <div class="space-y-4">
97
- {#each activeIncidents as incident}
98
- <div class="rounded-lg border border-border bg-surface p-4">
99
- <div class="flex items-start justify-between">
100
- <div>
101
- <h3 class="font-semibold text-foreground">{incident.title}</h3>
102
- <div class="mt-1 flex items-center gap-2 text-xs text-foreground-tertiary">
103
- <span class="rounded bg-red-500/10 px-1.5 py-0.5 text-red-500">
104
- {incident.severity}
105
- </span>
106
- <span>{formatDate(incident.createdAt)}</span>
142
+ <!-- Systems -->
143
+ {#if systems.length > 0}
144
+ <section>
145
+ <h2 class="mb-4 text-lg font-semibold text-foreground">Systems</h2>
146
+ <div class="space-y-3">
147
+ {#each systems as system}
148
+ <SystemCard
149
+ {system}
150
+ history={statusHistory[system.id] || []}
151
+ {showUptime}
152
+ />
153
+ {/each}
154
+ </div>
155
+ </section>
156
+ {/if}
157
+
158
+ <!-- Active Incidents -->
159
+ {#if activeIncidents.length > 0}
160
+ <section>
161
+ <h2 class="mb-4 text-lg font-semibold text-foreground">Active Incidents</h2>
162
+ <div class="space-y-4">
163
+ {#each activeIncidents as incident}
164
+ <div class="rounded-lg border border-border bg-surface p-4">
165
+ <div class="flex items-start justify-between">
166
+ <div>
167
+ <h3 class="font-semibold text-foreground">{incident.title}</h3>
168
+ <div class="mt-1 flex items-center gap-2 text-xs text-foreground-tertiary">
169
+ <span class="rounded bg-red-500/10 px-1.5 py-0.5 text-red-500">
170
+ {incident.severity}
171
+ </span>
172
+ <span>{formatDate(incident.createdAt)}</span>
173
+ </div>
107
174
  </div>
175
+ <StatusIndicator status={incident.status === 'resolved' ? 'operational' : 'outage'} size="sm" />
108
176
  </div>
109
- <StatusIndicator status={incident.status === 'resolved' ? 'operational' : 'outage'} size="sm" />
177
+ {#if incident.updates && incident.updates.length > 0}
178
+ <div class="mt-4 border-t border-border pt-4">
179
+ <IncidentTimeline updates={incident.updates} />
180
+ </div>
181
+ {/if}
110
182
  </div>
111
- {#if incident.updates && incident.updates.length > 0}
112
- <div class="mt-4 border-t border-border pt-4">
113
- <IncidentTimeline updates={incident.updates} />
114
- </div>
115
- {/if}
116
- </div>
117
- {/each}
118
- </div>
119
- </section>
120
- {/if}
183
+ {/each}
184
+ </div>
185
+ </section>
186
+ {/if}
121
187
 
122
- <!-- Resolved Incidents -->
123
- {#if recentResolved.length > 0}
124
- <section>
125
- <h2 class="mb-4 text-lg font-semibold text-foreground">Past Incidents</h2>
126
- <div class="space-y-4">
127
- {#each recentResolved as incident}
128
- <div class="rounded-lg border border-border bg-surface p-4">
129
- <div class="flex items-start justify-between">
130
- <div>
131
- <h3 class="font-semibold text-foreground">{incident.title}</h3>
132
- <p class="mt-1 text-xs text-foreground-tertiary">
133
- Resolved {incident.resolvedAt ? formatDate(incident.resolvedAt) : ''}
134
- </p>
188
+ <!-- Resolved Incidents -->
189
+ {#if recentResolved.length > 0}
190
+ <section>
191
+ <h2 class="mb-4 text-lg font-semibold text-foreground">Past Incidents</h2>
192
+ <div class="space-y-4">
193
+ {#each recentResolved as incident}
194
+ <div class="rounded-lg border border-border bg-surface p-4">
195
+ <div class="flex items-start justify-between">
196
+ <div>
197
+ <h3 class="font-semibold text-foreground">{incident.title}</h3>
198
+ <p class="mt-1 text-xs text-foreground-tertiary">
199
+ Resolved {incident.resolvedAt ? formatDate(incident.resolvedAt) : ''}
200
+ </p>
201
+ </div>
202
+ <StatusIndicator status="operational" size="sm" />
135
203
  </div>
136
- <StatusIndicator status="operational" size="sm" />
204
+ {#if incident.updates && incident.updates.length > 0}
205
+ <div class="mt-4 border-t border-border pt-4">
206
+ <IncidentTimeline updates={incident.updates} />
207
+ </div>
208
+ {/if}
137
209
  </div>
138
- {#if incident.updates && incident.updates.length > 0}
139
- <div class="mt-4 border-t border-border pt-4">
140
- <IncidentTimeline updates={incident.updates} />
141
- </div>
142
- {/if}
143
- </div>
144
- {/each}
145
- </div>
146
- </section>
147
- {/if}
210
+ {/each}
211
+ </div>
212
+ </section>
213
+ {/if}
148
214
 
149
- <!-- No Incidents -->
150
- {#if activeIncidents.length === 0 && recentResolved.length === 0}
151
- <div class="rounded-lg border border-border bg-surface p-8 text-center">
152
- <i class="fa-solid fa-circle-check mb-2 text-2xl text-green-500"></i>
153
- <p class="text-sm text-foreground-secondary">No incidents reported</p>
154
- </div>
215
+ <!-- No Incidents -->
216
+ {#if activeIncidents.length === 0 && recentResolved.length === 0}
217
+ <div class="rounded-lg border border-border bg-surface p-8 text-center">
218
+ <i class="fa-solid fa-circle-check mb-2 text-2xl text-green-500"></i>
219
+ <p class="text-sm text-foreground-secondary">No incidents reported</p>
220
+ </div>
221
+ {/if}
155
222
  {/if}
156
223
  </div>
@@ -1,9 +1,16 @@
1
1
  import type { System, Incident, StatusHistoryEntry } from '../types.js';
2
2
  interface Props {
3
+ /** Project display name */
3
4
  projectName: string;
4
- systems: System[];
5
- incidents: Incident[];
6
- /** Map of systemId → StatusHistoryEntry[] for uptime bars */
5
+ /** API URL for fetching data (self-fetching mode) */
6
+ apiUrl?: string;
7
+ /** API key for fetching data (self-fetching mode) */
8
+ apiKey?: string;
9
+ /** Systems data (pass-through mode — overrides API fetching) */
10
+ systems?: System[];
11
+ /** Incidents data (pass-through mode) */
12
+ incidents?: Incident[];
13
+ /** Map of systemId → StatusHistoryEntry[] for uptime bars (pass-through mode) */
7
14
  statusHistory?: Record<string, StatusHistoryEntry[]>;
8
15
  showUptime?: boolean;
9
16
  }
package/dist/index.d.ts CHANGED
@@ -2,20 +2,18 @@
2
2
  * @alliance-droid/status-feedback-system
3
3
  *
4
4
  * Drop-in system status pages and user feedback forms for SvelteKit apps.
5
+ * All data is fetched from a remote status-feedback-admin backend via API.
5
6
  *
6
- * Client exports (components):
7
- * import { StatusPage, FeedbackForm } from '@alliance-droid/status-feedback-system';
8
- *
9
- * Server exports:
10
- * import { createStatusServer } from '@alliance-droid/status-feedback-system/server';
11
- *
12
- * Admin exports:
13
- * import { AdminDashboard } from '@alliance-droid/status-feedback-system/admin';
7
+ * Usage:
8
+ * import { StatusPage, FeedbackButton, createStatusClient } from '@alliance-droid/status-feedback-system';
14
9
  */
15
- export type { Project, System, Incident, IncidentUpdate, Feedback, StatusHistoryEntry, SystemStatus, IncidentStatus, IncidentSeverity, FeedbackStatus, StatusServerConfig, ApiResponse, } from './types.js';
10
+ export type { Project, System, Incident, IncidentUpdate, Feedback, FeedbackResponse, FeedbackVisibility, StatusHistoryEntry, SystemStatus, IncidentStatus, IncidentSeverity, FeedbackStatus, ApiResponse, } from './types.js';
11
+ export { createStatusClient } from './api.js';
12
+ export type { StatusClient, StatusClientConfig, StatusData, IncidentData, UptimeData, BoardData, BoardItem, BoardCategory } from './api.js';
16
13
  export { default as StatusPage } from './components/StatusPage.svelte';
17
14
  export { default as StatusBanner } from './components/StatusBanner.svelte';
18
15
  export { default as FeedbackForm } from './components/FeedbackForm.svelte';
16
+ export { default as FeedbackBoard } from './components/FeedbackBoard.svelte';
19
17
  export { default as FeedbackButton } from './components/FeedbackButton.svelte';
20
18
  export { default as StatusIndicator } from './components/shared/StatusIndicator.svelte';
21
19
  export { default as UptimeBar } from './components/shared/UptimeBar.svelte';
package/dist/index.js CHANGED
@@ -2,20 +2,18 @@
2
2
  * @alliance-droid/status-feedback-system
3
3
  *
4
4
  * Drop-in system status pages and user feedback forms for SvelteKit apps.
5
+ * All data is fetched from a remote status-feedback-admin backend via API.
5
6
  *
6
- * Client exports (components):
7
- * import { StatusPage, FeedbackForm } from '@alliance-droid/status-feedback-system';
8
- *
9
- * Server exports:
10
- * import { createStatusServer } from '@alliance-droid/status-feedback-system/server';
11
- *
12
- * Admin exports:
13
- * import { AdminDashboard } from '@alliance-droid/status-feedback-system/admin';
7
+ * Usage:
8
+ * import { StatusPage, FeedbackButton, createStatusClient } from '@alliance-droid/status-feedback-system';
14
9
  */
10
+ // ── API Client ──
11
+ export { createStatusClient } from './api.js';
15
12
  // ── Client Components ──
16
13
  export { default as StatusPage } from './components/StatusPage.svelte';
17
14
  export { default as StatusBanner } from './components/StatusBanner.svelte';
18
15
  export { default as FeedbackForm } from './components/FeedbackForm.svelte';
16
+ export { default as FeedbackBoard } from './components/FeedbackBoard.svelte';
19
17
  export { default as FeedbackButton } from './components/FeedbackButton.svelte';
20
18
  // ── Shared Components ──
21
19
  export { default as StatusIndicator } from './components/shared/StatusIndicator.svelte';
package/dist/types.d.ts CHANGED
@@ -8,7 +8,6 @@ export type FeedbackStatus = 'new' | 'reviewed' | 'resolved' | 'archived';
8
8
  export interface Project {
9
9
  id: string;
10
10
  name: string;
11
- apiKey: string;
12
11
  description: string | null;
13
12
  allowedOrigins: string[];
14
13
  createdAt: number;
@@ -43,9 +42,18 @@ export interface IncidentUpdate {
43
42
  message: string;
44
43
  createdAt: number;
45
44
  }
45
+ export type FeedbackVisibility = 'public' | 'private';
46
+ export interface FeedbackResponse {
47
+ id: string;
48
+ feedbackId: string;
49
+ message: string;
50
+ author: string | null;
51
+ createdAt: number;
52
+ }
46
53
  export interface Feedback {
47
54
  id: string;
48
55
  projectId: string;
56
+ title: string | null;
49
57
  category: string | null;
50
58
  message: string;
51
59
  email: string | null;
@@ -53,6 +61,10 @@ export interface Feedback {
53
61
  pageUrl: string | null;
54
62
  metadata: Record<string, unknown> | null;
55
63
  status: FeedbackStatus;
64
+ visibility: FeedbackVisibility;
65
+ votes: number;
66
+ adminResponse: string | null;
67
+ responses?: FeedbackResponse[];
56
68
  createdAt: number;
57
69
  }
58
70
  export interface StatusHistoryEntry {
@@ -61,11 +73,6 @@ export interface StatusHistoryEntry {
61
73
  status: SystemStatus;
62
74
  changedAt: number;
63
75
  }
64
- export interface StatusServerConfig {
65
- database: {
66
- connectionString: string;
67
- };
68
- }
69
76
  export interface ApiResponse<T = unknown> {
70
77
  success: boolean;
71
78
  data?: T;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alliance-droid/status-feedback-system",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "description": "Drop-in system status pages and user feedback forms for SvelteKit apps",
6
6
  "svelte": "./dist/index.js",
@@ -9,14 +9,6 @@
9
9
  ".": {
10
10
  "types": "./dist/index.d.ts",
11
11
  "svelte": "./dist/index.js"
12
- },
13
- "./server": {
14
- "types": "./dist/server/index.d.ts",
15
- "default": "./dist/server/index.js"
16
- },
17
- "./admin": {
18
- "types": "./dist/components/admin/index.d.ts",
19
- "svelte": "./dist/components/admin/index.js"
20
12
  }
21
13
  },
22
14
  "files": [
@@ -37,9 +29,7 @@
37
29
  "svelte": "^5.0.0"
38
30
  },
39
31
  "dependencies": {
40
- "@alliance-droid/svelte-component-library": "^0.1.27",
41
- "mssql": "^11.0.0",
42
- "nanoid": "^5.0.0"
32
+ "@alliance-droid/svelte-component-library": "^0.1.27"
43
33
  },
44
34
  "devDependencies": {
45
35
  "@sveltejs/adapter-auto": "^7.0.0",
@@ -47,7 +37,6 @@
47
37
  "@sveltejs/package": "^2.3.0",
48
38
  "@sveltejs/vite-plugin-svelte": "^6.0.0",
49
39
  "@tailwindcss/vite": "^4.1.0",
50
- "@types/mssql": "^9.1.0",
51
40
  "publint": "^0.3.0",
52
41
  "svelte": "^5.48.0",
53
42
  "svelte-check": "^4.3.0",