forge-dev-framework 1.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.
Files changed (140) hide show
  1. package/.claude/rules/api-patterns.md +98 -0
  2. package/.claude/rules/security-baseline.md +204 -0
  3. package/.claude/rules/testing-standards.md +177 -0
  4. package/.claude/rules/ui-conventions.md +142 -0
  5. package/README.md +261 -0
  6. package/bin/forge.js +14 -0
  7. package/dist/bin/forge.js +14 -0
  8. package/dist/cli/index.d.ts +22 -0
  9. package/dist/cli/index.d.ts.map +1 -0
  10. package/dist/cli/index.js +116 -0
  11. package/dist/cli/index.js.map +1 -0
  12. package/dist/commands/base.d.ts +31 -0
  13. package/dist/commands/base.d.ts.map +1 -0
  14. package/dist/commands/base.js +31 -0
  15. package/dist/commands/base.js.map +1 -0
  16. package/dist/commands/config.d.ts +14 -0
  17. package/dist/commands/config.d.ts.map +1 -0
  18. package/dist/commands/config.js +175 -0
  19. package/dist/commands/config.js.map +1 -0
  20. package/dist/commands/generate.d.ts +17 -0
  21. package/dist/commands/generate.d.ts.map +1 -0
  22. package/dist/commands/generate.js +159 -0
  23. package/dist/commands/generate.js.map +1 -0
  24. package/dist/commands/help.d.ts +11 -0
  25. package/dist/commands/help.d.ts.map +1 -0
  26. package/dist/commands/help.js +65 -0
  27. package/dist/commands/help.js.map +1 -0
  28. package/dist/commands/index.d.ts +8 -0
  29. package/dist/commands/index.d.ts.map +1 -0
  30. package/dist/commands/index.js +8 -0
  31. package/dist/commands/index.js.map +1 -0
  32. package/dist/commands/init.d.ts +10 -0
  33. package/dist/commands/init.d.ts.map +1 -0
  34. package/dist/commands/init.js +22 -0
  35. package/dist/commands/init.js.map +1 -0
  36. package/dist/commands/status.d.ts +13 -0
  37. package/dist/commands/status.d.ts.map +1 -0
  38. package/dist/commands/status.js +101 -0
  39. package/dist/commands/status.js.map +1 -0
  40. package/dist/commands/stubs.d.ts +14 -0
  41. package/dist/commands/stubs.d.ts.map +1 -0
  42. package/dist/commands/stubs.js +30 -0
  43. package/dist/commands/stubs.js.map +1 -0
  44. package/dist/generators/index.d.ts +11 -0
  45. package/dist/generators/index.d.ts.map +1 -0
  46. package/dist/generators/index.js +10 -0
  47. package/dist/generators/index.js.map +1 -0
  48. package/dist/generators/required-fields.d.ts +74 -0
  49. package/dist/generators/required-fields.d.ts.map +1 -0
  50. package/dist/generators/required-fields.js +179 -0
  51. package/dist/generators/required-fields.js.map +1 -0
  52. package/dist/generators/template-engine.d.ts +65 -0
  53. package/dist/generators/template-engine.d.ts.map +1 -0
  54. package/dist/generators/template-engine.js +209 -0
  55. package/dist/generators/template-engine.js.map +1 -0
  56. package/dist/generators/token-validator.d.ts +51 -0
  57. package/dist/generators/token-validator.d.ts.map +1 -0
  58. package/dist/generators/token-validator.js +141 -0
  59. package/dist/generators/token-validator.js.map +1 -0
  60. package/dist/generators/types.d.ts +433 -0
  61. package/dist/generators/types.d.ts.map +1 -0
  62. package/dist/generators/types.js +5 -0
  63. package/dist/generators/types.js.map +1 -0
  64. package/dist/generators/xml-task-generator.d.ts +67 -0
  65. package/dist/generators/xml-task-generator.d.ts.map +1 -0
  66. package/dist/generators/xml-task-generator.js +297 -0
  67. package/dist/generators/xml-task-generator.js.map +1 -0
  68. package/dist/git/__tests__/worktree.test.d.ts +5 -0
  69. package/dist/git/__tests__/worktree.test.d.ts.map +1 -0
  70. package/dist/git/__tests__/worktree.test.js +121 -0
  71. package/dist/git/__tests__/worktree.test.js.map +1 -0
  72. package/dist/git/codeowners.d.ts +101 -0
  73. package/dist/git/codeowners.d.ts.map +1 -0
  74. package/dist/git/codeowners.js +216 -0
  75. package/dist/git/codeowners.js.map +1 -0
  76. package/dist/git/commit.d.ts +135 -0
  77. package/dist/git/commit.d.ts.map +1 -0
  78. package/dist/git/commit.js +223 -0
  79. package/dist/git/commit.js.map +1 -0
  80. package/dist/git/hooks/commit-msg.d.ts +8 -0
  81. package/dist/git/hooks/commit-msg.d.ts.map +1 -0
  82. package/dist/git/hooks/commit-msg.js +34 -0
  83. package/dist/git/hooks/commit-msg.js.map +1 -0
  84. package/dist/git/hooks/pre-commit.d.ts +8 -0
  85. package/dist/git/hooks/pre-commit.d.ts.map +1 -0
  86. package/dist/git/hooks/pre-commit.js +34 -0
  87. package/dist/git/hooks/pre-commit.js.map +1 -0
  88. package/dist/git/pre-commit-hooks.d.ts +117 -0
  89. package/dist/git/pre-commit-hooks.d.ts.map +1 -0
  90. package/dist/git/pre-commit-hooks.js +270 -0
  91. package/dist/git/pre-commit-hooks.js.map +1 -0
  92. package/dist/git/wipe-protocol.d.ts +281 -0
  93. package/dist/git/wipe-protocol.d.ts.map +1 -0
  94. package/dist/git/wipe-protocol.js +237 -0
  95. package/dist/git/wipe-protocol.js.map +1 -0
  96. package/dist/git/worktree.d.ts +69 -0
  97. package/dist/git/worktree.d.ts.map +1 -0
  98. package/dist/git/worktree.js +202 -0
  99. package/dist/git/worktree.js.map +1 -0
  100. package/dist/scripts/install.d.ts +8 -0
  101. package/dist/scripts/install.d.ts.map +1 -0
  102. package/dist/scripts/install.js +161 -0
  103. package/dist/scripts/install.js.map +1 -0
  104. package/dist/types/config.d.ts +30 -0
  105. package/dist/types/config.d.ts.map +1 -0
  106. package/dist/types/config.js +23 -0
  107. package/dist/types/config.js.map +1 -0
  108. package/dist/types/index.d.ts +6 -0
  109. package/dist/types/index.d.ts.map +1 -0
  110. package/dist/types/index.js +6 -0
  111. package/dist/types/index.js.map +1 -0
  112. package/dist/types/state.d.ts +56 -0
  113. package/dist/types/state.d.ts.map +1 -0
  114. package/dist/types/state.js +6 -0
  115. package/dist/types/state.js.map +1 -0
  116. package/dist/utils/config.d.ts +15 -0
  117. package/dist/utils/config.d.ts.map +1 -0
  118. package/dist/utils/config.js +80 -0
  119. package/dist/utils/config.js.map +1 -0
  120. package/dist/utils/errors.d.ts +25 -0
  121. package/dist/utils/errors.d.ts.map +1 -0
  122. package/dist/utils/errors.js +48 -0
  123. package/dist/utils/errors.js.map +1 -0
  124. package/dist/utils/index.d.ts +11 -0
  125. package/dist/utils/index.d.ts.map +1 -0
  126. package/dist/utils/index.js +9 -0
  127. package/dist/utils/index.js.map +1 -0
  128. package/dist/utils/logger.d.ts +34 -0
  129. package/dist/utils/logger.d.ts.map +1 -0
  130. package/dist/utils/logger.js +73 -0
  131. package/dist/utils/logger.js.map +1 -0
  132. package/dist/utils/state-api.d.ts +128 -0
  133. package/dist/utils/state-api.d.ts.map +1 -0
  134. package/dist/utils/state-api.js +170 -0
  135. package/dist/utils/state-api.js.map +1 -0
  136. package/dist/utils/template-client.d.ts +73 -0
  137. package/dist/utils/template-client.d.ts.map +1 -0
  138. package/dist/utils/template-client.js +151 -0
  139. package/dist/utils/template-client.js.map +1 -0
  140. package/package.json +72 -0
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Template Rendering Engine
3
+ *
4
+ * Uses Handlebars for template rendering with support for:
5
+ * - Variable interpolation ({{ variable }})
6
+ * - Conditional sections ({{#if}}...)
7
+ * - List iteration ({{#each}}...)
8
+ * - Custom helpers for formatting
9
+ */
10
+ import Handlebars from 'handlebars';
11
+ import { readFile } from 'fs/promises';
12
+ import { join } from 'path';
13
+ import { countTokens, validateTokenLimit } from './token-validator.js';
14
+ /**
15
+ * Template Engine class
16
+ */
17
+ export class TemplateEngine {
18
+ config;
19
+ handlebars;
20
+ constructor(config) {
21
+ this.config = config;
22
+ this.handlebars = Handlebars.create();
23
+ this.registerHelpers();
24
+ }
25
+ /**
26
+ * Register custom Handlebars helpers
27
+ */
28
+ registerHelpers() {
29
+ // Equals helper
30
+ this.handlebars.registerHelper('eq', function (a, b) {
31
+ return a === b;
32
+ });
33
+ // Not equals helper
34
+ this.handlebars.registerHelper('ne', function (a, b) {
35
+ return a !== b;
36
+ });
37
+ // And helper
38
+ this.handlebars.registerHelper('and', function (...args) {
39
+ // Last arg is options object
40
+ const options = args.pop();
41
+ return args.slice(0, -1).every((arg) => Boolean(arg));
42
+ });
43
+ // Or helper
44
+ this.handlebars.registerHelper('or', function (...args) {
45
+ // Last arg is options object
46
+ const options = args.pop();
47
+ return args.slice(0, -1).some((arg) => Boolean(arg));
48
+ });
49
+ // Default value helper
50
+ this.handlebars.registerHelper('default', function (value, defaultValue) {
51
+ return value ?? defaultValue;
52
+ });
53
+ // JSON stringify helper
54
+ this.handlebars.registerHelper('json', function (context, indent = 2) {
55
+ return JSON.stringify(context, null, indent);
56
+ });
57
+ // Concat helper
58
+ this.handlebars.registerHelper('concat', function (...args) {
59
+ // Last arg is options object
60
+ const options = args.pop();
61
+ return args.slice(0, -1).join('');
62
+ });
63
+ // ToLower helper
64
+ this.handlebars.registerHelper('toLowerCase', function (str) {
65
+ return str.toLowerCase();
66
+ });
67
+ // ToUpper helper
68
+ this.handlebars.registerHelper('toUpperCase', function (str) {
69
+ return str.toUpperCase();
70
+ });
71
+ }
72
+ /**
73
+ * Load a template file
74
+ */
75
+ async loadTemplate(templateName) {
76
+ const templatePath = join(this.config.templatesDir, templateName);
77
+ return await readFile(templatePath, 'utf-8');
78
+ }
79
+ /**
80
+ * Get token limit for a specific template
81
+ */
82
+ getTokenLimit(templateName) {
83
+ const limits = {
84
+ 'CLAUDE.md': this.config.tokenLimits.claude,
85
+ 'REQUIREMENTS.md': this.config.tokenLimits.requirements,
86
+ 'PLAN.md': this.config.tokenLimits.plan,
87
+ };
88
+ // Rules files
89
+ if (templateName.includes('rules/')) {
90
+ return this.config.tokenLimits.rules;
91
+ }
92
+ // Default limit for other templates
93
+ return limits[templateName] ?? 4000;
94
+ }
95
+ /**
96
+ * Render a template with the given context
97
+ */
98
+ async render(templateName, context) {
99
+ try {
100
+ // Load template
101
+ const templateSource = await this.loadTemplate(templateName);
102
+ // Compile template
103
+ const template = this.handlebars.compile(templateSource);
104
+ // Render with context
105
+ const content = template(context);
106
+ // Count tokens
107
+ const tokenCount = countTokens(content);
108
+ // Get token limit for this template
109
+ const limit = this.getTokenLimit(templateName);
110
+ // Validate against limit
111
+ const { withinLimit, warnings } = validateTokenLimit(tokenCount, limit);
112
+ return {
113
+ content,
114
+ tokenCount,
115
+ withinLimit,
116
+ warnings,
117
+ };
118
+ }
119
+ catch (error) {
120
+ throw new Error(`Failed to render template ${templateName}: ${error.message}`);
121
+ }
122
+ }
123
+ /**
124
+ * Render a template string directly (without loading from file)
125
+ */
126
+ renderString(templateString, context) {
127
+ try {
128
+ const template = this.handlebars.compile(templateString);
129
+ return template(context);
130
+ }
131
+ catch (error) {
132
+ throw new Error(`Failed to render template string: ${error.message}`);
133
+ }
134
+ }
135
+ /**
136
+ * Render multiple templates in batch
137
+ */
138
+ async renderBatch(templates) {
139
+ const results = new Map();
140
+ for (const { name, context } of templates) {
141
+ const result = await this.render(name, context);
142
+ results.set(name, result);
143
+ }
144
+ return results;
145
+ }
146
+ /**
147
+ * Validate context data structure
148
+ */
149
+ validateContext(context) {
150
+ const errors = [];
151
+ // Required fields
152
+ if (!context.projectName) {
153
+ errors.push('Missing required field: projectName');
154
+ }
155
+ if (!context.version) {
156
+ errors.push('Missing required field: version');
157
+ }
158
+ if (!context.timestamp) {
159
+ errors.push('Missing required field: timestamp');
160
+ }
161
+ if (!context.techStack) {
162
+ errors.push('Missing required field: techStack');
163
+ }
164
+ if (!context.patterns) {
165
+ errors.push('Missing required field: patterns');
166
+ }
167
+ if (!context.rules) {
168
+ errors.push('Missing required field: rules');
169
+ }
170
+ if (!context.definitionOfDone) {
171
+ errors.push('Missing required field: definitionOfDone');
172
+ }
173
+ return {
174
+ valid: errors.length === 0,
175
+ errors,
176
+ };
177
+ }
178
+ /**
179
+ * Create a partial template that can be included in other templates
180
+ */
181
+ registerPartial(name, templateString) {
182
+ this.handlebars.registerPartial(name, templateString);
183
+ }
184
+ /**
185
+ * Register a partial from a file
186
+ */
187
+ async registerPartialFromFile(name, partialPath) {
188
+ const templateSource = await readFile(join(this.config.templatesDir, partialPath), 'utf-8');
189
+ this.handlebars.registerPartial(name, templateSource);
190
+ }
191
+ }
192
+ /**
193
+ * Create a template engine instance with default configuration
194
+ */
195
+ export function createTemplateEngine(config) {
196
+ const defaultConfig = {
197
+ templatesDir: './src/templates',
198
+ outputDir: './',
199
+ tokenLimits: {
200
+ claude: 2000,
201
+ requirements: 4000,
202
+ plan: 6000,
203
+ rules: 1000,
204
+ },
205
+ ...config,
206
+ };
207
+ return new TemplateEngine(defaultConfig);
208
+ }
209
+ //# sourceMappingURL=template-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-engine.js","sourceRoot":"","sources":["../../src/generators/template-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Token Counter and Validator
3
+ *
4
+ * Provides token counting functionality for templates with estimation
5
+ * and limit validation capabilities.
6
+ */
7
+ import type { TokenCountResult } from './types.js';
8
+ /**
9
+ * Approximate token count for text
10
+ * Uses character-based estimation when tokenizer is not available
11
+ *
12
+ * Approximation: ~4 characters per token for English text
13
+ * This is a rough estimate - actual token count depends on the tokenizer used
14
+ */
15
+ export declare function countTokens(text: string): number;
16
+ /**
17
+ * More accurate token count for code
18
+ * Code typically has more tokens per character due to punctuation
19
+ */
20
+ export declare function countCodeTokens(code: string): number;
21
+ /**
22
+ * Count tokens in an array of strings
23
+ */
24
+ export declare function countTokensArray(strings: string[]): number;
25
+ /**
26
+ * Validate token count against limit
27
+ */
28
+ export declare function validateTokenLimit(tokenCount: number, limit: number, tolerance?: number): {
29
+ withinLimit: boolean;
30
+ warnings: string[];
31
+ };
32
+ /**
33
+ * Detailed token count result with metadata
34
+ */
35
+ export declare function getTokenCountDetails(text: string, isCode?: boolean): TokenCountResult;
36
+ /**
37
+ * Check if a file is within token limits
38
+ */
39
+ export declare function checkFileTokenLimit(content: string, filePath: string, limits: Record<string, number>): {
40
+ withinLimit: boolean;
41
+ warnings: string[];
42
+ };
43
+ /**
44
+ * Suggest content reduction strategies
45
+ */
46
+ export declare function suggestReduction(tokenCount: number, limit: number): string[];
47
+ /**
48
+ * Format token count for display
49
+ */
50
+ export declare function formatTokenCount(tokenCount: number): string;
51
+ //# sourceMappingURL=token-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-validator.d.ts","sourceRoot":"","sources":["../../src/generators/token-validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYhD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWpD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAE1D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,MAAY,GACtB;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA4B9C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,OAAe,GAAG,gBAAgB,CAc5F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAqB9C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA0B5E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAK3D"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Token Counter and Validator
3
+ *
4
+ * Provides token counting functionality for templates with estimation
5
+ * and limit validation capabilities.
6
+ */
7
+ /**
8
+ * Approximate token count for text
9
+ * Uses character-based estimation when tokenizer is not available
10
+ *
11
+ * Approximation: ~4 characters per token for English text
12
+ * This is a rough estimate - actual token count depends on the tokenizer used
13
+ */
14
+ export function countTokens(text) {
15
+ if (!text || text.length === 0) {
16
+ return 0;
17
+ }
18
+ // Simple character-based approximation
19
+ // Average token is ~4 characters for English text
20
+ // This is conservative (may overestimate slightly)
21
+ const charCount = text.length;
22
+ const tokenCount = Math.ceil(charCount / 4);
23
+ return tokenCount;
24
+ }
25
+ /**
26
+ * More accurate token count for code
27
+ * Code typically has more tokens per character due to punctuation
28
+ */
29
+ export function countCodeTokens(code) {
30
+ if (!code || code.length === 0) {
31
+ return 0;
32
+ }
33
+ // Code typically has ~3 characters per token
34
+ // Due to operators, punctuation, etc.
35
+ const charCount = code.length;
36
+ const tokenCount = Math.ceil(charCount / 3);
37
+ return tokenCount;
38
+ }
39
+ /**
40
+ * Count tokens in an array of strings
41
+ */
42
+ export function countTokensArray(strings) {
43
+ return strings.reduce((total, str) => total + countTokens(str), 0);
44
+ }
45
+ /**
46
+ * Validate token count against limit
47
+ */
48
+ export function validateTokenLimit(tokenCount, limit, tolerance = 0.1 // 10% tolerance by default
49
+ ) {
50
+ const warnings = [];
51
+ // Check if within limit with tolerance
52
+ const effectiveLimit = limit + Math.floor(limit * tolerance);
53
+ const withinLimit = tokenCount <= effectiveLimit;
54
+ // Generate warnings based on how close we are to limit
55
+ const percentage = (tokenCount / limit) * 100;
56
+ if (percentage > 100) {
57
+ warnings.push(`Token count (${tokenCount}) exceeds limit (${limit}) by ${Math.round(percentage - 100)}%`);
58
+ }
59
+ else if (percentage > 90) {
60
+ warnings.push(`Token count (${tokenCount}) is ${Math.round(percentage)}% of limit (${limit}) - consider reducing content`);
61
+ }
62
+ else if (percentage > 75) {
63
+ warnings.push(`Token count (${tokenCount}) is ${Math.round(percentage)}% of limit (${limit})`);
64
+ }
65
+ return {
66
+ withinLimit,
67
+ warnings,
68
+ };
69
+ }
70
+ /**
71
+ * Detailed token count result with metadata
72
+ */
73
+ export function getTokenCountDetails(text, isCode = false) {
74
+ const warnings = [];
75
+ // Use appropriate counter
76
+ const count = isCode ? countCodeTokens(text) : countTokens(text);
77
+ // Add warning that this is an estimate
78
+ warnings.push('Token count is estimated using character-based approximation');
79
+ return {
80
+ count,
81
+ estimated: true,
82
+ warnings,
83
+ };
84
+ }
85
+ /**
86
+ * Check if a file is within token limits
87
+ */
88
+ export function checkFileTokenLimit(content, filePath, limits) {
89
+ // Determine if this is code
90
+ const isCode = /\.(ts|js|tsx|jsx|py|go|rs|java|cpp|c|h)$/.test(filePath);
91
+ const count = isCode ? countCodeTokens(content) : countTokens(content);
92
+ // Find matching limit
93
+ let limit = 4000; // default
94
+ const fileName = filePath.split('/').pop() || '';
95
+ if (fileName.includes('CLAUDE.md')) {
96
+ limit = limits.claude || 2000;
97
+ }
98
+ else if (fileName.includes('REQUIREMENTS.md')) {
99
+ limit = limits.requirements || 4000;
100
+ }
101
+ else if (fileName.includes('PLAN.md')) {
102
+ limit = limits.plan || 6000;
103
+ }
104
+ else if (filePath.includes('rules/')) {
105
+ limit = limits.rules || 1000;
106
+ }
107
+ return validateTokenLimit(count, limit);
108
+ }
109
+ /**
110
+ * Suggest content reduction strategies
111
+ */
112
+ export function suggestReduction(tokenCount, limit) {
113
+ const suggestions = [];
114
+ const excess = tokenCount - limit;
115
+ if (excess <= 0) {
116
+ return suggestions;
117
+ }
118
+ const excessPercentage = Math.round((excess / limit) * 100);
119
+ // General suggestions
120
+ suggestions.push(`Reduce content by at least ${excess} tokens (${excessPercentage}% over limit)`);
121
+ suggestions.push('Move verbose sections to separate files and reference them');
122
+ suggestions.push('Use bullet points instead of full paragraphs');
123
+ suggestions.push('Remove redundant explanations');
124
+ suggestions.push('Consolidate similar items into lists');
125
+ // Specific suggestions based on file type
126
+ if (excessPercentage > 50) {
127
+ suggestions.push('Consider splitting this into multiple files');
128
+ suggestions.push('Extract detailed examples into a separate "examples" directory');
129
+ }
130
+ return suggestions;
131
+ }
132
+ /**
133
+ * Format token count for display
134
+ */
135
+ export function formatTokenCount(tokenCount) {
136
+ if (tokenCount < 1000) {
137
+ return `${tokenCount} tokens`;
138
+ }
139
+ return `${(tokenCount / 1000).toFixed(1)}k tokens`;
140
+ }
141
+ //# sourceMappingURL=token-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-validator.js","sourceRoot":"","sources":["../../src/generators/token-validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,uCAAuC;IACvC,kDAAkD;IAClD,mDAAmD;IACnD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;IAE5C,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,6CAA6C;IAC7C,sCAAsC;IACtC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;IAE5C,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAiB;IAChD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;AACrE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAAkB,EAClB,KAAa,EACb,YAAoB,GAAG,CAAC,2BAA2B;;IAEnD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,uCAAuC;IACvC,MAAM,cAAc,GAAG,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;IAC7D,MAAM,WAAW,GAAG,UAAU,IAAI,cAAc,CAAC;IAEjD,uDAAuD;IACvD,MAAM,UAAU,GAAG,CAAC,UAAU,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC;IAE9C,IAAI,UAAU,GAAG,GAAG,EAAE,CAAC;QACrB,QAAQ,CAAC,IAAI,CACX,gBAAgB,UAAU,oBAAoB,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC,GAAG,CAC3F,CAAC;IACJ,CAAC;SAAM,IAAI,UAAU,GAAG,EAAE,EAAE,CAAC;QAC3B,QAAQ,CAAC,IAAI,CACX,gBAAgB,UAAU,QAAQ,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,eAAe,KAAK,+BAA+B,CAC5G,CAAC;IACJ,CAAC;SAAM,IAAI,UAAU,GAAG,EAAE,EAAE,CAAC;QAC3B,QAAQ,CAAC,IAAI,CACX,gBAAgB,UAAU,QAAQ,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,eAAe,KAAK,GAAG,CAChF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,WAAW;QACX,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,SAAkB,KAAK;IACxE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,0BAA0B;IAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAEjE,uCAAuC;IACvC,QAAQ,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;IAE9E,OAAO;QACL,KAAK;QACL,SAAS,EAAE,IAAI;QACf,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAe,EACf,QAAgB,EAChB,MAA8B;IAE9B,4BAA4B;IAC5B,MAAM,MAAM,GAAG,0CAA0C,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEzE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAEvE,sBAAsB;IACtB,IAAI,KAAK,GAAG,IAAI,CAAC,CAAC,UAAU;IAC5B,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IAEjD,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACnC,KAAK,GAAG,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC;IAChC,CAAC;SAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAChD,KAAK,GAAG,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC;IACtC,CAAC;SAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACxC,KAAK,GAAG,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC;IAC9B,CAAC;SAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC;IAC/B,CAAC;IAED,OAAO,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAkB,EAAE,KAAa;IAChE,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,MAAM,MAAM,GAAG,UAAU,GAAG,KAAK,CAAC;IAElC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QAChB,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;IAE5D,sBAAsB;IACtB,WAAW,CAAC,IAAI,CACd,8BAA8B,MAAM,YAAY,gBAAgB,eAAe,CAChF,CAAC;IACF,WAAW,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;IAC/E,WAAW,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;IACjE,WAAW,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAClD,WAAW,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IAEzD,0CAA0C;IAC1C,IAAI,gBAAgB,GAAG,EAAE,EAAE,CAAC;QAC1B,WAAW,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QAChE,WAAW,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;IACrF,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,IAAI,UAAU,GAAG,IAAI,EAAE,CAAC;QACtB,OAAO,GAAG,UAAU,SAAS,CAAC;IAChC,CAAC;IACD,OAAO,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;AACrD,CAAC"}