{"id":19454611,"url":"https://github.com/fauna/fauna-js","last_synced_at":"2025-04-05T06:04:54.890Z","repository":{"id":65850992,"uuid":"546905367","full_name":"fauna/fauna-js","owner":"fauna","description":"Javascript driver for Fauna v10 (current)","archived":false,"fork":false,"pushed_at":"2025-02-10T22:49:48.000Z","size":2154,"stargazers_count":40,"open_issues_count":7,"forks_count":9,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-03-29T05:01:46.448Z","etag":null,"topics":["client","clients","database","driver","drivers","fauna","faunadb","javascript","nosql","nosql-database","serverless","typescript"],"latest_commit_sha":null,"homepage":"https://fauna.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fauna.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":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-06T20:59:32.000Z","updated_at":"2025-03-19T18:21:31.000Z","dependencies_parsed_at":"2024-05-06T19:54:43.257Z","dependency_job_id":"fe35bb1a-c21a-482f-bb58-8468cf490791","html_url":"https://github.com/fauna/fauna-js","commit_stats":null,"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fauna%2Ffauna-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fauna%2Ffauna-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fauna%2Ffauna-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fauna%2Ffauna-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fauna","download_url":"https://codeload.github.com/fauna/fauna-js/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247294538,"owners_count":20915340,"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":["client","clients","database","driver","drivers","fauna","faunadb","javascript","nosql","nosql-database","serverless","typescript"],"created_at":"2024-11-10T17:10:27.464Z","updated_at":"2025-04-05T06:04:54.870Z","avatar_url":"https://github.com/fauna.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Official JavaScript Driver for [Fauna v10](https://fauna.com) (current)\n\n[![npm Version](https://img.shields.io/npm/v/fauna.svg?maxAge=21600)](https://www.npmjs.com/package/fauna)\n[![License](https://img.shields.io/badge/license-MPL_2.0-blue.svg?maxAge=2592000)](https://raw.githubusercontent.com/fauna/fauna-js/main/LICENSE)\n\nThis driver can only be used with FQL v10, and is not compatible with earlier versions of FQL. To query your databases with earlier API versions, see the [faunadb](https://www.npmjs.com/package/faunadb) package.\n\nSee the [Fauna Documentation](https://docs.fauna.com/fauna/current/) for additional information on how to configure and query your databases.\n\n\u003cdetails\u003e\n\u003csummary\u003eTable of Contents\u003c/summary\u003e\n\n- [Official JavaScript Driver for Fauna v10 (current)](#official-javascript-driver-for-fauna-v10-current)\n  - [Supported runtimes](#supported-runtimes)\n  - [API reference](#api-reference)\n  - [Install](#install)\n  - [Usage](#usage)\n    - [Write FQL queries](#write-fql-queries)\n    - [Typescript support](#typescript-support)\n      - [Interfaces as `QueryValue` responses](#interfaces-as-queryvalue-responses)\n    - [Query options](#query-options)\n    - [Query statistics](#query-statistics)\n  - [Pagination](#pagination)\n  - [Client configuration](#client-configuration)\n    - [Environment variables](#environment-variables)\n    - [Retry](#retry)\n      - [Max attempts](#max-attempts)\n      - [Max backoff](#max-backoff)\n    - [Timeouts](#timeouts)\n      - [Query timeout](#query-timeout)\n      - [Client timeout](#client-timeout)\n      - [HTTP/2 session idle timeout](#http2-session-idle-timeout)\n  - [Event feeds](#event-feeds)\n    - [Request an event feed](#request-an-event-feed)\n    - [Iterate on an event feed](#iterate-on-an-event-feed)\n    - [Error handling](#error-handling)\n    - [Event feed options](#event-feed-options)\n  - [Event streams](#event-streams)\n    - [Start a stream](#start-a-stream)\n    - [Iterate on a stream](#iterate-on-a-stream)\n    - [Close a stream](#close-a-stream)\n    - [Stream options](#stream-options)\n  - [Debug logging](#debug-logging)\n  - [Contributing](#contributing)\n    - [Set up the repo](#set-up-the-repo)\n    - [Run tests](#run-tests)\n    - [Asserting types](#asserting-types)\n    - [Lint your code](#lint-your-code)\n  - [License](#license)\n\n\u003c/details\u003e\n\n## Supported runtimes\n\n**Server-side**\n\nNode.js - [Current and active LTS versions](https://nodejs.org/en/about/releases/):\n\n- Current - v22\n- LTS - v20\n- LTS (Maintenance) - v18\n\n**Cloud providers**\n\n- Cloudflare Workers\n- AWS Lambda\n- Netlify\n- Vercel\n\n**Browsers**\n\nStable versions of:\n\n- Chrome 69+\n- Firefox 62+\n- Safari 12.1+\n- Edge 79+\n\n## API reference\n\nAPI reference documentation for the driver is available at\nhttps://fauna.github.io/fauna-js/.\n\n## Install\n\nThe driver is available on [npm](https://www.npmjs.com/package/fauna). You\ncan install it using your preferred package manager. For example:\n\n```shell\nnpm install fauna\n```\n\nBrowsers can import the driver using a CDN link:\n\n```html\n\u003cscript type=\"module\"\u003e\n  import * as fauna from \"https://cdn.jsdelivr.net/npm/fauna@latest/dist/browser/index.js\";\n\u003c/script\u003e\n```\n\n## Usage\n\nBy default, the driver's `Client` instance authenticates with Fauna using an\naccess token in the `FAUNA_SECRET` environment variable. If needed, you can pass\nthe token to the client using the `secret` argument instead.\n\n```javascript\nimport { Client, fql, FaunaError } from \"fauna\";\n// Use `require` for CommonJS:\n// const { Client, fql, FaunaError } = require('fauna');\n\nconst client = new Client();\n// To configure your client:\n// const client = new Client({\n//   secret: YOUR_FAUNA_SECRET,\n// });\n\ntry {\n  // Build a query using the `fql` method\n  const collectionQuery = fql`Collection.create({ name: \"Dogs\" })`;\n  // Run the query\n  const collectionResponse = await client.query(collectionQuery);\n\n  // Declare a var for app data\n  const dog = { name: \"Scout\" };\n\n  // Build a query using the var\n  const documentQuery = fql`\n    Dogs.create(${dog}) {\n      id,\n      ts,\n      name\n    }\n  `;\n\n  // Run the query\n  const response = await client.query(documentQuery);\n  console.log(response);\n} catch (error) {\n  if (error instanceof FaunaError) {\n    console.log(error);\n  }\n} finally {\n  // Clean up any remaining resources\n  client.close();\n}\n```\n\n### Write FQL queries\n\nThe `fql` function is your gateway to building safe, reuseable Fauna queries.\n\nIt allows you compose queries from sub-queries and variables native to your program. Variables passed in are treated as unexecutable values in Fauna's API - preventing security issues like injection attacks.\n\nFor example:\n\n```javascript\nimport { Client, fql } from \"fauna\";\n\nconst client = new Client();\n\n// Variables can be used as arguments in an FQL query\nconst collectionName = \"Pets\";\n\n// Build a reusable sub-query to determine if a collection exists\nconst collectionExists = (name) =\u003e fql`Collection.byName(${name}) != null`;\n\n// Build query that uses the previous var and sub-query\nconst upsertCollectionQuery = fql`\n  if (${collectionExists(collectionName)}) {\n    \"Collection already exists\"\n  } else {\n    Collection.create({ name: ${collectionName} })\n    \"Collection created\"\n  }\n`;\n\n// Run the query\nconst response = await client.query(upsertCollectionQuery);\nconsole.log(response.data);\n\nclient.close();\n```\n\nThis has several advantages:\n\n- You can use `fql` to build a library of subqueries applicable to your domain - and combinable in whatever way you need\n- Injection attacks are not possible if you pass input variables into the interpolated (`` `${interpoloated_argument}` ``) parts of the query.\n- The driver speaks \"pure\" FQL - you can try out some FQL queries on the dashboard's terminal and paste it directly into your app like ``fql`copied from terminal...` `` and the query will work as is.\n\n### Typescript support\n\nWith TypeScript, you can apply a type parameter to your result.\n\n```typescript\nimport { fql, Client, type QuerySuccess } from \"fauna\";\n\nconst client = new Client();\n\ntype User = {\n  name: string;\n  email: string;\n};\n\nconst query = fql`{\n  name: \"Alice\",\n  email: \"alice@site.example\",\n}`;\n\nconst response: QuerySuccess\u003cUser\u003e = await client.query\u003cUser\u003e(query);\nconst userDoc: User = response.data;\n\nconsole.assert(userDoc.name === \"Alice\");\nconsole.assert(userDoc.email === \"alice@site.example\");\n\nclient.close();\n```\n\nAlternatively, you can apply a type parameter directly to your\nfql statements and `Client` methods will infer your return types.\nDue to backwards compatibility, if a type parameter is provided to\n`Client` methods, it will override the inferred type from your\nquery.\n\n```typescript\nconst query = fql\u003cUser\u003e`{\n  name: \"Alice\",\n  email: \"alice@site.example\",\n}`;\n\n// response will be typed as QuerySuccess\u003cUser\u003e\nconst response = await client.query(query);\n\n// userDoc will be automatically inferred as User\nconst userDoc = response.data;\n\nconsole.assert(userDoc.name === \"Alice\");\nconsole.assert(userDoc.email === \"alice@site.example\");\n\nclient.close();\n```\n\n#### Interfaces as `QueryValue` responses\n\nTo use a custom interface as a query response, extend the `QueryValueObject`\ninterface.\n\n```typescript\ninterface User extends QueryValueObject {\n  name: string;\n  email: string;\n}\n\nconst query = fql`{\n  name: \"Alice\",\n  email: \"alice@site.example\",\n}`;\n\nconst response: QuerySuccess\u003cUser\u003e = await client.query\u003cUser\u003e(query);\n```\n\n### Query options\n\nOptions are available to configure queries on each request. These override any\ndefault query options in the [client configuration](#client-configuration).\n\n```typescript\nimport { fql, Client, type QueryOptions } from \"fauna\";\n\nconst client = new Client();\n\nconst options: QueryOptions = {\n  arguments: { name: \"Alice\" },\n  format: \"tagged\",\n  long_type: \"number\",\n  linearized: false,\n  max_contention_retries: 5,\n  query_tags: { name: \"readme_query\" },\n  query_timeout_ms: 60_000,\n  traceparent: \"00-750efa5fb6a131eb2cf4db39f28366cb-000000000000000b-00\",\n  typecheck: true,\n};\n\nconst response = await client.query(fql`\"Hello, #{name}!\"`, options);\nconsole.log(response.data);\n\nclient.close();\n```\n\n### Query statistics\n\nQuery statistics are returned with successful query responses and errors of\nthe `ServiceError` type.\n\n```typescript\nimport {\n  fql,\n  Client,\n  ServiceError,\n  type QueryInfo,\n  type QueryStats,\n  type QuerySuccess,\n} from \"fauna\";\n\nconst client = new Client();\n\ntry {\n  const response: QuerySuccess\u003cstring\u003e = await client.query\u003cstring\u003e(\n    fql`\"Hello world\"`,\n  );\n  const stats: QueryStats | undefined = response.stats;\n  console.log(stats);\n} catch (error: any) {\n  if (error instanceof ServiceError) {\n    const info: QueryInfo = error.queryInfo;\n    const stats: QueryStats | undefined = info.stats;\n  }\n}\n```\n\nExample output:\n\n```javascript\n{\n  compute_ops: 1,\n  read_ops: 0,\n  write_ops: 0,\n  query_time_ms: 15,\n  storage_bytes_read: 0,\n  storage_bytes_write: 0,\n  contention_retries: 0\n}\n```\n\n## Pagination\n\nUse `paginate()` to iterate sets that contain more than one page of results.\n\n`paginate()` accepts the same [query options](#query-options) as\n`query()`.\n\n```typescript\nimport { fql, Client, type SetIterator, type QueryValue } from \"fauna\";\n\nconst client = new Client();\n\n// Adjust `pageSize()` size as needed.\nconst query = fql`\n  Product\n    .byName(\"limes\")\n    .pageSize(60) { description }`;\n\nconst options = {\n  query_timeout_ms: 60_000,\n};\n\nconst pages: SetIterator\u003cQueryValue\u003e = client.paginate(query, options);\n\nfor await (const products of pages) {\n  for (const product of products) {\n    console.log(product);\n  }\n}\n\nclient.close();\n```\n\nUse `flatten()` to get paginated results as a single, flat array:\n\n```typescript\nconst pages: SetIterator\u003cQueryValue\u003e = client.paginate(query, options);\n\nfor await (const product of pages.flatten()) {\n  console.log(product);\n}\n```\n\n## Client configuration\n\nThe driver's `Client` instance comes with reasonable defaults that should be\nused in most cases. You can override these defaults if needed.\n\nIn addition to configuring the client, you can also set default [query\noptions](#query-options).\n\n```typescript\nimport { Client, endpoints, type ClientConfiguration } from \"fauna\";\n\nconst config: ClientConfiguration = {\n  // Configure the client\n  client_timeout_buffer_ms: 5000,\n  endpoint: endpoints.default,\n  fetch_keepalive: false,\n  http2_max_streams: 100,\n  http2_session_idle_ms: 5000,\n  secret: YOUR_FAUNA_SECRET,\n\n  // Set default query options\n  format: \"tagged\",\n  long_type: \"number\",\n  linearized: false,\n  max_attempts: 3,\n  max_backoff: 20,\n  max_contention_retries: 5,\n  query_tags: { name: \"readme_query\" },\n  query_timeout_ms: 60_000,\n  traceparent: \"00-750efa5fb6a131eb2cf4db39f28366cb-000000000000000b-00\",\n  typecheck: true,\n};\n\nconst client = new Client(config);\n```\n\n### Environment variables\n\nThe driver will default to configuring your client with the values of the `FAUNA_SECRET` and `FAUNA_ENDPOINT` environment variable.\n\nFor example, if you set the following environment variables:\n\n```shell\nexport FAUNA_SECRET=YOUR_FAUNA_SECRET\nexport FAUNA_ENDPOINT=https://db.fauna.com/\n```\n\nYou can initalize the client with a default configuration:\n\n```javascript\nconst client = new Client();\n```\n\n### Retry\n\n#### Max attempts\n\nThe maximum number of times a query will be attempted if a retryable exception is thrown (ThrottlingError). Default 3, inclusive of the initial call. The retry strategy implemented is a simple exponential backoff.\n\nTo disable retries, pass max_attempts less than or equal to 1.\n\n#### Max backoff\n\nThe maximum backoff in seconds to be observed between each retry. Default 20 seconds.\n\n### Timeouts\n\nThere are a few different timeout settings that can be configured; each comes with a default setting. We recommend that most applications simply stick to the defaults.\n\n#### Query timeout\n\nThe query timeout is the time, in milliseconds, that Fauna will spend executing your query before aborting with a 503 Timeout error. If a query timeout occurs, the driver will throw an instance of `QueryTimeoutError`.\n\nThe query timeout can be set using the `query_timeout_ms` client configuration option. The default value if you do not provide one is 5000 ms (5 seconds).\n\n```javascript\nconst client = new Client({ query_timeout_ms: 20_000 });\n```\n\nThe query timeout can also be set to a different value for each query using the\n`query_timeout_ms` query option. Doing so overrides the client configuration\nwhen performing this query.\n\n```javascript\nconst response = await client.query(myQuery, { query_timeout_ms: 20_000 });\n```\n\n#### Client timeout\n\nThe client timeout is the time, in milliseconds, that the client will wait for a network response before canceling the request. If a client timeout occurs, the driver will throw an instance of `NetworkError`.\n\nThe client timeout is always the query timeout plus an additional buffer. This ensures that the client always waits for at least as long Fauna could work on your query and account for network latency. The client timeout buffer is configured by setting the `client_timeout_buffer_ms` option. The default value for the buffer if you do not provide on is 5000 ms (5 seconds), therefore the default client timeout is 10000 ms (10 s) when considering the default query timeout.\n\n```javascript\nconst client = new Client({ client_timeout_buffer_ms: 6000 });\n```\n\n#### HTTP/2 session idle timeout\n\nThe HTTP/2 session idle timeout is the time, in milliseconds, that an HTTP/2 session will remain open after there is no more pending communication. Once the session idle time has elapsed the session is considered idle and the session is closed. Subsequent requests will create a new session; the session idle timeout does not result in an error.\n\nConfigure the HTTP/2 session idle timeout using the `http2_session_idle_ms` option. The default value if you do not provide one is 5000 ms (5 seconds).\n\nThis setting only applies to clients using HTTP/2 implementations; for example, the default client for Node.js runtimes.\n\n```javascript\nconst client = new Client({ http2_session_idle_ms: 6000 });\n```\n\n\u003e **Note**\n\u003e Your application process may continue executing after all requests are completed for the duration of the session idle timeout. To prevent this, it is recommended to call `close()` once all requests are complete. It is not recommended to set `http2_session_idle_ms` to small values.\n\n\u003e **Warning**\n\u003e Setting `http2_session_idle_ms` to small values can lead to a race condition where requests cannot be transmitted before the session is closed, yielding `ERR_HTTP2_GOAWAY_SESSION` errors.\n\n## Event feeds\n\nThe driver supports [event feeds](https://docs.fauna.com/fauna/current/learn/cdc/#event-feeds).\n\n### Request an event feed\n\nAn event feed asynchronously polls an [event source](https://docs.fauna.com/fauna/current/learn/cdc/#create-an-event-source) for events.\n\nTo get an event source, append `eventSource()` or `eventsOn()` to a\n[supported Set](https://docs.fauna.com/fauna/current/reference/streaming_reference/#sets).\n\nTo get paginated events, pass the event source to `feed()`:\n\n```javascript\nconst response = await client.query(fql`\n  let set = Product.all()\n\n  {\n    initialPage: set.pageSize(10),\n    eventSource: set.eventSource()\n  }\n`);\nconst { initialPage, eventSource } = response.data;\n\nconst feed = client.feed(eventSource);\n```\n\nIf changes occur between the creation of the event source and the `feed()`\nrequest, the feed replays and emits any related events.\n\nYou can also pass a query that produces an event source directly to `feed()`:\n\n```javascript\nconst query = fql`Product.all().eventsOn(.price, .stock)`;\n\nconst feed = client.feed(query);\n```\n\nIf you pass an event source query to `feed()`, the driver creates the event\nsource and requests the event feed at the same time.\n\n### Iterate on an event feed\n\n`feed()` returns a `FeedClient` instance that can act as an `AsyncIterator`. You can use `for await...of` to iterate through all the pages:\n\n```ts\nconst query = fql`Product.all().eventsOn(.price, .stock)`;\nconst feed = client.feed(query);\n\nfor await (const page of feed) {\n  console.log(\"Page stats\", page.stats);\n\n  for (event in page.events) {\n    switch (event.type) {\n      case \"update\":\n      case \"add\":\n      case \"remove\":\n        console.log(\"Event: \", event);\n        // ...\n        break;\n    }\n  }\n}\n```\n\nAlternatively, use `flatten()` to get paginated results as a single, flat array:\n\n```ts\nconst query = fql`Product.all().eventsOn(.price, .stock)`;\nconst feed = client.feed(query);\n\nfor await (const event of feed.flatten()) {\n  console.log(\"Event: \", event);\n}\n```\n\n### Error handling\n\nExceptions can be raised at two different places:\n\n1. While fetching a page\n1. While iterating a page's events\n\nThis distinction allows for you to ignore errors originating from event processing.\nFor example:\n\n```ts\nconst feed = client.feed(fql`\n  Product.all().map(.details.toUpperCase()).eventSource()\n`);\n\ntry {\n  for await (const page of feed) {\n    // Pages will stop at the first error encountered.\n    // Therefore, its safe to handle an event failures\n    // and then pull more pages.\n    try {\n      for (const event of page.events) {\n        console.log(\"Event: \", event);\n      }\n    } catch (error: unknown) {\n      console.log(\"Feed event error: \", error);\n    }\n  }\n} catch (error: unknown) {\n  console.log(\"Non-retryable error: \", error);\n}\n```\n\n### Event feed options\n\nThe client configuration sets the default options for `feed()`. You can pass a `FeedClientConfiguration` object to override these defaults:\n\n```ts\nconst options: FeedClientConfiguration = {\n  long_type: \"number\",\n  max_attempts: 5,\n  max_backoff: 1000,\n  query_timeout_ms: 5000,\n  client_timeout_buffer_ms: 5000,\n  secret: \"FAUNA_SECRET\",\n  cursor: undefined,\n  start_ts: undefined,\n};\n\nclient.feed(fql`Product.all().eventSource()`, options);\n```\n\nYou can reuse\n[cursors](https://docs.fauna.com/fauna/current/reference/cdc/#get-events-after-a-specific-cursor)\nacross event sources with identical queries in the same database.\n\n## Event streams\n\nThe driver supports [event streams](https://docs.fauna.com/fauna/current/learn/cdc/#event-streaming).\n\n### Start a stream\n\nTo get an event source, append\n[`eventSource()`](https://docs.fauna.com/fauna/current/reference/reference/schema_entities/set/eventsource)\nor\n[`eventsOn()`](https://docs.fauna.com/fauna/current/reference/reference/schema_entities/set/eventson)\nto a set from a [supported\nsource](https://docs.fauna.com/fauna/current/reference/streaming_reference/#sets).\n\nTo start and subscribe to the stream, pass the event source to `stream()`:\n\n```javascript\nconst response = await client.query(fql`\n  let set = Product.all()\n\n  {\n    initialPage: set.pageSize(10),\n    eventSource: set.eventSource()\n  }\n`);\nconst { initialPage, eventSource } = response.data;\n\nclient.stream(eventSource);\n```\n\nYou can also pass a query that produces an event source directly to `stream()`:\n\n```javascript\nconst query = fql`Product.all().eventsOn(.price, .stock)`;\n\nclient.stream(query);\n```\n\n### Iterate on a stream\n\nYou can iterate on the stream using an async loop:\n\n```javascript\ntry {\n  for await (const event of stream) {\n    switch (event.type) {\n      case \"update\":\n      case \"add\":\n      case \"remove\":\n        console.log(\"Event: \", event);\n        // ...\n        break;\n    }\n  }\n} catch (error) {\n  // An error will be handled here if Fauna returns a terminal, \"error\" event, or\n  // if Fauna returns a non-200 response when trying to connect, or\n  // if the max number of retries on network errors is reached.\n  // ... handle fatal error\n}\n```\n\nOr you can use a callback function:\n\n```javascript\nstream.start(\n  function onEvent(event) {\n    switch (event.type) {\n      case \"update\":\n      case \"add\":\n      case \"remove\":\n        console.log(\"Event: \", event);\n        // ...\n        break;\n    }\n  },\n  function onFatalError(error) {\n    // An error will be handled here if Fauna returns a terminal, \"error\" event, or\n    // if Fauna returns a non-200 response when trying to connect, or\n    // if the max number of retries on network errors is reached.\n    // ... handle fatal error\n  },\n);\n```\n\n### Close a stream\n\nUse `close()` to close a stream:\n\n```javascript\nconst stream = await client.stream(fql`Product.all().eventSource()`);\n\nlet count = 0;\nfor await (const event of stream) {\n  console.log(\"Event: \", event);\n  // ...\n  count++;\n\n  // Close the stream after 2 events\n  if (count === 2) {\n    stream.close();\n    break;\n  }\n}\n```\n\n### Stream options\n\nThe [client configuration](#client-configuration) sets default options for the\n`stream()` method.\n\nYou can pass an `StreamClientConfiguration` object to override these defaults:\n\n```javascript\nconst options: StreamClientConfiguration = {\n  long_type: \"number\",\n  max_attempts: 5,\n  max_backoff: 1000,\n  secret: \"YOUR_FAUNA_SECRET\",\n  status_events: true,\n  cursor: null,\n};\n\nclient.stream(fql`Product.all().eventSource()`, options);\n```\n\nFor supported properties, see\n[StreamClientConfiguration](https://fauna.github.io/fauna-js/latest/types/StreamClientConfiguration.html)\nin the API reference.\n\n## Debug logging\n\nTo enable debug logging, set the `FAUNA_DEBUG` environment variable to a\nstring-encoded\n[`LOG_LEVELS`](https://fauna.github.io/fauna-js/latest/variables/LOG_LEVELS.html)\ninteger:\n\n```shell\n# Enable logging for warnings (3) and above:\nexport FAUNA_DEBUG=\"3\"\n```\n\nLogs are output to `console` methods. If `FAUNA_DEBUG` is not set or\nis invalid, logging is disabled.\n\nFor advanced logging, you can pass a custom log handler using the [client\nconfiguration](#client-configuration)'s `logger` property:\n\n```js\nimport { Client, LOG_LEVELS } from \"fauna\";\nimport { CustomLogHandler } from \"./your-logging-module\";\n\n// Create a client with a custom logger.\nconst client = new Client({\n  logger: new CustomLogHandler(LOG_LEVELS.DEBUG),\n});\n```\n\n## Contributing\n\nAny contributions from the community are greatly appreciated!\n\nIf you have a suggestion that would make this better, please fork the repo and create a pull request. You may also simply open an issue. We provide templates, so please complete those to the best of your ability.\n\nDon't forget to give the project a star! Thanks again!\n\n### Set up the repo\n\n1. Clone the repository; e.g. `gh repo clone fauna/fauna-js` if you use the GitHub CLI\n2. Install dependencies via `yarn install`\n\n### Run tests\n\n1. Start a docker desktop or other docker platform.\n2. Run `yarn test`. This will start local fauna containers, verify they're up and run all tests.\n\n### Asserting types\n\nIn cases where you are modifying types and need to test type enforcement, you can use `@ts-expect-error`. Using `@ts-expect-error` will supress any type errors on the following line. Conversely, if there's no error, TypeScript will report its usage as not being neccessary.\n\nTo learn more about `@ts-expect-error`, you can read more about it in the TypeScript [release notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#-ts-expect-error-comments).\n\n### Lint your code\n\nLinting runs automatically on each commit.\n\nIf you wish to run on-demand run `yarn lint`.\n\n## License\n\nDistributed under the MPL 2.0 License. See [LICENSE](./LICENSE) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffauna%2Ffauna-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffauna%2Ffauna-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffauna%2Ffauna-js/lists"}