Skip to content

Commit

Permalink
enhance: EntityMixin
Browse files Browse the repository at this point in the history
  • Loading branch information
ntucker committed Oct 12, 2024
1 parent f81737c commit 50f1e96
Show file tree
Hide file tree
Showing 18 changed files with 137 additions and 52 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ For the small price of 9kb gziped.    [🏁Get started now](https://da
<tbody><tr>
<td rowSpan="4"><a href="https://en.wikipedia.org/wiki/Object_(computer_science)">Object</a></td>
<td align="center">✅</td>
<td><a href="https://dataclient.io/rest/api/Entity">Entity</a>, <a href="https://dataclient.io/rest/api/schema.Entity">schema.Entity</a> mixin</td>
<td><a href="https://dataclient.io/rest/api/Entity">Entity</a>, <a href="https://dataclient.io/rest/api/EntityMixin">EntityMixin</a></td>
<td>single <em>unique</em> object</td>
<td align="center">✅</td>
</tr>
Expand Down
10 changes: 6 additions & 4 deletions __tests__/new.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { Temporal } from '@js-temporal/polyfill';
import React, { createContext, useContext } from 'react';

import {
schema,
Endpoint,
resource,
RestEndpoint,
Schema,
Entity,
EntityMixin,
RestGenerics,
hookifyResource,
RestType,
RestInstance,
Resource,
ResourceOptions,
} from '@data-client/rest';
import { Temporal } from '@js-temporal/polyfill';
import React, { createContext, useContext } from 'react';

/** Represents data with primary key being from 'id' field. */
export class IDEntity extends Entity {
Expand Down Expand Up @@ -44,7 +46,7 @@ export class VisSettings extends Entity implements Vis {

static key = 'VisSettings';
}
export class VisSettingsFromMixin extends schema.Entity(Vis) {
export class VisSettingsFromMixin extends EntityMixin(Vis) {
static cmpIncoming(
existingMeta: { date: number; fetchedAt: number },
incomingMeta: { date: number; fetchedAt: number },
Expand Down Expand Up @@ -179,7 +181,7 @@ class ArticleData {
readonly author: User | null = null;
readonly tags: string[] = [];
}
export class ArticleFromMixin extends schema.Entity(ArticleData, {
export class ArticleFromMixin extends EntityMixin(ArticleData, {
schema: { author: User },
}) {}
class ArticleEndpoint<O extends RestGenerics = any> extends RestEndpoint<O> {}
Expand Down
6 changes: 3 additions & 3 deletions docs/core/getting-started/resource.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export const TodoResource = {
<PkgInstall pkgs="@data-client/endpoint" />

Pre-existing TypeScript definitions can be used in <abbr title="Reactive Data Client">Data Client</abbr> with
[Endpoint](/rest/api/Endpoint) and [schema.Entity](/rest/api/schema.Entity).
[Endpoint](/rest/api/Endpoint) and [EntityMixin](/rest/api/EntityMixin).

<TypeScriptEditor row={false}>

Expand Down Expand Up @@ -198,7 +198,7 @@ import {
deleteTodo,
} from './existing/Todo';

export const TodoEntity = schema.Entity(Todo, { key: 'Todo' });
export const TodoEntity = EntityMixin(Todo, { key: 'Todo' });

export const TodoResource = {
get: new Endpoint(getTodo, { schema: TodoEntity }),
Expand Down Expand Up @@ -289,5 +289,5 @@ To aid in defining `Resources`, composable and extensible protocol specific help
[Image/binary](../guides/img-media.md), [Websockets+SSE](../concepts/managers.md#data-stream).

To use existing API definitions, or define your own protocol specific helpers, use
[Endpoint](/rest/api/Endpoint) and [schema.Entity](/rest/api/schema.Entity) from [@data-client/endpoint](https://www.npmjs.com/package/@data-client/endpoint).
[Endpoint](/rest/api/Endpoint) and [EntityMixin](/rest/api/EntityMixin) from [@data-client/endpoint](https://www.npmjs.com/package/@data-client/endpoint).
[See `Async/Promise` tab above]
2 changes: 1 addition & 1 deletion docs/core/shared/_VoteDemo.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class Post extends Entity {
static key = 'Post';

static schema = {
author: schema.Entity(
author: EntityMixin(
class User {
id = 0;
},
Expand Down
8 changes: 4 additions & 4 deletions docs/rest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,17 @@ export const ArticleResource = resource({
<TypeScriptEditor>

```typescript title="User" collapsed
import { schema } from '@data-client/rest';
import { EntityMixin } from '@data-client/rest';

export class User {
id = '';
username = '';
}
export class UserEntity extends schema.Entity(User) {}
export class UserEntity extends EntityMixin(User) {}
```

```typescript title="Article"
import { schema, resource } from '@data-client/rest';
import { EntityMixin, resource } from '@data-client/rest';
import { UserEntity } from './User';

export class Article {
Expand All @@ -104,7 +104,7 @@ export class Article {
createdAt = Temporal.Instant.fromEpochSeconds(0);
}

export class ArticleEntity extends schema.Entity(Article, {
export class ArticleEntity extends EntityMixin(Article, {
schema: {
author: UserEntity,
createdAt: Temporal.Instant.from,
Expand Down
2 changes: 1 addition & 1 deletion docs/rest/api/Entity.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ Entities are bound to Endpoints using [resource.schema](./resource.md#schema) or

:::tip

If you already have your classes defined, [schema.Entity](./schema.Entity.md) mixin can also be
If you already have your classes defined, [EntityMixin](./EntityMixin.md) mixin can also be
used to make Entities.

:::
Expand Down
22 changes: 11 additions & 11 deletions docs/rest/api/schema.Entity.md → docs/rest/api/EntityMixin.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: schema.Entity - Entity mixin
sidebar_label: schema.Entity
title: EntityMixin - Declarative unique objects for pre-existing classes
sidebar_label: EntityMixin
---

<head>
Expand All @@ -12,16 +12,16 @@ import LanguageTabs from '@site/src/components/LanguageTabs';
import { RestEndpoint } from '@data-client/rest';
import TypeScriptEditor from '@site/src/components/TypeScriptEditor';

# schema.Entity
# EntityMixin

`Entity` defines a single _unique_ object.

If you already have classes for your data-types, `schema.Entity` mixin may be for you.
If you already have classes for your data-types, `EntityMixin` mixin may be for you.

<TypeScriptEditor>

```typescript {10}
import { schema } from '@data-client/rest';
import { EntityMixin } from '@data-client/rest';

export class Article {
id = '';
Expand All @@ -30,7 +30,7 @@ export class Article {
tags: string[] = [];
}

export class ArticleEntity extends schema.Entity(Article) {}
export class ArticleEntity extends EntityMixin(Article) {}
```

</TypeScriptEditor>
Expand All @@ -48,7 +48,7 @@ class User {
username = '';
createdAt = Temporal.Instant.fromEpochSeconds(0);
}
class UserEntity extends schema.Entity(User, {
class UserEntity extends EntityMixin(User, {
pk: 'username',
key: 'User',
schema: { createdAt: Temporal.Instant.from },
Expand All @@ -75,7 +75,7 @@ class Thread {
slug = '';
content = '';
}
class ThreadEntity extends schema.Entity(Thread, {
class ThreadEntity extends EntityMixin(Thread, {
pk(value) {
return [value.forum, value.slug].join(',');
},
Expand All @@ -94,7 +94,7 @@ Specifies the [Entity.schema](./Entity.md#schema)

## Methods

`schema.Entity` mixin has the same [methods as the Entity](./Entity.md#lifecycle) class.
`EntityMixin` mixin has the same [methods as the Entity](./Entity.md#lifecycle) class.

## const vs class

Expand All @@ -118,8 +118,8 @@ export class Article {
tags: string[] = [];
}

export class ArticleEntity extends schema.Entity(Article) {}
export const ArticleEntity2 = schema.Entity(Article);
export class ArticleEntity extends EntityMixin(Article) {}
export const ArticleEntity2 = EntityMixin(Article);

const article: ArticleEntity = ArticleEntity.fromJS();
const articleFails: ArticleEntity2 = ArticleEntity2.fromJS();
Expand Down
6 changes: 3 additions & 3 deletions examples/benchmark/schemas.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Entity, schema } from './dist/index.js';
import { Entity, EntityMixin, schema } from './dist/index.js';

export class BuildTypeDescription extends Entity {
id = '';
Expand All @@ -13,7 +13,7 @@ export class BuildTypeDescription extends Entity {
export class BuildTypeDescriptionEmpty extends Entity {
static key = 'BuildTypeDescription';
}
export const BuildTypeDescriptionEntity = schema.Entity(
export const BuildTypeDescriptionEntity = EntityMixin(
class {
id = '';
internalId = 'bt17590';
Expand Down Expand Up @@ -51,7 +51,7 @@ export class ProjectWithBuildTypesDescriptionEmpty extends Entity {

static key = 'ProjectWithBuildTypesDescription';
}
export const ProjectWithBuildTypesDescriptionEntity = schema.Entity(
export const ProjectWithBuildTypesDescriptionEntity = EntityMixin(
class {
id = '';
internalId = 'project3239';
Expand Down
6 changes: 3 additions & 3 deletions packages/endpoint/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ export const updateTodo = (id: string, body: Partial<Todo>) =>
### 2) Turn them into Resources

```typescript
import { schema, Endpoint } from '@data-client/endpoint';
import { EntityMixin, Endpoint } from '@data-client/endpoint';
import { Todo, getTodoList, updateTodo } from './existing';

export const TodoEntity = schema.Entity(Todo, { key: 'Todo' });
export const TodoEntity = EntityMixin(Todo, { key: 'Todo' });

export const TodoResource = {
get: new Endpoint(getTodo, {
Expand Down Expand Up @@ -221,7 +221,7 @@ Networking definition: [Endpoints](https://dataclient.io/rest/api/Endpoint)
<tbody><tr>
<td rowSpan="4"><a href="https://en.wikipedia.org/wiki/Object_(computer_science)">Object</a></td>
<td align="center">✅</td>
<td><a href="https://dataclient.io/rest/api/Entity">Entity</a>, <a href="https://dataclient.io/rest/api/schema.Entity">schema.Entity</a> mixin</td>
<td><a href="https://dataclient.io/rest/api/Entity">Entity</a>, <a href="https://dataclient.io/rest/api/EntityMixin">EntityMixin</a></td>
<td>single <em>unique</em> object</td>
<td align="center">✅</td>
</tr>
Expand Down
1 change: 1 addition & 0 deletions packages/endpoint/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export * as schema from './schema.js';
// Clue 1) It only happens with types mentioned in return types of other types
export type { Array, Invalidate, Collection, DefaultArgs } from './schema.js';
export { default as Entity } from './schemas/Entity.js';
export { default as EntityMixin } from './schemas/EntityMixin.js';
export { default as validateRequired } from './validateRequired.js';
export { INVALID } from './special.js';
export type {
Expand Down
18 changes: 8 additions & 10 deletions packages/endpoint/src/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,10 @@ import type {
ObjectArgs,
} from './normal.js';
import { EntityFields } from './schemas/EntityFields.js';
import type {
IEntityClass,
IEntityInstance,
EntityOptions,
RequiredPKOptions,
IDClass,
Constructor,
PKClass,
} from './schemas/EntityTypes.js';
import {
default as EntityMixin,
default as Entity,
} from './schemas/EntityMixin.js';
import { default as Invalidate } from './schemas/Invalidate.js';
import { default as Query } from './schemas/Query.js';
import type {
Expand All @@ -40,7 +35,7 @@ import type {
UnionResult,
} from './schemaTypes.js';

export { EntityMap, Invalidate, Query };
export { EntityMap, Invalidate, Query, EntityMixin, Entity };

export type { SchemaClass };

Expand Down Expand Up @@ -410,6 +405,7 @@ export declare class Collection<
Args extends any[] = DefaultArgs,
Parent = any,
> extends CollectionRoot<S, Args, Parent> {}
<<<<<<< HEAD

/**
* Entity defines a single (globally) unique object.
Expand Down Expand Up @@ -442,3 +438,5 @@ export function Entity<TBase extends Constructor>(
IEntityClass<TBase> &
TBase;
*/
=======
>>>>>>> be944264a2 (enhance: EntityMixin)
5 changes: 4 additions & 1 deletion packages/endpoint/src/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@ export { default as All } from './schemas/All.js';
export { default as Object } from './schemas/Object.js';
export { default as Invalidate } from './schemas/Invalidate.js';
export { default as Collection } from './schemas/Collection.js';
export { default as Entity } from './schemas/EntityMixin.js';
export {
default as EntityMixin,
default as Entity,
} from './schemas/EntityMixin.js';
export { default as Query } from './schemas/Query.js';
29 changes: 27 additions & 2 deletions packages/endpoint/src/schemas/EntityMixin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Constructor, EntityOptions } from './EntityTypes.js';
import type {
Schema,
GetIndex,
Expand All @@ -7,11 +6,37 @@ import type {
Visit,
} from '../interface.js';
import { AbstractInstanceType } from '../normal.js';
import type {
IEntityClass,
IEntityInstance,
EntityOptions,
RequiredPKOptions,
IDClass,
Constructor,
PKClass,
} from './EntityTypes.js';

/**
* Entity defines a single (globally) unique object.
* @see https://dataclient.io/rest/api/schema.Entity
* @see https://dataclient.io/rest/api/EntityMixin
*/
export default function EntityMixin<TBase extends PKClass>(
Base: TBase,
opt?: EntityOptions<InstanceType<TBase>>,
): IEntityClass<TBase> & TBase;

// id is in Instance, so we default to that as pk
export default function EntityMixin<TBase extends IDClass>(
Base: TBase,
opt?: EntityOptions<InstanceType<TBase>>,
): IEntityClass<TBase> & TBase & (new (...args: any[]) => IEntityInstance);

// pk was specified in options, so we don't need to redefine
export default function EntityMixin<TBase extends Constructor>(
Base: TBase,
opt: RequiredPKOptions<InstanceType<TBase>>,
): IEntityClass<TBase> & TBase & (new (...args: any[]) => IEntityInstance);

export default function EntityMixin<TBase extends Constructor>(
Base: TBase,
options: EntityOptions<InstanceType<TBase>> = {},
Expand Down
4 changes: 4 additions & 0 deletions website/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ const config: Config = {
to: '/docs/getting-started/debugging',
from: ['/docs/guides/debugging'],
},
{
to: '/rest/api/schema.Entity',
from: ['/rest/api/EntityMixin'],
},
...gqlRedirects,
],
},
Expand Down
Loading

0 comments on commit 50f1e96

Please sign in to comment.