tego 1.3.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/utils.js ADDED
@@ -0,0 +1,176 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var utils_exports = {};
30
+ __export(utils_exports, {
31
+ downloadTar: () => downloadTar,
32
+ guessServePath: () => guessServePath,
33
+ initEnvFile: () => initEnvFile,
34
+ parseEnvironment: () => parseEnvironment
35
+ });
36
+ module.exports = __toCommonJS(utils_exports);
37
+ var import_node_crypto = require("node:crypto");
38
+ var import_node_fs = __toESM(require("node:fs"));
39
+ var import_promises = require("node:fs/promises");
40
+ var import_node_path = require("node:path");
41
+ var import_promises2 = require("node:stream/promises");
42
+ var import_globals = __toESM(require("@tachybase/globals"));
43
+ var import_dotenv = require("dotenv");
44
+ var import_npm_registry_fetch = __toESM(require("npm-registry-fetch"));
45
+ var tar = __toESM(require("tar"));
46
+ var import_constants = require("./constants");
47
+ function initEnvFile(name) {
48
+ const envPath = (0, import_node_path.resolve)(name, ".env");
49
+ if (!import_node_fs.default.existsSync(envPath)) {
50
+ import_node_fs.default.copyFileSync((0, import_node_path.resolve)(__dirname, "../presets/.env.example"), envPath);
51
+ console.log(".env file created.");
52
+ } else {
53
+ console.log(".env file already exists.");
54
+ }
55
+ }
56
+ __name(initEnvFile, "initEnvFile");
57
+ function parseEnv(name) {
58
+ if (name === "DB_UNDERSCORED") {
59
+ if (process.env.DB_UNDERSCORED === "true") {
60
+ return "true";
61
+ }
62
+ if (process.env.DB_UNDERSCORED) {
63
+ return "true";
64
+ }
65
+ return "false";
66
+ }
67
+ }
68
+ __name(parseEnv, "parseEnv");
69
+ function parseEnvironment() {
70
+ const env = {
71
+ APP_ENV: "development",
72
+ APP_KEY: "test-jwt-secret",
73
+ APP_PORT: 3e3,
74
+ API_BASE_PATH: "/api/",
75
+ DB_DIALECT: "sqlite",
76
+ DB_STORAGE: "storage/db/tachybase.sqlite",
77
+ DB_TIMEZONE: "+00:00",
78
+ DB_UNDERSCORED: parseEnv("DB_UNDERSCORED"),
79
+ DEFAULT_STORAGE_TYPE: "local",
80
+ RUN_MODE: "engine",
81
+ LOCAL_STORAGE_DEST: "storage/uploads",
82
+ PLUGIN_STORAGE_PATH: (0, import_node_path.resolve)(process.cwd(), "storage/plugins"),
83
+ MFSU_AD: "none",
84
+ WS_PATH: "/ws",
85
+ SOCKET_PATH: "storage/gateway.sock",
86
+ PM2_HOME: (0, import_node_path.resolve)(process.cwd(), "./storage/.pm2"),
87
+ PLUGIN_PACKAGE_PREFIX: "@tachybase/plugin-,@tachybase/module-",
88
+ SERVER_TSCONFIG_PATH: "./tsconfig.server.json",
89
+ PLAYWRIGHT_AUTH_FILE: (0, import_node_path.resolve)(process.cwd(), "storage/playwright/.auth/admin.json"),
90
+ CACHE_DEFAULT_STORE: "memory",
91
+ CACHE_MEMORY_MAX: 2e3,
92
+ PLUGIN_STATICS_PATH: "/static/plugins/",
93
+ LOGGER_BASE_PATH: "storage/logs",
94
+ APP_SERVER_BASE_URL: "",
95
+ APP_PUBLIC_PATH: "/"
96
+ };
97
+ (0, import_dotenv.config)({
98
+ path: (0, import_node_path.resolve)(process.cwd(), process.env.APP_ENV_PATH || ".env")
99
+ });
100
+ for (const key in env) {
101
+ if (!process.env[key]) {
102
+ process.env[key] = env[key];
103
+ }
104
+ }
105
+ if (!process.env.__env_modified__ && process.env.APP_PUBLIC_PATH) {
106
+ const publicPath = process.env.APP_PUBLIC_PATH.replace(/\/$/g, "");
107
+ const keys = ["API_BASE_PATH", "WS_PATH", "PLUGIN_STATICS_PATH"];
108
+ for (const key of keys) {
109
+ process.env[key] = publicPath + process.env[key];
110
+ }
111
+ process.env.__env_modified__ = "1";
112
+ }
113
+ if (!process.env.__env_modified__ && process.env.APP_SERVER_BASE_URL && !process.env.API_BASE_URL) {
114
+ process.env.API_BASE_URL = process.env.APP_SERVER_BASE_URL + process.env.API_BASE_PATH;
115
+ process.env.__env_modified__ = "1";
116
+ }
117
+ if (!process.env.SERVE_PATH) {
118
+ const servePath = guessServePath();
119
+ if (servePath) {
120
+ process.env.SERVE_PATH = servePath;
121
+ }
122
+ }
123
+ }
124
+ __name(parseEnvironment, "parseEnvironment");
125
+ function guessServePath() {
126
+ const distPath = (0, import_node_path.resolve)("apps/app-web/dist/index.html");
127
+ const clientPath = (0, import_node_path.resolve)("client/index.html");
128
+ if (import_node_fs.default.existsSync(distPath)) {
129
+ return (0, import_node_path.resolve)("apps/app-web/dist");
130
+ } else if (import_node_fs.default.existsSync(clientPath)) {
131
+ return (0, import_node_path.resolve)("client");
132
+ }
133
+ const pluginPaths = import_globals.default.getInstance().get("PLUGIN_PATHS");
134
+ for (const basePath of pluginPaths) {
135
+ if (import_node_fs.default.existsSync((0, import_node_path.resolve)(basePath, import_constants.DEFAULT_WEB_PACKAGE_NAME, "dist/index.html"))) {
136
+ return (0, import_node_path.resolve)(basePath, import_constants.DEFAULT_WEB_PACKAGE_NAME, "dist");
137
+ }
138
+ }
139
+ return false;
140
+ }
141
+ __name(guessServePath, "guessServePath");
142
+ async function getTarballUrl(pkgName, version = "latest") {
143
+ const info = await import_npm_registry_fetch.default.json(`/${pkgName}/${version}`, {
144
+ query: { fullMetadata: true }
145
+ });
146
+ return info.dist.tarball;
147
+ }
148
+ __name(getTarballUrl, "getTarballUrl");
149
+ async function downloadTar(packageName, target) {
150
+ const url = await getTarballUrl(packageName);
151
+ const tarballFile = (0, import_node_path.join)(target, "..", `${(0, import_node_crypto.createHash)("md5").update(packageName).digest("hex")}-tarball.gz`);
152
+ await (0, import_promises.mkdir)((0, import_node_path.dirname)(tarballFile), { recursive: true });
153
+ const writer = (0, import_node_fs.createWriteStream)(tarballFile);
154
+ const response = await fetch(url);
155
+ if (!response.ok || !response.body) {
156
+ throw new Error(`Failed to fetch tarball: ${response.statusText}`);
157
+ }
158
+ await (0, import_promises2.pipeline)(response.body, writer);
159
+ await (0, import_promises.mkdir)(target, { recursive: true });
160
+ await tar.x({
161
+ file: tarballFile,
162
+ gzip: true,
163
+ cwd: target,
164
+ strip: 1,
165
+ k: true
166
+ });
167
+ await (0, import_promises.unlink)(tarballFile);
168
+ }
169
+ __name(downloadTar, "downloadTar");
170
+ // Annotate the CommonJS export names for ESM import in node:
171
+ 0 && (module.exports = {
172
+ downloadTar,
173
+ guessServePath,
174
+ initEnvFile,
175
+ parseEnvironment
176
+ });
package/package.json ADDED
@@ -0,0 +1,88 @@
1
+ {
2
+ "name": "tego",
3
+ "version": "1.3.12",
4
+ "description": "",
5
+ "license": "Apache-2.0",
6
+ "main": "./lib/index.js",
7
+ "types": "./lib/index.d.ts",
8
+ "bin": {
9
+ "tego": "./bin/tego.js"
10
+ },
11
+ "dependencies": {
12
+ "@koa/cors": "5.0.0",
13
+ "@koa/multer": "3.1.0",
14
+ "@socketregistry/yocto-spinner": "1.0.19",
15
+ "async-mutex": "0.3.0",
16
+ "axios": "0.29.0",
17
+ "cache-manager": "5.7.6",
18
+ "chalk": "^4.1.2",
19
+ "commander": "^9.5.0",
20
+ "dayjs": "1.11.13",
21
+ "dotenv": "16.5.0",
22
+ "execa": "^5.1.1",
23
+ "i18next": "25.1.2",
24
+ "jsonwebtoken": "8.5.1",
25
+ "koa": "^2.15.3",
26
+ "koa-bodyparser": "4.4.1",
27
+ "lodash": "4.17.21",
28
+ "mathjs": "^10.6.4",
29
+ "multer": "2.0.1",
30
+ "mysql2": "3.14.1",
31
+ "npm-registry-fetch": "18.0.2",
32
+ "pg": "^8.13.1",
33
+ "react": "18.3.1",
34
+ "react-dom": "18.3.1",
35
+ "sequelize": "6.37.7",
36
+ "sqlite3": "5.1.7",
37
+ "tar": "7.4.3",
38
+ "tsx": "4.20.3",
39
+ "umzug": "3.8.2",
40
+ "winston": "3.17.0",
41
+ "winston-daily-rotate-file": "^5.0.0",
42
+ "@tachybase/acl": "1.3.12",
43
+ "@tachybase/cache": "1.3.12",
44
+ "@tachybase/actions": "1.3.12",
45
+ "@tachybase/database": "1.3.12",
46
+ "@tachybase/data-source": "1.3.12",
47
+ "@tachybase/evaluators": "1.3.12",
48
+ "@tachybase/auth": "1.3.12",
49
+ "@tachybase/globals": "1.3.12",
50
+ "@tachybase/loader": "1.3.12",
51
+ "@tachybase/logger": "1.3.12",
52
+ "@tachybase/resourcer": "1.3.12",
53
+ "@tachybase/schema": "1.3.12",
54
+ "@tachybase/server": "1.3.12",
55
+ "@tachybase/utils": "1.3.12"
56
+ },
57
+ "devDependencies": {
58
+ "@types/lodash": "4.17.18",
59
+ "@yao-pkg/pkg": "6.5.1",
60
+ "@tachybase/client": "1.3.12",
61
+ "@tachybase/cache": "1.3.12",
62
+ "@tachybase/logger": "1.3.12"
63
+ },
64
+ "pkg": {
65
+ "targets": [
66
+ "node22-macos-x64",
67
+ "node22-macos-arm64",
68
+ "node22-win-x64",
69
+ "node22-linux-x64",
70
+ "node22-linux-arm64"
71
+ ],
72
+ "assets": [
73
+ "presets/**/*"
74
+ ],
75
+ "outputPath": "dist"
76
+ },
77
+ "scripts": {
78
+ "build": "pkg . --no-bytecode --public-packages \"*\" --public --compress Brotli",
79
+ "build:debug": "pkg . --no-bytecode --public-packages \"*\" --public --debug",
80
+ "build:linux": "pkg --compress Brotli -t node22-linux-x64 .",
81
+ "build:linux:debug": "pkg --debug -t node22-linux-x64 .",
82
+ "build:mac": "pkg --compress Brotli -t node22-macos-arm64 .",
83
+ "build:mac:debug": "pkg --debug -t node22-macos-arm64 .",
84
+ "build:no-compress": "pkg . --no-bytecode --public-packages \"*\" --public",
85
+ "build:win": "pkg --compress Brotli -t node22-win-x64 .",
86
+ "build:win:debug": "pkg --debug -t node22-win-x64 ."
87
+ }
88
+ }
@@ -0,0 +1,92 @@
1
+ ################# TACHYBASE APPLICATION #################
2
+ APP_ENV=development
3
+ APP_PORT=3000
4
+ APP_KEY=test-key
5
+
6
+ # experimental support
7
+ EXTENSION_UI_BASE_PATH=/adapters/
8
+
9
+ API_BASE_PATH=/api/
10
+ API_BASE_URL=
11
+
12
+ # console | file | dailyRotateFile
13
+ LOGGER_TRANSPORT=
14
+ LOGGER_BASE_PATH=storage/logs
15
+ # error | warn | info | debug
16
+ LOGGER_LEVEL=
17
+ # If LOGGER_TRANSPORT is dailyRotateFile and using days, add 'd' as the suffix.
18
+ LOGGER_MAX_FILES=
19
+ # add 'k', 'm', 'g' as the suffix.
20
+ LOGGER_MAX_SIZE=
21
+ # json | splitter, split by '|' character
22
+ LOGGER_FORMAT=
23
+
24
+ ################# DATABASE #################
25
+
26
+ DB_DIALECT=sqlite
27
+ DB_STORAGE=storage/db/tachybase.sqlite
28
+ DB_TABLE_PREFIX=
29
+ # DB_HOST=localhost
30
+ # DB_PORT=5432
31
+ # DB_DATABASE=postgres
32
+ # DB_USER=tachybase
33
+ # DB_PASSWORD=tachybase
34
+ # DB_LOGGING=on
35
+ # DB_UNDERSCORED=false
36
+
37
+ #== SSL CONFIG ==#
38
+ # DB_DIALECT_OPTIONS_SSL_CA=
39
+ # DB_DIALECT_OPTIONS_SSL_KEY=
40
+ # DB_DIALECT_OPTIONS_SSL_CERT=
41
+ # DB_DIALECT_OPTIONS_SSL_REJECT_UNAUTHORIZED=true
42
+
43
+ ################# CACHE #################
44
+ CACHE_DEFAULT_STORE=memory
45
+ # max number of items in memory cache
46
+ CACHE_MEMORY_MAX=2000
47
+ # CACHE_REDIS_URL=
48
+
49
+ ################# STORAGE (Initialization only) #################
50
+
51
+ INIT_APP_LANG=zh-CN
52
+ INIT_ROOT_EMAIL=admin@tachybase.com
53
+ INIT_ROOT_PASSWORD=!Admin123.
54
+ INIT_ROOT_NICKNAME=Super Admin
55
+ INIT_ROOT_USERNAME=tachybase
56
+
57
+ ################# ENCRYPTION FIELD #################
58
+
59
+ ENCRYPTION_FIELD_KEY=
60
+
61
+ ##### PRESETS #####
62
+
63
+ # 单写名称:添加指定插件且默认启用 名称前加!:移除指定插件 名称前加|:添加指定插件但默认禁用
64
+ # PRESETS_CORE_PLUGINS=api-doc,api-keys,!messages
65
+ PRESETS_LOCAL_PLUGINS=!adapter-bullmq,!adapter-red-node,!adapter-remix,!api-keys,!audit-logs,!auth-cas,!auth-dingtalk,!auth-lark,!auth-oidc,!auth-saml,!auth-sms,!auth-wechat,!auth-wecom,!block-comments,!block-map,!block-step-form,!data-source-common,!demos-game-runesweeper,!devtools,!field-markdown-vditor,!field-snapshot,!hera,!i18n-editor,!multi-app,!multi-app-share-collection,!online-user,!simple-cms,!sub-accounts,!theme-editor,!workflow-approval,!ai-chat,!department,!workflow-analysis,!api-logs,!ocr-convert,!text-copy
66
+ # 运行时插件,插件不写入数据库,且优先加载
67
+ # RUNTIME_PLUGINS=
68
+
69
+ # 主应用工作线程默认数量
70
+ WORKER_COUNT=0
71
+ # WORKER_TIMEOUT=1800
72
+ # 主应用工作线程最大数量
73
+ WORKER_COUNT_MAX=8
74
+ # WORKER_ERROR_RETRY=3
75
+ # 子应用工作线程默认数量
76
+ WORKER_COUNT_SUB=0
77
+ # 子应用工作线程最大数量
78
+ WORKER_COUNT_MAX_SUB=1
79
+
80
+ # export config, max length of export data to use main thread and page size in worker thread
81
+ # EXPORT_LENGTH_MAX=2000
82
+ # EXPORT_WORKER_PAGESIZE=1000
83
+
84
+ # 开发环境测试locale 强制使用 cache
85
+ #FORCE_LOCALE_CACHE=1
86
+
87
+ # 禁止子应用装载的插件,多个用逗号分隔
88
+ # FORBID_SUB_APP_PLUGINS=multi-app,manual-notification,multi-app-share-collection
89
+
90
+
91
+ # 工作线程最大内存,单位为MB
92
+ # WORKER_MAX_MEMORY=4096
package/src/config.ts ADDED
@@ -0,0 +1,49 @@
1
+ import { parseDatabaseOptionsFromEnv } from '@tachybase/database';
2
+ import { getLoggerLevel, getLoggerTransport } from '@tachybase/logger';
3
+
4
+ const DbTypeMap = {
5
+ sqlite: require('sqlite3'),
6
+ mysql: require('mysql2'),
7
+ mariadb: require('mysql2'),
8
+ postgres: require('pg'),
9
+ };
10
+
11
+ export async function getConfig() {
12
+ return {
13
+ database: {
14
+ ...(await parseDatabaseOptionsFromEnv()),
15
+ dialectModule: DbTypeMap[process.env.DB_DIALECT || 'sqlite'],
16
+ } as any,
17
+ resourcer: {
18
+ prefix: process.env.API_BASE_PATH || '/api/',
19
+ },
20
+ plugins: ['tachybase'],
21
+ cacheManager: {
22
+ defaultStore: process.env.CACHE_DEFAULT_STORE || 'memory',
23
+ stores: {
24
+ memory: {
25
+ store: 'memory',
26
+ max: parseInt(process.env.CACHE_MEMORY_MAX) || 2000,
27
+ },
28
+ ...(process.env.CACHE_REDIS_URL
29
+ ? {
30
+ redis: {
31
+ url: process.env.CACHE_REDIS_URL,
32
+ },
33
+ }
34
+ : {}),
35
+ },
36
+ },
37
+ logger: {
38
+ request: {
39
+ transports: getLoggerTransport(),
40
+ level: getLoggerLevel(),
41
+ },
42
+ system: {
43
+ transports: getLoggerTransport(),
44
+ level: getLoggerLevel(),
45
+ },
46
+ },
47
+ perfHooks: process.env.ENABLE_PERF_HOOKS ? true : false,
48
+ };
49
+ }
@@ -0,0 +1,7 @@
1
+ import path from 'node:path';
2
+
3
+ export const DEFAULT_DEV_PLUGINS_PATH = path.resolve('plugins', 'dev');
4
+ export const DEFAULT_REMOTE_PLUGINS_PATH = path.resolve('plugins', 'remote');
5
+ export const DEFAULT_BUILTIN_PLUGINS_PATH = path.resolve('plugins', 'builtin');
6
+ export const DEFAULT_BUILTIN_PLUGINS_RELATIVE_PATH = path.join('plugins', 'builtin');
7
+ export const DEFAULT_WEB_PACKAGE_NAME = '@tachybase/app-web';
@@ -0,0 +1,24 @@
1
+ export const defaultModules = [
2
+ 'acl',
3
+ 'app-info',
4
+ 'auth',
5
+ 'backup',
6
+ 'cloud-component',
7
+ 'collection',
8
+ 'cron',
9
+ 'data-source',
10
+ 'error-handler',
11
+ 'event-source',
12
+ 'file',
13
+ 'message',
14
+ 'pdf',
15
+ 'ui-schema',
16
+ 'user',
17
+ 'web',
18
+ 'worker-thread',
19
+ 'instrumentation',
20
+ 'workflow',
21
+ 'env-secrets',
22
+ 'hera', // FIXME: refactor later
23
+ 'multi-app',
24
+ ];
@@ -0,0 +1,24 @@
1
+ export const defaultPlugins = [
2
+ 'action-bulk-edit',
3
+ 'action-bulk-update',
4
+ 'action-custom-request',
5
+ 'action-duplicate',
6
+ 'action-export',
7
+ 'action-import',
8
+ 'action-print',
9
+ 'block-calendar',
10
+ 'block-charts',
11
+ 'block-gantt',
12
+ 'block-kanban',
13
+ 'block-presentation',
14
+ 'field-china-region',
15
+ 'field-formula',
16
+ 'field-sequence',
17
+ 'field-encryption',
18
+ 'log-viewer',
19
+ 'otp',
20
+ 'full-text-search',
21
+ 'password-policy',
22
+ 'auth-pages',
23
+ 'manual-notification',
24
+ ];
package/src/index.ts ADDED
@@ -0,0 +1,69 @@
1
+ import './preload';
2
+
3
+ import { performance } from 'node:perf_hooks';
4
+ import TachybaseGlobal from '@tachybase/globals';
5
+ import { Gateway } from '@tachybase/server';
6
+ import { createDevPluginsSymlink, createStoragePluginsSymlink } from '@tachybase/utils';
7
+
8
+ import { Command } from 'commander';
9
+
10
+ import { getConfig } from './config';
11
+ import PluginPresets from './plugin-presets';
12
+ import { prepare } from './prepare';
13
+ import { parseEnvironment } from './utils';
14
+
15
+ // 解析环境变量
16
+ parseEnvironment();
17
+
18
+ const program = new Command();
19
+ program.name('tachybase-engine').version(require('../package.json').version);
20
+
21
+ const run = async () => {
22
+ // 注册 presets 插件
23
+ TachybaseGlobal.getInstance().set('PRESETS', {
24
+ tachybase: PluginPresets,
25
+ });
26
+
27
+ // 初始化插件链接
28
+ await createDevPluginsSymlink();
29
+ await createStoragePluginsSymlink();
30
+
31
+ console.log(`Engine loaded at ${performance.now().toFixed(2)} ms`);
32
+ await Gateway.getInstance().run({
33
+ mainAppOptions: (await getConfig()) as any,
34
+ });
35
+ };
36
+
37
+ // default action
38
+ program.allowUnknownOption().action(async () => {
39
+ await run();
40
+ });
41
+
42
+ program
43
+ .command('init')
44
+ .description('init a tachybase application project')
45
+ .option('--plugins <list>', 'Comma-separated list of plugins to install', (value) => {
46
+ return value
47
+ .split(',')
48
+ .map((s) => s.trim())
49
+ .filter(Boolean);
50
+ })
51
+ .argument('[name]', 'project name or path', 'my-app')
52
+ .action(async (name, options) => {
53
+ await prepare({ name, plugins: options.plugins, init: true });
54
+ });
55
+
56
+ program
57
+ .command('sync')
58
+ .description('sync latest packages in current project')
59
+ .option('--plugins <list>', 'Comma-separated list of plugins to sync', (value) => {
60
+ return value
61
+ .split(',')
62
+ .map((s) => s.trim())
63
+ .filter(Boolean);
64
+ })
65
+ .action(async (options) => {
66
+ await prepare({ plugins: options.plugins });
67
+ });
68
+
69
+ program.parse();