Skip to content

Commit

Permalink
Setup typedoc
Browse files Browse the repository at this point in the history
  • Loading branch information
mbeckem committed Apr 11, 2024
1 parent 34000ce commit 0db239d
Show file tree
Hide file tree
Showing 15 changed files with 185 additions and 11 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Framework agnostic library for building reactive applications.
> [!WARNING]
> The APIs implemented in this repository are highly experimental and subject to change.
## Reactivity-API

See the [README of the `@conterra/reactivity-core` package](./packages/reactivity-core/README.md).

## Setup

Install [pnpm](https://pnpm.io/), for example by running `npm install -g pnpm`.
Expand Down Expand Up @@ -38,6 +42,22 @@ $ pnpm watch-types
You can try this library together with Vue3 in the `playground` directory.
See [README](./playground/README.md) for more details.

## Render typedoc

Build typedoc output (to `dist/docs`).

```bash
$ pnpm build-docs
```

Then, use any local web server to serve the documentation.
The following example uses [serve](https://www.npmjs.com/package/serve):

```bash
$ pnpm install -g serve # global installation; only necessary once
$ serve dist/docs
```

## Releasing

The release process is semi-automatic at this time.
Expand Down
11 changes: 2 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"scripts": {
"clean": "pnpm -r run --parallel clean",
"build": "pnpm -r run --aggregate-output build",
"build-docs": "typedoc",
"test": "pnpm -r run --aggregate-output test run",
"check-types": "tsc",
"watch-types": "pnpm check-types -w",
Expand All @@ -25,21 +26,13 @@
"prettier": "^3.2.5",
"rimraf": "^5.0.5",
"tsx": "^4.7.2",
"typedoc": "^0.25.13",
"typescript": "~5.4.4",
"vite": "^5.2.8",
"vitest": "^1.4.0"
},
"engines": {
"node": ">= 18",
"pnpm": "^8"
},
"pnpm": {
"packageExtensions": {
"@vue/test-utils@^2": {
"peerDependencies": {
"vue": "^3"
}
}
}
}
}
5 changes: 5 additions & 0 deletions packages/reactivity-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,9 @@ map.set("foo", "bar"); // effect prints "bar"

## API

This section gives an overview over the available APIs.
For more details, consult the comments inside the type declarations or the built TypeDoc documentation.

### Primitives

### Subscribing to changes
Expand All @@ -357,4 +360,6 @@ map.set("foo", "bar"); // effect prints "bar"

### Effects triggering "too often"

### Sync vs async effect / watch

### Writing nonreactive code
8 changes: 8 additions & 0 deletions packages/reactivity-core/Reactive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export type AddWritableBrand<T> = AddBrand<T> & { [IS_WRITABLE_REACTIVE]: true }
*
* When a reactive value changes, all users of that value (computed reactive values, effects, watchers)
* are notified automatically.
*
* @group Primitives
*/
export interface Reactive<T> {
// Compile time symbol to identify reactive objects.
Expand Down Expand Up @@ -45,6 +47,8 @@ export interface Reactive<T> {
*
* The value stored in this object can be changed through assignment,
* and all its users will be notified automatically.
*
* @group Primitives
*/
export interface WritableReactive<T> extends Reactive<T> {
// Compile time symbol to identify writable objects.
Expand All @@ -62,6 +66,8 @@ export interface WritableReactive<T> extends Reactive<T> {
* Holds a value from an external source.
*
* Instances of this type are used to integrate "foreign" state into the reactivity system.
*
* @group Primitives
*/
export interface ExternalReactive<T> extends Reactive<T> {
/**
Expand All @@ -78,6 +84,8 @@ export interface ExternalReactive<T> extends Reactive<T> {
/**
* A handle returned by various functions to dispose of a resource,
* such as a watcher or an effect.
*
* @group Watching
*/
export interface CleanupHandle {
/**
Expand Down
20 changes: 20 additions & 0 deletions packages/reactivity-core/ReactiveImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ import {

/**
* A function that should return `true` if `a` and `b` are considered equal, `false` otherwise.
*
* @group Primitives
*/
export type EqualsFunc<T> = (a: T, b: T) => boolean;

/**
* Options that can be passed when creating a new reactive value.
*
* @group Primitives
*/
export interface ReactiveOptions<T> {
/**
Expand All @@ -43,6 +47,8 @@ export interface ReactiveOptions<T> {
* console.log(foo.value); // undefined
* foo.value = 123; // updates the current value
* ```
*
* @group Primitives
*/
export function reactive<T>(): WritableReactive<T | undefined>;

Expand All @@ -56,6 +62,8 @@ export function reactive<T>(): WritableReactive<T | undefined>;
* console.log(foo.value); // 123
* foo.value = 456; // updates the current value
* ```
*
* @group Primitives
*/
export function reactive<T>(initialValue: T, options?: ReactiveOptions<T>): WritableReactive<T>;
export function reactive<T>(
Expand Down Expand Up @@ -86,6 +94,8 @@ export function reactive<T>(
* foo.value = 2;
* console.log(doubleFoo.value); // 4
* ```
*
* @group Primitives
*/
export function computed<T>(compute: () => T, options?: ReactiveOptions<T>): Reactive<T> {
const impl = new ComputedReactiveImpl(compute, options?.equal);
Expand Down Expand Up @@ -121,6 +131,8 @@ export function computed<T>(compute: () => T, options?: ReactiveOptions<T>): Rea
*
* // later: unsubscribe from signal
* ```
*
* @group Primitives
*/
export function external<T>(compute: () => T, options?: ReactiveOptions<T>): ExternalReactive<T> {
/*
Expand Down Expand Up @@ -178,6 +190,8 @@ export function external<T>(compute: () => T, options?: ReactiveOptions<T>): Ext
* });
* // now the effect runs once
* ```
*
* @group Primitives
*/
export function batch<T>(callback: () => T): T {
return rawBatch(callback);
Expand All @@ -190,6 +204,8 @@ export function batch<T>(callback: () => T): T {
* even if they occur inside a computed object or in an effect.
*
* `untracked` returns the value of `callback()`.
*
* @group Primitives
*/
export function untracked<T>(callback: () => T): T {
return rawUntracked(callback);
Expand All @@ -200,6 +216,8 @@ export function untracked<T>(callback: () => T): T {
* if it is not reactive.
*
* The access to `.value` is tracked.
*
* @group Primitives
*/
export function getValue<T>(maybeReactive: Reactive<T> | T) {
if (!isReactive(maybeReactive)) {
Expand All @@ -213,6 +231,8 @@ export function getValue<T>(maybeReactive: Reactive<T> | T) {
* if it is not reactive.
*
* The access to `.value` is _not_ tracked.
*
* @group Primitives
*/
export function peekValue<T>(maybeReactive: Reactive<T> | T) {
if (!isReactive(maybeReactive)) {
Expand Down
4 changes: 4 additions & 0 deletions packages/reactivity-core/async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import { EffectFunc, syncEffectOnce, syncEffect, WatchOptions, syncWatch } from
* > This is done to avoid redundant executions as a result of many fine-grained changes.
* >
* > If you need more control, take a look at {@link syncEffect}.
*
* @group Watching
*/
export function effect(callback: EffectFunc): CleanupHandle {
let currentSyncEffect: CleanupHandle | undefined;
Expand Down Expand Up @@ -133,6 +135,8 @@ export function effect(callback: EffectFunc): CleanupHandle {
* > This is done to avoid redundant executions as a result of many fine-grained changes.
* >
* > If you need more control, take a look at {@link syncWatch}.
*
* @group Watching
*/
export function watch<const Values extends readonly unknown[]>(
selector: () => Values,
Expand Down
6 changes: 6 additions & 0 deletions packages/reactivity-core/collections/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { reactive } from "../ReactiveImpl";
* Reactive array interface without modifying methods.
*
* See also {@link ReactiveArray}.
*
* @group Collections
*/
export interface ReadonlyReactiveArray<T> extends Iterable<T> {
/**
Expand Down Expand Up @@ -267,6 +269,8 @@ export interface ReadonlyReactiveArray<T> extends Iterable<T> {
* Not all builtin array methods are implemented right now, but most of them are.
*
* Reads and writes to this array are reactive.
*
* @group Collections
*/
export interface ReactiveArray<T> extends ReadonlyReactiveArray<T> {
/**
Expand Down Expand Up @@ -331,6 +335,8 @@ export interface ReactiveArray<T> extends ReadonlyReactiveArray<T> {
* // With initial content
* const array2 = reactiveArray<number>([1, 2, 3]);
* ```
*
* @group Collections
*/
export function reactiveArray<T>(items?: Iterable<T>): ReactiveArray<T> {
return new ReactiveArrayImpl(items);
Expand Down
6 changes: 6 additions & 0 deletions packages/reactivity-core/collections/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { reactive } from "../ReactiveImpl";
* This map interface is designed ot be very similar to (but not exactly the same as) the standard JavaScript `Map`.
*
* Reads from and writes to this map are reactive.
*
* @group Collections
*/
export interface ReactiveMap<K, V> extends Iterable<[key: K, value: V]> {
/**
Expand Down Expand Up @@ -65,6 +67,8 @@ export interface ReactiveMap<K, V> extends Iterable<[key: K, value: V]> {
* Reactive map interface without modifying methods.
*
* See also {@link ReactiveMap}.
*
* @group Collections
*/
export type ReadonlyReactiveMap<K, V> = Omit<ReactiveMap<K, V>, "set" | "delete" | "clear">;

Expand All @@ -80,6 +84,8 @@ export type ReadonlyReactiveMap<K, V> = Omit<ReactiveMap<K, V>, "set" | "delete"
* // With initial content
* const map2 = reactiveMap<string, number>([["foo", 1], ["bar", 2]]);
* ```
*
* @group Collections
*/
export function reactiveMap<K, V>(initial?: Iterable<[K, V]> | undefined): ReactiveMap<K, V> {
return new ReactiveMapImpl(initial);
Expand Down
6 changes: 6 additions & 0 deletions packages/reactivity-core/collections/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { ReactiveMap, reactiveMap } from "./map";
* This set interface is designed ot be very similar to (but not exactly the same as) the standard JavaScript `Set`.
*
* Reads from and writes to this set are reactive.
*
* @group Collections
*/
export interface ReactiveSet<V> extends Iterable<V> {
/**
Expand Down Expand Up @@ -56,6 +58,8 @@ export interface ReactiveSet<V> extends Iterable<V> {
* Reactive set interface without modifying methods.
*
* See also {@link ReactiveSet}.
*
* @group Collections
*/
export type ReadonlyReactiveSet<K> = Omit<ReactiveSet<K>, "set" | "delete" | "clear">;

Expand All @@ -71,6 +75,8 @@ export type ReadonlyReactiveSet<K> = Omit<ReactiveSet<K>, "set" | "delete" | "cl
* // With initial content
* const set2 = reactiveSet<string>(["foo", "bar"]);
* ```
*
* @group Collections
*/
export function reactiveSet<V>(initial?: Iterable<V> | undefined): ReactiveSet<V> {
return new ReactiveSetImpl<V>(initial);
Expand Down
18 changes: 18 additions & 0 deletions packages/reactivity-core/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
/**
* A framework agnostic library for building reactive applications.
*
* @module
*
* @groupDescription Primitives
*
* Primitive building blocks for reactive code.
*
* @groupDescription Watching
*
* Utilities to run code when reactive values change.
*
* @groupDescription Collections
*
* Reactive collections to simplify working with complex data structures.
*/

export {
type ExternalReactive,
type Reactive,
Expand Down
12 changes: 12 additions & 0 deletions packages/reactivity-core/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { CleanupHandle } from "./Reactive";
*
* This function will be invoked before the effect is triggered again,
* or when the effect is disposed.
*
* @group Watching
*/
export type EffectCleanupFn = () => void;

Expand All @@ -19,6 +21,8 @@ export type EffectCleanupFn = () => void;
*
* Instructions in this function are tracked: when any of its reactive
* dependencies change, the effect will be triggered again.
*
* @group Watching
*/
export type EffectFunc = (() => void) | (() => EffectCleanupFn);

Expand Down Expand Up @@ -54,6 +58,8 @@ export type EffectFunc = (() => void) | (() => EffectCleanupFn);
* // later:
* handle.destroy();
* ```
*
* @group Watching
*/
export function syncEffect(callback: EffectFunc): CleanupHandle {
const destroy = rawEffect(callback);
Expand All @@ -69,6 +75,8 @@ export function syncEffect(callback: EffectFunc): CleanupHandle {
* Typically, `onInvalidate` will be very cheap (e.g. schedule a new render).
*
* Note that `onInvalidate` will never be invoked more than once.
*
* @group Watching
*/
export function syncEffectOnce(callback: EffectFunc, onInvalidate: () => void): CleanupHandle {
let execution = 0;
Expand All @@ -91,6 +99,8 @@ export function syncEffectOnce(callback: EffectFunc, onInvalidate: () => void):

/**
* Options that can be passed to {@link syncWatch}.
*
* @group Watching
*/
export interface WatchOptions {
/**
Expand Down Expand Up @@ -137,6 +147,8 @@ export interface WatchOptions {
* ```
*
* > NOTE: You must *not* modify the array that gets passed into `callback`.
*
* @group Watching
*/
export function syncWatch<const Values extends readonly unknown[]>(
selector: () => Values,
Expand Down
5 changes: 5 additions & 0 deletions packages/reactivity-core/typedoc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
// project-root is a dev dependency (link to the project root)
"extends": ["project-root/typedoc.base.json"],
"entryPoints": ["./index.ts"]
}
Loading

0 comments on commit 0db239d

Please sign in to comment.