This commit is contained in:
Xu Chang 2022-03-25 16:44:27 +08:00
parent c7892ade3f
commit b14c026048
17 changed files with 219 additions and 28 deletions

View File

@ -1,5 +1,4 @@
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-domain/EntityDict';
import { Context as BaseContext } from 'oak-memory-tree-store';
export declare class FrontContext<ED extends EntityDict & BaseEntityDict> extends BaseContext<ED> {
export declare class FrontContext<ED extends EntityDict> extends BaseContext<ED> {
}

View File

@ -1,11 +1,7 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];

View File

@ -2,7 +2,7 @@ import { EntityDict, OpRecord } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-domain/EntityDict';
import { Aspect } from 'oak-domain/lib/types/Aspect';
import { Feature } from '../types/Feature';
export declare class Cache<ED extends EntityDict & BaseEntityDict, AD extends Record<string, Aspect<ED>>> extends Feature<ED, AD> {
export declare class Cache<ED extends EntityDict, AD extends Record<string, Aspect<ED>>> extends Feature<ED, AD> {
get<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], params?: object): Promise<Partial<ED[T]["Schema"] & {
$expr?: any;
$expr1?: any;
@ -26,8 +26,8 @@ export declare class Cache<ED extends EntityDict & BaseEntityDict, AD extends Re
$expr19?: any;
$expr20?: any;
}>[]>;
protected refresh<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], params?: object): Promise<void>;
protected sync(opRecords: OpRecord<ED>[]): Promise<void>;
refresh<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], params?: object): Promise<import("oak-domain/lib/types/Entity").OperationResult>;
sync(opRecords: OpRecord<ED>[]): Promise<void>;
}
export declare type Action<ED extends EntityDict & BaseEntityDict, AD extends Record<string, Aspect<ED>>> = {
refresh: Cache<ED, AD>['refresh'];

View File

@ -2,13 +2,14 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.Cache = void 0;
const Feature_1 = require("../types/Feature");
const lodash_1 = require("lodash");
class Cache extends Feature_1.Feature {
async get(entity, selection, params) {
const { result } = await this.getContext().rowStore.select(entity, selection, this.getContext(), params);
return result;
}
async refresh(entity, selection, params) {
this.getAspectProxy().select({ entity: entity, selection, params });
return this.getAspectProxy().operate({ entity: entity, operation: (0, lodash_1.assign)({}, selection, { action: 'select' }), params });
}
async sync(opRecords) {
await this.getContext().rowStore.sync(opRecords, this.getContext());

View File

@ -1,11 +1,7 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];

11
lib/features/node.d.ts vendored Normal file
View File

@ -0,0 +1,11 @@
import { DeduceUpdateOperation, EntityDict } from 'oak-domain/lib/types/Entity';
import { Aspect } from 'oak-domain/lib/types/Aspect';
import { Cache } from './cache';
export declare class Node<ED extends EntityDict, AD extends Record<string, Aspect<ED>>, T extends keyof ED> {
protected entity: T;
protected projection: ED[T]['Selection']['data'];
protected cache: Cache<ED, AD>;
private parent?;
protected updateData?: DeduceUpdateOperation<ED[T]['OpSchema']>;
constructor(entity: T, projection: ED[T]['Selection']['data'], cache: Cache<ED, AD>, parent?: Node<ED, AD, keyof ED>);
}

85
lib/features/node.js Normal file
View File

@ -0,0 +1,85 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Node = void 0;
const filter_1 = require("oak-domain/lib/schema/filter");
const assert_1 = __importDefault(require("assert"));
class Node {
entity;
projection;
cache;
parent;
updateData;
constructor(entity, projection, cache, parent) {
this.entity = entity;
this.projection = projection;
this.cache = cache;
this.parent = parent;
}
}
exports.Node = Node;
class ListNode extends Node {
ids;
children;
append;
filters;
sorter;
indexFrom;
count;
hasMore;
total;
constructor(entity, projection, cache, parent, append) {
super(entity, projection, cache, parent);
this.ids = [];
this.children = [];
this.append = append || false; // todo 根据environment来自动决定
}
async refresh() {
const { entity, projection, filters, sorter, count } = this;
const { ids } = await this.cache.refresh(entity, {
data: projection,
filter: filters && (0, filter_1.combineFilters)(filters),
sorter,
indexFrom: count && 0,
count,
});
(0, assert_1.default)(ids);
this.ids = ids;
this.indexFrom = 0;
this.hasMore = ids.length === count;
}
async nextPage() {
}
async prevPage() {
}
}
class SingleNode extends Node {
id;
children;
constructor(entity, projection, cache, parent, id) {
super(entity, projection, cache, parent);
this.id = id;
this.children = {};
}
async refresh() {
const { entity, projection, id } = this;
(0, assert_1.default)(id);
await this.cache.refresh(entity, {
data: projection,
filter: {
id,
},
}); // 搞不懂为何这里过不去
}
async get() {
const { entity, projection, id } = this;
const row = id && this.cache.get(entity, {
data: projection,
filter: {
id,
},
});
}
}

1
lib/index.d.ts vendored
View File

@ -14,4 +14,5 @@ export declare function initialize<ED extends EntityDict & BaseEntityDict, AD ex
}): Promise<{
subscribe: (callback: () => void) => () => void;
action: <F extends keyof FeatureActions<ED, AD> | keyof FAD, M extends keyof (FeatureActions<ED, AD> & FAD)[F]>(name: F, method: M, ...params: Parameters<(FeatureActions<ED, AD> & FAD)[F][M]>) => Promise<ReturnType<(FeatureActions<ED, AD> & FAD)[F][M]>>;
features: BasicFeatures<ED, AD> & FD;
}>;

View File

@ -119,6 +119,7 @@ async function initialize(storageSchema, applicationId, createFeatures, triggers
return {
subscribe,
action,
features,
};
}
exports.initialize = initialize;

View File

@ -1,6 +1,5 @@
import { Aspect } from "oak-domain/lib/types/Aspect";
import { EntityDict } from "oak-domain/lib/types/Entity";
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-domain/EntityDict';
export declare type AspectProxy<ED extends BaseEntityDict & EntityDict, AD extends Record<string, Aspect<ED>>> = {
export declare type AspectProxy<ED extends EntityDict, AD extends Record<string, Aspect<ED>>> = {
[K in keyof AD]: (p: Parameters<AD[K]>[0]) => ReturnType<AD[K]>;
};

View File

@ -1,10 +1,9 @@
import { Aspect } from 'oak-domain/lib/types/Aspect';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-domain/EntityDict';
import { aspectDict as basicAspectDict } from 'oak-general-business';
import { FrontContext } from '../FrontContext';
import { AspectProxy } from './AspectProxy';
export declare abstract class Feature<ED extends EntityDict & BaseEntityDict, AD extends Record<string, Aspect<ED>>> {
export declare abstract class Feature<ED extends EntityDict, AD extends Record<string, Aspect<ED>>> {
private aspectProxy?;
private context?;
protected getAspectProxy(): NonNullable<AspectProxy<ED, AD & {

View File

@ -2,6 +2,6 @@ import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-domain/EntityDict';
import { Context as BaseContext } from 'oak-memory-tree-store';
export class FrontContext<ED extends EntityDict & BaseEntityDict> extends BaseContext<ED> {
export class FrontContext<ED extends EntityDict> extends BaseContext<ED> {
};

View File

@ -1,19 +1,20 @@
import { EntityDict, OpRecord } from 'oak-domain/lib/types/Entity';
import { DeduceSelection, EntityDict, OpRecord } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-domain/EntityDict';
import { Aspect } from 'oak-domain/lib/types/Aspect';
import { Feature } from '../types/Feature';
import { assign } from 'lodash';
export class Cache<ED extends EntityDict & BaseEntityDict, AD extends Record<string, Aspect<ED>>> extends Feature<ED, AD> {
export class Cache<ED extends EntityDict, AD extends Record<string, Aspect<ED>>> extends Feature<ED, AD> {
async get<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], params?: object) {
const { result } = await this.getContext().rowStore.select(entity, selection, this.getContext(), params);
return result;
}
protected async refresh<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], params?: object) {
this.getAspectProxy().select({ entity: entity as any, selection, params });
async refresh<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], params?: object) {
return this.getAspectProxy().operate({ entity: entity as any, operation: assign({}, selection, { action: 'select' }) as DeduceSelection<ED[T]['Schema']>, params });
}
protected async sync(opRecords: OpRecord<ED>[]) {
async sync(opRecords: OpRecord<ED>[]) {
await this.getContext().rowStore.sync(opRecords, this.getContext());
}
}

101
src/features/node.ts Normal file
View File

@ -0,0 +1,101 @@
import { DeduceUpdateOperation, EntityDict, OpRecord } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-domain/EntityDict';
import { Aspect } from 'oak-domain/lib/types/Aspect';
import { combineFilters } from 'oak-domain/lib/schema/filter';
import { Feature } from '../types/Feature';
import { Cache } from './cache';
import assert from 'assert';
export class Node<ED extends EntityDict, AD extends Record<string, Aspect<ED>>, T extends keyof ED> {
protected entity: T;
protected projection: ED[T]['Selection']['data'];
protected cache: Cache<ED, AD>;
private parent?: Node<ED, AD, keyof ED>;
protected updateData?: DeduceUpdateOperation<ED[T]['OpSchema']>;
constructor(entity: T, projection: ED[T]['Selection']['data'], cache: Cache<ED, AD>, parent?: Node<ED, AD, keyof ED>) {
this.entity = entity;
this.projection = projection;
this.cache = cache;
this.parent = parent;
}
}
class ListNode<ED extends EntityDict, AD extends Record<string, Aspect<ED>>, T extends keyof ED> extends Node<ED, AD, T>{
private ids: string[];
private children: Node<ED, AD, T>[];
private append: boolean;
private filters?: ED[T]['Selection']['filter'][];
private sorter?: ED[T]['Selection']['sorter'];
private indexFrom?: number;
private count?: number;
private hasMore?: boolean;
private total?: number;
constructor(entity: T, projection: ED[T]['Selection']['data'], cache: Cache<ED, AD>, parent?: Node<ED, AD, keyof ED>, append?: boolean) {
super(entity, projection, cache, parent);
this.ids = [];
this.children = [];
this.append = append || false; // todo 根据environment来自动决定
}
async refresh() {
const { entity, projection, filters, sorter, count } = this;
const { ids } = await this.cache.refresh(entity, {
data: projection as any,
filter: filters && combineFilters(filters as any),
sorter,
indexFrom: count && 0,
count,
});
assert(ids);
this.ids = ids;
this.indexFrom = 0;
this.hasMore = ids.length === count;
}
async nextPage() {
}
async prevPage() {
}
}
class SingleNode<ED extends EntityDict, AD extends Record<string, Aspect<ED>>, T extends keyof ED> extends Node<ED, AD, T>{
private id?: string;
private children: Partial<Record<keyof ED[T]['Schema'], Node<ED, AD, keyof ED>>>;
constructor(entity: T, projection: ED[T]['Selection']['data'], cache: Cache<ED, AD>, parent?: Node<ED, AD, keyof ED>, id?: string) {
super(entity, projection, cache, parent);
this.id = id;
this.children = {};
}
async refresh() {
const { entity, projection, id } = this;
assert (id);
await this.cache.refresh<T>(entity, {
data: projection,
filter: {
id,
},
} as ED[T]['Selection']); // 搞不懂为何这里过不去
}
async get() {
const { entity, projection, id } = this;
const row = id && this.cache.get<T>(entity, {
data: projection,
filter: {
id,
},
} as ED[T]['Selection']);
}
}

View File

@ -185,5 +185,6 @@ export async function initialize<
return {
subscribe,
action,
features,
};
}

View File

@ -2,6 +2,6 @@ import { Aspect } from "oak-domain/lib/types/Aspect";
import { EntityDict } from "oak-domain/lib/types/Entity";
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-domain/EntityDict';
export type AspectProxy<ED extends BaseEntityDict & EntityDict, AD extends Record<string, Aspect<ED>>> = {
export type AspectProxy<ED extends EntityDict, AD extends Record<string, Aspect<ED>>> = {
[K in keyof AD]: (p: Parameters<AD[K]>[0]) => ReturnType<AD[K]>;
};

View File

@ -6,7 +6,7 @@ import { aspectDict as basicAspectDict} from 'oak-general-business';
import { FrontContext } from '../FrontContext';
import { AspectProxy } from './AspectProxy';
export abstract class Feature<ED extends EntityDict & BaseEntityDict, AD extends Record<string, Aspect<ED>>> {
export abstract class Feature<ED extends EntityDict, AD extends Record<string, Aspect<ED>>> {
private aspectProxy?: AspectProxy<ED, AD & typeof basicAspectDict>;
private context?: FrontContext<ED>;