{"id":13998439,"url":"https://github.com/TanStack/bling","last_synced_at":"2025-07-23T06:31:41.247Z","repository":{"id":73873977,"uuid":"604841634","full_name":"TanStack/bling","owner":"TanStack","description":"💍 Framework agnostic transpilation utilities for client/server RPCs, env isolation, islands, module splitting, and more.","archived":false,"fork":false,"pushed_at":"2024-06-14T20:21:05.000Z","size":910,"stargazers_count":1500,"open_issues_count":8,"forks_count":31,"subscribers_count":27,"default_branch":"main","last_synced_at":"2024-11-28T18:01:11.393Z","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/TanStack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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":"tannerlinsley"}},"created_at":"2023-02-21T22:45:24.000Z","updated_at":"2024-11-16T02:39:37.000Z","dependencies_parsed_at":"2024-01-15T19:44:43.956Z","dependency_job_id":"6fd470e4-81ad-4812-bcdf-1f931978c185","html_url":"https://github.com/TanStack/bling","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TanStack%2Fbling","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TanStack%2Fbling/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TanStack%2Fbling/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TanStack%2Fbling/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TanStack","download_url":"https://codeload.github.com/TanStack/bling/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227245175,"owners_count":17753239,"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-08-09T19:01:40.465Z","updated_at":"2024-11-30T00:31:36.120Z","avatar_url":"https://github.com/TanStack.png","language":"TypeScript","readme":"# @TanStack/Bling\n\nFramework agnostic transpilation utilities for client/server RPCs, env isolation, islands, module splitting, and more.\n\n=======\n\n# API\n\n## Macros\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cspan style=\"font-size: 1.5rem; font-weight: bold\"\u003e\u003ccode\u003eserver$\u003c/code\u003e\u003c/span\u003e\u003c/summary\u003e\n\nThe `server$` function is used to create an isomorphic server-side RPC. It takes a function and an optional configuration object and returns a function that can be called on both server (ssr or ssg) and client. The function passed to `server$` will only be executed on the server. On the client, a `fetch` call is made to the server function instead. The results of the function will be exactly the same on both server and client.\n\n**🧠 Important Notes**:\n\n- The server-side function must be an `async` function.\n- The fetch calls made by the client default to using the `POST` method and passing arguments via the request body. To use `GET` requests and search-param payloads instead, the `opts.method` can be set to `GET`. This will automatically configure both the method and the payload serialization to work via search params instead of a request body. You can also alter the actual request (and request body) manually to your liking.\n\n```tsx\nimport { server$ } from '@tanstack/bling'\n\nconst fetchFn = server$(async (payload) =\u003e {\n  // do something\n  return 'result'\n})\n```\n\n### Signature\n\n```tsx\nserver$\u003cT extends (...args: any[]) =\u003e Promise\u003cany\u003e\u003e(fn: T, options: {\n  method?: 'POST' | 'GET' // Defaults to `POST`\n  request?: RequestInit\n}): T\n```\n\n### Arguments\n\n- `fn`\n  - The function to be called from the client-side.\n  - Arguments\n    - `payload`\n      - The payload passed from the client-side.\n    - `ctx`\n      - The context object passed from the client-side.\n      - `request`\n        - The request object passed from the client-side.\n  - Returns the data or response to be sent back to the client-side\n    - `Promise\u003cJSON | Response\u003e`\n  - Can use utilities like `json`, `redirect`, or `eventStream` to return convenient responses.\n- `options`\n  - `method`\n    - The HTTP method to use when calling the server-side function.\n    - Defaults to `POST`\n    - If `GET` is used, the payload will automatically be encoded as query parameters.\n  - `request`\n    - The default request object to be passed to the `fetch` call to the server function.\n    - Can be used to add headers, signals, etc.\n\n### Returns\n\nA function that can be called isomorphically from server or client side code to execute the server-side function.\n\n- ```tsx\n    fn(\n      payload: JSON,\n      options: {\n        method?: 'POST' | 'GET' // Defaults to `POST`\n        request?: RequestInit\n      }\n    ) =\u003e Promise\u003c\n      Awaited\u003cReturnType\u003cT\u003e\u003e extends JsonResponse\u003cinfer R\u003e\n        ? R\n        : ReturnType\u003cT\u003e\n    \u003e\n  ```\n\n  - Arguments\n    - `payload`\n      - The payload to be passed to the server-side function.\n    - `options`\n      - `method`\n        - The HTTP method to use when calling the server-side function.\n        - Defaults to `POST`\n        - If `GET` is used, the payload will automatically be encoded as query parameters.\n      - `request`\n        - The request object to be passed to the `fetch` call to the server function.\n        - Can be used to add headers, signals, etc.\n  - Returns\n    - If a plain Response is returned in the server function, it will be returned here.\n    - If a redirect is returned or thrown in the server function, the redirect will be followed.\n    - All other values will be treated as JSON. For type-safe JSON, use the `json(data, responseInit)` utility\n\n- `fn.fetch`\n\n  - A convenience `fn.fetch` method is also exposed on the function itself to facilitate custom fetch calls. In this case, only the request object is passed as the first argument. Any data you wish to pass should be encoded in the request object.\n\n  ```tsx\n    fn.fetch(\n      request: RequestInit,\n    ) =\u003e Promise\u003c\n      Awaited\u003cReturnType\u003cT\u003e\u003e extends JsonResponse\u003cinfer R\u003e\n        ? R\n        : ReturnType\u003cT\u003e\n    \u003e\n  ```\n\n  - Arguments\n    - `payload`\n      - The payload to be passed to the server-side function.\n    - `options`\n      - `request`\n        - The request object to be passed to the `fetch` call to the server function.\n        - Can be used to add headers, signals, etc.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003esecret$\u003c/code\u003e\u003c/summary\u003e\n\n## `secret$`\n\nThe `secret$` function can be used to scope any expression to the server (secret)-bundle only. This means that the expression will be removed from the client bundle. This is useful for things like server-side only imports, server-side only code or sensitive env variables that should never be available on the client.\n\n```tsx\nimport { secret$ } from '@tanstack/bling'\n\nconst secretMessage = secret$('It is a secret!')')\n```\n\nServer Output:\n\n```tsx\nconst secretMessage = server$('It is a secret!')')\n```\n\nClient Output:\n\n```tsx\nconst secretMessage = undefined\n```\n\n### Signature\n\n```tsx\nsecret$\u003cT\u003e(input: T): T\n```\n\n\u003e 🧠 The return type is the same as the input type. Although the value could technically be `undefined` on the client, it's more useful to retain a non-nullable type in the wild.\n\n### Arguments\n\n- `input`\n  - Any function, expression, or variable.\n\n### Returns\n\n- The variable on the server\n- `undefined` on the client\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003eimport$\u003c/code\u003e\u003c/summary\u003e\n\n## `import$`\n\nThe `import$` function can be used to code-split any expression into it's own module on both server and client at build-time. This is helpful for you to coordinate what code loads when without having to create new files for every part you want want to code-split. It's an async function just like the native dynamic import. It actually compiles down to a dynamic import, but with a unique hash for each import$ instance used in the file.\n\n```tsx\nimport { import$ } from '@tanstack/bling'\n\nconst fn = await import$(async (name: string) =\u003e {\n  return `Hello ${name}`\n})\n```\n\nThis can be used to code-split React/Solid components too:\n\n```tsx\nimport { import$ } from '@tanstack/bling'\nimport { lazy } from 'react'\n\nconst fn = lazy(() =\u003e import$({\n  default: () =\u003e \u003cdiv\u003eHello World!\u003c/div\u003e,\n}))\n```\n\nOutput:\n\n```tsx\nconst fn = await import('/this/file?split=0\u0026ref=fn').then((m) =\u003e m.default)\n```\n\n### Signature\n\n```tsx\nimport$\u003cT extends any\u003e(fn: T) =\u003e Promise\u003cT\u003e\n```\n\n### Arguments\n\n- `value`\n  - The value/expression/function to be code-split.\n\n### Returns\n\n- A code-split version of the original expression.\n\n\u003c/details\u003e\n\n## File conventions\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003eSecret files\u003c/code\u003e\u003c/summary\u003e\n\n## Server-Only Files\n\nThe `[filename].secret.[ext]` pattern can be used to create server-side only files. These files will be removed from the client bundle. This is useful for things like server-side only imports, or server-side only code. It works with any file name and extension so long as `.server$.` is found in the resolved file pathname.\n\nWhen a server-only file is imported on the client, it will be provided the same exports, but stubbed with undefined values. Don't put anything sensitive in the exported variable name! 😜\n\n```tsx\n// secret.server$.ts`\nexport const secret = 'This is top secret!'\nexport const anotherSecret = '🤫 Shhh!'\n```\n\nClient output:\n\n```tsx\nexport const secret = undefined\nexport const anotherSecret = undefined\n```\n\n\u003c/details\u003e\n\n## Proposed APIs\n\nThe following APIs are proposed for future versions of Bling. They are not yet implemented, but are being considered for future releases.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003eworker$\u003c/code\u003e\u003c/summary\u003e\n\n## `worker$`\n\nThe `worker$` function is used to create an isomorphic Web Worker and interact with it. On the server, the function will run in the same process as the server. On the client, the function will be compiled to a Web Worker and will return an interface similar to `server$` to make it easy to call from the client\n\n\u003e 🧠 Similar to `server$`, data sent to and from workers will be serialized. This means that you can pass any JSON-serializable data to the worker, but you cannot pass functions or classes. If you need to use non-serializable assets in your worker, you can import them and use them directly in the worker function, however the instances of those assets will be unique to the worker thread.\n\n```tsx\nimport { worker$ } from '@tanstack/bling'\n\nconst sayHello = worker$(async (name: string) =\u003e {\n  // do something\n  return `Hello ${name}`\n})\n\nconst result = sayHello('World!')\nconsole.log(result) // 'Hello World!'\n```\n\n\u003c/details\u003e\n\u003c!-- Use the force, Luke! --\u003e\n\n  - [`websocket$`](#websocket)\n  - [`lazy$`](#lazy)\n  - [`interactive$`/`island$`](#interactive)\n","funding_links":["https://github.com/sponsors/tannerlinsley"],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTanStack%2Fbling","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTanStack%2Fbling","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTanStack%2Fbling/lists"}