{"id":16227849,"url":"https://github.com/akryum/moquerie","last_synced_at":"2025-05-16T04:05:47.709Z","repository":{"id":221009704,"uuid":"697864337","full_name":"Akryum/moquerie","owner":"Akryum","description":"Effortlessly mock your entire API with simple configuration and a beautiful UI - or create a fake REST API in seconds","archived":false,"fork":false,"pushed_at":"2024-12-09T11:16:46.000Z","size":4180,"stargazers_count":208,"open_issues_count":2,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-16T04:05:40.972Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/Akryum.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"Akryum"}},"created_at":"2023-09-28T16:18:09.000Z","updated_at":"2025-04-07T10:17:20.000Z","dependencies_parsed_at":"2024-08-22T11:31:04.813Z","dependency_job_id":"7b0f28b0-03d3-4d93-b131-18bd63e7f9b7","html_url":"https://github.com/Akryum/moquerie","commit_stats":{"total_commits":364,"total_committers":1,"mean_commits":364.0,"dds":0.0,"last_synced_commit":"89e9088ab24e217914bb7c4bdf3c1adc37312fa9"},"previous_names":["akryum/moquerie"],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Akryum%2Fmoquerie","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Akryum%2Fmoquerie/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Akryum%2Fmoquerie/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Akryum%2Fmoquerie/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Akryum","download_url":"https://codeload.github.com/Akryum/moquerie/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254464895,"owners_count":22075570,"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-10T12:53:59.431Z","updated_at":"2025-05-16T04:05:42.699Z","avatar_url":"https://github.com/Akryum.png","language":"TypeScript","funding_links":["https://github.com/sponsors/Akryum"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./logo.svg\" width=\"150px\"/\u003e\n\u003c/p\u003e\n\n# moquerie\n\n\u003e Effortlessly mock your entire API with simple configuration and a beautiful UI.\n\nMoquerie is a tool that allows you to easily create a fake GraphQL or REST API (or both at the same time). It is designed to be simple to use and easy to configure.\n\n[Continuous Releases ➡️](https://nightly.akryum.dev/akryum/moquerie) | [Demo on StackBlitz ⚡️](https://stackblitz.com/edit/moquerie-demo?file=README.md)\n\n## Main features\n\n- **Local Database** (automatically managed for you)\n  - **Deactivate rows** so they are not returned by the API without deleting them\n  - **Factories** to create table rows (aka 'Resource Instances') (can be saved and committed to your repository)\n  - **Branches** (duplicate or empty)\n  - **Snapshots** (full or partial) (can be saved and committed to your repository)\n  - History\n- Generate database tables (aka 'Resource Types') from GraphQL schema or TypeScript files\n- Automatic **RESTful endpoints** (GET, POST, PUT, PATCH, DELETE)\n- Automatic **GraphQL server**\n- **No-Code read queries** (for GraphQL)\n- **Dashboard UI**\n- Extensible with `.moq.ts` files or with plugins\n- Typed APIs\n\n## Use Cases\n\n- Develop a frontend without needing the backend\n- Test while mocking the backend\n- Run a fake REST API for demos/workshops\n\n## Sponsors\n\n[Become a sponsor!](https://github.com/sponsors/Akryum)\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://guillaume-chau.info/sponsors/\" target=\"_blank\"\u003e\n    \u003cimg src='https://akryum.netlify.app/sponsors.svg'/\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## Setup\n\nInstall the `moquerie` package:\n\n```bash\npnpm install moquerie\n```\n\n*(Optional)* Create a `moquerie.config.ts` (or `moquerie.config.js`) file in the root of your project:\n\n```ts\nimport { defineConfig } from 'moquerie/config'\n\nexport default defineConfig({\n  // API port\n  server: {\n    port: 4002,\n  },\n})\n```\n\n## Getting started\n\n### REST Quickstart\n\n*(Optional)* To quickly create a fake REST server, create a `moquerie.rest.ts` file in your project that export resource types:\n\n```ts\n// moquerie.rest.ts\n\nexport interface MyObject {\n  id: string\n  title: string\n  count: number\n}\n```\n\nMoquerie will detect this file and automatically create RESTful endpoints for each resource type found within (without any additional configuration).\n\n### GraphQL Quickstart\n\nIf you have a GraphQL schema, you can let moquerie scan your code files for graphql schema definitions that uses the `gql` tag.\n\n```ts\n// moquerie.config.ts\n\nimport { defineConfig } from 'moquerie/config'\n\nexport default defineConfig({\n  // API port\n  server: {\n    port: 4002,\n  },\n  // GraphQL schema\n  graphql: {\n    schema: {\n      scanCodeFiles: './src/schema/**/*.ts',\n    },\n  },\n})\n```\n\nYou also have several options to configure your GraphQL schema:\n\n- `url`: Live URL to the GraphQL server\n- `jsonFile`: Introspection result JSON file\n- `graphqlFiles`: `.graphql` files to load, can be a path to a single file or a glob pattern\n- `scanCodeFiles`: Glob pattern to scan code files for GraphQL schema definitions that uses the `gql` tag\n\nFor REST you don't need additional configuration, but your need to register API Routes.\n\n### Run the server\n\nRun the `moquerie` command to start the server:\n\n```bash\npnpm exec moquerie\n```\n\nOpen your browser at the UI URL displayed in the console.\n\n![screenshot of home](./docs/home.png)\n\nYou can see the mocked API endpoints listed here.\n\n### Resource types\n\nBy default moquerie will infer resource types from your GraphQL schema. If you don't have one, you can define resource types for your REST API with the `rest.typeFiles` config:\n\n```ts\nimport { defineConfig } from 'moquerie/config'\n\nexport default defineConfig({\n  rest: {\n    typeFiles: [\n      'src/rest/types.ts',\n    ],\n  },\n})\n```\n\nWith this configuration, moquerie will automatically create RESTful endpoints for each resource types found with:\n\n- `GET /resourceType`: list all instances\n  - Filter the results with query parameters, for example `GET /resourceType?name=foo`\n  - Paginate with `__page` (first page is `0`) and `__pageSize` (default `10`) query parameters: `GET /resourceType?__page=1\u0026__pageSize=10`\n  - Sort with `__sort` query parameter with the syntax `\u003cfield\u003e:asc` or `\u003cfield\u003e:desc`: `GET /resourceType?__sort=name:asc`\n  - Search for text with `__search` query parameter: `GET /resourceType?__search=foo`\n- `POST /resourceType`: create a new instance\n- `GET /resourceType/:id`: get an instance\n- `PUT /resourceType/:id`: update an instance\n- `PATCH /resourceType/:id`: update an instance\n- `DELETE /resourceType/:id`: delete an instance\n\nHere is an example that demonstrate several supported features such as importing types from other files, optional fields, union types, and deprecated fields:\n\n```ts\nimport type { MyObjectNotExported } from './other.js'\n\nexport interface MyObject {\n  id: string\n  name: string\n  count: number\n}\n\n/**\n * Another object\n * @restPath /foo\n */\nexport interface MyOtherObject {\n  id: string\n  /**\n   * Some useful description\n   */\n  description?: string\n  otherDescription: string | undefined\n  thirdDescription: null | string\n  objects: MyObject[]\n  notExported: MyObjectNotExported\n  /**\n   * @deprecated Use `otherDescription` instead\n   */\n  deprecatedField: string\n}\n\n/**\n * @deprecated Use `MyOtherObject` instead\n */\nexport interface OldObject {\n  id: string\n  name: string\n  count: number\n}\n```\n\nYou can also easily extend types for existing resource types (usually from a GraphQL schema)\n\n```ts\nimport { defineConfig } from 'moquerie/config'\n\nexport default defineConfig({\n  graphql: {\n    schema: {\n      scanCodeFiles: './src/**/*.ts',\n    },\n  },\n\n  extendTypes: {\n    typeFiles: [\n      'src/extend/types.ts',\n    ],\n  },\n})\n```\n\nHere is an example that demonstrate extending a type from a GraphQL schema:\n\n```ts\n// Extend the Message type from the GraphQL schema\nexport interface Message {\n  /**\n   * Some example property added to the schema\n   */\n  internalProp: string\n}\n```\n\n### API Routes\n\nEvery code you write for  moquerie should be placed inside files ending with `.moq.ts` (you can change this in the config with `mockFiles`). Moquerie will automatically load these files for you.\n\nIn addition to API routes, we can also define resolvers, scripts and much more as described later.\n\nHere is an example of a simple API route:\n\n```ts\n// file-name.moq.ts\n\nimport { defineApiRoutes, defineResolvers, defineSchemaTransforms, defineScripts } from 'moquerie/mocks'\n\nexport default {\n  // Define API routes\n  ...defineApiRoutes((router) =\u003e {\n    router.get('/messages/count', () =\u003e 42)\n  }),\n}\n```\n\nWe recommend using the spread operator to merge the results of the `defineApiRoutes`, `defineResolvers`, `defineSchemaTransforms`, and `defineScripts` functions. For example:\n\n```ts\n// file-name.moq.ts\n\nexport default {\n  ...defineApiRoutes((router) =\u003e {\n    // Define API routes\n  }),\n  ...defineResolvers({\n    // Define resolvers\n  }),\n  ...defineSchemaTransforms(({ schema }) =\u003e {\n    // Define schema transforms\n  }),\n  ...defineScripts({\n    // Define scripts\n  }),\n}\n```\n\nYou can use the `router` object to define API routes. The `router` object has a method for each HTTP verb and each handler function receive a useful object as the parameter that allow you to access the database and other utilities.\n\n```ts\n// file-name.moq.ts\n\nimport { defineApiRoutes, defineResolvers, defineSchemaTransforms, defineScripts } from 'moquerie/mocks'\n\nexport default {\n  // Define API routes\n  ...defineApiRoutes((router) =\u003e {\n    router.get('/messages/count', async ({ db }) =\u003e {\n      // There are many more methods available on the context object above\n      return (await db.Message.findMany()).length\n    })\n  }),\n}\n```\n\n## Database\n\nThe Database page is a data explorer in which you can create, read, update, and delete rows (aka 'Resource Instances'). You can also deactivate rows so they are not returned by the API without deleting them.\n\n![screenshot of database](./docs/database.png)\n\nInstances that are active (open eye icon) will be taken into account when querying the API, while inactive instances (slashed eye icon) will be ignored - even if you call the database in resolvers! This is useful for testing different scenarios without having to delete and recreate instances constantly.\n\nYou can select an instance to see its details, update it, or deactivate it. You can also select multiple instances to apply bulk changes using the `Shift` key.\n\n![screenshot of multiple selection](./docs/database-select-many.png)\n\n![screenshot of multiple selection](./docs/database-bulk-edit.png)\n\n### Branches\n\nTo help you switch between different scenarios, you can create branches. Branches are like a copy of the database at a certain point in time. You can create a new branch from the current database, or you can create an empty branch.\n\n![screenshot of branches](./docs/database-branches.png)\n\n![screenshot of creating a branch](./docs/database-branch-create.png)\n\n### No-Code GraphQL Queries\n\nMoquerie allows you to query your mocked GraphQL API without writing any code for reading data. Use the `Query` resource that represents the root query type of your GraphQL schema. Your API will automatically use the active `Query` instance to return data for your GraphQL queries.\n\nFor example, if you have a `Query` resource with a `hello` field that returns a string, you can query it like this:\n\n```graphql\nquery {\n  hello\n}\n```\n\nIn the Dashboard UI, create a `Query` instance and set the value of the `hello` field to `world`.\n\n\u003e [!TIP]\n\u003e It's a  'singleton' resource (it has the `singleton` tag as shown in the UI), meaning you can only have one active instance at a time. If you activate another instance, the previous one will be deactivated automatically.\n\nNow if you run the above query in the GraphQL Playground, you will get the following result:\n\n```json\n{\n  \"data\": {\n    \"hello\": \"world\"\n  }\n}\n```\n\nAny resources referenced in the `Query` instance will be resolved automatically. For example, if the `Query` instance has a `currentUser` field that references a `User` resource, the `User` resource will be resolved and returned as part of the response. To change which `User` resource is returned, you can create a new `User` instance and reference it in the `Query` instance by clicking on the `currentUser` field and adding the newly created `User` instance.\n\n![screenshot of the Query resource](./docs/database-reference.png)\n\n![screenshot of the modal to edit references](./docs/database-reference-edit.png)\n\n\u003e [!TIP]\n\u003e Even if a field is supposed to return a single instance, you can still reference multiple instances. Moquerie will automatically pick the first active instance. You can reorder the instances to change which one is picked first.\n\n## Factories\n\nFactories are simple functions that create a single row (aka 'Resource Instance') in the database. They can be saved and committed to your repository to be easily shared with your team.\n\n![screenshot of a factory](./docs/factory.png)\n\nFactories use [faker](https://github.com/faker-js/faker) to generate random data.\n\n![screenshot of faker ui in the factory](./docs/factory-faker.png)\n\nYou can then use them to create instances in the database.\n\n![screenshot of a factory creating instances](./docs/factory-create-instances.png)\n\nAnytime you can save things to the current repository, you will see a toggle to switch between `Local` and `Repository`.\n\n![screenshot of the location toggle](./docs/factory-toggle-location.png)\n\n## Snapshots\n\nSnapshots are a way to save the state of the database at a certain point in time. You can save full snapshots or partial snapshots (only some resource instances). Similar to factories, snapshots can be saved and committed to your repository.\n\n![screenshot of a snapshot](./docs/snapshot.png)\n\nYou can then edit, delete or import snapshots to your database. Note that data inside resource instances cannot be directly edited in the snapshot editor.\n\n## PubSub\n\nYou can use the PubSub editor to publish real-time events to your API. This is useful for testing subscriptions or other real-time features.\n\n![screenshot of the pubsub editor](./docs/pubsub.png)\n\n## Scripts\n\nScripts allows you to create complex scenarios that involve calling multiple factories, database operations and maybe more.\n\nSimilar to API Routes, you need to define scripts in `.moq.ts` files.\n\n```ts\n// file-name.moq.ts\n\nimport { defineScripts } from 'moquerie/mocks'\n\nexport default {\n  ...defineScripts({\n    // Each key is a script\n    createSimpleMessage: {\n      description: `Create a simple message sent by current user`,\n      fn: async ({ generateResource, db }) =\u003e {\n        // Create message with a Factory\n        const [ref] = await generateResource('Message', 'SimpleMessageFactory')\n\n        // Update message with current user\n        const me = await db.User.findFirstReference((data, { tags }) =\u003e tags.includes('me'))\n        if (!me) {\n          throw new Error(`User with tag 'me' not found`)\n        }\n        await db.Message.updateFirst({\n          from: me,\n        }, (_, instance) =\u003e instance.id === ref.__id)\n      },\n    },\n  }),\n}\n```\n\nYou can run scripts from the UI or from the API. In the Dashboard UI, you will see a summary of the operations done by the script or any error that occurred.\n\n![screenshot of the script editor](./docs/script.png)\n\n## Resolvers\n\nResolvers are functions that are called when a query is made to the API. They can be used to customize the response of the API, or to perform complex operations. Each resolver is a function accosiated with a specific field of a specific Resource Type in the schema.\n\nSimilar to API Routes and Scripts, you need to define resolvers in `.moq.ts` files.\n\n```ts\nimport { defineResolvers } from 'moquerie/mocks'\n\nexport default {\n  ...defineResolvers({\n    // Each key is a Resource Type\n    // Target type is `Query`\n    Query: {\n      // Each key is a field of the `Query` type\n\n      // field name is `manyHellosCount`\n      manyHellosCount: async ({ db }) =\u003e {\n        const query = await db.Query.findFirst()\n        return query?.manyHellos.length ?? 0\n      },\n    },\n\n    // Target type is `Mutation`\n    Mutation: {\n      // Each key is a field of the `Mutation` type\n\n      // field name is `addHello`\n      addHello: async ({ input, db, pubsub }) =\u003e {\n        const query = await db.Query.findFirst()\n        const manyHellos = query?.manyHellos ?? []\n        manyHellos.push(input.message)\n        await db.Query.updateFirst({\n          manyHellos,\n        })\n        pubsub.graphql.publish('helloAdded', {\n          helloAdded: input.message,\n        })\n        return manyHellos\n      },\n\n      // field name is `removeHello`\n      removeHello: async ({ input, db, pubsub }) =\u003e {\n        const query = await db.Query.findFirst()\n        const manyHellos = query?.manyHellos ?? []\n        const index = manyHellos.indexOf(input.message)\n        if (index !== -1) {\n          manyHellos.splice(index, 1)\n          await db.Query.updateFirst({\n            manyHellos,\n          })\n        }\n        pubsub.graphql.publish('helloRemoved', {\n          helloRemoved: input.message,\n        })\n        return manyHellos\n      },\n\n      testMutation: () =\u003e true,\n\n      addSimple: async ({ input, db, pubsub }) =\u003e {\n        const simple = await db.Simple.create({\n          id: input.id,\n        })\n\n        // Publish resource instance value\n\n        // Either pass the value directly if it comes from `db`:\n        // pubsub.graphql.publish('simpleAdded', {\n        //   simpleAdded: simple,\n        // })\n\n        // Or pass the reference:\n        pubsub.graphql.publish('simpleAdded', {\n          simpleAdded: await db.Simple.findFirstReference(s =\u003e s.id === simple.id),\n        })\n\n        // This will not work as we lose the hidden flag:\n        // pubsub.graphql.publish('simpleAdded', {\n        //   simpleAdded: {\n        //     ...simple,\n        //   },\n        // })\n\n        return simple\n      },\n    },\n\n    // Target type is `User`\n    User: {\n      // field name is `fullName`\n      fullName: ({ parent: user }) =\u003e `${user.firstName} ${user.lastName}`\n    }\n  }),\n}\n```\n\nYou can inspect which resolvers are detected by moquerie in the UI.\n\n![screenshot of the resolvers](./docs/resolvers.png)\n\n## Database Operations\n\nYou can perform database operations in resolvers, scripts and API routes. Usually, you can use the `db` object to interact with the database from the context parameter object.\n\n```ts\nimport { defineResolvers } from 'moquerie/mocks'\n\nexport default {\n  ...defineResolvers({\n    Query: {\n      manyHellosCount: async ({ db }) =\u003e {\n        // Access the database\n        const query = await db.Query.findFirst()\n        return query?.manyHellos.length ?? 0\n      },\n    },\n  }),\n}\n```\n\nEach Resource Type has a set of methods that you can use to interact with the database, using the following pattern:\n\n```ts\nconst result = await db.ResourceType.methodName(/* Params... */)\n```\n\n### Instance References\n\nResource instances are stored in a single file each. If an instance contains other instances, they are stored as references. A reference looks like this:\n\n```json\n{\n  \"__resourceName\": \"User\",\n  \"__id\": \"SamRdWgbjDqv3BN2ZAHky\"\n}\n```\n\n\u003e [!TIP]\n\u003e Moquerie will automatically resolve the references when reading resource instances. References will never appear in the result of the database calls, so you can safely use them as response values for your mocked API.\n\nYou can get the reference of an instance with the `findFirstReference` method:\n\n```ts\nconst reference = await db.Messages.findFirstReference(m =\u003e m.id === someId)\n```\n\nYou can then use it to update other instances without getting the full object.\n\nYou can also get multiple references with the `findManyReferences` method:\n\n```ts\nconst references = await db.User.findManyReferences(u =\u003e u.email.endsWith('@acme.com'))\n```\n\n### Retrieve instances\n\nFind the first instance that matches a condition:\n\n```ts\nconst user = await db.User.findFirst(u =\u003e u.email === 'cat@acme.com')\n```\n\n\u003e [!TIP]\n\u003e Only active instances are returned by the database. You can deactivate instances to hide them from the API in the dashboard UI.\n\nYou can also omit the condition to get the first instance that is active:\n\n```ts\nconst query = await db.Query.findFirst()\n```\n\nThere is also a convenience version that throws an error if the instance is not found:\n\n```ts\nconst user = await db.User.findFirstOrThrow(u =\u003e u.email === 'cat@acme.com')\n```\n\nFind many instances that match a condition:\n\n```ts\nconst users = await db.User.findMany(u =\u003e u.email.endsWith('@acme.com'))\n```\n\nPick a random instance:\n\n```ts\nconst user = await db.User.pickOneRandom()\n```\n\nPick multiple random instances:\n\n```ts\n// Randomly pick between 1 and 10 user instances\nconst users = await db.User.pickManyRandom(1, 10)\n```\n\n\u003e [!TIP]\n\u003e You can also use the `findMany` method to narrow down the results with the filter, then use the `pickRandom` util function from the context object.\n\n### Tags and instance metadata\n\nUsually when there is a condition predicate, you can also use the second parameter (which is the full instance including metadata) to access the tags of the instance:\n\n```ts\nconst me = await db.User.findFirst((_data, { tags }) =\u003e tags.includes('me'))\nconst userRefs = await db.User.findManyReferences((_u, { tags }) =\u003e tags.includes('admin'))\nconst users = await db.User.findMany((_u, { tags }) =\u003e tags.includes('admin'))\n```\n\nTags and other metadata are never included in the result of the Database calls. They are only used to facilitate your queries.\n\n### Update instances\n\nUpdate the first instance that matches a condition:\n\n```ts\nconst user = await db.User.updateFirst({\n  someProperty: 'newValue',\n}, u =\u003e u.email === 'cat@acme.com')\n```\n\nOr multiple instances:\n\n```ts\nconst users = await db.User.updateMany({\n  someProperty: 'newValue',\n}, u =\u003e u.email.endsWith('@acme.com'))\n```\n\n### Create instances\n\nCreate a new instance:\n\n```ts\nconst user = await db.User.create({\n  id: generateId(), // `generateId` is a util from context object\n  email: 'cat@acme.com',\n})\n```\n\n### Delete instances\n\nDelete **all instances** that match a condition:\n\n```ts\nawait db.User.delete(u =\u003e u.email.endsWith('@acme.com'))\n```\n\n## History\n\nYou can see the history of all the changes made to the database in the History page.\n\n![screenshot of the history](./docs/history.png)\n\n## REST Playground\n\nYou can use the REST Playground to test your REST API.\n\n![screenshot of the rest playground](./docs/rest-playground.png)\n\n## GraphQL Playground\n\nYou can use the GraphQL Playground to test your GraphQL API.\n\n![screenshot of the graphql playground](./docs/graphql-playground.png)\n\n## Schema Transforms\n\nYou can make changes to the schema programmatically using schema transforms. This is useful for adding new internal fields for example.\n\n```ts\n// file-name.moq.ts\n\nimport { defineSchemaTransforms } from 'moquerie/mocks'\n\nexport default {\n  ...defineSchemaTransforms(({ schema, createEnumField }) =\u003e {\n    schema.types.User.fields.customInternalField = createEnumField('customInternalField', [\n      { value: 1, description: 'One' },\n      { value: 2, description: 'Two' },\n      { value: 3, description: 'Three' },\n    ])\n  }),\n}\n```\n\n## Programmatic API\n\nYou can also use moquerie programmatically. You always start by creating an instance of moquerie:\n\n```ts\nimport { createMoquerieInstance } from 'moquerie'\n\nconst mq = await createMoquerieInstance({\n  cwd: process.cwd(),\n  watching: true,\n  skipWrites: false,\n})\n```\n\n\u003e [!TIP]\n\u003e You can set `watching` to `false` and `skipWrites` to `true` to disable watching and writing to the disk during tests.\n\nYou can then pass the moquerie instance to most of the functions in the `moquerie` package.\n\n### Start server\n\nThis will start the mocked APIs.\n\n```ts\nimport { startServer } from 'moquerie'\n\nawait startServer(mq)\n```\n\n### Run a Script\n\nYou can run a script by its id (the key used in `defineScripts`).\n\n```ts\nimport { runScript } from 'moquerie'\n\nconst report = await runScript(mq, 'createSimpleMessage')\n```\n\n### Call a Factory\n\n```ts\nimport { createInstanceFromFactory, getFactoryByName } from 'moquerie'\n\nconst factory = await getFactoryByName(mq, 'SimpleMessage')\nconst instance = await createInstanceFromFactory(mq, {\n  factory,\n  save: true,\n})\n```\n\n### Use a Snapshot\n\nThis will create a new branch from the snapshot.\n\n```ts\nimport { useSnapshot } from 'moquerie'\n\nawait useSnapshot(mq, 'some-snapshot-id')\n```\n\n### Get the resolved context\n\nThe resolved context of the moquerie instance is useful to access the database, the pubsub, the resource schema, the list of scripts, resolvers, and so on.\n\n```ts\nconst ctx = await mq.getResolvedContext()\n```\n\n### Call the Database\n\nYou can call the database the same way you would in a resolver or a script using the resolved context.\n\n```ts\nconst ctx = await mq.getResolvedContext()\n// You can even check for the tags\nconst me = await ctx.db.User.findFirstReference((data, { tags }) =\u003e tags.includes('me'))\n```\n\n### Cleanup\n\nYou can stop and cleanup the moquerie instance and its server:\n\n```ts\nawait mq.destroy()\n```\n\n## Tests\n\nIn your tests you can use the Programmatic API to start the server, run scripts, call factories, and more. This ensures that your app can still make requests to the mocked API even in the test environment.\n\n1. First, create an instance with `createTestInstance`. By default it will disable disk writes and watching.\n2. Then you can use an existing snapshot saved to the repository with `useSnapshot` or use factories/scripts defined in your `.moq.ts` files.\n3. Finally you can start the server with `startServer`.\n\nAfter your test run, you can destroy the instance with `destroy`.\n\n```ts\nimport type { MoquerieInstance } from 'moquerie'\nimport { addResolvers, createTestInstance, startServer, useSnapshot } from 'moquerie'\nimport { afterEach, beforeEach, describe, expect, it } from 'vitest'\n\ndescribe('fetch', () =\u003e {\n  let mq: MoquerieInstance\n  let port: number\n\n  beforeEach(async () =\u003e {\n    mq = await createTestInstance({}, {\n      snapshot: 'vitest', // Shortcut\n    })\n    // await useSnapshot(mq, 'vitest')\n    const result = await startServer(mq)\n    port = result.port\n  })\n\n  afterEach(async () =\u003e {\n    await mq.destroy()\n  })\n\n  it('should fetch GraphQL', async () =\u003e {\n    const response = await fetch(`http://localhost:${port}/graphql`, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify({\n        query: `\n          query {\n            hello\n          }\n        `,\n      }),\n    })\n    const data = await response.json()\n    expect(data).toEqual({\n      data: {\n        hello: 'villa',\n      },\n    })\n  })\n\n  it('should fetch REST', async () =\u003e {\n    // await addResolvers(mq, {\n    //   Query: {\n    //     hello: () =\u003e 'world',\n    //   },\n    // })\n\n    {\n      const response = await fetch(`http://localhost:${port}/rest/my-object`)\n      const data = await response.json()\n      expect(data).toEqual({ data: [] })\n    }\n    await fetch(`http://localhost:${port}/rest/my-object`, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify({\n        id: 'abc',\n        name: 'cat',\n        count: 42,\n      }),\n    })\n    const response = await fetch(`http://localhost:${port}/rest/my-object`)\n    const data = await response.json()\n    expect(data).toEqual({\n      data: [\n        {\n          __typename: 'MyObject',\n          id: 'abc',\n          name: 'cat',\n          count: 42,\n        },\n      ],\n    })\n  })\n})\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakryum%2Fmoquerie","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakryum%2Fmoquerie","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakryum%2Fmoquerie/lists"}