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 +5 -5
- package/lib/config.js +15 -4
- package/lib/constants.js +12 -0
- package/lib/plugin-presets.d.ts +5 -10
- package/lib/plugin-presets.js +28 -20
- package/lib/prepare.js +0 -10
- package/lib/utils.d.ts +1 -1
- package/lib/utils.js +59 -52
- package/package.json +21 -21
- package/presets/settings.js +293 -0
- package/src/__tests__/utils.test.ts +24 -0
- package/src/config.ts +5 -4
- package/src/constants.ts +15 -0
- package/src/plugin-presets.ts +19 -26
- package/src/prepare.ts +2 -18
- package/src/utils.ts +72 -51
- package/presets/.env.example +0 -105
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:
|
|
8
|
+
defaultStore: any;
|
|
9
9
|
stores: {
|
|
10
10
|
redis?: {
|
|
11
|
-
url:
|
|
11
|
+
url: any;
|
|
12
12
|
};
|
|
13
13
|
memory: {
|
|
14
14
|
store: string;
|
|
15
|
-
max:
|
|
15
|
+
max: any;
|
|
16
16
|
};
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
19
|
logger: {
|
|
20
20
|
request: {
|
|
21
21
|
transports: ("console" | "file" | "dailyRotateFile")[];
|
|
22
|
-
level:
|
|
22
|
+
level: any;
|
|
23
23
|
};
|
|
24
24
|
system: {
|
|
25
25
|
transports: ("console" | "file" | "dailyRotateFile")[];
|
|
26
|
-
level:
|
|
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:
|
|
47
|
+
defaultStore: import_globals.default.settings.cache.defaultStore ?? "memory",
|
|
37
48
|
stores: {
|
|
38
49
|
memory: {
|
|
39
50
|
store: "memory",
|
|
40
|
-
max:
|
|
51
|
+
max: import_globals.default.settings.cache.memoryMax ?? 2e3
|
|
41
52
|
},
|
|
42
|
-
...
|
|
53
|
+
...import_globals.default.settings.cache.redisUrl ? {
|
|
43
54
|
redis: {
|
|
44
|
-
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");
|
package/lib/plugin-presets.d.ts
CHANGED
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
import { Plugin } from '@tego/core';
|
|
2
2
|
export declare class PluginPresets extends Plugin {
|
|
3
|
-
|
|
4
|
-
|
|
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():
|
|
12
|
+
getForbidSubAppPlugin(): any;
|
|
18
13
|
forbidSubAppPlugin(): Promise<void>;
|
|
19
14
|
filterForbidSubAppPlugin(plugins: any[]): Promise<void>;
|
|
20
15
|
}
|
package/lib/plugin-presets.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 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
|
-
|
|
32
|
-
if (!PRESETS_BULTIN_PLUGINS) {
|
|
39
|
+
if (!import_globals.default.settings.presets.builtinPlugins) {
|
|
33
40
|
throw new Error(
|
|
34
|
-
"
|
|
41
|
+
"presets.builtinPlugins is not defined! Please refer to the settings.js file for the correct configuration."
|
|
35
42
|
);
|
|
36
43
|
}
|
|
37
|
-
|
|
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
|
-
|
|
47
|
-
if (!PRESETS_EXTERNAL_PLUGINS) {
|
|
47
|
+
if (!import_globals.default.settings.presets.externalPlugins) {
|
|
48
48
|
throw new Error(
|
|
49
|
-
"
|
|
49
|
+
"presets.externalPlugins is not defined! Please refer to the settings.js file for the correct configuration."
|
|
50
50
|
);
|
|
51
51
|
}
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
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,
|
|
101
|
-
|
|
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 =
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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/
|
|
53
|
-
"@tachybase/
|
|
54
|
-
"@tachybase/auth": "1.3.
|
|
55
|
-
"@tachybase/
|
|
56
|
-
"@tachybase/
|
|
57
|
-
"@tachybase/
|
|
58
|
-
"@tachybase/
|
|
59
|
-
"@tachybase/globals": "1.3.
|
|
60
|
-
"@tachybase/
|
|
61
|
-
"@tachybase/
|
|
62
|
-
"@tachybase/
|
|
63
|
-
"@tachybase/schema": "1.3.
|
|
64
|
-
"@
|
|
65
|
-
"@tego/
|
|
66
|
-
"@
|
|
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.
|
|
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:
|
|
15
|
+
defaultStore: TachybaseGlobal.settings.cache.defaultStore ?? 'memory',
|
|
15
16
|
stores: {
|
|
16
17
|
memory: {
|
|
17
18
|
store: 'memory',
|
|
18
|
-
max:
|
|
19
|
+
max: TachybaseGlobal.settings.cache.memoryMax ?? 2000,
|
|
19
20
|
},
|
|
20
|
-
...(
|
|
21
|
+
...(TachybaseGlobal.settings.cache.redisUrl
|
|
21
22
|
? {
|
|
22
23
|
redis: {
|
|
23
|
-
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');
|
package/src/plugin-presets.ts
CHANGED
|
@@ -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
|
-
|
|
11
|
-
if (!PRESETS_BULTIN_PLUGINS) {
|
|
8
|
+
if (!TachybaseGlobal.settings.presets.builtinPlugins) {
|
|
12
9
|
throw new Error(
|
|
13
|
-
'
|
|
10
|
+
'presets.builtinPlugins is not defined! Please refer to the settings.js file for the correct configuration.',
|
|
14
11
|
);
|
|
15
12
|
}
|
|
16
|
-
|
|
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
|
-
|
|
31
|
-
if (!PRESETS_EXTERNAL_PLUGINS) {
|
|
17
|
+
if (!TachybaseGlobal.settings.presets.externalPlugins) {
|
|
32
18
|
throw new Error(
|
|
33
|
-
'
|
|
19
|
+
'presets.externalPlugins is not defined! Please refer to the settings.js file for the correct configuration.',
|
|
34
20
|
);
|
|
35
21
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
73
|
-
|
|
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 =
|
|
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
|
+
}
|
package/presets/.env.example
DELETED
|
@@ -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
|