@mandujs/cli 0.9.45 → 0.10.0
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/package.json +1 -1
- package/src/commands/build.ts +27 -19
- package/src/commands/check.ts +290 -238
- package/src/commands/dev.ts +486 -440
- package/src/commands/init.ts +128 -21
- package/src/commands/lock.ts +434 -0
- package/src/main.ts +445 -428
package/package.json
CHANGED
package/src/commands/build.ts
CHANGED
|
@@ -44,7 +44,27 @@ export async function build(options: BuildOptions = {}): Promise<boolean> {
|
|
|
44
44
|
return false;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
// 2.
|
|
47
|
+
// 2. Tailwind CSS 빌드 (Island 여부와 무관하게 먼저 실행)
|
|
48
|
+
const hasTailwind = await isTailwindProject(cwd);
|
|
49
|
+
const resolvedMinify = options.minify ?? buildConfig.minify ?? true;
|
|
50
|
+
|
|
51
|
+
if (hasTailwind) {
|
|
52
|
+
console.log(`\n🎨 Tailwind CSS v4 빌드 중...`);
|
|
53
|
+
const cssResult = await buildCSS({
|
|
54
|
+
rootDir: cwd,
|
|
55
|
+
minify: resolvedMinify,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (!cssResult.success) {
|
|
59
|
+
console.error(`\n❌ CSS 빌드 실패: ${cssResult.error}`);
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
console.log(` ✅ CSS 빌드 완료 (${cssResult.buildTime?.toFixed(0)}ms)`);
|
|
64
|
+
console.log(` 출력: ${cssResult.outputPath}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 3. Hydration이 필요한 라우트 확인
|
|
48
68
|
const hydratedRoutes = manifest.routes.filter(
|
|
49
69
|
(route) =>
|
|
50
70
|
route.kind === "page" &&
|
|
@@ -55,6 +75,12 @@ export async function build(options: BuildOptions = {}): Promise<boolean> {
|
|
|
55
75
|
if (hydratedRoutes.length === 0) {
|
|
56
76
|
console.log("\n📭 Hydration이 필요한 라우트가 없습니다.");
|
|
57
77
|
console.log(" (clientModule이 없거나 hydration.strategy: none)");
|
|
78
|
+
|
|
79
|
+
// CSS만 빌드된 경우도 성공으로 처리
|
|
80
|
+
if (hasTailwind) {
|
|
81
|
+
console.log(`\n✅ CSS 빌드 완료`);
|
|
82
|
+
console.log(` CSS: .mandu/client/globals.css`);
|
|
83
|
+
}
|
|
58
84
|
return true;
|
|
59
85
|
}
|
|
60
86
|
|
|
@@ -64,24 +90,6 @@ export async function build(options: BuildOptions = {}): Promise<boolean> {
|
|
|
64
90
|
console.log(` - ${route.id} (${hydration.strategy}, ${hydration.priority || "visible"})`);
|
|
65
91
|
}
|
|
66
92
|
|
|
67
|
-
// 3. Tailwind CSS 빌드 (감지 시에만)
|
|
68
|
-
const hasTailwind = await isTailwindProject(cwd);
|
|
69
|
-
if (hasTailwind) {
|
|
70
|
-
console.log(`\n🎨 Tailwind CSS v4 빌드 중...`);
|
|
71
|
-
const cssResult = await buildCSS({
|
|
72
|
-
rootDir: cwd,
|
|
73
|
-
minify: options.minify ?? true,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
if (!cssResult.success) {
|
|
77
|
-
console.error(`\n❌ CSS 빌드 실패: ${cssResult.error}`);
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
console.log(` ✅ CSS 빌드 완료 (${cssResult.buildTime?.toFixed(0)}ms)`);
|
|
82
|
-
console.log(` 출력: ${cssResult.outputPath}`);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
93
|
// 4. 번들 빌드
|
|
86
94
|
const startTime = performance.now();
|
|
87
95
|
const resolvedBuildOptions: BuildOptions = {
|
package/src/commands/check.ts
CHANGED
|
@@ -1,238 +1,290 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* mandu check - Workflow Check Command
|
|
3
|
-
*
|
|
4
|
-
* FS Routes + Architecture Guard + Legacy Guard 통합 검사
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
generateManifest,
|
|
9
|
-
scanRoutes,
|
|
10
|
-
checkDirectory,
|
|
11
|
-
printReport,
|
|
12
|
-
getPreset,
|
|
13
|
-
validateAndReport,
|
|
14
|
-
loadManifest,
|
|
15
|
-
runGuardCheck,
|
|
16
|
-
buildGuardReport,
|
|
17
|
-
printReportSummary,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
"client/
|
|
130
|
-
"
|
|
131
|
-
"
|
|
132
|
-
"
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
"
|
|
136
|
-
"client
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
"
|
|
140
|
-
"
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
"
|
|
144
|
-
"
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
"server/
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
"
|
|
151
|
-
"
|
|
152
|
-
"shared/
|
|
153
|
-
"shared/
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if (
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
1
|
+
/**
|
|
2
|
+
* mandu check - Workflow Check Command
|
|
3
|
+
*
|
|
4
|
+
* FS Routes + Architecture Guard + Legacy Guard 통합 검사
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
generateManifest,
|
|
9
|
+
scanRoutes,
|
|
10
|
+
checkDirectory,
|
|
11
|
+
printReport,
|
|
12
|
+
getPreset,
|
|
13
|
+
validateAndReport,
|
|
14
|
+
loadManifest,
|
|
15
|
+
runGuardCheck,
|
|
16
|
+
buildGuardReport,
|
|
17
|
+
printReportSummary,
|
|
18
|
+
guardConfig,
|
|
19
|
+
formatConfigGuardResult,
|
|
20
|
+
calculateHealthScore,
|
|
21
|
+
type GuardConfig,
|
|
22
|
+
type ConfigGuardResult,
|
|
23
|
+
} from "@mandujs/core";
|
|
24
|
+
import path from "path";
|
|
25
|
+
import { resolveFromCwd, isDirectory, pathExists } from "../util/fs";
|
|
26
|
+
import { resolveOutputFormat } from "../util/output";
|
|
27
|
+
|
|
28
|
+
export async function check(): Promise<boolean> {
|
|
29
|
+
const rootDir = resolveFromCwd(".");
|
|
30
|
+
const config = await validateAndReport(rootDir);
|
|
31
|
+
if (!config) return false;
|
|
32
|
+
|
|
33
|
+
const guardConfigFromFile = config.guard ?? {};
|
|
34
|
+
const preset = guardConfigFromFile.preset ?? "mandu";
|
|
35
|
+
const format = resolveOutputFormat();
|
|
36
|
+
const quiet = false;
|
|
37
|
+
const strictWarnings = process.env.CI === "true";
|
|
38
|
+
const enableFsRoutes = await isDirectory(path.resolve(rootDir, "app"));
|
|
39
|
+
const specPath = resolveFromCwd("spec/routes.manifest.json");
|
|
40
|
+
const hasSpec = await pathExists(specPath);
|
|
41
|
+
|
|
42
|
+
let success = true;
|
|
43
|
+
|
|
44
|
+
const log = (message: string) => {
|
|
45
|
+
if (format === "console" && !quiet) {
|
|
46
|
+
console.log(message);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const print = (message: string) => {
|
|
51
|
+
if (format === "console") {
|
|
52
|
+
console.log(message);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
if (format === "console") {
|
|
57
|
+
log("🥟 Mandu Check\n");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 1) FS Routes 검사
|
|
61
|
+
let routesSummary: { enabled: boolean; count: number; warnings: string[] } = {
|
|
62
|
+
enabled: false,
|
|
63
|
+
count: 0,
|
|
64
|
+
warnings: [],
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
if (enableFsRoutes) {
|
|
68
|
+
routesSummary.enabled = true;
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
if (format === "console") {
|
|
72
|
+
const result = await generateManifest(rootDir, {
|
|
73
|
+
scanner: config.fsRoutes,
|
|
74
|
+
outputPath: ".mandu/routes.manifest.json",
|
|
75
|
+
skipLegacy: true,
|
|
76
|
+
});
|
|
77
|
+
routesSummary.count = result.manifest.routes.length;
|
|
78
|
+
routesSummary.warnings = result.warnings;
|
|
79
|
+
|
|
80
|
+
if (quiet) {
|
|
81
|
+
print(`✅ FS Routes: ${routesSummary.count}개`);
|
|
82
|
+
} else {
|
|
83
|
+
log(`✅ FS Routes: ${routesSummary.count}개`);
|
|
84
|
+
}
|
|
85
|
+
if (routesSummary.warnings.length > 0) {
|
|
86
|
+
if (!quiet) {
|
|
87
|
+
log("⚠️ 경고:");
|
|
88
|
+
}
|
|
89
|
+
for (const warning of routesSummary.warnings) {
|
|
90
|
+
if (!quiet) {
|
|
91
|
+
log(` - ${warning}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (!quiet) {
|
|
96
|
+
log("");
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
const scan = await scanRoutes(rootDir, config.fsRoutes);
|
|
100
|
+
routesSummary.count = scan.routes.length;
|
|
101
|
+
routesSummary.warnings = scan.errors.map((e) => `${e.type}: ${e.message}`);
|
|
102
|
+
}
|
|
103
|
+
} catch (error) {
|
|
104
|
+
success = false;
|
|
105
|
+
routesSummary.warnings.push(
|
|
106
|
+
error instanceof Error ? error.message : String(error)
|
|
107
|
+
);
|
|
108
|
+
if (format === "console") {
|
|
109
|
+
console.error("❌ FS Routes 검사 실패:", error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
if (quiet) {
|
|
114
|
+
print("ℹ️ app/ 폴더 없음 - FS Routes 검사 스킵");
|
|
115
|
+
} else {
|
|
116
|
+
log("ℹ️ app/ 폴더 없음 - FS Routes 검사 스킵\n");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 2) Architecture Guard 검사
|
|
121
|
+
const archGuardConfig: GuardConfig = {
|
|
122
|
+
preset,
|
|
123
|
+
srcDir: guardConfigFromFile.srcDir ?? "src",
|
|
124
|
+
exclude: guardConfigFromFile.exclude,
|
|
125
|
+
fsRoutes: enableFsRoutes
|
|
126
|
+
? {
|
|
127
|
+
noPageToPage: true,
|
|
128
|
+
pageCanImport: [
|
|
129
|
+
"client/pages",
|
|
130
|
+
"client/widgets",
|
|
131
|
+
"client/features",
|
|
132
|
+
"client/entities",
|
|
133
|
+
"client/shared",
|
|
134
|
+
"shared/contracts",
|
|
135
|
+
"shared/types",
|
|
136
|
+
"shared/utils/client",
|
|
137
|
+
],
|
|
138
|
+
layoutCanImport: [
|
|
139
|
+
"client/app",
|
|
140
|
+
"client/widgets",
|
|
141
|
+
"client/shared",
|
|
142
|
+
"shared/contracts",
|
|
143
|
+
"shared/types",
|
|
144
|
+
"shared/utils/client",
|
|
145
|
+
],
|
|
146
|
+
routeCanImport: [
|
|
147
|
+
"server/api",
|
|
148
|
+
"server/application",
|
|
149
|
+
"server/domain",
|
|
150
|
+
"server/infra",
|
|
151
|
+
"server/core",
|
|
152
|
+
"shared/contracts",
|
|
153
|
+
"shared/schema",
|
|
154
|
+
"shared/types",
|
|
155
|
+
"shared/utils/client",
|
|
156
|
+
"shared/utils/server",
|
|
157
|
+
"shared/env",
|
|
158
|
+
],
|
|
159
|
+
}
|
|
160
|
+
: undefined,
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const report = await checkDirectory(archGuardConfig, rootDir);
|
|
164
|
+
const hasArchErrors = report.bySeverity.error > 0;
|
|
165
|
+
const hasArchWarnings = report.bySeverity.warn > 0;
|
|
166
|
+
if (hasArchErrors || (strictWarnings && hasArchWarnings)) {
|
|
167
|
+
success = false;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (format === "console") {
|
|
171
|
+
const presetDef = getPreset(preset);
|
|
172
|
+
if (quiet) {
|
|
173
|
+
print(`📊 Architecture: ${report.totalViolations}개 위반 (Errors: ${report.bySeverity.error})`);
|
|
174
|
+
} else {
|
|
175
|
+
printReport(report, presetDef.hierarchy);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// 3) Legacy Guard 검사 (spec 파일이 있을 때만)
|
|
180
|
+
let legacySummary: { enabled: boolean; passed: boolean; violations: number; errors?: string[] } = {
|
|
181
|
+
enabled: false,
|
|
182
|
+
passed: true,
|
|
183
|
+
violations: 0,
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
if (hasSpec) {
|
|
187
|
+
legacySummary.enabled = true;
|
|
188
|
+
|
|
189
|
+
const manifestResult = await loadManifest(specPath);
|
|
190
|
+
if (!manifestResult.success || !manifestResult.data) {
|
|
191
|
+
legacySummary.passed = false;
|
|
192
|
+
legacySummary.errors = manifestResult.errors ?? ["Spec 로드 실패"];
|
|
193
|
+
success = false;
|
|
194
|
+
|
|
195
|
+
if (format === "console") {
|
|
196
|
+
console.error("❌ Spec 로드 실패:");
|
|
197
|
+
manifestResult.errors?.forEach((e) => console.error(` - ${e}`));
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
const checkResult = await runGuardCheck(manifestResult.data, rootDir);
|
|
201
|
+
legacySummary.passed = checkResult.passed;
|
|
202
|
+
legacySummary.violations = checkResult.violations.length;
|
|
203
|
+
if (strictWarnings && checkResult.violations.length > 0) {
|
|
204
|
+
success = false;
|
|
205
|
+
} else {
|
|
206
|
+
success = success && checkResult.passed;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (format === "console") {
|
|
210
|
+
const legacyReport = buildGuardReport(checkResult);
|
|
211
|
+
if (quiet) {
|
|
212
|
+
print(`📊 Legacy Guard: ${legacySummary.violations}개 위반`);
|
|
213
|
+
} else {
|
|
214
|
+
printReportSummary(legacyReport);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
if (quiet) {
|
|
220
|
+
print("ℹ️ spec/routes.manifest.json 없음 - 레거시 Guard 스킵");
|
|
221
|
+
} else {
|
|
222
|
+
log("ℹ️ spec/routes.manifest.json 없음 - 레거시 Guard 스킵");
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// 4) Config Integrity 검사 (Lockfile)
|
|
227
|
+
const configGuardResult = await guardConfig(rootDir, config);
|
|
228
|
+
|
|
229
|
+
if (configGuardResult.action === "error" || configGuardResult.action === "block") {
|
|
230
|
+
success = false;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (format === "console") {
|
|
234
|
+
if (!quiet) {
|
|
235
|
+
log("");
|
|
236
|
+
}
|
|
237
|
+
if (quiet) {
|
|
238
|
+
if (configGuardResult.lockfileValid) {
|
|
239
|
+
print(`✅ Config: 무결성 확인됨 (${configGuardResult.currentHash?.slice(0, 8) ?? "N/A"})`);
|
|
240
|
+
} else if (!configGuardResult.lockfileExists) {
|
|
241
|
+
print(`💡 Config: Lockfile 없음`);
|
|
242
|
+
} else {
|
|
243
|
+
print(`❌ Config: 무결성 실패`);
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
246
|
+
log(formatConfigGuardResult(configGuardResult));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// 5) 통합 헬스 점수
|
|
251
|
+
const healthScore = calculateHealthScore(
|
|
252
|
+
report.totalViolations,
|
|
253
|
+
report.bySeverity.error,
|
|
254
|
+
configGuardResult
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
if (format === "console" && !quiet) {
|
|
258
|
+
log("");
|
|
259
|
+
log("═══════════════════════════════════════");
|
|
260
|
+
log(`🏥 Health Score: ${healthScore}/100`);
|
|
261
|
+
log("═══════════════════════════════════════");
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (format !== "console") {
|
|
265
|
+
const summary = {
|
|
266
|
+
ok: success,
|
|
267
|
+
healthScore,
|
|
268
|
+
routes: routesSummary,
|
|
269
|
+
architecture: {
|
|
270
|
+
totalViolations: report.totalViolations,
|
|
271
|
+
bySeverity: report.bySeverity,
|
|
272
|
+
byType: report.byType,
|
|
273
|
+
report,
|
|
274
|
+
},
|
|
275
|
+
config: {
|
|
276
|
+
valid: configGuardResult.lockfileValid,
|
|
277
|
+
exists: configGuardResult.lockfileExists,
|
|
278
|
+
action: configGuardResult.action,
|
|
279
|
+
currentHash: configGuardResult.currentHash,
|
|
280
|
+
lockedHash: configGuardResult.lockedHash,
|
|
281
|
+
errors: configGuardResult.errors,
|
|
282
|
+
warnings: configGuardResult.warnings,
|
|
283
|
+
},
|
|
284
|
+
legacy: legacySummary,
|
|
285
|
+
};
|
|
286
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return success;
|
|
290
|
+
}
|