@formlm/cli 0.3.0 → 0.5.1
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/README.md +326 -65
- package/dist/commands/app.d.ts.map +1 -1
- package/dist/commands/app.js +74 -16
- package/dist/commands/app.js.map +1 -1
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +186 -7
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/connect.js +3 -3
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/doctor.d.ts +11 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +109 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/expert.d.ts.map +1 -1
- package/dist/commands/expert.js +42 -18
- package/dist/commands/expert.js.map +1 -1
- package/dist/commands/field.d.ts.map +1 -1
- package/dist/commands/field.js +9 -11
- package/dist/commands/field.js.map +1 -1
- package/dist/commands/profile.js +1 -1
- package/dist/commands/profile.js.map +1 -1
- package/dist/commands/report.d.ts.map +1 -1
- package/dist/commands/report.js +39 -12
- package/dist/commands/report.js.map +1 -1
- package/dist/commands/scale.d.ts.map +1 -1
- package/dist/commands/scale.js +4 -1
- package/dist/commands/scale.js.map +1 -1
- package/dist/commands/share.d.ts.map +1 -1
- package/dist/commands/share.js +258 -28
- package/dist/commands/share.js.map +1 -1
- package/dist/commands/skill.d.ts.map +1 -1
- package/dist/commands/skill.js +2 -3
- package/dist/commands/skill.js.map +1 -1
- package/dist/commands/smart.d.ts.map +1 -1
- package/dist/commands/smart.js +337 -59
- package/dist/commands/smart.js.map +1 -1
- package/dist/commands/snapshot.d.ts +0 -11
- package/dist/commands/snapshot.d.ts.map +1 -1
- package/dist/commands/snapshot.js +168 -42
- package/dist/commands/snapshot.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/doctor.d.ts +51 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +202 -0
- package/dist/doctor.js.map +1 -0
- package/dist/exec.d.ts +39 -1
- package/dist/exec.d.ts.map +1 -1
- package/dist/exec.js +309 -4
- package/dist/exec.js.map +1 -1
- package/dist/index.js +55 -6
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +283 -67
- package/dist/mcp.js.map +1 -1
- package/dist/output.d.ts +23 -1
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +69 -7
- package/dist/output.js.map +1 -1
- package/dist/summary.d.ts +17 -0
- package/dist/summary.d.ts.map +1 -0
- package/dist/summary.js +64 -0
- package/dist/summary.js.map +1 -0
- package/dist/utils.d.ts +10 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +45 -6
- package/dist/utils.js.map +1 -1
- package/package.json +11 -2
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { execCommand } from '../exec.js';
|
|
2
|
+
import { output, localFail, isJsonMode, guidance } from '../output.js';
|
|
3
|
+
import { asArray, buildSummary } from '../summary.js';
|
|
2
4
|
/**
|
|
3
5
|
* Snapshot Command — Aggregated App State Query
|
|
4
6
|
*
|
|
@@ -9,62 +11,186 @@ import { execCommand } from '../exec.js';
|
|
|
9
11
|
*
|
|
10
12
|
* By default, all modules use --json for consistent structured output.
|
|
11
13
|
* Use --md to switch to markdown format (token-efficient for AI consumption).
|
|
14
|
+
* Use --summary for a compact machine-checkable profile (field/question/dimension counts,
|
|
15
|
+
* report pages, expert/share state, styled flag) — the right tool for batch audits.
|
|
16
|
+
* Use --apps id1,id2 to read a batch inside one process (no per-app Node cold start).
|
|
17
|
+
*
|
|
18
|
+
* NOTE: this command is CLIENT-SYNTHESIZED (6 parallel `assess <module> query` calls over
|
|
19
|
+
* the exec channel). There is no server-side `assess snapshot`, so raw POST /api/v1/mcp/exec
|
|
20
|
+
* with "assess snapshot ..." is expected to be rejected (403) — loop the 6 queries instead.
|
|
12
21
|
*/
|
|
22
|
+
const VALID_MODULES = ['form', 'scale', 'connect', 'report', 'expert', 'share'];
|
|
23
|
+
/** Read the requested modules (+ app title) for one app and assemble the snapshot. */
|
|
24
|
+
async function collect(appId, opts) {
|
|
25
|
+
const modules = opts.module ? [opts.module] : VALID_MODULES;
|
|
26
|
+
const format = opts.md && !opts.summary ? '--md' : '--json';
|
|
27
|
+
const commands = {
|
|
28
|
+
form: `assess form query --app ${appId} ${format}`,
|
|
29
|
+
scale: `assess scale query --app ${appId} ${format}`,
|
|
30
|
+
connect: `assess connect query --app ${appId} ${format}`,
|
|
31
|
+
report: `assess report query --app ${appId} ${format}`,
|
|
32
|
+
expert: `assess expert query --app ${appId} ${format}`,
|
|
33
|
+
share: `assess share query --app ${appId} ${format}`,
|
|
34
|
+
};
|
|
35
|
+
// App title is not part of any module payload — fetch it once in parallel
|
|
36
|
+
// (assess app use returns {appId,name,description,type}) so page↔app name audits work.
|
|
37
|
+
const [execResults, appResult] = await Promise.all([
|
|
38
|
+
Promise.all(modules.map((m) => execCommand(commands[m]).then((r) => [m, r]))),
|
|
39
|
+
execCommand(`assess app use --app ${appId} --json`),
|
|
40
|
+
]);
|
|
41
|
+
let appName = '';
|
|
42
|
+
if (appResult.code === 0 && appResult.data) {
|
|
43
|
+
try {
|
|
44
|
+
appName = (typeof appResult.data === 'string' ? JSON.parse(appResult.data) : appResult.data)?.name || '';
|
|
45
|
+
}
|
|
46
|
+
catch { }
|
|
47
|
+
}
|
|
48
|
+
const snapshot = { appId, appName: appName || null };
|
|
49
|
+
const errors = [];
|
|
50
|
+
const parsedMods = {};
|
|
51
|
+
for (const [module, result] of execResults) {
|
|
52
|
+
if (result.code === 0) {
|
|
53
|
+
if (!opts.md) {
|
|
54
|
+
try {
|
|
55
|
+
snapshot[module] = JSON.parse(result.data);
|
|
56
|
+
parsedMods[module] = snapshot[module];
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
snapshot[module] = result.data || result.message;
|
|
60
|
+
parsedMods[module] = null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
snapshot[module] = result.data || result.message;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Partial-failure visibility: mark degraded instead of a bare null that
|
|
69
|
+
// batch auditors misread as "module exists but empty".
|
|
70
|
+
snapshot[module] = null;
|
|
71
|
+
snapshot['_degraded'] = true;
|
|
72
|
+
errors.push(`${module}: [${result.code}] ${result.message}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Optional deep-fill: widget values per report page (the compact report query omits value)
|
|
76
|
+
if (opts.withValues && !opts.md && parsedMods.report) {
|
|
77
|
+
try {
|
|
78
|
+
const pages = asArray(parsedMods.report);
|
|
79
|
+
const valueLists = await Promise.all(pages.map((p) => p?.id
|
|
80
|
+
? execCommand(`assess report widget list --app ${appId} --page ${p.id} --json`)
|
|
81
|
+
: Promise.resolve(null)));
|
|
82
|
+
// report is an ARRAY of pages server-side — attach values per page object
|
|
83
|
+
pages.forEach((p, i) => {
|
|
84
|
+
const r = valueLists[i];
|
|
85
|
+
let widgets = null;
|
|
86
|
+
if (r && r.code === 0 && r.data) {
|
|
87
|
+
try {
|
|
88
|
+
widgets = JSON.parse(r.data);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
widgets = r.data;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (p && typeof p === 'object')
|
|
95
|
+
p.widgetsFull = widgets;
|
|
96
|
+
});
|
|
97
|
+
snapshot.report = pages;
|
|
98
|
+
parsedMods.report = pages;
|
|
99
|
+
}
|
|
100
|
+
catch { /* keep snapshot as-is if deep-fill fails */ }
|
|
101
|
+
}
|
|
102
|
+
if (errors.length > 0)
|
|
103
|
+
snapshot['_errors'] = errors;
|
|
104
|
+
return { snapshot, appName, parsedMods, errors };
|
|
105
|
+
}
|
|
13
106
|
export function registerSnapshotCommand(parent) {
|
|
14
107
|
parent
|
|
15
108
|
.command('snapshot')
|
|
16
|
-
.description('Get aggregated snapshot of ALL app modules (form + scale + connect + report + expert + share) — one call, full context')
|
|
17
|
-
.
|
|
18
|
-
.option('--
|
|
109
|
+
.description('Get aggregated snapshot of ALL app modules (form + scale + connect + report + expert + share) — one call, full context. Client-synthesized from 6 module queries (no server-side "assess snapshot" exists on the raw exec channel). --summary returns a compact audit profile; --apps runs a batch in one process.')
|
|
110
|
+
.option('--app <appId>', 'App ID (single app)')
|
|
111
|
+
.option('--apps <ids>', 'Batch mode: comma-separated app IDs, read in one process (combine with --summary; concurrency via FORMLM_CONCURRENCY, default 4). Replaces per-app subprocess loops.')
|
|
112
|
+
.option('--module <name>', `Get only a specific module: ${VALID_MODULES.join(' / ')} (default: all)`)
|
|
19
113
|
.option('--md', 'Output all modules in Markdown format (token-efficient for AI, default: JSON)')
|
|
114
|
+
.option('--summary', 'Compact audit profile only (fieldCount/questionCount/dimCount/reportPages/styled/expert/share), instead of full module payloads')
|
|
115
|
+
.option('--with-values', 'In full JSON mode, also fetch each report page widget values (extra report widget list calls; needed to language/content-audit report text — the compact snapshot query omits value)')
|
|
20
116
|
.action(async (opts) => {
|
|
21
|
-
const validModules = ['form', 'scale', 'connect', 'report', 'expert', 'share'];
|
|
22
117
|
// Validate module name early — prevent silent empty snapshot
|
|
23
|
-
if (opts.module && !
|
|
24
|
-
|
|
25
|
-
process.exit(1);
|
|
118
|
+
if (opts.module && !VALID_MODULES.includes(opts.module)) {
|
|
119
|
+
localFail(`Invalid module "${opts.module}". Valid: ${VALID_MODULES.join(', ')}`);
|
|
26
120
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
snapshot[module] = result.data || result.message;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
snapshot[module] = result.data || result.message;
|
|
121
|
+
if (!opts.app && !opts.apps)
|
|
122
|
+
localFail('Either --app <appId> or --apps <id1,id2,...> is required.');
|
|
123
|
+
if (opts.app && opts.apps)
|
|
124
|
+
localFail('Use either --app or --apps, not both.');
|
|
125
|
+
if (opts.apps && !opts.summary && !opts.module) {
|
|
126
|
+
// Full payloads for a batch would be enormous; require an explicit narrowing.
|
|
127
|
+
guidance('⚠️ --apps without --summary/--module returns full payloads for every app (large). Add --summary for the compact batch profile.');
|
|
128
|
+
}
|
|
129
|
+
// ── Batch mode ───────────────────────────────────────────
|
|
130
|
+
if (opts.apps) {
|
|
131
|
+
const ids = String(opts.apps).split(',').map(s => s.trim()).filter(Boolean);
|
|
132
|
+
if (ids.length === 0)
|
|
133
|
+
localFail('--apps listed no valid app ID.');
|
|
134
|
+
const CONC = Number(process.env.FORMLM_CONCURRENCY) || 4;
|
|
135
|
+
const out = new Array(ids.length);
|
|
136
|
+
let cursor = 0;
|
|
137
|
+
const worker = async () => {
|
|
138
|
+
for (;;) {
|
|
139
|
+
const i = cursor++;
|
|
140
|
+
if (i >= ids.length)
|
|
141
|
+
return;
|
|
142
|
+
const c = await collect(ids[i], opts);
|
|
143
|
+
out[i] = opts.summary
|
|
144
|
+
? Object.assign({ _degraded: c.errors.length > 0 ? true : undefined }, buildSummary(ids[i], c.appName, c.parsedMods), c.errors.length ? { _errors: c.errors } : {})
|
|
145
|
+
: c.snapshot;
|
|
57
146
|
}
|
|
147
|
+
};
|
|
148
|
+
await Promise.all(Array.from({ length: Math.min(CONC, ids.length) }, worker));
|
|
149
|
+
const anyDegraded = out.some(o => o?._degraded);
|
|
150
|
+
output({
|
|
151
|
+
code: anyDegraded ? 207 : 0,
|
|
152
|
+
message: anyDegraded ? 'partial: one or more apps had unreadable modules' : 'ok',
|
|
153
|
+
data: JSON.stringify({ count: out.length, apps: out }),
|
|
154
|
+
});
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const c = await collect(opts.app, opts);
|
|
158
|
+
if (opts.summary) {
|
|
159
|
+
const summary = buildSummary(opts.app, c.appName, c.parsedMods);
|
|
160
|
+
if (opts.withValues)
|
|
161
|
+
summary['_withValuesNote'] = 'widget values fetched per report page (see the full snapshot --with-values output, not part of summary)';
|
|
162
|
+
if (c.errors.length > 0) {
|
|
163
|
+
summary['_errors'] = c.errors;
|
|
164
|
+
summary['_degraded'] = true;
|
|
165
|
+
}
|
|
166
|
+
// Never report ok for a partial read: counts of unreadable modules are 0-by-absence,
|
|
167
|
+
// not truth — code 500 when nothing could be read, 207 when the profile is incomplete.
|
|
168
|
+
const nothingRead = Object.values(c.parsedMods).every(v => v === null);
|
|
169
|
+
const code = c.errors.length === 0 ? 0 : (nothingRead ? 500 : 207);
|
|
170
|
+
if (nothingRead)
|
|
171
|
+
summary['_note'] = 'All module reads failed — the zero counts below are UNKNOWNS, not empty state.';
|
|
172
|
+
if (isJsonMode()) {
|
|
173
|
+
console.log(JSON.stringify({ ok: code === 0, code, message: code === 0 ? 'ok' : (nothingRead ? 'unreadable' : 'partial'), data: summary }));
|
|
58
174
|
}
|
|
59
175
|
else {
|
|
60
|
-
|
|
61
|
-
|
|
176
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
177
|
+
if (code !== 0 && process.env.FORMLM_NO_EXIT !== '1')
|
|
178
|
+
process.exit(1);
|
|
62
179
|
}
|
|
180
|
+
return;
|
|
63
181
|
}
|
|
64
|
-
if (
|
|
65
|
-
|
|
182
|
+
if (opts.md) {
|
|
183
|
+
// Markdown mode keeps the historic plain output (no envelope concept)
|
|
184
|
+
console.log(JSON.stringify(c.snapshot, null, 2));
|
|
185
|
+
return;
|
|
66
186
|
}
|
|
67
|
-
|
|
187
|
+
// Unified envelope contract: route through output() so snapshot speaks the
|
|
188
|
+
// same {ok,code,message,data} language as every other command under FORMLM_JSON.
|
|
189
|
+
output({
|
|
190
|
+
code: c.errors.length === 0 ? 0 : (Object.keys(c.parsedMods).length > 0 ? 207 : 500),
|
|
191
|
+
message: c.errors.length === 0 ? 'ok' : `partial: ${c.errors.join('; ')}`,
|
|
192
|
+
data: JSON.stringify(c.snapshot),
|
|
193
|
+
});
|
|
68
194
|
});
|
|
69
195
|
}
|
|
70
196
|
//# sourceMappingURL=snapshot.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/commands/snapshot.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/commands/snapshot.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEtD;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAgBhF,sFAAsF;AACtF,KAAK,UAAU,OAAO,CAAC,KAAa,EAAE,IAAiB;IACrD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;IAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;IAE5D,MAAM,QAAQ,GAA2B;QACvC,IAAI,EAAE,2BAA2B,KAAK,IAAI,MAAM,EAAE;QAClD,KAAK,EAAE,4BAA4B,KAAK,IAAI,MAAM,EAAE;QACpD,OAAO,EAAE,8BAA8B,KAAK,IAAI,MAAM,EAAE;QACxD,MAAM,EAAE,6BAA6B,KAAK,IAAI,MAAM,EAAE;QACtD,MAAM,EAAE,6BAA6B,KAAK,IAAI,MAAM,EAAE;QACtD,KAAK,EAAE,4BAA4B,KAAK,IAAI,MAAM,EAAE;KACrD,CAAC;IAEF,0EAA0E;IAC1E,uFAAuF;IACvF,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAU,CAAC,CAAC,CAAC;QACtF,WAAW,CAAC,wBAAwB,KAAK,SAAS,CAAC;KACpD,CAAC,CAAC;IAEH,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC;QAC3C,IAAI,CAAC;YAAC,OAAO,GAAG,CAAC,OAAO,SAAS,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IAC5H,CAAC;IAED,MAAM,QAAQ,GAA4B,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,CAAC;IAC9E,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,UAAU,GAAwB,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC3C,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;gBACb,IAAI,CAAC;oBACH,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;oBAC3C,UAAU,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACxC,CAAC;gBAAC,MAAM,CAAC;oBACP,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC;oBACjD,UAAU,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;gBAC5B,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC;YACnD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,wEAAwE;YACxE,uDAAuD;YACvD,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;YACxB,QAAQ,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,MAAM,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,2FAA2F;IAC3F,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;QACrD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACzC,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,GAAG,CAClC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE;gBACzB,CAAC,CAAC,WAAW,CAAC,mCAAmC,KAAK,WAAW,CAAC,CAAC,EAAE,SAAS,CAAC;gBAC/E,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAC3B,CAAC;YACF,0EAA0E;YAC1E,KAAK,CAAC,OAAO,CAAC,CAAC,CAAM,EAAE,CAAS,EAAE,EAAE;gBAClC,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;gBACxB,IAAI,OAAO,GAAQ,IAAI,CAAC;gBACxB,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;oBAAC,IAAI,CAAC;wBAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAAC,CAAC;oBAAC,MAAM,CAAC;wBAAC,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC;oBAAC,CAAC;gBAAC,CAAC;gBACtG,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;oBAAE,CAAC,CAAC,WAAW,GAAG,OAAO,CAAC;YAC1D,CAAC,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC;YACxB,UAAU,CAAC,MAAM,GAAG,KAAK,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC,CAAC,4CAA4C,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC;IACpD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAe;IACrD,MAAM;SACH,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,oTAAoT,CAAC;SACjU,MAAM,CAAC,eAAe,EAAE,qBAAqB,CAAC;SAC9C,MAAM,CAAC,cAAc,EAAE,sKAAsK,CAAC;SAC9L,MAAM,CAAC,iBAAiB,EAAE,+BAA+B,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC;SACpG,MAAM,CAAC,MAAM,EAAE,+EAA+E,CAAC;SAC/F,MAAM,CAAC,WAAW,EAAE,iIAAiI,CAAC;SACtJ,MAAM,CAAC,eAAe,EAAE,sLAAsL,CAAC;SAC/M,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,6DAA6D;QAC7D,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACxD,SAAS,CAAC,mBAAmB,IAAI,CAAC,MAAM,aAAa,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,SAAS,CAAC,2DAA2D,CAAC,CAAC;QACpG,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI;YAAE,SAAS,CAAC,uCAAuC,CAAC,CAAC;QAC9E,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAC/C,8EAA8E;YAC9E,QAAQ,CAAC,iIAAiI,CAAC,CAAC;QAC9I,CAAC;QAED,4DAA4D;QAC5D,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC5E,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS,CAAC,gCAAgC,CAAC,CAAC;YAClE,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;YACzD,MAAM,GAAG,GAAU,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACzC,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,MAAM,MAAM,GAAG,KAAK,IAAI,EAAE;gBACxB,SAAS,CAAC;oBACR,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC;oBACnB,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM;wBAAE,OAAO;oBAC5B,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;oBACtC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO;wBACnB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBACnK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;gBACjB,CAAC;YACH,CAAC,CAAC;YACF,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;YAC9E,MAAM,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;YAChD,MAAM,CAAC;gBACL,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBAC3B,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,kDAAkD,CAAC,CAAC,CAAC,IAAI;gBAChF,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;aACvD,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAExC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;YAChE,IAAI,IAAI,CAAC,UAAU;gBAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,yGAAyG,CAAC;YAC5J,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;gBAAC,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;YAAC,CAAC;YACxF,qFAAqF;YACrF,uFAAuF;YACvF,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;YACvE,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACnE,IAAI,WAAW;gBAAE,OAAO,CAAC,OAAO,CAAC,GAAG,gFAAgF,CAAC;YACrH,IAAI,UAAU,EAAE,EAAE,CAAC;gBACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,KAAK,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YAC9I,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC9C,IAAI,IAAI,KAAK,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,GAAG;oBAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACxE,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,sEAAsE;YACtE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACjD,OAAO;QACT,CAAC;QAED,2EAA2E;QAC3E,iFAAiF;QACjF,MAAM,CAAC;YACL,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YACpF,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACzE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;SACjC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/config.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export interface Profile {
|
|
|
7
7
|
export interface Config {
|
|
8
8
|
profiles: Profile[];
|
|
9
9
|
}
|
|
10
|
+
export declare const CONFIG_DIR: string;
|
|
10
11
|
export declare function loadConfig(): Config;
|
|
11
12
|
export declare function saveConfig(config: Config): void;
|
|
12
13
|
export declare function getActiveProfile(): Profile | null;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,eAAO,MAAM,UAAU,QAAqC,CAAC;AAG7D,wBAAgB,UAAU,IAAI,MAAM,CAUnC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAK/C;AAED,wBAAgB,gBAAgB,IAAI,OAAO,GAAG,IAAI,CAGjD;AAED,wBAAgB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAIxD;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAErD;AAID,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAajD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAStD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAYnD"}
|
package/dist/config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import * as os from 'node:os';
|
|
4
|
-
const CONFIG_DIR = path.join(os.homedir(), '.formlm');
|
|
4
|
+
export const CONFIG_DIR = path.join(os.homedir(), '.formlm');
|
|
5
5
|
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
6
6
|
export function loadConfig() {
|
|
7
7
|
if (!fs.existsSync(CONFIG_FILE)) {
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAa9B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/doctor.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doctor core — one-call READ-ONLY quality inspection of an app.
|
|
3
|
+
*
|
|
4
|
+
* Consolidates the audits batch agents otherwise hand-roll outside the CLI (regex scans
|
|
5
|
+
* over dozens of apps, per-page widget queries, `share query` + `curl`). Each finding
|
|
6
|
+
* carries a level so scripts can gate on `fail` while humans review `warn`.
|
|
7
|
+
* Shared by the `doctor` CLI command and the `formlm_doctor` MCP tool so both surfaces
|
|
8
|
+
* give identical verdicts.
|
|
9
|
+
*
|
|
10
|
+
* Checks:
|
|
11
|
+
* content form fields / scored questions / dimensions / report pages present
|
|
12
|
+
* scoredNoDim scored questions exist but no scale dimension (scores go nowhere)
|
|
13
|
+
* expert enabled-but-empty / configured-but-disabled / referenced-but-missing
|
|
14
|
+
* styling not styled (plain default look)
|
|
15
|
+
* report dimensions without report pages, or report pages with nothing scored
|
|
16
|
+
* certificate certificate-like page on an app whose type/name says "certificate"
|
|
17
|
+
* language --expect-lang: script-consistency scan of titles (+ widget values with deep)
|
|
18
|
+
* share published / anonymous vs login-required / permanence / expiry
|
|
19
|
+
* reachability fill-in URL answers (HTTP 200 alone never proves anonymous access)
|
|
20
|
+
*/
|
|
21
|
+
export type DoctorLevel = 'pass' | 'warn' | 'fail';
|
|
22
|
+
export interface DoctorFinding {
|
|
23
|
+
name: string;
|
|
24
|
+
level: DoctorLevel;
|
|
25
|
+
detail: string;
|
|
26
|
+
fix?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface DoctorOptions {
|
|
29
|
+
/** BCP-47 expected language, e.g. en / zh / zh-hant / ja. Enables the language check. */
|
|
30
|
+
expectLang?: string;
|
|
31
|
+
/** Also fetch per-page widget values (N extra queries) for the language scan. */
|
|
32
|
+
deep?: boolean;
|
|
33
|
+
/** Probe the fill-in URL for reachability (default true). */
|
|
34
|
+
probe?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface DoctorReport {
|
|
37
|
+
appId: string;
|
|
38
|
+
appName: string | null;
|
|
39
|
+
appType: string | null;
|
|
40
|
+
ok: boolean;
|
|
41
|
+
failCount: number;
|
|
42
|
+
warnCount: number;
|
|
43
|
+
summary: any;
|
|
44
|
+
findings: DoctorFinding[];
|
|
45
|
+
}
|
|
46
|
+
/** Target-language script uses CJK glyphs? (zh/ja/ko families) */
|
|
47
|
+
export declare function langIsCJK(lang: string): boolean;
|
|
48
|
+
/** BCP-47 shape guard used by both the CLI flag and the MCP tool parameter. */
|
|
49
|
+
export declare function isValidLangCode(lang: string): boolean;
|
|
50
|
+
export declare function runDoctor(appId: string, opts?: DoctorOptions): Promise<DoctorReport>;
|
|
51
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AACnD,MAAM,WAAW,aAAa;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE;AACjG,MAAM,WAAW,aAAa;IAC5B,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,6DAA6D;IAC7D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AACD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,GAAG,CAAC;IACb,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AASD,kEAAkE;AAClE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG/C;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AASD,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAoK9F"}
|
package/dist/doctor.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { execCommand, probeUrl } from './exec.js';
|
|
2
|
+
import { getBaseUrl } from './config.js';
|
|
3
|
+
import { absHttpsUrl } from './utils.js';
|
|
4
|
+
import { asArray, buildSummary } from './summary.js';
|
|
5
|
+
const CJK_RE = /[\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF]/;
|
|
6
|
+
const CERT_NAME_RE = /证书|證書|certificate|diploma|结业|結業|completion/i;
|
|
7
|
+
function finding(name, level, detail, fix) {
|
|
8
|
+
return { name, level, detail, fix };
|
|
9
|
+
}
|
|
10
|
+
/** Target-language script uses CJK glyphs? (zh/ja/ko families) */
|
|
11
|
+
export function langIsCJK(lang) {
|
|
12
|
+
const l = String(lang || '').toLowerCase();
|
|
13
|
+
return l.startsWith('zh') || l.startsWith('ja') || l.startsWith('ko');
|
|
14
|
+
}
|
|
15
|
+
/** BCP-47 shape guard used by both the CLI flag and the MCP tool parameter. */
|
|
16
|
+
export function isValidLangCode(lang) {
|
|
17
|
+
return /^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,4})*$/.test(String(lang || ''));
|
|
18
|
+
}
|
|
19
|
+
async function jsonExec(cmd, timeoutMs) {
|
|
20
|
+
const r = await execCommand(cmd, undefined, timeoutMs);
|
|
21
|
+
if (r.code !== 0)
|
|
22
|
+
return { __error: `[${r.code}] ${r.message}`, __code: r.code };
|
|
23
|
+
if (r.data === null || r.data === undefined)
|
|
24
|
+
return null;
|
|
25
|
+
try {
|
|
26
|
+
return typeof r.data === 'string' ? JSON.parse(r.data) : r.data;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return r.data;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export async function runDoctor(appId, opts = {}) {
|
|
33
|
+
// Module payloads + app title (app use also carries `type`), all in parallel
|
|
34
|
+
const [appRaw, form, scale, connect, report, expert, share] = await Promise.all([
|
|
35
|
+
jsonExec(`assess app use --app ${appId} --json`),
|
|
36
|
+
jsonExec(`assess form query --app ${appId} --json`),
|
|
37
|
+
jsonExec(`assess scale query --app ${appId} --json`),
|
|
38
|
+
jsonExec(`assess connect query --app ${appId} --json`),
|
|
39
|
+
jsonExec(`assess report query --app ${appId} --json`),
|
|
40
|
+
jsonExec(`assess expert query --app ${appId} --json`),
|
|
41
|
+
jsonExec(`assess share query --app ${appId} --json`),
|
|
42
|
+
]);
|
|
43
|
+
const urls = await jsonExec(`assess app urls --app ${appId} --json`);
|
|
44
|
+
const mods = {
|
|
45
|
+
form: form && !form.__error ? form : null,
|
|
46
|
+
scale: scale && !scale.__error ? scale : null,
|
|
47
|
+
connect: connect && !connect.__error ? connect : null,
|
|
48
|
+
report: report && !report.__error ? report : null,
|
|
49
|
+
// expert query --json yields the literal "无数据" when unconfigured → not an object
|
|
50
|
+
expert: expert && !expert.__error && typeof expert === 'object' ? expert : null,
|
|
51
|
+
share: share && !share.__error ? share : null,
|
|
52
|
+
};
|
|
53
|
+
const degraded = [];
|
|
54
|
+
for (const [name, val] of Object.entries({ form, scale, connect, report, expert, share })) {
|
|
55
|
+
if (val && val.__error)
|
|
56
|
+
degraded.push(`${name}: ${val.__error}`);
|
|
57
|
+
}
|
|
58
|
+
const appName = (appRaw && !appRaw.__error && appRaw.name) || '';
|
|
59
|
+
const appType = (appRaw && !appRaw.__error && appRaw.type) || '';
|
|
60
|
+
const s = buildSummary(appId, appName, mods);
|
|
61
|
+
const findings = [];
|
|
62
|
+
// ── content ─────────────────────────────────────────────────
|
|
63
|
+
if (degraded.length > 0) {
|
|
64
|
+
findings.push(finding('fetch', 'warn', `Some modules could not be read; their checks were SKIPPED (they did not pass): ${degraded.join('; ')}`));
|
|
65
|
+
}
|
|
66
|
+
if (!mods.form) {
|
|
67
|
+
findings.push(finding('content', 'fail', 'Form module unreadable or absent — the app has no field definitions.'));
|
|
68
|
+
}
|
|
69
|
+
else if (s.fieldCount === 0) {
|
|
70
|
+
findings.push(finding('content', 'fail', 'App has 0 fields — the fill-in page will be blank.', `formlm-cli field add --app ${appId} --id q1 --title "..." --type radio`));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
findings.push(finding('content', 'pass', `${s.fieldCount} fields (${s.questionCount} scored), ${s.dimCount} dimensions, ${s.reportPageCount} report pages.`));
|
|
74
|
+
}
|
|
75
|
+
if (s.questionCount > 0 && s.dimCount === 0) {
|
|
76
|
+
findings.push(finding('scoredNoDim', 'fail', `${s.questionCount} scored questions exist but NO scale dimension is defined — answers are collected yet never scored, so report scores stay empty.`, `formlm-cli scale add --app ${appId} --id <dim> --name "<Dim>" --format sum --kbText "..."`));
|
|
77
|
+
}
|
|
78
|
+
// ── expert ──────────────────────────────────────────────────
|
|
79
|
+
const expertObj = mods.expert;
|
|
80
|
+
if (expertObj) {
|
|
81
|
+
if (s.expertEnabled && !s.expertHasContent) {
|
|
82
|
+
findings.push(finding('expert', 'fail', 'Expert is ENABLED but has no name/knowledge/prompt — the final page shows a dead AI assistant chat.', `formlm-cli expert config --app ${appId} --name "..." --role "..." --kbText "..." --enable true`));
|
|
83
|
+
}
|
|
84
|
+
else if (!s.expertEnabled && s.expertHasContent) {
|
|
85
|
+
findings.push(finding('expert', 'warn', 'Expert is configured but DISABLED (enable=false) — it will not appear for respondents.', `formlm-cli expert set --app ${appId} --property enable --value true`));
|
|
86
|
+
}
|
|
87
|
+
else if (s.expertEnabled) {
|
|
88
|
+
findings.push(finding('expert', 'pass', `Expert enabled: ${expertObj.name || '(unnamed)'}.`));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// A report/final page embedding the expert widget while no enabled expert exists = dead entry point
|
|
92
|
+
if (mods.report) {
|
|
93
|
+
const refsExpert = JSON.stringify(mods.report).includes('train-expert');
|
|
94
|
+
if (refsExpert && !s.expertEnabled) {
|
|
95
|
+
findings.push(finding('expertRef', 'fail', 'A report widget of type train-expert exists but no enabled expert is configured — that entry point is a dead link.', `formlm-cli expert config --app ${appId} --name "..." --role "..." --kbText "..." --enable true`));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// ── styling ─────────────────────────────────────────────────
|
|
99
|
+
if (mods.connect) {
|
|
100
|
+
if (s.styled === false) {
|
|
101
|
+
findings.push(finding('styling', 'warn', 'App is not styled — it renders with the plain default look.', `formlm-cli connect style apply-all --app ${appId} --look "<scene + visual tone>"`));
|
|
102
|
+
}
|
|
103
|
+
else if (s.styled === true) {
|
|
104
|
+
findings.push(finding('styling', 'pass', 'Visual style applied.'));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// ── report / scoring drift ──────────────────────────────────
|
|
108
|
+
if (s.dimCount > 0 && s.reportPageCount === 0) {
|
|
109
|
+
findings.push(finding('report', 'fail', `${s.dimCount} dimensions exist but the report has 0 pages — respondents submit and receive nothing.`));
|
|
110
|
+
}
|
|
111
|
+
else if (s.dimCount === 0 && s.questionCount === 0 && s.reportPageCount > 0) {
|
|
112
|
+
findings.push(finding('report', 'warn', 'Report pages exist but nothing is scored (0 dimensions, 0 scored questions) — score-driven widgets will stay empty.'));
|
|
113
|
+
}
|
|
114
|
+
// ── certificate heuristics (name/type based → advisory) ─────
|
|
115
|
+
// A certificate page is expected for exam/learn (completion certificates) and for apps whose
|
|
116
|
+
// type/name says certificate; elsewhere it is usually an AI-attached boilerplate tail page.
|
|
117
|
+
const certExpected = /(^|[^a-z])(exam|learn|cert|diploma|credential|training|course)/i.test(`${appType} ${appName}`);
|
|
118
|
+
const certPages = s.reportPages.filter((p) => p.name && CERT_NAME_RE.test(String(p.name)));
|
|
119
|
+
if (certPages.length > 0 && !certExpected) {
|
|
120
|
+
findings.push(finding('certificate', 'warn', `Certificate-like page(s) present (${certPages.map((p) => `${p.id}:${p.name}`).join(', ')}) but the app type/name (${appType || appName || 'unnamed'}) does not indicate a certificate. Verify it was intended — AI generation sometimes attaches a boilerplate 结业证书 page to plain screenings/screeners.`, `formlm-cli report page remove --app ${appId} --id <pageId>`));
|
|
121
|
+
}
|
|
122
|
+
// ── language consistency (opt-in) ───────────────────────────
|
|
123
|
+
if (opts.expectLang) {
|
|
124
|
+
const expectCJK = langIsCJK(opts.expectLang);
|
|
125
|
+
const texts = [];
|
|
126
|
+
for (const f of asArray(mods.form)) {
|
|
127
|
+
if (f?.title)
|
|
128
|
+
texts.push({ where: `form ${f.id || f.key}`, text: String(f.title) });
|
|
129
|
+
if (f?.name)
|
|
130
|
+
texts.push({ where: `form ${f.id || f.key}.name`, text: String(f.name) });
|
|
131
|
+
}
|
|
132
|
+
for (const d of asArray(mods.scale)) {
|
|
133
|
+
if (d?.name)
|
|
134
|
+
texts.push({ where: `scale ${d.id}`, text: String(d.name) });
|
|
135
|
+
}
|
|
136
|
+
for (const p of s.reportPages) {
|
|
137
|
+
if (p.name)
|
|
138
|
+
texts.push({ where: `report page ${p.id}`, text: String(p.name) });
|
|
139
|
+
}
|
|
140
|
+
// Widget VALUES are omitted by the compact report query — fetch per page when asked
|
|
141
|
+
if (opts.deep && s.reportPageCount > 0) {
|
|
142
|
+
const lists = await Promise.all(s.reportPages.map((p) => p.id ? jsonExec(`assess report widget list --app ${appId} --page ${p.id} --json`) : Promise.resolve(null)));
|
|
143
|
+
lists.forEach((list, i) => {
|
|
144
|
+
if (!list || list.__error)
|
|
145
|
+
return;
|
|
146
|
+
for (const w of asArray(list)) {
|
|
147
|
+
const v = typeof w?.value === 'string' ? w.value : '';
|
|
148
|
+
if (v)
|
|
149
|
+
texts.push({ where: `report widget ${s.reportPages[i].id}/${w.id}`, text: v.replace(/<[^>]+>/g, ' ') });
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
const offenders = texts.filter(t => expectCJK ? !CJK_RE.test(t.text) : CJK_RE.test(t.text));
|
|
154
|
+
if (offenders.length > 0) {
|
|
155
|
+
const sample = offenders.slice(0, 8).map(o => `${o.where}="${o.text.slice(0, 40)}"`).join(', ');
|
|
156
|
+
findings.push(finding('language', 'fail', `${offenders.length} text(s) do not match --expect-lang ${opts.expectLang}${opts.deep ? ' (titles + widget values scanned)' : ' (titles/labels only; pass deep=true to include widget body text)'}: ${sample}${offenders.length > 8 ? ' …' : ''}`, 'fix with report widget set / field update, or regenerate the module with smart plan --lang ' + opts.expectLang));
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
findings.push(finding('language', 'pass', `All scanned texts match --expect-lang ${opts.expectLang} (${texts.length} strings${opts.deep ? ', incl. widget values' : ''}).`));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// ── share / access ──────────────────────────────────────────
|
|
163
|
+
const shareForm = mods.share && typeof mods.share === 'object' ? (mods.share.form ?? mods.share) : null;
|
|
164
|
+
const type = shareForm?.type ?? urls?.shareType ?? null;
|
|
165
|
+
const day = Number(shareForm?.day ?? urls?.shareDay ?? 0);
|
|
166
|
+
const perm = shareForm?.perm ?? urls?.sharePerm ?? '?';
|
|
167
|
+
const fillAbs = urls?.shareUrlAbsolute || absHttpsUrl(getBaseUrl(), urls?.shareUrl || '');
|
|
168
|
+
if (!type || type === 'no') {
|
|
169
|
+
findings.push(finding('share', 'fail', 'App is NOT published — respondents cannot reach any fill-in URL.', `formlm-cli share publish --app ${appId} --access visitor`));
|
|
170
|
+
}
|
|
171
|
+
else if (type === 'all' || type === 'owner') {
|
|
172
|
+
findings.push(finding('share', 'fail', `Published as type=${type}, which REQUIRES a logged-in FormLM account — anonymous visitors get the login page, not the form. Use visitor for "anyone can fill".`, `formlm-cli share publish --app ${appId} --access visitor`));
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
findings.push(finding('share', 'pass', `Published as type=${type}, perm=${perm}, ${day >= 3650000 ? 'permanent' : 'valid ' + day + ' day(s)'}.`));
|
|
176
|
+
}
|
|
177
|
+
if (day > 0 && day < 3650000) {
|
|
178
|
+
findings.push(finding('shareExpiry', 'warn', `Share link expires in ${day} day(s) (only 1..30 are finite server-side) — long-lived pages should re-publish with --days forever.`));
|
|
179
|
+
}
|
|
180
|
+
if (opts.probe !== false && fillAbs && type && type !== 'no') {
|
|
181
|
+
const probe = await probeUrl(fillAbs);
|
|
182
|
+
if (!probe.ok) {
|
|
183
|
+
findings.push(finding('reachability', 'fail', `Fill-in URL did not answer OK (HTTP ${probe.status || 'no response'}${probe.message ? ': ' + probe.message : ''}).`));
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
findings.push(finding('reachability', 'pass', `Fill-in URL answered HTTP ${probe.status} (200 alone does not prove anonymous access — read the share check).`));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const fails = findings.filter(f => f.level === 'fail');
|
|
190
|
+
const warns = findings.filter(f => f.level === 'warn');
|
|
191
|
+
return {
|
|
192
|
+
appId,
|
|
193
|
+
appName: appName || null,
|
|
194
|
+
appType: appType || null,
|
|
195
|
+
ok: fails.length === 0,
|
|
196
|
+
failCount: fails.length,
|
|
197
|
+
warnCount: warns.length,
|
|
198
|
+
summary: s,
|
|
199
|
+
findings,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|