增加了i18n相应的routine

This commit is contained in:
Xu Chang 2025-08-18 15:06:03 +08:00
parent 8c3b74cb89
commit 34697f3ef5
8 changed files with 253 additions and 38 deletions

View File

@ -17,6 +17,7 @@ const DataSubscriber_1 = tslib_1.__importDefault(require("./cluster/DataSubscrib
const env_1 = require("./cluster/env");
const Synchronizer_1 = tslib_1.__importDefault(require("./Synchronizer"));
const i18n_1 = tslib_1.__importDefault(require("oak-domain/lib/data/i18n"));
const requirePrj_1 = tslib_1.__importDefault(require("./utils/requirePrj"));
class AppLoader extends types_1.AppLoader {
dbStore;
aspectDict;
@ -28,21 +29,7 @@ class AppLoader extends types_1.AppLoader {
watcherTimerId;
scheduledJobs = {};
requireSth(filePath) {
const depFilePath = (0, path_1.join)(this.path, filePath);
let sth;
if ((0, fs_1.existsSync)(`${depFilePath}.js`)) {
sth = require((0, path_1.join)(this.path, filePath)).default;
}
const sthExternal = this.externalDependencies.map(ele => {
const depFilePath = (0, path_1.join)(this.path, 'node_modules', ele, filePath);
if ((0, fs_1.existsSync)(`${depFilePath}.js`)) {
return require(depFilePath).default;
}
}).filter(ele => !!ele);
if (sth) {
sthExternal.push(sth);
}
return (0, lodash_1.mergeConcatMany)(sthExternal);
return (0, requirePrj_1.default)(this.path, filePath, this.externalDependencies);
}
async makeContext(cxtStr, headers) {
const context = this.contextBuilder(this.dbStore);
@ -506,7 +493,15 @@ class AppLoader extends types_1.AppLoader {
}
async execRoutine(routine) {
const context = await this.makeContext();
await routine(context);
try {
const result = await routine(context);
await context.commit();
return result;
}
catch (e) {
await context.rollback();
throw e;
}
}
}
exports.AppLoader = AppLoader;

15
lib/routines/i18n.d.ts vendored Normal file
View File

@ -0,0 +1,15 @@
import { EntityDict } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
/**
* i18n数据和数据库中的差异
* @param context
* @returns
*/
export declare function checkI18n<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>>(context: Cxt): Promise<(void | Awaited<import("oak-domain/lib/types").OperationResult<ED>>)[]>;
/**
* i18n数据和数据库中的差异
* @param context
* @returns
*/
export declare function checkAndUpdateI18n<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>>(context: Cxt): Promise<(void | Awaited<import("oak-domain/lib/types").OperationResult<ED>>)[]>;

78
lib/routines/i18n.js Normal file
View File

@ -0,0 +1,78 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkAndUpdateI18n = exports.checkI18n = void 0;
const tslib_1 = require("tslib");
const node_path_1 = require("node:path");
const requirePrj_1 = tslib_1.__importDefault(require("../utils/requirePrj"));
const dependencyBuilder_1 = require("oak-domain/lib/compiler/dependencyBuilder");
const node_assert_1 = tslib_1.__importDefault(require("node:assert"));
const lodash_1 = require("lodash");
const uuid_1 = require("oak-domain/lib/utils/uuid");
async function checkAndUpdateI18nInner(context, onlyCheck) {
const pwd = process.cwd();
const i18nData = (0, requirePrj_1.default)(pwd, (0, node_path_1.join)('lib', 'data', 'i18n'), (0, dependencyBuilder_1.analyzeDepedency)(pwd).ascOrder);
const originI18nData = await context.select('i18n', {
data: {
id: 1,
namespace: 1,
language: 1,
module: 1,
position: 1,
data: 1,
},
}, { dontCollect: true });
const originDataDict = {};
originI18nData.forEach((data) => originDataDict[data.id] = data);
const result = i18nData.map(async (i18n) => {
const { id, namespace, language, module, position, data } = i18n;
const origin = originDataDict[id];
if (origin) {
(0, node_assert_1.default)(namespace === origin.namespace && language === origin.language && module === origin.module && position === origin.position);
if (!(0, lodash_1.isEqual)(data, origin.data)) {
console.log(`[${namespace}]数据${onlyCheck ? '需要更新' : '将被更新'}`);
if (!onlyCheck) {
return context.operate('i18n', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'update',
data: {
data,
},
filter: {
id,
},
}, {});
}
}
}
else {
console.log(`[${namespace}]数据${onlyCheck ? '需要新建' : '将被新建'}`);
if (!onlyCheck) {
return context.operate('i18n', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'create',
data: i18n,
}, {});
}
}
return Promise.resolve();
});
return await Promise.all(result);
}
/**
* 检查项目目录下的i18n数据和数据库中的差异
* @param context
* @returns
*/
function checkI18n(context) {
return checkAndUpdateI18nInner(context, true);
}
exports.checkI18n = checkI18n;
/**
* 检查项目目录下的i18n数据和数据库中的差异并更新
* @param context
* @returns
*/
function checkAndUpdateI18n(context) {
return checkAndUpdateI18nInner(context);
}
exports.checkAndUpdateI18n = checkAndUpdateI18n;

1
lib/utils/requirePrj.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export default function requireSth(prjPath: string, filePath: string, dependencies: string[]): any;

23
lib/utils/requirePrj.js Normal file
View File

@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const lodash_1 = require("oak-domain/lib/utils/lodash");
const path_1 = require("path");
function requireSth(prjPath, filePath, dependencies) {
const depFilePath = (0, path_1.join)(prjPath, filePath);
let sth;
if ((0, fs_1.existsSync)(`${depFilePath}.js`)) {
sth = require((0, path_1.join)(prjPath, filePath)).default;
}
const sthExternal = dependencies.map(ele => {
const depFilePath = (0, path_1.join)(prjPath, 'node_modules', ele, filePath);
if ((0, fs_1.existsSync)(`${depFilePath}.js`)) {
return require(depFilePath).default;
}
}).filter(ele => !!ele);
if (sth) {
sthExternal.push(sth);
}
return (0, lodash_1.mergeConcatMany)(sthExternal);
}
exports.default = requireSth;

View File

@ -21,6 +21,7 @@ import { getClusterInfo } from './cluster/env';
import Synchronizer from './Synchronizer';
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
import domainI18nData from 'oak-domain/lib/data/i18n';
import requireSth from './utils/requirePrj';
export class AppLoader<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>> extends GeneralAppLoader<ED, Cxt> {
protected dbStore: DbStore<ED, Cxt>;
@ -34,27 +35,7 @@ export class AppLoader<ED extends EntityDict & BaseEntityDict, Cxt extends Backe
private scheduledJobs: Record<string, Job> = {};
private requireSth(filePath: string): any {
const depFilePath = join(this.path, filePath);
let sth: any;
if (existsSync(`${depFilePath}.js`)) {
sth = require(join(this.path, filePath)).default;
}
const sthExternal = this.externalDependencies.map(
ele => {
const depFilePath = join(this.path, 'node_modules', ele, filePath);
if (existsSync(`${depFilePath}.js`)) {
return require(depFilePath).default
}
}
).filter(
ele => !!ele
);
if (sth) {
sthExternal.push(sth);
}
return mergeConcatMany(sthExternal);
return requireSth(this.path, filePath, this.externalDependencies);
}
protected async makeContext(cxtStr?: string, headers?: IncomingHttpHeaders) {
@ -595,6 +576,14 @@ export class AppLoader<ED extends EntityDict & BaseEntityDict, Cxt extends Backe
async execRoutine(routine: <Cxt extends AsyncContext<ED>>(context: Cxt) => Promise<void>) {
const context = await this.makeContext();
await routine(context);
try {
const result = await routine(context);
await context.commit();
return result;
}
catch(e: any) {
await context.rollback();
throw e;
}
}
}

87
src/routines/i18n.ts Normal file
View File

@ -0,0 +1,87 @@
import { EntityDict } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
import { join } from 'node:path';
import requireSth from '../utils/requirePrj';
import { analyzeDepedency } from 'oak-domain/lib/compiler/dependencyBuilder';
import assert from 'node:assert';
import { isEqual } from 'lodash';
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
async function checkAndUpdateI18nInner<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>>(context: Cxt, onlyCheck?: true) {
const pwd = process.cwd();
const i18nData = requireSth(pwd, join('lib', 'data', 'i18n'), analyzeDepedency(pwd).ascOrder) as BaseEntityDict['i18n']['OpSchema'][];
const originI18nData = await context.select('i18n', {
data: {
id: 1,
namespace: 1,
language: 1,
module: 1,
position: 1,
data: 1,
},
}, { dontCollect: true });
const originDataDict: Record<string, BaseEntityDict['i18n']['OpSchema']> = {};
originI18nData.forEach(
(data) => originDataDict[data.id!] = data as BaseEntityDict['i18n']['OpSchema']
);
const result = i18nData.map(
async (i18n) => {
const { id, namespace, language, module, position, data } = i18n;
const origin = originDataDict[id];
if (origin) {
assert(namespace === origin.namespace && language === origin.language && module === origin.module && position === origin.position);
if (!isEqual(data, origin.data)) {
console.log(`[${namespace}]数据${onlyCheck ? '需要更新' : '将被更新'}`);
if (!onlyCheck) {
return context.operate('i18n', {
id: await generateNewIdAsync(),
action: 'update',
data: {
data,
},
filter: {
id,
},
}, {});
}
}
}
else {
console.log(`[${namespace}]数据${onlyCheck ? '需要新建' : '将被新建'}`);
if (!onlyCheck) {
return context.operate('i18n', {
id: await generateNewIdAsync(),
action: 'create',
data: i18n,
}, {});
}
}
return Promise.resolve();
}
);
return await Promise.all(result);
}
/**
* i18n数据和数据库中的差异
* @param context
* @returns
*/
export function checkI18n<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>>(context: Cxt) {
return checkAndUpdateI18nInner<ED, Cxt>(context, true);
}
/**
* i18n数据和数据库中的差异
* @param context
* @returns
*/
export function checkAndUpdateI18n<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>>(context: Cxt) {
return checkAndUpdateI18nInner<ED, Cxt>(context);
}

27
src/utils/requirePrj.ts Normal file
View File

@ -0,0 +1,27 @@
import { existsSync } from "fs";
import { mergeConcatMany } from "oak-domain/lib/utils/lodash";
import { join } from "path";
export default function requireSth(prjPath: string, filePath: string, dependencies: string[]) {
const depFilePath = join(prjPath, filePath);
let sth: any;
if (existsSync(`${depFilePath}.js`)) {
sth = require(join(prjPath, filePath)).default;
}
const sthExternal = dependencies.map(
ele => {
const depFilePath = join(prjPath, 'node_modules', ele, filePath);
if (existsSync(`${depFilePath}.js`)) {
return require(depFilePath).default
}
}
).filter(
ele => !!ele
);
if (sth) {
sthExternal.push(sth);
}
return mergeConcatMany(sthExternal);
}