Skip to content

Commit

Permalink
feat: added transactions support
Browse files Browse the repository at this point in the history
  • Loading branch information
pie6k committed Feb 12, 2023
1 parent 8302a4e commit 4bbf58b
Show file tree
Hide file tree
Showing 14 changed files with 181 additions and 70 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
"language": "markdown",
"scheme": "file"
}
]
],
"typescript.tsdk": "node_modules/typescript/lib"
}
3 changes: 0 additions & 3 deletions core/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { assert } from "./utils/assert";
import { createEntityClient } from "./client";
import { DbContextInstance } from "./context";
import { createCleanupObject } from "./utils/cleanup";
import { IS_CLIENT } from "./utils/client";
import { ClientDbEvents, ClientDbEventsEmmiter } from "./events";
import { createEventsEmmiter } from "./utils/eventManager";

Expand All @@ -32,8 +31,6 @@ export function createClientDb(
definitions: Array<EntityDefinition<any, any>>,
{ contexts }: ClientDbConfig = {}
): ClientDb {
assert(IS_CLIENT, "Client DB can only be created on client side");

const clientsLookup = new Map<
EntityDefinition<any, any>,
EntityClient<any, any>
Expand Down
18 changes: 9 additions & 9 deletions core/definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,16 @@ export interface EntityDefinition<Data, View> {
): EntityDefinition<Data, View>;
}

export interface EntityViewLinker<Data, View> {
export interface EntityViewLinker<Data> {
db: ClientDb;
updateSelf(data: Partial<Data>): EntityUpdatedEvent<Data, View>;
updateSelf(data: Partial<Data>): EntityUpdatedEvent<Data, unknown>;
cleanup: CleanupObject;
}

type EntityDefinitionGetView<Data, View> = (
type EntityDefinitionGetView<Data, AddedView> = (
item: Data,
linker: EntityViewLinker<Data, View>
) => View;
linker: EntityViewLinker<Data>
) => AddedView;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type EntityDataByDefinition<Def extends EntityDefinition<any, any>> =
Expand All @@ -94,7 +94,7 @@ export type EntityDataByDefinition<Def extends EntityDefinition<any, any>> =

export type AnyEntityDefinition = EntityDefinition<any, any>;

export function defineEntity<Data extends {}, View extends {} = {}>(
export function defineEntity<Data, View = {}>(
config: EntityConfig<Data, View>
): EntityDefinition<Data, View> {
if (!config.idField) {
Expand All @@ -114,11 +114,11 @@ export function defineEntity<Data extends {}, View extends {} = {}>(
const sortedKeys = [...config.fields].sort();
return getHash(sortedKeys.join(""));
},
addView<View>(getView: EntityDefinitionGetView<Data, View>) {
return defineEntity<Data, View>({
addView<AddedView>(getView: EntityDefinitionGetView<Data, AddedView>) {
return defineEntity<Data, AddedView>({
...config,
getView,
} as EntityConfig<Data, View>) as EntityDefinition<Data, View>;
} as EntityConfig<Data, AddedView>) as EntityDefinition<Data, AddedView>;
},
addRootFilter(validator) {
return defineEntity({ ...config, rootFilter: validator });
Expand Down
9 changes: 6 additions & 3 deletions core/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,21 @@ export function createEntity<D, V>({

const cleanupObject = createCleanupObject();

const viewLinker: EntityViewLinker<D, V> = {
const viewLinker: EntityViewLinker<D> = {
db,
updateSelf(data) {
return entity.update(data);
return entity.update(data) as EntityUpdatedEvent<D, unknown>;
},
cleanup: cleanupObject,
};

const view = config.getView?.(observableData, viewLinker) ?? ({} as V);

// Note: we dont want to add view as {...data, ...connections}. Connections might have getters so it would simply unwrap them.
const observableDataAndView = extendObservable(observableData, view);
const observableDataAndView = extendObservable(
observableData,
view as V & object
);

const entityMethods: EntityMethods<D, V> = {
definition,
Expand Down
2 changes: 2 additions & 0 deletions core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export * from "./utils/cachedComputed";
export * from "./utils/cachedComputedWithoutArgs";
export * from "./context";
export * from "./find";
export * from "./events";
export * from "./transaction";
4 changes: 2 additions & 2 deletions core/tests/eventHandlers.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createClientDb, defineEntity, ClientDb } from "@clientdb/core";
import { createClientDb, defineEntity } from "@clientdb/core";

import { TestOwnerEntity, getDefaultCommonData } from "./utils";
import { getDefaultCommonData, TestOwnerEntity } from "./utils";

const created = jest.fn();
const updated = jest.fn();
Expand Down
2 changes: 1 addition & 1 deletion core/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { typedKeys } from "./utils/object";
* - undo means we want to undo the transaction even if it was successful - it means it will also need to be re-emitted and synced.
*/

type Change = EntityChangeEvent<unknown, unknown>;
export type Change = EntityChangeEvent<unknown, unknown>;
type AnyEntity = Entity<unknown, unknown>;

/**
Expand Down
42 changes: 0 additions & 42 deletions core/utils/analyzeFragment.ts

This file was deleted.

10 changes: 8 additions & 2 deletions core/utils/cachedComputed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,24 @@ function isArrayMethodInlineCall(...args: any[]) {
return true;
}

interface Options<T> extends CachedComputedOptions<T> {
equalCompareArgs?: boolean;
}

/**
* Creates 'lazy computed', but with possibility of using multiple arguments
*/
export function cachedComputed<A extends any[], T>(
getter: (...args: A) => T,
options: CachedComputedOptions<T> = {}
options: Options<T> = {}
) {
// For easier debugging - try to get name of getter function
const getterName = getter.name || undefined;

// TODO: cleanup map entries after lazy is disposed
const map = createDeepMap<CachedComputed<T>>();
const map = createDeepMap<CachedComputed<T>>({
checkEquality: options?.equalCompareArgs ?? false,
});

function getComputedForArgs(...args: A) {
return map.getOrCreate(args, () =>
Expand Down
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc"
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@docusaurus/core": "latest",
Expand Down
3 changes: 2 additions & 1 deletion docs/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// This file is not used in compilation. It is here just for a nice editor experience.
"extends": "@tsconfig/docusaurus/tsconfig.json",
"compilerOptions": {
"baseUrl": "."
"baseUrl": ".",
"jsx": "react"
}
}
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
"scripts": {
"core": "yarn workspace @clientdb/core",
"engine": "yarn workspace @clientdb/engine",
"docs": "yarn workspace @clientdb/docs"
"docs": "yarn workspace @clientdb/docs",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@parcel/packager-ts": "2.6.2",
"@parcel/transformer-typescript-types": "2.6.2",
"@types/jest": "^29.4.0",
"typescript": ">=3.0.0"
},
"packageManager": "yarn@3.2.1"
Expand Down
6 changes: 2 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"lib": ["dom", "dom.iterable", "esnext"],

// "jsx": "preserve", /* Specify what JSX code is generated. */
"jsx": "react" /* Specify what JSX code is generated. */,
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
Expand All @@ -33,9 +33,7 @@
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
"types": [
"node"
] /* Specify type package names to be included without being referenced in a source file. */,

// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "resolveJsonModule": true, /* Enable importing .json files. */
Expand Down
Loading

0 comments on commit 4bbf58b

Please sign in to comment.