{"id":16103292,"url":"https://github.com/blinpete/atlan-mock-task","last_synced_at":"2026-02-20T01:01:35.000Z","repository":{"id":104057296,"uuid":"581268388","full_name":"blinpete/atlan-mock-task","owner":"blinpete","description":"Atlan mock test","archived":false,"fork":false,"pushed_at":"2022-12-22T18:57:42.000Z","size":962,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-25T10:56:49.166Z","etag":null,"topics":["atlan","mock-test"],"latest_commit_sha":null,"homepage":"https://atlan-blinpete.netlify.app","language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blinpete.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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":"2022-12-22T18:08:06.000Z","updated_at":"2022-12-22T19:04:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"36e5c084-2322-497d-9792-d11194dd5208","html_url":"https://github.com/blinpete/atlan-mock-task","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/blinpete/atlan-mock-task","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blinpete%2Fatlan-mock-task","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blinpete%2Fatlan-mock-task/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blinpete%2Fatlan-mock-task/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blinpete%2Fatlan-mock-task/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blinpete","download_url":"https://codeload.github.com/blinpete/atlan-mock-task/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blinpete%2Fatlan-mock-task/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29637915,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T22:32:43.237Z","status":"ssl_error","status_checked_at":"2026-02-19T22:32:38.330Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["atlan","mock-test"],"created_at":"2024-10-09T18:56:34.830Z","updated_at":"2026-02-20T01:01:34.982Z","avatar_url":"https://github.com/blinpete.png","language":"Vue","readme":"[![Netlify Status](https://api.netlify.com/api/v1/badges/f8a70bf8-49e3-4042-a1cb-45fa28a49d31/deploy-status)](https://app.netlify.com/sites/atlan-blinpete/deploys)\n\n# atlan-mock-task\n\nMock task from [Atlan](https://atlan.com/).\nHere's the original [statement](https://atlanhq.notion.site/Task-Atlan-Frontend-Engineer-80ca8e35cc694e31bfd6b415d328269c).\n\n\n## Overview\n\nThis is an SQL query viewer:\n- it takes a query\n- sends it to the *fake server*\n- and displays the response (supporting unlimited amount of data due to list virtualization)\n- keeps a history of queries requested so that the user can switch between them\n\nIt implements the best practices for working with large data sets:\n- virtual list render\n- and lazy data loading technique\n\n## 1. Decomposition\n\nBasic blocks:\n- **data source** and **API client** wrapping it\n- **input field** for SQL query\n- **table** component rendering the data\n- **tabs or dropdown** for switching between queries\n\nThe statement offers brownies for rendering large amount of rows. It brings 2 extra points:\n- the API must support **chunking mechanism** and provide large amount of data. So rather than use those CSVs we generate data of any size using fakerjs.\n- we have to **virtualize** the table (for example, using VueUse)\n\n\n## 2. Stack\n\nScaffolding the project with `npm init vue@latest`.\n\n- [Vue 3](https://vuejs.org/) for rendering\n- [Typescript](https://www.typescriptlang.org/) (as always)\n- [Pinia](https://pinia.vuejs.org/) for state management\n- [VueUse](https://vueuse.org/) for having ready-to-go composables\n- [Faker](https://fakerjs.dev/) for mocking the server\n\n\n## 3. Mocking the server\n\nThis part is a bit troublesome because usually in frontend we go to a backend team and take an API contract (OpenAPI or GraphQL scheme) to generate both API client and types.\n\nNow we have to do it manually.\n\nThe server must provide chunking interface so I assume the following API:\n\n\n```ts\n\ntype ID = string\n\ninterface Identified {\n  id: ID\n}\n\n/**\n * We don't need any validation on the client side,\n * but even if we do it should run on the server.\n * So we have no types regarding SQL tables on the front.\n * The server owns all the data types, the client side knows\n * nothing about SQL schemes actual tables and structures.\n *\n * That's why `Item` maps to values of type `any`.\n *\n * The only thing we require is `Identified` contract.\n*/\ntype Item = Identified \u0026 Record\u003cstring, any\u003e\n\n\ntype Response\u003cT\u003e = Promise\u003cResponseSqlSelect\u003cT\u003e | ApiError\u003e\n\ntype ResponseSqlSelect\u003cT\u003e = {\n  /**\n   * This is a total length of the data matching a given query.\n   * The server should provide it because we load data by chunks\n   * and therefore have no any information about the total data size\n   * we are querying.\n  */\n  length: number\n\n  /** I expect the server to send the table headers as well.\n   * For relying on the data itself isn't safe, because\n   * there could be optional fields\n   * */\n  keys: (keyof T)[]\n\n  /** Chunk of data matching a given query */\n  data: T[]\n}\n\ntype API = {\n  getData: ({ query:  string, from: ID, to: ID, limit: number }) =\u003e Response\u003cItem\u003e\n}\n\n```\n\nData itself comes from Faker.\n\nThe **fake server** supports 3 tables: users, tasks, posts.\nAnd it maps a query to fixed random seed for samples to be consistent\nbetween calls.\n\n\n## 4. Virtual table\n\nI'm using `useVirtualList` from VueUse to virtualize the *tbody* part of the table.\nBut this particular implementation uses wrappers around the target element,\nso here we are trading off semantics.\n\nTable interface:\n```ts\ntype Props = {\n  items: Item[]\n  keys: string[]\n\n  /**\n   * We have to track an event when the bottom of the table entering viewport\n   * to support lazy loading technique.\n   **/\n  trackBottom?: boolean\n\n  /** We need this state to decide whether the data is fully loaded\n   * or there are chunks waiting on the server.\n  */\n  exhausted: boolean\n}\n```\n## 5. `History` feature\n\nI've picked Pinia for the project as a stare management solution because it's easy-to-use and modern.\n\nThe `history` feature provides a user with a sidebar showing their previous queries to switch between them at any time.\n\nThis is implemented as a sidebar because it has higher UX than a dropdown or tabs.\n\n## Performance metrics\n\nIn Lighthouse the app hits only 61 points because of the FakerJS (2.5MB of minified code)\n\nWith a real server it would hit 100 points.\n\n### Lighthouse perf score (with faker)\n\n![](./page-load-metrics/Lighthouse-with-faker.png)\n\n### Lighthouse perf score (without faker)\n![](./page-load-metrics/Lighthouse-without-faker.png)\n\nHowever in the more realistic tests (Chrome Performance insights) the page load is totaly ok:\n\n### Performance insights (with faker)\n![](page-load-metrics/Perf-insights-with-faker.png)\n\n### Performance insights (without faker)\n![](page-load-metrics/Perf-insights-without-faker.png)\n\n\nIn-depth JSON reports can be found in [page-load-metrics](./page-load-metrics/) directory.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblinpete%2Fatlan-mock-task","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblinpete%2Fatlan-mock-task","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblinpete%2Fatlan-mock-task/lists"}