@grunnverk/kilde 0.1.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.
Files changed (75) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +31 -0
  3. package/.github/pull_request_template.md +48 -0
  4. package/.github/workflows/deploy-docs.yml +59 -0
  5. package/.github/workflows/npm-publish.yml +48 -0
  6. package/.github/workflows/test.yml +48 -0
  7. package/CHANGELOG.md +92 -0
  8. package/CONTRIBUTING.md +438 -0
  9. package/LICENSE +190 -0
  10. package/PROJECT_SUMMARY.md +318 -0
  11. package/README.md +444 -0
  12. package/RELEASE_CHECKLIST.md +182 -0
  13. package/dist/application.js +166 -0
  14. package/dist/application.js.map +1 -0
  15. package/dist/commands/release.js +326 -0
  16. package/dist/commands/release.js.map +1 -0
  17. package/dist/constants.js +122 -0
  18. package/dist/constants.js.map +1 -0
  19. package/dist/logging.js +176 -0
  20. package/dist/logging.js.map +1 -0
  21. package/dist/main.js +24 -0
  22. package/dist/main.js.map +1 -0
  23. package/dist/mcp-server.js +17467 -0
  24. package/dist/mcp-server.js.map +7 -0
  25. package/dist/utils/config.js +89 -0
  26. package/dist/utils/config.js.map +1 -0
  27. package/docs/AI_GUIDE.md +618 -0
  28. package/eslint.config.mjs +85 -0
  29. package/guide/architecture.md +776 -0
  30. package/guide/commands.md +580 -0
  31. package/guide/configuration.md +779 -0
  32. package/guide/mcp-integration.md +708 -0
  33. package/guide/overview.md +225 -0
  34. package/package.json +91 -0
  35. package/scripts/build-mcp.js +115 -0
  36. package/scripts/test-mcp-compliance.js +254 -0
  37. package/src/application.ts +246 -0
  38. package/src/commands/release.ts +450 -0
  39. package/src/constants.ts +162 -0
  40. package/src/logging.ts +210 -0
  41. package/src/main.ts +25 -0
  42. package/src/mcp/prompts/index.ts +98 -0
  43. package/src/mcp/resources.ts +121 -0
  44. package/src/mcp/server.ts +195 -0
  45. package/src/mcp/tools.ts +219 -0
  46. package/src/types.ts +131 -0
  47. package/src/utils/config.ts +181 -0
  48. package/tests/application.test.ts +114 -0
  49. package/tests/commands/commit.test.ts +248 -0
  50. package/tests/commands/release.test.ts +325 -0
  51. package/tests/constants.test.ts +118 -0
  52. package/tests/logging.test.ts +142 -0
  53. package/tests/mcp/prompts/index.test.ts +202 -0
  54. package/tests/mcp/resources.test.ts +166 -0
  55. package/tests/mcp/tools.test.ts +211 -0
  56. package/tests/utils/config.test.ts +212 -0
  57. package/tsconfig.json +32 -0
  58. package/vite.config.ts +107 -0
  59. package/vitest.config.ts +40 -0
  60. package/website/index.html +14 -0
  61. package/website/src/App.css +142 -0
  62. package/website/src/App.tsx +34 -0
  63. package/website/src/components/Commands.tsx +182 -0
  64. package/website/src/components/Configuration.tsx +214 -0
  65. package/website/src/components/Examples.tsx +234 -0
  66. package/website/src/components/Footer.css +99 -0
  67. package/website/src/components/Footer.tsx +93 -0
  68. package/website/src/components/GettingStarted.tsx +94 -0
  69. package/website/src/components/Hero.css +95 -0
  70. package/website/src/components/Hero.tsx +50 -0
  71. package/website/src/components/Navigation.css +102 -0
  72. package/website/src/components/Navigation.tsx +57 -0
  73. package/website/src/index.css +36 -0
  74. package/website/src/main.tsx +10 -0
  75. package/website/vite.config.ts +12 -0
@@ -0,0 +1,89 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import yaml from 'js-yaml';
4
+ import { getLogger } from '../logging.js';
5
+ import { KILDE_DEFAULTS } from '../constants.js';
6
+
7
+ const CONFIG_FILES = [
8
+ '.kilde/config.yaml',
9
+ '.kilde/config.yml',
10
+ '.kilderc.yaml',
11
+ '.kilderc.yml',
12
+ '.kilderc.json',
13
+ 'kilde.config.json'
14
+ ];
15
+ /**
16
+ * Load configuration from file
17
+ */ async function loadConfig(cwd = process.cwd()) {
18
+ const logger = getLogger();
19
+ for (const filename of CONFIG_FILES){
20
+ const configPath = path.join(cwd, filename);
21
+ try {
22
+ const content = await fs.readFile(configPath, 'utf-8');
23
+ let config;
24
+ if (filename.endsWith('.json')) {
25
+ config = JSON.parse(content);
26
+ } else if (filename.endsWith('.yaml') || filename.endsWith('.yml')) {
27
+ config = yaml.load(content);
28
+ } else {
29
+ // Try JSON first, then YAML
30
+ try {
31
+ config = JSON.parse(content);
32
+ } catch {
33
+ config = yaml.load(content);
34
+ }
35
+ }
36
+ // Return config as-is
37
+ logger.verbose(`Loaded configuration from ${configPath}`);
38
+ return config;
39
+ } catch (error) {
40
+ if (error.code !== 'ENOENT') {
41
+ logger.warn(`CONFIG_LOAD_FAILED: Failed to load configuration file | Path: ${configPath} | Error: ${error.message} | Action: Using defaults`);
42
+ }
43
+ }
44
+ }
45
+ logger.verbose('No configuration file found, using defaults');
46
+ return null;
47
+ }
48
+ /**
49
+ * Get default configuration
50
+ */ function getDefaultConfig() {
51
+ return KILDE_DEFAULTS;
52
+ }
53
+ /**
54
+ * Deep merge two objects
55
+ */ function deepMerge(target, source) {
56
+ const result = {
57
+ ...target
58
+ };
59
+ for(const key in source){
60
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
61
+ const sourceValue = source[key];
62
+ const targetValue = result[key];
63
+ if (sourceValue && typeof sourceValue === 'object' && !Array.isArray(sourceValue) && targetValue && typeof targetValue === 'object' && !Array.isArray(targetValue)) {
64
+ result[key] = deepMerge(targetValue, sourceValue);
65
+ } else if (sourceValue !== undefined) {
66
+ result[key] = sourceValue;
67
+ }
68
+ }
69
+ }
70
+ return result;
71
+ }
72
+ /**
73
+ * Merge loaded config with defaults
74
+ */ function mergeWithDefaults(config) {
75
+ const defaults = getDefaultConfig();
76
+ if (!config) {
77
+ return defaults;
78
+ }
79
+ return deepMerge(defaults, config);
80
+ }
81
+ /**
82
+ * Get effective configuration (loaded + defaults)
83
+ */ async function getEffectiveConfig(cwd = process.cwd()) {
84
+ const loaded = await loadConfig(cwd);
85
+ return mergeWithDefaults(loaded);
86
+ }
87
+
88
+ export { getDefaultConfig, getEffectiveConfig, loadConfig, mergeWithDefaults };
89
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sources":["../../src/utils/config.ts"],"sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\nimport yaml from 'js-yaml';\nimport { getLogger } from '../logging';\nimport { Config } from '@grunnverk/core';\nimport { KILDE_DEFAULTS } from '../constants';\n\nconst CONFIG_FILES = [\n '.kilde/config.yaml',\n '.kilde/config.yml',\n '.kilderc.yaml',\n '.kilderc.yml',\n '.kilderc.json',\n 'kilde.config.json',\n];\n\n/**\n * Load configuration from file\n */\nexport async function loadConfig(cwd: string = process.cwd()): Promise<Config | null> {\n const logger = getLogger();\n\n for (const filename of CONFIG_FILES) {\n const configPath = path.join(cwd, filename);\n\n try {\n const content = await fs.readFile(configPath, 'utf-8');\n\n let config: any;\n if (filename.endsWith('.json')) {\n config = JSON.parse(content);\n } else if (filename.endsWith('.yaml') || filename.endsWith('.yml')) {\n config = yaml.load(content);\n } else {\n // Try JSON first, then YAML\n try {\n config = JSON.parse(content);\n } catch {\n config = yaml.load(content);\n }\n }\n\n // Return config as-is\n logger.verbose(`Loaded configuration from ${configPath}`);\n return config as Config;\n } catch (error: any) {\n if (error.code !== 'ENOENT') {\n logger.warn(`CONFIG_LOAD_FAILED: Failed to load configuration file | Path: ${configPath} | Error: ${error.message} | Action: Using defaults`);\n }\n }\n }\n\n logger.verbose('No configuration file found, using defaults');\n return null;\n}\n\n/**\n * Get default configuration\n */\nexport function getDefaultConfig(): Config {\n return KILDE_DEFAULTS;\n}\n\n/**\n * Deep merge two objects\n */\nfunction deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n const sourceValue = source[key];\n const targetValue = result[key];\n\n if (sourceValue && typeof sourceValue === 'object' && !Array.isArray(sourceValue) &&\n targetValue && typeof targetValue === 'object' && !Array.isArray(targetValue)) {\n result[key] = deepMerge(targetValue, sourceValue) as any;\n } else if (sourceValue !== undefined) {\n result[key] = sourceValue as any;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Merge loaded config with defaults\n */\nexport function mergeWithDefaults(config: Config | null): Config {\n const defaults = getDefaultConfig();\n\n if (!config) {\n return defaults;\n }\n\n return deepMerge(defaults, config);\n}\n\n/**\n * Get effective configuration (loaded + defaults)\n */\nexport async function getEffectiveConfig(cwd: string = process.cwd()): Promise<Config> {\n const loaded = await loadConfig(cwd);\n return mergeWithDefaults(loaded);\n}\n\n/**\n * Create a sample configuration file\n */\nexport function createSampleConfig(): string {\n const config = {\n // Global settings\n verbose: false,\n debug: false,\n model: 'gpt-4o-mini',\n openaiReasoning: 'low',\n outputDirectory: 'output/kilde',\n\n // Commit configuration\n commit: {\n sendit: false,\n interactive: false,\n messageLimit: 3,\n maxDiffBytes: 20480,\n },\n\n // Release configuration\n release: {\n interactive: false,\n messageLimit: 3,\n maxDiffBytes: 20480,\n },\n };\n\n return yaml.dump(config, {\n indent: 2,\n lineWidth: 100,\n noRefs: true,\n });\n}\n\n/**\n * Save sample configuration to file\n */\nexport async function saveSampleConfig(cwd: string = process.cwd()): Promise<string> {\n const logger = getLogger();\n const configDir = path.join(cwd, '.kilde');\n const configPath = path.join(configDir, 'config.yaml');\n\n try {\n // Create directory if it doesn't exist\n await fs.mkdir(configDir, { recursive: true });\n\n // Write sample config\n const sampleConfig = createSampleConfig();\n await fs.writeFile(configPath, sampleConfig, 'utf-8');\n\n logger.info(`Created sample configuration file at ${configPath}`);\n return configPath;\n } catch (error: any) {\n logger.error(`Failed to create sample configuration: ${error.message}`);\n throw error;\n }\n}\n\n/**\n * Check if configuration file exists\n */\nexport async function configFileExists(cwd: string = process.cwd()): Promise<boolean> {\n for (const filename of CONFIG_FILES) {\n const configPath = path.join(cwd, filename);\n try {\n await fs.access(configPath);\n return true;\n } catch {\n // File doesn't exist, continue checking\n }\n }\n return false;\n}\n"],"names":["CONFIG_FILES","loadConfig","cwd","process","logger","getLogger","filename","configPath","path","join","content","fs","readFile","config","endsWith","JSON","parse","yaml","load","verbose","error","code","warn","message","getDefaultConfig","KILDE_DEFAULTS","deepMerge","target","source","result","key","Object","prototype","hasOwnProperty","call","sourceValue","targetValue","Array","isArray","undefined","mergeWithDefaults","defaults","getEffectiveConfig","loaded"],"mappings":"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"}