@yoyoboot/yoyo-admin-cli 10.5.5
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/dist/bin.d.ts +9 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +10 -0
- package/dist/catalogs/capability.d.ts +54 -0
- package/dist/catalogs/capability.d.ts.map +1 -0
- package/dist/catalogs/capability.js +129 -0
- package/dist/catalogs/crud.d.ts +64 -0
- package/dist/catalogs/crud.d.ts.map +1 -0
- package/dist/catalogs/crud.js +83 -0
- package/dist/catalogs/source.d.ts +16 -0
- package/dist/catalogs/source.d.ts.map +1 -0
- package/dist/catalogs/source.js +8 -0
- package/dist/catalogs/standard-crud.d.ts +51 -0
- package/dist/catalogs/standard-crud.d.ts.map +1 -0
- package/dist/catalogs/standard-crud.js +100 -0
- package/dist/cli.d.ts +20 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +86 -0
- package/dist/commands/capabilities.d.ts +78 -0
- package/dist/commands/capabilities.d.ts.map +1 -0
- package/dist/commands/capabilities.js +72 -0
- package/dist/commands/contracts.d.ts +16 -0
- package/dist/commands/contracts.d.ts.map +1 -0
- package/dist/commands/contracts.js +83 -0
- package/dist/commands/create-frontend-module.d.ts +8 -0
- package/dist/commands/create-frontend-module.d.ts.map +1 -0
- package/dist/commands/create-frontend-module.js +90 -0
- package/dist/commands/create-package.d.ts +17 -0
- package/dist/commands/create-package.d.ts.map +1 -0
- package/dist/commands/create-package.js +75 -0
- package/dist/commands/create-registry.d.ts +32 -0
- package/dist/commands/create-registry.d.ts.map +1 -0
- package/dist/commands/create-registry.js +20 -0
- package/dist/commands/create.d.ts +23 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +111 -0
- package/dist/commands/doctor.d.ts +17 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +150 -0
- package/dist/commands/inspect.d.ts +139 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +379 -0
- package/dist/generators/frontend-module.d.ts +81 -0
- package/dist/generators/frontend-module.d.ts.map +1 -0
- package/dist/generators/frontend-module.js +358 -0
- package/dist/generators/package.d.ts +46 -0
- package/dist/generators/package.d.ts.map +1 -0
- package/dist/generators/package.js +230 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/kernel/arguments.d.ts +44 -0
- package/dist/kernel/arguments.d.ts.map +1 -0
- package/dist/kernel/arguments.js +127 -0
- package/dist/kernel/command.d.ts +71 -0
- package/dist/kernel/command.d.ts.map +1 -0
- package/dist/kernel/command.js +120 -0
- package/dist/kernel/fs-plan.d.ts +50 -0
- package/dist/kernel/fs-plan.d.ts.map +1 -0
- package/dist/kernel/fs-plan.js +82 -0
- package/dist/kernel/help.d.ts +54 -0
- package/dist/kernel/help.d.ts.map +1 -0
- package/dist/kernel/help.js +109 -0
- package/dist/kernel/lockfile.d.ts +73 -0
- package/dist/kernel/lockfile.d.ts.map +1 -0
- package/dist/kernel/lockfile.js +117 -0
- package/dist/kernel/manifests-wiring.d.ts +44 -0
- package/dist/kernel/manifests-wiring.d.ts.map +1 -0
- package/dist/kernel/manifests-wiring.js +165 -0
- package/dist/kernel/plan-runner.d.ts +81 -0
- package/dist/kernel/plan-runner.d.ts.map +1 -0
- package/dist/kernel/plan-runner.js +176 -0
- package/dist/kernel/process-runner.d.ts +25 -0
- package/dist/kernel/process-runner.d.ts.map +1 -0
- package/dist/kernel/process-runner.js +29 -0
- package/dist/kernel/render.d.ts +20 -0
- package/dist/kernel/render.d.ts.map +1 -0
- package/dist/kernel/render.js +63 -0
- package/dist/kernel/result.d.ts +66 -0
- package/dist/kernel/result.d.ts.map +1 -0
- package/dist/kernel/result.js +36 -0
- package/dist/kernel/workspace.d.ts +31 -0
- package/dist/kernel/workspace.d.ts.map +1 -0
- package/dist/kernel/workspace.js +66 -0
- package/package.json +31 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `yoyo-admin create <recipe>`
|
|
3
|
+
*
|
|
4
|
+
* 作者操作的统一入口。
|
|
5
|
+
*
|
|
6
|
+
* 生命周期(保证零部分写入):
|
|
7
|
+
* 1. 构建完整 FsPlan(含新文件、接线更新)
|
|
8
|
+
* 2. preflight 只读校验全部目标
|
|
9
|
+
* 3. 全部通过后事务化落盘(失败自动回滚)
|
|
10
|
+
*
|
|
11
|
+
* `--dry-run` 在第 1 步后停止,只渲染计划。
|
|
12
|
+
*
|
|
13
|
+
* recipe 的注册表见 `create-registry.ts`:dispatch、capabilities、help、
|
|
14
|
+
* 参数校验共用,本文件不再维护手工 recipe 列表。
|
|
15
|
+
*/
|
|
16
|
+
import { defineCommand } from '../kernel/command.js';
|
|
17
|
+
import { renderRecipeHelp, renderRecipeListHelp, } from '../kernel/help.js';
|
|
18
|
+
import { YoyoAdminCliUsageError } from '../kernel/result.js';
|
|
19
|
+
import { listCreateRecipes, registerCreateRecipe, resolveCreateRecipe, } from './create-registry.js';
|
|
20
|
+
import { registerFrontendModuleRecipe } from './create-frontend-module.js';
|
|
21
|
+
import { registerPackageRecipe } from './create-package.js';
|
|
22
|
+
registerFrontendModuleRecipe(registerCreateRecipe);
|
|
23
|
+
registerPackageRecipe(registerCreateRecipe);
|
|
24
|
+
const registeredRecipes = listCreateRecipes();
|
|
25
|
+
const recipeNameList = registeredRecipes.map(recipe => recipe.name).join('、');
|
|
26
|
+
export function runCreate(context) {
|
|
27
|
+
const recipeName = context.parsed.positionals[0];
|
|
28
|
+
if (recipeName === undefined || recipeName.length === 0) {
|
|
29
|
+
throw new YoyoAdminCliUsageError('unknown-recipe', `缺少 recipe 参数。当前支持:${recipeNameList}。`);
|
|
30
|
+
}
|
|
31
|
+
const recipe = resolveCreateRecipe(recipeName);
|
|
32
|
+
if (recipe === undefined) {
|
|
33
|
+
throw new YoyoAdminCliUsageError('unknown-recipe', `未知 recipe ${recipeName}。当前支持:${recipeNameList}。`);
|
|
34
|
+
}
|
|
35
|
+
return recipe.run(context);
|
|
36
|
+
}
|
|
37
|
+
/** recipe 级 spec:`create package --module x` 这类「存在但不属于本 recipe」的选项据此被拒绝。 */
|
|
38
|
+
function createArgumentSpec(positionals) {
|
|
39
|
+
const recipeName = positionals[0];
|
|
40
|
+
const recipe = recipeName === undefined ? undefined : resolveCreateRecipe(recipeName);
|
|
41
|
+
return {
|
|
42
|
+
booleanFlags: recipe?.booleanFlags ?? [],
|
|
43
|
+
valueOptions: (recipe?.options ?? []).map(option => option.flag),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** `create` 的 help 投影面:与 inspect 共用同一套渲染器,只有"面"不同。 */
|
|
47
|
+
export const CREATE_HELP_SURFACE = {
|
|
48
|
+
command: 'create',
|
|
49
|
+
title: '按 recipe 生成标准结构',
|
|
50
|
+
itemLabel: 'recipe',
|
|
51
|
+
usageSuffix: '[options] [--dry-run] [--json]',
|
|
52
|
+
itemUsageHint: '完整参数:yoyo-admin create <recipe> --help',
|
|
53
|
+
};
|
|
54
|
+
function createHelp(positionals) {
|
|
55
|
+
const recipeName = positionals[0];
|
|
56
|
+
const recipe = recipeName === undefined ? undefined : resolveCreateRecipe(recipeName);
|
|
57
|
+
// help 请求本身永不失败:未知 recipe 回落到 recipe 清单(其中已列出真实可用项)。
|
|
58
|
+
return recipe === undefined
|
|
59
|
+
? renderRecipeListHelp(registeredRecipes, CREATE_HELP_SURFACE)
|
|
60
|
+
: renderRecipeHelp(recipe, CREATE_HELP_SURFACE);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* recipe 选项的合并投影:同一 flag 被多个 recipe 声明时只出现一次,
|
|
64
|
+
* 描述里标注它属于哪个 recipe;`--kind` 的候选值取各 recipe 的 kinds 并集。
|
|
65
|
+
*/
|
|
66
|
+
function projectRecipeOptions(recipes) {
|
|
67
|
+
const byFlag = new Map();
|
|
68
|
+
for (const recipe of recipes) {
|
|
69
|
+
for (const option of recipe.options) {
|
|
70
|
+
const entry = byFlag.get(option.flag) ?? {
|
|
71
|
+
flag: option.flag,
|
|
72
|
+
descriptions: [],
|
|
73
|
+
values: new Set(),
|
|
74
|
+
};
|
|
75
|
+
entry.descriptions.push(`${recipe.name}: ${option.description}`);
|
|
76
|
+
for (const value of option.values ?? [])
|
|
77
|
+
entry.values.add(value);
|
|
78
|
+
if (option.flag === '--kind') {
|
|
79
|
+
for (const kind of recipe.kinds)
|
|
80
|
+
entry.values.add(kind);
|
|
81
|
+
}
|
|
82
|
+
byFlag.set(option.flag, entry);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return [...byFlag.values()].map(entry => ({
|
|
86
|
+
flag: entry.flag,
|
|
87
|
+
description: entry.descriptions.join(' '),
|
|
88
|
+
...(entry.values.size === 0 ? {} : { values: [...entry.values] }),
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
const descriptorArguments = [
|
|
92
|
+
{
|
|
93
|
+
name: 'recipe',
|
|
94
|
+
required: true,
|
|
95
|
+
description: `recipe 名称,当前支持:${recipeNameList}。`,
|
|
96
|
+
},
|
|
97
|
+
];
|
|
98
|
+
export const createCommand = defineCommand({
|
|
99
|
+
descriptor: {
|
|
100
|
+
name: 'create',
|
|
101
|
+
summary: `按 recipe 生成标准结构。当前支持:${registeredRecipes.map(recipe => recipe.name).join(' / ')}。`,
|
|
102
|
+
usage: `yoyo-admin create <${registeredRecipes.map(recipe => recipe.name).join('|')}> [options] [--dry-run] [--json]`,
|
|
103
|
+
arguments: descriptorArguments,
|
|
104
|
+
options: projectRecipeOptions(registeredRecipes),
|
|
105
|
+
authoring: true,
|
|
106
|
+
capability: 'standard-frontend-module-create-wire-verify',
|
|
107
|
+
},
|
|
108
|
+
argumentSpec: createArgumentSpec,
|
|
109
|
+
renderHelp: createHelp,
|
|
110
|
+
run: runCreate,
|
|
111
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `yoyo-admin doctor`
|
|
3
|
+
*
|
|
4
|
+
* 环境与仓库诊断:确认 CLI 能在当前 checkout 上正确工作。
|
|
5
|
+
* 只读,不修改任何文件。
|
|
6
|
+
*/
|
|
7
|
+
import { type CommandContext } from '../kernel/command.js';
|
|
8
|
+
import { type YoyoAdminCliResult } from '../kernel/result.js';
|
|
9
|
+
/** CLI 支持的最低 Node 主版本。与仓库现有 CI 基线一致,不额外抬高。 */
|
|
10
|
+
export declare const MINIMUM_NODE_MAJOR = 20;
|
|
11
|
+
/**
|
|
12
|
+
* 诊断命令是唯一允许在「workspace 定位失败」下继续执行并**如实报告**的命令:
|
|
13
|
+
* 它消费分发层已经解析好的 `context.workspace`,不自行解析仓库。
|
|
14
|
+
*/
|
|
15
|
+
export declare function runDoctor(context: CommandContext): YoyoAdminCliResult;
|
|
16
|
+
export declare const doctorCommand: import("../index.js").RegisteredCommand;
|
|
17
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACzE,OAAO,EAKL,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAA;AAU5B,8CAA8C;AAC9C,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAIpC;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,kBAAkB,CA2CrE;AAmID,eAAO,MAAM,aAAa,yCAUxB,CAAA"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `yoyo-admin doctor`
|
|
3
|
+
*
|
|
4
|
+
* 环境与仓库诊断:确认 CLI 能在当前 checkout 上正确工作。
|
|
5
|
+
* 只读,不修改任何文件。
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { defineCommand } from '../kernel/command.js';
|
|
10
|
+
import { finding, ok, warn, } from '../kernel/result.js';
|
|
11
|
+
import { ADMIN_VUE_HOST_RELATIVE, ADMIN_WORKSPACE_RELATIVE, } from '../kernel/workspace.js';
|
|
12
|
+
import { CRUD_CATALOG_RELATIVE } from '../catalogs/crud.js';
|
|
13
|
+
import { CAPABILITY_CATALOG_RELATIVE } from '../catalogs/capability.js';
|
|
14
|
+
import { runProcess } from '../kernel/process-runner.js';
|
|
15
|
+
/** CLI 支持的最低 Node 主版本。与仓库现有 CI 基线一致,不额外抬高。 */
|
|
16
|
+
export const MINIMUM_NODE_MAJOR = 20;
|
|
17
|
+
const REQUIRED_PACKAGES = ['admin-core', 'admin-schema', 'admin-kit'];
|
|
18
|
+
/**
|
|
19
|
+
* 诊断命令是唯一允许在「workspace 定位失败」下继续执行并**如实报告**的命令:
|
|
20
|
+
* 它消费分发层已经解析好的 `context.workspace`,不自行解析仓库。
|
|
21
|
+
*/
|
|
22
|
+
export function runDoctor(context) {
|
|
23
|
+
const findings = [];
|
|
24
|
+
findings.push(checkNodeVersion());
|
|
25
|
+
findings.push(checkPnpmAvailable(context.startDirectory));
|
|
26
|
+
const workspace = context.workspace;
|
|
27
|
+
if (workspace === undefined) {
|
|
28
|
+
findings.push(finding(context.workspaceError?.code ?? 'repo-root-not-found', 'error', '未能定位 YoyoBoot 仓库,CLI 无法继续。', context.workspaceError?.message ??
|
|
29
|
+
`查找起点:${context.startDirectory}(需要同时存在 .git、` +
|
|
30
|
+
`${ADMIN_WORKSPACE_RELATIVE} 与 ${ADMIN_VUE_HOST_RELATIVE})。`));
|
|
31
|
+
return { command: 'doctor', status: 'error', findings };
|
|
32
|
+
}
|
|
33
|
+
findings.push(finding('repo-root', 'ok', '已定位仓库根目录。', workspace.repoRoot));
|
|
34
|
+
findings.push(...checkWorkspaceLayout(workspace));
|
|
35
|
+
findings.push(...checkPackageManifests(workspace));
|
|
36
|
+
findings.push(...checkGeneratorCatalogs(workspace.repoRoot));
|
|
37
|
+
const data = {
|
|
38
|
+
node: process.versions.node,
|
|
39
|
+
platform: `${process.platform}/${process.arch}`,
|
|
40
|
+
startDirectory: context.startDirectory,
|
|
41
|
+
repoRoot: workspace.repoRoot,
|
|
42
|
+
workspace: workspace.adminWorkspace,
|
|
43
|
+
};
|
|
44
|
+
const hasErrorFinding = findings.some((item) => item.status === 'error');
|
|
45
|
+
const hasWarnFinding = findings.some((item) => item.status === 'warn');
|
|
46
|
+
return hasErrorFinding
|
|
47
|
+
? { command: 'doctor', status: 'error', findings, data }
|
|
48
|
+
: hasWarnFinding
|
|
49
|
+
? warn('doctor', findings, data)
|
|
50
|
+
: ok('doctor', findings, data);
|
|
51
|
+
}
|
|
52
|
+
function checkNodeVersion() {
|
|
53
|
+
const major = Number.parseInt(process.versions.node.split('.')[0] ?? '0', 10);
|
|
54
|
+
if (Number.isNaN(major) || major < MINIMUM_NODE_MAJOR) {
|
|
55
|
+
return finding('node-version', 'error', `Node 主版本需 >= ${MINIMUM_NODE_MAJOR},当前 ${process.versions.node}。`);
|
|
56
|
+
}
|
|
57
|
+
return finding('node-version', 'ok', `Node ${process.versions.node} 满足要求。`);
|
|
58
|
+
}
|
|
59
|
+
function checkPnpmAvailable(cwd) {
|
|
60
|
+
// 如实检查:能执行 `pnpm --version` 才报告 pnpm 可用。
|
|
61
|
+
// CLI 本身通过 `pnpm run cli` 调起,pnpm 缺失时入口都不会执行到这里;
|
|
62
|
+
// 但 doctor 也可能被直接以 node 调用,此处仍需真实结论。
|
|
63
|
+
const probe = runProcess({ command: 'pnpm', args: ['--version'], cwd });
|
|
64
|
+
if (probe.error !== undefined || probe.status !== 0) {
|
|
65
|
+
return finding('package-manager', 'error', 'pnpm 不可执行(`pnpm --version` 失败);包级验证与稳定入口依赖 pnpm。', probe.error instanceof Error ? probe.error.message : String(probe.stderr ?? '').trim());
|
|
66
|
+
}
|
|
67
|
+
const version = String(probe.stdout ?? '').trim();
|
|
68
|
+
if (version !== '11.28.0') {
|
|
69
|
+
return finding('package-manager', 'error', `仓库开发需要 pnpm 11.28.0,当前 ${version}。`);
|
|
70
|
+
}
|
|
71
|
+
return finding('package-manager', 'ok', `pnpm 可用(${version})。`);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* create 依赖的两个生成 catalog 必须存在且可解析。
|
|
75
|
+
* 缺失/损坏不代表环境损坏(可由生成命令修复),因此报 warn 而非 error:
|
|
76
|
+
* doctor 仍可用于环境诊断,但 create 在该状态下会被 plan-time fail-closed 拒绝。
|
|
77
|
+
*/
|
|
78
|
+
function checkGeneratorCatalogs(repoRoot) {
|
|
79
|
+
const findings = [];
|
|
80
|
+
const catalogChecks = [
|
|
81
|
+
{
|
|
82
|
+
relative: CRUD_CATALOG_RELATIVE,
|
|
83
|
+
code: 'crud-catalog',
|
|
84
|
+
label: 'CRUD resource catalog(create frontend-module 依赖)',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
relative: CAPABILITY_CATALOG_RELATIVE,
|
|
88
|
+
code: 'capability-catalog',
|
|
89
|
+
label: 'capability catalog(权限校验依赖)',
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
for (const { relative, code, label } of catalogChecks) {
|
|
93
|
+
const absolute = join(repoRoot, relative);
|
|
94
|
+
if (!existsSync(absolute)) {
|
|
95
|
+
findings.push(finding(code, 'warn', `${label}不存在;相关 create recipe 不可用。`, relative));
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
JSON.parse(readFileSync(absolute, 'utf8'));
|
|
100
|
+
findings.push(finding(code, 'ok', `${label}存在且可解析。`, relative));
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
findings.push(finding(code, 'warn', `${label}解析失败;请重新生成后再执行 create。`, error instanceof Error ? error.message : String(error)));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return findings;
|
|
107
|
+
}
|
|
108
|
+
function checkWorkspaceLayout(workspace) {
|
|
109
|
+
const expected = [
|
|
110
|
+
{ path: workspace.adminWorkspace, label: 'admin 工作区 packages/yoyo-admin' },
|
|
111
|
+
{ path: workspace.adminVueHost, label: 'admin-vue 宿主 apps/yoyo-admin/admin-vue' },
|
|
112
|
+
{ path: join(workspace.adminVueHost, 'src/app'), label: '宿主 app 目录' },
|
|
113
|
+
{
|
|
114
|
+
path: join(workspace.adminVueHost, 'src/app/manifests.ts'),
|
|
115
|
+
label: '显式组合入口 app/manifests.ts',
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
return expected.map(({ path, label }) => existsSync(path)
|
|
119
|
+
? finding('workspace-layout', 'ok', `${label} 存在。`)
|
|
120
|
+
: finding('workspace-layout', 'error', `${label} 不存在。`, path));
|
|
121
|
+
}
|
|
122
|
+
function checkPackageManifests(workspace) {
|
|
123
|
+
const findings = [];
|
|
124
|
+
for (const packageName of REQUIRED_PACKAGES) {
|
|
125
|
+
const manifestPath = join(workspace.adminWorkspace, packageName, 'package.json');
|
|
126
|
+
if (!existsSync(manifestPath)) {
|
|
127
|
+
findings.push(finding('package-manifest', 'error', `缺少包 ${packageName} 的 package.json。`));
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
132
|
+
findings.push(finding('package-manifest', 'ok', `${packageName} → ${manifest.name ?? '(未命名)'}`));
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
findings.push(finding('package-manifest', 'error', `${packageName}/package.json 解析失败。`, error instanceof Error ? error.message : String(error)));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return findings;
|
|
139
|
+
}
|
|
140
|
+
export const doctorCommand = defineCommand({
|
|
141
|
+
descriptor: {
|
|
142
|
+
name: 'doctor',
|
|
143
|
+
summary: '诊断当前环境与仓库布局,确认 CLI 可在此 checkout 上工作。',
|
|
144
|
+
usage: 'yoyo-admin doctor [--repo <path>] [--json]',
|
|
145
|
+
arguments: [],
|
|
146
|
+
options: [],
|
|
147
|
+
authoring: false,
|
|
148
|
+
},
|
|
149
|
+
run: runDoctor,
|
|
150
|
+
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `yoyo-admin inspect <subject>`
|
|
3
|
+
*
|
|
4
|
+
* Agent-facing 只读事实查询:**只投影已有正式事实源**(generated crud catalog /
|
|
5
|
+
* capability catalog),不解析业务源码猜事实、不复制 JSON reader、不 import generator。
|
|
6
|
+
*
|
|
7
|
+
* 设计要点:
|
|
8
|
+
* - `inspect` 本身**永不写文件**(descriptor `authoring: false`);
|
|
9
|
+
* - 「资源不是 standard-crud」是**观察结果**(`standardCrud.eligible: false`),
|
|
10
|
+
* 不是命令失败 —— 只有 resourceKey / permissionName / prefix 根本不存在才 exit 2;
|
|
11
|
+
* - `--json` 输出稳定:所有数组都按确定顺序排序(resourceKey / operation / name)。
|
|
12
|
+
*
|
|
13
|
+
* 明确不做 `inspect module`:module/navigation 的真相是可执行 TypeScript
|
|
14
|
+
* (`app/manifests.ts` → `appModuleManifests` → createYoyoAdminManifestRegistry),
|
|
15
|
+
* 没有静态 navigation manifest catalog。用正则/AST 猜 route/page 会重新制造
|
|
16
|
+
* 「双维护事实」,因此本轮不提供,等宿主给出正式的 machine projection 再消费。
|
|
17
|
+
*/
|
|
18
|
+
import { type CommandContext } from '../kernel/command.js';
|
|
19
|
+
import { type RecipeHelpSurface } from '../kernel/help.js';
|
|
20
|
+
import { type YoyoAdminCliResult } from '../kernel/result.js';
|
|
21
|
+
import { type CapabilityPermissionDescriptor } from '../catalogs/capability.js';
|
|
22
|
+
import type { CatalogSource } from '../catalogs/source.js';
|
|
23
|
+
export interface InspectSubject {
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly summary: string;
|
|
26
|
+
readonly usage: string;
|
|
27
|
+
readonly arguments: readonly {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly required: boolean;
|
|
30
|
+
readonly description: string;
|
|
31
|
+
}[];
|
|
32
|
+
readonly options: readonly {
|
|
33
|
+
readonly flag: string;
|
|
34
|
+
readonly required: boolean;
|
|
35
|
+
readonly description: string;
|
|
36
|
+
readonly values?: readonly string[];
|
|
37
|
+
}[];
|
|
38
|
+
readonly run: (context: CommandContext, args: readonly string[]) => YoyoAdminCliResult;
|
|
39
|
+
}
|
|
40
|
+
export declare function listInspectSubjects(): readonly InspectSubject[];
|
|
41
|
+
export declare function resolveInspectSubject(name: string): InspectSubject | undefined;
|
|
42
|
+
export interface InspectResourcesPayload {
|
|
43
|
+
readonly kind: 'resources';
|
|
44
|
+
readonly source: CatalogSource;
|
|
45
|
+
readonly resources: readonly {
|
|
46
|
+
readonly resourceKey: string;
|
|
47
|
+
readonly serviceName: string;
|
|
48
|
+
readonly operations: readonly string[];
|
|
49
|
+
}[];
|
|
50
|
+
}
|
|
51
|
+
export interface InspectResourcePayload {
|
|
52
|
+
readonly kind: 'resource';
|
|
53
|
+
readonly source: CatalogSource;
|
|
54
|
+
readonly resource: {
|
|
55
|
+
readonly resourceKey: string;
|
|
56
|
+
readonly serviceName: string;
|
|
57
|
+
readonly operations: readonly {
|
|
58
|
+
readonly operation: string;
|
|
59
|
+
readonly operationId: string;
|
|
60
|
+
}[];
|
|
61
|
+
readonly requestSchemas: readonly {
|
|
62
|
+
readonly operation: string;
|
|
63
|
+
readonly schemaRef: string;
|
|
64
|
+
}[];
|
|
65
|
+
readonly binding: {
|
|
66
|
+
readonly list?: {
|
|
67
|
+
readonly queryParameters: readonly {
|
|
68
|
+
readonly parameter: string;
|
|
69
|
+
readonly field: string;
|
|
70
|
+
}[];
|
|
71
|
+
readonly itemsPath: readonly string[];
|
|
72
|
+
readonly totalCountPath: readonly string[];
|
|
73
|
+
};
|
|
74
|
+
readonly getForEdit?: {
|
|
75
|
+
readonly idParameter: string;
|
|
76
|
+
readonly entityPath: readonly string[];
|
|
77
|
+
};
|
|
78
|
+
readonly create?: {
|
|
79
|
+
readonly fieldMappings: readonly CrudFieldMappingView[];
|
|
80
|
+
};
|
|
81
|
+
readonly update?: {
|
|
82
|
+
readonly fieldMappings: readonly CrudFieldMappingView[];
|
|
83
|
+
};
|
|
84
|
+
readonly setEnabled?: {
|
|
85
|
+
readonly fieldMappings: readonly CrudFieldMappingView[];
|
|
86
|
+
};
|
|
87
|
+
readonly remove?: {
|
|
88
|
+
readonly idParameter: string;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
readonly standardCrud: {
|
|
92
|
+
readonly eligible: true;
|
|
93
|
+
readonly rowKey: string;
|
|
94
|
+
readonly formFields: readonly {
|
|
95
|
+
readonly key: string;
|
|
96
|
+
readonly editableOn: string;
|
|
97
|
+
}[];
|
|
98
|
+
readonly operations: {
|
|
99
|
+
readonly create: boolean;
|
|
100
|
+
readonly update: boolean;
|
|
101
|
+
readonly setEnabled: boolean;
|
|
102
|
+
readonly remove: boolean;
|
|
103
|
+
};
|
|
104
|
+
} | {
|
|
105
|
+
readonly eligible: false;
|
|
106
|
+
readonly code: string;
|
|
107
|
+
readonly message: string;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
interface CrudFieldMappingView {
|
|
112
|
+
readonly source: string;
|
|
113
|
+
readonly target: readonly string[];
|
|
114
|
+
}
|
|
115
|
+
export interface InspectPermissionsPayload {
|
|
116
|
+
readonly kind: 'permissions';
|
|
117
|
+
readonly source: CatalogSource;
|
|
118
|
+
/** `null` = 未加 `--prefix`,返回全部权限。 */
|
|
119
|
+
readonly prefix: string | null;
|
|
120
|
+
readonly permissions: readonly CapabilityPermissionDescriptor[];
|
|
121
|
+
}
|
|
122
|
+
export interface InspectPermissionPayload {
|
|
123
|
+
readonly kind: 'permission';
|
|
124
|
+
readonly source: CatalogSource;
|
|
125
|
+
readonly permission: CapabilityPermissionDescriptor;
|
|
126
|
+
/** 由 parent 链派生的祖先,从根到直接父级。 */
|
|
127
|
+
readonly ancestors: readonly string[];
|
|
128
|
+
readonly directChildren: readonly string[];
|
|
129
|
+
}
|
|
130
|
+
export type InspectPayload = InspectResourcesPayload | InspectResourcePayload | InspectPermissionsPayload | InspectPermissionPayload;
|
|
131
|
+
export declare function isInspectPayload(value: unknown): value is InspectPayload;
|
|
132
|
+
/** `inspect` 的 help 投影面:与 create 共用同一套渲染器。 */
|
|
133
|
+
export declare const INSPECT_HELP_SURFACE: RecipeHelpSurface;
|
|
134
|
+
export declare function runInspect(context: CommandContext): YoyoAdminCliResult;
|
|
135
|
+
export declare const inspectCommand: import("../index.js").RegisteredCommand;
|
|
136
|
+
/** 人类可读输出(`--json` 走结果信封,不经过这里)。 */
|
|
137
|
+
export declare function renderInspectPayload(payload: InspectPayload): string;
|
|
138
|
+
export {};
|
|
139
|
+
//# sourceMappingURL=inspect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../src/commands/inspect.ts"],"names":[],"mappings":"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"}
|