diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d89de31..bb8c23d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,6 +12,7 @@ jobs: name: Release permissions: contents: write + id-token: write runs-on: ubuntu-latest steps: - name: Checkout Repo @@ -27,7 +28,7 @@ jobs: with: node-version: 20 cache: 'pnpm' - registry-url: "https://registry.npmjs.org" + registry-url: 'https://registry.npmjs.org' - name: Install Dependencies run: pnpm install @@ -44,9 +45,12 @@ jobs: id: changesets uses: changesets/action@v1 with: - publish: pnpm publish-signal + publish: pnpm publish env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} TURBO_TELEMETRY_DISABLED: 1 + + - name: Publish to JSR + run: pnpm publish:jsr diff --git a/README.md b/README.md index 8f714dd..ba6ba4d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ [![npm](https://img.shields.io/npm/v/@kaiverse/signal)](https://www.npmjs.com/package/@kaiverse/signal) +[![JSR](https://jsr.io/badges/@kaiverse/signal)](https://jsr.io/@kaiverse/signal) [![.github/workflows/ci.yml](https://github.com/kaisergeX/signal-proxy/actions/workflows/ci.yml/badge.svg)](https://github.com/kaisergeX/signal-proxy/actions/workflows/ci.yml)
@@ -9,113 +10,9 @@ [JS Signals proposal](https://github.com/tc39/proposal-signals) is currently in Stage 1. This package draws strong inspiration from [KnockoutJS](https://github.com/knockout/knockout)'s concepts and [SolidJS](https://github.com/solidjs)'s Signal, enabling us to use Signals in vanilla JavaScript. -## Installation +## Docs -Via `npmjs` - -``` -npm i @kaiverse/signal -``` - -or - -``` -pnpm add @kaiverse/signal -``` - -Via `jsr` - -
- (Not available yet) - -``` -deno add @kaiverse/signal -``` -or -``` -npx jsr add @kaiverse/signal -``` -or -``` -pnpm dlx jsr add @kaiverse/signal -``` -

- -Via `unpkg` CDN: - -``` -unpkg.com/@kaiverse/signal -``` - -## Compatibility - -Signal is a [**Proxy**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Proxy) object at its core, please check [compatibility section](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Proxy#browser_compatibility). - -## Example - -[Playground source code](packages/signal/src/playground/index.ts) - -### Use Signal Proxy - -````js -/** - * ```html - *

- * - * ``` - */ - -import {signalProxy} from '@kaiverse/signal'; - -const resultElement = document.getElementById('fetch-result'); - -const userSignal = signalProxy({userId: 123, reqCount: 0}, async (key, newValue) => { - // Do something when any userSignal's prop value changes - console.log(`[userSignal updated] key: ${key}, value: ${newValue}`); - - if (key === 'userId') { - // Do something on `userId` changes only - const userId = newValue; - const response = await fetch(`${basePath}/user/${userId}`); - const userData = await response.json(); - const totalReqCount = userSignal.reqCount + 1; - userSignal.reqCount = totalReqCount; - - if (resultElement) - resultElement.innerHTML = `Name: ${userData.name}
Total requests: ${totalReqCount}`; - } -}); - -function fetchNextUser() { - userSignal.userId++; -} -```` - -### Signal utilities examples - -```js -import {createComputed, createEffect, createSignal} from '@kaiverse/signal'; - -const [count, setCount] = createSignal(0); - -setInterval(() => { - setCount((c) => c + 1); // or setCount(count() + 1) -}, 1000); - -createEffect(() => { - console.log('count =', count()); -}); - -const doubled = createComputed(() => count() * 2); - -createEffect(() => { - console.log('[computed] doubled =', doubled()); -}); -``` - -## Framework ports? - -- [Experimental] [React signal hooks](apps/playground/src/hooks/react-signal.ts) implementation ([React playground source code](apps/playground/src/routes/signal/route.lazy.tsx)). **DO NOT** use in production.
Those hooks work, but its lack of testing and seems that the usage of memory is inefficient. An alternative approach may be better. Please feel free to open PRs. Your contributions are welcomed and appreciated. +[Documentation page](packages/signal/README.md) ## Run this monorepo locally diff --git a/package.json b/package.json index 9b1c57d..fd70e26 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "lint": "turbo lint", "format": "prettier --write \"**/*.{ts,tsx,md}\"", "clean": "turbo run clean && rm -rf node_modules", - "publish-signal": "turbo run build lint --filter=./packages/signal && pnpm publish --filter './packages/signal' --access public && changeset tag" + "publish": "turbo run build lint --filter=./packages/signal && pnpm publish --filter './packages/signal' --access public && changeset tag", + "publish:jsr": "cd ./packages/signal && pnpm dlx jsr publish" }, "type": "module", "devDependencies": { @@ -29,4 +30,4 @@ "node": ">=18", "pnpm": ">=9" } -} +} \ No newline at end of file diff --git a/packages/signal/README.md b/packages/signal/README.md index 1194aa5..2ea7032 100644 --- a/packages/signal/README.md +++ b/packages/signal/README.md @@ -10,7 +10,7 @@ ## Installation -Via `npmjs` +### Via `npmjs` ``` npm i @kaiverse/signal @@ -22,25 +22,25 @@ or pnpm add @kaiverse/signal ``` -Via `jsr` +### Via `jsr` -
- (Not available yet) - ``` deno add @kaiverse/signal ``` + or + ``` npx jsr add @kaiverse/signal ``` + or + ``` pnpm dlx jsr add @kaiverse/signal ``` -

-Via `unpkg` CDN: +### Via `unpkg` CDN: ``` unpkg.com/@kaiverse/signal @@ -114,4 +114,6 @@ createEffect(() => { ## Framework ports? -- [Experimental] [React signal hooks](../../apps/playground/src/hooks/react-signal.ts) implementation ([React playground source code](../../apps/playground/src/routes/signal/route.lazy.tsx)). **DO NOT** use in production.
Those hooks work, but its lack of testing and seems that the usage of memory is inefficient. An alternative approach may be better. Please feel free to open PRs. Your contributions are welcomed and appreciated. +### React + +[Experimental] [React signal hooks](../../apps/playground/src/hooks/react-signal.ts) implementation ([React playground source code](../../apps/playground/src/routes/signal/route.lazy.tsx)). **DO NOT** use in production.
Those hooks work, but its lack of testing and seems that the usage of memory is inefficient. An alternative approach may be better. Please feel free to open PRs. Your contributions are welcomed and appreciated. diff --git a/packages/signal/jsr.json b/packages/signal/jsr.json index 23bd68a..9c829df 100644 --- a/packages/signal/jsr.json +++ b/packages/signal/jsr.json @@ -1,5 +1,13 @@ { "name": "@kaiverse/signal", "version": "0.2.1", - "exports": "./src/index.ts" + "exports": "./src/index.ts", + "publish": { + "exclude": [ + "vite.config.ts", + "tsconfig.json", + "index.html", + "./src/vite-env.d.ts" + ] + } } \ No newline at end of file diff --git a/packages/signal/src/core.ts b/packages/signal/src/core.ts index 9628302..4477b3b 100644 --- a/packages/signal/src/core.ts +++ b/packages/signal/src/core.ts @@ -1,7 +1,8 @@ import type {ObjectAny, SignalCompareEqual, SignalUpdateCallback} from './types'; +/** Create a Signal Proxy. It track a `initialValue` object that changes over time. */ export function signalProxy( - target: T, + initialValue: T, callback: SignalUpdateCallback, equals: SignalCompareEqual = Object.is, ): T { @@ -20,5 +21,5 @@ export function signalProxy( }, }; - return new Proxy(target, handler); + return new Proxy(initialValue, handler); } diff --git a/packages/signal/src/types.ts b/packages/signal/src/types.ts index 53c1c25..a736dbf 100644 --- a/packages/signal/src/types.ts +++ b/packages/signal/src/types.ts @@ -18,7 +18,10 @@ export type SignalSetter = { ): undefined extends T ? undefined : U; (value: T | SignalSetterCb): T; }; + +/** Signals value getter. */ export type Signal = () => T; +/** Signal options */ export type SignalOptions = { /** * Customize Signal comparison @@ -31,7 +34,9 @@ export type SignalOptions = { /** Runs whenever Signal value changes */ onChange?: (newValue: T) => void; }; +/** Return type of a Signal */ export type SignalFactoryReturnType = Readonly<[get: Signal, set: SignalSetter]>; +/** An Effect that runs whenever its dependencies change. */ export type SignalEffect = () => void; export type EffectTracking = {execute: SignalEffect; deps: Set>}; export type CleanupEffectFn = () => void;