This commit is contained in:
pqcqaq 2024-10-11 22:32:56 +08:00
commit 12aeea8db6
9 changed files with 58 additions and 27 deletions

View File

@ -588,9 +588,17 @@ function outputFeatureIndex(dependencies, briefNames, sourceFile, printer, filen
importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("FeatureDict"), factory.createIdentifier(fdName))])), factory.createStringLiteral(dep), undefined)); importStatements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("FeatureDict"), factory.createIdentifier(fdName))])), factory.createStringLiteral(dep), undefined));
fdNames.push(fdName); fdNames.push(fdName);
}); });
const stmt4 = statements[4], stmt5 = statements[5]; let i = 0;
(0, assert_1.default)(ts.isImportDeclaration(stmt4) && ts.isFunctionDeclaration(stmt5)); while (true) {
const { name, parameters } = stmt5; const stmt = statements[i];
if (ts.isFunctionDeclaration(stmt)) {
break;
}
i++;
}
const stmt3 = statements[i - 1], stmt4 = statements[i];
(0, assert_1.default)(ts.isImportDeclaration(stmt3) && ts.isFunctionDeclaration(stmt4));
const { name, parameters } = stmt4;
(0, assert_1.default)(ts.isIdentifier(name) && name.text === 'create' && parameters.length === 1); (0, assert_1.default)(ts.isIdentifier(name) && name.text === 'create' && parameters.length === 1);
const [param] = parameters; const [param] = parameters;
const { name: paramName, type } = param; const { name: paramName, type } = param;
@ -604,9 +612,9 @@ function outputFeatureIndex(dependencies, briefNames, sourceFile, printer, filen
]) ])
}); });
statements2 = [ statements2 = [
...statements.slice(0, 5), ...statements.slice(0, i),
...importStatements, ...importStatements,
...statements.slice(5) ...statements.slice(i)
]; ];
if (isModule) { if (isModule) {
statements2.push(factory.createFunctionDeclaration([ statements2.push(factory.createFunctionDeclaration([
@ -756,7 +764,7 @@ function tryCopyModuleTemplateFiles(cwd, dependencies, briefNames, printer) {
const moduleTemplateDir = join(moduleDir, 'template'); const moduleTemplateDir = join(moduleDir, 'template');
if ((0, fs_1.existsSync)(moduleTemplateDir)) { if ((0, fs_1.existsSync)(moduleTemplateDir)) {
// data.ts中规定的初始化数据拷贝到data目录下并注入到data/index.ts // data.ts中规定的初始化数据拷贝到data目录下并注入到data/index.ts
const dataFile = join(moduleTemplateDir, 'data', 'data.ts'); const dataFile = join(moduleTemplateDir, 'data.ts');
if ((0, fs_1.existsSync)(dataFile)) { if ((0, fs_1.existsSync)(dataFile)) {
const prjDataFile = join(cwd, 'src', 'data', `${briefNames[idx]}Data.ts`); const prjDataFile = join(cwd, 'src', 'data', `${briefNames[idx]}Data.ts`);
if (!(0, fs_1.existsSync)(prjDataFile)) { if (!(0, fs_1.existsSync)(prjDataFile)) {

View File

@ -311,7 +311,7 @@ function createAttrUpdateCheckers(schema, attrUpdateMatrix) {
const checkers = []; const checkers = [];
for (const entity in attrUpdateMatrix) { for (const entity in attrUpdateMatrix) {
const matrix = attrUpdateMatrix[entity]; const matrix = attrUpdateMatrix[entity];
const updateAttrs = Object.keys(matrix); const updateAttrs = [types_1.UpdateAtAttribute, types_1.TriggerDataAttribute, types_1.TriggerUuidAttribute].concat(Object.keys(matrix));
const { actions } = schema[entity]; const { actions } = schema[entity];
const updateActions = actions.filter((a) => !action_1.readOnlyActions.concat(['create', 'remove']).includes(a)); const updateActions = actions.filter((a) => !action_1.readOnlyActions.concat(['create', 'remove']).includes(a));
/** /**
@ -328,7 +328,7 @@ function createAttrUpdateCheckers(schema, attrUpdateMatrix) {
throw new types_1.OakAttrCantUpdateException(entity, extras, '更新了不允许的属性'); throw new types_1.OakAttrCantUpdateException(entity, extras, '更新了不允许的属性');
} }
const condition = attrs.map(ele => matrix[ele]); const condition = attrs.map(ele => matrix[ele]);
const actions = condition.map(ele => ele.actions).filter(ele => !!ele); const actions = condition.map(ele => ele?.actions).filter(ele => !!ele);
const a = actions.length > 0 && (0, lodash_1.intersection)(actions.flat()); const a = actions.length > 0 && (0, lodash_1.intersection)(actions.flat());
if (a) { if (a) {
if (!a.includes(action)) { if (!a.includes(action)) {
@ -338,10 +338,10 @@ function createAttrUpdateCheckers(schema, attrUpdateMatrix) {
} }
} }
const filters = condition.map(ele => { const filters = condition.map(ele => {
if (typeof ele.filter === 'function') { if (typeof ele?.filter === 'function') {
return ele.filter(action || 'select'); return ele.filter(action || 'select');
} }
return ele.filter; return ele?.filter;
}).filter(ele => !!ele); }).filter(ele => !!ele);
const f = filters.length > 0 && (0, filter_1.combineFilters)(entity, schema, filters); const f = filters.length > 0 && (0, filter_1.combineFilters)(entity, schema, filters);
if (f) { if (f) {

View File

@ -148,7 +148,7 @@ class RelationAuth {
if (!entity2) { if (!entity2) {
entity2 = relations[0]?.entity; entity2 = relations[0]?.entity;
} }
else { else if (relations.length) {
(0, assert_1.default)(entity2 === relations[0]?.entity); (0, assert_1.default)(entity2 === relations[0]?.entity);
} }
return relations.map(ele => ele.id); return relations.map(ele => ele.id);
@ -156,6 +156,7 @@ class RelationAuth {
const relationIds = getRelationIds(); const relationIds = getRelationIds();
if (relationIds instanceof Promise) { if (relationIds instanceof Promise) {
return relationIds.then((ids) => { return relationIds.then((ids) => {
(0, assert_1.default)(ids.length > 0);
return Promise.all(ids.map(ele => checkOnRelationId(entity2, ele, entityFilter))).then((value) => { return Promise.all(ids.map(ele => checkOnRelationId(entity2, ele, entityFilter))).then((value) => {
if (intersection) { if (intersection) {
return !(value.includes(false)); return !(value.includes(false));
@ -164,6 +165,10 @@ class RelationAuth {
}); });
}); });
} }
if (relationIds.length === 0) {
// 如果没有relationId前端cache中直接返回false
return false;
}
const value = relationIds.map(ele => checkOnRelationId(entity2, ele, entityFilter)); const value = relationIds.map(ele => checkOnRelationId(entity2, ele, entityFilter));
if (intersection) { if (intersection) {
return !(value.includes(false)); return !(value.includes(false));

2
lib/types/Sync.d.ts vendored
View File

@ -38,6 +38,8 @@ export interface PushEntityDef<ED extends EntityDict & BaseEntityDict, T extends
* *
*/ */
onSynchronized?: (result: { onSynchronized?: (result: {
remoteEntity: keyof ED;
remoteEntityId: string;
action: ED[T]['Action']; action: ED[T]['Action'];
data: ED[T]['Operation']['data']; data: ED[T]['Operation']['data'];
rowIds: string[]; rowIds: string[];

View File

@ -1,6 +1,6 @@
{ {
"name": "oak-domain", "name": "oak-domain",
"version": "5.1.2", "version": "5.1.5",
"author": { "author": {
"name": "XuChang" "name": "XuChang"
}, },

View File

@ -1108,9 +1108,17 @@ function outputFeatureIndex(
} }
); );
const stmt4 = statements[4], stmt5 = statements[5]; let i = 0;
assert(ts.isImportDeclaration(stmt4) && ts.isFunctionDeclaration(stmt5)); while (true) {
const { name, parameters } = stmt5; const stmt = statements[i];
if (ts.isFunctionDeclaration(stmt)) {
break;
}
i ++;
}
const stmt3 = statements[i-1], stmt4 = statements[i];
assert(ts.isImportDeclaration(stmt3) && ts.isFunctionDeclaration(stmt4));
const { name, parameters } = stmt4;
assert(ts.isIdentifier(name!) && name.text === 'create' && parameters.length === 1); assert(ts.isIdentifier(name!) && name.text === 'create' && parameters.length === 1);
const [param] = parameters; const [param] = parameters;
const { name: paramName, type } = param; const { name: paramName, type } = param;
@ -1127,9 +1135,9 @@ function outputFeatureIndex(
}); });
statements2 = [ statements2 = [
...statements.slice(0, 5), ...statements.slice(0, i),
...importStatements, ...importStatements,
...statements.slice(5) ...statements.slice(i)
]; ];
if (isModule) { if (isModule) {
statements2.push( statements2.push(
@ -1442,7 +1450,7 @@ function tryCopyModuleTemplateFiles(
const moduleTemplateDir = join(moduleDir, 'template'); const moduleTemplateDir = join(moduleDir, 'template');
if (existsSync(moduleTemplateDir)) { if (existsSync(moduleTemplateDir)) {
// data.ts中规定的初始化数据拷贝到data目录下并注入到data/index.ts // data.ts中规定的初始化数据拷贝到data目录下并注入到data/index.ts
const dataFile = join(moduleTemplateDir, 'data', 'data.ts'); const dataFile = join(moduleTemplateDir, 'data.ts');
if (existsSync(dataFile)) { if (existsSync(dataFile)) {
const prjDataFile = join(cwd, 'src', 'data', `${briefNames[idx]}Data.ts`); const prjDataFile = join(cwd, 'src', 'data', `${briefNames[idx]}Data.ts`);
if (!existsSync(prjDataFile)) { if (!existsSync(prjDataFile)) {

View File

@ -1,4 +1,4 @@
import { ActionDefDict, Checker, EntityDict, StorageSchema, RowChecker, OakUniqueViolationException, CHECKER_MAX_PRIORITY, AttrUpdateMatrix, LogicalChecker, OakAttrCantUpdateException } from "../types"; import { ActionDefDict, Checker, EntityDict, StorageSchema, RowChecker, OakUniqueViolationException, CHECKER_MAX_PRIORITY, AttrUpdateMatrix, LogicalChecker, OakAttrCantUpdateException, UpdateAtAttribute, TriggerDataAttribute, TriggerUuidAttribute } from "../types";
import { SyncContext } from "./SyncRowStore"; import { SyncContext } from "./SyncRowStore";
import { AsyncContext } from "./AsyncRowStore"; import { AsyncContext } from "./AsyncRowStore";
import { pick, intersection, difference, omit } from '../utils/lodash'; import { pick, intersection, difference, omit } from '../utils/lodash';
@ -380,7 +380,7 @@ function createAttrUpdateCheckers<ED extends EntityDict & BaseEntityDict, Cxt ex
const checkers: Checker<ED, keyof ED, Cxt | FrontCxt>[] = []; const checkers: Checker<ED, keyof ED, Cxt | FrontCxt>[] = [];
for (const entity in attrUpdateMatrix) { for (const entity in attrUpdateMatrix) {
const matrix = attrUpdateMatrix[entity]!; const matrix = attrUpdateMatrix[entity]!;
const updateAttrs = Object.keys(matrix) as string[]; const updateAttrs = [UpdateAtAttribute, TriggerDataAttribute, TriggerUuidAttribute].concat(Object.keys(matrix));
const { actions } = schema[entity]; const { actions } = schema[entity];
const updateActions = actions.filter( const updateActions = actions.filter(
(a) => !readOnlyActions.concat(['create', 'remove']).includes(a) (a) => !readOnlyActions.concat(['create', 'remove']).includes(a)
@ -400,7 +400,7 @@ function createAttrUpdateCheckers<ED extends EntityDict & BaseEntityDict, Cxt ex
throw new OakAttrCantUpdateException(entity, extras, '更新了不允许的属性'); throw new OakAttrCantUpdateException(entity, extras, '更新了不允许的属性');
} }
const condition = attrs.map(ele => matrix[ele]!); const condition = attrs.map(ele => matrix[ele]!);
const actions = condition.map(ele => ele.actions).filter(ele => !!ele); const actions = condition.map(ele => ele?.actions).filter(ele => !!ele);
const a = actions.length > 0 && intersection(actions.flat()); const a = actions.length > 0 && intersection(actions.flat());
if (a) { if (a) {
if (!a.includes(action)) { if (!a.includes(action)) {
@ -412,10 +412,10 @@ function createAttrUpdateCheckers<ED extends EntityDict & BaseEntityDict, Cxt ex
} }
} }
const filters = condition.map(ele => { const filters = condition.map(ele => {
if (typeof ele.filter === 'function') { if (typeof ele?.filter === 'function') {
return ele.filter(action || 'select'); return ele.filter(action || 'select');
} }
return ele.filter; return ele?.filter;
}).filter(ele => !!ele); }).filter(ele => !!ele);
const f = filters.length > 0 && combineFilters(entity, schema, filters); const f = filters.length > 0 && combineFilters(entity, schema, filters);
if (f) { if (f) {

View File

@ -217,7 +217,7 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict> {
if (!entity2) { if (!entity2) {
entity2 = relations[0]?.entity; entity2 = relations[0]?.entity;
} }
else { else if (relations.length) {
assert(entity2 === relations[0]?.entity); assert(entity2 === relations[0]?.entity);
} }
return relations.map(ele => ele.id!); return relations.map(ele => ele.id!);
@ -227,6 +227,7 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict> {
if (relationIds instanceof Promise) { if (relationIds instanceof Promise) {
return relationIds.then( return relationIds.then(
(ids) => { (ids) => {
assert(ids.length > 0);
return Promise.all( return Promise.all(
ids.map( ids.map(
ele => checkOnRelationId(entity2!, ele, entityFilter) ele => checkOnRelationId(entity2!, ele, entityFilter)
@ -242,6 +243,11 @@ export class RelationAuth<ED extends EntityDict & BaseEntityDict> {
} }
); );
} }
if (relationIds.length === 0) {
// 如果没有relationId前端cache中直接返回false
return false;
}
const value = relationIds.map(ele => checkOnRelationId(entity2!, ele, entityFilter)) as boolean[]; const value = relationIds.map(ele => checkOnRelationId(entity2!, ele, entityFilter)) as boolean[];
if (intersection) { if (intersection) {
return !(value.includes(false)); return !(value.includes(false));

View File

@ -47,6 +47,8 @@ export interface PushEntityDef<ED extends EntityDict & BaseEntityDict, T extends
* *
*/ */
onSynchronized?: (result: { onSynchronized?: (result: {
remoteEntity: keyof ED;
remoteEntityId: string;
action: ED[T]['Action'], action: ED[T]['Action'],
data: ED[T]['Operation']['data']; data: ED[T]['Operation']['data'];
rowIds: string[]; rowIds: string[];
@ -57,10 +59,10 @@ export interface PushEntityDef<ED extends EntityDict & BaseEntityDict, T extends
export interface SyncRemoteConfigBase<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> { export interface SyncRemoteConfigBase<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> {
entity: keyof ED; // 对方结点所关联的entity名称两边一致 entity: keyof ED; // 对方结点所关联的entity名称两边一致
endpoint?: string; // 对方结点同步数据的endpoint默认为/sync/:entity endpoint?: string; // 对方结点同步数据的endpoint默认为/sync/:entity
pathToUser?: string; // entity到对应remote user的路径如果remote user和enitity之间是relation关系则为空 pathToUser?: string; // entity到对应remote user的路径如果remote user和entity之间是relation关系则为空
relationName?: string; // 如果remote user和entity之间是relation关系此处表达的是relation名称 relationName?: string; // 如果remote user和entity之间是relation关系此处表达的是relation名称
pushEntities?: Array<PushEntityDef<ED, keyof ED, Cxt>>; // 在这个entity上需要同步的entities pushEntities?: Array<PushEntityDef<ED, keyof ED, Cxt>>; // 在这个entity上需要同步的entities
pullEntities?: Array<PullEntityDef<ED, keyof ED, Cxt>>; // 从这个entity上可能会接收到的同步entites pullEntities?: Array<PullEntityDef<ED, keyof ED, Cxt>>; // 从这个entity上可能会接收到的同步entities
}; };
export interface SyncRemoteConfig<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> extends SyncRemoteConfigBase<ED, Cxt> { export interface SyncRemoteConfig<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> extends SyncRemoteConfigBase<ED, Cxt> {