alemonjs 2.1.86 → 2.1.88

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/bin/README.md CHANGED
@@ -100,6 +100,27 @@ alemonc version update
100
100
 
101
101
  读取本地 `package.json`,查找所有 `alemonjs` 和 `@alemonjs/*` 依赖,检查并更新到最新版本。
102
102
 
103
+ #### publish — 智能发布当前包
104
+
105
+ ```sh
106
+ alemonc publish
107
+ alemonc publish patch
108
+ alemonc publish --dry-run
109
+ ```
110
+
111
+ 行为说明:
112
+
113
+ - 默认会查询 git tag 历史作为版本基线
114
+ - 不传参数时:
115
+ - 如果本地版本高于最新 tag,直接发布本地版本
116
+ - 否则自动按最新 tag `patch +1`
117
+ - 传 `patch/minor/major/prepatch/preminor/premajor/prerelease` 时会自动递增
118
+ - 传具体版本号时会直接以该版本发布
119
+ - 默认先执行 `npm run build`
120
+ - 文件选择规则直接复用 npm 机制,也就是 `package.json.files`、`.npmignore`、`.gitignore` 和 npm 默认规则
121
+ - 最终把产物提交到 git `release` 分支,并推送对应 tag
122
+ - 默认要求 git 工作区干净,发布成功后会自动提交源码中的 `package.json` 版本变更
123
+
103
124
  ---
104
125
 
105
126
  ### 项目诊断
package/bin/alemonc.js CHANGED
@@ -6,6 +6,7 @@ import { versionUpdate } from './versionUpdate.js';
6
6
  import { info } from './info.js';
7
7
  import { platformAdd, platformRemove, platformList } from './platform.js';
8
8
  import { login } from './login.js';
9
+ import { publish } from './publish.js';
9
10
  import { Command } from 'commander';
10
11
  const program = new Command();
11
12
 
@@ -74,6 +75,24 @@ program
74
75
  versionUpdate();
75
76
  });
76
77
 
78
+ program
79
+ .command('publish [release]')
80
+ .description('智能发布当前包到 git release 仓库,支持 patch/minor/major 或直接指定版本号')
81
+ .option('--tag <tag>', 'git 标签通道,默认 stable 为 latest,预发布为 next')
82
+ .option('--preid <preid>', '预发布标识,默认 beta', 'beta')
83
+ .option('--branch <branch>', '发布目标分支,默认 release')
84
+ .option('--dry-run', '只执行检查和打包,不真正发布')
85
+ .option('--skip-build', '跳过构建')
86
+ .option('--no-git-checks', '跳过 git 干净工作区检查及发布后自动提交源码版本')
87
+ .action(async (release, options) => {
88
+ try {
89
+ await publish(release, options);
90
+ } catch (error) {
91
+ console.error(error instanceof Error ? error.message : error);
92
+ process.exit(1);
93
+ }
94
+ });
95
+
77
96
  program
78
97
  .command('info')
79
98
  .description('输出项目诊断信息')
@@ -118,4 +137,4 @@ program
118
137
  program.help();
119
138
  });
120
139
 
121
- program.parse(process.argv);
140
+ program.parseAsync(process.argv);
package/bin/publish.js ADDED
@@ -0,0 +1,405 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'fs';
3
+ import { join } from 'path';
4
+ import os from 'os';
5
+ import { execSync, spawnSync } from 'child_process';
6
+
7
+ const RELEASE_TYPES = new Set(['patch', 'minor', 'major', 'prepatch', 'preminor', 'premajor', 'prerelease']);
8
+ const SEMVER_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
9
+
10
+ function readPackageJson() {
11
+ const pkgPath = join(process.cwd(), 'package.json');
12
+
13
+ if (!fs.existsSync(pkgPath)) {
14
+ throw new Error('未找到 package.json');
15
+ }
16
+
17
+ return {
18
+ pkgPath,
19
+ pkg: JSON.parse(fs.readFileSync(pkgPath, 'utf8'))
20
+ };
21
+ }
22
+
23
+ function runCommand(command, args, options = {}) {
24
+ const result = spawnSync(command, args, {
25
+ cwd: process.cwd(),
26
+ stdio: 'inherit',
27
+ shell: false,
28
+ ...options
29
+ });
30
+
31
+ if (result.error) {
32
+ throw result.error;
33
+ }
34
+
35
+ if (result.status !== 0) {
36
+ throw new Error(`命令执行失败: ${command} ${args.join(' ')}`);
37
+ }
38
+ }
39
+
40
+ function getCommandOutput(command) {
41
+ return execSync(command, {
42
+ cwd: process.cwd(),
43
+ encoding: 'utf8',
44
+ stdio: ['ignore', 'pipe', 'ignore']
45
+ }).trim();
46
+ }
47
+
48
+ function hasCommand(command) {
49
+ const result = spawnSync(command, ['--version'], {
50
+ cwd: process.cwd(),
51
+ stdio: 'ignore'
52
+ });
53
+
54
+ return !result.error;
55
+ }
56
+
57
+ function isGitRepo() {
58
+ try {
59
+ return getCommandOutput('git rev-parse --is-inside-work-tree') === 'true';
60
+ } catch {
61
+ return false;
62
+ }
63
+ }
64
+
65
+ function ensureCleanGit() {
66
+ const status = getCommandOutput('git status --porcelain');
67
+ if (status) {
68
+ throw new Error('工作区存在未提交改动,请先提交或使用 --no-git-checks 跳过检查');
69
+ }
70
+ }
71
+
72
+ function parseVersion(version) {
73
+ const matched = version.match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/);
74
+ if (!matched) {
75
+ throw new Error(`非法版本号: ${version}`);
76
+ }
77
+
78
+ return {
79
+ major: Number(matched[1]),
80
+ minor: Number(matched[2]),
81
+ patch: Number(matched[3]),
82
+ prerelease: matched[4] ?? null
83
+ };
84
+ }
85
+
86
+ function compareVersions(a, b) {
87
+ const av = parseVersion(a);
88
+ const bv = parseVersion(b);
89
+
90
+ for (const key of ['major', 'minor', 'patch']) {
91
+ if (av[key] > bv[key]) return 1;
92
+ if (av[key] < bv[key]) return -1;
93
+ }
94
+
95
+ if (av.prerelease === bv.prerelease) return 0;
96
+ if (av.prerelease === null) return 1;
97
+ if (bv.prerelease === null) return -1;
98
+
99
+ return av.prerelease.localeCompare(bv.prerelease);
100
+ }
101
+
102
+ function incrementVersion(baseVersion, releaseType, preid = 'beta') {
103
+ const parsed = parseVersion(baseVersion);
104
+
105
+ if (releaseType === 'patch') {
106
+ return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}`;
107
+ }
108
+
109
+ if (releaseType === 'minor') {
110
+ return `${parsed.major}.${parsed.minor + 1}.0`;
111
+ }
112
+
113
+ if (releaseType === 'major') {
114
+ return `${parsed.major + 1}.0.0`;
115
+ }
116
+
117
+ if (releaseType === 'prepatch') {
118
+ return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}-${preid}.0`;
119
+ }
120
+
121
+ if (releaseType === 'preminor') {
122
+ return `${parsed.major}.${parsed.minor + 1}.0-${preid}.0`;
123
+ }
124
+
125
+ if (releaseType === 'premajor') {
126
+ return `${parsed.major + 1}.0.0-${preid}.0`;
127
+ }
128
+
129
+ if (releaseType === 'prerelease') {
130
+ if (parsed.prerelease) {
131
+ const next = parsed.prerelease.match(/^(.*?)(\d+)$/);
132
+ if (next) {
133
+ return `${parsed.major}.${parsed.minor}.${parsed.patch}-${next[1]}${Number(next[2]) + 1}`;
134
+ }
135
+
136
+ return `${parsed.major}.${parsed.minor}.${parsed.patch}-${parsed.prerelease}.1`;
137
+ }
138
+
139
+ return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}-${preid}.0`;
140
+ }
141
+
142
+ throw new Error(`不支持的发布类型: ${releaseType}`);
143
+ }
144
+
145
+ function resolveTargetVersion(localVersion, remoteVersion, release, preid) {
146
+ if (!release) {
147
+ if (!remoteVersion) {
148
+ return localVersion;
149
+ }
150
+
151
+ if (compareVersions(localVersion, remoteVersion) > 0) {
152
+ return localVersion;
153
+ }
154
+
155
+ return incrementVersion(remoteVersion, 'patch', preid);
156
+ }
157
+
158
+ if (RELEASE_TYPES.has(release)) {
159
+ const base = remoteVersion && compareVersions(remoteVersion, localVersion) > 0 ? remoteVersion : localVersion;
160
+ return incrementVersion(base, release, preid);
161
+ }
162
+
163
+ if (SEMVER_RE.test(release)) {
164
+ return release;
165
+ }
166
+
167
+ throw new Error(`无法识别的发布参数: ${release}`);
168
+ }
169
+
170
+ function updateVersion(pkgPath, pkg, version) {
171
+ pkg.version = version;
172
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
173
+ }
174
+
175
+ function getPackResult(cwd = process.cwd()) {
176
+ const output = execSync('npm pack --json --dry-run', {
177
+ cwd,
178
+ encoding: 'utf8',
179
+ stdio: ['ignore', 'pipe', 'ignore'],
180
+ maxBuffer: 20 * 1024 * 1024
181
+ }).trim();
182
+
183
+ const result = JSON.parse(output);
184
+ if (!Array.isArray(result) || result.length === 0 || !Array.isArray(result[0]?.files)) {
185
+ throw new Error('无法解析 npm pack 文件清单');
186
+ }
187
+
188
+ return result[0];
189
+ }
190
+
191
+ function copyPublishFiles(files) {
192
+ const stageDir = fs.mkdtempSync(join(os.tmpdir(), 'alemon-publish-'));
193
+
194
+ for (const item of files) {
195
+ const relativePath = item.path;
196
+ const sourcePath = join(process.cwd(), relativePath);
197
+ const targetPath = join(stageDir, relativePath);
198
+
199
+ fs.mkdirSync(join(targetPath, '..'), { recursive: true });
200
+ fs.copyFileSync(sourcePath, targetPath);
201
+ }
202
+
203
+ return stageDir;
204
+ }
205
+
206
+ function materializePublishDir(sourceDir, files) {
207
+ const publishDir = fs.mkdtempSync(join(os.tmpdir(), 'alemon-release-'));
208
+
209
+ for (const item of files) {
210
+ const relativePath = item.path;
211
+ const sourcePath = join(sourceDir, relativePath);
212
+ const targetPath = join(publishDir, relativePath);
213
+
214
+ fs.mkdirSync(join(targetPath, '..'), { recursive: true });
215
+ fs.copyFileSync(sourcePath, targetPath);
216
+ }
217
+
218
+ return publishDir;
219
+ }
220
+
221
+ function removeDirContents(dirPath) {
222
+ for (const entry of fs.readdirSync(dirPath)) {
223
+ if (entry === '.git') {
224
+ continue;
225
+ }
226
+
227
+ fs.rmSync(join(dirPath, entry), { recursive: true, force: true });
228
+ }
229
+ }
230
+
231
+ function copyDirContents(sourceDir, targetDir) {
232
+ for (const entry of fs.readdirSync(sourceDir)) {
233
+ fs.cpSync(join(sourceDir, entry), join(targetDir, entry), { recursive: true });
234
+ }
235
+ }
236
+
237
+ function ensureGitRepo() {
238
+ if (!isGitRepo()) {
239
+ throw new Error('当前目录不是 git 仓库,无法执行 git 发布');
240
+ }
241
+ }
242
+
243
+ function remoteBranchExists(branch) {
244
+ const result = spawnSync('git', ['ls-remote', '--exit-code', '--heads', 'origin', branch], {
245
+ cwd: process.cwd(),
246
+ stdio: 'ignore'
247
+ });
248
+
249
+ return result.status === 0;
250
+ }
251
+
252
+ function localBranchExists(branch) {
253
+ const result = spawnSync('git', ['show-ref', '--verify', '--quiet', `refs/heads/${branch}`], {
254
+ cwd: process.cwd(),
255
+ stdio: 'ignore'
256
+ });
257
+
258
+ return result.status === 0;
259
+ }
260
+
261
+ function createReleaseWorktree(branch) {
262
+ const worktreeDir = fs.mkdtempSync(join(os.tmpdir(), 'alemon-worktree-'));
263
+
264
+ if (remoteBranchExists(branch)) {
265
+ runCommand('git', ['fetch', 'origin', branch]);
266
+ runCommand('git', ['worktree', 'add', '-B', branch, worktreeDir, `origin/${branch}`]);
267
+ } else if (localBranchExists(branch)) {
268
+ runCommand('git', ['worktree', 'add', worktreeDir, branch]);
269
+ } else {
270
+ runCommand('git', ['worktree', 'add', '-b', branch, worktreeDir]);
271
+ }
272
+
273
+ return worktreeDir;
274
+ }
275
+
276
+ function cleanupWorktree(worktreeDir) {
277
+ if (!worktreeDir) {
278
+ return;
279
+ }
280
+
281
+ spawnSync('git', ['worktree', 'remove', '--force', worktreeDir], {
282
+ cwd: process.cwd(),
283
+ stdio: 'ignore'
284
+ });
285
+ fs.rmSync(worktreeDir, { recursive: true, force: true });
286
+ }
287
+
288
+ export async function publish(release, options = {}) {
289
+ if (!hasCommand('git')) {
290
+ throw new Error('未找到 git,请先安装 git');
291
+ }
292
+
293
+ if (!hasCommand('npm')) {
294
+ throw new Error('未找到 npm,请先安装 Node.js/npm');
295
+ }
296
+
297
+ const { pkgPath, pkg } = readPackageJson();
298
+ const packageName = pkg.name;
299
+ const localVersion = String(pkg.version || '').trim();
300
+
301
+ if (!packageName) {
302
+ throw new Error('package.json 缺少 name');
303
+ }
304
+
305
+ if (!SEMVER_RE.test(localVersion)) {
306
+ throw new Error(`当前 package.json 版本号非法: ${localVersion}`);
307
+ }
308
+
309
+ console.log(`发布包: ${packageName}`);
310
+ console.log(`本地版本: ${localVersion}`);
311
+
312
+ ensureGitRepo();
313
+
314
+ const releaseBranch = options.branch || 'release';
315
+ const remoteVersion = getCommandOutput(`git tag --list "v*" --sort=-v:refname | head -n 1`).replace(/^v/, '');
316
+ if (remoteVersion) {
317
+ console.log(`最新 git tag: v${remoteVersion}`);
318
+ } else {
319
+ console.log('最新 git tag: 无,将按首次发布处理');
320
+ }
321
+
322
+ if (options.gitChecks !== false && isGitRepo()) {
323
+ ensureCleanGit();
324
+ }
325
+
326
+ const targetVersion = resolveTargetVersion(localVersion, remoteVersion, release, options.preid);
327
+ const distTag = options.tag || (targetVersion.includes('-') ? 'next' : 'latest');
328
+ const gitTagName = distTag === 'latest' ? `v${targetVersion}` : `v${targetVersion}-${distTag}`;
329
+ console.log(`目标版本: ${targetVersion}`);
330
+ console.log(`发布分支: ${releaseBranch}`);
331
+ console.log(`git 标签: ${gitTagName}`);
332
+
333
+ if (targetVersion !== localVersion) {
334
+ updateVersion(pkgPath, pkg, targetVersion);
335
+ console.log(`已更新 package.json 版本: ${localVersion} -> ${targetVersion}`);
336
+ }
337
+
338
+ let stageDir = null;
339
+ let publishDir = null;
340
+ let worktreeDir = null;
341
+ try {
342
+ if (!options.skipBuild) {
343
+ if (pkg.scripts?.build) {
344
+ console.log('执行构建...');
345
+ runCommand('npm', ['run', 'build']);
346
+ } else {
347
+ console.log('未定义 build 脚本,跳过构建');
348
+ }
349
+ } else {
350
+ console.log('已跳过构建');
351
+ }
352
+
353
+ const packResult = getPackResult();
354
+ stageDir = copyPublishFiles(packResult.files);
355
+
356
+ const filteredPackResult = getPackResult(stageDir);
357
+ publishDir = materializePublishDir(stageDir, filteredPackResult.files);
358
+
359
+ console.log(`发布文件数: ${filteredPackResult.files.length}`);
360
+
361
+ if (options.dryRun) {
362
+ console.log('dry-run 模式,不会真正推送到 git');
363
+ return;
364
+ }
365
+
366
+ console.log('准备 release worktree...');
367
+ worktreeDir = createReleaseWorktree(releaseBranch);
368
+ removeDirContents(worktreeDir);
369
+ copyDirContents(publishDir, worktreeDir);
370
+
371
+ runCommand('git', ['-C', worktreeDir, 'add', '-A']);
372
+ const hasChanges = spawnSync('git', ['-C', worktreeDir, 'diff', '--cached', '--quiet']).status !== 0;
373
+ if (!hasChanges) {
374
+ console.log('release 分支无文件变化,跳过提交');
375
+ } else {
376
+ runCommand('git', ['-C', worktreeDir, 'commit', '-m', `release: ${gitTagName}`]);
377
+ runCommand('git', ['-C', worktreeDir, 'push', 'origin', `HEAD:${releaseBranch}`]);
378
+ console.log(`已推送到分支: ${releaseBranch}`);
379
+ }
380
+
381
+ runCommand('git', ['tag', '-f', gitTagName]);
382
+ runCommand('git', ['push', 'origin', gitTagName, '--force']);
383
+ console.log(`发布完成: ${packageName}@${targetVersion}`);
384
+ } catch (error) {
385
+ if (targetVersion !== localVersion) {
386
+ updateVersion(pkgPath, pkg, localVersion);
387
+ console.log(`已回滚 package.json 版本到 ${localVersion}`);
388
+ }
389
+ throw error;
390
+ } finally {
391
+ if (stageDir) {
392
+ fs.rmSync(stageDir, { recursive: true, force: true });
393
+ }
394
+ if (publishDir) {
395
+ fs.rmSync(publishDir, { recursive: true, force: true });
396
+ }
397
+ cleanupWorktree(worktreeDir);
398
+ }
399
+
400
+ if (options.gitChecks !== false && isGitRepo()) {
401
+ runCommand('git', ['add', 'package.json']);
402
+ runCommand('git', ['commit', '-m', `release: ${gitTagName}`]);
403
+ console.log(`已记录源码版本变更: ${gitTagName}`);
404
+ }
405
+ }
@@ -21,5 +21,6 @@ const defineRouter = routes => {
21
21
  current: routes
22
22
  };
23
23
  };
24
+ global.defineRouter = defineRouter;
24
25
 
25
26
  export { defineRouter, lazy, runHandler };
@@ -1 +1,9 @@
1
- export {};
1
+ import '../define-children.js';
2
+ import '../define-response.js';
3
+ import '../define-middleware.js';
4
+ import '../define-router.js';
5
+ import '../format/message-api.js';
6
+ import './event-response.js';
7
+ import './event-middleware.js';
8
+ import './event-utils.js';
9
+ import './event-group.js';
@@ -1,3 +1,12 @@
1
+ import '../define-children.js';
2
+ import '../define-response.js';
3
+ import '../define-middleware.js';
4
+ import '../define-router.js';
5
+ import '../format/message-api.js';
6
+ import './event-response.js';
7
+ import './event-middleware.js';
8
+ import './event-utils.js';
9
+ import './event-group.js';
1
10
  import { cbpClient } from './cbp/connects/client.js';
2
11
  import 'flatted';
3
12
  import 'fs';
@@ -177,19 +177,19 @@ const dispatchAppKoaRouters = async (ctx, appName) => {
177
177
  const beforeRouterPath = ctx.routerPath;
178
178
  let fallthrough = false;
179
179
  await rewriteCtxPath(ctx, rewrittenPath, async () => {
180
- await koaRouter.routes()(ctx, () => {
180
+ await koaRouter.routes()(ctx, async () => {
181
181
  fallthrough = true;
182
182
  });
183
183
  });
184
184
  const afterMatched = Array.isArray(matchedContext.matched) ? matchedContext.matched.length : 0;
185
185
  const afterMatchedRoute = ctx._matchedRoute;
186
186
  const afterRouterPath = ctx.routerPath;
187
- const handled = afterMatched > beforeMatched
188
- || afterMatchedRoute !== beforeMatchedRoute
189
- || afterRouterPath !== beforeRouterPath
190
- || ctx.status !== beforeStatus
191
- || ctx.body !== beforeBody
192
- || !fallthrough;
187
+ const handled = afterMatched > beforeMatched ||
188
+ afterMatchedRoute !== beforeMatchedRoute ||
189
+ afterRouterPath !== beforeRouterPath ||
190
+ ctx.status !== beforeStatus ||
191
+ ctx.body !== beforeBody ||
192
+ !fallthrough;
193
193
  if (!handled) {
194
194
  continue;
195
195
  }
@@ -1,5 +1,5 @@
1
1
  import { dirname, join } from 'path';
2
- import { existsSync } from 'fs';
2
+ import { existsSync, readFileSync } from 'fs';
3
3
  import { showErrorModule, getRecursiveDirFiles, createEventName } from '../../../common/utils.js';
4
4
  import { registerRuntimeApp, updateRuntimeAppStatus, ChildrenApp, clearRuntimeAppKoaRouters, setRuntimeAppKoaRouters, updateRuntimeAppCapabilities } from '../store.js';
5
5
  import { registerExpose } from '../../expose.js';
@@ -11,6 +11,50 @@ import { dispatchRuntimeStatusChange, dispatchAppDispose, dispatchAppReady } fro
11
11
  const initRequire = () => { };
12
12
  initRequire.resolve = () => '';
13
13
  const require$1 = module$1?.createRequire?.(import.meta.url) ?? initRequire;
14
+ const resolvePackageDir = (appName) => {
15
+ const resolveWithPaths = require$1.resolve;
16
+ const candidatePaths = resolveWithPaths?.paths?.(appName) ?? [];
17
+ for (const basePath of candidatePaths) {
18
+ const packageDir = join(basePath, appName);
19
+ if (existsSync(join(packageDir, 'package.json'))) {
20
+ return packageDir;
21
+ }
22
+ }
23
+ return null;
24
+ };
25
+ const resolvePackageEntryFromPackageJson = (packageDir) => {
26
+ const packageJsonPath = join(packageDir, 'package.json');
27
+ if (!existsSync(packageJsonPath)) {
28
+ return null;
29
+ }
30
+ try {
31
+ const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) ?? {};
32
+ const exportsField = pkg?.exports;
33
+ let entry = null;
34
+ if (typeof exportsField === 'string') {
35
+ entry = exportsField;
36
+ }
37
+ else if (exportsField && typeof exportsField === 'object') {
38
+ const rootExport = exportsField['.'];
39
+ if (typeof rootExport === 'string') {
40
+ entry = rootExport;
41
+ }
42
+ else if (rootExport && typeof rootExport === 'object') {
43
+ entry = rootExport.import ?? rootExport.default ?? rootExport.require ?? null;
44
+ }
45
+ }
46
+ if (!entry) {
47
+ entry = pkg?.module ?? pkg?.main ?? 'index.js';
48
+ }
49
+ if (typeof entry !== 'string' || !entry.trim()) {
50
+ return null;
51
+ }
52
+ return join(packageDir, entry);
53
+ }
54
+ catch {
55
+ return null;
56
+ }
57
+ };
14
58
  const resolvePackageRoot = (startDir) => {
15
59
  let currentDir = startDir;
16
60
  while (currentDir && currentDir !== dirname(currentDir)) {
@@ -253,7 +297,14 @@ const loadChildrenFile = (appName) => {
253
297
  return;
254
298
  }
255
299
  try {
256
- const mainPath = require$1.resolve(appName);
300
+ let mainPath = require$1.resolve(appName);
301
+ if (!existsSync(mainPath)) {
302
+ const packageDir = resolvePackageDir(appName);
303
+ const fallbackMainPath = packageDir ? resolvePackageEntryFromPackageJson(packageDir) : null;
304
+ if (fallbackMainPath) {
305
+ mainPath = fallbackMainPath;
306
+ }
307
+ }
257
308
  if (!existsSync(mainPath)) {
258
309
  updateRuntimeAppStatus(appName, 'failed', new Error('The main file does not exist,' + mainPath));
259
310
  logger.error({
@@ -274,6 +325,20 @@ const loadChildrenFile = (appName) => {
274
325
  void loadChildren(mainPath, appName);
275
326
  }
276
327
  catch (e) {
328
+ const packageDir = resolvePackageDir(appName);
329
+ const fallbackMainPath = packageDir ? resolvePackageEntryFromPackageJson(packageDir) : null;
330
+ if (fallbackMainPath && existsSync(fallbackMainPath)) {
331
+ registerRuntimeApp({
332
+ name: appName,
333
+ kind: 'plugin',
334
+ enabled: true,
335
+ status: 'discovered',
336
+ rootDir: dirname(fallbackMainPath),
337
+ mainPath: fallbackMainPath
338
+ });
339
+ void loadChildren(fallbackMainPath, appName);
340
+ return;
341
+ }
277
342
  updateRuntimeAppStatus(appName, 'failed', e);
278
343
  showErrorModule(e);
279
344
  }
@@ -107,8 +107,8 @@ const registerRuntimeApp = (record) => {
107
107
  createdAt: current?.createdAt ?? now,
108
108
  updatedAt: now
109
109
  };
110
- if (current?.status !== record.status) {
111
- logRuntimeAppStatus(record.status === 'failed' ? 'warn' : 'debug', runtimeApps[record.name]);
110
+ if (current?.status !== record.status && process.env.NODE_ENV === 'development') {
111
+ logRuntimeAppStatus('debug', runtimeApps[record.name]);
112
112
  }
113
113
  return runtimeApps[record.name];
114
114
  };
package/lib/global.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { DefineChildrenFunc, OnResponseReversalFunc, OnMiddlewareReversalFunc, OnSelectsFunc, OnDataFormatFunc, OnResponseReversalFuncBack, OnGroupFunc, OnMiddlewareReversalFuncBack, DefineResponseFunc, defineMiddlewareFunc, StoreChildrenApp, StateSubscribeMap, SubscribeKeysMap, LoggerUtils, ResponseState, StartOptions } from './types';
1
+ import type { DefineChildrenFunc, OnResponseReversalFunc, OnMiddlewareReversalFunc, OnSelectsFunc, OnDataFormatFunc, OnResponseReversalFuncBack, OnGroupFunc, OnMiddlewareReversalFuncBack, DefineResponseFunc, defineMiddlewareFunc, DefineRouterFunc, StoreChildrenApp, StateSubscribeMap, SubscribeKeysMap, LoggerUtils, ResponseState, StartOptions } from './types';
2
2
  import { type Server } from 'ws';
3
3
  import type WebSocket from 'ws';
4
4
  import type { IncomingMessage } from 'http';
@@ -7,6 +7,9 @@ import type { RuntimeAppRecord } from './application/runtime/store.js';
7
7
  declare global {
8
8
  var __config: any;
9
9
  var __options: StartOptions;
10
+ var __sandbox: boolean | undefined;
11
+ var __client_loaded: boolean | undefined;
12
+ var __publicIp: string | undefined;
10
13
  var logger: LoggerUtils;
11
14
  var alemonjsCore: {
12
15
  storeState: ResponseState;
@@ -25,6 +28,7 @@ declare global {
25
28
  var chatbotServer: Server<typeof WebSocket, typeof IncomingMessage>;
26
29
  var chatbotPlatform: WebSocket;
27
30
  var chatbotClient: WebSocket;
31
+ var testoneClient: WebSocket | undefined;
28
32
  var onResponse: OnResponseReversalFunc;
29
33
  var OnResponse: OnResponseReversalFuncBack;
30
34
  var onMiddleware: OnMiddlewareReversalFunc;
@@ -32,6 +36,7 @@ declare global {
32
36
  var defineChildren: DefineChildrenFunc;
33
37
  var defineResponse: DefineResponseFunc;
34
38
  var defineMiddleware: defineMiddlewareFunc;
39
+ var defineRouter: DefineRouterFunc;
35
40
  var onSelects: OnSelectsFunc;
36
41
  var format: OnDataFormatFunc;
37
42
  var onGroup: OnGroupFunc;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alemonjs",
3
- "version": "2.1.86",
3
+ "version": "2.1.88",
4
4
  "description": "bot script",
5
5
  "author": "lemonade",
6
6
  "license": "MIT",
@@ -93,4 +93,4 @@
93
93
  "url": "https://github.com/lemonade-lab/alemonjs.git"
94
94
  },
95
95
  "gitHead": "c6aa5616afe091a37610dad22fbb2d2618d943b8"
96
- }
96
+ }