2.4.0 • Published 1 year ago

@synvox/core-client v2.4.0

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

@synvox/core-client

Core client provides an ergonomic interface for working with @synvox/core. It is not required when using @synvox/core.

Using types

In your Core server, you may save TypeScript types for your database schema. like this:

// on your server
if (process.env.NODE_ENV !== "production") {
  core.init().then(async () => {
    await core.saveTsTypes(
      path.resolve(__dirname, "/project/client/types.ts"),
      {
        includeLinks: false,
        includeRelations: true,
        includeParams: true,
      }
    );
  });
}

includeLinks: false will tell Core server not to save _links and _url properties.

includeRelations: true will tell Core to save related tables as properties. For example, if you have a posts and a comments table, core might output something like:

type Post = {
  id: number;
  title: string;
  comments: Comment[];
};

type Comment = {
  id: number;
  body: string;
  post: Post;
};

includeParams: true will tell Core to save the query parameter options for a table.

type Post = {
  id: number;
  title: string;
  comments: Comment[];
};

type PostParams = {
  id: number;
  title: string;
  // more not shown
};

type Comment = {
  id: number;
  body: string;
  post: Post;
};

type CommentParams = {
  id: number;
  body: string;
  // more not shown
};

Quick Start

Using the post and comments example, define your core schema and the routes each resource may be on.

import { core, table } from "@synvox/core-client";
import Axios from "axios";

const axios = Axios.create({ baseURL: "/api" });

const { useCore } = core(axios, {
  posts: table<Post, PostParams>("/posts"),
  comments: table<Comment, CommentParams>("/comments"),
});

export { useCore };

Then in your component:

function Post({ postId }: { postId: number }) {
  const core = useCore();

  const post = core.posts(postId);
  // `post` will be of type `Post`
  // `postId` must be of type `PostParams['id']`

  return <>{post.name}</>;
}

🎉 and Core will load that post into your component. Internally this works similar to React.lazy. Core will manage an in-memory cache and suspend for data it needs.

Core provides hypermedia links (like _url, and _links). When core requests a collection like /posts, core will also cache the embedded rows like /posts/1 and /posts/2. So if you have a component that does this:

function Posts() {
  const core = useCore();

  const posts = core.posts();
  // posts will be assigned type `Post[]`

  return posts.map((post) => <Post key={post.id} postId={post.id} />);
}

function Post({ postId }: { postId: number }) {
  const core = useCore();

  const post = core.posts(postId);
  // post will be assigned type`Post`

  return <>{post.name}</>;
}

Then there will not be a separate request to get /post/:id. Core already has it in the cache from /posts. There's no need to load it a second time.

The useCore hook

The useCore hook has suspending and non-suspending methods.

const core = useCore()
// suspending
core.posts.get(id: PostParams['id'], params?: PostParams) // => Post
core.posts.get(params?: PostParams) // => Post[]
core.posts() // same as core.posts.get
core.first(params?: PostParams) // => Post
core.ids(params?: PostParams) // => Array<PostParams['id']>
core.count(params?: PostParams) // => number

// async
core.posts.post(data: Partial<Post> | Partial<Post>[], params?: Params) // => ChangeTo<Post[]>
core.posts.put(id: PostParams['id'], data: Partial<Post>, params?: Params) // => ChangeTo<Post>
core.posts.delete(id: PostParams['id'], params?: Params) // => ChangeTo<Post[]>
core.posts.post(url:string, data: Partial<Post> | Partial<Post>[], params?: Params) // => ChangeTo<Post[]>
// useful when calling something like `POST /users/:method`

Resolving changes

The ChangeTo type includes an update method. After sending a request, call update to update all components that may have been changed by the request.

async function saveComment() {
  const { update } = await core.comments.post({
    body: newPostBody,
  });

  await update();
}

Core will not automatically call update for you so you in case you need to change something before the components are updated, like redirect.

Preloading

If you have a waterfall request that you would like to avoid, you can preload.

import { preload } from "@synvox/core-client";

const { useCore } = core(axios, {
  item: table<Item, ItemParams>("/items"),
});

function Component() {
  const core = useCore();

  preload(() => core.items(1));
  preload(() => core.items(2));
}

This will load both /items/1 and /items/2. Each preload call will return an async function that resolves the return value once it exists in the cache.

Deferring

This is similar to preloading but instead of returning a promise, it will return {data: T[] | undefined, isLoading: boolean}. This makes it useful for sending requests that should not suspend.

import { preload } from "@synvox/core-client";

const { useCore } = core(axios, {
  item: table<Item, ItemParams>("/items"),
});

function Component() {
  const core = useCore();

  const { data: user, isLoading } = suspend(() => {
    return core.users("me");
  });
}

Cache Invalidation

In the case you need to invalidate cached urls, you can use the touch method.

const { useCore, touch } = core(axios, {
  posts: table<Post, PostParams>("/posts"),
  comments: table<Comment, CommentParams>("/comments"),
});

// then elsewhere...

await touch((url) => {
  // return true if you want to invalidate this url
  return url.startsWith("/posts") || url.startsWith("/comments");
});

Core will rerun the request that loaded that url and once all urls are loaded again, Core will update the components.

Loading raw URLs

If you need to load a url into the cache manually, use the useGetUrl hook

const { useGetUrl } = core(axios, {
  item: table<Item, ItemParams>("/items"),
});

// then elsewhere...
const item = useGetUrl("/items/1");
2.5.0-alpha.83

1 year ago

2.5.0-alpha.82

1 year ago

2.5.0-alpha.76

2 years ago

2.5.0-alpha.74

2 years ago

2.5.0-alpha.73

2 years ago

2.5.0-alpha.75

2 years ago

2.5.0-alpha.68

2 years ago

2.5.0-alpha.67

2 years ago

2.5.0-alpha.65

2 years ago

2.5.0-alpha.64

2 years ago

2.5.0-alpha.62

2 years ago

2.5.0-alpha.61

2 years ago

2.5.0-alpha.54

2 years ago

2.5.0-alpha.53

2 years ago

2.5.0-alpha.52

3 years ago

2.5.0-alpha.51

3 years ago

2.5.0-alpha.50

3 years ago

2.5.0-alpha.49

3 years ago

2.5.0-alpha.48

3 years ago

2.5.0-alpha.47

3 years ago

2.5.0-alpha.46

3 years ago

2.5.0-alpha.44

3 years ago

2.5.0-alpha.43

3 years ago

2.5.0-alpha.42

3 years ago

2.5.0-alpha.40

3 years ago

2.5.0-alpha.30

3 years ago

2.5.0-alpha.29

3 years ago

2.5.0-alpha.28

3 years ago

2.5.0-alpha.39

3 years ago

2.5.0-alpha.38

3 years ago

2.5.0-alpha.37

3 years ago

2.5.0-alpha.36

3 years ago

2.5.0-alpha.35

3 years ago

2.5.0-alpha.34

3 years ago

2.5.0-alpha.33

3 years ago

2.5.0-alpha.32

3 years ago

2.5.0-alpha.27

3 years ago

2.5.0-alpha.26

3 years ago

2.5.0-alpha.25

3 years ago

2.5.0-alpha.15

3 years ago

2.5.0-alpha.14

3 years ago

2.5.0-alpha.9

3 years ago

2.5.0-alpha.8

3 years ago

2.5.0-alpha.7

3 years ago

2.5.0-alpha.6

3 years ago

2.5.0-alpha.3

3 years ago

2.5.0-alpha.0

3 years ago

2.4.0

3 years ago

2.3.2

3 years ago

2.3.1

3 years ago

2.3.1-alpha.1

3 years ago

2.3.1-alpha.2

3 years ago

2.3.1-alpha.0

3 years ago

2.3.1-alpha.5

3 years ago

2.3.1-alpha.6

3 years ago

2.3.1-alpha.3

3 years ago

2.3.1-alpha.4

3 years ago

2.3.1-alpha.7

3 years ago

2.1.0

3 years ago

2.0.0

3 years ago

2.0.0-20

3 years ago

2.0.0-19

3 years ago

2.0.0-18

3 years ago

2.0.0-17

3 years ago

2.0.0-16

3 years ago

2.0.0-15

3 years ago

2.0.0-14

3 years ago

2.0.0-13

3 years ago

2.0.0-12

3 years ago

2.0.0-11

3 years ago

2.0.0-10

3 years ago

2.0.0-9

3 years ago

2.0.0-8

3 years ago

2.0.0-7

3 years ago

2.0.0-6

3 years ago

2.0.0-5

3 years ago

2.0.0-4

3 years ago

2.0.0-3

3 years ago

2.0.0-2

3 years ago

2.0.0-1

3 years ago

2.0.0-0

3 years ago

1.0.0

3 years ago