{"id":19034324,"url":"https://github.com/tynarus/apily","last_synced_at":"2025-12-30T21:45:13.386Z","repository":{"id":57182114,"uuid":"208321534","full_name":"Tynarus/apily","owner":"Tynarus","description":"A basic mock service written in JavaScript, for easy implementation into JavaScript UI projects requiring mocks for development or testing.","archived":false,"fork":false,"pushed_at":"2023-03-01T22:31:31.000Z","size":61,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-01T17:34:07.107Z","etag":null,"topics":["apily","expressjs","http-mock","http-mocking","http-request","http-response","javascript","mock","mock-api","mock-data","mock-framework","mock-functions","mock-library","mock-server","mock-service","mocking","mocking-framework","mocks","node","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Tynarus.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-13T18:16:38.000Z","updated_at":"2019-09-16T17:37:39.000Z","dependencies_parsed_at":"2024-11-08T21:44:54.101Z","dependency_job_id":"ef8b2fae-5460-44ad-a891-4e25b2bac392","html_url":"https://github.com/Tynarus/apily","commit_stats":{"total_commits":12,"total_committers":1,"mean_commits":12.0,"dds":0.0,"last_synced_commit":"4df6c2a034ed8be61ec36aadb264426d78b433a8"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Tynarus/apily","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tynarus%2Fapily","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tynarus%2Fapily/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tynarus%2Fapily/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tynarus%2Fapily/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Tynarus","download_url":"https://codeload.github.com/Tynarus/apily/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tynarus%2Fapily/sbom","scorecard":{"id":144864,"data":{"date":"2025-08-11","repo":{"name":"github.com/Tynarus/apily","commit":"4df6c2a034ed8be61ec36aadb264426d78b433a8"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/11 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 3 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"11 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7","Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x","Warn: Project is vulnerable to: GHSA-rv95-896h-c2vc","Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg","Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-16T09:11:24.514Z","repository_id":57182114,"created_at":"2025-08-16T09:11:24.514Z","updated_at":"2025-08-16T09:11:24.514Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270820793,"owners_count":24651534,"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","status":"online","status_checked_at":"2025-08-17T02:00:09.016Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["apily","expressjs","http-mock","http-mocking","http-request","http-response","javascript","mock","mock-api","mock-data","mock-framework","mock-functions","mock-library","mock-server","mock-service","mocking","mocking-framework","mocks","node","typescript"],"created_at":"2024-11-08T21:44:46.701Z","updated_at":"2025-12-30T21:45:13.359Z","avatar_url":"https://github.com/Tynarus.png","language":"TypeScript","readme":"# Apily\n\nA basic mock service written in JavaScript, for easy implementation into JavaScript UI projects requiring mocks for development or testing.\n\nApily is written in TypeScript, and as such includes typings. Documentation examples will be written in TypeScript.\n\n## Setting up a Mock Service\n\nOnce the Apily package is installed, standing a mock service up is fairly straightforward. We'll start by making the main file that will launch the mock server.\n\nFor TypeScript projects, create a new directory called `mock/` at the root of your project, with an appropriate `tsconfig.json` file (your desired tsconfig may vary):\n \n```json\n{\n    \"compilerOptions\": {\n        \"module\": \"commonjs\",\n        \"moduleResolution\": \"node\",\n        \"target\": \"es6\",\n        \"outDir\": \"./dist\"\n    },\n    \"include\": [\n        \"./**/*.ts\"\n    ],\n    \"exclude\": [\n        \"../node_modules\"\n    ]\n}\n```\n \nWe'll also be adding a new file named `mock-server.ts` with the following content:\n\n```typescript\nimport { start } from 'apily';\n\nconst port = 4300;\n\nstart(port);\n```\n\nFrom there, we can add a new script to our `package.json`:\n\n```json\n\"scripts\": {\n    \"mock-server\": \"tsc --project ./mock/tsconfig.json \u0026\u0026 node ./mock/dist/mock/mock-server.js\"\n}\n```\n\nRunning this script with `npm run mock-server` should result in the mock service starting with the message `Loaded 0 mock requests`. The port specified above was `4300`, so we should now be able to hit our empty mock service at `http://localhost:4300`.\n\n## Creating Mocks\n\nHeading back into `mock-server.ts`, we can create our very first mock endpoint:\n\n```typescript\nimport { start, mock } from 'apily';\n\nmock({\n    method: 'GET',\n    url: '/test',\n    responseStatus: 200,\n    responseBody: {\n        text: 'Hello world!'\n    }\n});\n\nstart();\n```\n\nRestart the mock service, and instead we should now get the message `Loaded 1 mock requests`. If we try to hit `http://localhost:4300/test` in our browser, we should be given a JSON response of `{ text: 'Hello world!' }` \n\nIdeally as more mock are created, they'll be extrapolated out into their own mock files. We can move this test mock into a new file named `test-mock.ts`:\n\n```typescript\nimport { mock } from 'apily';\n\nmock({\n    method: 'GET',\n    url: '/test',\n    responseStatus: 200,\n    responseBody: {\n        text: 'Hello world!'\n    }\n});\n```\n\n...and instead now import that file into the main `mock-server.ts` file:\n\n```typescript\nimport { start } from 'apily';\n\nimport './test-mock';\n\nstart();\n```\n\nThis keeps our main mock service file clean and makes mocks easier to find.\n\n## Mock Config\n\nThe `mock()` function takes a single parameter, a `MockOptions` object. `MockOptions` is declared as follows:\n\n```typescript\ninterface MockOptions {\n    priority?: number;\n    method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n    url: string;\n    requestHeaders?: any;\n    requestParams?: any;\n    requestBody?: any;\n    responseStatus: number;\n    responseHeaders?: any;\n    responseBody?: any;\n}\n```\n\n- `priority` is the priority of the mock being created. In the case that multiple mocks are found for a given request, the one with the lowest `priority` value will be used. If multiple are found with the same `priority` value, the first one in wins.\n- `method` is the required request method. `GET`, `POST`, `PUT`, `PATCH`, or `DELETE`. All calls with the `OPTIONS` method are ignored by Apily.\n- `url` the exact url for the mock. `/test`, `/users/1/details`, `/news/items`, or whatever your particular request URL may be. Regex param variables are planned for a future release.\n- `requestHeaders` the headers that the mock requires. For example, setting this to `{ 'Authorization': 'Bearer mytoken' }` will mean that the mock will require that any requests send the `Authorization` header with the value `Bearer mytoken`.\n- `requestParams` the URL params that the mock requires. This is not yet functional and is planned for a future release.\n- `requestBody` the JSON request body required by the mock. \n- `responseStatus` the response status code. Ie `200` for OK, `401` for Unauthorized, `500` for internal server error, etc.\n- `responseHeaders` the response headers that will be returned by the mock.\n- `responseBody` the body that will be returned by the mock. Accepts strings, JSON, or a `ResponseFile` object that accepts a `fileName` parameter.\n  - It is possible to return static files, ie PDFs, as such: Supply a `responseBody` value of `new ResponseFile(myFileNameAndPath)` with a matching `responseHeaders` header of `'content-type': 'application/pdf'`.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftynarus%2Fapily","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftynarus%2Fapily","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftynarus%2Fapily/lists"}