@herb-tools/config 0.8.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/README.md +58 -0
- package/dist/herb-config.cjs +12736 -0
- package/dist/herb-config.cjs.map +1 -0
- package/dist/herb-config.esm.js +12712 -0
- package/dist/herb-config.esm.js.map +1 -0
- package/dist/package.json +49 -0
- package/dist/src/config-schema.js +39 -0
- package/dist/src/config-schema.js.map +1 -0
- package/dist/src/config.js +856 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/merge.js +41 -0
- package/dist/src/merge.js.map +1 -0
- package/dist/src/vscode.js +73 -0
- package/dist/src/vscode.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/config-schema.d.ts +90 -0
- package/dist/types/config.d.ts +348 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/merge.d.ts +11 -0
- package/dist/types/src/config-schema.d.ts +90 -0
- package/dist/types/src/config.d.ts +348 -0
- package/dist/types/src/index.d.ts +5 -0
- package/dist/types/src/merge.d.ts +11 -0
- package/dist/types/src/vscode.d.ts +13 -0
- package/dist/types/vscode.d.ts +13 -0
- package/package.json +49 -0
- package/src/config-schema.ts +51 -0
- package/src/config-template.yml +78 -0
- package/src/config.ts +1105 -0
- package/src/index.ts +17 -0
- package/src/merge.ts +47 -0
- package/src/vscode.ts +96 -0
- package/src/yaml.d.ts +9 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { Config } from "./config.js"
|
|
2
|
+
export { HerbConfigSchema } from "./config-schema.js"
|
|
3
|
+
export { addHerbExtensionRecommendation, getExtensionsJsonRelativePath } from "./vscode.js"
|
|
4
|
+
|
|
5
|
+
export type {
|
|
6
|
+
HerbConfig,
|
|
7
|
+
HerbConfigOptions,
|
|
8
|
+
LinterConfig,
|
|
9
|
+
FormatterConfig,
|
|
10
|
+
RuleConfig,
|
|
11
|
+
FilesConfig,
|
|
12
|
+
LoadOptions,
|
|
13
|
+
FromObjectOptions,
|
|
14
|
+
ConfigValidationError
|
|
15
|
+
} from "./config.js"
|
|
16
|
+
|
|
17
|
+
export type { VSCodeExtensionsJson } from "./vscode.js"
|
package/src/merge.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
type DeepPartial<T> = T extends object ? {
|
|
2
|
+
[P in keyof T]?: DeepPartial<T[P]>;
|
|
3
|
+
} : T;
|
|
4
|
+
|
|
5
|
+
function isObject(item: unknown): item is Record<string, any> {
|
|
6
|
+
return item !== null && typeof item === 'object' && !Array.isArray(item)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Deep merge two objects
|
|
11
|
+
* @param target - The base object (defaults)
|
|
12
|
+
* @param source - The object to merge in (user config)
|
|
13
|
+
* @returns Merged object
|
|
14
|
+
*/
|
|
15
|
+
export function deepMerge<T extends Record<string, any>>(target: T, source: DeepPartial<T>): T {
|
|
16
|
+
const output = { ...target }
|
|
17
|
+
|
|
18
|
+
for (const key in source) {
|
|
19
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
20
|
+
const sourceValue = source[key]
|
|
21
|
+
const targetValue = target[key]
|
|
22
|
+
|
|
23
|
+
if (sourceValue === undefined) {
|
|
24
|
+
continue
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (Array.isArray(sourceValue)) {
|
|
28
|
+
if (key === 'include' && Array.isArray(targetValue)) {
|
|
29
|
+
;(output as any)[key] = [...targetValue, ...sourceValue]
|
|
30
|
+
} else {
|
|
31
|
+
;(output as any)[key] = [...sourceValue]
|
|
32
|
+
}
|
|
33
|
+
continue
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (isObject(sourceValue) && isObject(targetValue)) {
|
|
37
|
+
;(output as any)[key] = deepMerge(targetValue, sourceValue)
|
|
38
|
+
|
|
39
|
+
continue
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
;(output as any)[key] = sourceValue
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return output
|
|
47
|
+
}
|
package/src/vscode.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { join } from "path"
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs"
|
|
3
|
+
|
|
4
|
+
export interface VSCodeExtensionsJson {
|
|
5
|
+
recommendations?: string[]
|
|
6
|
+
unwantedRecommendations?: string[]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const HERB_EXTENSION_ID = "marcoroth.herb-lsp"
|
|
10
|
+
const VSCODE_DIR = ".vscode"
|
|
11
|
+
const EXTENSIONS_FILE = "extensions.json"
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Ensures the .vscode directory exists in the project
|
|
15
|
+
*/
|
|
16
|
+
function ensureVSCodeDirectory(projectPath: string): string {
|
|
17
|
+
const vscodeDir = join(projectPath, VSCODE_DIR)
|
|
18
|
+
|
|
19
|
+
if (!existsSync(vscodeDir)) {
|
|
20
|
+
mkdirSync(vscodeDir, { recursive: true })
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return vscodeDir
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Gets the path to the VSCode extensions.json file
|
|
28
|
+
*/
|
|
29
|
+
function getExtensionsJsonPath(projectPath: string): string {
|
|
30
|
+
const vscodeDir = ensureVSCodeDirectory(projectPath)
|
|
31
|
+
|
|
32
|
+
return join(vscodeDir, EXTENSIONS_FILE)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Reads the current extensions.json file, or returns an empty structure
|
|
37
|
+
*/
|
|
38
|
+
function readExtensionsJson(filePath: string): VSCodeExtensionsJson {
|
|
39
|
+
if (!existsSync(filePath)) {
|
|
40
|
+
return { recommendations: [] }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const content = readFileSync(filePath, "utf-8")
|
|
45
|
+
const parsed = JSON.parse(content)
|
|
46
|
+
|
|
47
|
+
if (!Array.isArray(parsed.recommendations)) {
|
|
48
|
+
parsed.recommendations = []
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return parsed
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.warn(`Warning: Could not parse ${filePath}, creating new file`)
|
|
54
|
+
|
|
55
|
+
return { recommendations: [] }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Writes the extensions.json file with proper formatting
|
|
61
|
+
*/
|
|
62
|
+
function writeExtensionsJson(filePath: string, data: VSCodeExtensionsJson): void {
|
|
63
|
+
const content = JSON.stringify(data, null, 2) + "\n"
|
|
64
|
+
|
|
65
|
+
writeFileSync(filePath, content, "utf-8")
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Adds the Herb VSCode extension to the recommended extensions list
|
|
70
|
+
* Returns true if the extension was added, false if it was already present
|
|
71
|
+
*/
|
|
72
|
+
export function addHerbExtensionRecommendation(projectPath: string): boolean {
|
|
73
|
+
const extensionsPath = getExtensionsJsonPath(projectPath)
|
|
74
|
+
const extensions = readExtensionsJson(extensionsPath)
|
|
75
|
+
|
|
76
|
+
if (extensions.recommendations?.includes(HERB_EXTENSION_ID)) {
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!extensions.recommendations) {
|
|
81
|
+
extensions.recommendations = []
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
extensions.recommendations.push(HERB_EXTENSION_ID)
|
|
85
|
+
|
|
86
|
+
writeExtensionsJson(extensionsPath, extensions)
|
|
87
|
+
|
|
88
|
+
return true
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Gets the relative path to the extensions.json file from the project root
|
|
93
|
+
*/
|
|
94
|
+
export function getExtensionsJsonRelativePath(): string {
|
|
95
|
+
return join(VSCODE_DIR, EXTENSIONS_FILE)
|
|
96
|
+
}
|