{"id":18010271,"url":"https://github.com/ivorscott/client-backend-go","last_synced_at":"2025-03-26T14:31:55.469Z","repository":{"id":44140284,"uuid":"220719405","full_name":"ivorscott/client-backend-go","owner":"ivorscott","description":"Monolith backend in Go","archived":false,"fork":false,"pushed_at":"2023-05-11T20:39:00.000Z","size":9785,"stargazers_count":2,"open_issues_count":3,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-21T23:23:59.208Z","etag":null,"topics":["monolith","rest"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ivorscott.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2019-11-10T00:01:23.000Z","updated_at":"2022-07-27T08:25:56.000Z","dependencies_parsed_at":"2023-07-13T16:54:34.169Z","dependency_job_id":null,"html_url":"https://github.com/ivorscott/client-backend-go","commit_stats":null,"previous_names":["ivorscott/devpie-client-backend-go"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivorscott%2Fclient-backend-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivorscott%2Fclient-backend-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivorscott%2Fclient-backend-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivorscott%2Fclient-backend-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ivorscott","download_url":"https://codeload.github.com/ivorscott/client-backend-go/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245670796,"owners_count":20653424,"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":["monolith","rest"],"created_at":"2024-10-30T02:13:31.612Z","updated_at":"2025-03-26T14:31:54.956Z","avatar_url":"https://github.com/ivorscott.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Client Backend\n\nMaking public the project I've been streaming on Twitch. twitch.tv/ivorscott\n\n### Usage in 5 steps\n\n1 - Copy .env.sample and rename it to .env\n\nInclude the necessary `API_WEB_*` secrets from Auth0.\n\n```bash\nAPI_WEB_AUTH_DOMAIN=\nAPI_WEB_AUTH_AUDIENCE=\nAPI_WEB_AUTH_MAPI_AUDIENCE=\nAPI_WEB_AUTH_M_2_M_CLIENT=\nAPI_WEB_AUTH_M_2_M_SECRET=\n\nAPI_PORT=4000\nPPROF_PORT=6060\nCLIENT_PORT=3000\n\nREACT_APP_BACKEND=https://localhost:4000/v1\nAPI_WEB_FRONTEND_ADDRESS=https://localhost:3000\n\nDB_URL=postgres://postgres:postgres@db:5432/postgres?sslmode=disable\n```\n\n2 - Unblock port 5432 for postgres\n\n3 - Create self-signed certificates\n\n\n```makefile\nmkdir -p ./tls\ngo run $(go env GOROOT)/src/crypto/tls/generate_cert.go --rsa-bits=2048 --host=localhost\nmv *.pem ./tls\n```\n\n4 - Setup up the Postgres container\n\nRun the database in the background.\n\n```makefile\ndocker-compose up -d db\n```\n\n5 - Run the API with live reload enabled\n\n```\ndocker-compose up api\n```\n\n### The Migration and Seeding Workflow\n\nImagine an API that serves products. \n\n#### Make a migration to create the products table\n\n```makefile\ndocker-compose run migration create_products_table\n```\n\nAdd sql to both `up` \u0026 `down` migrations files found at: `./internal/schema/migrations/`.\n\n**Up**\n\n```sql\n-- 000001_create_products_table.up.sql\n\nCREATE TABLE products (\n    id UUID not null unique,\n    name varchar(100) not null,\n    price real not null,\n    description varchar(100) not null,\n    created timestamp without time zone default (now() at time zone 'utc')\n);\n```\n\n**Down**\n\n```sql\n-- 000001_create_products_table.down.sql\n\nDROP TABLE IF EXISTS products;\n```\n\n#### Creating a second migration\n\nMake another migration to add tags to products:\n\n```\ndocker-compose run migration add_tags_to_products\n```\n\n**Up**\n\n```sql\n\n-- 000002_add_tags_to_products.up.sql\n\nALTER TABLE products\nADD COLUMN tags varchar(255);\n```\n\n**Down**\n\n```sql\n-- 000002_add_tags_to_products.down.sql\n\nALTER TABLE products\nDROP Column tags;\n```\n\nMigrate up to the latest migration\n\n```makefile\ndocker-compose run up # you can migrate down with \"docker-compose run down\"\n```\n\nDisplay which version you have selected. Expect it two print `2` since you created 2 migrations.\n\n```makefile\ndocker-compose run version\n```\n\n### Seeding the database (optional)\n\nCreate a seed file of the appropriate name matching the table name you wish to seed.\n\nFor example:\n\n```makefile\ntouch ./internal/schema/seeds/products.sql\n```\n\nThis adds an empty products.sql seed file found under `./internal/schema/seeds`. Add the following sql content:\n\n```sql\n-- ./internal/schema/seeds/products.sql\n\nINSERT INTO products (id, name, price, description, created) VALUES\n('cbef5139-323f-48b8-b911-dc9be7d0bc07','Xbox One X', 499.00, 'Eighth-generation home video game console developed by Microsoft.','2019-01-01 00:00:01.000001+00'),\n('ce93a886-3a0e-456b-b7f5-8652d2de1e8f','Playstation 4', 299.00, 'Eighth-generation home video game console developed by Sony Interactive Entertainment.','2019-01-01 00:00:01.000001+00'),\n('faa25b57-7031-4b37-8a89-de013418deb0','Nintendo Switch', 299.00, 'Hybrid console that can be used as a stationary and portable device developed by Nintendo.','2019-01-01 00:00:01.000001+00')\nON CONFLICT DO NOTHING;\n```\n\nConflicts may arise when you execute the seed file more than once to the database. Appending \"ON CONFLICT DO NOTHING;\" to the end prevents this. This functionality depends on at least one table column having a unique constraint. In our case id is unique.\n\nFinally, add the products seed to the database.\n\n```\ndocker-compose exec db psql postgres postgres -f /seed/products.sql\n```\n\nEnter the database and examine its state.\n\n```makefile\ndocker-compose run debug-db\n```\n\n![Minion](documentation/compose-db-debug.png)\n\nIf the database container is removed, you don't need to start from scratch. A named volume was created to persist the data. Simply run the container in the background again.\n\n### Warning\n\nTo replicate the production environment as much as possible locally, we use self-signed certificates.\n\nIn your browser, you may see a warning and need to click a link to proceed to the requested page. This is common when using self-signed certificates.\n\n### Idiomatic Go Development (without a container)\n\nAnother approach is to containerize only the database. Work with the API in an idiomatic fashion. This means without a container and with live reloading `disabled`. To configure the API, use command line flags or export environment variables.\n\n```makefile\n# USING ENV VARS\nexport env $(cat .env | grep -v \"#\" | xargs)\ngo run ./cmd/api\n\n# USING FLAGS\ngo run ./cmd/api --db-disable-tls=true --web-auth-domain=\u003cINSERT-VALUE-HERE\u003e --web-auth-audience=\u003cINSERT-VALUE-HERE\u003e --web-auth-m-2-m-client=\u003cINSERT-VALUE-HERE\u003e --web-auth-m-2-m-secret=\u003cINSERT-VALUE-HERE\u003e --web-auth-mapi-audience=\u003cINSERT-VALUE-HERE\u003e\n```\n#### Development Commands\n\n```makefile\ndocker-compose up api # develop api with live reload\n\ndocker-compose up -d db # start the database in the background\n\ndocker-compose run debug-db # use pgcli to inspect postgres db\n\ndocker-compose run migration \u003cname\u003e # create a migration\n\ndocker-compose run version # print current migration version\n\ndocker-compose run up \u003cnumber\u003e # migrate up a number (optional number, defaults to latest migration)\n\ndocker-compose run down \u003cnumber\u003e # migrate down a number (optional number, defaults to 1)\n\ndocker-compose run force \u003cversion\u003e # Set version but don't run migration (ignores dirty state)\n\ndocker-compose exec db psql postgres postgres -f /seed/\u003cname\u003e.sql  # insert seed file to database\n```\n#### Build and Deploy Steps (in order)\n```makefile\nmake build # build production ready image\n\nmake login # login to Docker Hub\n\nmake publish # publish to Docker Hub\n\nmake metrics # enable Docker engine metrics\n\nmake secrets # create Docker swarm secrets\n\nmake server # create digital ocean server\n\nmake swarm # create single node Swarm cluster\n\nmake deploy # perform \"docker stack deploy\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivorscott%2Fclient-backend-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivorscott%2Fclient-backend-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivorscott%2Fclient-backend-go/lists"}