Skip to content

Commit

Permalink
feat(readonly): implement readonly operator
Browse files Browse the repository at this point in the history
  • Loading branch information
chshanovskiy committed Jan 13, 2024
1 parent 0118292 commit d703b71
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ All methods split into categories.

- [combineEvents](./combine-events/readme.md) — Wait for all passed events is triggered.
- [format](./format/readme.md) — Combine stores to a string literal.
- [readonly](./readonly/readme.md) — Create readonly version of store or event.
- [reshape](./reshape/readme.md) — Destructure one store to different stores
- [snapshot](./snapshot/readme.md) — Create store value snapshot.
- [splitMap](./split-map/readme.md) — Split event to different events and map data.
Expand Down
8 changes: 8 additions & 0 deletions src/readonly/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Store, Event } from 'effector';

export function readonly<T extends unknown>(source: Store<T>): Store<T>;
export function readonly<T extends unknown>(source: Event<T>): Event<T>;

export function readonly<T extends unknown>(source: Store<T> | Event<T>) {
return source.map((value) => value, { skipVoid: false });
}
54 changes: 54 additions & 0 deletions src/readonly/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# readonly

:::note since
patronum 2.2.0
:::

```ts
import { readonly } from 'patronum';
// or
import { readonly } from 'patronum/readonly';
```

### Motivation

The method allows to convert writable store and callable event to their readonly versions.
It can be helpful to create more strict public api.

### Formulae

```ts
$result = readonly($store);
```

- `$result` store contains mapped `$store`, which is readonly for consumers.

```ts
result = readonly(event);
```

- `result` event contains mapped `event`, which is not callable by consumers.

### Arguments

- `value: Store<T>|Event<T>` — Any store or event, that required to be readonly

### Returns

- `result: Store<T>|Event<T>`

### Example

```ts
const $store = createStore({});
const $readonlyStore = readonly($store);

console.assert(false === is.targetable($readonlyStore));
```

```ts
const event = createEvent();
const readonlyEvent = readonly(event);

console.assert(false === is.targetable($readonlyStore));
```
16 changes: 16 additions & 0 deletions src/readonly/readonly.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { createEvent, createStore, is } from 'effector';
import { readonly } from './index';

it('should convert store to readonly store', () => {
const $store = createStore({});
const $result = readonly($store);

expect(is.targetable($result)).toBe(false);
});

it('should convert event to readonly event', () => {
const event = createEvent();
const result = readonly(event);

expect(is.targetable(result)).toBe(false);
});
51 changes: 51 additions & 0 deletions test-typings/readonly.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { createDomain, createEffect, createEvent, createStore, Store, Event } from 'effector';
import { expectType } from 'tsd';
import { readonly } from '../dist/readonly';

// Always returns the store
{
const $store = createStore<number>(1);

expectType<Store<number>>(readonly($store));
}

// Always returns the store
{
const $store = createStore<number>(1);
const $mapped = $store.map(store => store)

expectType<Store<number>>(readonly($mapped));
}

// Always returns the event
{
const event = createEvent<void>();

expectType<Event<void>>(readonly(event));
}

// Always returns the event
{
const event = createEvent<void>();
const mapped = event.map(event => event)

expectType<Event<void>>(readonly(mapped));
}

// Should not receive non-store or non-event as argument
{
// @ts-expect-error
readonly(createEffect());

// @ts-expect-error
readonly(createDomain());

// @ts-expect-error
readonly(1);

// @ts-expect-error
readonly(true);

// @ts-expect-error
readonly({});
}

0 comments on commit d703b71

Please sign in to comment.