{"id":20181866,"url":"https://github.com/nichoth/jazz-signals-v1","last_synced_at":"2025-06-30T03:36:55.143Z","repository":{"id":191997527,"uuid":"684881137","full_name":"nichoth/jazz-signals-v1","owner":"nichoth","description":"Use Jazz with preact signals","archived":false,"fork":false,"pushed_at":"2023-09-28T19:44:49.000Z","size":254,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-13T17:24:21.521Z","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":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nichoth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-08-30T03:31:09.000Z","updated_at":"2023-10-17T22:55:04.000Z","dependencies_parsed_at":"2023-09-01T23:35:07.687Z","dependency_job_id":"3d0b05fe-de6f-4411-b884-1be63a6da901","html_url":"https://github.com/nichoth/jazz-signals-v1","commit_stats":null,"previous_names":["nichoth/jazz-signals"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichoth%2Fjazz-signals-v1","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichoth%2Fjazz-signals-v1/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichoth%2Fjazz-signals-v1/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichoth%2Fjazz-signals-v1/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nichoth","download_url":"https://codeload.github.com/nichoth/jazz-signals-v1/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241616692,"owners_count":19991543,"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-11-14T02:36:57.093Z","updated_at":"2025-03-03T06:12:38.296Z","avatar_url":"https://github.com/nichoth.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jazz signals\nA library to help use [Jazz](https://jazz.tools/) with [preact signals](https://preactjs.com/blog/introducing-signals/).\n\n## install\n```bash\nnpm i -S @nichoth/jazz-signals\n```\n\n## develop\nStart a local vite server\n\n```bash\nnpm start\n```\n\n## API\n\n### localAuth\nImport a function `localAuth` that helps with authentication, and has a property `createState` that returns observable state. This will create and return a signal of a `localNode`, the object used for persistence/`telepathicState`.\n\n```js\nimport { localAuth } from '@nichoth/jazz-signals'\n```\n\n### localAuth.createState\nCreate a state object that includes signals.\n\n```ts\nexport interface LocalAuthState {\n    authStatus:Signal\u003cAuthStatus\u003e;\n    localNode:Signal\u003cLocalNode|null\u003e;\n    logoutCount:Signal\u003cnumber\u003e;\n    syncAddress?:string;\n}\n\nlocalAuth.createState = function ():LocalAuthState\n```\n\nThe returned state object should be passed into the `localAuth` function. See an example [in the example app](https://github.com/nichoth/jazz-signals/blob/main/example/todo-app.tsx#L27).\n\nThe signals returned are plain signals; you [would want to wrap them in a call to `useMemo`](https://preactjs.com/guide/v10/signals/#local-state-with-signals) if you use them in a view component.\n\n```ts\nfunction localAuth (\n    appName:string,\n    appHostname:string|undefined,\n    opts:LocalAuthState\n):() =\u003e void\n```\n\nThis will create a new [BrowserLocalAuth](https://github.com/gardencmp/jazz/tree/fe1092ccf639d5cdb5013056d1184a415af826d0/packages/jazz-browser-auth-local), and mutate the signals passed in as `opts:LocalAuthState`. The return value is a function that will unsubscribe from `BrowserLocalAuth`. See [the example](https://github.com/nichoth/jazz-signals/blob/main/example/todo-app.tsx#L76) for a demonstration of how the unsubscribe function can be used.\n\nTo check if you are logged in, look for the `authStatus.value.logout` property. If `.logout` exists, then you are logged in. Call `authStatus.value.signUp` or `authStatus.value.signIn` to handle creating an account and logging in, respectively. See [an example of handling auth](https://github.com/nichoth/jazz-signals/blob/main/example/state.ts#L130).\n\n\n### telepathicSignal \n```ts\nfunction telepathicSignal\u003cT extends CoValueImpl\u003e ({\n    id,\n    localNode\n}:{\n    id?:CoID\u003cT\u003e,\n    localNode:Signal\u003cLocalNode|null\u003e\n}):Signal\u003c[ T|null, (()=\u003evoid)|null ]\u003e {\n```\n\n-------\n\n## example\n\n### localAuth\nAn example of an application that consumes this package is in the [example directory](https://github.com/nichoth/jazz-signals/tree/main/example).\n\nCreate a localNode by mutating the signals that are passed in. Signals are created by `localNode.createState`.\n\nYou should create a state object first with `localAuth.createState`, then pass the state to `localAuth`.\n\n```js\nimport { localAuth } from '@nichoth/jazz-signals'\nimport { useEffect, useMemo } from 'preact/hooks'\n\nfunction MyComponent ({ appHostName, syncAddress, appName }) {\n    const state = useMemo(() =\u003e localAuth.createState(), [])\n    const { localNode } = state  // \u003c-- a signal for our localNode\n\n    /**\n     * Handle auth, create a node\n     */\n    useEffect(() =\u003e {\n        let unlisten:()=\u003evoid = () =\u003e null\n\n        localAuth(appName, appHostName, { ...state }).then(_unlisten =\u003e {\n            unlisten = _unlisten\n        })\n\n        return unlisten\n    }, [appName, appHostName, syncAddress, logoutCount.value])\n}\n```\n\n### telepathicSignal\nCreate a new signal that is subscribed to any changes from the `cojson`\nobject referenced by the given `id`.\n\n```js\nimport { telepathicSignal } from '@nichoth/jazz-signals'\n\nconst mySignal = telepathicSignal({\n    id: 'co_zPLDBXZD5UuZtYGzpqAvgAAHhs4',\n    localNode\n})\n```\n\n```jsx\nimport { telepathicSignal } from '@nichoth/jazz-signals'\nimport { useMemo } from 'preact/hooks'\n\nfunction Component () {\n    const projectSignal = useMemo(() =\u003e {\n        return telepathicSignal({\n            // get the `id` from the URL or something\n            id: 'co_zPLDBXZD5UuZtYGzpqAvgAAHhs4',\n            localNode  // \u003c-- here we consume the localNode we created earlier\n        })\n    }, [params.id, localNode.value])\n\n    const [project] = projectSignal.value\n\n    // get tasks (the list of things to do)\n    // this is where we subscribe to task changes\n    const tasksSignal = useMemo(() =\u003e {\n        if (!project) return signal([])\n        // we depend on the 'tasks' key existing.\n        const tasksId = project.get('tasks')\n\n        return telepathicSignal({ id: tasksId, localNode })\n    }, [project, localNode.value])\n\n    const [tasks] = tasksSignal.value\n\n    return (\u003cdiv\u003e\n        \u003ch2\u003e{project.get('title')}\u003c/h2\u003e\n\n        \u003cul className=\"todo-list\"\u003e\n            {tasks?.map((taskId: CoID\u003cTask\u003e) =\u003e {\n                // subscribe to each TODO list item\n                const [task] = useMemo(\n                    () =\u003e telepathicSignal\u003cTask\u003e({ id: taskId, localNode }),\n                    [taskId, localNode.value]\n                ).value\n\n                // The view will re-render when the task updates.\n                // This is magically in sync with multiple devices.\n                // You can create an invitation for a second device, and changes\n                // will automatically be visible in both places.\n                return (\u003cli key={taskId}\u003e\n                    {task?.get('done') ?\n                        (\u003cs\u003e{task.get('text')}\u003c/s\u003e) :\n                        (\u003cspan\u003e{task.get('text')}\u003c/span\u003e)\n                    }\n                \u003c/li\u003e)\n            })}\n        \u003c/ul\u003e\n    \u003c/div\u003e)\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnichoth%2Fjazz-signals-v1","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnichoth%2Fjazz-signals-v1","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnichoth%2Fjazz-signals-v1/lists"}