@girardmedia/bootspring 2.5.0 → 2.5.2

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.
Files changed (59) hide show
  1. package/README.md +9 -403
  2. package/bin/bootspring.js +1 -96
  3. package/dist/cli/index.js +65134 -0
  4. package/dist/cli-launcher.js +92 -0
  5. package/dist/core/index.d.ts +2110 -5582
  6. package/dist/core/index.js +2 -0
  7. package/dist/core.js +21123 -5413
  8. package/dist/mcp/index.d.ts +357 -1
  9. package/dist/mcp/index.js +2 -0
  10. package/dist/mcp-server.js +51948 -1976
  11. package/package.json +27 -63
  12. package/scripts/postinstall.cjs +144 -0
  13. package/LICENSE +0 -29
  14. package/dist/cli/index.cjs +0 -20776
  15. package/generators/api-docs.js +0 -827
  16. package/generators/decisions.js +0 -655
  17. package/generators/generate.js +0 -595
  18. package/generators/health.js +0 -942
  19. package/generators/index.ts +0 -82
  20. package/generators/presets/full.js +0 -28
  21. package/generators/presets/index.js +0 -12
  22. package/generators/presets/minimal.js +0 -29
  23. package/generators/presets/standard.js +0 -28
  24. package/generators/questionnaire.js +0 -414
  25. package/generators/sections/advanced.js +0 -136
  26. package/generators/sections/ai.js +0 -106
  27. package/generators/sections/auth.js +0 -89
  28. package/generators/sections/backend.js +0 -146
  29. package/generators/sections/business.js +0 -118
  30. package/generators/sections/content.js +0 -300
  31. package/generators/sections/deployment.js +0 -139
  32. package/generators/sections/features.js +0 -122
  33. package/generators/sections/frontend.js +0 -118
  34. package/generators/sections/identity.js +0 -76
  35. package/generators/sections/index.js +0 -40
  36. package/generators/sections/instructions.js +0 -146
  37. package/generators/sections/payments.js +0 -104
  38. package/generators/sections/plugins.js +0 -142
  39. package/generators/sections/pre-build.js +0 -130
  40. package/generators/sections/security.js +0 -127
  41. package/generators/sections/technical.js +0 -171
  42. package/generators/sections/testing.js +0 -125
  43. package/generators/sections/workflow.js +0 -104
  44. package/generators/sprint.js +0 -675
  45. package/generators/templates/agents.template.js +0 -199
  46. package/generators/templates/assistant-context.template.js +0 -83
  47. package/generators/templates/build-planning.template.js +0 -708
  48. package/generators/templates/claude.template.js +0 -379
  49. package/generators/templates/content.template.js +0 -819
  50. package/generators/templates/index.js +0 -16
  51. package/generators/templates/planning.template.js +0 -515
  52. package/generators/templates/seed.template.js +0 -109
  53. package/generators/visual-doc-generator.js +0 -910
  54. package/scripts/postinstall.js +0 -197
  55. /package/{claude-commands → assets/claude-commands}/agent.md +0 -0
  56. /package/{claude-commands → assets/claude-commands}/bs.md +0 -0
  57. /package/{claude-commands → assets/claude-commands}/build.md +0 -0
  58. /package/{claude-commands → assets/claude-commands}/skill.md +0 -0
  59. /package/{claude-commands → assets/claude-commands}/todo.md +0 -0
@@ -1,127 +0,0 @@
1
- /**
2
- * Security Section
3
- *
4
- * Security requirements, compliance, and best practices.
5
- *
6
- * @package bootspring
7
- * @module generators/sections/security
8
- */
9
-
10
- const title = 'Security Requirements';
11
- const description = 'Security and compliance setup';
12
-
13
- /**
14
- * Run the security section
15
- */
16
- async function run(rl, previousAnswers, helpers) {
17
- const { askChoice, askMultiSelect, askYesNo } = helpers;
18
- const answers = {};
19
-
20
- // Security Level
21
- const levelOptions = [
22
- { label: 'Basic', value: 'basic', description: 'Standard security practices' },
23
- { label: 'Standard', value: 'standard', description: 'Industry best practices' },
24
- { label: 'High', value: 'high', description: 'Enhanced security measures' },
25
- { label: 'Enterprise', value: 'enterprise', description: 'Maximum security' }
26
- ];
27
-
28
- answers.securityLevel = await askChoice(
29
- rl,
30
- 'Security level:',
31
- levelOptions,
32
- 1
33
- );
34
-
35
- // Security Features
36
- const featureOptions = [
37
- { label: 'HTTPS enforcement', value: 'https' },
38
- { label: 'CSP headers', value: 'csp' },
39
- { label: 'Rate limiting', value: 'ratelimit' },
40
- { label: 'Input sanitization', value: 'sanitization' },
41
- { label: 'SQL injection prevention', value: 'sqli' },
42
- { label: 'XSS prevention', value: 'xss' },
43
- { label: 'CSRF protection', value: 'csrf' },
44
- { label: 'Secret scanning', value: 'secrets' }
45
- ];
46
-
47
- // Default based on security level
48
- const defaultFeatures = answers.securityLevel === 'basic'
49
- ? ['https', 'sanitization']
50
- : answers.securityLevel === 'standard'
51
- ? ['https', 'csp', 'ratelimit', 'sanitization', 'xss']
52
- : ['https', 'csp', 'ratelimit', 'sanitization', 'sqli', 'xss', 'csrf', 'secrets'];
53
-
54
- answers.securityFeatures = await askMultiSelect(
55
- rl,
56
- 'Security features:',
57
- featureOptions,
58
- defaultFeatures
59
- );
60
-
61
- // Compliance Requirements
62
- const complianceOptions = [
63
- { label: 'None', value: 'none' },
64
- { label: 'GDPR', value: 'gdpr' },
65
- { label: 'SOC 2', value: 'soc2' },
66
- { label: 'HIPAA', value: 'hipaa' },
67
- { label: 'PCI DSS', value: 'pci' },
68
- { label: 'CCPA', value: 'ccpa' }
69
- ];
70
-
71
- answers.compliance = await askMultiSelect(
72
- rl,
73
- 'Compliance requirements:',
74
- complianceOptions,
75
- []
76
- );
77
-
78
- // Data handling
79
- if (answers.compliance.length > 0 && !answers.compliance.includes('none')) {
80
- const dataOptions = [
81
- { label: 'Data encryption at rest', value: 'encryption-rest' },
82
- { label: 'Data encryption in transit', value: 'encryption-transit' },
83
- { label: 'Data retention policies', value: 'retention' },
84
- { label: 'Data deletion (right to forget)', value: 'deletion' },
85
- { label: 'Data export', value: 'export' },
86
- { label: 'Audit logging', value: 'audit' }
87
- ];
88
-
89
- answers.dataHandling = await askMultiSelect(
90
- rl,
91
- 'Data handling requirements:',
92
- dataOptions,
93
- ['encryption-rest', 'encryption-transit']
94
- );
95
- }
96
-
97
- // Vulnerability Scanning
98
- answers.enableSecurityScanning = await askYesNo(
99
- rl,
100
- 'Enable automated security scanning?',
101
- true
102
- );
103
-
104
- if (answers.enableSecurityScanning) {
105
- const scanOptions = [
106
- { label: 'Dependabot', value: 'dependabot', description: 'GitHub dependency alerts' },
107
- { label: 'Snyk', value: 'snyk', description: 'Security monitoring' },
108
- { label: 'CodeQL', value: 'codeql', description: 'GitHub code scanning' },
109
- { label: 'SonarQube', value: 'sonar', description: 'Code quality & security' }
110
- ];
111
-
112
- answers.securityScanner = await askChoice(
113
- rl,
114
- 'Security scanner:',
115
- scanOptions,
116
- 0
117
- );
118
- }
119
-
120
- return answers;
121
- }
122
-
123
- module.exports = {
124
- title,
125
- description,
126
- run
127
- };
@@ -1,171 +0,0 @@
1
- /**
2
- * Technical Stack Section
3
- *
4
- * Collects framework, language, database, and hosting choices.
5
- *
6
- * @package bootspring
7
- * @module generators/sections/technical
8
- */
9
-
10
- const fs = require('fs');
11
- const path = require('path');
12
- const utils = require('../../core/utils');
13
-
14
- const title = 'Technical Stack';
15
- const description = 'Your technology choices';
16
-
17
- /**
18
- * Detect tech stack from existing files
19
- */
20
- function detectStack(projectRoot) {
21
- const detected = {
22
- framework: null,
23
- language: null,
24
- database: null,
25
- orm: null
26
- };
27
-
28
- const pkg = utils.getPackageJson(projectRoot);
29
- if (!pkg) return detected;
30
-
31
- const deps = { ...pkg.dependencies, ...pkg.devDependencies };
32
-
33
- // Detect framework
34
- if (deps.next) detected.framework = 'nextjs';
35
- else if (deps['@remix-run/react']) detected.framework = 'remix';
36
- else if (deps.nuxt) detected.framework = 'nuxt';
37
- else if (deps['@sveltejs/kit']) detected.framework = 'sveltekit';
38
- else if (deps.express) detected.framework = 'express';
39
- else if (deps.fastify) detected.framework = 'fastify';
40
- else if (deps.hono) detected.framework = 'hono';
41
-
42
- // Detect language
43
- detected.language = fs.existsSync(path.join(projectRoot, 'tsconfig.json'))
44
- ? 'typescript'
45
- : 'javascript';
46
-
47
- // Detect ORM/Database
48
- if (deps['@prisma/client']) {
49
- detected.orm = 'prisma';
50
- detected.database = 'postgresql'; // Default assumption
51
- } else if (deps.drizzle) {
52
- detected.orm = 'drizzle';
53
- } else if (deps.mongoose) {
54
- detected.orm = 'mongoose';
55
- detected.database = 'mongodb';
56
- }
57
-
58
- return detected;
59
- }
60
-
61
- /**
62
- * Run the technical section
63
- */
64
- async function run(rl, previousAnswers, helpers) {
65
- const { askChoice } = helpers;
66
- const detected = detectStack(process.cwd());
67
-
68
- if (detected.framework) {
69
- console.log(`\nDetected: ${detected.framework} + ${detected.language}`);
70
- if (detected.orm) console.log(` ${detected.orm}`);
71
- }
72
-
73
- const answers = {};
74
-
75
- // Framework
76
- const frameworkOptions = [
77
- { label: 'Next.js', value: 'nextjs', description: 'React framework with SSR' },
78
- { label: 'Remix', value: 'remix', description: 'Full-stack React framework' },
79
- { label: 'Nuxt', value: 'nuxt', description: 'Vue.js framework' },
80
- { label: 'SvelteKit', value: 'sveltekit', description: 'Svelte framework' },
81
- { label: 'Express', value: 'express', description: 'Node.js backend' },
82
- { label: 'Fastify', value: 'fastify', description: 'Fast Node.js backend' },
83
- { label: 'Hono', value: 'hono', description: 'Lightweight edge runtime' },
84
- { label: 'Other', value: 'other', description: 'Something else' }
85
- ];
86
- const detectedFrameworkIndex = frameworkOptions.findIndex(f => f.value === detected.framework);
87
-
88
- answers.framework = await askChoice(
89
- rl,
90
- 'Framework:',
91
- frameworkOptions,
92
- detectedFrameworkIndex >= 0 ? detectedFrameworkIndex : 0
93
- );
94
-
95
- // Language
96
- answers.language = await askChoice(
97
- rl,
98
- 'Language:',
99
- [
100
- { label: 'TypeScript', value: 'typescript', description: 'Recommended for type safety' },
101
- { label: 'JavaScript', value: 'javascript', description: 'Classic JS' }
102
- ],
103
- detected.language === 'typescript' ? 0 : 1
104
- );
105
-
106
- // Database
107
- const databaseOptions = [
108
- { label: 'PostgreSQL', value: 'postgresql', description: 'Powerful relational DB' },
109
- { label: 'MySQL', value: 'mysql', description: 'Popular relational DB' },
110
- { label: 'MongoDB', value: 'mongodb', description: 'Document database' },
111
- { label: 'SQLite', value: 'sqlite', description: 'File-based, great for dev' },
112
- { label: 'None', value: 'none', description: 'No database needed' }
113
- ];
114
- const detectedDbIndex = databaseOptions.findIndex(d => d.value === detected.database);
115
-
116
- answers.database = await askChoice(
117
- rl,
118
- 'Database:',
119
- databaseOptions,
120
- detectedDbIndex >= 0 ? detectedDbIndex : 0
121
- );
122
-
123
- // ORM (if database selected)
124
- if (answers.database !== 'none') {
125
- const ormOptions = answers.database === 'mongodb'
126
- ? [
127
- { label: 'Mongoose', value: 'mongoose', description: 'Popular MongoDB ODM' },
128
- { label: 'Native driver', value: 'native', description: 'Use MongoDB driver directly' }
129
- ]
130
- : [
131
- { label: 'Prisma', value: 'prisma', description: 'Type-safe ORM (Recommended)' },
132
- { label: 'Drizzle', value: 'drizzle', description: 'Lightweight TypeScript ORM' },
133
- { label: 'TypeORM', value: 'typeorm', description: 'Decorator-based ORM' },
134
- { label: 'Raw SQL', value: 'raw', description: 'Use SQL directly' }
135
- ];
136
-
137
- const detectedOrmIndex = ormOptions.findIndex(o => o.value === detected.orm);
138
-
139
- answers.orm = await askChoice(
140
- rl,
141
- 'ORM/Database client:',
142
- ormOptions,
143
- detectedOrmIndex >= 0 ? detectedOrmIndex : 0
144
- );
145
- }
146
-
147
- // Hosting
148
- const hostingOptions = [
149
- { label: 'Vercel', value: 'vercel', description: 'Best for Next.js' },
150
- { label: 'Netlify', value: 'netlify', description: 'Great for JAMstack' },
151
- { label: 'Railway', value: 'railway', description: 'Full-stack hosting' },
152
- { label: 'Fly.io', value: 'fly', description: 'Edge deployment' },
153
- { label: 'AWS', value: 'aws', description: 'Full AWS stack' },
154
- { label: 'Self-hosted', value: 'self-hosted', description: 'Your own servers' }
155
- ];
156
-
157
- answers.hosting = await askChoice(
158
- rl,
159
- 'Hosting platform:',
160
- hostingOptions,
161
- 0
162
- );
163
-
164
- return answers;
165
- }
166
-
167
- module.exports = {
168
- title,
169
- description,
170
- run
171
- };
@@ -1,125 +0,0 @@
1
- /**
2
- * Testing Section
3
- *
4
- * Testing strategy, frameworks, and coverage.
5
- *
6
- * @package bootspring
7
- * @module generators/sections/testing
8
- */
9
-
10
- const title = 'Testing Strategy';
11
- const description = 'Testing setup and approach';
12
-
13
- /**
14
- * Run the testing section
15
- */
16
- async function run(rl, previousAnswers, helpers) {
17
- const { askChoice, askMultiSelect, askYesNo } = helpers;
18
- const answers = {};
19
-
20
- // Enable testing
21
- answers.enableTesting = await askYesNo(
22
- rl,
23
- 'Set up testing infrastructure?',
24
- true
25
- );
26
-
27
- if (!answers.enableTesting) {
28
- return answers;
29
- }
30
-
31
- // Test Runner
32
- const runnerOptions = [
33
- { label: 'Vitest', value: 'vitest', description: 'Fast, Vite-native (Recommended)' },
34
- { label: 'Jest', value: 'jest', description: 'Popular, full-featured' },
35
- { label: 'Bun test', value: 'bun', description: 'Fast, Bun runtime' },
36
- { label: 'Node test runner', value: 'node', description: 'Built-in Node.js' }
37
- ];
38
-
39
- answers.testRunner = await askChoice(
40
- rl,
41
- 'Test runner:',
42
- runnerOptions,
43
- 0
44
- );
45
-
46
- // Testing Types
47
- const typeOptions = [
48
- { label: 'Unit tests', value: 'unit' },
49
- { label: 'Integration tests', value: 'integration' },
50
- { label: 'E2E tests', value: 'e2e' },
51
- { label: 'Component tests', value: 'component' },
52
- { label: 'API tests', value: 'api' },
53
- { label: 'Visual regression', value: 'visual' }
54
- ];
55
-
56
- answers.testTypes = await askMultiSelect(
57
- rl,
58
- 'Testing types:',
59
- typeOptions,
60
- ['unit', 'integration']
61
- );
62
-
63
- // E2E Framework (if selected)
64
- if (answers.testTypes.includes('e2e')) {
65
- const e2eOptions = [
66
- { label: 'Playwright', value: 'playwright', description: 'Modern E2E (Recommended)' },
67
- { label: 'Cypress', value: 'cypress', description: 'Popular E2E' },
68
- { label: 'Puppeteer', value: 'puppeteer', description: 'Chrome automation' }
69
- ];
70
-
71
- answers.e2eFramework = await askChoice(
72
- rl,
73
- 'E2E framework:',
74
- e2eOptions,
75
- 0
76
- );
77
- }
78
-
79
- // Component Testing (if React-based)
80
- if (answers.testTypes.includes('component')) {
81
- const componentOptions = [
82
- { label: 'Testing Library', value: 'testing-library', description: 'User-centric testing' },
83
- { label: 'Storybook', value: 'storybook', description: 'Component explorer' },
84
- { label: 'Both', value: 'both', description: 'Testing Library + Storybook' }
85
- ];
86
-
87
- answers.componentTesting = await askChoice(
88
- rl,
89
- 'Component testing:',
90
- componentOptions,
91
- 0
92
- );
93
- }
94
-
95
- // Coverage
96
- const coverageOptions = [
97
- { label: 'No coverage', value: 'none' },
98
- { label: 'Basic (50%+)', value: 'basic' },
99
- { label: 'Standard (70%+)', value: 'standard' },
100
- { label: 'High (85%+)', value: 'high' },
101
- { label: 'Strict (95%+)', value: 'strict' }
102
- ];
103
-
104
- answers.coverageTarget = await askChoice(
105
- rl,
106
- 'Coverage target:',
107
- coverageOptions,
108
- 2
109
- );
110
-
111
- // CI Integration
112
- answers.testInCI = await askYesNo(
113
- rl,
114
- 'Run tests in CI pipeline?',
115
- true
116
- );
117
-
118
- return answers;
119
- }
120
-
121
- module.exports = {
122
- title,
123
- description,
124
- run
125
- };
@@ -1,104 +0,0 @@
1
- /**
2
- * Development Workflow Section
3
- *
4
- * Collects git strategy, team size, and commit conventions.
5
- *
6
- * @package bootspring
7
- * @module generators/sections/workflow
8
- */
9
-
10
- const title = 'Development Workflow';
11
- const description = 'How you work';
12
-
13
- /**
14
- * Run the workflow section
15
- */
16
- async function run(rl, previousAnswers, helpers) {
17
- const { askChoice, askYesNo } = helpers;
18
-
19
- const answers = {};
20
-
21
- // Team size
22
- answers.teamSize = await askChoice(
23
- rl,
24
- 'Team size:',
25
- [
26
- { label: 'Solo', value: 'solo', description: 'Just me' },
27
- { label: 'Small (2-5)', value: 'small', description: 'Small team' },
28
- { label: 'Medium (6-15)', value: 'medium', description: 'Growing team' },
29
- { label: 'Large (15+)', value: 'large', description: 'Large organization' }
30
- ],
31
- 0
32
- );
33
-
34
- // Git strategy
35
- answers.gitStrategy = await askChoice(
36
- rl,
37
- 'Git workflow:',
38
- [
39
- { label: 'Feature Branch', value: 'feature-branch', description: 'Branch per feature, merge to main' },
40
- { label: 'Trunk-Based', value: 'trunk', description: 'Direct commits to main with flags' },
41
- { label: 'GitFlow', value: 'gitflow', description: 'develop, release, hotfix branches' },
42
- { label: 'GitHub Flow', value: 'github-flow', description: 'Simple branch + PR' }
43
- ],
44
- answers.teamSize === 'solo' ? 1 : 0
45
- );
46
-
47
- // Commit style
48
- answers.commitStyle = await askChoice(
49
- rl,
50
- 'Commit message style:',
51
- [
52
- { label: 'Conventional', value: 'conventional', description: 'feat:, fix:, docs: etc.' },
53
- { label: 'Gitmoji', value: 'gitmoji', description: 'Emoji prefixes' },
54
- { label: 'Free-form', value: 'freeform', description: 'No strict format' }
55
- ],
56
- 0
57
- );
58
-
59
- // Code review
60
- if (answers.teamSize !== 'solo') {
61
- answers.requireReview = await askYesNo(
62
- rl,
63
- 'Require code review for PRs?',
64
- true
65
- );
66
-
67
- answers.minReviewers = answers.requireReview
68
- ? await askChoice(rl, 'Minimum reviewers:', [
69
- { label: '1', value: 1 },
70
- { label: '2', value: 2 },
71
- { label: '3+', value: 3 }
72
- ], 0)
73
- : 0;
74
- }
75
-
76
- // CI/CD
77
- answers.enableCI = await askYesNo(
78
- rl,
79
- 'Set up CI/CD pipeline?',
80
- true
81
- );
82
-
83
- if (answers.enableCI) {
84
- answers.ciProvider = await askChoice(
85
- rl,
86
- 'CI/CD provider:',
87
- [
88
- { label: 'GitHub Actions', value: 'github-actions', description: 'Built into GitHub' },
89
- { label: 'Vercel', value: 'vercel', description: 'Automatic with Vercel' },
90
- { label: 'GitLab CI', value: 'gitlab', description: 'GitLab pipelines' },
91
- { label: 'CircleCI', value: 'circleci', description: 'Dedicated CI service' }
92
- ],
93
- 0
94
- );
95
- }
96
-
97
- return answers;
98
- }
99
-
100
- module.exports = {
101
- title,
102
- description,
103
- run
104
- };