{"id":26702132,"url":"https://github.com/leoantony72/blog_api","last_synced_at":"2025-07-27T15:13:12.046Z","repository":{"id":45598572,"uuid":"384202836","full_name":"leoantony72/blog_api","owner":"leoantony72","description":"Blog API made with typescript, express \u0026 PostgreSQL","archived":false,"fork":false,"pushed_at":"2021-12-06T09:22:41.000Z","size":407,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-27T02:39:15.723Z","etag":null,"topics":["api","api-rest","blog","express","nodejs","postgresql","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leoantony72.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-07-08T17:34:54.000Z","updated_at":"2024-01-31T15:31:01.000Z","dependencies_parsed_at":"2022-09-07T17:51:15.595Z","dependency_job_id":null,"html_url":"https://github.com/leoantony72/blog_api","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leoantony72%2Fblog_api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leoantony72%2Fblog_api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leoantony72%2Fblog_api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leoantony72%2Fblog_api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leoantony72","download_url":"https://codeload.github.com/leoantony72/blog_api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248705064,"owners_count":21148477,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","api-rest","blog","express","nodejs","postgresql","typescript"],"created_at":"2025-03-27T02:33:54.693Z","updated_at":"2025-04-13T11:27:53.016Z","avatar_url":"https://github.com/leoantony72.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Introduction\r\n\r\n\u003cp\u003eBlog API made with typescript, express \u0026 PostgreSQL with all the basic features and more !\u003c/p\u003e\r\n\r\n### Technologies\r\n\r\n- Nodejs\r\n- Expressjs\r\n- Typescript\r\n- PostgreSQL\r\n- Redis\r\n\r\n\u0026nbsp;\r\n\r\n## File Structure\r\n\r\n![GitHub Logo](readmeimg/file.png)\r\n\r\n## Basic commands\r\n\r\n```bash\r\ngit clone https://github.com/leoantony72/blog_api\r\n```\r\n\r\n```bash\r\nnpm install\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n### PostgreSQL Setup\r\n\r\n\u003cp\u003eYou have to install Postgres Yourself🙃\u003c/p\u003e\r\n\r\n\u003cp\u003eStart Postgres server❗\u003c/p\u003e\r\n\r\n```postgres\r\nsudo service postgresql start\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n\u003cp\u003eAfter installing get into postgres CLI\u003c/p\u003e\r\n\r\n```POSTGRES\r\nCREATE DATABASE blog; //This will create the database\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n\u003cp\u003eNext we have to setup TABLES❗\u003c/p\u003e\r\n\r\n```POSTGRES\r\n\\C blog //this will take you inside blog db\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n\u003cp\u003eCopy tables From blogapi.sql file(src-\u003emodels-\u003eblog_api.sql)❗\u003c/p\u003e\r\n\r\n```POSTGRES\r\n\\i FILE PATH\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n\u003cP\u003eOR YOU CAN COPY/PASTE FROM blogapi.sql\u003c/p\u003e\r\n\r\n```POSTGRESQL\r\nCREATE TABLE users(\r\n    userid VARCHAR(11) NOT NULL PRIMARY KEY,\r\n    username VARCHAR(50) NOT NULL,\r\n    passwordHash text NOT NULL,\r\n    user_role VARCHAR(25) NOT NULL,\r\n    sessionid text ,\r\n    registeredAt TIMESTAMP NOT NULL\r\n);\r\n\r\nCREATE INDEX idx_userid ON users(userid);\r\n\r\nCREATE TABLE authors(\r\n    id VARCHAR(11) NOT NULL PRIMARY KEY,\r\n    username VARCHAR(50),\r\n    profile_image BYTEA NULL\r\n);\r\n\r\nCREATE TABLE post(\r\n    post_id VARCHAR(11) NOT NULL PRIMARY KEY,\r\n    title VARCHAR(100) NOT NULL,\r\n    meta_title VARCHAR(100) NULL,\r\n    slug VARCHAR(100) NOT NULL UNIQUE,\r\n    summary VARCHAR(100) NULL,\r\n    content TEXT NULL DEFAULT NULL,\r\n    published VARCHAR(20) NULL,\r\n    publishedAt TIMESTAMP NOT NULL,\r\n    author_id VARCHAR(11) NULL REFERENCES authors(id)\r\n    ON DELETE CASCADE\r\n    ON UPDATE CASCADE\r\n);\r\n\r\nCREATE TABLE savedpost(\r\n    id VARCHAR(11) NOT NULL PRIMARY KEY,\r\n    userid VARCHAR(11) NOT NULL REFERENCES users(userid)\r\n    ON DELETE CASCADE\r\n    ON UPDATE CASCADE,\r\n    post_id VARCHAR(11) NOT NULL REFERENCES post(post_id)\r\n    ON DELETE CASCADE\r\n    ON UPDATE CASCADE\r\n);\r\n\r\nCREATE TABLE category(\r\n    id VARCHAR(11) NOT NULL PRIMARY KEY,\r\n    title VARCHAR(75) NOT NULL,\r\n    meta_title VARCHAR(100) NULL DEFAULT NULL,\r\n    slug VARCHAR(100) NOT NULL\r\n);\r\n\r\nCREATE INDEX idx_category_parent on category(id);\r\n\r\nCREATE TABLE post_category(\r\n    post_id VARCHAR(11) NOT NULL REFERENCES post(post_id)\r\n    ON DELETE CASCADE\r\n    ON UPDATE CASCADE ,\r\n    category_id VARCHAR(11) NOT NULL REFERENCES category(id)\r\n    ON DELETE CASCADE\r\n    ON UPDATE CASCADE\r\n);\r\nCREATE INDEX idx_post_post ON post_category(post_id ASC);\r\nCREATE INDEX idx_post_category ON post_category(category_id ASC);\r\n\r\n\r\n```\r\n\r\n\u003cp\u003eWITH THIS DB SETUP IS FINISHED😸\u003c/p\u003e\r\n\u0026nbsp;\r\n\r\n## Setting Up .ENV File😈\r\n\r\n\u003cP\u003eThese are the env variabes of database❗\u003c/P\u003e\r\n\r\n```ENV\r\nPORT = 3000\r\nDB_USER = test\r\nDB_PASSWORD = password\r\nDB_HOST = localhost\r\nDB_PORT = 5432\r\nDB_DATABASE = blog\r\nSESSION_SECRET = secret for session //use a strong one\r\nSESSION_MAXAGE = 3600000 * 60 * 10\r\nGMAIL_USER = example\r\nGMAIL_PASS = password\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n### Image Folder\r\n\r\n\u003cp\u003eCreate images Folder in Root dir, Inside Images Folder create post_banner Folder❗\u003c/p\u003e\r\n\r\n\u0026nbsp;\r\n\r\n### Start Server❗\r\n\r\n```SERVER\r\nnpm run dev -L //RUNNNING IN LOCALHOST:3000\r\n```\r\n\r\n\u003cP\u003eThe Server is now Running✔\u003c/P\u003e\r\n\r\n\u0026nbsp;\r\n\r\n# Api Routes\r\n\r\n\u003cp\u003eGET POSTS\u003c/p\u003e\r\n\r\n```ROUTES\r\nhttp://localhost:3000/api/posts //get all posts\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n\u003cp\u003eGET POST BY ID\u003c/p\u003e\r\n\r\n```ROUTES\r\nhttp://localhost:3000/api/post/:id //get post by ID\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n\u003cp\u003eGET POST BY CATEGORY\u003c/p\u003e\r\n\r\n```routes\r\nhttp://localhost:3000/api/posts/category/:category //get post by category\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n\u003cp\u003eGET POST BY AUTHOR\u003c/p\u003e\r\n\r\n```ROUTES\r\nhttp://localhost:3000/api/posts/author/leo //get post by author name\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n## REGISTER/LOGIN/LOGOUT (POST request) 🔥\r\n\r\n- \u003cp\u003eRegister User🙍‍♀️\u003c/p\u003e\r\n\r\n```ROUTES\r\nhttp://localhost:3000/api/auth/register\r\n```\r\n\r\n```JSON\r\n{\r\n  \"username\": \"example\",\r\n  \"email\": \"example@gmail.com\",\r\n  \"password\": \"password183$\",\r\n  \"confirmpassword\": \"password183$\"//password are hashed before storing in db\r\n}\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n- Login User\r\n\r\n```routes\r\nhttp://localhost:3000/api/auth/login  //Login users\r\n```\r\n\r\n```JSON\r\n{\r\n  \"username\":\"Leoantony72\",\r\n  \"password\":\"test1234\"\r\n}\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n- Logout Users\r\n\r\n```ROUTES\r\nhttp://localhost:3000/api/logout\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n- Forgot Password\r\n\r\n```ROUTES\r\nhttp://localhost:3000/api/auth/forgotpassword\r\n```\r\n\r\n```JSON\r\n{\r\n    \"success\": \"Email Sent\"\r\n}\r\n```\r\n\r\nSends 📧 to provided user, Also checks if user exist in db\r\n\u0026nbsp;\r\n\r\n# User Roles\r\n\r\n```JSON\r\nUSER AND ADMIN\r\n```\r\n\r\n\u003cP\u003eUsers cannot create posts,updatepost etc... , Only Admin users can Create post \u0026 modify post\u003c/P\u003e\r\n\r\n\u003cp\u003eBy default role is USER ,After registering a user you need go to db to change Role to ADMIN  ❗❗\u003c/p\u003e\r\n\r\n\u003cP\u003e⭕I RECOMMEND USING POSTBIRD (GUI) It is simple to use \u003c/P\u003e\r\n\u0026nbsp;\r\n\r\n# Create New Post \u0026 Modify\r\n\r\nUSE POSTMAN FOR TESTING❗\r\n\r\n- New post (post req)\r\n\r\n```Routes\r\nhttp://localhost:3000/api/admin/upload //create new post\r\n```\r\n\r\n\u003cP\u003eWE ALSO HAVE TO UPLOAD IMAGE SO CHOOSE *FORM DATA* IN POSTMAN ❗❗ \u003c/P\u003e\r\n\r\n![GitHub Logo](readmeimg/newpost.png)\r\n\r\n```json\r\n{\r\n  \"post_id\": \"hapefdmrktf\" //IF SUCCESS IT WILL RETURN A POSTID\r\n}\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n- Update Post (PUT req)\r\n\r\n```routes\r\nhttp://localhost:3000/api/admin/post/hapefdmrktf //update post\r\n```\r\n\r\n![GitHub Logo](readmeimg/updatepost.png)\r\n\r\n```json\r\n\"post updated\" //if success you will get this\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n- Delete Post (DELETE req)\r\n\r\n```routes\r\nhttp://localhost:3000/api/admin/post/hapefdmrktf //Delete post by post ID\r\n```\r\n\r\n```json\r\n\"post deleted\" //if success you will get this\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n# Search Post\r\n\r\n\u003cp\u003eSearch post by title/meta title\u003c/p\u003e\r\n\r\n```routes\r\nhttp://localhost:3000/api/search/attack on titan //Search post by post ID\r\n```\r\n\r\n```JSON\r\n{\r\n        \"post_id\": \"itlfosfntlj\",\r\n        \"title\": \"cool boi\",\r\n        \"meta_title\": \"attack on titan\\r\\n\",\r\n        \"slug\": \"testfgggfgr\",\r\n        \"summary\": \"res\",\r\n        \"content\": \"rser\",\r\n        \"published\": \"published\",\r\n        \"publishedat\": \"2021-07-19T06:02:55.380Z\",\r\n        \"author_id\": \"1\",\r\n        \"image\": \"1626674575348.jpeg\"\r\n    }\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n# Save Post\r\n\r\nyou need to login to use this feature\r\n\r\n- Add saved post (POST req)\r\n\r\n```routes\r\nhttp://localhost:3000/api/savedpost/itlfosfntlj //save post\r\n```\r\n\r\n```json\r\n{\r\n  \"success\": \"Post saved\" // if success you will get this\r\n}\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n- Delete saved post (DELETE req)\r\n\r\n```routes\r\nhttp://localhost:3000/api/savedpost/:id //delete saved post\r\n```\r\n\r\n```json\r\n{\r\n  \"success\": \"Post deleted\" // if success you will get this\r\n}\r\n```\r\n\r\n\u0026nbsp;\r\n\r\n- Get saved post (GET req)\r\n\r\n```routes\r\nhttp://localhost:3000/api/savedpost //Get saved post\r\n```\r\n\r\n```json\r\n//you will get the post if success\r\n[\r\n  {\r\n    \"post_id\": \"7383e359ddb\",\r\n    \"title\": \"cool boi\",\r\n    \"meta_title\": \"leo\",\r\n    \"slug\": \"nofsea\",\r\n    \"summary\": \"testsef\",\r\n    \"content\": \"test\",\r\n    \"published\": \"published\",\r\n    \"publishedat\": \"2021-08-04T22:34:30.985Z\",\r\n    \"author_id\": \"1\",\r\n    \"image\": \"1628116470935.jpeg\"\r\n  }\r\n]\r\n```\r\n\r\n## Some Additional Info\r\n\r\n\r\n\u003ch5\u003e\r\n\u003cp\u003e- Added Forgot Password\u003c/p\u003e\r\n\u003cp\u003e- included session \u0026 cookies\u003c/p\u003e\r\n\u003cp\u003e- Caching for Posts(/posts,/post/:id)\u003c/p\u003e\r\n\u003cp\u003e- Email verification,if not verified you cannot login\u003c/p\u003e\r\n\u003cp\u003e- You can only upload .png/.jpg/.jpeg file below 5mb ❗\u003c/p\u003e\r\n\u003cp\u003e- Passwords and tokens are hashed \u0026 stored in database\u003c/p\u003e\r\n\u003cp\u003e- Added input Validation in Login/register/forgotpassword\u003c/p\u003e\r\n\u003c/h5\u003e\r\n\r\n- \u003cb\u003eDependencies\u003c/b\u003e\r\n\r\n![GitHub Logo](readmeimg/Dependencies.png)\r\n\r\n## This marks the end of the documentaion...\r\n\r\nAny future updates and additional info will be added\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleoantony72%2Fblog_api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleoantony72%2Fblog_api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleoantony72%2Fblog_api/lists"}