create-qa-architect 5.0.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/.editorconfig +12 -0
- package/.github/CLAUDE_MD_AUTOMATION.md +248 -0
- package/.github/PROGRESSIVE_QUALITY_IMPLEMENTATION.md +408 -0
- package/.github/PROGRESSIVE_QUALITY_PROPOSAL.md +443 -0
- package/.github/RELEASE_CHECKLIST.md +100 -0
- package/.github/dependabot.yml +50 -0
- package/.github/git-sync.sh +48 -0
- package/.github/workflows/claude-md-validation.yml +82 -0
- package/.github/workflows/nightly-gitleaks-verification.yml +176 -0
- package/.github/workflows/pnpm-ci.yml.example +53 -0
- package/.github/workflows/python-ci.yml.example +69 -0
- package/.github/workflows/quality-legacy.yml.backup +165 -0
- package/.github/workflows/quality-progressive.yml.example +291 -0
- package/.github/workflows/quality.yml +436 -0
- package/.github/workflows/release.yml +53 -0
- package/.nvmrc +1 -0
- package/.prettierignore +14 -0
- package/.prettierrc +9 -0
- package/.stylelintrc.json +5 -0
- package/README.md +212 -0
- package/config/.lighthouserc.js +45 -0
- package/config/.pre-commit-config.yaml +66 -0
- package/config/constants.js +128 -0
- package/config/defaults.js +124 -0
- package/config/pyproject.toml +124 -0
- package/config/quality-config.schema.json +97 -0
- package/config/quality-python.yml +89 -0
- package/config/requirements-dev.txt +15 -0
- package/create-saas-monetization.js +1465 -0
- package/eslint.config.cjs +117 -0
- package/eslint.config.ts.cjs +99 -0
- package/legal/README.md +106 -0
- package/legal/copyright.md +76 -0
- package/legal/disclaimer.md +146 -0
- package/legal/privacy-policy.html +324 -0
- package/legal/privacy-policy.md +196 -0
- package/legal/terms-of-service.md +224 -0
- package/lib/billing-dashboard.html +645 -0
- package/lib/config-validator.js +163 -0
- package/lib/dependency-monitoring-basic.js +185 -0
- package/lib/dependency-monitoring-premium.js +1490 -0
- package/lib/error-reporter.js +444 -0
- package/lib/interactive/prompt.js +128 -0
- package/lib/interactive/questions.js +146 -0
- package/lib/license-validator.js +403 -0
- package/lib/licensing.js +989 -0
- package/lib/package-utils.js +187 -0
- package/lib/project-maturity.js +516 -0
- package/lib/security-enhancements.js +340 -0
- package/lib/setup-enhancements.js +317 -0
- package/lib/smart-strategy-generator.js +344 -0
- package/lib/telemetry.js +323 -0
- package/lib/template-loader.js +252 -0
- package/lib/typescript-config-generator.js +210 -0
- package/lib/ui-helpers.js +74 -0
- package/lib/validation/base-validator.js +174 -0
- package/lib/validation/cache-manager.js +158 -0
- package/lib/validation/config-security.js +741 -0
- package/lib/validation/documentation.js +326 -0
- package/lib/validation/index.js +186 -0
- package/lib/validation/validation-factory.js +153 -0
- package/lib/validation/workflow-validation.js +172 -0
- package/lib/yaml-utils.js +120 -0
- package/marketing/beta-user-email-campaign.md +372 -0
- package/marketing/landing-page.html +721 -0
- package/package.json +165 -0
- package/setup.js +2076 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const Ajv = require('ajv')
|
|
4
|
+
const addFormats = require('ajv-formats')
|
|
5
|
+
const fs = require('fs')
|
|
6
|
+
const path = require('path')
|
|
7
|
+
|
|
8
|
+
function validateQualityConfig(configPath) {
|
|
9
|
+
const result = {
|
|
10
|
+
valid: false,
|
|
11
|
+
errors: [],
|
|
12
|
+
config: null,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// DEBUG: Log entry
|
|
16
|
+
if (process.env.DEBUG_VALIDATOR) {
|
|
17
|
+
console.error(`[DEBUG] validateQualityConfig called with: ${configPath}`)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!fs.existsSync(configPath)) {
|
|
21
|
+
result.errors.push('Configuration file not found: ' + configPath)
|
|
22
|
+
return result
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let config
|
|
26
|
+
try {
|
|
27
|
+
const configContent = fs.readFileSync(configPath, 'utf8')
|
|
28
|
+
config = JSON.parse(configContent)
|
|
29
|
+
result.config = config
|
|
30
|
+
} catch (error) {
|
|
31
|
+
result.errors.push('Failed to parse configuration file: ' + error.message)
|
|
32
|
+
return result
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let schema
|
|
36
|
+
try {
|
|
37
|
+
const schemaPath = path.join(
|
|
38
|
+
__dirname,
|
|
39
|
+
'..',
|
|
40
|
+
'config',
|
|
41
|
+
'quality-config.schema.json'
|
|
42
|
+
)
|
|
43
|
+
const schemaContent = fs.readFileSync(schemaPath, 'utf8')
|
|
44
|
+
schema = JSON.parse(schemaContent)
|
|
45
|
+
} catch (error) {
|
|
46
|
+
result.errors.push('Failed to load configuration schema: ' + error.message)
|
|
47
|
+
return result
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const ajv = new Ajv({ allErrors: true, strict: false })
|
|
51
|
+
addFormats(ajv)
|
|
52
|
+
|
|
53
|
+
const validate = ajv.compile(schema)
|
|
54
|
+
const valid = validate(config)
|
|
55
|
+
|
|
56
|
+
if (!valid) {
|
|
57
|
+
if (validate.errors) {
|
|
58
|
+
validate.errors.forEach(error => {
|
|
59
|
+
const errorPath = error.instancePath || '(root)'
|
|
60
|
+
const message = error.message || 'validation failed'
|
|
61
|
+
|
|
62
|
+
if (error.keyword === 'required') {
|
|
63
|
+
result.errors.push(
|
|
64
|
+
'Missing required field: ' +
|
|
65
|
+
(error.params?.missingProperty || 'unknown')
|
|
66
|
+
)
|
|
67
|
+
} else if (error.keyword === 'enum') {
|
|
68
|
+
result.errors.push(
|
|
69
|
+
'Invalid value at ' +
|
|
70
|
+
errorPath +
|
|
71
|
+
': must be one of ' +
|
|
72
|
+
(error.params?.allowedValues?.join(', ') || 'unknown values')
|
|
73
|
+
)
|
|
74
|
+
} else if (error.keyword === 'type') {
|
|
75
|
+
result.errors.push(
|
|
76
|
+
'Invalid type at ' +
|
|
77
|
+
errorPath +
|
|
78
|
+
': expected ' +
|
|
79
|
+
(error.params?.type || 'unknown')
|
|
80
|
+
)
|
|
81
|
+
} else if (error.keyword === 'pattern') {
|
|
82
|
+
result.errors.push('Invalid format at ' + errorPath + ': ' + message)
|
|
83
|
+
} else if (error.keyword === 'minimum') {
|
|
84
|
+
result.errors.push(
|
|
85
|
+
'Invalid value at ' +
|
|
86
|
+
errorPath +
|
|
87
|
+
': must be >= ' +
|
|
88
|
+
(error.params?.limit ?? 'unknown')
|
|
89
|
+
)
|
|
90
|
+
} else if (error.keyword === 'additionalProperties') {
|
|
91
|
+
result.errors.push(
|
|
92
|
+
'Unknown property at ' +
|
|
93
|
+
errorPath +
|
|
94
|
+
': ' +
|
|
95
|
+
(error.params?.additionalProperty || 'unknown')
|
|
96
|
+
)
|
|
97
|
+
} else {
|
|
98
|
+
result.errors.push(
|
|
99
|
+
'Validation error at ' + errorPath + ': ' + message
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
result.valid = true
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return result
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Validate configuration and print results to console
|
|
113
|
+
* @param {string} configPath - Path to .qualityrc.json file
|
|
114
|
+
* @returns {boolean} - true if valid, false if invalid
|
|
115
|
+
*/
|
|
116
|
+
function validateAndReport(configPath) {
|
|
117
|
+
const { formatMessage } = require('./ui-helpers')
|
|
118
|
+
|
|
119
|
+
console.log(
|
|
120
|
+
formatMessage('working', 'Validating .qualityrc.json configuration...')
|
|
121
|
+
)
|
|
122
|
+
console.log('')
|
|
123
|
+
|
|
124
|
+
const result = validateQualityConfig(configPath)
|
|
125
|
+
|
|
126
|
+
if (!result.valid) {
|
|
127
|
+
console.error(formatMessage('error', 'Configuration validation failed!\n'))
|
|
128
|
+
result.errors.forEach((error, index) => {
|
|
129
|
+
console.error(` ${index + 1}. ${error}`)
|
|
130
|
+
})
|
|
131
|
+
console.error('')
|
|
132
|
+
console.error(formatMessage('info', 'Fix the errors above and try again.'))
|
|
133
|
+
console.error(
|
|
134
|
+
formatMessage('info', 'See .qualityrc.json.example for reference.\n')
|
|
135
|
+
)
|
|
136
|
+
return false
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
console.log(formatMessage('success', 'Configuration is valid!\n'))
|
|
140
|
+
|
|
141
|
+
if (result.config) {
|
|
142
|
+
console.log('Configuration summary:')
|
|
143
|
+
console.log(` Version: ${result.config.version}`)
|
|
144
|
+
console.log(` Maturity: ${result.config.maturity || 'auto'}`)
|
|
145
|
+
|
|
146
|
+
if (result.config.checks) {
|
|
147
|
+
const enabledChecks = Object.entries(result.config.checks)
|
|
148
|
+
.filter(
|
|
149
|
+
([, check]) => check.enabled === true || check.enabled === 'auto'
|
|
150
|
+
)
|
|
151
|
+
.map(([name]) => name)
|
|
152
|
+
|
|
153
|
+
console.log(
|
|
154
|
+
` Enabled checks: ${enabledChecks.length > 0 ? enabledChecks.join(', ') : 'none'}`
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
console.log('')
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return true
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
module.exports = { validateQualityConfig, validateAndReport }
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic Dependency Monitoring Library (Free Tier)
|
|
3
|
+
* Generates simple Dependabot configuration without advanced features
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs')
|
|
7
|
+
const path = require('path')
|
|
8
|
+
const { convertToYaml } = require('./yaml-utils')
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Detect if project has package.json (npm projects only for free tier)
|
|
12
|
+
*/
|
|
13
|
+
function hasNpmProject(projectPath) {
|
|
14
|
+
return fs.existsSync(path.join(projectPath, 'package.json'))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Generate basic Dependabot configuration (Free Tier)
|
|
19
|
+
* Limited to npm only, no framework detection, basic settings
|
|
20
|
+
*/
|
|
21
|
+
function generateBasicDependabotConfig(options = {}) {
|
|
22
|
+
const {
|
|
23
|
+
projectPath = '.',
|
|
24
|
+
schedule = 'weekly',
|
|
25
|
+
day = 'monday',
|
|
26
|
+
time = '09:00',
|
|
27
|
+
} = options
|
|
28
|
+
|
|
29
|
+
if (!hasNpmProject(projectPath)) {
|
|
30
|
+
return null // Only npm projects supported in free tier
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const config = {
|
|
34
|
+
version: 2,
|
|
35
|
+
updates: [
|
|
36
|
+
{
|
|
37
|
+
'package-ecosystem': 'npm',
|
|
38
|
+
directory: '/',
|
|
39
|
+
schedule: {
|
|
40
|
+
interval: schedule,
|
|
41
|
+
day: day,
|
|
42
|
+
time: time,
|
|
43
|
+
},
|
|
44
|
+
'open-pull-requests-limit': 5,
|
|
45
|
+
labels: ['dependencies'],
|
|
46
|
+
'commit-message': {
|
|
47
|
+
prefix: 'deps',
|
|
48
|
+
include: 'scope',
|
|
49
|
+
},
|
|
50
|
+
// Note: Dependabot will create PRs for all dependency updates.
|
|
51
|
+
// To auto-merge specific updates (e.g., security patches), add a GitHub Actions
|
|
52
|
+
// workflow with conditions like: if: contains(github.event.pull_request.labels.*.name, 'security')
|
|
53
|
+
// See: https://docs.github.com/en/code-security/dependabot/working-with-dependabot/automating-dependabot-with-github-actions
|
|
54
|
+
},
|
|
55
|
+
// GitHub Actions monitoring (free tier includes this)
|
|
56
|
+
{
|
|
57
|
+
'package-ecosystem': 'github-actions',
|
|
58
|
+
directory: '/',
|
|
59
|
+
schedule: {
|
|
60
|
+
interval: schedule,
|
|
61
|
+
day: day,
|
|
62
|
+
time: time,
|
|
63
|
+
},
|
|
64
|
+
labels: ['dependencies', 'github-actions'],
|
|
65
|
+
'commit-message': {
|
|
66
|
+
prefix: 'deps(actions)',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return config
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Validate Dependabot configuration structure
|
|
77
|
+
* Ensures the configuration matches Dependabot schema requirements
|
|
78
|
+
*/
|
|
79
|
+
function validateDependabotConfig(config) {
|
|
80
|
+
// Basic structure validation
|
|
81
|
+
if (!config || typeof config !== 'object') {
|
|
82
|
+
throw new Error('Config must be a valid object')
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!config.version || config.version !== 2) {
|
|
86
|
+
throw new Error('Dependabot configuration must specify version: 2')
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!config.updates || !Array.isArray(config.updates)) {
|
|
90
|
+
throw new Error('Dependabot configuration must have an updates array')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (config.updates.length === 0) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
'Dependabot configuration must have at least one update configuration'
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Validate each update configuration
|
|
100
|
+
config.updates.forEach((update, index) => {
|
|
101
|
+
if (!update['package-ecosystem']) {
|
|
102
|
+
throw new Error(
|
|
103
|
+
`Update configuration ${index} must specify package-ecosystem`
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!update.directory) {
|
|
108
|
+
throw new Error(`Update configuration ${index} must specify directory`)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!update.schedule || !update.schedule.interval) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
`Update configuration ${index} must specify schedule.interval`
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Validate package-ecosystem values
|
|
118
|
+
const validEcosystems = [
|
|
119
|
+
'npm',
|
|
120
|
+
'github-actions',
|
|
121
|
+
'docker',
|
|
122
|
+
'pip',
|
|
123
|
+
'composer',
|
|
124
|
+
'bundler',
|
|
125
|
+
'go',
|
|
126
|
+
'nuget',
|
|
127
|
+
'maven',
|
|
128
|
+
'gradle',
|
|
129
|
+
'terraform',
|
|
130
|
+
]
|
|
131
|
+
if (!validEcosystems.includes(update['package-ecosystem'])) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
`Invalid package-ecosystem '${update['package-ecosystem']}' in update configuration ${index}`
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Validate schedule intervals
|
|
138
|
+
const validIntervals = ['daily', 'weekly', 'monthly']
|
|
139
|
+
if (!validIntervals.includes(update.schedule.interval)) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
`Invalid schedule interval '${update.schedule.interval}' in update configuration ${index}`
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
return true
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Write basic Dependabot configuration to file
|
|
151
|
+
*/
|
|
152
|
+
function writeBasicDependabotConfig(config, outputPath) {
|
|
153
|
+
// Validate configuration before writing
|
|
154
|
+
validateDependabotConfig(config)
|
|
155
|
+
|
|
156
|
+
const yamlContent = `# Basic Dependabot configuration (Free Tier)
|
|
157
|
+
# Auto-generated by create-qa-architect
|
|
158
|
+
# Upgrade to Pro for framework-aware grouping and multi-language support
|
|
159
|
+
# See: https://create-qa-architect.dev/pro
|
|
160
|
+
|
|
161
|
+
${convertToYaml(config)}`
|
|
162
|
+
|
|
163
|
+
const configDir = path.dirname(outputPath)
|
|
164
|
+
if (!fs.existsSync(configDir)) {
|
|
165
|
+
fs.mkdirSync(configDir, { recursive: true })
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
fs.writeFileSync(outputPath, yamlContent)
|
|
169
|
+
|
|
170
|
+
// Post-write validation: verify the file can be parsed
|
|
171
|
+
try {
|
|
172
|
+
const yaml = require('js-yaml')
|
|
173
|
+
const writtenContent = fs.readFileSync(outputPath, 'utf8')
|
|
174
|
+
yaml.load(writtenContent)
|
|
175
|
+
} catch (error) {
|
|
176
|
+
throw new Error(
|
|
177
|
+
`Generated Dependabot configuration is invalid YAML: ${error.message}`
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
module.exports = {
|
|
182
|
+
hasNpmProject,
|
|
183
|
+
generateBasicDependabotConfig,
|
|
184
|
+
writeBasicDependabotConfig,
|
|
185
|
+
}
|