Merge branch 'release'
This commit is contained in:
commit
f9aa003f1a
|
|
@ -54,9 +54,23 @@ class LocaleBuilder {
|
|||
const statements = [
|
||||
factory.createImportDeclaration(undefined, factory.createImportClause(false, undefined, factory.createNamedImports([factory.createImportSpecifier(false, factory.createIdentifier("CreateOperationData"), factory.createIdentifier("I18n"))])), factory.createStringLiteral("../oak-app-domain/I18n/Schema"), undefined)
|
||||
];
|
||||
if (this.dependencies) {
|
||||
this.dependencies.forEach((ele, idx) => statements.push(factory.createImportDeclaration(undefined, factory.createImportClause(false, factory.createIdentifier(`i18ns${idx}`), undefined), factory.createStringLiteral(`${ele}/lib/data/i18n`), undefined)));
|
||||
}
|
||||
// 改为在初始化时合并
|
||||
/* if (this.dependencies) {
|
||||
this.dependencies.forEach(
|
||||
(ele, idx) => statements.push(
|
||||
factory.createImportDeclaration(
|
||||
undefined,
|
||||
factory.createImportClause(
|
||||
false,
|
||||
factory.createIdentifier(`i18ns${idx}`),
|
||||
undefined
|
||||
),
|
||||
factory.createStringLiteral(`${ele}/lib/data/i18n`),
|
||||
undefined
|
||||
)
|
||||
)
|
||||
)
|
||||
} */
|
||||
statements.push(factory.createVariableStatement(undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(factory.createIdentifier("i18ns"), undefined, factory.createArrayTypeNode(factory.createTypeReferenceNode(factory.createIdentifier("I18n"), undefined)), factory.createArrayLiteralExpression(Object.keys(this.locales).map((k) => {
|
||||
const [module, position, language, data] = this.locales[k];
|
||||
// 用哈希计算来保证id唯一性
|
||||
|
|
@ -73,12 +87,27 @@ class LocaleBuilder {
|
|||
factory.createPropertyAssignment(factory.createIdentifier("data"), transferObjectToObjectLiteral(data))
|
||||
], true);
|
||||
}), true))], ts.NodeFlags.Const)));
|
||||
if (this.dependencies.length > 0) {
|
||||
statements.push(factory.createExportAssignment(undefined, undefined, factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("i18ns"), factory.createIdentifier("concat")), undefined, this.dependencies.map((ele, idx) => factory.createIdentifier(`i18ns${idx}`)))));
|
||||
}
|
||||
else {
|
||||
statements.push(factory.createExportAssignment(undefined, undefined, factory.createIdentifier("i18ns")));
|
||||
/* if (this.dependencies.length > 0) {
|
||||
statements.push(
|
||||
factory.createExportAssignment(
|
||||
undefined,
|
||||
undefined,
|
||||
factory.createCallExpression(
|
||||
factory.createPropertyAccessExpression(
|
||||
factory.createIdentifier("i18ns"),
|
||||
factory.createIdentifier("concat")
|
||||
),
|
||||
undefined,
|
||||
this.dependencies.map(
|
||||
(ele, idx) => factory.createIdentifier(`i18ns${idx}`)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
else { */
|
||||
statements.push(factory.createExportAssignment(undefined, undefined, factory.createIdentifier("i18ns")));
|
||||
/* } */
|
||||
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
||||
const result = printer.printList(ts.ListFormat.SourceFileStatements, factory.createNodeArray(statements), ts.createSourceFile("someFileName.ts", "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS));
|
||||
const filename = (0, path_1.join)(this.pwd, 'src', 'data', 'i18n.ts');
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
export declare function buildRouter(projectDir: string, startupDir: string, watch?: boolean): void;
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.buildRouter = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const path_1 = require("path");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const assert_1 = tslib_1.__importDefault(require("assert"));
|
||||
const ts = tslib_1.__importStar(require("typescript"));
|
||||
const node_watch_1 = tslib_1.__importDefault(require("node-watch"));
|
||||
const { factory } = ts;
|
||||
const NameSpaceDescDict = {};
|
||||
function checkPageDir(dir, relativePath, ns, type) {
|
||||
let changed = false;
|
||||
const { pages } = NameSpaceDescDict[ns];
|
||||
const subdirs = [];
|
||||
const files = (0, fs_extra_1.readdirSync)(dir);
|
||||
files.forEach((file) => {
|
||||
const filepath = (0, path_1.join)(dir, file);
|
||||
const stat = (0, fs_extra_1.statSync)(filepath);
|
||||
if (stat.isFile() &&
|
||||
['web.tsx', 'web.pc.tsx', 'render.native.tsx', 'render.ios.tsx', 'render.android.tsx', 'index.xml'].includes(file)) {
|
||||
if (!pages.hasOwnProperty(dir)) {
|
||||
const indexJsonFile = (0, path_1.join)(dir, 'index.json');
|
||||
let oakDisablePulldownRefresh = false;
|
||||
if ((0, fs_extra_1.existsSync)(indexJsonFile)) {
|
||||
const { enablePullDownRefresh = true, } = require(indexJsonFile);
|
||||
oakDisablePulldownRefresh =
|
||||
!enablePullDownRefresh;
|
||||
}
|
||||
pages[dir] = {
|
||||
path: relativePath.replace(/\\/g, '/'),
|
||||
oakDisablePulldownRefresh,
|
||||
hasNative: ['render.native.tsx', 'render.ios.tsx', 'render.android.tsx'].includes(file),
|
||||
hasWeb: ['web.tsx', 'web.pc.tsx'].includes(file),
|
||||
hasWechatMp: file === 'index.xml',
|
||||
};
|
||||
changed = true;
|
||||
}
|
||||
else {
|
||||
if (['render.native.tsx', 'render.ios.tsx', 'render.android.tsx'].includes(file) && type === 'native') {
|
||||
if (pages[dir].hasNative === false) {
|
||||
pages[dir].hasNative = true;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else if (['web.tsx', 'web.pc.tsx'].includes(file) && type === 'web') {
|
||||
if (pages[dir].hasWeb === false) {
|
||||
pages[dir].hasWeb = true;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pages[dir].hasWechatMp === false && type === 'wechatMp') {
|
||||
pages[dir].hasWechatMp = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (stat.isDirectory()) {
|
||||
subdirs.push(file);
|
||||
}
|
||||
});
|
||||
return {
|
||||
subdirs,
|
||||
changed,
|
||||
};
|
||||
}
|
||||
function traverseNsDir(nsDir, ns, type) {
|
||||
NameSpaceDescDict[ns] = {
|
||||
pages: {}
|
||||
};
|
||||
const { pages } = NameSpaceDescDict[ns];
|
||||
const traverse = (dir, relativePath) => {
|
||||
const { subdirs } = checkPageDir(dir, relativePath, ns, type);
|
||||
subdirs.forEach((subdir) => {
|
||||
const dir2 = (0, path_1.join)(dir, subdir);
|
||||
const relativePath2 = (0, path_1.join)(relativePath, subdir);
|
||||
traverse(dir2, relativePath2);
|
||||
});
|
||||
};
|
||||
traverse(nsDir, '');
|
||||
}
|
||||
function traversePageDir(projectDir, type) {
|
||||
const pageDir = (0, path_1.join)(projectDir, 'src', 'pages');
|
||||
const namespaces = (0, fs_extra_1.readdirSync)(pageDir);
|
||||
namespaces.forEach((ns) => {
|
||||
const nsDir = (0, path_1.join)(pageDir, ns);
|
||||
const stat = (0, fs_extra_1.statSync)(nsDir);
|
||||
if (stat.isDirectory()) {
|
||||
traverseNsDir(nsDir, ns, type);
|
||||
}
|
||||
});
|
||||
}
|
||||
function makeWebAllRouters(namespaceDir, projectDir, routerFileDir) {
|
||||
const nss = (0, fs_extra_1.readdirSync)(namespaceDir);
|
||||
return factory.createArrayLiteralExpression(nss.map((ns) => {
|
||||
(0, assert_1.default)(NameSpaceDescDict[ns], `${ns}在pages下没有对应的目录`);
|
||||
const { pages } = NameSpaceDescDict[ns];
|
||||
const nsIndexJsonFile = (0, path_1.join)(namespaceDir, ns, 'index.json');
|
||||
let path2 = `/${ns}`;
|
||||
let notFound2 = '', first2 = '';
|
||||
if ((0, fs_extra_1.existsSync)(nsIndexJsonFile)) {
|
||||
const { path, notFound, first } = require(nsIndexJsonFile);
|
||||
if (path) {
|
||||
path2 = path.replace(/\\/g, '/');
|
||||
}
|
||||
if (notFound) {
|
||||
notFound2 = notFound.replace(/\\/g, '/');
|
||||
}
|
||||
if (first) {
|
||||
first2 = first.replace(/\\/g, '/');
|
||||
if (first2.startsWith('/')) {
|
||||
first2 = first2.slice(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
const children = Object.values(pages).filter((ele) => ele.hasWeb).map(({ path, oakDisablePulldownRefresh }) => {
|
||||
const properties = [
|
||||
factory.createPropertyAssignment('path', factory.createStringLiteral(path)),
|
||||
factory.createPropertyAssignment('namespace', factory.createStringLiteral(path2)),
|
||||
factory.createPropertyAssignment('meta', factory.createObjectLiteralExpression([
|
||||
factory.createPropertyAssignment('oakDisablePulldownRefresh', oakDisablePulldownRefresh ? factory.createTrue() : factory.createFalse())
|
||||
])),
|
||||
factory.createPropertyAssignment(factory.createIdentifier("Component"), factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("React"), factory.createIdentifier("lazy")), undefined, [factory.createArrowFunction(undefined, undefined, [], undefined, factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), factory.createCallExpression(factory.createIdentifier('import'), undefined, [
|
||||
factory.createStringLiteral((0, path_1.relative)(routerFileDir, (0, path_1.join)(projectDir, 'src', 'pages', ns, path)).replace(/\\/g, '/'))
|
||||
]))]))
|
||||
];
|
||||
if (first2 === path) {
|
||||
properties.push(factory.createPropertyAssignment('isFirst', factory.createTrue()));
|
||||
}
|
||||
return factory.createObjectLiteralExpression(properties, true);
|
||||
});
|
||||
if (notFound2) {
|
||||
children.push(factory.createObjectLiteralExpression([
|
||||
factory.createPropertyAssignment('path', factory.createStringLiteral('*')),
|
||||
factory.createPropertyAssignment('namespace', factory.createStringLiteral(path2)),
|
||||
factory.createPropertyAssignment(factory.createIdentifier("Component"), factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("React"), factory.createIdentifier("lazy")), undefined, [factory.createArrowFunction(undefined, undefined, [], undefined, factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), factory.createCallExpression(factory.createIdentifier('import'), undefined, [
|
||||
factory.createStringLiteral((0, path_1.relative)(routerFileDir, (0, path_1.join)(projectDir, 'src', 'pages', ns, notFound2)).replace(/\\/g, '/'))
|
||||
]))]))
|
||||
], true));
|
||||
}
|
||||
return factory.createObjectLiteralExpression([
|
||||
factory.createPropertyAssignment('path', factory.createStringLiteral(path2)),
|
||||
factory.createPropertyAssignment('namespace', factory.createStringLiteral(path2)),
|
||||
factory.createPropertyAssignment(factory.createIdentifier("Component"), factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("React"), factory.createIdentifier("lazy")), undefined, [factory.createArrowFunction(undefined, undefined, [], undefined, factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), factory.createCallExpression(factory.createIdentifier('import'), undefined, [
|
||||
factory.createStringLiteral((0, path_1.relative)(routerFileDir, (0, path_1.join)(namespaceDir, ns)).replace(/\\/g, '/'))
|
||||
]))])),
|
||||
factory.createPropertyAssignment('children', factory.createArrayLiteralExpression(children))
|
||||
], true);
|
||||
}), true);
|
||||
}
|
||||
function judgeUseOakRouterBuilder(statements) {
|
||||
const stmt = statements[0];
|
||||
return ts.isExpressionStatement(stmt) && ts.isStringLiteral(stmt.expression) && stmt.expression.text === 'use oak router builder';
|
||||
}
|
||||
function outputInWebAppDir(appDir) {
|
||||
const routerFileName = (0, path_1.join)(appDir, 'router', 'allRouters.ts');
|
||||
if ((0, fs_extra_1.existsSync)(routerFileName)) {
|
||||
const program = ts.createProgram([routerFileName], {
|
||||
removeComments: false,
|
||||
});
|
||||
const routerFile = program.getSourceFile(routerFileName);
|
||||
(0, assert_1.default)(routerFile);
|
||||
const namespaceDir = (0, path_1.join)(appDir, 'namespaces');
|
||||
const { statements } = routerFile;
|
||||
if (judgeUseOakRouterBuilder(statements)) {
|
||||
statements.forEach((statement) => {
|
||||
if (ts.isVariableStatement(statement)) {
|
||||
const declaration = statement.declarationList.declarations.find(declaration => ts.isIdentifier(declaration.name) && declaration.name.text === 'allRouters');
|
||||
if (declaration) {
|
||||
Object.assign(declaration, {
|
||||
initializer: makeWebAllRouters(namespaceDir, (0, path_1.join)(appDir, '../../../..'), (0, path_1.dirname)(routerFileName))
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed, removeComments: false });
|
||||
const result = printer.printNode(ts.EmitHint.Unspecified, routerFile, routerFile);
|
||||
(0, fs_extra_1.writeFileSync)(routerFileName, result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.warn(`${appDir}的目录结构未按照标准建立,缺少了${routerFileName}`);
|
||||
}
|
||||
}
|
||||
function outputInWebDir(dir) {
|
||||
const srcAppDir = (0, path_1.join)(dir, 'src', 'app');
|
||||
const apps = (0, fs_extra_1.readdirSync)(srcAppDir);
|
||||
apps.forEach((app) => {
|
||||
const appDir = (0, path_1.join)(srcAppDir, app);
|
||||
const stat = (0, fs_extra_1.statSync)(appDir);
|
||||
if (stat.isDirectory()) {
|
||||
outputInWebAppDir(appDir);
|
||||
}
|
||||
});
|
||||
}
|
||||
function watchDir(projectDir, startupDir, type) {
|
||||
const srcPageDir = (0, path_1.join)(projectDir, 'src', 'pages');
|
||||
console.log('watch dir ', srcPageDir);
|
||||
if (startupDir.startsWith('web')) {
|
||||
const srcAppDir = (0, path_1.join)(projectDir, startupDir, 'src', 'app');
|
||||
const apps = (0, fs_extra_1.readdirSync)(srcAppDir);
|
||||
const tryOutputAppDir = (ns) => {
|
||||
apps.forEach((app) => {
|
||||
const appDir = (0, path_1.join)(srcAppDir, app);
|
||||
const namespaceDir = (0, path_1.join)(appDir, 'namespaces');
|
||||
const namespaces = (0, fs_extra_1.readdirSync)(namespaceDir);
|
||||
if (namespaces.includes(ns)) {
|
||||
outputInWebAppDir(appDir);
|
||||
}
|
||||
});
|
||||
};
|
||||
(0, node_watch_1.default)(srcPageDir, {
|
||||
recursive: true,
|
||||
filter: new RegExp('web\.tsx|web\.pc\.tsx|index\.xml|render\.(native|ios|android)\.tsx'),
|
||||
}, (evt, filepath) => {
|
||||
const dir = (0, path_1.dirname)(filepath);
|
||||
const relativeDir = (0, path_1.relative)((0, path_1.join)(projectDir, 'src', 'pages'), filepath);
|
||||
const ns = relativeDir.split('\\')[0];
|
||||
const relativePath = (0, path_1.relative)(ns, (0, path_1.dirname)(relativeDir));
|
||||
const { pages } = NameSpaceDescDict[ns];
|
||||
console.log(filepath, dir, ns);
|
||||
if (evt === 'remove') {
|
||||
if ((0, fs_extra_1.existsSync)(dir)) {
|
||||
const { changed } = checkPageDir(dir, relativePath, ns, type);
|
||||
if (changed) {
|
||||
tryOutputAppDir(ns);
|
||||
}
|
||||
}
|
||||
else {
|
||||
delete pages[dir];
|
||||
tryOutputAppDir(ns);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const { changed } = checkPageDir(dir, relativePath, ns, type);
|
||||
if (changed) {
|
||||
tryOutputAppDir(ns);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
function buildRouter(projectDir, startupDir, watch) {
|
||||
const type = startupDir.startsWith('web') ? 'web' : (startupDir.startsWith('native') ? 'native' : 'wechatMp');
|
||||
traversePageDir(projectDir, type);
|
||||
const subDir = (0, fs_extra_1.readdirSync)(projectDir);
|
||||
(0, assert_1.default)(subDir.includes(startupDir));
|
||||
if (startupDir.startsWith('web')) {
|
||||
outputInWebDir((0, path_1.join)(projectDir, startupDir));
|
||||
}
|
||||
// todo native
|
||||
if (watch) {
|
||||
watchDir(projectDir, startupDir, type);
|
||||
}
|
||||
}
|
||||
exports.buildRouter = buildRouter;
|
||||
|
|
@ -18,9 +18,10 @@ export declare abstract class CascadeStore<ED extends EntityDict & BaseEntityDic
|
|||
registerOperationRewriter(rewriter: OperationRewriter<ED, AsyncContext<ED> | SyncContext<ED>, OperateOption>): void;
|
||||
registerSelectionRewriter(rewriter: SelectionRewriter<ED, AsyncContext<ED> | SyncContext<ED>, SelectOption>): void;
|
||||
protected abstract selectAbjointRow<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Partial<ED[T]['Schema']>[];
|
||||
protected abstract countAbjointRow<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, selection: Pick<ED[T]['Selection'], 'filter' | 'count'>, context: Cxt, option: OP): number;
|
||||
protected abstract countAbjointRowAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, selection: Pick<ED[T]['Selection'], 'filter' | 'count'>, context: Cxt, option: OP): Promise<number>;
|
||||
protected abstract updateAbjointRow<T extends keyof ED, OP extends OperateOption, Cxt extends SyncContext<ED>>(entity: T, operation: ED[T]['Operation'], context: Cxt, option: OP): number;
|
||||
protected abstract selectAbjointRowAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Promise<Partial<ED[T]['Schema']>[]>;
|
||||
protected abstract countAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, selection: Pick<ED[T]['Selection'], 'filter' | 'count'>, context: Cxt, option: OP): Promise<number>;
|
||||
protected abstract updateAbjointRowAsync<T extends keyof ED, OP extends OperateOption, Cxt extends AsyncContext<ED>>(entity: T, operation: ED[T]['Create'] | ED[T]['Update'] | ED[T]['Remove'], context: Cxt, option: OP): Promise<number>;
|
||||
protected abstract aggregateAbjointRowSync<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, aggregation: ED[T]['Aggregation'], context: Cxt, option: OP): AggregationResult<ED[T]['Schema']>;
|
||||
protected abstract aggregateAbjointRowAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, aggregation: ED[T]['Aggregation'], context: Cxt, option: OP): Promise<AggregationResult<ED[T]['Schema']>>;
|
||||
|
|
@ -103,4 +104,6 @@ export declare abstract class CascadeStore<ED extends EntityDict & BaseEntityDic
|
|||
protected selectSync<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Partial<ED[T]['Schema']>[];
|
||||
protected operateSync<T extends keyof ED, Cxt extends SyncContext<ED>, OP extends OperateOption>(entity: T, operation: ED[T]['Operation'], context: Cxt, option: OP): OperationResult<ED>;
|
||||
protected operateAsync<T extends keyof ED, Cxt extends AsyncContext<ED>, OP extends OperateOption>(entity: T, operation: ED[T]['Operation'], context: Cxt, option: OP): Promise<OperationResult<ED>>;
|
||||
protected countSync<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, selection: Pick<ED[T]['Selection'], 'filter' | 'count'>, context: Cxt, option: OP): number;
|
||||
protected countAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(entity: T, selection: Pick<ED[T]['Selection'], 'filter' | 'count'>, context: Cxt, option: OP): Promise<number>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class CascadeStore extends RowStore_1.RowStore {
|
|||
this.reinforceSelectionInner(entity, selection, context);
|
||||
}
|
||||
this.selectionRewriters.forEach(ele => {
|
||||
const result = ele(this.getSchema(), entity, selection, context, option);
|
||||
const result = ele(this.getSchema(), entity, selection, context, option, isAggr);
|
||||
(0, assert_1.default)(!(result instanceof Promise));
|
||||
});
|
||||
}
|
||||
|
|
@ -1736,5 +1736,13 @@ class CascadeStore extends RowStore_1.RowStore {
|
|||
await this.reinforceOperation(entity, operation, context, option);
|
||||
return this.cascadeUpdateAsync(entity, operation, context, option);
|
||||
}
|
||||
countSync(entity, selection, context, option) {
|
||||
this.reinforceSelectionSync(entity, selection, context, option, true); // 这样写可能有问题的,虽然能跳过本地的projection补全,但如果有更多的selectionRewriter注入可能会出问题。by Xc 20231220
|
||||
return this.countAbjointRow(entity, selection, context, option);
|
||||
}
|
||||
countAsync(entity, selection, context, option) {
|
||||
this.reinforceSelectionAsync(entity, selection, context, option, true); // 这样写可能有问题的,虽然能跳过本地的projection补全,但如果有更多的selectionRewriter注入可能会出问题。by Xc 20231220
|
||||
return this.countAbjointRowAsync(entity, selection, context, option);
|
||||
}
|
||||
}
|
||||
exports.CascadeStore = CascadeStore;
|
||||
|
|
|
|||
|
|
@ -452,7 +452,7 @@ class TriggerExecutor {
|
|||
const rs = grouped[uuid];
|
||||
const { [Entity_1.TriggerDataAttribute]: triggerData } = rs[0];
|
||||
const { name, cxtStr, option } = triggerData;
|
||||
await context.initialize(JSON.parse(cxtStr));
|
||||
// await context.initialize(JSON.parse(cxtStr)); // 这里token有可能过期(用户注销),先用root态模拟吧
|
||||
await this.execVolatileTrigger(entity, name, rs.map(ele => ele.id), context, option);
|
||||
}
|
||||
await context.commit();
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ function makeIntrinsicCTWs(schema, actionDefDict) {
|
|||
action: 'create',
|
||||
type: 'data',
|
||||
entity,
|
||||
priority: 10,
|
||||
priority: 10, // 优先级要高,先于真正的data检查进行
|
||||
checker: (data) => {
|
||||
if (data instanceof Array) {
|
||||
data.forEach(ele => {
|
||||
|
|
@ -181,7 +181,7 @@ function makeIntrinsicCTWs(schema, actionDefDict) {
|
|||
entity,
|
||||
action: 'create',
|
||||
type: 'logicalData',
|
||||
priority: types_1.CHECKER_MAX_PRIORITY,
|
||||
priority: types_1.CHECKER_MAX_PRIORITY, // 优先级要放在最低,所有前置的checker/trigger将数据完整之后再在这里检测
|
||||
checker: (operation, context) => {
|
||||
const { data } = operation;
|
||||
if (data instanceof Array) {
|
||||
|
|
@ -197,9 +197,9 @@ function makeIntrinsicCTWs(schema, actionDefDict) {
|
|||
}
|
||||
}, {
|
||||
entity,
|
||||
action: 'update',
|
||||
action: 'update', // 只检查update,其它状态转换的action应该不会涉及unique约束的属性
|
||||
type: 'logicalData',
|
||||
priority: types_1.CHECKER_MAX_PRIORITY,
|
||||
priority: types_1.CHECKER_MAX_PRIORITY, // 优先级要放在最低,所有前置的checker/trigger将数据完整之后再在这里检测
|
||||
checker: (operation, context) => {
|
||||
const { data, filter: operationFilter } = operation;
|
||||
if (data) {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class SimpleConnector {
|
|||
}
|
||||
catch (err) {
|
||||
// fetch返回异常一定是网络异常
|
||||
throw new types_1.OakNetworkException();
|
||||
throw new types_1.OakNetworkException(`请求[${this.serverAspectUrl}],发生网络异常`);
|
||||
}
|
||||
if (response.status > 299) {
|
||||
const err = new types_1.OakServerProxyException(`网络请求返回status是${response.status}`);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference types="node" />
|
||||
/**
|
||||
* 防止assert打包体积过大,从这里引用
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "oak-domain",
|
||||
"version": "4.0.1",
|
||||
"version": "4.0.2",
|
||||
"author": {
|
||||
"name": "XuChang"
|
||||
},
|
||||
|
|
@ -37,6 +37,7 @@
|
|||
"fs-extra": "^10.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mocha": "^8.2.1",
|
||||
"node-watch": "^0.7.4",
|
||||
"ts-node": "^10.9.1",
|
||||
"tslib": "^2.4.0",
|
||||
"typescript": "^5.2.2"
|
||||
|
|
|
|||
|
|
@ -80,7 +80,8 @@ export default class LocaleBuilder {
|
|||
)
|
||||
];
|
||||
|
||||
if (this.dependencies) {
|
||||
// 改为在初始化时合并
|
||||
/* if (this.dependencies) {
|
||||
this.dependencies.forEach(
|
||||
(ele, idx) => statements.push(
|
||||
factory.createImportDeclaration(
|
||||
|
|
@ -95,7 +96,7 @@ export default class LocaleBuilder {
|
|||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
} */
|
||||
|
||||
statements.push(
|
||||
factory.createVariableStatement(
|
||||
|
|
@ -159,7 +160,7 @@ export default class LocaleBuilder {
|
|||
),
|
||||
);
|
||||
|
||||
if (this.dependencies.length > 0) {
|
||||
/* if (this.dependencies.length > 0) {
|
||||
statements.push(
|
||||
factory.createExportAssignment(
|
||||
undefined,
|
||||
|
|
@ -177,7 +178,7 @@ export default class LocaleBuilder {
|
|||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
else { */
|
||||
statements.push(
|
||||
factory.createExportAssignment(
|
||||
undefined,
|
||||
|
|
@ -185,7 +186,7 @@ export default class LocaleBuilder {
|
|||
factory.createIdentifier("i18ns")
|
||||
)
|
||||
);
|
||||
}
|
||||
/* } */
|
||||
|
||||
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
||||
const result = printer.printList(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,469 @@
|
|||
import { join, relative, dirname } from 'path';
|
||||
import { readdirSync, statSync, existsSync, writeFileSync } from 'fs-extra';
|
||||
import assert from 'assert';
|
||||
import * as ts from 'typescript';
|
||||
import NodeWatch from 'node-watch';
|
||||
const { factory } = ts;
|
||||
|
||||
/**
|
||||
* 一个项目,根据其pages下的目录结构,构建出web/native工程下的router以及pageMap
|
||||
* wechatMp暂不处理
|
||||
* 项目目录结构应为:
|
||||
*
|
||||
* -src
|
||||
* --pages
|
||||
* ---${namespace1}
|
||||
* -----${page1}
|
||||
* -------${subPage1.1}
|
||||
* -------${subPage1.2}
|
||||
* -----${page2}
|
||||
* ---${namespace2}
|
||||
* -----${page3}
|
||||
*
|
||||
* -web
|
||||
* --src
|
||||
* ---${appName}
|
||||
* -----namespaces
|
||||
* -------${namespace1}
|
||||
* ---------index.json (此namespace下的配置)
|
||||
* ---------pageMap.json (编译器将pageMap注入到这里)
|
||||
* -------${namespace2}
|
||||
* -----router
|
||||
* ---------index.ts (编译器将router.ts注入到这里)
|
||||
*
|
||||
* -native
|
||||
* --namspaces
|
||||
* ----${namespace1}
|
||||
* -------index.json (此namespace下的配置)
|
||||
* -------pageMap.json (编译器将pageMap注入到这里)
|
||||
* --router
|
||||
* ----index.ts (编译器将router.ts注入到这里)
|
||||
*
|
||||
*/
|
||||
|
||||
type PageDesc = {
|
||||
path: string;
|
||||
oakDisablePulldownRefresh: boolean;
|
||||
hasWeb: boolean;
|
||||
hasNative: boolean;
|
||||
hasWechatMp: boolean;
|
||||
}
|
||||
|
||||
type NamespaceDesc = {
|
||||
pages: Record<string, PageDesc>;
|
||||
}
|
||||
|
||||
const NameSpaceDescDict: Record<string, NamespaceDesc> = {};
|
||||
|
||||
function checkPageDir(dir: string, relativePath: string, ns: string, type: 'native' | 'web' | 'wechatMp') {
|
||||
let changed = false;
|
||||
const { pages } = NameSpaceDescDict[ns];
|
||||
const subdirs: string[] = [];
|
||||
const files = readdirSync(dir);
|
||||
files.forEach((file) => {
|
||||
const filepath = join(dir, file);
|
||||
const stat = statSync(filepath);
|
||||
if (stat.isFile() &&
|
||||
['web.tsx', 'web.pc.tsx', 'render.native.tsx', 'render.ios.tsx', 'render.android.tsx', 'index.xml'].includes(
|
||||
file
|
||||
)) {
|
||||
if (!pages.hasOwnProperty(dir)) {
|
||||
const indexJsonFile = join(dir, 'index.json');
|
||||
let oakDisablePulldownRefresh = false;
|
||||
if (existsSync(indexJsonFile)) {
|
||||
const {
|
||||
enablePullDownRefresh = true,
|
||||
} = require(indexJsonFile);
|
||||
oakDisablePulldownRefresh =
|
||||
!enablePullDownRefresh;
|
||||
}
|
||||
pages[dir] = {
|
||||
path: relativePath.replace(/\\/g, '/'),
|
||||
oakDisablePulldownRefresh,
|
||||
hasNative: ['render.native.tsx', 'render.ios.tsx', 'render.android.tsx'].includes(file),
|
||||
hasWeb: ['web.tsx', 'web.pc.tsx'].includes(file),
|
||||
hasWechatMp: file === 'index.xml',
|
||||
};
|
||||
changed = true;
|
||||
}
|
||||
else {
|
||||
if (['render.native.tsx', 'render.ios.tsx', 'render.android.tsx'].includes(file) && type === 'native') {
|
||||
if (pages[dir].hasNative === false) {
|
||||
pages[dir].hasNative = true;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else if (['web.tsx', 'web.pc.tsx'].includes(file) && type === 'web') {
|
||||
if (pages[dir].hasWeb === false) {
|
||||
pages[dir].hasWeb = true;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pages[dir].hasWechatMp === false && type === 'wechatMp') {
|
||||
pages[dir].hasWechatMp = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (stat.isDirectory()) {
|
||||
subdirs.push(file);
|
||||
}
|
||||
});
|
||||
return {
|
||||
subdirs,
|
||||
changed,
|
||||
};
|
||||
}
|
||||
|
||||
function traverseNsDir(nsDir: string, ns: string, type: 'native' | 'web' | 'wechatMp') {
|
||||
NameSpaceDescDict[ns] = {
|
||||
pages: {}
|
||||
};
|
||||
const { pages } = NameSpaceDescDict[ns];
|
||||
const traverse = (dir: string, relativePath: string) => {
|
||||
const { subdirs } = checkPageDir(dir, relativePath, ns, type);
|
||||
subdirs.forEach(
|
||||
(subdir) => {
|
||||
const dir2 = join(dir, subdir);
|
||||
const relativePath2 = join(relativePath, subdir);
|
||||
traverse(dir2, relativePath2);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
traverse(nsDir, '');
|
||||
}
|
||||
|
||||
function traversePageDir(projectDir: string, type: 'native' | 'web' | 'wechatMp') {
|
||||
const pageDir = join(projectDir, 'src', 'pages');
|
||||
|
||||
const namespaces = readdirSync(pageDir);
|
||||
namespaces.forEach(
|
||||
(ns) => {
|
||||
const nsDir = join(pageDir, ns);
|
||||
const stat = statSync(nsDir);
|
||||
if (stat.isDirectory()) {
|
||||
traverseNsDir(nsDir, ns, type);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function makeWebAllRouters(namespaceDir: string, projectDir: string, routerFileDir: string) {
|
||||
const nss = readdirSync(namespaceDir);
|
||||
|
||||
return factory.createArrayLiteralExpression(
|
||||
nss.map(
|
||||
(ns) => {
|
||||
assert(NameSpaceDescDict[ns], `${ns}在pages下没有对应的目录`);
|
||||
const { pages } = NameSpaceDescDict[ns];
|
||||
const nsIndexJsonFile = join(namespaceDir, ns, 'index.json');
|
||||
let path2 = `/${ns}`;
|
||||
let notFound2 = '', first2 = '';
|
||||
if (existsSync(nsIndexJsonFile)) {
|
||||
const { path, notFound, first } = require(nsIndexJsonFile);
|
||||
if (path) {
|
||||
path2 = path.replace(/\\/g, '/');
|
||||
}
|
||||
if (notFound) {
|
||||
notFound2 = notFound.replace(/\\/g, '/');
|
||||
}
|
||||
if (first) {
|
||||
first2 = first.replace(/\\/g, '/');
|
||||
if (first2.startsWith('/')) {
|
||||
first2 = first2.slice(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
const children = Object.values(pages).filter(
|
||||
(ele) => ele.hasWeb
|
||||
).map(
|
||||
({ path, oakDisablePulldownRefresh }) => {
|
||||
const properties = [
|
||||
factory.createPropertyAssignment(
|
||||
'path',
|
||||
factory.createStringLiteral(path)
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
'namespace',
|
||||
factory.createStringLiteral(path2)
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
'meta',
|
||||
factory.createObjectLiteralExpression(
|
||||
[
|
||||
factory.createPropertyAssignment(
|
||||
'oakDisablePulldownRefresh',
|
||||
oakDisablePulldownRefresh ? factory.createTrue() : factory.createFalse()
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("Component"),
|
||||
factory.createCallExpression(
|
||||
factory.createPropertyAccessExpression(
|
||||
factory.createIdentifier("React"),
|
||||
factory.createIdentifier("lazy")
|
||||
),
|
||||
undefined,
|
||||
[factory.createArrowFunction(
|
||||
undefined,
|
||||
undefined,
|
||||
[],
|
||||
undefined,
|
||||
factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
||||
factory.createCallExpression(
|
||||
factory.createIdentifier('import'),
|
||||
undefined,
|
||||
[
|
||||
factory.createStringLiteral(
|
||||
relative(routerFileDir, join(projectDir, 'src', 'pages', ns, path)).replace(/\\/g, '/')
|
||||
)
|
||||
]
|
||||
)
|
||||
)]
|
||||
)
|
||||
)
|
||||
];
|
||||
if (first2 === path) {
|
||||
properties.push(
|
||||
factory.createPropertyAssignment(
|
||||
'isFirst',
|
||||
factory.createTrue()
|
||||
)
|
||||
)
|
||||
}
|
||||
return factory.createObjectLiteralExpression(
|
||||
properties,
|
||||
true,
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
if (notFound2) {
|
||||
children.push(
|
||||
factory.createObjectLiteralExpression(
|
||||
[
|
||||
factory.createPropertyAssignment(
|
||||
'path',
|
||||
factory.createStringLiteral('*')
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
'namespace',
|
||||
factory.createStringLiteral(path2)
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("Component"),
|
||||
factory.createCallExpression(
|
||||
factory.createPropertyAccessExpression(
|
||||
factory.createIdentifier("React"),
|
||||
factory.createIdentifier("lazy")
|
||||
),
|
||||
undefined,
|
||||
[factory.createArrowFunction(
|
||||
undefined,
|
||||
undefined,
|
||||
[],
|
||||
undefined,
|
||||
factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
||||
factory.createCallExpression(
|
||||
factory.createIdentifier('import'),
|
||||
undefined,
|
||||
[
|
||||
factory.createStringLiteral(
|
||||
relative(routerFileDir, join(projectDir, 'src', 'pages', ns, notFound2)).replace(/\\/g, '/')
|
||||
)
|
||||
]
|
||||
)
|
||||
)]
|
||||
)
|
||||
)
|
||||
],
|
||||
true
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return factory.createObjectLiteralExpression(
|
||||
[
|
||||
factory.createPropertyAssignment(
|
||||
'path',
|
||||
factory.createStringLiteral(path2)
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
'namespace',
|
||||
factory.createStringLiteral(path2)
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
factory.createIdentifier("Component"),
|
||||
factory.createCallExpression(
|
||||
factory.createPropertyAccessExpression(
|
||||
factory.createIdentifier("React"),
|
||||
factory.createIdentifier("lazy")
|
||||
),
|
||||
undefined,
|
||||
[factory.createArrowFunction(
|
||||
undefined,
|
||||
undefined,
|
||||
[],
|
||||
undefined,
|
||||
factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
||||
factory.createCallExpression(
|
||||
factory.createIdentifier('import'),
|
||||
undefined,
|
||||
[
|
||||
factory.createStringLiteral(
|
||||
relative(routerFileDir, join(namespaceDir, ns)).replace(/\\/g, '/')
|
||||
)
|
||||
]
|
||||
)
|
||||
)]
|
||||
)
|
||||
),
|
||||
factory.createPropertyAssignment(
|
||||
'children',
|
||||
factory.createArrayLiteralExpression(
|
||||
children
|
||||
)
|
||||
)
|
||||
],
|
||||
true
|
||||
)
|
||||
}
|
||||
),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
function judgeUseOakRouterBuilder(statements: ts.NodeArray<ts.Statement>) {
|
||||
const stmt = statements[0];
|
||||
return ts.isExpressionStatement(stmt) && ts.isStringLiteral(stmt.expression) && stmt.expression.text === 'use oak router builder';
|
||||
}
|
||||
|
||||
function outputInWebAppDir(appDir: string) {
|
||||
const routerFileName = join(appDir, 'router', 'allRouters.ts');
|
||||
if (existsSync(routerFileName)) {
|
||||
const program = ts.createProgram([routerFileName], {
|
||||
removeComments: false,
|
||||
});
|
||||
const routerFile = program.getSourceFile(routerFileName);
|
||||
assert(routerFile);
|
||||
const namespaceDir = join(appDir, 'namespaces');
|
||||
const { statements } = routerFile;
|
||||
if (judgeUseOakRouterBuilder(statements)) {
|
||||
statements.forEach(
|
||||
(statement) => {
|
||||
if (ts.isVariableStatement(statement)) {
|
||||
const declaration = statement.declarationList.declarations.find(
|
||||
declaration => ts.isIdentifier(declaration.name) && declaration.name.text === 'allRouters'
|
||||
);
|
||||
if (declaration) {
|
||||
Object.assign(declaration, {
|
||||
initializer: makeWebAllRouters(namespaceDir, join(appDir, '../../../..'), dirname(routerFileName))
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed, removeComments: false });
|
||||
const result = printer.printNode(
|
||||
ts.EmitHint.Unspecified,
|
||||
routerFile,
|
||||
routerFile,
|
||||
);
|
||||
|
||||
writeFileSync(routerFileName, result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.warn(`${appDir}的目录结构未按照标准建立,缺少了${routerFileName}`);
|
||||
}
|
||||
}
|
||||
|
||||
function outputInWebDir(dir: string) {
|
||||
const srcAppDir = join(dir, 'src', 'app');
|
||||
const apps = readdirSync(srcAppDir);
|
||||
apps.forEach(
|
||||
(app) => {
|
||||
const appDir = join(srcAppDir, app);
|
||||
const stat = statSync(appDir);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
outputInWebAppDir(appDir);
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
function watchDir(projectDir: string, startupDir: string, type: 'native' | 'web' | 'wechatMp') {
|
||||
const srcPageDir = join(projectDir, 'src', 'pages');
|
||||
console.log('watch dir ', srcPageDir);
|
||||
|
||||
if (startupDir.startsWith('web')) {
|
||||
const srcAppDir = join(projectDir, startupDir, 'src', 'app');
|
||||
const apps = readdirSync(srcAppDir);
|
||||
const tryOutputAppDir = (ns: string) => {
|
||||
apps.forEach(
|
||||
(app) => {
|
||||
const appDir = join(srcAppDir, app);
|
||||
const namespaceDir = join(appDir, 'namespaces');
|
||||
const namespaces = readdirSync(namespaceDir);
|
||||
if (namespaces.includes(ns)) {
|
||||
outputInWebAppDir(appDir);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
NodeWatch(srcPageDir, {
|
||||
recursive: true,
|
||||
filter: new RegExp('web\.tsx|web\.pc\.tsx|index\.xml|render\.(native|ios|android)\.tsx'),
|
||||
}, (evt, filepath) => {
|
||||
const dir = dirname(filepath);
|
||||
const relativeDir = relative(join(projectDir, 'src', 'pages'), filepath);
|
||||
const ns = relativeDir.split('\\')[0];
|
||||
const relativePath = relative(ns, dirname(relativeDir));
|
||||
const { pages } = NameSpaceDescDict[ns];
|
||||
console.log(filepath, dir, ns);
|
||||
if (evt === 'remove') {
|
||||
if (existsSync(dir)) {
|
||||
const { changed } = checkPageDir(dir, relativePath, ns, type);
|
||||
if (changed) {
|
||||
tryOutputAppDir(ns);
|
||||
}
|
||||
}
|
||||
else {
|
||||
delete pages[dir];
|
||||
tryOutputAppDir(ns);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const { changed } = checkPageDir(dir, relativePath, ns, type);
|
||||
if (changed) {
|
||||
tryOutputAppDir(ns);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function buildRouter(projectDir: string, startupDir: string, watch?: boolean) {
|
||||
const type = startupDir.startsWith('web') ? 'web' : (startupDir.startsWith('native') ? 'native' : 'wechatMp');
|
||||
traversePageDir(projectDir, type);
|
||||
|
||||
const subDir = readdirSync(projectDir);
|
||||
assert(subDir.includes(startupDir));
|
||||
|
||||
if (startupDir.startsWith('web')) {
|
||||
outputInWebDir(join(projectDir, startupDir));
|
||||
}
|
||||
|
||||
// todo native
|
||||
|
||||
if (watch) {
|
||||
watchDir(projectDir, startupDir, type);
|
||||
}
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
|
||||
this.selectionRewriters.forEach(
|
||||
ele => {
|
||||
const result = ele(this.getSchema(), entity, selection, context, option);
|
||||
const result = ele(this.getSchema(), entity, selection, context, option, isAggr);
|
||||
assert(!(result instanceof Promise));
|
||||
}
|
||||
);
|
||||
|
|
@ -377,7 +377,6 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
$$createAt$$: 1,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private async reinforceOperation<Cxt extends AsyncContext<ED>, Op extends OperateOption>(
|
||||
|
|
@ -403,6 +402,19 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
selection: ED[T]['Selection'],
|
||||
context: Cxt,
|
||||
option: OP): Partial<ED[T]['Schema']>[];
|
||||
|
||||
protected abstract countAbjointRow<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(
|
||||
entity: T,
|
||||
selection: Pick<ED[T]['Selection'], 'filter' | 'count'>,
|
||||
context: Cxt,
|
||||
option: OP): number;
|
||||
|
||||
|
||||
protected abstract countAbjointRowAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(
|
||||
entity: T,
|
||||
selection: Pick<ED[T]['Selection'], 'filter' | 'count'>,
|
||||
context: Cxt,
|
||||
option: OP): Promise<number>;
|
||||
|
||||
protected abstract updateAbjointRow<T extends keyof ED, OP extends OperateOption, Cxt extends SyncContext<ED>>(
|
||||
entity: T,
|
||||
|
|
@ -416,13 +428,6 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
context: Cxt,
|
||||
option: OP): Promise<Partial<ED[T]['Schema']>[]>;
|
||||
|
||||
protected abstract countAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(
|
||||
entity: T,
|
||||
selection: Pick<ED[T]['Selection'], 'filter' | 'count'>,
|
||||
context: Cxt,
|
||||
option: OP
|
||||
): Promise<number>;
|
||||
|
||||
protected abstract updateAbjointRowAsync<T extends keyof ED, OP extends OperateOption, Cxt extends AsyncContext<ED>>(
|
||||
entity: T,
|
||||
operation: ED[T]['Create'] | ED[T]['Update'] | ED[T]['Remove'],
|
||||
|
|
@ -2169,4 +2174,22 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
|
|||
await this.reinforceOperation(entity, operation, context, option);
|
||||
return this.cascadeUpdateAsync(entity, operation, context, option);
|
||||
}
|
||||
|
||||
protected countSync<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(
|
||||
entity: T,
|
||||
selection: Pick<ED[T]['Selection'], 'filter' | 'count'>,
|
||||
context: Cxt,
|
||||
option: OP) {
|
||||
this.reinforceSelectionSync(entity, selection as ED[T]['Selection'], context, option, true); // 这样写可能有问题的,虽然能跳过本地的projection补全,但如果有更多的selectionRewriter注入可能会出问题。by Xc 20231220
|
||||
return this.countAbjointRow(entity, selection as ED[T]['Selection'], context, option);
|
||||
}
|
||||
|
||||
protected countAsync<T extends keyof ED, OP extends SelectOption, Cxt extends AsyncContext<ED>>(
|
||||
entity: T,
|
||||
selection: Pick<ED[T]['Selection'], 'filter' | 'count'>,
|
||||
context: Cxt,
|
||||
option: OP) {
|
||||
this.reinforceSelectionAsync(entity, selection as ED[T]['Selection'], context, option, true); // 这样写可能有问题的,虽然能跳过本地的projection补全,但如果有更多的selectionRewriter注入可能会出问题。by Xc 20231220
|
||||
return this.countAbjointRowAsync(entity, selection as ED[T]['Selection'], context, option);
|
||||
}
|
||||
}
|
||||
|
|
@ -563,7 +563,7 @@ export class TriggerExecutor<ED extends EntityDict & BaseEntityDict, Cxt extends
|
|||
const rs = grouped[uuid];
|
||||
const { [TriggerDataAttribute]: triggerData } = rs[0];
|
||||
const { name, cxtStr, option } = triggerData!;
|
||||
await context.initialize(JSON.parse(cxtStr));
|
||||
// await context.initialize(JSON.parse(cxtStr)); // 这里token有可能过期(用户注销),先用root态模拟吧
|
||||
await this.execVolatileTrigger(entity, name, rs.map(ele => ele.id!), context, option);
|
||||
}
|
||||
await context.commit();
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ export class SimpleConnector<ED extends EntityDict, FrontCxt extends SyncContext
|
|||
});
|
||||
} catch (err) {
|
||||
// fetch返回异常一定是网络异常
|
||||
throw new OakNetworkException();
|
||||
throw new OakNetworkException(`请求[${this.serverAspectUrl}],发生网络异常`);
|
||||
}
|
||||
if (response.status > 299) {
|
||||
const err = new OakServerProxyException(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
import { generateNewId } from '../src/utils/uuid';
|
||||
/* import { generateNewId } from '../src/utils/uuid';
|
||||
|
||||
let iter = 20;
|
||||
|
||||
while (iter > 0) {
|
||||
console.log(generateNewId());
|
||||
iter --;
|
||||
}
|
||||
} */
|
||||
import { join } from 'path';
|
||||
import { buildRouter } from '../src/compiler/routerBuilder';
|
||||
|
||||
buildRouter(join(process.cwd(), '..', 'taicang'), 'web', true);
|
||||
Loading…
Reference in New Issue