tego 1.3.52 → 1.3.54

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/config.d.ts CHANGED
@@ -5,25 +5,25 @@ export declare function getConfig(): Promise<{
5
5
  };
6
6
  plugins: string[];
7
7
  cacheManager: {
8
- defaultStore: string;
8
+ defaultStore: any;
9
9
  stores: {
10
10
  redis?: {
11
- url: string;
11
+ url: any;
12
12
  };
13
13
  memory: {
14
14
  store: string;
15
- max: number;
15
+ max: any;
16
16
  };
17
17
  };
18
18
  };
19
19
  logger: {
20
20
  request: {
21
21
  transports: ("console" | "file" | "dailyRotateFile")[];
22
- level: string;
22
+ level: any;
23
23
  };
24
24
  system: {
25
25
  transports: ("console" | "file" | "dailyRotateFile")[];
26
- level: string;
26
+ level: any;
27
27
  };
28
28
  };
29
29
  perfHooks: boolean;
package/lib/config.js CHANGED
@@ -1,6 +1,8 @@
1
+ var __create = Object.create;
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
4
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
7
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
8
  var __export = (target, all) => {
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
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
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
  var config_exports = {};
20
30
  __export(config_exports, {
@@ -22,6 +32,7 @@ __export(config_exports, {
22
32
  });
23
33
  module.exports = __toCommonJS(config_exports);
24
34
  var import_database = require("@tachybase/database");
35
+ var import_globals = __toESM(require("@tachybase/globals"));
25
36
  var import_logger = require("@tachybase/logger");
26
37
  async function getConfig() {
27
38
  return {
@@ -33,15 +44,15 @@ async function getConfig() {
33
44
  },
34
45
  plugins: ["tachybase"],
35
46
  cacheManager: {
36
- defaultStore: process.env.CACHE_DEFAULT_STORE || "memory",
47
+ defaultStore: import_globals.default.settings.cache.defaultStore ?? "memory",
37
48
  stores: {
38
49
  memory: {
39
50
  store: "memory",
40
- max: parseInt(process.env.CACHE_MEMORY_MAX) || 2e3
51
+ max: import_globals.default.settings.cache.memoryMax ?? 2e3
41
52
  },
42
- ...process.env.CACHE_REDIS_URL ? {
53
+ ...import_globals.default.settings.cache.redisUrl ? {
43
54
  redis: {
44
- url: process.env.CACHE_REDIS_URL
55
+ url: import_globals.default.settings.cache.redisUrl
45
56
  }
46
57
  } : {}
47
58
  }
package/lib/constants.js CHANGED
@@ -35,9 +35,21 @@ __export(constants_exports, {
35
35
  LAST_UPDATE_FILE_SUFFIX: () => LAST_UPDATE_FILE_SUFFIX
36
36
  });
37
37
  module.exports = __toCommonJS(constants_exports);
38
+ var import_node_fs = __toESM(require("node:fs"));
38
39
  var import_node_path = __toESM(require("node:path"));
40
+ var import_globals = __toESM(require("@tachybase/globals"));
39
41
  var import_utils = require("./utils");
40
42
  (0, import_utils.parseEnvironment)();
43
+ if (!import_node_fs.default.existsSync(`${process.env.TEGO_RUNTIME_HOME}/settings.js`)) {
44
+ import_node_fs.default.mkdirSync(`${process.env.TEGO_RUNTIME_HOME}`, { recursive: true });
45
+ import_node_fs.default.copyFileSync(import_node_path.default.join(__dirname, "../presets/settings.js"), `${process.env.TEGO_RUNTIME_HOME}/settings.js`);
46
+ }
47
+ import_globals.default.settings = require(`${process.env.TEGO_RUNTIME_HOME}/settings.js`);
48
+ for (const key in import_globals.default.settings.env) {
49
+ if (!process.env[key]) {
50
+ process.env[key] = import_globals.default.settings.env[key];
51
+ }
52
+ }
41
53
  const DEFAULT_DEV_PLUGINS_PATH = import_node_path.default.join(process.env.TEGO_RUNTIME_HOME, "plugins", "dev");
42
54
  const DEFAULT_REMOTE_PLUGINS_PATH = import_node_path.default.join(process.env.TEGO_RUNTIME_HOME, "plugins", "remote");
43
55
  const DEFAULT_BUILTIN_PLUGINS_PATH = import_node_path.default.join(process.env.TEGO_RUNTIME_HOME, "plugins", "builtin");
@@ -1,20 +1,15 @@
1
1
  import { Plugin } from '@tego/core';
2
2
  export declare class PluginPresets extends Plugin {
3
- splitNames(name: string): string[];
4
- getBuiltInPlugins(): string[];
5
- parseNames(plugins: string): string[][];
6
- getExternalPlugins(): {
7
- installedPlugins: string[];
8
- disabledPlugins: string[];
9
- };
3
+ getBuiltInPlugins(): any;
4
+ getExternalPlugins(): any;
10
5
  getPackageJson(name: any): Promise<any>;
11
- allPlugins(): Promise<any[]>;
12
- getPluginToBeUpgraded(): Promise<any[]>;
6
+ allPlugins(): Promise<any>;
7
+ getPluginToBeUpgraded(): Promise<any>;
13
8
  updateOrCreatePlugins(): Promise<void>;
14
9
  createIfNotExists(): Promise<void>;
15
10
  install(): Promise<void>;
16
11
  upgrade(): Promise<void>;
17
- getForbidSubAppPlugin(): string[];
12
+ getForbidSubAppPlugin(): any;
18
13
  forbidSubAppPlugin(): Promise<void>;
19
14
  filterForbidSubAppPlugin(plugins: any[]): Promise<void>;
20
15
  }
@@ -1,6 +1,8 @@
1
+ var __create = Object.create;
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
4
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
7
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
8
  var __export = (target, all) => {
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
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
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
  var plugin_presets_exports = {};
20
30
  __export(plugin_presets_exports, {
@@ -22,35 +32,34 @@ __export(plugin_presets_exports, {
22
32
  default: () => plugin_presets_default
23
33
  });
24
34
  module.exports = __toCommonJS(plugin_presets_exports);
35
+ var import_globals = __toESM(require("@tachybase/globals"));
25
36
  var import_core = require("@tego/core");
26
37
  const _PluginPresets = class _PluginPresets extends import_core.Plugin {
27
- splitNames(name) {
28
- return (name || "").split(",").filter(Boolean);
29
- }
30
38
  getBuiltInPlugins() {
31
- const { PRESETS_BULTIN_PLUGINS } = process.env;
32
- if (!PRESETS_BULTIN_PLUGINS) {
39
+ if (!import_globals.default.settings.presets.builtinPlugins) {
33
40
  throw new Error(
34
- "PRESETS_BUILTIN_PLUGINS is not defined! Please refer to the .env.example file for the correct configuration."
41
+ "presets.builtinPlugins is not defined! Please refer to the settings.js file for the correct configuration."
35
42
  );
36
43
  }
37
- const [installedPlugins] = this.parseNames(PRESETS_BULTIN_PLUGINS);
38
- return installedPlugins;
39
- }
40
- parseNames(plugins) {
41
- const installedPlugins = this.splitNames(plugins).filter((name) => !name.startsWith("!"));
42
- const disabledPlugins = this.splitNames(plugins).filter((name) => name.startsWith("!")).map((name) => name.slice(1));
43
- return [installedPlugins, disabledPlugins];
44
+ return import_globals.default.settings.presets.builtinPlugins;
44
45
  }
45
46
  getExternalPlugins() {
46
- const { PRESETS_EXTERNAL_PLUGINS } = process.env;
47
- if (!PRESETS_EXTERNAL_PLUGINS) {
47
+ if (!import_globals.default.settings.presets.externalPlugins) {
48
48
  throw new Error(
49
- "PRESETS_EXTERNAL_PLUGINS is not defined! Please refer to the .env.example file for the correct configuration."
49
+ "presets.externalPlugins is not defined! Please refer to the settings.js file for the correct configuration."
50
50
  );
51
51
  }
52
- const [installedPlugins, disabledPlugins] = this.parseNames(PRESETS_EXTERNAL_PLUGINS);
53
- return { installedPlugins, disabledPlugins };
52
+ return import_globals.default.settings.presets.externalPlugins.reduce(
53
+ (acc, cur) => {
54
+ if (cur.enabledByDefault) {
55
+ acc.installedPlugins.push(cur.name);
56
+ } else {
57
+ acc.disabledPlugins.push(cur.name);
58
+ }
59
+ return acc;
60
+ },
61
+ { installedPlugins: [], disabledPlugins: [] }
62
+ );
54
63
  }
55
64
  async getPackageJson(name) {
56
65
  let packageName = name;
@@ -192,8 +201,7 @@ const _PluginPresets = class _PluginPresets extends import_core.Plugin {
192
201
  if (this.app.name === "main") {
193
202
  return [];
194
203
  }
195
- const { FORBID_SUB_APP_PLUGINS } = process.env;
196
- return FORBID_SUB_APP_PLUGINS ? FORBID_SUB_APP_PLUGINS.split(",") : [];
204
+ return import_globals.default.settings.misc.forbidSubAppPlugins;
197
205
  }
198
206
  // 从环境变量读取禁止子应用装载的插件
199
207
  async forbidSubAppPlugin() {
package/lib/prepare.js CHANGED
@@ -44,16 +44,6 @@ async function prepare({
44
44
  plugins = [],
45
45
  init = false
46
46
  }) {
47
- if (init) {
48
- if (import_node_fs.default.existsSync(name)) {
49
- console.log(`project folder ${name} already exists, exit now.`);
50
- return;
51
- }
52
- import_node_fs.default.mkdirSync(name);
53
- (0, import_utils.initEnvFile)(name);
54
- } else {
55
- name = import_node_process.default.cwd();
56
- }
57
47
  let npmExist = true;
58
48
  try {
59
49
  await (0, import_execa.default)("npm", ["--version"]);
package/lib/utils.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- export declare function initEnvFile(name: string): void;
2
1
  export declare function parseEnvironment(): void;
3
2
  export declare function guessServePath(): string | false;
4
3
  export declare function downloadTar(packageName: string, target: string): Promise<void>;
@@ -15,3 +14,4 @@ export declare class TegoIndexManager {
15
14
  private fetchIndexFile;
16
15
  getIndex(): Promise<any>;
17
16
  }
17
+ export declare function convertEnvToSettings(flatEnv: Record<string, string | undefined>): any;
package/lib/utils.js CHANGED
@@ -29,9 +29,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  var utils_exports = {};
30
30
  __export(utils_exports, {
31
31
  TegoIndexManager: () => TegoIndexManager,
32
+ convertEnvToSettings: () => convertEnvToSettings,
32
33
  downloadTar: () => downloadTar,
33
34
  guessServePath: () => guessServePath,
34
- initEnvFile: () => initEnvFile,
35
35
  parseEnvironment: () => parseEnvironment
36
36
  });
37
37
  module.exports = __toCommonJS(utils_exports);
@@ -46,60 +46,16 @@ var import_dotenv = require("dotenv");
46
46
  var import_npm_registry_fetch = __toESM(require("npm-registry-fetch"));
47
47
  var tar = __toESM(require("tar"));
48
48
  var import_constants = require("./constants");
49
- function initEnvFile(name) {
50
- const envPath = (0, import_node_path.resolve)(name, ".env");
51
- if (!import_node_fs.default.existsSync(envPath)) {
52
- import_node_fs.default.copyFileSync((0, import_node_path.resolve)(__dirname, "../presets/.env.example"), envPath);
53
- console.info(".env file created.");
54
- } else {
55
- console.info(".env file already exists.");
56
- }
57
- }
58
- __name(initEnvFile, "initEnvFile");
59
- function parseEnv(name) {
60
- if (name === "DB_UNDERSCORED") {
61
- if (process.env.DB_UNDERSCORED === "true") {
62
- return "true";
63
- }
64
- if (process.env.DB_UNDERSCORED) {
65
- return "true";
66
- }
67
- return "false";
68
- }
69
- }
70
- __name(parseEnv, "parseEnv");
71
49
  function parseEnvironment() {
72
50
  const env = {
73
- APP_ENV: "development",
74
- APP_KEY: "test-jwt-secret",
75
- APP_PORT: 3e3,
76
- API_BASE_PATH: "/api/",
77
- DB_DIALECT: "sqlite",
78
- DB_STORAGE: "storage/db/tachybase.sqlite",
79
- DB_TIMEZONE: "+00:00",
80
- DB_UNDERSCORED: parseEnv("DB_UNDERSCORED"),
81
- DEFAULT_STORAGE_TYPE: "local",
82
- RUN_MODE: "engine",
83
- LOCAL_STORAGE_DEST: "storage/uploads",
84
- PLUGIN_STORAGE_PATH: "storage/plugins",
85
- MFSU_AD: "none",
86
- WS_PATH: "/ws",
87
- SOCKET_PATH: "storage/gateway.sock",
88
- PLUGIN_PACKAGE_PREFIX: "@tachybase/plugin-,@tachybase/module-",
89
- SERVER_TSCONFIG_PATH: "./tsconfig.server.json",
90
- PLAYWRIGHT_AUTH_FILE: "storage/playwright/.auth/admin.json",
91
- CACHE_DEFAULT_STORE: "memory",
92
- CACHE_MEMORY_MAX: 2e3,
93
- PLUGIN_STATICS_PATH: "/static/plugins/",
94
- LOGGER_BASE_PATH: "storage/logs",
95
- APP_SERVER_BASE_URL: "",
96
- APP_PUBLIC_PATH: "/",
97
51
  TEGO_HOME: (0, import_node_path.join)(import_node_os.default.homedir(), ".tego"),
98
52
  TEGO_RUNTIME_NAME: "current"
99
53
  };
100
- (0, import_dotenv.config)({
101
- path: (0, import_node_path.resolve)(process.cwd(), process.env.APP_ENV_PATH || ".env")
102
- });
54
+ if ((0, import_node_fs.existsSync)((0, import_node_path.resolve)(process.cwd(), ".env"))) {
55
+ (0, import_dotenv.config)({
56
+ path: (0, import_node_path.resolve)(process.cwd(), ".env")
57
+ });
58
+ }
103
59
  if (!process.env.TEGO_RUNTIME_HOME && !process.env.TEGO_RUNTIME_NAME && import_node_fs.default.existsSync((0, import_node_path.resolve)(process.cwd(), "storage"))) {
104
60
  process.env.TEGO_RUNTIME_HOME = process.cwd();
105
61
  }
@@ -206,7 +162,7 @@ const _TegoIndexManager = class _TegoIndexManager {
206
162
  constructor({
207
163
  indexUrl,
208
164
  baseDir,
209
- lastUpdateSuffix = ".last-update-at"
165
+ lastUpdateSuffix = import_constants.LAST_UPDATE_FILE_SUFFIX
210
166
  }) {
211
167
  this.indexUrl = indexUrl;
212
168
  this.indexFile = (0, import_node_path.join)(baseDir, "index.tego.json");
@@ -242,11 +198,62 @@ const _TegoIndexManager = class _TegoIndexManager {
242
198
  };
243
199
  __name(_TegoIndexManager, "TegoIndexManager");
244
200
  let TegoIndexManager = _TegoIndexManager;
201
+ function convertEnvToSettings(flatEnv) {
202
+ const settings = {
203
+ env: {},
204
+ logger: {},
205
+ database: {},
206
+ cache: {},
207
+ encryptionField: {},
208
+ presets: {},
209
+ worker: {},
210
+ export: {},
211
+ misc: {}
212
+ };
213
+ for (const key in flatEnv) {
214
+ const value = flatEnv[key];
215
+ if (value === void 0) continue;
216
+ if (key.startsWith("LOGGER_")) {
217
+ const subKey = key.replace("LOGGER_", "").toLowerCase();
218
+ if (subKey === "transport") {
219
+ settings.logger.transport = value.split(",").map((x) => x.trim());
220
+ } else if (subKey === "maxfiles") {
221
+ settings.logger.maxFiles = value;
222
+ } else if (subKey === "maxsize") {
223
+ settings.logger.maxSize = value;
224
+ } else if (subKey === "format") {
225
+ settings.logger.format = value;
226
+ } else {
227
+ settings.logger[subKey] = value;
228
+ }
229
+ continue;
230
+ }
231
+ if (key.startsWith("DB_")) {
232
+ const subKey = key.replace("DB_", "").toLowerCase();
233
+ if (subKey.startsWith("dialect_options_ssl_")) {
234
+ const sslKey = subKey.replace("dialect_options_ssl_", "");
235
+ settings.database.ssl = settings.database.ssl || {};
236
+ settings.database.ssl[sslKey] = value;
237
+ } else {
238
+ settings.database[subKey] = value;
239
+ }
240
+ continue;
241
+ }
242
+ if (key.startsWith("CACHE_")) {
243
+ const subKey = key.replace("CACHE_", "").toLowerCase();
244
+ settings.cache[subKey] = value;
245
+ continue;
246
+ }
247
+ settings.env[key] = value;
248
+ }
249
+ return settings;
250
+ }
251
+ __name(convertEnvToSettings, "convertEnvToSettings");
245
252
  // Annotate the CommonJS export names for ESM import in node:
246
253
  0 && (module.exports = {
247
254
  TegoIndexManager,
255
+ convertEnvToSettings,
248
256
  downloadTar,
249
257
  guessServePath,
250
- initEnvFile,
251
258
  parseEnvironment
252
259
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tego",
3
- "version": "1.3.52",
3
+ "version": "1.3.54",
4
4
  "description": "",
5
5
  "keywords": [
6
6
  "tego",
@@ -24,7 +24,7 @@
24
24
  "dependencies": {
25
25
  "@koa/cors": "5.0.0",
26
26
  "@koa/multer": "3.1.0",
27
- "@socketregistry/yocto-spinner": "1.0.20",
27
+ "@socketregistry/yocto-spinner": "1.0.23",
28
28
  "async-mutex": "0.5.0",
29
29
  "axios": "0.29.0",
30
30
  "cache-manager": "5.7.6",
@@ -35,39 +35,39 @@
35
35
  "execa": "^5.1.1",
36
36
  "i18next": "23.16.8",
37
37
  "jsonwebtoken": "8.5.1",
38
- "koa": "^2.16.1",
38
+ "koa": "^2.16.2",
39
39
  "koa-bodyparser": "4.4.1",
40
40
  "lodash": "4.17.21",
41
41
  "multer": "2.0.2",
42
- "mysql2": "3.14.3",
42
+ "mysql2": "3.14.4",
43
43
  "npm-registry-fetch": "19.0.0",
44
44
  "pg": "^8.16.3",
45
45
  "react": "18.3.1",
46
46
  "sequelize": "6.37.7",
47
47
  "sqlite3": "5.1.7",
48
- "tar": "7.4.3",
48
+ "tar": "7.5.1",
49
49
  "umzug": "3.8.2",
50
50
  "winston": "3.17.0",
51
51
  "winston-daily-rotate-file": "^5.0.0",
52
- "@tachybase/actions": "1.3.52",
53
- "@tachybase/cache": "1.3.52",
54
- "@tachybase/auth": "1.3.52",
55
- "@tachybase/acl": "1.3.52",
56
- "@tachybase/database": "1.3.52",
57
- "@tachybase/evaluators": "1.3.52",
58
- "@tachybase/loader": "1.3.52",
59
- "@tachybase/globals": "1.3.52",
60
- "@tachybase/data-source": "1.3.52",
61
- "@tachybase/logger": "1.3.52",
62
- "@tachybase/resourcer": "1.3.52",
63
- "@tachybase/schema": "1.3.52",
64
- "@tachybase/utils": "1.3.52",
65
- "@tego/server": "1.3.52",
66
- "@tego/core": "1.3.52"
52
+ "@tachybase/acl": "1.3.54",
53
+ "@tachybase/actions": "1.3.54",
54
+ "@tachybase/auth": "1.3.54",
55
+ "@tachybase/data-source": "1.3.54",
56
+ "@tachybase/cache": "1.3.54",
57
+ "@tachybase/database": "1.3.54",
58
+ "@tachybase/evaluators": "1.3.54",
59
+ "@tachybase/globals": "1.3.54",
60
+ "@tachybase/logger": "1.3.54",
61
+ "@tachybase/resourcer": "1.3.54",
62
+ "@tachybase/loader": "1.3.54",
63
+ "@tachybase/schema": "1.3.54",
64
+ "@tego/server": "1.3.54",
65
+ "@tego/core": "1.3.54",
66
+ "@tachybase/utils": "1.3.54"
67
67
  },
68
68
  "devDependencies": {
69
69
  "@types/lodash": "4.17.20",
70
- "@yao-pkg/pkg": "6.5.1"
70
+ "@yao-pkg/pkg": "6.6.0"
71
71
  },
72
72
  "pkg": {
73
73
  "targets": [
@@ -0,0 +1,293 @@
1
+ /** @type {import('@tachybase/globals').Settings} */
2
+ module.exports = {
3
+ /**
4
+ * 如果对应的环境变量没设置,则使用这里面的值,如果有设置,不用这里的值
5
+ */
6
+ env: {
7
+ APP_ENV: 'development',
8
+ APP_PORT: 3000,
9
+ APP_KEY: 'test-key',
10
+ API_BASE_PATH: '/api/',
11
+ INIT_APP_LANG: 'en-US',
12
+ INIT_ROOT_EMAIL: 'admin@tachybase.com',
13
+ INIT_ROOT_USERNAME: 'tego',
14
+ INIT_ROOT_PASSWORD: 'tego',
15
+ INIT_ROOT_NICKNAME: 'Admin',
16
+ PLUGIN_STORAGE_PATH: 'storage/plugins',
17
+ WS_PATH: '/ws',
18
+ SOCKET_PATH: 'storage/gateway.sock',
19
+ PLUGIN_PACKAGE_PREFIX: '@tachybase/plugin-,@tachybase/module-',
20
+ SERVER_TSCONFIG_PATH: './tsconfig.server.json',
21
+ PLAYWRIGHT_AUTH_FILE: 'storage/playwright/.auth/admin.json',
22
+ PLUGIN_STATICS_PATH: '/static/plugins/',
23
+ APP_SERVER_BASE_URL: '',
24
+ APP_PUBLIC_PATH: '/',
25
+ // 开发环境测试locale 强制使用 cache
26
+ // FORCE_LOCALE_CACHE: '1',
27
+ },
28
+ logger: {
29
+ /**
30
+ * console | file | dailyRotateFile
31
+ */
32
+ transport: ['console', 'dailyRotateFile'],
33
+
34
+ /**
35
+ *
36
+ */
37
+ basePath: 'storage/logs',
38
+ /**
39
+ *
40
+ * error | warn | info | debug
41
+ * /
42
+ // level: 'warn',
43
+
44
+ /**
45
+ * If LOGGER_TRANSPORT is dailyRotateFile and using days, add 'd' as the suffix.
46
+ */
47
+ // maxFiles: '14d',
48
+
49
+ /**
50
+ * add 'k', 'm', 'g' as the suffix.
51
+ */
52
+ // maxSize: '10m',
53
+
54
+ /**
55
+ * json | splitter, split by '|' character
56
+ */
57
+ // format: '',
58
+ },
59
+
60
+ database: {
61
+ /**
62
+ *
63
+ */
64
+ dialect: 'sqlite',
65
+
66
+ /**
67
+ *
68
+ */
69
+ storage: 'storage/db/tego.sqlite',
70
+
71
+ /**
72
+ *
73
+ */
74
+ // tablePrefix: ''
75
+
76
+ /**
77
+ *
78
+ */
79
+ // host: 'localhost'
80
+
81
+ /**
82
+ *
83
+ */
84
+ // port: 5432,
85
+
86
+ /**
87
+ *
88
+ */
89
+ // database: 'tego',
90
+
91
+ /**
92
+ *
93
+ */
94
+ // user: 'tego',
95
+
96
+ /**
97
+ *
98
+ */
99
+ // password: 'tego',
100
+
101
+ /**
102
+ *
103
+ */
104
+ // logging: true,
105
+
106
+ /**
107
+ *
108
+ */
109
+ underscored: false,
110
+
111
+ /**
112
+ * mysql/postgres
113
+ */
114
+ timezone: '+00:00',
115
+
116
+ /**
117
+ * ssl config
118
+ */
119
+ ssl: {
120
+ // ca: '',
121
+ // key: '',
122
+ // cert: '',
123
+ // rejectUnauthorized: true,
124
+ },
125
+ },
126
+
127
+ cache: {
128
+ /**
129
+ *
130
+ */
131
+ defaultStore: 'memory',
132
+
133
+ /**
134
+ * max number of items in memory cache
135
+ */
136
+ memoryMax: 2000,
137
+
138
+ /**
139
+ *
140
+ */
141
+ // redisUrl: ''
142
+ },
143
+
144
+ encryptionField: {
145
+ /**
146
+ *
147
+ */
148
+ // key: '',
149
+ },
150
+
151
+ presets: {
152
+ /**
153
+ * 默认启用,并且不可删除
154
+ */
155
+ builtinPlugins: [
156
+ 'acl',
157
+ 'app-info',
158
+ 'auth',
159
+ 'backup',
160
+ 'cloud-component',
161
+ 'collection',
162
+ 'cron',
163
+ 'data-source',
164
+ 'error-handler',
165
+ 'event-source',
166
+ 'file',
167
+ 'workflow',
168
+ 'message',
169
+ 'pdf',
170
+ 'ui-schema',
171
+ 'user',
172
+ 'web',
173
+ 'worker-thread',
174
+ 'env-secrets',
175
+ ],
176
+ /**
177
+ * 可删除
178
+ */
179
+ externalPlugins: [
180
+ { name: 'action-bulk-edit', enabledByDefault: true },
181
+ { name: 'action-bulk-update', enabledByDefault: true },
182
+ { name: 'action-custom-request', enabledByDefault: true },
183
+ { name: 'action-duplicate', enabledByDefault: true },
184
+ { name: 'action-export', enabledByDefault: true },
185
+ { name: 'action-import', enabledByDefault: true },
186
+ { name: 'action-print', enabledByDefault: true },
187
+ { name: 'block-calendar', enabledByDefault: true },
188
+ { name: 'block-charts', enabledByDefault: true },
189
+ { name: 'block-gantt', enabledByDefault: true },
190
+ { name: 'block-kanban', enabledByDefault: true },
191
+ { name: 'block-presentation', enabledByDefault: true },
192
+ { name: 'field-china-region', enabledByDefault: true },
193
+ { name: 'field-formula', enabledByDefault: true },
194
+ { name: 'field-sequence', enabledByDefault: true },
195
+ { name: 'field-encryption', enabledByDefault: true },
196
+ { name: 'log-viewer', enabledByDefault: true },
197
+ { name: 'otp', enabledByDefault: true },
198
+ { name: 'instrumentation', enabledByDefault: true },
199
+ { name: 'full-text-search', enabledByDefault: true },
200
+ { name: 'password-policy', enabledByDefault: true },
201
+ { name: 'auth-pages', enabledByDefault: true },
202
+ { name: 'manual-notification', enabledByDefault: true },
203
+ { name: 'auth-main-app', enabledByDefault: true },
204
+
205
+ { name: 'adapter-bullmq', enabledByDefault: false },
206
+ { name: 'adapter-red-node', enabledByDefault: false },
207
+ { name: 'adapter-remix', enabledByDefault: false },
208
+ { name: 'api-keys', enabledByDefault: false },
209
+ { name: 'audit-logs', enabledByDefault: false },
210
+ { name: 'auth-cas', enabledByDefault: false },
211
+ { name: 'auth-dingtalk', enabledByDefault: false },
212
+ { name: 'auth-lark', enabledByDefault: false },
213
+ { name: 'auth-oidc', enabledByDefault: false },
214
+ { name: 'auth-saml', enabledByDefault: false },
215
+ { name: 'auth-sms', enabledByDefault: false },
216
+ { name: 'auth-wechat', enabledByDefault: false },
217
+ { name: 'auth-wecom', enabledByDefault: false },
218
+ { name: 'block-comments', enabledByDefault: false },
219
+ { name: 'block-map', enabledByDefault: false },
220
+ { name: 'block-step-form', enabledByDefault: false },
221
+ { name: 'data-source-common', enabledByDefault: false },
222
+ { name: 'demos-game-runesweeper', enabledByDefault: false },
223
+ { name: 'devtools', enabledByDefault: false },
224
+ { name: 'field-markdown-vditor', enabledByDefault: false },
225
+ { name: 'field-snapshot', enabledByDefault: false },
226
+ { name: 'hera', enabledByDefault: false },
227
+ { name: 'i18n-editor', enabledByDefault: false },
228
+ { name: 'multi-app', enabledByDefault: false },
229
+ { name: 'multi-app-share-collection', enabledByDefault: false },
230
+ { name: 'online-user', enabledByDefault: false },
231
+ { name: 'simple-cms', enabledByDefault: false },
232
+ { name: 'sub-accounts', enabledByDefault: false },
233
+ { name: 'theme-editor', enabledByDefault: false },
234
+ { name: 'workflow-approval', enabledByDefault: false },
235
+ { name: 'ai-chat', enabledByDefault: false },
236
+ { name: 'department', enabledByDefault: false },
237
+ { name: 'workflow-analysis', enabledByDefault: false },
238
+ { name: 'api-logs', enabledByDefault: false },
239
+ { name: 'ocr-convert', enabledByDefault: false },
240
+ { name: 'text-copy', enabledByDefault: false },
241
+ { name: 'user-manual-feishu', enabledByDefault: false },
242
+ { name: 'form-design', enabledByDefault: false },
243
+ ],
244
+
245
+ /**
246
+ *
247
+ */
248
+ runtimePlugins: [],
249
+ },
250
+
251
+ worker: {
252
+ /**
253
+ * -1 为不限制,自动设置为核心数量
254
+ * 0 禁用 worker
255
+ * 其他值为 worker 数量
256
+ */
257
+ count: -1,
258
+
259
+ /**
260
+ * -1 为最大为核心数量
261
+ * 其他值为最大 worker 数量
262
+ */
263
+ countMax: -1,
264
+
265
+ /**
266
+ * 错误尝试次数
267
+ */
268
+ // errorRetry: 3
269
+
270
+ /**
271
+ * MB
272
+ */
273
+ // maxMemory: 4096
274
+ },
275
+
276
+ /**
277
+ * export config, max length of export data to use main thread and page size in worker thread
278
+ */
279
+ export: {
280
+ /**
281
+ *
282
+ */
283
+ // lengthMax: 2000,
284
+ /**
285
+ *
286
+ */
287
+ // workerPageSize: 1000
288
+ },
289
+
290
+ misc: {
291
+ forbidSubAppPlugins: ['multi-app', 'manual-notification', 'multi-app-share-collection'],
292
+ },
293
+ };
@@ -0,0 +1,24 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { convertEnvToSettings } from '../utils';
4
+
5
+ describe('convertEnvToSettings', () => {
6
+ it('should convert flat env into structured settings object', () => {
7
+ const input = {
8
+ LOGGER_TRANSPORT: 'console,dailyRotateFile',
9
+ LOGGER_MAX_FILES: '7d',
10
+ DB_STORAGE: 'storage/db/tachybase.sqlite',
11
+ CACHE_DEFAULT_STORE: 'memory',
12
+ INIT_APP_LANG: 'zh-CN',
13
+ };
14
+
15
+ const result = convertEnvToSettings(input as any);
16
+
17
+ expect(result.logger.transport).toEqual(['console', 'dailyRotateFile']);
18
+ expect(result.logger.max_files).toBeUndefined(); // 未提供
19
+ expect(result.logger.maxFiles).toBe('7d');
20
+ expect(result.database.storage).toBe('storage/db/tachybase.sqlite');
21
+ expect(result.cache.default_store).toBe('memory');
22
+ expect(result.env.INIT_APP_LANG).toBe('zh-CN');
23
+ });
24
+ });
package/src/config.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { parseDatabaseOptionsFromEnv } from '@tachybase/database';
2
+ import TachybaseGlobal from '@tachybase/globals';
2
3
  import { getLoggerLevel, getLoggerTransport } from '@tachybase/logger';
3
4
 
4
5
  export async function getConfig() {
@@ -11,16 +12,16 @@ export async function getConfig() {
11
12
  },
12
13
  plugins: ['tachybase'],
13
14
  cacheManager: {
14
- defaultStore: process.env.CACHE_DEFAULT_STORE || 'memory',
15
+ defaultStore: TachybaseGlobal.settings.cache.defaultStore ?? 'memory',
15
16
  stores: {
16
17
  memory: {
17
18
  store: 'memory',
18
- max: parseInt(process.env.CACHE_MEMORY_MAX) || 2000,
19
+ max: TachybaseGlobal.settings.cache.memoryMax ?? 2000,
19
20
  },
20
- ...(process.env.CACHE_REDIS_URL
21
+ ...(TachybaseGlobal.settings.cache.redisUrl
21
22
  ? {
22
23
  redis: {
23
- url: process.env.CACHE_REDIS_URL,
24
+ url: TachybaseGlobal.settings.cache.redisUrl,
24
25
  },
25
26
  }
26
27
  : {}),
package/src/constants.ts CHANGED
@@ -1,10 +1,25 @@
1
+ import fs from 'node:fs';
1
2
  import path from 'node:path';
3
+ import TachybaseGlobal from '@tachybase/globals';
2
4
 
3
5
  import { parseEnvironment } from './utils';
4
6
 
5
7
  // 解析环境变量
6
8
  parseEnvironment();
7
9
 
10
+ // 读取配置
11
+ if (!fs.existsSync(`${process.env.TEGO_RUNTIME_HOME}/settings.js`)) {
12
+ fs.mkdirSync(`${process.env.TEGO_RUNTIME_HOME}`, { recursive: true });
13
+ fs.copyFileSync(path.join(__dirname, '../presets/settings.js'), `${process.env.TEGO_RUNTIME_HOME}/settings.js`);
14
+ }
15
+ TachybaseGlobal.settings = require(`${process.env.TEGO_RUNTIME_HOME}/settings.js`);
16
+
17
+ for (const key in TachybaseGlobal.settings.env) {
18
+ if (!process.env[key]) {
19
+ process.env[key] = TachybaseGlobal.settings.env[key];
20
+ }
21
+ }
22
+
8
23
  export const DEFAULT_DEV_PLUGINS_PATH = path.join(process.env.TEGO_RUNTIME_HOME, 'plugins', 'dev');
9
24
  export const DEFAULT_REMOTE_PLUGINS_PATH = path.join(process.env.TEGO_RUNTIME_HOME, 'plugins', 'remote');
10
25
  export const DEFAULT_BUILTIN_PLUGINS_PATH = path.join(process.env.TEGO_RUNTIME_HOME, 'plugins', 'builtin');
@@ -1,41 +1,35 @@
1
+ import TachybaseGlobal from '@tachybase/globals';
1
2
  import { Plugin, PluginManager } from '@tego/core';
3
+
2
4
  import _ from 'lodash';
3
5
 
4
6
  export class PluginPresets extends Plugin {
5
- splitNames(name: string) {
6
- return (name || '').split(',').filter(Boolean);
7
- }
8
-
9
7
  getBuiltInPlugins() {
10
- const { PRESETS_BULTIN_PLUGINS } = process.env;
11
- if (!PRESETS_BULTIN_PLUGINS) {
8
+ if (!TachybaseGlobal.settings.presets.builtinPlugins) {
12
9
  throw new Error(
13
- 'PRESETS_BUILTIN_PLUGINS is not defined! Please refer to the .env.example file for the correct configuration.',
10
+ 'presets.builtinPlugins is not defined! Please refer to the settings.js file for the correct configuration.',
14
11
  );
15
12
  }
16
- const [installedPlugins] = this.parseNames(PRESETS_BULTIN_PLUGINS);
17
- return installedPlugins;
18
- }
19
-
20
- parseNames(plugins: string) {
21
- const installedPlugins = this.splitNames(plugins).filter((name) => !name.startsWith('!'));
22
- const disabledPlugins = this.splitNames(plugins)
23
- .filter((name) => name.startsWith('!'))
24
- .map((name) => name.slice(1));
25
-
26
- return [installedPlugins, disabledPlugins];
13
+ return TachybaseGlobal.settings.presets.builtinPlugins;
27
14
  }
28
15
 
29
16
  getExternalPlugins() {
30
- const { PRESETS_EXTERNAL_PLUGINS } = process.env;
31
- if (!PRESETS_EXTERNAL_PLUGINS) {
17
+ if (!TachybaseGlobal.settings.presets.externalPlugins) {
32
18
  throw new Error(
33
- 'PRESETS_EXTERNAL_PLUGINS is not defined! Please refer to the .env.example file for the correct configuration.',
19
+ 'presets.externalPlugins is not defined! Please refer to the settings.js file for the correct configuration.',
34
20
  );
35
21
  }
36
- const [installedPlugins, disabledPlugins] = this.parseNames(PRESETS_EXTERNAL_PLUGINS);
37
-
38
- return { installedPlugins, disabledPlugins };
22
+ return TachybaseGlobal.settings.presets.externalPlugins.reduce(
23
+ (acc, cur) => {
24
+ if (cur.enabledByDefault) {
25
+ acc.installedPlugins.push(cur.name);
26
+ } else {
27
+ acc.disabledPlugins.push(cur.name);
28
+ }
29
+ return acc;
30
+ },
31
+ { installedPlugins: [] as string[], disabledPlugins: [] as string[] },
32
+ );
39
33
  }
40
34
 
41
35
  async getPackageJson(name) {
@@ -189,8 +183,7 @@ export class PluginPresets extends Plugin {
189
183
  if (this.app.name === 'main') {
190
184
  return [];
191
185
  }
192
- const { FORBID_SUB_APP_PLUGINS } = process.env;
193
- return FORBID_SUB_APP_PLUGINS ? FORBID_SUB_APP_PLUGINS.split(',') : [];
186
+ return TachybaseGlobal.settings.misc.forbidSubAppPlugins;
194
187
  }
195
188
  // 从环境变量读取禁止子应用装载的插件
196
189
  async forbidSubAppPlugin() {
package/src/prepare.ts CHANGED
@@ -5,13 +5,8 @@ import process from 'node:process';
5
5
  import yoctoSpinner from '@socketregistry/yocto-spinner/index.cjs';
6
6
  import execa from 'execa';
7
7
 
8
- import {
9
- DEFAULT_BUILTIN_PLUGINS_PATH,
10
- DEFAULT_WEB_PACKAGE_NAME,
11
- INDEX_TEGO_URL,
12
- LAST_UPDATE_FILE_SUFFIX,
13
- } from './constants';
14
- import { downloadTar, initEnvFile, TegoIndexManager } from './utils';
8
+ import { DEFAULT_BUILTIN_PLUGINS_PATH, DEFAULT_WEB_PACKAGE_NAME, INDEX_TEGO_URL } from './constants';
9
+ import { downloadTar, TegoIndexManager } from './utils';
15
10
 
16
11
  export async function prepare({
17
12
  name,
@@ -22,17 +17,6 @@ export async function prepare({
22
17
  plugins: string[];
23
18
  init?: boolean;
24
19
  }) {
25
- if (init) {
26
- if (fs.existsSync(name)) {
27
- console.log(`project folder ${name} already exists, exit now.`);
28
- return;
29
- }
30
- fs.mkdirSync(name);
31
- initEnvFile(name);
32
- } else {
33
- name = process.cwd();
34
- }
35
-
36
20
  let npmExist = true;
37
21
  // 判断 npm 是否存在
38
22
  try {
package/src/utils.ts CHANGED
@@ -15,64 +15,22 @@ import { config } from 'dotenv';
15
15
  import npmRegistryFetch from 'npm-registry-fetch';
16
16
  import * as tar from 'tar';
17
17
 
18
- import { DEFAULT_WEB_PACKAGE_NAME, INDEX_TEGO_URL, LAST_UPDATE_FILE_SUFFIX } from './constants';
19
-
20
- export function initEnvFile(name: string) {
21
- const envPath = resolve(name, '.env');
22
- if (!fs.existsSync(envPath)) {
23
- fs.copyFileSync(resolve(__dirname, '../presets/.env.example'), envPath);
24
- console.info('.env file created.');
25
- } else {
26
- console.info('.env file already exists.');
27
- }
28
- }
29
-
30
- function parseEnv(name: string) {
31
- if (name === 'DB_UNDERSCORED') {
32
- if (process.env.DB_UNDERSCORED === 'true') {
33
- return 'true';
34
- }
35
- if (process.env.DB_UNDERSCORED) {
36
- return 'true';
37
- }
38
- return 'false';
39
- }
40
- }
18
+ import { DEFAULT_WEB_PACKAGE_NAME, LAST_UPDATE_FILE_SUFFIX } from './constants';
41
19
 
42
20
  export function parseEnvironment() {
43
21
  const env = {
44
- APP_ENV: 'development',
45
- APP_KEY: 'test-jwt-secret',
46
- APP_PORT: 3000,
47
- API_BASE_PATH: '/api/',
48
- DB_DIALECT: 'sqlite',
49
- DB_STORAGE: 'storage/db/tachybase.sqlite',
50
- DB_TIMEZONE: '+00:00',
51
- DB_UNDERSCORED: parseEnv('DB_UNDERSCORED'),
52
- DEFAULT_STORAGE_TYPE: 'local',
53
- RUN_MODE: 'engine',
54
- LOCAL_STORAGE_DEST: 'storage/uploads',
55
- PLUGIN_STORAGE_PATH: 'storage/plugins',
56
- MFSU_AD: 'none',
57
- WS_PATH: '/ws',
58
- SOCKET_PATH: 'storage/gateway.sock',
59
- PLUGIN_PACKAGE_PREFIX: '@tachybase/plugin-,@tachybase/module-',
60
- SERVER_TSCONFIG_PATH: './tsconfig.server.json',
61
- PLAYWRIGHT_AUTH_FILE: 'storage/playwright/.auth/admin.json',
62
- CACHE_DEFAULT_STORE: 'memory',
63
- CACHE_MEMORY_MAX: 2000,
64
- PLUGIN_STATICS_PATH: '/static/plugins/',
65
- LOGGER_BASE_PATH: 'storage/logs',
66
- APP_SERVER_BASE_URL: '',
67
- APP_PUBLIC_PATH: '/',
68
22
  TEGO_HOME: join(os.homedir(), '.tego'),
69
23
  TEGO_RUNTIME_NAME: 'current',
70
24
  };
71
25
 
72
- config({
73
- path: resolve(process.cwd(), process.env.APP_ENV_PATH || '.env'),
74
- });
26
+ // 允许 .env 不存在
27
+ if (_existsSync(resolve(process.cwd(), '.env'))) {
28
+ config({
29
+ path: resolve(process.cwd(), '.env'),
30
+ });
31
+ }
75
32
 
33
+ // 如果存在 storage 的话,TEGO_RUNTIME_HOME 默认指向当前路径
76
34
  if (
77
35
  !process.env.TEGO_RUNTIME_HOME &&
78
36
  !process.env.TEGO_RUNTIME_NAME &&
@@ -87,6 +45,7 @@ export function parseEnvironment() {
87
45
  }
88
46
  }
89
47
 
48
+ // 如果 TEGO_RUNTIME_HOME 还未设置,那就设置为 TEGO_HOME/TEGO_RUNTIME_NAME
90
49
  if (!process.env.TEGO_RUNTIME_HOME) {
91
50
  process.env.TEGO_RUNTIME_HOME = join(process.env.TEGO_HOME!, process.env.TEGO_RUNTIME_NAME!);
92
51
  }
@@ -205,7 +164,7 @@ export class TegoIndexManager {
205
164
  constructor({
206
165
  indexUrl,
207
166
  baseDir,
208
- lastUpdateSuffix = '.last-update-at',
167
+ lastUpdateSuffix = LAST_UPDATE_FILE_SUFFIX,
209
168
  }: {
210
169
  indexUrl: string;
211
170
  baseDir: string;
@@ -248,3 +207,65 @@ export class TegoIndexManager {
248
207
  return await this.fetchIndexFile();
249
208
  }
250
209
  }
210
+
211
+ export function convertEnvToSettings(flatEnv: Record<string, string | undefined>) {
212
+ const settings: any = {
213
+ env: {},
214
+ logger: {},
215
+ database: {},
216
+ cache: {},
217
+ encryptionField: {},
218
+ presets: {},
219
+ worker: {},
220
+ export: {},
221
+ misc: {},
222
+ };
223
+
224
+ // LOGGER_
225
+ for (const key in flatEnv) {
226
+ const value = flatEnv[key];
227
+ if (value === undefined) continue;
228
+
229
+ if (key.startsWith('LOGGER_')) {
230
+ const subKey = key.replace('LOGGER_', '').toLowerCase();
231
+ if (subKey === 'transport') {
232
+ settings.logger.transport = value.split(',').map((x) => x.trim());
233
+ } else if (subKey === 'maxfiles') {
234
+ settings.logger.maxFiles = value;
235
+ } else if (subKey === 'maxsize') {
236
+ settings.logger.maxSize = value;
237
+ } else if (subKey === 'format') {
238
+ settings.logger.format = value;
239
+ } else {
240
+ settings.logger[subKey] = value;
241
+ }
242
+ continue;
243
+ }
244
+
245
+ // DB_
246
+ if (key.startsWith('DB_')) {
247
+ const subKey = key.replace('DB_', '').toLowerCase();
248
+ if (subKey.startsWith('dialect_options_ssl_')) {
249
+ // e.g. DB_DIALECT_OPTIONS_SSL_CA
250
+ const sslKey = subKey.replace('dialect_options_ssl_', '');
251
+ settings.database.ssl = settings.database.ssl || {};
252
+ settings.database.ssl[sslKey] = value;
253
+ } else {
254
+ settings.database[subKey] = value;
255
+ }
256
+ continue;
257
+ }
258
+
259
+ // CACHE_
260
+ if (key.startsWith('CACHE_')) {
261
+ const subKey = key.replace('CACHE_', '').toLowerCase();
262
+ settings.cache[subKey] = value;
263
+ continue;
264
+ }
265
+
266
+ // 其它 => 默认归到 settings.env
267
+ settings.env[key] = value;
268
+ }
269
+
270
+ return settings;
271
+ }
@@ -1,105 +0,0 @@
1
- ################# TACHYBASE APPLICATION #################
2
- APP_ENV=development
3
- APP_PORT=3000
4
- APP_KEY=test-key
5
-
6
- # 默认为 ~/.tego
7
- TEGO_HOME=
8
- # 默认为 current
9
- TEGO_RUNTIME_NAME=
10
- # 默认为 ~/.tego/current,设置后会覆盖 TEGO_RUNTIME_NAME
11
- TEGO_RUNTIME_HOME=
12
-
13
- # experimental support
14
- EXTENSION_UI_BASE_PATH=/adapters/
15
-
16
- API_BASE_PATH=/api/
17
- API_BASE_URL=
18
-
19
- # console | file | dailyRotateFile
20
- LOGGER_TRANSPORT=
21
- LOGGER_BASE_PATH=storage/logs
22
- # error | warn | info | debug
23
- LOGGER_LEVEL=
24
- # If LOGGER_TRANSPORT is dailyRotateFile and using days, add 'd' as the suffix.
25
- LOGGER_MAX_FILES=
26
- # add 'k', 'm', 'g' as the suffix.
27
- LOGGER_MAX_SIZE=
28
- # json | splitter, split by '|' character
29
- LOGGER_FORMAT=
30
-
31
- ################# DATABASE #################
32
-
33
- DB_DIALECT=sqlite
34
- DB_STORAGE=storage/db/tachybase.sqlite
35
- DB_TABLE_PREFIX=
36
- # DB_HOST=localhost
37
- # DB_PORT=5432
38
- # DB_DATABASE=postgres
39
- # DB_USER=tachybase
40
- # DB_PASSWORD=tachybase
41
- # DB_LOGGING=on
42
- # DB_UNDERSCORED=false
43
-
44
- #== SSL CONFIG ==#
45
- # DB_DIALECT_OPTIONS_SSL_CA=
46
- # DB_DIALECT_OPTIONS_SSL_KEY=
47
- # DB_DIALECT_OPTIONS_SSL_CERT=
48
- # DB_DIALECT_OPTIONS_SSL_REJECT_UNAUTHORIZED=true
49
-
50
- ################# CACHE #################
51
- CACHE_DEFAULT_STORE=memory
52
- # max number of items in memory cache
53
- CACHE_MEMORY_MAX=2000
54
- # CACHE_REDIS_URL=
55
-
56
- ################# STORAGE (Initialization only) #################
57
-
58
- INIT_APP_LANG=zh-CN
59
- INIT_ROOT_EMAIL=admin@tachybase.com
60
- INIT_ROOT_PASSWORD=!Admin123.
61
- INIT_ROOT_NICKNAME=Super Admin
62
- INIT_ROOT_USERNAME=tachybase
63
-
64
- ################# ENCRYPTION FIELD #################
65
-
66
- ENCRYPTION_FIELD_KEY=
67
-
68
- ##### PRESETS #####
69
-
70
- # Built-in plugins: Enabled by default.
71
- # When the plugin list is updated, any plugins no longer in the list will be removed,(TODO)
72
- # and newly added plugins will be included to stay aligned with the latest configuration.
73
- PRESETS_BULTIN_PLUGINS=acl,app-info,auth,backup,cloud-component,collection,cron,data-source,error-handler,event-source,file,workflow,message,pdf,ui-schema,user,web,worker-thread,env-secrets
74
- # External plugins: Enabled by default.
75
- # Prefixing a plugin name with ! marks it as disabled.
76
- # When the plugin list is updated, only newly added plugins will be included;
77
- # existing plugin states will remain unchanged.
78
- PRESETS_EXTERNAL_PLUGINS=action-bulk-edit,action-bulk-update,action-custom-request,action-duplicate,action-export,action-import,action-print,block-calendar,block-charts,block-gantt,block-kanban,block-presentation,field-china-region,field-formula,field-sequence,field-encryption,log-viewer,otp,instrumentation,full-text-search,password-policy,auth-pages,manual-notification,auth-main-app,!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,!user-manual-feishu
79
- # Runtime plugins: Not persisted to the database and are loaded with the highest priority among all plugins.
80
- # RUNTIME_PLUGINS=
81
-
82
- # 主应用工作线程默认数量
83
- WORKER_COUNT=0
84
- # WORKER_TIMEOUT=1800
85
- # 主应用工作线程最大数量
86
- WORKER_COUNT_MAX=8
87
- # WORKER_ERROR_RETRY=3
88
- # 子应用工作线程默认数量
89
- WORKER_COUNT_SUB=0
90
- # 子应用工作线程最大数量
91
- WORKER_COUNT_MAX_SUB=1
92
-
93
- # export config, max length of export data to use main thread and page size in worker thread
94
- # EXPORT_LENGTH_MAX=2000
95
- # EXPORT_WORKER_PAGESIZE=1000
96
-
97
- # 开发环境测试locale 强制使用 cache
98
- #FORCE_LOCALE_CACHE=1
99
-
100
- # 禁止子应用装载的插件,多个用逗号分隔
101
- # FORBID_SUB_APP_PLUGINS=multi-app,manual-notification,multi-app-share-collection
102
-
103
-
104
- # 工作线程最大内存,单位为MB
105
- # WORKER_MAX_MEMORY=4096