repos / starfx

supercharged async flow control library.
git clone https://github.com/neurosnap/starfx.git

commit
ee29a97
parent
2e93eae
author
Eric Bower
date
2023-11-23 02:31:22 +0000 UTC
docs: readme
1 files changed,  +73, -30
M README.md
+73, -30
  1@@ -29,41 +29,84 @@ Read my introductory blog post:
  2 - state management should not be coupled to the view
  3 - full control over state management
  4 
  5-## example
  6+# example: thunks are tasks for business logic
  7 
  8-This complete solution to the problem Jake Archibald discusses in his blog
  9-article
 10-[The gotcha of unhandled promise rejections](https://jakearchibald.com/2023/unhandled-rejections/):
 11+```ts
 12+import { createThunks, mdw } from "starfx";
 13+
 14+const thunks = createThunks();
 15+thunks.use(mdw.err);
 16+thunks.use(thunks.routes());
 17+
 18+const log = thunks.create("log", function* (ctx, next) {
 19+  console.log("before calling next middleware");
 20+  yield* next();
 21+  console.log("after all middleware have run");
 22+});
 23+
 24+store.dispatch(log());
 25+```
 26+
 27+# example: endpoints are tasks for managing HTTP requests
 28 
 29 ```ts
 30-import { each, json, main, parallel, request } from "starfx";
 31-
 32-function* fetchChapter(title: string) {
 33-  const response = yield* request(`/chapters/${title}`);
 34-  const data = yield* json(response);
 35-  return data;
 36-}
 37-
 38-const task = main(function* () {
 39-  const chapters = ["01", "02", "03"];
 40-  const ops = chapters.map((title) => () => fetchChapter(title));
 41-
 42-  // parallel returns a list of `Result` type
 43-  const chapters = yield* parallel(ops);
 44-
 45-  // make http requests in parallel but process them in sequence (e.g. 01, 02, 03)
 46-  for (const result of yield* each(chapters.sequence)) {
 47-    if (result.ok) {
 48-      console.log(result.value);
 49-    } else {
 50-      console.error(result.error);
 51-    }
 52-    yield* each.next();
 53-  }
 54+import { createApi, mdw } from "starfx";
 55+
 56+const api = createApi();
 57+api.use(mdw.api());
 58+api.use(api.routes());
 59+api.use(mdw.fetch({ baseUrl: "https://jsonplaceholder.typicode.com" }));
 60+
 61+export const fetchUsers = api.get("/users", api.cache());
 62+
 63+store.dispatch(fetchUsers());
 64+// now accessible with useCache(fetchUsers)
 65+```
 66+
 67+# example: an immutable store that acts like a reactive, in-memory database
 68+
 69+```ts
 70+import { configureStore, createSchema, slice } from "starfx/store";
 71+
 72+// app-wide database for ui, api data, or anything that needs reactivity
 73+const { db, initialState, update } = createSchema({
 74+  users: slice.table(),
 75+  cache: slice.table(),
 76+  loaders: slice.loader(),
 77 });
 78 
 79-const results = await task;
 80-console.log(results);
 81+const fetchUsers = api.get<never, User[]>(
 82+  "/users",
 83+  function* (ctx, next) {
 84+    // make the http request
 85+    yield* next();
 86+
 87+    // ctx.json is a Result type that either contains the http response
 88+    // json data or an error
 89+    if (!ctx.json.ok) {
 90+      return;
 91+    }
 92+
 93+    const { value } = ctx.json;
 94+    const users = value.reduce<Record<string, User>>((acc, user) => {
 95+      acc[user.id] = user;
 96+      return acc;
 97+    }, {});
 98+
 99+    // update the store and trigger a re-render in react
100+    yield* update(db.users.add(users));
101+
102+    // User[]
103+    const users = yield* select(db.users.selectTableAsList);
104+    // User
105+    const user = yield* select(
106+      (state) => db.users.selectById(state, { id: "1" }),
107+    );
108+  },
109+);
110+
111+const store = configureStore({ initialState });
112+store.dispatch(fetchUsers());
113 ```
114 
115 ## usage