diff --git a/TODO.md b/TODO.md index d6fb624..af8e0dc 100644 --- a/TODO.md +++ b/TODO.md @@ -30,7 +30,7 @@ ## Feature Requests Module -- [x] Submit feature requests (title, description, category) +- [x] Submit feature requests (title, description) - [ ] Handle feature request edition - [ ] Should we have the ability to do it? - [ ] How do we show to users that a feature request was indeed edited @@ -40,12 +40,11 @@ - [x] Admin ability to update status - [ ] Post official/pinned responses - [x] Sort by top voted, newest -- [ ] Filter by status by category +- [ ] Filter by status - [ ] Comments on requests - [x] Simple comments - [ ] Comments threads on requests - [x] Merge duplicate requests -- [ ] Request categories management ## Feeds Module diff --git a/drizzle/0006_melodic_menace.sql b/drizzle/0006_melodic_menace.sql new file mode 100644 index 0000000..a9d2fa2 --- /dev/null +++ b/drizzle/0006_melodic_menace.sql @@ -0,0 +1,2 @@ +DROP INDEX `idx_feature_requests_category`;--> statement-breakpoint +ALTER TABLE `feature_requests` DROP COLUMN `category`; \ No newline at end of file diff --git a/drizzle/meta/0006_snapshot.json b/drizzle/meta/0006_snapshot.json new file mode 100644 index 0000000..0a24e7b --- /dev/null +++ b/drizzle/meta/0006_snapshot.json @@ -0,0 +1,1523 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "eec14d3f-541d-45c5-844c-4b45eb164b0c", + "prevId": "f024260b-c00f-40d3-981d-89f2c8962fe8", + "tables": { + "oauth_sessions": { + "name": "oauth_sessions", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "session": { + "name": "session", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "oauth_states": { + "name": "oauth_states", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "indexer_cursor": { + "name": "indexer_cursor", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false, + "default": "'jetstream'" + }, + "cursor": { + "name": "cursor", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sphere_entry_counter": { + "name": "sphere_entry_counter", + "columns": { + "sphere_id": { + "name": "sphere_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "last_number": { + "name": "last_number", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": { + "sphere_entry_counter_sphere_id_spheres_id_fk": { + "name": "sphere_entry_counter_sphere_id_spheres_id_fk", + "tableFrom": "sphere_entry_counter", + "tableTo": "spheres", + "columnsFrom": [ + "sphere_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "entity_labels": { + "name": "entity_labels", + "columns": { + "label_id": { + "name": "label_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_entity_labels_entity": { + "name": "idx_entity_labels_entity", + "columns": [ + "entity_id", + "entity_type" + ], + "isUnique": false + } + }, + "foreignKeys": { + "entity_labels_label_id_sphere_labels_id_fk": { + "name": "entity_labels_label_id_sphere_labels_id_fk", + "tableFrom": "entity_labels", + "tableTo": "sphere_labels", + "columnsFrom": [ + "label_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "entity_labels_label_id_entity_id_pk": { + "columns": [ + "label_id", + "entity_id" + ], + "name": "entity_labels_label_id_entity_id_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sphere_labels": { + "name": "sphere_labels", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "sphere_id": { + "name": "sphere_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "idx_sphere_labels_sphere_name": { + "name": "idx_sphere_labels_sphere_name", + "columns": [ + "sphere_id", + "name" + ], + "isUnique": true + }, + "idx_sphere_labels_sphere_position": { + "name": "idx_sphere_labels_sphere_position", + "columns": [ + "sphere_id", + "position" + ], + "isUnique": false + } + }, + "foreignKeys": { + "sphere_labels_sphere_id_spheres_id_fk": { + "name": "sphere_labels_sphere_id_spheres_id_fk", + "tableFrom": "sphere_labels", + "tableTo": "spheres", + "columnsFrom": [ + "sphere_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sphere_members": { + "name": "sphere_members", + "columns": { + "sphere_id": { + "name": "sphere_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "did": { + "name": "did", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'member'" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'invited'" + }, + "invited_by": { + "name": "invited_by", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pds_uri": { + "name": "pds_uri", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "approval_pds_uri": { + "name": "approval_pds_uri", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "idx_sphere_members_did": { + "name": "idx_sphere_members_did", + "columns": [ + "did" + ], + "isUnique": false + } + }, + "foreignKeys": { + "sphere_members_sphere_id_spheres_id_fk": { + "name": "sphere_members_sphere_id_spheres_id_fk", + "tableFrom": "sphere_members", + "tableTo": "spheres", + "columnsFrom": [ + "sphere_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "sphere_members_sphere_id_did_pk": { + "columns": [ + "sphere_id", + "did" + ], + "name": "sphere_members_sphere_id_did_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sphere_modules": { + "name": "sphere_modules", + "columns": { + "sphere_id": { + "name": "sphere_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "module_name": { + "name": "module_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "enabled_at": { + "name": "enabled_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "sphere_modules_sphere_id_spheres_id_fk": { + "name": "sphere_modules_sphere_id_spheres_id_fk", + "tableFrom": "sphere_modules", + "tableTo": "spheres", + "columnsFrom": [ + "sphere_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "sphere_modules_sphere_id_module_name_pk": { + "columns": [ + "sphere_id", + "module_name" + ], + "name": "sphere_modules_sphere_id_module_name_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sphere_permissions": { + "name": "sphere_permissions", + "columns": { + "sphere_id": { + "name": "sphere_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "action_key": { + "name": "action_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "min_role": { + "name": "min_role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": {}, + "foreignKeys": { + "sphere_permissions_sphere_id_spheres_id_fk": { + "name": "sphere_permissions_sphere_id_spheres_id_fk", + "tableFrom": "sphere_permissions", + "tableTo": "spheres", + "columnsFrom": [ + "sphere_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "sphere_permissions_sphere_id_action_key_pk": { + "columns": [ + "sphere_id", + "action_key" + ], + "name": "sphere_permissions_sphere_id_action_key_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "spheres": { + "name": "spheres", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "handle": { + "name": "handle", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "visibility": { + "name": "visibility", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'public'" + }, + "owner_did": { + "name": "owner_did", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "pds_uri": { + "name": "pds_uri", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "spheres_handle_unique": { + "name": "spheres_handle_unique", + "columns": [ + "handle" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "feature_request_comment_votes": { + "name": "feature_request_comment_votes", + "columns": { + "comment_id": { + "name": "comment_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "author_did": { + "name": "author_did", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "pds_uri": { + "name": "pds_uri", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "idx_feature_request_comment_votes_comment": { + "name": "idx_feature_request_comment_votes_comment", + "columns": [ + "comment_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "feature_request_comment_votes_comment_id_feature_request_comments_id_fk": { + "name": "feature_request_comment_votes_comment_id_feature_request_comments_id_fk", + "tableFrom": "feature_request_comment_votes", + "tableTo": "feature_request_comments", + "columnsFrom": [ + "comment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "feature_request_comment_votes_comment_id_author_did_pk": { + "columns": [ + "comment_id", + "author_did" + ], + "name": "feature_request_comment_votes_comment_id_author_did_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "feature_request_comments": { + "name": "feature_request_comments", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "author_did": { + "name": "author_did", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "pds_uri": { + "name": "pds_uri", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "hidden_at": { + "name": "hidden_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "moderated_by": { + "name": "moderated_by", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "idx_feature_request_comments_request": { + "name": "idx_feature_request_comments_request", + "columns": [ + "request_id" + ], + "isUnique": false + }, + "idx_feature_request_comments_author_request": { + "name": "idx_feature_request_comments_author_request", + "columns": [ + "author_did", + "request_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "feature_request_comments_request_id_feature_requests_id_fk": { + "name": "feature_request_comments_request_id_feature_requests_id_fk", + "tableFrom": "feature_request_comments", + "tableTo": "feature_requests", + "columnsFrom": [ + "request_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "feature_request_statuses": { + "name": "feature_request_statuses", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "author_did": { + "name": "author_did", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "pds_uri": { + "name": "pds_uri", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "idx_feature_request_statuses_request": { + "name": "idx_feature_request_statuses_request", + "columns": [ + "request_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "feature_request_statuses_request_id_feature_requests_id_fk": { + "name": "feature_request_statuses_request_id_feature_requests_id_fk", + "tableFrom": "feature_request_statuses", + "tableTo": "feature_requests", + "columnsFrom": [ + "request_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "feature_request_votes": { + "name": "feature_request_votes", + "columns": { + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "author_did": { + "name": "author_did", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "pds_uri": { + "name": "pds_uri", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "idx_feature_request_votes_request": { + "name": "idx_feature_request_votes_request", + "columns": [ + "request_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "feature_request_votes_request_id_feature_requests_id_fk": { + "name": "feature_request_votes_request_id_feature_requests_id_fk", + "tableFrom": "feature_request_votes", + "tableTo": "feature_requests", + "columnsFrom": [ + "request_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "feature_request_votes_request_id_author_did_pk": { + "columns": [ + "request_id", + "author_did" + ], + "name": "feature_request_votes_request_id_author_did_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "feature_requests": { + "name": "feature_requests", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "sphere_id": { + "name": "sphere_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "number": { + "name": "number", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "author_did": { + "name": "author_did", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'requested'" + }, + "duplicate_of_id": { + "name": "duplicate_of_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pds_uri": { + "name": "pds_uri", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "hidden_at": { + "name": "hidden_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "moderated_by": { + "name": "moderated_by", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "label_tid": { + "name": "label_tid", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "idx_feature_requests_sphere_number": { + "name": "idx_feature_requests_sphere_number", + "columns": [ + "sphere_id", + "number" + ], + "isUnique": true + }, + "idx_feature_requests_sphere": { + "name": "idx_feature_requests_sphere", + "columns": [ + "sphere_id" + ], + "isUnique": false + }, + "idx_feature_requests_status": { + "name": "idx_feature_requests_status", + "columns": [ + "status" + ], + "isUnique": false + } + }, + "foreignKeys": { + "feature_requests_sphere_id_spheres_id_fk": { + "name": "feature_requests_sphere_id_spheres_id_fk", + "tableFrom": "feature_requests", + "tableTo": "spheres", + "columnsFrom": [ + "sphere_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "feed_posts": { + "name": "feed_posts", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "author_did": { + "name": "author_did", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "parent_id": { + "name": "parent_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pds_uri": { + "name": "pds_uri", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "idx_feed_posts_parent": { + "name": "idx_feed_posts_parent", + "columns": [ + "parent_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "kanban_columns": { + "name": "kanban_columns", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "sphere_id": { + "name": "sphere_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "idx_kanban_columns_sphere_slug": { + "name": "idx_kanban_columns_sphere_slug", + "columns": [ + "sphere_id", + "slug" + ], + "isUnique": true + }, + "idx_kanban_columns_sphere_position": { + "name": "idx_kanban_columns_sphere_position", + "columns": [ + "sphere_id", + "position" + ], + "isUnique": false + } + }, + "foreignKeys": { + "kanban_columns_sphere_id_spheres_id_fk": { + "name": "kanban_columns_sphere_id_spheres_id_fk", + "tableFrom": "kanban_columns", + "tableTo": "spheres", + "columnsFrom": [ + "sphere_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "kanban_task_comments": { + "name": "kanban_task_comments", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "task_id": { + "name": "task_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "author_did": { + "name": "author_did", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "pds_uri": { + "name": "pds_uri", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + }, + "hidden_at": { + "name": "hidden_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "moderated_by": { + "name": "moderated_by", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "idx_kanban_task_comments_task": { + "name": "idx_kanban_task_comments_task", + "columns": [ + "task_id" + ], + "isUnique": false + }, + "idx_kanban_task_comments_author_task": { + "name": "idx_kanban_task_comments_author_task", + "columns": [ + "author_did", + "task_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "kanban_task_comments_task_id_kanban_tasks_id_fk": { + "name": "kanban_task_comments_task_id_kanban_tasks_id_fk", + "tableFrom": "kanban_task_comments", + "tableTo": "kanban_tasks", + "columnsFrom": [ + "task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "kanban_task_status_changes": { + "name": "kanban_task_status_changes", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "task_id": { + "name": "task_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "author_did": { + "name": "author_did", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "pds_uri": { + "name": "pds_uri", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "idx_kanban_task_status_changes_task": { + "name": "idx_kanban_task_status_changes_task", + "columns": [ + "task_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "kanban_task_status_changes_task_id_kanban_tasks_id_fk": { + "name": "kanban_task_status_changes_task_id_kanban_tasks_id_fk", + "tableFrom": "kanban_task_status_changes", + "tableTo": "kanban_tasks", + "columnsFrom": [ + "task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "kanban_tasks": { + "name": "kanban_tasks", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "sphere_id": { + "name": "sphere_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "number": { + "name": "number", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "author_did": { + "name": "author_did", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "''" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'backlog'" + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "assignee_did": { + "name": "assignee_did", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pds_uri": { + "name": "pds_uri", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "hidden_at": { + "name": "hidden_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "moderated_by": { + "name": "moderated_by", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "label_tid": { + "name": "label_tid", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(datetime('now'))" + } + }, + "indexes": { + "idx_kanban_tasks_sphere_number": { + "name": "idx_kanban_tasks_sphere_number", + "columns": [ + "sphere_id", + "number" + ], + "isUnique": true + }, + "idx_kanban_tasks_sphere": { + "name": "idx_kanban_tasks_sphere", + "columns": [ + "sphere_id" + ], + "isUnique": false + }, + "idx_kanban_tasks_status": { + "name": "idx_kanban_tasks_status", + "columns": [ + "status" + ], + "isUnique": false + }, + "idx_kanban_tasks_sphere_status_position": { + "name": "idx_kanban_tasks_sphere_status_position", + "columns": [ + "sphere_id", + "status", + "position" + ], + "isUnique": false + } + }, + "foreignKeys": { + "kanban_tasks_sphere_id_spheres_id_fk": { + "name": "kanban_tasks_sphere_id_spheres_id_fk", + "tableFrom": "kanban_tasks", + "tableTo": "spheres", + "columnsFrom": [ + "sphere_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index 2d90b0d..f773f6a 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -43,6 +43,13 @@ "when": 1776250350625, "tag": "0005_volatile_mystique", "breakpoints": true + }, + { + "idx": 6, + "version": "6", + "when": 1776417674886, + "tag": "0006_melodic_menace", + "breakpoints": true } ] -} +} \ No newline at end of file diff --git a/packages/app/e2e/seed.ts b/packages/app/e2e/seed.ts index 710d2f1..7feecd7 100644 --- a/packages/app/e2e/seed.ts +++ b/packages/app/e2e/seed.ts @@ -81,7 +81,6 @@ const MEMBER_DID = "did:plc:e2e-test-member"; number: 1, title: "Add dark mode support", description: "It would be great to have a dark mode option for better readability at night.", - category: "enhancement", status: "approved", authorDid: MEMBER_DID, }, @@ -90,7 +89,6 @@ const MEMBER_DID = "did:plc:e2e-test-member"; number: 2, title: "Export data as CSV", description: "Allow users to export their data in CSV format for analysis.", - category: "general", status: "requested", authorDid: OWNER_DID, }, @@ -99,7 +97,6 @@ const MEMBER_DID = "did:plc:e2e-test-member"; number: 3, title: "Mobile app", description: "A native mobile application would improve the user experience significantly.", - category: "general", status: "requested", authorDid: MEMBER_DID, }, @@ -108,7 +105,6 @@ const MEMBER_DID = "did:plc:e2e-test-member"; number: 4, title: "Keyboard shortcuts", description: "Add keyboard shortcuts for common actions like voting and navigation.", - category: "enhancement", status: "done", authorDid: OWNER_DID, }, @@ -117,7 +113,6 @@ const MEMBER_DID = "did:plc:e2e-test-member"; number: 5, title: "Windows phone support", description: "Please add support for Windows Phone platform.", - category: "general", status: "not-planned", authorDid: MEMBER_DID, }, @@ -125,9 +120,9 @@ const MEMBER_DID = "did:plc:e2e-test-member"; for (const fr of featureRequests) { db.run( - `INSERT INTO feature_requests (id, sphere_id, number, title, description, category, status, author_did) - VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, - [fr.id, SPHERE_ID, fr.number, fr.title, fr.description, fr.category, fr.status, fr.authorDid], + `INSERT INTO feature_requests (id, sphere_id, number, title, description, status, author_did) + VALUES (?, ?, ?, ?, ?, ?, ?)`, + [fr.id, SPHERE_ID, fr.number, fr.title, fr.description, fr.status, fr.authorDid], ); } @@ -194,7 +189,6 @@ const MEMBER_DID = "did:plc:e2e-test-member"; number: 1, title: "Alpha dark mode", description: "Dark mode for Alpha sphere.", - category: "enhancement", status: "approved", authorDid: OWNER_DID, }, @@ -203,7 +197,6 @@ const MEMBER_DID = "did:plc:e2e-test-member"; number: 2, title: "Alpha CSV export", description: "CSV export for Alpha sphere.", - category: "general", status: "requested", authorDid: MEMBER_DID, }, @@ -212,7 +205,6 @@ const MEMBER_DID = "did:plc:e2e-test-member"; number: 3, title: "Alpha done feature", description: "A completed feature.", - category: "general", status: "done", authorDid: OWNER_DID, }, @@ -221,7 +213,6 @@ const MEMBER_DID = "did:plc:e2e-test-member"; number: 4, title: "Alpha rejected idea", description: "A rejected feature.", - category: "general", status: "not-planned", authorDid: MEMBER_DID, }, @@ -229,15 +220,14 @@ const MEMBER_DID = "did:plc:e2e-test-member"; for (const fr of alphaRequests) { db.run( - `INSERT INTO feature_requests (id, sphere_id, number, title, description, category, status, author_did) - VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, + `INSERT INTO feature_requests (id, sphere_id, number, title, description, status, author_did) + VALUES (?, ?, ?, ?, ?, ?, ?)`, [ fr.id, "sphere-alpha", fr.number, fr.title, fr.description, - fr.category, fr.status, fr.authorDid, ], @@ -280,7 +270,6 @@ const MEMBER_DID = "did:plc:e2e-test-member"; number: 1, title: "Beta mobile app", description: "Mobile app for Beta sphere.", - category: "general", status: "requested", authorDid: MEMBER_DID, }, @@ -289,7 +278,6 @@ const MEMBER_DID = "did:plc:e2e-test-member"; number: 2, title: "Beta API access", description: "Public API for Beta sphere.", - category: "enhancement", status: "approved", authorDid: OWNER_DID, }, @@ -297,15 +285,14 @@ const MEMBER_DID = "did:plc:e2e-test-member"; for (const fr of betaRequests) { db.run( - `INSERT INTO feature_requests (id, sphere_id, number, title, description, category, status, author_did) - VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, + `INSERT INTO feature_requests (id, sphere_id, number, title, description, status, author_did) + VALUES (?, ?, ?, ?, ?, ?, ?)`, [ fr.id, "sphere-beta", fr.number, fr.title, fr.description, - fr.category, fr.status, fr.authorDid, ], diff --git a/packages/core/src/db/migrate.ts b/packages/core/src/db/migrate.ts index b1ee115..0c14a9c 100644 --- a/packages/core/src/db/migrate.ts +++ b/packages/core/src/db/migrate.ts @@ -4,24 +4,12 @@ import { getDb } from "./index.ts"; const migrationsFolder = process.env.MIGRATIONS_PATH || "drizzle"; -const categoryDefaults = [ - { name: "General", slug: "general", color: "#6b7280", position: 0 }, - { name: "Enhancement", slug: "enhancement", color: "#3b82f6", position: 1 }, - { name: "Bug", slug: "bug", color: "#ef4444", position: 2 }, - { name: "Integration", slug: "integration", color: "#8b5cf6", position: 3 }, - { name: "UI / UX", slug: "ui-ux", color: "#f59e0b", position: 4 }, -] as const; - migrate(getDb(), { migrationsFolder }); // Data migration: renumber feature requests and kanban tasks to use the // shared sphere_entry_counter. Runs only once — skips if counter rows exist. seedEntryCounters(); -// Data migration: convert hardcoded feature request categories into -// sphere_labels + entity_labels. Runs only once — skips if labels already exist. -seedLabelsFromCategories(); - function seedEntryCounters() { const dbPath = process.env.DATABASE_PATH || "exosphere.sqlite"; const db = new Database(dbPath); @@ -97,84 +85,3 @@ function seedEntryCounters() { db.close(); } -function seedLabelsFromCategories() { - const dbPath = process.env.DATABASE_PATH || "exosphere.sqlite"; - const db = new Database(dbPath); - - // Check if the sphere_labels table exists - const tableExists = db - .query<{ name: string }, []>( - "SELECT name FROM sqlite_master WHERE type='table' AND name='sphere_labels'", - ) - .get(); - if (!tableExists) { - db.close(); - return; - } - - // Skip if already seeded - const existing = db.query<{ c: number }, []>("SELECT count(*) as c FROM sphere_labels").get(); - if (existing && existing.c > 0) { - db.close(); - return; - } - - // Check if feature_requests table exists (module may not be enabled) - const frTableExists = db - .query<{ name: string }, []>( - "SELECT name FROM sqlite_master WHERE type='table' AND name='feature_requests'", - ) - .get(); - if (!frTableExists) { - db.close(); - return; - } - - // Find spheres that have feature requests - const spheres = db - .query<{ sphere_id: string }, []>("SELECT DISTINCT sphere_id FROM feature_requests") - .all(); - - if (spheres.length === 0) { - db.close(); - return; - } - - let labelCounter = 0; - - for (const { sphere_id } of spheres) { - const tx = db.transaction(() => { - // Create labels for this sphere - const labelIds: Record = {}; - for (const cat of categoryDefaults) { - const id = `label_migration_${sphere_id}_${labelCounter++}`; - db.run( - "INSERT INTO sphere_labels (id, sphere_id, name, description, color, position) VALUES (?, ?, ?, NULL, ?, ?)", - [id, sphere_id, cat.name, cat.color, cat.position], - ); - labelIds[cat.slug] = id; - } - - // Link existing feature requests to their corresponding labels - const requests = db - .query<{ id: string; category: string }, [string]>( - "SELECT id, category FROM feature_requests WHERE sphere_id = ? AND category IS NOT NULL", - ) - .all(sphere_id); - - for (const req of requests) { - const labelId = labelIds[req.category]; - if (labelId) { - db.run( - "INSERT OR IGNORE INTO entity_labels (label_id, entity_id, entity_type) VALUES (?, ?, ?)", - [labelId, req.id, "feature-request"], - ); - } - } - }); - tx(); - console.log(`[migrate] Sphere ${sphere_id}: created labels from categories`); - } - - db.close(); -} diff --git a/packages/core/src/generated/lexicon-records.ts b/packages/core/src/generated/lexicon-records.ts index e771ebc..c4ffdbc 100644 --- a/packages/core/src/generated/lexicon-records.ts +++ b/packages/core/src/generated/lexicon-records.ts @@ -17,7 +17,6 @@ export interface FeatureRequestCommentVoteRecord { export interface FeatureRequestEntryRecord { title: string; description?: string; - category?: string; /** did — DID of the Sphere owner (the identity hosting the site.exosphere.sphere.profile record). */ subject: string; /** datetime */ diff --git a/packages/feature-requests/src/__tests__/db-operations.test.ts b/packages/feature-requests/src/__tests__/db-operations.test.ts index 93461b1..2f4a5b9 100644 --- a/packages/feature-requests/src/__tests__/db-operations.test.ts +++ b/packages/feature-requests/src/__tests__/db-operations.test.ts @@ -50,7 +50,7 @@ function seedFR(overrides: Partial & { id: authorDid: AUTHOR_DID, title: "Test FR", description: "A test feature request", - category: "general" as const, + status: "requested" as const, ...overrides, }; db.insert(featureRequests).values(values).run(); @@ -72,7 +72,6 @@ describe("insertFeatureRequest", () => { authorDid: AUTHOR_DID, title: "First", description: "Desc", - category: "general", pdsUri: null, }); expect(fr1).toBeDefined(); @@ -84,7 +83,6 @@ describe("insertFeatureRequest", () => { authorDid: AUTHOR_DID, title: "Second", description: "Desc", - category: "bug", pdsUri: null, }); expect(fr2!.number).toBe(2); @@ -97,7 +95,6 @@ describe("insertFeatureRequest", () => { authorDid: AUTHOR_DID, title: "Original", description: "Desc", - category: "general", pdsUri: null, }); @@ -108,7 +105,6 @@ describe("insertFeatureRequest", () => { authorDid: AUTHOR_DID, title: "Duplicate", description: "Desc", - category: "general", pdsUri: null, }); expect(dup).toBeDefined(); diff --git a/packages/feature-requests/src/__tests__/schemas.test.ts b/packages/feature-requests/src/__tests__/schemas.test.ts index 5974096..bfa12d0 100644 --- a/packages/feature-requests/src/__tests__/schemas.test.ts +++ b/packages/feature-requests/src/__tests__/schemas.test.ts @@ -15,16 +15,8 @@ describe("createFeatureRequestSchema", () => { it("accepts valid input with defaults", () => { const result = createFeatureRequestSchema.parse(valid); - expect(result.category).toBe("general"); - }); - - it("accepts an explicit category", () => { - const result = createFeatureRequestSchema.parse({ ...valid, category: "bug" }); - expect(result.category).toBe("bug"); - }); - - it("rejects unknown category", () => { - expect(() => createFeatureRequestSchema.parse({ ...valid, category: "nope" })).toThrow(); + expect(result.title).toBe("Add dark mode"); + expect(result.labelIds).toEqual([]); }); it("rejects empty title", () => { diff --git a/packages/feature-requests/src/api/requests.ts b/packages/feature-requests/src/api/requests.ts index 841eb7d..b174cc9 100644 --- a/packages/feature-requests/src/api/requests.ts +++ b/packages/feature-requests/src/api/requests.ts @@ -40,7 +40,6 @@ app.get("/:number{[0-9]+}", async (c) => { authorDid: featureRequests.authorDid, title: featureRequests.title, description: featureRequests.description, - category: featureRequests.category, status: featureRequests.status, duplicateOfId: featureRequests.duplicateOfId, pdsUri: featureRequests.pdsUri, @@ -164,7 +163,7 @@ app.post("/", requireAuth, requirePermission("feature-requests", "create"), asyn return c.json({ error: z.flattenError(result.error) }, 400); } - const { title, description, category, labelIds } = result.data; + const { title, description, labelIds } = result.data; const sphereId = c.var.sphereId; const sphereOwnerDid = c.var.sphereOwnerDid; const sphereVisibility = c.var.sphereVisibility; @@ -173,7 +172,6 @@ app.post("/", requireAuth, requirePermission("feature-requests", "create"), asyn let pdsUri: string | null = null; - // Write to PDS for public spheres (category deprecated — no longer written) if (sphereVisibility === "public") { const session = c.var.session; pdsUri = await putPdsRecord(session, COLLECTION, id, { @@ -189,7 +187,6 @@ app.post("/", requireAuth, requirePermission("feature-requests", "create"), asyn authorDid: did, title, description, - category, pdsUri, }); diff --git a/packages/feature-requests/src/db/operations.ts b/packages/feature-requests/src/db/operations.ts index 830f4ba..424847a 100644 --- a/packages/feature-requests/src/db/operations.ts +++ b/packages/feature-requests/src/db/operations.ts @@ -11,7 +11,7 @@ import { featureRequestCommentVotes, featureRequestStatuses, } from "./schema.ts"; -import type { Category, Status } from "../schemas/feature-request.ts"; +import type { Status } from "../schemas/feature-request.ts"; // ---- Feature Requests ---- @@ -21,7 +21,6 @@ export function insertFeatureRequest(params: { authorDid: string; title: string; description: string; - category: Category; pdsUri: string | null; }): typeof featureRequests.$inferSelect | undefined { const db = getDb(); @@ -43,7 +42,6 @@ export function insertFeatureRequest(params: { authorDid: params.authorDid, title: params.title, description: params.description, - category: params.category, pdsUri: params.pdsUri, }) .run(); diff --git a/packages/feature-requests/src/db/schema.ts b/packages/feature-requests/src/db/schema.ts index 5ae6b55..5e4d29e 100644 --- a/packages/feature-requests/src/db/schema.ts +++ b/packages/feature-requests/src/db/schema.ts @@ -9,7 +9,7 @@ import { import { sql } from "drizzle-orm"; import type { InferSelectModel } from "drizzle-orm"; import { spheres } from "@exosphere/core/db/schema"; -import { categories, statuses } from "../schemas/feature-request.ts"; +import { statuses } from "../schemas/feature-request.ts"; export const featureRequests = sqliteTable( "feature_requests", @@ -22,9 +22,6 @@ export const featureRequests = sqliteTable( authorDid: text("author_did").notNull(), title: text("title").notNull(), description: text("description").notNull(), - category: text("category", { enum: [...categories] }) - .notNull() - .default("general"), status: text("status", { enum: [...statuses] }) .notNull() .default("requested"), @@ -41,7 +38,6 @@ export const featureRequests = sqliteTable( uniqueIndex("idx_feature_requests_sphere_number").on(table.sphereId, table.number), index("idx_feature_requests_sphere").on(table.sphereId), index("idx_feature_requests_status").on(table.status), - index("idx_feature_requests_category").on(table.category), ], ); diff --git a/packages/feature-requests/src/indexer.ts b/packages/feature-requests/src/indexer.ts index 3c6f62f..9452e31 100644 --- a/packages/feature-requests/src/indexer.ts +++ b/packages/feature-requests/src/indexer.ts @@ -12,8 +12,8 @@ import { getDb } from "@exosphere/core/db"; import { eq, and } from "@exosphere/core/db/drizzle"; import { spheres } from "@exosphere/core/db/schema"; import { featureRequests, featureRequestComments } from "./db/schema.ts"; -import { categories, statuses } from "./schemas/feature-request.ts"; -import type { Category, Status } from "./schemas/feature-request.ts"; +import { statuses } from "./schemas/feature-request.ts"; +import type { Status } from "./schemas/feature-request.ts"; import { insertFeatureRequest, deleteFeatureRequestCascade, @@ -111,18 +111,12 @@ export const featureRequestsIndexer: ModuleIndexer = { if (!access.allowed || !access.sphereId) return; const sphereId = access.sphereId; - const rawCategory = record.category as string; - const category: Category = (categories as readonly string[]).includes(rawCategory) - ? (rawCategory as Category) - : "general"; - insertFeatureRequest({ id: rkey, sphereId, authorDid: did, title: (record.title as string) ?? "", description: (record.description as string) ?? "", - category, pdsUri, }); return; diff --git a/packages/feature-requests/src/mcp.ts b/packages/feature-requests/src/mcp.ts index e7ead87..693ba7b 100644 --- a/packages/feature-requests/src/mcp.ts +++ b/packages/feature-requests/src/mcp.ts @@ -15,7 +15,7 @@ export const featureRequestMcpTools: McpTool[] = [ { name: "list_feature_requests", description: - "List feature requests with optional filtering by status and sorting. Returns title, description, category, status, vote count, and comment count for each.", + "List feature requests with optional filtering by status and sorting. Returns title, description, status, vote count, and comment count for each.", inputSchema: { type: "object", properties: { diff --git a/packages/feature-requests/src/schemas/feature-request.ts b/packages/feature-requests/src/schemas/feature-request.ts index e57e873..5e4a693 100644 --- a/packages/feature-requests/src/schemas/feature-request.ts +++ b/packages/feature-requests/src/schemas/feature-request.ts @@ -1,17 +1,5 @@ import { z } from "zod"; -export const categories = ["general", "enhancement", "bug", "integration", "ui-ux"] as const; - -export type Category = (typeof categories)[number]; - -export const categoryLabels: Record = { - general: "General", - enhancement: "Enhancement", - bug: "Bug", - integration: "Integration", - "ui-ux": "UI / UX", -}; - export const statuses = [ "requested", "not-planned", @@ -54,7 +42,6 @@ export const markAsDuplicateSchema = z.object({ export const createFeatureRequestSchema = z.object({ title: z.string().min(1).max(200), description: z.string().min(1).max(10000), - category: z.enum(categories).default("general"), labelIds: z.array(z.string()).default([]), }); diff --git a/packages/feature-requests/src/types.ts b/packages/feature-requests/src/types.ts index b502e69..ef1c082 100644 --- a/packages/feature-requests/src/types.ts +++ b/packages/feature-requests/src/types.ts @@ -1,8 +1,6 @@ export type { FeatureRequest, FeatureRequestComment, FeatureRequestStatus } from "./db/schema.ts"; -export type { Category, Status, SettableStatus } from "./schemas/feature-request.ts"; +export type { Status, SettableStatus } from "./schemas/feature-request.ts"; export { - categoryLabels, - categories, statuses, settableStatuses, statusLabels, diff --git a/packages/feature-requests/src/ui/api/feature-requests.ts b/packages/feature-requests/src/ui/api/feature-requests.ts index aa87df0..34affc4 100644 --- a/packages/feature-requests/src/ui/api/feature-requests.ts +++ b/packages/feature-requests/src/ui/api/feature-requests.ts @@ -27,8 +27,6 @@ export function getFeatureRequests(statuses?: string[], sort?: SortBy, order?: S export function createFeatureRequest(body: { title: string; description: string; - /** @deprecated Kept for backward compat with PDS indexer; defaults to "general" server-side. */ - category?: string; labelIds?: string[]; }) { return moduleFetch<{ featureRequest: FeatureRequest }>("/feature-requests", {