tego 1.3.49 → 1.3.51
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/constants.d.ts +2 -0
- package/lib/constants.js +8 -2
- package/lib/prepare.js +8 -17
- package/lib/utils.d.ts +13 -0
- package/lib/utils.js +91 -17
- package/package.json +16 -15
- package/src/constants.ts +2 -0
- package/src/prepare.ts +16 -22
- package/src/utils.ts +109 -18
- package/lib/default-modules.d.ts +0 -1
- package/lib/default-modules.js +0 -51
- package/lib/default-plugins.d.ts +0 -1
- package/lib/default-plugins.js +0 -51
- package/src/default-modules.ts +0 -24
- package/src/default-plugins.ts +0 -25
package/lib/constants.d.ts
CHANGED
|
@@ -2,3 +2,5 @@ export declare const DEFAULT_DEV_PLUGINS_PATH: string;
|
|
|
2
2
|
export declare const DEFAULT_REMOTE_PLUGINS_PATH: string;
|
|
3
3
|
export declare const DEFAULT_BUILTIN_PLUGINS_PATH: string;
|
|
4
4
|
export declare const DEFAULT_WEB_PACKAGE_NAME = "@tego/web";
|
|
5
|
+
export declare const INDEX_TEGO_URL = "https://tachybase.org/index.tego.json";
|
|
6
|
+
export declare const LAST_UPDATE_FILE_SUFFIX = ".last-update-at";
|
package/lib/constants.js
CHANGED
|
@@ -30,7 +30,9 @@ __export(constants_exports, {
|
|
|
30
30
|
DEFAULT_BUILTIN_PLUGINS_PATH: () => DEFAULT_BUILTIN_PLUGINS_PATH,
|
|
31
31
|
DEFAULT_DEV_PLUGINS_PATH: () => DEFAULT_DEV_PLUGINS_PATH,
|
|
32
32
|
DEFAULT_REMOTE_PLUGINS_PATH: () => DEFAULT_REMOTE_PLUGINS_PATH,
|
|
33
|
-
DEFAULT_WEB_PACKAGE_NAME: () => DEFAULT_WEB_PACKAGE_NAME
|
|
33
|
+
DEFAULT_WEB_PACKAGE_NAME: () => DEFAULT_WEB_PACKAGE_NAME,
|
|
34
|
+
INDEX_TEGO_URL: () => INDEX_TEGO_URL,
|
|
35
|
+
LAST_UPDATE_FILE_SUFFIX: () => LAST_UPDATE_FILE_SUFFIX
|
|
34
36
|
});
|
|
35
37
|
module.exports = __toCommonJS(constants_exports);
|
|
36
38
|
var import_node_path = __toESM(require("node:path"));
|
|
@@ -40,10 +42,14 @@ const DEFAULT_DEV_PLUGINS_PATH = import_node_path.default.join(process.env.TEGO_
|
|
|
40
42
|
const DEFAULT_REMOTE_PLUGINS_PATH = import_node_path.default.join(process.env.TEGO_RUNTIME_HOME, "plugins", "remote");
|
|
41
43
|
const DEFAULT_BUILTIN_PLUGINS_PATH = import_node_path.default.join(process.env.TEGO_RUNTIME_HOME, "plugins", "builtin");
|
|
42
44
|
const DEFAULT_WEB_PACKAGE_NAME = "@tego/web";
|
|
45
|
+
const INDEX_TEGO_URL = "https://tachybase.org/index.tego.json";
|
|
46
|
+
const LAST_UPDATE_FILE_SUFFIX = ".last-update-at";
|
|
43
47
|
// Annotate the CommonJS export names for ESM import in node:
|
|
44
48
|
0 && (module.exports = {
|
|
45
49
|
DEFAULT_BUILTIN_PLUGINS_PATH,
|
|
46
50
|
DEFAULT_DEV_PLUGINS_PATH,
|
|
47
51
|
DEFAULT_REMOTE_PLUGINS_PATH,
|
|
48
|
-
DEFAULT_WEB_PACKAGE_NAME
|
|
52
|
+
DEFAULT_WEB_PACKAGE_NAME,
|
|
53
|
+
INDEX_TEGO_URL,
|
|
54
|
+
LAST_UPDATE_FILE_SUFFIX
|
|
49
55
|
});
|
package/lib/prepare.js
CHANGED
|
@@ -38,12 +38,10 @@ var import_node_process = __toESM(require("node:process"));
|
|
|
38
38
|
var import_yocto_spinner = __toESM(require("@socketregistry/yocto-spinner/index.cjs"));
|
|
39
39
|
var import_execa = __toESM(require("execa"));
|
|
40
40
|
var import_constants = require("./constants");
|
|
41
|
-
var import_default_modules = require("./default-modules");
|
|
42
|
-
var import_default_plugins = require("./default-plugins");
|
|
43
41
|
var import_utils = require("./utils");
|
|
44
42
|
async function prepare({
|
|
45
43
|
name,
|
|
46
|
-
plugins =
|
|
44
|
+
plugins = [],
|
|
47
45
|
init = false
|
|
48
46
|
}) {
|
|
49
47
|
if (init) {
|
|
@@ -67,21 +65,14 @@ async function prepare({
|
|
|
67
65
|
await (0, import_utils.downloadTar)(import_constants.DEFAULT_WEB_PACKAGE_NAME, `${import_constants.DEFAULT_BUILTIN_PLUGINS_PATH}/${import_constants.DEFAULT_WEB_PACKAGE_NAME}`);
|
|
68
66
|
spinner.success();
|
|
69
67
|
console.log();
|
|
70
|
-
console.log("\u{1F680} ~ start download ~ required modules");
|
|
71
|
-
const moduleNames = import_default_modules.defaultModules.map((moduleName) => `@tachybase/module-${moduleName}`);
|
|
72
|
-
let index = 1;
|
|
73
|
-
for (const moduleName of moduleNames) {
|
|
74
|
-
const spinner2 = (0, import_yocto_spinner.default)({ text: `[${index++}/${moduleNames.length}] Loading ${moduleName}` }).start();
|
|
75
|
-
await (0, import_utils.downloadTar)(moduleName, `${import_constants.DEFAULT_BUILTIN_PLUGINS_PATH}/${moduleName}`);
|
|
76
|
-
if (npmExist) {
|
|
77
|
-
await npmInstall(`${import_constants.DEFAULT_BUILTIN_PLUGINS_PATH}/${moduleName}`, spinner2);
|
|
78
|
-
}
|
|
79
|
-
spinner2.success();
|
|
80
|
-
}
|
|
81
|
-
console.log();
|
|
82
68
|
console.log("\u{1F680} ~ start download ~ plugins");
|
|
83
|
-
|
|
84
|
-
|
|
69
|
+
const manager = new import_utils.TegoIndexManager({
|
|
70
|
+
indexUrl: import_constants.INDEX_TEGO_URL,
|
|
71
|
+
baseDir: import_node_process.default.env.TEGO_HOME
|
|
72
|
+
});
|
|
73
|
+
const pluginIndex = await manager.getIndex();
|
|
74
|
+
const pluginNames = plugins.length > 0 ? plugins : pluginIndex.plugins.map((plugin) => plugin.name);
|
|
75
|
+
let index = 1;
|
|
85
76
|
for (const pluginName of pluginNames) {
|
|
86
77
|
const spinner2 = (0, import_yocto_spinner.default)({ text: `[${index++}/${pluginNames.length}] Loading ${pluginName}` }).start();
|
|
87
78
|
await (0, import_utils.downloadTar)(pluginName, `${import_constants.DEFAULT_BUILTIN_PLUGINS_PATH}/${pluginName}`);
|
package/lib/utils.d.ts
CHANGED
|
@@ -2,3 +2,16 @@ export declare function initEnvFile(name: string): void;
|
|
|
2
2
|
export declare function parseEnvironment(): void;
|
|
3
3
|
export declare function guessServePath(): string | false;
|
|
4
4
|
export declare function downloadTar(packageName: string, target: string): Promise<void>;
|
|
5
|
+
export declare class TegoIndexManager {
|
|
6
|
+
private indexUrl;
|
|
7
|
+
private indexFile;
|
|
8
|
+
private lastUpdateFile;
|
|
9
|
+
constructor({ indexUrl, baseDir, lastUpdateSuffix, }: {
|
|
10
|
+
indexUrl: string;
|
|
11
|
+
baseDir: string;
|
|
12
|
+
lastUpdateSuffix?: string;
|
|
13
|
+
});
|
|
14
|
+
private readLastUpdateTime;
|
|
15
|
+
private fetchIndexFile;
|
|
16
|
+
getIndex(): Promise<any>;
|
|
17
|
+
}
|
package/lib/utils.js
CHANGED
|
@@ -28,6 +28,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
var utils_exports = {};
|
|
30
30
|
__export(utils_exports, {
|
|
31
|
+
TegoIndexManager: () => TegoIndexManager,
|
|
31
32
|
downloadTar: () => downloadTar,
|
|
32
33
|
guessServePath: () => guessServePath,
|
|
33
34
|
initEnvFile: () => initEnvFile,
|
|
@@ -49,9 +50,9 @@ function initEnvFile(name) {
|
|
|
49
50
|
const envPath = (0, import_node_path.resolve)(name, ".env");
|
|
50
51
|
if (!import_node_fs.default.existsSync(envPath)) {
|
|
51
52
|
import_node_fs.default.copyFileSync((0, import_node_path.resolve)(__dirname, "../presets/.env.example"), envPath);
|
|
52
|
-
console.
|
|
53
|
+
console.info(".env file created.");
|
|
53
54
|
} else {
|
|
54
|
-
console.
|
|
55
|
+
console.info(".env file already exists.");
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
__name(initEnvFile, "initEnvFile");
|
|
@@ -141,36 +142,109 @@ function guessServePath() {
|
|
|
141
142
|
return false;
|
|
142
143
|
}
|
|
143
144
|
__name(guessServePath, "guessServePath");
|
|
144
|
-
async function
|
|
145
|
+
async function getTarballMeta(pkgName, version = "latest") {
|
|
145
146
|
const info = await import_npm_registry_fetch.default.json(`/${pkgName}/${version}`, {
|
|
146
|
-
query: { fullMetadata: true }
|
|
147
|
+
query: { fullMetadata: true },
|
|
148
|
+
registry: process.env.NPM_CONFIG_REGISTRY ?? "https://registry.npmjs.org"
|
|
147
149
|
});
|
|
148
|
-
return info.dist.tarball;
|
|
150
|
+
return { url: info.dist.tarball, shasum: info.dist.shasum };
|
|
149
151
|
}
|
|
150
|
-
__name(
|
|
152
|
+
__name(getTarballMeta, "getTarballMeta");
|
|
153
|
+
function sha1(buffer) {
|
|
154
|
+
return (0, import_node_crypto.createHash)("sha1").update(buffer).digest("hex");
|
|
155
|
+
}
|
|
156
|
+
__name(sha1, "sha1");
|
|
157
|
+
async function getFileSha1(filePath) {
|
|
158
|
+
const buffer = await (0, import_promises.readFile)(filePath);
|
|
159
|
+
return sha1(buffer);
|
|
160
|
+
}
|
|
161
|
+
__name(getFileSha1, "getFileSha1");
|
|
162
|
+
async function fileExists(path) {
|
|
163
|
+
try {
|
|
164
|
+
await (0, import_promises.access)(path);
|
|
165
|
+
return true;
|
|
166
|
+
} catch {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
__name(fileExists, "fileExists");
|
|
151
171
|
async function downloadTar(packageName, target) {
|
|
152
|
-
const url = await
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
172
|
+
const { url, shasum } = await getTarballMeta(packageName);
|
|
173
|
+
const baseName = `${packageName.replace("/", "__")}@${shasum}`;
|
|
174
|
+
const cachedTar = (0, import_node_path.join)(process.env.TEGO_HOME, "plugins", `${baseName}.tar.gz`);
|
|
175
|
+
const cachedSha = (0, import_node_path.join)(process.env.TEGO_HOME, "plugins", `${baseName}.sha1`);
|
|
176
|
+
const exists = await fileExists(cachedTar);
|
|
177
|
+
const shaMatches = exists ? await getFileSha1(cachedTar) === shasum : false;
|
|
178
|
+
if (!exists || !shaMatches) {
|
|
179
|
+
await (0, import_promises.mkdir)((0, import_node_path.dirname)(cachedTar), { recursive: true });
|
|
180
|
+
const res = await fetch(url);
|
|
181
|
+
if (!res.ok || !res.body) {
|
|
182
|
+
throw new Error(`Failed to fetch tarball: ${res.statusText}`);
|
|
183
|
+
}
|
|
184
|
+
const writer = (0, import_node_fs.createWriteStream)(cachedTar);
|
|
185
|
+
await (0, import_promises2.pipeline)(res.body, writer);
|
|
186
|
+
const actualSha = await getFileSha1(cachedTar);
|
|
187
|
+
if (actualSha !== shasum) {
|
|
188
|
+
await (0, import_promises.unlink)(cachedTar);
|
|
189
|
+
throw new Error(`Downloaded tarball hash mismatch for ${packageName}`);
|
|
190
|
+
}
|
|
191
|
+
await (0, import_promises.writeFile)(cachedSha, shasum, "utf-8");
|
|
192
|
+
}
|
|
193
|
+
await (0, import_promises.rm)(target, { recursive: true, force: true });
|
|
161
194
|
await (0, import_promises.mkdir)(target, { recursive: true });
|
|
162
195
|
await tar.x({
|
|
163
|
-
file:
|
|
196
|
+
file: cachedTar,
|
|
164
197
|
gzip: true,
|
|
165
198
|
cwd: target,
|
|
166
199
|
strip: 1,
|
|
167
200
|
k: true
|
|
168
201
|
});
|
|
169
|
-
await (0, import_promises.unlink)(tarballFile);
|
|
170
202
|
}
|
|
171
203
|
__name(downloadTar, "downloadTar");
|
|
204
|
+
const ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
205
|
+
const _TegoIndexManager = class _TegoIndexManager {
|
|
206
|
+
constructor({
|
|
207
|
+
indexUrl,
|
|
208
|
+
baseDir,
|
|
209
|
+
lastUpdateSuffix = ".last-update-at"
|
|
210
|
+
}) {
|
|
211
|
+
this.indexUrl = indexUrl;
|
|
212
|
+
this.indexFile = (0, import_node_path.join)(baseDir, "index.tego.json");
|
|
213
|
+
this.lastUpdateFile = (0, import_node_path.join)(baseDir, "index.tego.json" + lastUpdateSuffix);
|
|
214
|
+
}
|
|
215
|
+
async readLastUpdateTime() {
|
|
216
|
+
try {
|
|
217
|
+
const content = await (0, import_promises.readFile)(this.lastUpdateFile, "utf-8");
|
|
218
|
+
return new Date(content.trim());
|
|
219
|
+
} catch {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async fetchIndexFile() {
|
|
224
|
+
const res = await fetch(this.indexUrl);
|
|
225
|
+
if (!res.ok) {
|
|
226
|
+
throw new Error(`Failed to fetch ${this.indexUrl}: ${res.statusText}`);
|
|
227
|
+
}
|
|
228
|
+
const json = await res.json();
|
|
229
|
+
await (0, import_promises.writeFile)(this.indexFile, JSON.stringify(json, null, 2), "utf-8");
|
|
230
|
+
await (0, import_promises.writeFile)(this.lastUpdateFile, (/* @__PURE__ */ new Date()).toISOString(), "utf-8");
|
|
231
|
+
return json;
|
|
232
|
+
}
|
|
233
|
+
async getIndex() {
|
|
234
|
+
const lastUpdated = await this.readLastUpdateTime();
|
|
235
|
+
if (lastUpdated && Date.now() - lastUpdated.getTime() < ONE_DAY_MS) {
|
|
236
|
+
console.info(`\u{1F552} index.tego.json was updated within 1 day, skipping download.`);
|
|
237
|
+
const content = await (0, import_promises.readFile)(this.indexFile, "utf-8");
|
|
238
|
+
return JSON.parse(content);
|
|
239
|
+
}
|
|
240
|
+
return await this.fetchIndexFile();
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
__name(_TegoIndexManager, "TegoIndexManager");
|
|
244
|
+
let TegoIndexManager = _TegoIndexManager;
|
|
172
245
|
// Annotate the CommonJS export names for ESM import in node:
|
|
173
246
|
0 && (module.exports = {
|
|
247
|
+
TegoIndexManager,
|
|
174
248
|
downloadTar,
|
|
175
249
|
guessServePath,
|
|
176
250
|
initEnvFile,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tego",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.51",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tego",
|
|
@@ -49,20 +49,21 @@
|
|
|
49
49
|
"umzug": "3.8.2",
|
|
50
50
|
"winston": "3.17.0",
|
|
51
51
|
"winston-daily-rotate-file": "^5.0.0",
|
|
52
|
-
"@tachybase/acl": "1.3.
|
|
53
|
-
"@tachybase/
|
|
54
|
-
"@tachybase/data-source": "1.3.
|
|
55
|
-
"@tachybase/
|
|
56
|
-
"@tachybase/
|
|
57
|
-
"@tachybase/
|
|
58
|
-
"@tachybase/globals": "1.3.
|
|
59
|
-
"@tachybase/
|
|
60
|
-
"@tachybase/loader": "1.3.
|
|
61
|
-
"@tachybase/logger": "1.3.
|
|
62
|
-
"@tachybase/
|
|
63
|
-
"@
|
|
64
|
-
"@tachybase/
|
|
65
|
-
"@
|
|
52
|
+
"@tachybase/acl": "1.3.51",
|
|
53
|
+
"@tachybase/auth": "1.3.51",
|
|
54
|
+
"@tachybase/data-source": "1.3.51",
|
|
55
|
+
"@tachybase/database": "1.3.51",
|
|
56
|
+
"@tachybase/evaluators": "1.3.51",
|
|
57
|
+
"@tachybase/actions": "1.3.51",
|
|
58
|
+
"@tachybase/globals": "1.3.51",
|
|
59
|
+
"@tachybase/cache": "1.3.51",
|
|
60
|
+
"@tachybase/loader": "1.3.51",
|
|
61
|
+
"@tachybase/logger": "1.3.51",
|
|
62
|
+
"@tachybase/resourcer": "1.3.51",
|
|
63
|
+
"@tachybase/schema": "1.3.51",
|
|
64
|
+
"@tachybase/utils": "1.3.51",
|
|
65
|
+
"@tego/core": "1.3.51",
|
|
66
|
+
"@tego/server": "1.3.51"
|
|
66
67
|
},
|
|
67
68
|
"devDependencies": {
|
|
68
69
|
"@types/lodash": "4.17.20",
|
package/src/constants.ts
CHANGED
|
@@ -9,3 +9,5 @@ export const DEFAULT_DEV_PLUGINS_PATH = path.join(process.env.TEGO_RUNTIME_HOME,
|
|
|
9
9
|
export const DEFAULT_REMOTE_PLUGINS_PATH = path.join(process.env.TEGO_RUNTIME_HOME, 'plugins', 'remote');
|
|
10
10
|
export const DEFAULT_BUILTIN_PLUGINS_PATH = path.join(process.env.TEGO_RUNTIME_HOME, 'plugins', 'builtin');
|
|
11
11
|
export const DEFAULT_WEB_PACKAGE_NAME = '@tego/web';
|
|
12
|
+
export const INDEX_TEGO_URL = 'https://tachybase.org/index.tego.json';
|
|
13
|
+
export const LAST_UPDATE_FILE_SUFFIX = '.last-update-at';
|
package/src/prepare.ts
CHANGED
|
@@ -5,14 +5,17 @@ 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
|
-
|
|
11
|
-
|
|
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';
|
|
12
15
|
|
|
13
16
|
export async function prepare({
|
|
14
17
|
name,
|
|
15
|
-
plugins =
|
|
18
|
+
plugins = [],
|
|
16
19
|
init = false,
|
|
17
20
|
}: {
|
|
18
21
|
name?: string;
|
|
@@ -45,24 +48,15 @@ export async function prepare({
|
|
|
45
48
|
spinner.success();
|
|
46
49
|
console.log();
|
|
47
50
|
|
|
48
|
-
console.log('🚀 ~ start download ~ required modules');
|
|
49
|
-
// 安装必须得模块
|
|
50
|
-
const moduleNames = defaultModules.map((moduleName) => `@tachybase/module-${moduleName}`);
|
|
51
|
-
let index = 1;
|
|
52
|
-
for (const moduleName of moduleNames) {
|
|
53
|
-
const spinner = yoctoSpinner({ text: `[${index++}/${moduleNames.length}] Loading ${moduleName}` }).start();
|
|
54
|
-
await downloadTar(moduleName, `${DEFAULT_BUILTIN_PLUGINS_PATH}/${moduleName}`);
|
|
55
|
-
if (npmExist) {
|
|
56
|
-
await npmInstall(`${DEFAULT_BUILTIN_PLUGINS_PATH}/${moduleName}`, spinner);
|
|
57
|
-
}
|
|
58
|
-
spinner.success();
|
|
59
|
-
}
|
|
60
|
-
console.log();
|
|
61
|
-
|
|
62
51
|
console.log('🚀 ~ start download ~ plugins');
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
52
|
+
const manager = new TegoIndexManager({
|
|
53
|
+
indexUrl: INDEX_TEGO_URL,
|
|
54
|
+
baseDir: process.env.TEGO_HOME!,
|
|
55
|
+
});
|
|
56
|
+
const pluginIndex = await manager.getIndex();
|
|
57
|
+
// download plugins
|
|
58
|
+
const pluginNames = plugins.length > 0 ? plugins : pluginIndex.plugins.map((plugin: { name: string }) => plugin.name);
|
|
59
|
+
let index = 1;
|
|
66
60
|
for (const pluginName of pluginNames) {
|
|
67
61
|
const spinner = yoctoSpinner({ text: `[${index++}/${pluginNames.length}] Loading ${pluginName}` }).start();
|
|
68
62
|
await downloadTar(pluginName, `${DEFAULT_BUILTIN_PLUGINS_PATH}/${pluginName}`);
|
package/src/utils.ts
CHANGED
|
@@ -5,7 +5,7 @@ import fs, {
|
|
|
5
5
|
writeFileSync as _writeFileSync,
|
|
6
6
|
createWriteStream,
|
|
7
7
|
} from 'node:fs';
|
|
8
|
-
import { mkdir, unlink } from 'node:fs/promises';
|
|
8
|
+
import { access, mkdir, readFile, rm, unlink, writeFile } from 'node:fs/promises';
|
|
9
9
|
import os from 'node:os';
|
|
10
10
|
import { dirname, join, resolve } from 'node:path';
|
|
11
11
|
import { pipeline } from 'node:stream/promises';
|
|
@@ -15,15 +15,15 @@ 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 } from './constants';
|
|
18
|
+
import { DEFAULT_WEB_PACKAGE_NAME, INDEX_TEGO_URL, LAST_UPDATE_FILE_SUFFIX } from './constants';
|
|
19
19
|
|
|
20
20
|
export function initEnvFile(name: string) {
|
|
21
21
|
const envPath = resolve(name, '.env');
|
|
22
22
|
if (!fs.existsSync(envPath)) {
|
|
23
23
|
fs.copyFileSync(resolve(__dirname, '../presets/.env.example'), envPath);
|
|
24
|
-
console.
|
|
24
|
+
console.info('.env file created.');
|
|
25
25
|
} else {
|
|
26
|
-
console.
|
|
26
|
+
console.info('.env file already exists.');
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -126,34 +126,125 @@ export function guessServePath() {
|
|
|
126
126
|
return false;
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
async function
|
|
129
|
+
async function getTarballMeta(pkgName, version = 'latest') {
|
|
130
130
|
const info = await npmRegistryFetch.json(`/${pkgName}/${version}`, {
|
|
131
131
|
query: { fullMetadata: true },
|
|
132
|
+
registry: process.env.NPM_CONFIG_REGISTRY ?? 'https://registry.npmjs.org',
|
|
132
133
|
});
|
|
133
|
-
return info.dist.tarball;
|
|
134
|
+
return { url: info.dist.tarball, shasum: info.dist.shasum };
|
|
134
135
|
}
|
|
135
136
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
137
|
+
function sha1(buffer: Buffer | string) {
|
|
138
|
+
return createHash('sha1').update(buffer).digest('hex');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function getFileSha1(filePath: string): Promise<string> {
|
|
142
|
+
const buffer = await readFile(filePath);
|
|
143
|
+
return sha1(buffer);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function fileExists(path: string): Promise<boolean> {
|
|
147
|
+
try {
|
|
148
|
+
await access(path);
|
|
149
|
+
return true;
|
|
150
|
+
} catch {
|
|
151
|
+
return false;
|
|
144
152
|
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 下载并缓存 tgz 到 ~/.tego/plugins
|
|
156
|
+
export async function downloadTar(packageName: string, target: string) {
|
|
157
|
+
const { url, shasum } = await getTarballMeta(packageName);
|
|
145
158
|
|
|
146
|
-
|
|
147
|
-
|
|
159
|
+
const baseName = `${packageName.replace('/', '__')}@${shasum}`;
|
|
160
|
+
const cachedTar = join(process.env.TEGO_HOME!, 'plugins', `${baseName}.tar.gz`);
|
|
161
|
+
const cachedSha = join(process.env.TEGO_HOME!, 'plugins', `${baseName}.sha1`);
|
|
148
162
|
|
|
163
|
+
const exists = await fileExists(cachedTar);
|
|
164
|
+
const shaMatches = exists ? (await getFileSha1(cachedTar)) === shasum : false;
|
|
165
|
+
|
|
166
|
+
if (!exists || !shaMatches) {
|
|
167
|
+
await mkdir(dirname(cachedTar), { recursive: true });
|
|
168
|
+
|
|
169
|
+
const res = await fetch(url);
|
|
170
|
+
if (!res.ok || !res.body) {
|
|
171
|
+
throw new Error(`Failed to fetch tarball: ${res.statusText}`);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const writer = createWriteStream(cachedTar);
|
|
175
|
+
await pipeline(res.body as any, writer);
|
|
176
|
+
|
|
177
|
+
const actualSha = await getFileSha1(cachedTar);
|
|
178
|
+
if (actualSha !== shasum) {
|
|
179
|
+
await unlink(cachedTar);
|
|
180
|
+
throw new Error(`Downloaded tarball hash mismatch for ${packageName}`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
await writeFile(cachedSha, shasum, 'utf-8');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
await rm(target, { recursive: true, force: true });
|
|
149
187
|
await mkdir(target, { recursive: true });
|
|
188
|
+
|
|
150
189
|
await tar.x({
|
|
151
|
-
file:
|
|
190
|
+
file: cachedTar,
|
|
152
191
|
gzip: true,
|
|
153
192
|
cwd: target,
|
|
154
193
|
strip: 1,
|
|
155
194
|
k: true,
|
|
156
195
|
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
|
|
199
|
+
|
|
200
|
+
export class TegoIndexManager {
|
|
201
|
+
private indexUrl: string;
|
|
202
|
+
private indexFile: string;
|
|
203
|
+
private lastUpdateFile: string;
|
|
204
|
+
|
|
205
|
+
constructor({
|
|
206
|
+
indexUrl,
|
|
207
|
+
baseDir,
|
|
208
|
+
lastUpdateSuffix = '.last-update-at',
|
|
209
|
+
}: {
|
|
210
|
+
indexUrl: string;
|
|
211
|
+
baseDir: string;
|
|
212
|
+
lastUpdateSuffix?: string;
|
|
213
|
+
}) {
|
|
214
|
+
this.indexUrl = indexUrl;
|
|
215
|
+
this.indexFile = join(baseDir, 'index.tego.json');
|
|
216
|
+
this.lastUpdateFile = join(baseDir, 'index.tego.json' + lastUpdateSuffix);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private async readLastUpdateTime(): Promise<Date | null> {
|
|
220
|
+
try {
|
|
221
|
+
const content = await readFile(this.lastUpdateFile, 'utf-8');
|
|
222
|
+
return new Date(content.trim());
|
|
223
|
+
} catch {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
157
227
|
|
|
158
|
-
|
|
228
|
+
private async fetchIndexFile(): Promise<any> {
|
|
229
|
+
const res = await fetch(this.indexUrl);
|
|
230
|
+
if (!res.ok) {
|
|
231
|
+
throw new Error(`Failed to fetch ${this.indexUrl}: ${res.statusText}`);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const json = await res.json();
|
|
235
|
+
await writeFile(this.indexFile, JSON.stringify(json, null, 2), 'utf-8');
|
|
236
|
+
await writeFile(this.lastUpdateFile, new Date().toISOString(), 'utf-8');
|
|
237
|
+
return json;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async getIndex(): Promise<any> {
|
|
241
|
+
const lastUpdated = await this.readLastUpdateTime();
|
|
242
|
+
if (lastUpdated && Date.now() - lastUpdated.getTime() < ONE_DAY_MS) {
|
|
243
|
+
console.info(`🕒 index.tego.json was updated within 1 day, skipping download.`);
|
|
244
|
+
const content = await readFile(this.indexFile, 'utf-8');
|
|
245
|
+
return JSON.parse(content);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return await this.fetchIndexFile();
|
|
249
|
+
}
|
|
159
250
|
}
|
package/lib/default-modules.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const defaultModules: string[];
|
package/lib/default-modules.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
-
var __export = (target, all) => {
|
|
6
|
-
for (var name in all)
|
|
7
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
-
};
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
for (let key of __getOwnPropNames(from))
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
16
|
-
};
|
|
17
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
-
var default_modules_exports = {};
|
|
19
|
-
__export(default_modules_exports, {
|
|
20
|
-
defaultModules: () => defaultModules
|
|
21
|
-
});
|
|
22
|
-
module.exports = __toCommonJS(default_modules_exports);
|
|
23
|
-
const defaultModules = [
|
|
24
|
-
"acl",
|
|
25
|
-
"app-info",
|
|
26
|
-
"auth",
|
|
27
|
-
"backup",
|
|
28
|
-
"cloud-component",
|
|
29
|
-
"collection",
|
|
30
|
-
"cron",
|
|
31
|
-
"data-source",
|
|
32
|
-
"error-handler",
|
|
33
|
-
"event-source",
|
|
34
|
-
"file",
|
|
35
|
-
"message",
|
|
36
|
-
"pdf",
|
|
37
|
-
"ui-schema",
|
|
38
|
-
"user",
|
|
39
|
-
"web",
|
|
40
|
-
"worker-thread",
|
|
41
|
-
"instrumentation",
|
|
42
|
-
"workflow",
|
|
43
|
-
"env-secrets",
|
|
44
|
-
"hera",
|
|
45
|
-
// FIXME: refactor later
|
|
46
|
-
"multi-app"
|
|
47
|
-
];
|
|
48
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
49
|
-
0 && (module.exports = {
|
|
50
|
-
defaultModules
|
|
51
|
-
});
|
package/lib/default-plugins.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const defaultPlugins: string[];
|
package/lib/default-plugins.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
-
var __export = (target, all) => {
|
|
6
|
-
for (var name in all)
|
|
7
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
-
};
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
for (let key of __getOwnPropNames(from))
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
16
|
-
};
|
|
17
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
-
var default_plugins_exports = {};
|
|
19
|
-
__export(default_plugins_exports, {
|
|
20
|
-
defaultPlugins: () => defaultPlugins
|
|
21
|
-
});
|
|
22
|
-
module.exports = __toCommonJS(default_plugins_exports);
|
|
23
|
-
const defaultPlugins = [
|
|
24
|
-
"action-bulk-edit",
|
|
25
|
-
"action-bulk-update",
|
|
26
|
-
"action-custom-request",
|
|
27
|
-
"action-duplicate",
|
|
28
|
-
"action-export",
|
|
29
|
-
"action-import",
|
|
30
|
-
"action-print",
|
|
31
|
-
"block-calendar",
|
|
32
|
-
"block-charts",
|
|
33
|
-
"block-gantt",
|
|
34
|
-
"block-kanban",
|
|
35
|
-
"block-presentation",
|
|
36
|
-
"field-china-region",
|
|
37
|
-
"field-formula",
|
|
38
|
-
"field-sequence",
|
|
39
|
-
"field-encryption",
|
|
40
|
-
"log-viewer",
|
|
41
|
-
"otp",
|
|
42
|
-
"full-text-search",
|
|
43
|
-
"password-policy",
|
|
44
|
-
"auth-pages",
|
|
45
|
-
"manual-notification",
|
|
46
|
-
"auth-main-app"
|
|
47
|
-
];
|
|
48
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
49
|
-
0 && (module.exports = {
|
|
50
|
-
defaultPlugins
|
|
51
|
-
});
|
package/src/default-modules.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
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
|
-
];
|
package/src/default-plugins.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
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
|
-
'auth-main-app',
|
|
25
|
-
];
|