{"id":15416854,"url":"https://github.com/ussserrr/print-service","last_synced_at":"2025-10-19T11:07:34.223Z","repository":{"id":113442604,"uuid":"326513860","full_name":"ussserrr/print-service","owner":"ussserrr","description":null,"archived":false,"fork":false,"pushed_at":"2021-07-14T10:35:22.000Z","size":2181,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-08T16:02:48.926Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","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/ussserrr.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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-03T22:35:04.000Z","updated_at":"2021-07-14T10:35:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"f2754df3-785b-4c11-96ee-3dbfbb3e3dea","html_url":"https://github.com/ussserrr/print-service","commit_stats":{"total_commits":79,"total_committers":1,"mean_commits":79.0,"dds":0.0,"last_synced_commit":"425b4c1bfb39192c310a1e31215f3d58f8584127"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ussserrr%2Fprint-service","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ussserrr%2Fprint-service/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ussserrr%2Fprint-service/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ussserrr%2Fprint-service/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ussserrr","download_url":"https://codeload.github.com/ussserrr/print-service/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240779324,"owners_count":19856165,"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":[],"created_at":"2024-10-01T17:14:02.309Z","updated_at":"2025-10-19T11:07:34.157Z","avatar_url":"https://github.com/ussserrr.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Print service\nWeb system to store, manage and print DOCX templates. Supplied with the frontend [control panel](https://github.com/ussserrr/print-cms).\n\n\n## Technologies overview\n - Latest \u0026 greatest NodeJS (v16 atm)\n - Core – modern yet popular NestJS framework:\n   - Highly active community\n   - Large plugins base\n - 100% latest TypeScript-powered\n - GraphQL Web API (NestJS feature):\n   - Versatile request-response communication\n   - Metadata, errors and extensions (warnings)\n   - Schema-first approach – schema is a source of truth for all underlying layers\n - Database – PostgreSQL\n - ORM – TypeORM (by NestJS):\n   - Auto-generates described schemas\n   - Strongly typed\n   - Create/update/remove etc. events triggers\n - Template files actual storage – file-system mount point:\n   - Can be a dedicated hard drive, network disk or just a local directory – just provide a path as an ENV variable\n   - Human-readable file structure – all files/foldres are named in respect to user input (with a proper sanitizing, of course) so the storage can be easily observed just by looking at a file explorer. Kept in-sync with possible renaming.\n - Templates filling (fields substitution): Docxtemplater package – time-proven solution\n - Printing to PDF by LibreOffice:\n   - On-demand execution by native NodeJS `child_process` API as a separate forked non-blocking process\n   - Easily installable by any popular Linux package manager\n   - Convenient CLI\n   - 3rd-party fonts support\n   - Free \u0026 open modular software\n - Print jobs queue:\n   - Powered by Redis DB\n   - NestJS-recommended Bull queue NodeJS package\n   - Asynchronous running\n   - Full support for distributed multi-instance configurations and unexpected processes crashes\n   - Set number of attempts\n   - Straightforward monitoring by any 3rd-party tool, shipped with Web GUI Bull-board\n - Background job for a temp files/jobs cleanups\n - Server-sent events (SSE) API to notify clients about requested jobs progress/results\n - Simple HTML home page is returned on root URL endpont to help a user find their way\n - Documentation by Compodoc:\n   - Complete Web static assets folder generation based on developer JSDocs (utilize existing controller)\n   - Zero-touching dependencies/relations graphs rendering\n - Docker/Kubernetes proof-of-concept configuration provided (see a diagram below):\n   - Ingress Nginx is catching requests at the entrance and route them to corresponding services. Also, acts as a load-balancer\n   - Deployment of each service (front- and backend) describes a number of instances (replicas) and hydrates containers with ENV variables\n\n\n## Kubernetes cluster architecture\n![diagram](/k8s/cluster-diagram.png)\n\n\n## Install \u0026 build\nThis project is a NestJS project and fully compilant with its CLI. Refer to Nest documentation on how to perform common tasks.\n\n\n## Running the app\nDevelopment mode:\n```bash\n$ npm run prebuild \u0026\u0026 NODE_ENV=development npm run start:dev\n```\n\nIn production, intended to be deployed on the Kubernetes cluster (see a diagram above):\n```bash\n$ kubectl apply -f k8s/prod -f k8s/ingress.yaml -f k8s/service.yaml\n```\n\n\n## Useful commands\nThese commands were used on different stages of development\n\n### Create new TemplateFile via curl:\n```bash\n$ curl -X POST -F 'operations={\"query\":\"mutation CreateTemplateFile($file:Upload!) {\\n  createTemplateFile(file:$file data:{templateTypeId:\\\"b1c1d8aa-5f07-4475-8719-a6dbb669b13e\\\"})\\n {id title}}\", \"variables\":{\"file\":null}}' -F 'map={\"0\":[\"variables.file\"]}' -F '0=@/Users/chufyrev/Pictures/IMG_3184.JPG' http://localhost/api/graphql\n```\n\n### Build a Docker image:\n```bash\n# development\n$ docker build -t print-service .\n\n# production\n$ docker build -t print-service-prod -f Dockerfile.prod .\n```\n\n### Run the development Docker container:\n```bash\n$ docker-compose up\n```\n\n### Shutdown a cluster:\n```bash\n$ kubectl delete -f k8s/prod -f k8s/ingress.yaml -f k8s/service.yaml\n```\n\n### Connect to service logs stream:\n```bash\n$ kubectl logs -f -lapp=print-service --all-containers=true\n```\n\n### List pods:\n```bash\n$ kubectl get pods\n```\n\n### Execute a command inside the particular pod:\n```\n$ kubectl exec print-service-deployment-797f9f96b6-847qc -- ls\n```\n\n### Generate docs:\n```\n$ npx @compodoc/compodoc -p tsconfig.json -d docs --silent\n```\n\n\n## Useful links\n - GraphQL file upload spec: https://github.com/jaydenseric/graphql-upload#tips\n - TypeORM i18n notes: https://github.com/typeorm/typeorm/issues/1612\n - Install Nginx Ingress for Kubernetes: https://kubernetes.github.io/ingress-nginx/deploy/\n\n\n## Roadmap\nSee [TODO](/TODO.md) and in-place TODOs to get a look on what can be improved in the future.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fussserrr%2Fprint-service","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fussserrr%2Fprint-service","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fussserrr%2Fprint-service/lists"}