@polymorphism-tech/morph-spec 3.0.0 → 3.0.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/CLAUDE.md +75 -371
- package/LICENSE +72 -72
- package/bin/detect-agents.js +225 -225
- package/bin/render-template.js +302 -302
- package/bin/semantic-detect-agents.js +246 -246
- package/bin/validate-agents-skills.js +251 -251
- package/bin/validate-agents.js +69 -69
- package/bin/validate-phase.js +263 -263
- package/content/.azure/README.md +293 -293
- package/content/.azure/docs/azure-devops-setup.md +454 -454
- package/content/.azure/docs/branch-strategy.md +398 -398
- package/content/.azure/docs/local-development.md +515 -515
- package/content/.azure/pipelines/pipeline-variables.yml +34 -34
- package/content/.azure/pipelines/prod-pipeline.yml +319 -319
- package/content/.azure/pipelines/staging-pipeline.yml +234 -234
- package/content/.azure/pipelines/templates/build-dotnet.yml +75 -75
- package/content/.azure/pipelines/templates/deploy-app-service.yml +94 -94
- package/content/.azure/pipelines/templates/deploy-container-app.yml +120 -120
- package/content/.azure/pipelines/templates/infra-deploy.yml +90 -90
- package/content/.claude/commands/morph-archive.md +79 -79
- package/content/.claude/commands/morph-deploy.md +529 -529
- package/content/.claude/commands/morph-infra.md +209 -209
- package/content/.claude/commands/morph-preflight.md +227 -227
- package/content/.claude/commands/morph-troubleshoot.md +122 -122
- package/content/.claude/settings.local.json +15 -15
- package/content/.claude/skills/{specialists → level-2-domains/architecture}/prompt-engineer.md +189 -189
- package/content/.claude/skills/{specialists → level-2-domains/architecture}/seo-growth-hacker.md +320 -320
- package/content/.claude/skills/{infra → level-2-domains/infrastructure}/azure-deploy-specialist.md +699 -699
- package/content/.morph/.morphversion +5 -5
- package/content/.morph/archive/.gitkeep +25 -25
- package/content/.morph/config/agents.json +7 -5
- package/content/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +392 -392
- package/content/.morph/examples/api-nextjs/README.md +241 -241
- package/content/.morph/examples/api-nextjs/contracts.ts +307 -307
- package/content/.morph/examples/api-nextjs/spec.md +399 -399
- package/content/.morph/examples/api-nextjs/tasks.md +168 -168
- package/content/.morph/examples/micro-saas/README.md +125 -125
- package/content/.morph/examples/micro-saas/contracts.cs +358 -358
- package/content/.morph/examples/micro-saas/decisions.md +246 -246
- package/content/.morph/examples/micro-saas/spec.md +236 -236
- package/content/.morph/examples/micro-saas/tasks.md +150 -150
- package/content/.morph/examples/multi-agent/README.md +309 -309
- package/content/.morph/examples/multi-agent/contracts.cs +433 -433
- package/content/.morph/examples/multi-agent/spec.md +479 -479
- package/content/.morph/examples/multi-agent/tasks.md +185 -185
- package/content/.morph/examples/state-v3.json +188 -188
- package/content/.morph/features/.gitkeep +25 -25
- package/content/.morph/hooks/pre-commit-all.sh +48 -48
- package/content/.morph/hooks/pre-commit-specs.sh +49 -49
- package/content/.morph/hooks/pre-commit-tests.sh +60 -60
- package/content/.morph/project.md +160 -160
- package/content/.morph/schemas/agent.schema.json +296 -296
- package/content/.morph/specs/.gitkeep +20 -20
- package/content/.morph/standards/coding.md +377 -377
- package/content/.morph/standards/fluent-ui-setup.md +590 -590
- package/content/.morph/standards/migration-guide.md +514 -514
- package/content/.morph/standards/passkeys-auth.md +423 -423
- package/content/.morph/standards/vector-search-rag.md +536 -536
- package/content/.morph/state.json +17 -17
- package/content/.morph/templates/FluentDesignTheme.cs +149 -149
- package/content/.morph/templates/MudTheme.cs +281 -281
- package/content/.morph/templates/component.razor +239 -239
- package/content/.morph/templates/contracts.cs +217 -217
- package/content/.morph/templates/design-system.css +226 -226
- package/content/.morph/templates/infra/.dockerignore.example +89 -89
- package/content/.morph/templates/infra/Dockerfile.example +82 -82
- package/content/.morph/templates/infra/README.md +286 -286
- package/content/.morph/templates/infra/app-insights.bicep +63 -63
- package/content/.morph/templates/infra/app-service.bicep +164 -164
- package/content/.morph/templates/infra/azure-pipelines-deploy.yml +480 -480
- package/content/.morph/templates/infra/container-app-env.bicep +49 -49
- package/content/.morph/templates/infra/container-app.bicep +156 -156
- package/content/.morph/templates/infra/deploy-checklist.md +426 -426
- package/content/.morph/templates/infra/deploy.ps1 +229 -229
- package/content/.morph/templates/infra/deploy.sh +208 -208
- package/content/.morph/templates/infra/key-vault.bicep +91 -91
- package/content/.morph/templates/infra/main.bicep +189 -189
- package/content/.morph/templates/infra/parameters.dev.json +29 -29
- package/content/.morph/templates/infra/parameters.prod.json +29 -29
- package/content/.morph/templates/infra/parameters.staging.json +29 -29
- package/content/.morph/templates/infra/sql-database.bicep +103 -103
- package/content/.morph/templates/infra/storage.bicep +106 -106
- package/content/.morph/templates/integrations/asaas-client.cs +387 -387
- package/content/.morph/templates/integrations/asaas-webhook.cs +351 -351
- package/content/.morph/templates/integrations/azure-identity-config.cs +288 -288
- package/content/.morph/templates/integrations/clerk-config.cs +258 -258
- package/content/.morph/templates/job.cs +171 -171
- package/content/.morph/templates/migration.cs +83 -83
- package/content/.morph/templates/repository.cs +141 -141
- package/content/.morph/templates/saas/subscription.cs +347 -347
- package/content/.morph/templates/saas/tenant.cs +338 -338
- package/content/.morph/templates/service.cs +139 -139
- package/content/.morph/templates/sprint-status.yaml +68 -68
- package/content/.morph/templates/story.md +143 -143
- package/content/.morph/templates/test.cs +239 -239
- package/content/.morph/templates/ui-design-system.md +286 -286
- package/content/.morph/templates/ui-flows.md +336 -336
- package/content/.morph/templates/ui-mockups.md +133 -133
- package/content/.morph/test-infra/example.bicep +59 -59
- package/content/README.md +79 -79
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +977 -977
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1048 -1048
- package/docs/api/scripts/collapse.js +38 -38
- package/docs/api/scripts/commonNav.js +28 -28
- package/docs/api/scripts/linenumber.js +25 -25
- package/docs/api/scripts/nav.js +12 -12
- package/docs/api/scripts/polyfill.js +3 -3
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -202
- package/docs/api/scripts/prettify/lang-css.js +2 -2
- package/docs/api/scripts/prettify/prettify.js +28 -28
- package/docs/api/scripts/search.js +98 -98
- package/docs/api/styles/jsdoc.css +776 -776
- package/docs/api/styles/prettify.css +80 -80
- package/docs/examples.md +328 -328
- package/docs/templates.md +418 -418
- package/package.json +1 -2
- package/scripts/postinstall.js +132 -132
- package/scripts/reorganize-skills.cjs +175 -0
- package/scripts/validate-agents-structure.cjs +52 -0
- package/scripts/validate-skills.cjs +180 -0
- package/src/commands/analyze-blazor-concurrency.js +193 -193
- package/src/commands/create-story.js +351 -351
- package/src/commands/deploy.js +780 -780
- package/src/commands/detect-agents.js +9 -0
- package/src/commands/detect.js +104 -104
- package/src/commands/generate.js +149 -149
- package/src/commands/lint-fluent.js +352 -352
- package/src/commands/rollback-phase.js +185 -185
- package/src/commands/session-summary.js +291 -291
- package/src/commands/shard-spec.js +224 -224
- package/src/commands/sprint-status.js +250 -250
- package/src/commands/state.js +334 -333
- package/src/commands/sync.js +167 -167
- package/src/commands/troubleshoot.js +222 -222
- package/src/commands/update.js +13 -1
- package/src/commands/validate-blazor-state.js +210 -210
- package/src/commands/validate-blazor.js +156 -156
- package/src/commands/validate-css.js +84 -84
- package/src/commands/validate-phase.js +221 -221
- package/src/lib/blazor-concurrency-analyzer.js +288 -288
- package/src/lib/blazor-state-validator.js +291 -291
- package/src/lib/blazor-validator.js +374 -374
- package/src/lib/css-validator.js +352 -352
- package/src/lib/design-system-generator.js +298 -298
- package/{detectors → src/lib/detectors}/config-detector.js +223 -223
- package/{detectors → src/lib/detectors}/conversation-analyzer.js +163 -163
- package/{detectors → src/lib/detectors}/index.js +84 -84
- package/{detectors → src/lib/detectors}/standards-generator.js +275 -275
- package/src/lib/learning-system.js +520 -520
- package/src/lib/mockup-generator.js +366 -366
- package/src/lib/state-manager.js +21 -4
- package/src/lib/troubleshoot-grep.js +194 -194
- package/src/lib/troubleshoot-index.js +144 -144
- package/src/lib/ui-detector.js +350 -350
- package/src/lib/validators/architecture-validator.js +387 -387
- package/src/lib/validators/package-validator.js +360 -360
- package/src/lib/validators/ui-contrast-validator.js +422 -422
- package/src/utils/logger.js +32 -32
- package/src/utils/version-checker.js +175 -175
- /package/{detectors → src/lib/detectors}/structure-detector.js +0 -0
|
@@ -1,210 +1,210 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* validate-blazor-state command
|
|
3
|
-
*
|
|
4
|
-
* Validates Blazor Server session state patterns.
|
|
5
|
-
* Ensures proper Persist + Reload pattern implementation.
|
|
6
|
-
*
|
|
7
|
-
* Usage:
|
|
8
|
-
* morph-spec validate-blazor-state [path]
|
|
9
|
-
* morph-spec validate-blazor-state src/ --verbose
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { glob } from 'glob';
|
|
13
|
-
import { readFileSync, existsSync, statSync } from 'fs';
|
|
14
|
-
import { join, resolve } from 'path';
|
|
15
|
-
import chalk from 'chalk';
|
|
16
|
-
import ora from 'ora';
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
validateBlazorState,
|
|
20
|
-
countIssues,
|
|
21
|
-
} from '../lib/blazor-state-validator.js';
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Main command handler for validate-blazor-state.
|
|
25
|
-
*
|
|
26
|
-
* @param {string} [targetPath] - Path to validate (file or directory)
|
|
27
|
-
* @param {Object} options - Command options
|
|
28
|
-
* @param {boolean} [options.verbose] - Show detailed output
|
|
29
|
-
*/
|
|
30
|
-
export async function validateBlazorStateCommand(targetPath, options = {}) {
|
|
31
|
-
const { verbose = false } = options;
|
|
32
|
-
|
|
33
|
-
console.log('');
|
|
34
|
-
console.log(
|
|
35
|
-
chalk.cyan('\uD83D\uDD0D Validando padroes de SessionState em Blazor Server...')
|
|
36
|
-
);
|
|
37
|
-
console.log('');
|
|
38
|
-
|
|
39
|
-
// Determine target path
|
|
40
|
-
const basePath = targetPath ? resolve(targetPath) : process.cwd();
|
|
41
|
-
|
|
42
|
-
if (!existsSync(basePath)) {
|
|
43
|
-
console.log(chalk.red(`\u274C Path not found: ${basePath}`));
|
|
44
|
-
process.exit(1);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const spinner = ora('Scanning for C# and Razor files...').start();
|
|
48
|
-
|
|
49
|
-
let files = [];
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
const stats = statSync(basePath);
|
|
53
|
-
|
|
54
|
-
if (stats.isFile()) {
|
|
55
|
-
if (basePath.endsWith('.cs') || basePath.endsWith('.razor')) {
|
|
56
|
-
files = [basePath];
|
|
57
|
-
} else {
|
|
58
|
-
spinner.fail('File must be .cs or .razor');
|
|
59
|
-
process.exit(1);
|
|
60
|
-
}
|
|
61
|
-
} else {
|
|
62
|
-
// Find all relevant files
|
|
63
|
-
const pattern = join(basePath, '**/*.{cs,razor}');
|
|
64
|
-
files = await glob(pattern, {
|
|
65
|
-
ignore: [
|
|
66
|
-
'**/node_modules/**',
|
|
67
|
-
'**/bin/**',
|
|
68
|
-
'**/obj/**',
|
|
69
|
-
'**/Migrations/**',
|
|
70
|
-
],
|
|
71
|
-
windowsPathsNoEscape: true,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
spinner.succeed(`Found ${files.length} file(s)`);
|
|
76
|
-
} catch (error) {
|
|
77
|
-
spinner.fail(`Error scanning files: ${error.message}`);
|
|
78
|
-
process.exit(1);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (files.length === 0) {
|
|
82
|
-
console.log(chalk.yellow('\n\u26A0\uFE0F No files found to validate'));
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Validate each file
|
|
87
|
-
const allIssues = [];
|
|
88
|
-
const fileResults = [];
|
|
89
|
-
|
|
90
|
-
for (const file of files) {
|
|
91
|
-
try {
|
|
92
|
-
const content = readFileSync(file, 'utf-8');
|
|
93
|
-
const issues = validateBlazorState(content, file);
|
|
94
|
-
|
|
95
|
-
if (issues.length > 0) {
|
|
96
|
-
allIssues.push(...issues);
|
|
97
|
-
fileResults.push({ file, issues });
|
|
98
|
-
}
|
|
99
|
-
} catch (error) {
|
|
100
|
-
if (verbose) {
|
|
101
|
-
console.log(chalk.red(`\u274C Error reading ${file}: ${error.message}`));
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Output results
|
|
107
|
-
console.log('');
|
|
108
|
-
|
|
109
|
-
if (allIssues.length === 0) {
|
|
110
|
-
console.log(
|
|
111
|
-
chalk.green('\u2705 Padroes de SessionState validados com sucesso!')
|
|
112
|
-
);
|
|
113
|
-
console.log(
|
|
114
|
-
chalk.gray(
|
|
115
|
-
' Dica: Certifique-se de sempre verificar IsLoaded em OnInitializedAsync.'
|
|
116
|
-
)
|
|
117
|
-
);
|
|
118
|
-
console.log('');
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Display issues
|
|
123
|
-
if (verbose) {
|
|
124
|
-
fileResults.forEach(({ file, issues }) => {
|
|
125
|
-
console.log(chalk.white.bold(`\n${file}`));
|
|
126
|
-
console.log(chalk.gray('-'.repeat(60)));
|
|
127
|
-
|
|
128
|
-
issues.forEach((issue) => {
|
|
129
|
-
const icon =
|
|
130
|
-
issue.type === 'error'
|
|
131
|
-
? '\u274C'
|
|
132
|
-
: issue.type === 'warning'
|
|
133
|
-
? '\u26A0\uFE0F'
|
|
134
|
-
: '\u2139\uFE0F';
|
|
135
|
-
|
|
136
|
-
const color =
|
|
137
|
-
issue.type === 'error'
|
|
138
|
-
? chalk.red
|
|
139
|
-
: issue.type === 'warning'
|
|
140
|
-
? chalk.yellow
|
|
141
|
-
: chalk.blue;
|
|
142
|
-
|
|
143
|
-
console.log(`${icon} ${color(issue.message)}`);
|
|
144
|
-
if (issue.suggestion) {
|
|
145
|
-
console.log(chalk.gray(` \u2192 ${issue.suggestion}`));
|
|
146
|
-
}
|
|
147
|
-
if (issue.line) {
|
|
148
|
-
console.log(chalk.dim(` Linha: ${issue.line}`));
|
|
149
|
-
}
|
|
150
|
-
console.log('');
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
} else {
|
|
154
|
-
allIssues.forEach((issue) => {
|
|
155
|
-
const icon =
|
|
156
|
-
issue.type === 'error'
|
|
157
|
-
? '\u274C'
|
|
158
|
-
: issue.type === 'warning'
|
|
159
|
-
? '\u26A0\uFE0F'
|
|
160
|
-
: '\u2139\uFE0F';
|
|
161
|
-
|
|
162
|
-
const color =
|
|
163
|
-
issue.type === 'error'
|
|
164
|
-
? chalk.red
|
|
165
|
-
: issue.type === 'warning'
|
|
166
|
-
? chalk.yellow
|
|
167
|
-
: chalk.blue;
|
|
168
|
-
|
|
169
|
-
console.log(`${icon} ${color(issue.message)}`);
|
|
170
|
-
if (issue.suggestion) {
|
|
171
|
-
console.log(chalk.gray(` \u2192 ${issue.suggestion}`));
|
|
172
|
-
}
|
|
173
|
-
console.log(chalk.dim(` ${issue.file}`));
|
|
174
|
-
console.log('');
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Summary
|
|
179
|
-
const { errors, warnings, infos } = countIssues(allIssues);
|
|
180
|
-
const summaryColor = errors > 0 ? chalk.red : chalk.yellow;
|
|
181
|
-
|
|
182
|
-
console.log(chalk.gray('-'.repeat(60)));
|
|
183
|
-
console.log(
|
|
184
|
-
summaryColor(
|
|
185
|
-
`\n${files.length} arquivo(s) validado(s) | ${errors} erro(s) | ${warnings} warning(s) | ${infos} info(s)\n`
|
|
186
|
-
)
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
// Checklist reminder
|
|
190
|
-
console.log(chalk.cyan('\uD83D\uDCCB Checklist SessionState:'));
|
|
191
|
-
console.log(chalk.gray(' [ ] SessionState tem LoadFrom(entity)?'));
|
|
192
|
-
console.log(chalk.gray(' [ ] SessionState tem propriedade IsLoaded?'));
|
|
193
|
-
console.log(chalk.gray(' [ ] Paginas verificam IsLoaded em OnInitializedAsync?'));
|
|
194
|
-
console.log(chalk.gray(' [ ] SessionMiddleware configurado em Program.cs?'));
|
|
195
|
-
console.log(chalk.gray(' [ ] IHttpContextAccessor registrado?'));
|
|
196
|
-
console.log('');
|
|
197
|
-
|
|
198
|
-
// Recommendation
|
|
199
|
-
if (errors > 0) {
|
|
200
|
-
console.log(
|
|
201
|
-
chalk.cyan(
|
|
202
|
-
'\uD83D\uDCD6 Consulte: framework/standards/blazor-state.md para o padrao completo'
|
|
203
|
-
)
|
|
204
|
-
);
|
|
205
|
-
console.log('');
|
|
206
|
-
process.exit(1);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
export default validateBlazorStateCommand;
|
|
1
|
+
/**
|
|
2
|
+
* validate-blazor-state command
|
|
3
|
+
*
|
|
4
|
+
* Validates Blazor Server session state patterns.
|
|
5
|
+
* Ensures proper Persist + Reload pattern implementation.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* morph-spec validate-blazor-state [path]
|
|
9
|
+
* morph-spec validate-blazor-state src/ --verbose
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { glob } from 'glob';
|
|
13
|
+
import { readFileSync, existsSync, statSync } from 'fs';
|
|
14
|
+
import { join, resolve } from 'path';
|
|
15
|
+
import chalk from 'chalk';
|
|
16
|
+
import ora from 'ora';
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
validateBlazorState,
|
|
20
|
+
countIssues,
|
|
21
|
+
} from '../lib/blazor-state-validator.js';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Main command handler for validate-blazor-state.
|
|
25
|
+
*
|
|
26
|
+
* @param {string} [targetPath] - Path to validate (file or directory)
|
|
27
|
+
* @param {Object} options - Command options
|
|
28
|
+
* @param {boolean} [options.verbose] - Show detailed output
|
|
29
|
+
*/
|
|
30
|
+
export async function validateBlazorStateCommand(targetPath, options = {}) {
|
|
31
|
+
const { verbose = false } = options;
|
|
32
|
+
|
|
33
|
+
console.log('');
|
|
34
|
+
console.log(
|
|
35
|
+
chalk.cyan('\uD83D\uDD0D Validando padroes de SessionState em Blazor Server...')
|
|
36
|
+
);
|
|
37
|
+
console.log('');
|
|
38
|
+
|
|
39
|
+
// Determine target path
|
|
40
|
+
const basePath = targetPath ? resolve(targetPath) : process.cwd();
|
|
41
|
+
|
|
42
|
+
if (!existsSync(basePath)) {
|
|
43
|
+
console.log(chalk.red(`\u274C Path not found: ${basePath}`));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const spinner = ora('Scanning for C# and Razor files...').start();
|
|
48
|
+
|
|
49
|
+
let files = [];
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const stats = statSync(basePath);
|
|
53
|
+
|
|
54
|
+
if (stats.isFile()) {
|
|
55
|
+
if (basePath.endsWith('.cs') || basePath.endsWith('.razor')) {
|
|
56
|
+
files = [basePath];
|
|
57
|
+
} else {
|
|
58
|
+
spinner.fail('File must be .cs or .razor');
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
// Find all relevant files
|
|
63
|
+
const pattern = join(basePath, '**/*.{cs,razor}');
|
|
64
|
+
files = await glob(pattern, {
|
|
65
|
+
ignore: [
|
|
66
|
+
'**/node_modules/**',
|
|
67
|
+
'**/bin/**',
|
|
68
|
+
'**/obj/**',
|
|
69
|
+
'**/Migrations/**',
|
|
70
|
+
],
|
|
71
|
+
windowsPathsNoEscape: true,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
spinner.succeed(`Found ${files.length} file(s)`);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
spinner.fail(`Error scanning files: ${error.message}`);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (files.length === 0) {
|
|
82
|
+
console.log(chalk.yellow('\n\u26A0\uFE0F No files found to validate'));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Validate each file
|
|
87
|
+
const allIssues = [];
|
|
88
|
+
const fileResults = [];
|
|
89
|
+
|
|
90
|
+
for (const file of files) {
|
|
91
|
+
try {
|
|
92
|
+
const content = readFileSync(file, 'utf-8');
|
|
93
|
+
const issues = validateBlazorState(content, file);
|
|
94
|
+
|
|
95
|
+
if (issues.length > 0) {
|
|
96
|
+
allIssues.push(...issues);
|
|
97
|
+
fileResults.push({ file, issues });
|
|
98
|
+
}
|
|
99
|
+
} catch (error) {
|
|
100
|
+
if (verbose) {
|
|
101
|
+
console.log(chalk.red(`\u274C Error reading ${file}: ${error.message}`));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Output results
|
|
107
|
+
console.log('');
|
|
108
|
+
|
|
109
|
+
if (allIssues.length === 0) {
|
|
110
|
+
console.log(
|
|
111
|
+
chalk.green('\u2705 Padroes de SessionState validados com sucesso!')
|
|
112
|
+
);
|
|
113
|
+
console.log(
|
|
114
|
+
chalk.gray(
|
|
115
|
+
' Dica: Certifique-se de sempre verificar IsLoaded em OnInitializedAsync.'
|
|
116
|
+
)
|
|
117
|
+
);
|
|
118
|
+
console.log('');
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Display issues
|
|
123
|
+
if (verbose) {
|
|
124
|
+
fileResults.forEach(({ file, issues }) => {
|
|
125
|
+
console.log(chalk.white.bold(`\n${file}`));
|
|
126
|
+
console.log(chalk.gray('-'.repeat(60)));
|
|
127
|
+
|
|
128
|
+
issues.forEach((issue) => {
|
|
129
|
+
const icon =
|
|
130
|
+
issue.type === 'error'
|
|
131
|
+
? '\u274C'
|
|
132
|
+
: issue.type === 'warning'
|
|
133
|
+
? '\u26A0\uFE0F'
|
|
134
|
+
: '\u2139\uFE0F';
|
|
135
|
+
|
|
136
|
+
const color =
|
|
137
|
+
issue.type === 'error'
|
|
138
|
+
? chalk.red
|
|
139
|
+
: issue.type === 'warning'
|
|
140
|
+
? chalk.yellow
|
|
141
|
+
: chalk.blue;
|
|
142
|
+
|
|
143
|
+
console.log(`${icon} ${color(issue.message)}`);
|
|
144
|
+
if (issue.suggestion) {
|
|
145
|
+
console.log(chalk.gray(` \u2192 ${issue.suggestion}`));
|
|
146
|
+
}
|
|
147
|
+
if (issue.line) {
|
|
148
|
+
console.log(chalk.dim(` Linha: ${issue.line}`));
|
|
149
|
+
}
|
|
150
|
+
console.log('');
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
} else {
|
|
154
|
+
allIssues.forEach((issue) => {
|
|
155
|
+
const icon =
|
|
156
|
+
issue.type === 'error'
|
|
157
|
+
? '\u274C'
|
|
158
|
+
: issue.type === 'warning'
|
|
159
|
+
? '\u26A0\uFE0F'
|
|
160
|
+
: '\u2139\uFE0F';
|
|
161
|
+
|
|
162
|
+
const color =
|
|
163
|
+
issue.type === 'error'
|
|
164
|
+
? chalk.red
|
|
165
|
+
: issue.type === 'warning'
|
|
166
|
+
? chalk.yellow
|
|
167
|
+
: chalk.blue;
|
|
168
|
+
|
|
169
|
+
console.log(`${icon} ${color(issue.message)}`);
|
|
170
|
+
if (issue.suggestion) {
|
|
171
|
+
console.log(chalk.gray(` \u2192 ${issue.suggestion}`));
|
|
172
|
+
}
|
|
173
|
+
console.log(chalk.dim(` ${issue.file}`));
|
|
174
|
+
console.log('');
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Summary
|
|
179
|
+
const { errors, warnings, infos } = countIssues(allIssues);
|
|
180
|
+
const summaryColor = errors > 0 ? chalk.red : chalk.yellow;
|
|
181
|
+
|
|
182
|
+
console.log(chalk.gray('-'.repeat(60)));
|
|
183
|
+
console.log(
|
|
184
|
+
summaryColor(
|
|
185
|
+
`\n${files.length} arquivo(s) validado(s) | ${errors} erro(s) | ${warnings} warning(s) | ${infos} info(s)\n`
|
|
186
|
+
)
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
// Checklist reminder
|
|
190
|
+
console.log(chalk.cyan('\uD83D\uDCCB Checklist SessionState:'));
|
|
191
|
+
console.log(chalk.gray(' [ ] SessionState tem LoadFrom(entity)?'));
|
|
192
|
+
console.log(chalk.gray(' [ ] SessionState tem propriedade IsLoaded?'));
|
|
193
|
+
console.log(chalk.gray(' [ ] Paginas verificam IsLoaded em OnInitializedAsync?'));
|
|
194
|
+
console.log(chalk.gray(' [ ] SessionMiddleware configurado em Program.cs?'));
|
|
195
|
+
console.log(chalk.gray(' [ ] IHttpContextAccessor registrado?'));
|
|
196
|
+
console.log('');
|
|
197
|
+
|
|
198
|
+
// Recommendation
|
|
199
|
+
if (errors > 0) {
|
|
200
|
+
console.log(
|
|
201
|
+
chalk.cyan(
|
|
202
|
+
'\uD83D\uDCD6 Consulte: framework/standards/blazor-state.md para o padrao completo'
|
|
203
|
+
)
|
|
204
|
+
);
|
|
205
|
+
console.log('');
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export default validateBlazorStateCommand;
|