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

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 (52) hide show
  1. package/dist/api.d.ts +57 -0
  2. package/dist/api.js +76 -0
  3. package/dist/components/FeedbackButton.svelte +3 -3
  4. package/dist/components/FeedbackButton.svelte.d.ts +1 -1
  5. package/dist/components/FeedbackForm.svelte +3 -3
  6. package/dist/components/FeedbackForm.svelte.d.ts +1 -1
  7. package/dist/components/StatusBanner.svelte +36 -3
  8. package/dist/components/StatusBanner.svelte.d.ts +7 -1
  9. package/dist/components/StatusPage.svelte +150 -83
  10. package/dist/components/StatusPage.svelte.d.ts +10 -3
  11. package/dist/index.d.ts +6 -9
  12. package/dist/index.js +5 -8
  13. package/dist/types.d.ts +0 -6
  14. package/package.json +2 -13
  15. package/dist/components/admin/AdminDashboard.svelte +0 -274
  16. package/dist/components/admin/AdminDashboard.svelte.d.ts +0 -9
  17. package/dist/components/admin/ApiKeyManager.svelte +0 -68
  18. package/dist/components/admin/ApiKeyManager.svelte.d.ts +0 -7
  19. package/dist/components/admin/FeedbackList.svelte +0 -160
  20. package/dist/components/admin/FeedbackList.svelte.d.ts +0 -17
  21. package/dist/components/admin/IncidentForm.svelte +0 -135
  22. package/dist/components/admin/IncidentForm.svelte.d.ts +0 -14
  23. package/dist/components/admin/IncidentManager.svelte +0 -153
  24. package/dist/components/admin/IncidentManager.svelte.d.ts +0 -13
  25. package/dist/components/admin/ProjectForm.svelte +0 -106
  26. package/dist/components/admin/ProjectForm.svelte.d.ts +0 -13
  27. package/dist/components/admin/ProjectList.svelte +0 -57
  28. package/dist/components/admin/ProjectList.svelte.d.ts +0 -10
  29. package/dist/components/admin/StatusControl.svelte +0 -62
  30. package/dist/components/admin/StatusControl.svelte.d.ts +0 -8
  31. package/dist/components/admin/SystemManager.svelte +0 -119
  32. package/dist/components/admin/SystemManager.svelte.d.ts +0 -13
  33. package/dist/components/admin/index.d.ts +0 -9
  34. package/dist/components/admin/index.js +0 -9
  35. package/dist/server/db.d.ts +0 -17
  36. package/dist/server/db.js +0 -68
  37. package/dist/server/feedback.d.ts +0 -27
  38. package/dist/server/feedback.js +0 -124
  39. package/dist/server/handlers.d.ts +0 -41
  40. package/dist/server/handlers.js +0 -251
  41. package/dist/server/incidents.d.ts +0 -27
  42. package/dist/server/incidents.js +0 -180
  43. package/dist/server/index.d.ts +0 -101
  44. package/dist/server/index.js +0 -71
  45. package/dist/server/projects.d.ts +0 -45
  46. package/dist/server/projects.js +0 -156
  47. package/dist/server/schema.d.ts +0 -9
  48. package/dist/server/schema.js +0 -94
  49. package/dist/server/systems.d.ts +0 -20
  50. package/dist/server/systems.js +0 -146
  51. package/dist/server/types.d.ts +0 -4
  52. package/dist/server/types.js +0 -4
@@ -1,156 +0,0 @@
1
- /**
2
- * Project CRUD + API key management
3
- */
4
- import { nanoid } from 'nanoid';
5
- /**
6
- * Generate a prefixed API key
7
- */
8
- function generateApiKey() {
9
- return `sf_${nanoid(32)}`;
10
- }
11
- /**
12
- * Create a new project
13
- */
14
- export async function createProject(pool, data) {
15
- const id = nanoid(16);
16
- const apiKey = generateApiKey();
17
- const now = Date.now();
18
- await pool
19
- .request()
20
- .input('id', id)
21
- .input('name', data.name)
22
- .input('apiKey', apiKey)
23
- .input('description', data.description || null)
24
- .input('allowedOrigins', JSON.stringify(data.allowedOrigins || []))
25
- .input('createdAt', now)
26
- .input('updatedAt', now)
27
- .query(`
28
- INSERT INTO sf_projects (id, name, api_key, description, allowed_origins, created_at, updated_at)
29
- VALUES (@id, @name, @apiKey, @description, @allowedOrigins, @createdAt, @updatedAt)
30
- `);
31
- return {
32
- id,
33
- name: data.name,
34
- apiKey,
35
- description: data.description || null,
36
- allowedOrigins: data.allowedOrigins || [],
37
- createdAt: now,
38
- updatedAt: now,
39
- };
40
- }
41
- /**
42
- * Get a project by API key
43
- */
44
- export async function getProjectByApiKey(pool, apiKey) {
45
- const result = await pool
46
- .request()
47
- .input('apiKey', apiKey)
48
- .query('SELECT * FROM sf_projects WHERE api_key = @apiKey');
49
- if (result.recordset.length === 0)
50
- return null;
51
- return mapRow(result.recordset[0]);
52
- }
53
- /**
54
- * Get a project by ID
55
- */
56
- export async function getProjectById(pool, id) {
57
- const result = await pool
58
- .request()
59
- .input('id', id)
60
- .query('SELECT * FROM sf_projects WHERE id = @id');
61
- if (result.recordset.length === 0)
62
- return null;
63
- return mapRow(result.recordset[0]);
64
- }
65
- /**
66
- * List all projects
67
- */
68
- export async function listProjects(pool) {
69
- const result = await pool.request().query('SELECT * FROM sf_projects ORDER BY created_at DESC');
70
- return result.recordset.map(mapRow);
71
- }
72
- /**
73
- * Update a project
74
- */
75
- export async function updateProject(pool, id, data) {
76
- const existing = await getProjectById(pool, id);
77
- if (!existing)
78
- return null;
79
- const now = Date.now();
80
- await pool
81
- .request()
82
- .input('id', id)
83
- .input('name', data.name ?? existing.name)
84
- .input('description', data.description ?? existing.description)
85
- .input('allowedOrigins', JSON.stringify(data.allowedOrigins ?? existing.allowedOrigins))
86
- .input('updatedAt', now)
87
- .query(`
88
- UPDATE sf_projects
89
- SET name = @name, description = @description, allowed_origins = @allowedOrigins, updated_at = @updatedAt
90
- WHERE id = @id
91
- `);
92
- return { ...existing, ...data, updatedAt: now };
93
- }
94
- /**
95
- * Delete a project and all related data
96
- */
97
- export async function deleteProject(pool, id) {
98
- // Delete in dependency order
99
- await pool.request().input('id', id).query(`
100
- DELETE FROM sf_status_history WHERE system_id IN (SELECT id FROM sf_systems WHERE project_id = @id);
101
- DELETE FROM sf_incident_updates WHERE incident_id IN (SELECT id FROM sf_incidents WHERE project_id = @id);
102
- DELETE FROM sf_incidents WHERE project_id = @id;
103
- DELETE FROM sf_systems WHERE project_id = @id;
104
- DELETE FROM sf_feedback WHERE project_id = @id;
105
- DELETE FROM sf_projects WHERE id = @id;
106
- `);
107
- return true;
108
- }
109
- /**
110
- * Regenerate a project's API key
111
- */
112
- export async function regenerateApiKey(pool, id) {
113
- const existing = await getProjectById(pool, id);
114
- if (!existing)
115
- return null;
116
- const newKey = generateApiKey();
117
- const now = Date.now();
118
- await pool
119
- .request()
120
- .input('id', id)
121
- .input('apiKey', newKey)
122
- .input('updatedAt', now)
123
- .query('UPDATE sf_projects SET api_key = @apiKey, updated_at = @updatedAt WHERE id = @id');
124
- return newKey;
125
- }
126
- /**
127
- * Validate an API key and return the project
128
- */
129
- export async function validateApiKey(pool, apiKey) {
130
- if (!apiKey || !apiKey.startsWith('sf_'))
131
- return null;
132
- return getProjectByApiKey(pool, apiKey);
133
- }
134
- // ── Helpers ──
135
- function mapRow(row) {
136
- return {
137
- id: row.id,
138
- name: row.name,
139
- apiKey: row.api_key,
140
- description: row.description || null,
141
- allowedOrigins: parseJsonArray(row.allowed_origins),
142
- createdAt: row.created_at,
143
- updatedAt: row.updated_at,
144
- };
145
- }
146
- function parseJsonArray(value) {
147
- if (!value)
148
- return [];
149
- try {
150
- const parsed = JSON.parse(value);
151
- return Array.isArray(parsed) ? parsed : [];
152
- }
153
- catch {
154
- return [];
155
- }
156
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * Database schema — auto-migration for all sf_ tables
3
- * Creates tables if they don't exist. All tables prefixed sf_ to avoid conflicts.
4
- */
5
- import type { ConnectionPool } from 'mssql';
6
- /**
7
- * Run auto-migration: create all tables and indexes if they don't exist
8
- */
9
- export declare function runMigrations(pool: ConnectionPool): Promise<void>;
@@ -1,94 +0,0 @@
1
- /**
2
- * Database schema — auto-migration for all sf_ tables
3
- * Creates tables if they don't exist. All tables prefixed sf_ to avoid conflicts.
4
- */
5
- const TABLES = [
6
- `IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'sf_projects')
7
- CREATE TABLE sf_projects (
8
- id NVARCHAR(50) PRIMARY KEY,
9
- name NVARCHAR(255) NOT NULL,
10
- api_key NVARCHAR(100) UNIQUE NOT NULL,
11
- description NVARCHAR(MAX),
12
- allowed_origins NVARCHAR(MAX),
13
- created_at BIGINT NOT NULL,
14
- updated_at BIGINT NOT NULL
15
- )`,
16
- `IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'sf_systems')
17
- CREATE TABLE sf_systems (
18
- id NVARCHAR(50) PRIMARY KEY,
19
- project_id NVARCHAR(50) NOT NULL REFERENCES sf_projects(id),
20
- name NVARCHAR(255) NOT NULL,
21
- description NVARCHAR(MAX),
22
- status NVARCHAR(50) NOT NULL DEFAULT 'operational',
23
- display_order INT DEFAULT 0,
24
- created_at BIGINT NOT NULL,
25
- updated_at BIGINT NOT NULL
26
- )`,
27
- `IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'sf_incidents')
28
- CREATE TABLE sf_incidents (
29
- id NVARCHAR(50) PRIMARY KEY,
30
- project_id NVARCHAR(50) NOT NULL REFERENCES sf_projects(id),
31
- title NVARCHAR(500) NOT NULL,
32
- status NVARCHAR(50) NOT NULL DEFAULT 'investigating',
33
- severity NVARCHAR(50) NOT NULL DEFAULT 'minor',
34
- affected_systems NVARCHAR(MAX),
35
- created_at BIGINT NOT NULL,
36
- updated_at BIGINT NOT NULL,
37
- resolved_at BIGINT
38
- )`,
39
- `IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'sf_incident_updates')
40
- CREATE TABLE sf_incident_updates (
41
- id NVARCHAR(50) PRIMARY KEY,
42
- incident_id NVARCHAR(50) NOT NULL REFERENCES sf_incidents(id),
43
- status NVARCHAR(50) NOT NULL,
44
- message NVARCHAR(MAX) NOT NULL,
45
- created_at BIGINT NOT NULL
46
- )`,
47
- `IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'sf_feedback')
48
- CREATE TABLE sf_feedback (
49
- id NVARCHAR(50) PRIMARY KEY,
50
- project_id NVARCHAR(50) NOT NULL REFERENCES sf_projects(id),
51
- category NVARCHAR(100),
52
- message NVARCHAR(MAX) NOT NULL,
53
- email NVARCHAR(255),
54
- user_agent NVARCHAR(500),
55
- page_url NVARCHAR(500),
56
- metadata NVARCHAR(MAX),
57
- status NVARCHAR(50) DEFAULT 'new',
58
- created_at BIGINT NOT NULL
59
- )`,
60
- `IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'sf_status_history')
61
- CREATE TABLE sf_status_history (
62
- id NVARCHAR(50) PRIMARY KEY,
63
- system_id NVARCHAR(50) NOT NULL REFERENCES sf_systems(id),
64
- status NVARCHAR(50) NOT NULL,
65
- changed_at BIGINT NOT NULL
66
- )`,
67
- ];
68
- const INDEXES = [
69
- `IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_sf_systems_project')
70
- CREATE INDEX idx_sf_systems_project ON sf_systems(project_id)`,
71
- `IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_sf_incidents_project')
72
- CREATE INDEX idx_sf_incidents_project ON sf_incidents(project_id)`,
73
- `IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_sf_incident_updates_incident')
74
- CREATE INDEX idx_sf_incident_updates_incident ON sf_incident_updates(incident_id)`,
75
- `IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_sf_feedback_project')
76
- CREATE INDEX idx_sf_feedback_project ON sf_feedback(project_id)`,
77
- `IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_sf_feedback_status')
78
- CREATE INDEX idx_sf_feedback_status ON sf_feedback(status)`,
79
- `IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_sf_status_history_system')
80
- CREATE INDEX idx_sf_status_history_system ON sf_status_history(system_id)`,
81
- `IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'idx_sf_projects_api_key')
82
- CREATE INDEX idx_sf_projects_api_key ON sf_projects(api_key)`,
83
- ];
84
- /**
85
- * Run auto-migration: create all tables and indexes if they don't exist
86
- */
87
- export async function runMigrations(pool) {
88
- for (const sql of TABLES) {
89
- await pool.request().query(sql);
90
- }
91
- for (const sql of INDEXES) {
92
- await pool.request().query(sql);
93
- }
94
- }
@@ -1,20 +0,0 @@
1
- /**
2
- * Systems CRUD + status management
3
- */
4
- import type { ConnectionPool } from 'mssql';
5
- import type { System, SystemStatus, StatusHistoryEntry } from './types.js';
6
- export declare function createSystem(pool: ConnectionPool, projectId: string, data: {
7
- name: string;
8
- description?: string;
9
- displayOrder?: number;
10
- }): Promise<System>;
11
- export declare function getSystemById(pool: ConnectionPool, id: string): Promise<System | null>;
12
- export declare function getSystemsByProject(pool: ConnectionPool, projectId: string): Promise<System[]>;
13
- export declare function updateSystem(pool: ConnectionPool, id: string, data: {
14
- name?: string;
15
- description?: string;
16
- displayOrder?: number;
17
- }): Promise<System | null>;
18
- export declare function deleteSystem(pool: ConnectionPool, id: string): Promise<boolean>;
19
- export declare function updateSystemStatus(pool: ConnectionPool, id: string, status: SystemStatus): Promise<System | null>;
20
- export declare function getStatusHistory(pool: ConnectionPool, systemId: string, days?: number): Promise<StatusHistoryEntry[]>;
@@ -1,146 +0,0 @@
1
- /**
2
- * Systems CRUD + status management
3
- */
4
- import { nanoid } from 'nanoid';
5
- // ── CRUD ──
6
- export async function createSystem(pool, projectId, data) {
7
- const id = nanoid(16);
8
- const now = Date.now();
9
- await pool
10
- .request()
11
- .input('id', id)
12
- .input('projectId', projectId)
13
- .input('name', data.name)
14
- .input('description', data.description || null)
15
- .input('displayOrder', data.displayOrder ?? 0)
16
- .input('createdAt', now)
17
- .input('updatedAt', now)
18
- .query(`
19
- INSERT INTO sf_systems (id, project_id, name, description, display_order, created_at, updated_at)
20
- VALUES (@id, @projectId, @name, @description, @displayOrder, @createdAt, @updatedAt)
21
- `);
22
- // Record initial status in history
23
- await recordStatusChange(pool, id, 'operational', now);
24
- return {
25
- id,
26
- projectId,
27
- name: data.name,
28
- description: data.description || null,
29
- status: 'operational',
30
- displayOrder: data.displayOrder ?? 0,
31
- createdAt: now,
32
- updatedAt: now,
33
- };
34
- }
35
- export async function getSystemById(pool, id) {
36
- const result = await pool
37
- .request()
38
- .input('id', id)
39
- .query('SELECT * FROM sf_systems WHERE id = @id');
40
- if (result.recordset.length === 0)
41
- return null;
42
- return mapSystemRow(result.recordset[0]);
43
- }
44
- export async function getSystemsByProject(pool, projectId) {
45
- const result = await pool
46
- .request()
47
- .input('projectId', projectId)
48
- .query('SELECT * FROM sf_systems WHERE project_id = @projectId ORDER BY display_order ASC, created_at ASC');
49
- return result.recordset.map(mapSystemRow);
50
- }
51
- export async function updateSystem(pool, id, data) {
52
- const existing = await getSystemById(pool, id);
53
- if (!existing)
54
- return null;
55
- const now = Date.now();
56
- await pool
57
- .request()
58
- .input('id', id)
59
- .input('name', data.name ?? existing.name)
60
- .input('description', data.description ?? existing.description)
61
- .input('displayOrder', data.displayOrder ?? existing.displayOrder)
62
- .input('updatedAt', now)
63
- .query(`
64
- UPDATE sf_systems
65
- SET name = @name, description = @description, display_order = @displayOrder, updated_at = @updatedAt
66
- WHERE id = @id
67
- `);
68
- return {
69
- ...existing,
70
- name: data.name ?? existing.name,
71
- description: data.description ?? existing.description,
72
- displayOrder: data.displayOrder ?? existing.displayOrder,
73
- updatedAt: now,
74
- };
75
- }
76
- export async function deleteSystem(pool, id) {
77
- await pool.request().input('id', id).query(`
78
- DELETE FROM sf_status_history WHERE system_id = @id;
79
- DELETE FROM sf_systems WHERE id = @id;
80
- `);
81
- return true;
82
- }
83
- // ── Status Management ──
84
- export async function updateSystemStatus(pool, id, status) {
85
- const existing = await getSystemById(pool, id);
86
- if (!existing)
87
- return null;
88
- if (existing.status === status)
89
- return existing;
90
- const now = Date.now();
91
- await pool
92
- .request()
93
- .input('id', id)
94
- .input('status', status)
95
- .input('updatedAt', now)
96
- .query('UPDATE sf_systems SET status = @status, updated_at = @updatedAt WHERE id = @id');
97
- await recordStatusChange(pool, id, status, now);
98
- return { ...existing, status, updatedAt: now };
99
- }
100
- export async function getStatusHistory(pool, systemId, days = 90) {
101
- const since = Date.now() - days * 24 * 60 * 60 * 1000;
102
- const result = await pool
103
- .request()
104
- .input('systemId', systemId)
105
- .input('since', since)
106
- .query(`
107
- SELECT * FROM sf_status_history
108
- WHERE system_id = @systemId AND changed_at >= @since
109
- ORDER BY changed_at ASC
110
- `);
111
- return result.recordset.map(mapHistoryRow);
112
- }
113
- // ── Helpers ──
114
- async function recordStatusChange(pool, systemId, status, changedAt) {
115
- const id = nanoid(16);
116
- await pool
117
- .request()
118
- .input('id', id)
119
- .input('systemId', systemId)
120
- .input('status', status)
121
- .input('changedAt', changedAt)
122
- .query(`
123
- INSERT INTO sf_status_history (id, system_id, status, changed_at)
124
- VALUES (@id, @systemId, @status, @changedAt)
125
- `);
126
- }
127
- function mapSystemRow(row) {
128
- return {
129
- id: row.id,
130
- projectId: row.project_id,
131
- name: row.name,
132
- description: row.description || null,
133
- status: row.status,
134
- displayOrder: row.display_order,
135
- createdAt: row.created_at,
136
- updatedAt: row.updated_at,
137
- };
138
- }
139
- function mapHistoryRow(row) {
140
- return {
141
- id: row.id,
142
- systemId: row.system_id,
143
- status: row.status,
144
- changedAt: row.changed_at,
145
- };
146
- }
@@ -1,4 +0,0 @@
1
- /**
2
- * Server-side types for the status-feedback-system
3
- */
4
- export type { Project, System, Incident, IncidentUpdate, Feedback, StatusHistoryEntry, SystemStatus, IncidentStatus, IncidentSeverity, FeedbackStatus, StatusServerConfig, ApiResponse } from '../types.js';
@@ -1,4 +0,0 @@
1
- /**
2
- * Server-side types for the status-feedback-system
3
- */
4
- export {};