Skip to content

Commit

Permalink
Remove the forge() method, use memo() instead (#4)
Browse files Browse the repository at this point in the history
Signed-off-by: Matteo Collina <[email protected]>
  • Loading branch information
mcollina authored May 21, 2024
1 parent 81f5308 commit bd7a4de
Show file tree
Hide file tree
Showing 11 changed files with 49 additions and 309 deletions.
44 changes: 5 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,12 @@ npm i asyncforge
## Usage

```js
import { start, forge, memo } from 'asyncforge'

const a = forge((config) => {
return {
value: config.foo
}
})
import { memo } from 'asyncforge'

const a = memo()
const b = memo()

start({ foo: 'bar' })
a.set(42)
b.set(123)

// simulate an event loop turn
Expand All @@ -41,7 +36,7 @@ setImmediate(() => {
})
})

start({ foo: 'baz' })
a.set(43)
b.set(321)

// simulate an event loop turn
Expand All @@ -50,43 +45,14 @@ setImmediate(() => {
console.log('a', a())
console.log('b', b())
})

const c = memo("myKeyC");
const d = memo("myKeyD");

setAll({
[c.key]: 42,
[d.key]: 24,
});

console.log(c(), d()); // 42 24
```

## TypeScript

You can call the `asyncforge` functions in a type-safe way:

```ts
// You can define the `AsyncForgeConfig` interface so that `start` and `forge` can use it (TS module augmentation)
declare module "asyncforge" {
interface AsyncForgeConfig {
foo: string;
baz: number;
}
}

// This is correct
start({ foo: "bar", baz: 42 })

// TypeScript will complain, since it's not following the definition of AsyncForgeConfig
start({ wrong: true })

// Valid
forge(({ baz: data, foo: value }) => ({ data, value }));

// Invalid
forge(({ invalid }) => ({ invalid }));

import { start, memo, setAll } from "asyncforge";
const memoNum = memo<number>();

// This is okay for TypeScript, since you're passing a number
Expand Down
12 changes: 1 addition & 11 deletions asyncforge.d.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
declare namespace asyncforge {
interface AsyncForgeConfig {}

type ForgeCallback<T> = {
(config: AsyncForgeConfig): T;
name?: string;
};

export function start(config: AsyncForgeConfig): void;
export function forge<T extends unknown>(
fn: ForgeCallback<T>
): () => ReturnType<ForgeCallback<T>>;
export function start(): void;
export function memo<T extends unknown>(
name?: string
): {
Expand Down
24 changes: 2 additions & 22 deletions asyncforge.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,11 @@ const { AsyncLocalStorage } = require('node:async_hooks')

const asyncLocalStorage = new AsyncLocalStorage()

function start (config) {
function start () {
const store = Object.create(null)
store.config = config
asyncLocalStorage.enterWith(store)
}

let forgeCounter = 0
function forge (fn) {
const sym = Symbol('forge.' + (fn.name || forgeCounter++))
return function () {
let store = asyncLocalStorage.getStore()
if (!store) {
store = Object.create(null)
asyncLocalStorage.enterWith(store)
}
if (store[sym]) {
return store[sym]
}
const res = fn(store.config)
store[sym] = res
return res
}
}

let memoCounter = 0
function memo (name) {
name = name || 'memo' + memoCounter++
Expand Down Expand Up @@ -65,7 +46,6 @@ function setAll (memos) {
asyncLocalStorage.enterWith(store)
}

module.exports.start = start
module.exports.forge = forge
module.exports.memo = memo
module.exports.start = start
module.exports.setAll = setAll
34 changes: 2 additions & 32 deletions asyncforge.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,7 @@
import { expectError, expectType } from "tsd";
import { start, forge, memo, setAll } from ".";
import { start, memo, setAll } from ".";

declare module "." {
interface AsyncForgeConfig {
foo: string;
baz: number;
}
}

// start
expectType<void>(start({ foo: "bar", baz: 42 }));
expectType<void>(start({ baz: 24, foo: "xyz" }));
expectError<void>(start({}));
expectError<void>(start({ foo: false, baz: 42 }));

// forge
const forgeObject = forge(() => ({ something: "else" }));
expectType<{ something: string }>(forgeObject());
expectError<{ something: boolean }>(forgeObject());

const forgeString = forge(() => "");
expectType<string>(forgeString());
expectError<boolean>(forgeString());

const remapForge = forge(({ baz: data, foo: value }) => ({ data, value }));
expectType<{ data: number; value: string }>(remapForge());
expectType<() => void>(forge((config) => console.log(config.baz)));
expectError<() => void>(forge((config) => config.invalid));

const getFooString = forge((config) => {
return config.baz + config.foo;
});
expectType<string>(getFooString());
expectType<() => void>(start);

// memo
const memoNum = memo<number>();
Expand Down
13 changes: 4 additions & 9 deletions example.mjs
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import { start, forge, memo } from './asyncforge.js'

const a = forge((config) => {
return {
value: config.foo
}
})
import { memo } from './asyncforge.js'

const a = memo()
const b = memo()

start({ foo: 'bar' })
a.set(42)
b.set(123)

// simulate an event loop turn
Expand All @@ -25,7 +20,7 @@ setImmediate(() => {
})
})

start({ foo: 'baz' })
a.set(43)
b.set(321)

// simulate an event loop turn
Expand Down
94 changes: 0 additions & 94 deletions test/basic.test.js

This file was deleted.

73 changes: 0 additions & 73 deletions test/do-not-start-memo.test.js

This file was deleted.

9 changes: 0 additions & 9 deletions test/fixture/basic/a.js

This file was deleted.

10 changes: 0 additions & 10 deletions test/fixture/basic/b.js

This file was deleted.

9 changes: 0 additions & 9 deletions test/fixture/basic/index.js

This file was deleted.

Loading

0 comments on commit bd7a4de

Please sign in to comment.