@viberails/config 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.
@@ -0,0 +1,314 @@
1
+ import { ConfigRules, ScanResult, ViberailsConfig } from '@viberails/types';
2
+
3
+ /**
4
+ * Default rule thresholds and toggles for a new viberails config.
5
+ * These values are intentionally conservative to build trust on first run.
6
+ */
7
+ declare const DEFAULT_RULES: ConfigRules;
8
+ /**
9
+ * Default glob patterns for files and directories to ignore.
10
+ */
11
+ declare const DEFAULT_IGNORE: string[];
12
+
13
+ /**
14
+ * Generate a ViberailsConfig from scan results.
15
+ *
16
+ * Maps the scanner's DetectedStack, DetectedStructure, and conventions
17
+ * into the config format with smart defaults. Low-confidence conventions
18
+ * are omitted. The project name is derived from the root directory basename.
19
+ *
20
+ * @param scanResult - The output of scanning a project
21
+ * @returns A complete ViberailsConfig ready to be written as JSON
22
+ */
23
+ declare function generateConfig(scanResult: ScanResult): ViberailsConfig;
24
+
25
+ /**
26
+ * Load and parse a viberails config file.
27
+ *
28
+ * Reads the JSON file at the given path, validates that it contains
29
+ * the required fields (version, name, stack, rules), and returns
30
+ * the parsed config.
31
+ *
32
+ * @param configPath - Absolute or relative path to viberails.config.json
33
+ * @returns The parsed ViberailsConfig
34
+ * @throws If the file doesn't exist, contains invalid JSON, or is missing required fields
35
+ */
36
+ declare function loadConfig(configPath: string): Promise<ViberailsConfig>;
37
+ /**
38
+ * Safely load a viberails config file, returning null on any error.
39
+ *
40
+ * Used by the CLI for "does config already exist?" checks where
41
+ * failure is an expected case, not an error.
42
+ *
43
+ * @param configPath - Absolute or relative path to viberails.config.json
44
+ * @returns The parsed ViberailsConfig, or null if loading fails
45
+ */
46
+ declare function loadConfigSafe(configPath: string): Promise<ViberailsConfig | null>;
47
+
48
+ /**
49
+ * Merge a new scan result into an existing config for `viberails sync`.
50
+ *
51
+ * Preserves all developer-confirmed values from the existing config.
52
+ * Adds newly detected conventions with a `_detected: true` annotation
53
+ * so the developer can review them. Never removes rules or values
54
+ * the developer has set.
55
+ *
56
+ * @param existing - The current ViberailsConfig (from viberails.config.json)
57
+ * @param scanResult - Fresh scan results from re-scanning the project
58
+ * @returns A merged config that preserves existing values and adds new detections
59
+ */
60
+ declare function mergeConfig(existing: ViberailsConfig, scanResult: ScanResult): ViberailsConfig;
61
+
62
+ /**
63
+ * JSON Schema (draft-07) definition for viberails.config.json.
64
+ *
65
+ * This schema will eventually be hosted at https://viberails.sh/schema/v1.json.
66
+ * For now it is exported as a TypeScript object that can be serialized to JSON.
67
+ */
68
+ declare const configSchema: {
69
+ readonly $schema: "http://json-schema.org/draft-07/schema#";
70
+ readonly $id: "https://viberails.sh/schema/v1.json";
71
+ readonly title: "viberails configuration";
72
+ readonly description: "Configuration file for viberails — guardrails for vibe coding.";
73
+ readonly type: "object";
74
+ readonly required: readonly ["version", "name", "stack", "rules"];
75
+ readonly properties: {
76
+ readonly $schema: {
77
+ readonly type: "string";
78
+ readonly description: "JSON Schema URL for editor validation.";
79
+ };
80
+ readonly version: {
81
+ readonly type: "number";
82
+ readonly const: 1;
83
+ readonly description: "Config format version. Always 1 for V1.0.";
84
+ };
85
+ readonly name: {
86
+ readonly type: "string";
87
+ readonly description: "Project name, typically from package.json.";
88
+ };
89
+ readonly enforcement: {
90
+ readonly type: "string";
91
+ readonly enum: readonly ["warn", "enforce"];
92
+ readonly default: "warn";
93
+ readonly description: "Whether conventions are warned about or enforced as errors.";
94
+ };
95
+ readonly stack: {
96
+ readonly type: "object";
97
+ readonly required: readonly ["language", "packageManager"];
98
+ readonly properties: {
99
+ readonly framework: {
100
+ readonly type: "string";
101
+ readonly description: "Primary framework identifier (e.g. \"nextjs@15\", \"remix@2\").";
102
+ };
103
+ readonly language: {
104
+ readonly type: "string";
105
+ readonly description: "Primary language (e.g. \"typescript\", \"javascript\").";
106
+ };
107
+ readonly styling: {
108
+ readonly type: "string";
109
+ readonly description: "Styling solution (e.g. \"tailwindcss@4\", \"css-modules\").";
110
+ };
111
+ readonly backend: {
112
+ readonly type: "string";
113
+ readonly description: "Backend framework (e.g. \"express@5\", \"fastify\").";
114
+ };
115
+ readonly packageManager: {
116
+ readonly type: "string";
117
+ readonly description: "Package manager (e.g. \"pnpm\", \"npm\", \"yarn\").";
118
+ };
119
+ readonly linter: {
120
+ readonly type: "string";
121
+ readonly description: "Linter (e.g. \"eslint@9\", \"biome\").";
122
+ };
123
+ readonly testRunner: {
124
+ readonly type: "string";
125
+ readonly description: "Test runner (e.g. \"vitest\", \"jest\").";
126
+ };
127
+ };
128
+ readonly additionalProperties: false;
129
+ readonly description: "Detected or configured technology stack.";
130
+ };
131
+ readonly structure: {
132
+ readonly type: "object";
133
+ readonly properties: {
134
+ readonly srcDir: {
135
+ readonly type: "string";
136
+ readonly description: "Source directory (e.g. \"src\"), or omit for flat structure.";
137
+ };
138
+ readonly pages: {
139
+ readonly type: "string";
140
+ readonly description: "Pages or routes directory (e.g. \"src/app\").";
141
+ };
142
+ readonly components: {
143
+ readonly type: "string";
144
+ readonly description: "Components directory (e.g. \"src/components\").";
145
+ };
146
+ readonly hooks: {
147
+ readonly type: "string";
148
+ readonly description: "Hooks directory (e.g. \"src/hooks\").";
149
+ };
150
+ readonly utils: {
151
+ readonly type: "string";
152
+ readonly description: "Utilities directory (e.g. \"src/utils\", \"src/lib\").";
153
+ };
154
+ readonly types: {
155
+ readonly type: "string";
156
+ readonly description: "Type definitions directory (e.g. \"src/types\").";
157
+ };
158
+ readonly tests: {
159
+ readonly type: "string";
160
+ readonly description: "Tests directory (e.g. \"tests\", \"__tests__\").";
161
+ };
162
+ readonly testPattern: {
163
+ readonly type: "string";
164
+ readonly description: "Test file naming pattern (e.g. \"*.test.ts\", \"*.spec.ts\").";
165
+ };
166
+ };
167
+ readonly additionalProperties: false;
168
+ readonly description: "Detected or configured directory structure.";
169
+ };
170
+ readonly conventions: {
171
+ readonly type: "object";
172
+ readonly properties: {
173
+ readonly fileNaming: {
174
+ readonly $ref: "#/definitions/conventionValue";
175
+ };
176
+ readonly componentNaming: {
177
+ readonly $ref: "#/definitions/conventionValue";
178
+ };
179
+ readonly hookNaming: {
180
+ readonly $ref: "#/definitions/conventionValue";
181
+ };
182
+ readonly importAlias: {
183
+ readonly $ref: "#/definitions/conventionValue";
184
+ };
185
+ };
186
+ readonly additionalProperties: false;
187
+ readonly description: "Detected or configured coding conventions.";
188
+ };
189
+ readonly rules: {
190
+ readonly type: "object";
191
+ readonly required: readonly ["maxFileLines", "maxFunctionLines", "requireTests", "enforceNaming", "enforceBoundaries"];
192
+ readonly properties: {
193
+ readonly maxFileLines: {
194
+ readonly type: "number";
195
+ readonly default: 300;
196
+ readonly description: "Maximum number of lines allowed per file.";
197
+ };
198
+ readonly maxFunctionLines: {
199
+ readonly type: "number";
200
+ readonly default: 50;
201
+ readonly description: "Maximum number of lines allowed per function.";
202
+ };
203
+ readonly requireTests: {
204
+ readonly type: "boolean";
205
+ readonly default: true;
206
+ readonly description: "Whether to require test files for source modules.";
207
+ };
208
+ readonly enforceNaming: {
209
+ readonly type: "boolean";
210
+ readonly default: true;
211
+ readonly description: "Whether to enforce detected file naming conventions.";
212
+ };
213
+ readonly enforceBoundaries: {
214
+ readonly type: "boolean";
215
+ readonly default: false;
216
+ readonly description: "Whether to enforce module boundary rules.";
217
+ };
218
+ };
219
+ readonly additionalProperties: false;
220
+ readonly description: "Rule thresholds and toggles for enforcement.";
221
+ };
222
+ readonly ignore: {
223
+ readonly type: "array";
224
+ readonly items: {
225
+ readonly type: "string";
226
+ };
227
+ readonly description: "Glob patterns for files and directories to ignore.";
228
+ };
229
+ readonly boundaries: {
230
+ readonly type: "array";
231
+ readonly items: {
232
+ readonly type: "object";
233
+ readonly required: readonly ["from", "to", "allow"];
234
+ readonly properties: {
235
+ readonly from: {
236
+ readonly type: "string";
237
+ readonly description: "Source package or directory pattern.";
238
+ };
239
+ readonly to: {
240
+ readonly type: "string";
241
+ readonly description: "Target package or directory pattern.";
242
+ };
243
+ readonly allow: {
244
+ readonly type: "boolean";
245
+ readonly description: "Whether this import direction is allowed or disallowed.";
246
+ };
247
+ readonly reason: {
248
+ readonly type: "string";
249
+ readonly description: "Human-readable explanation of why this boundary exists.";
250
+ };
251
+ };
252
+ readonly additionalProperties: false;
253
+ };
254
+ readonly description: "Module boundary rules for import enforcement.";
255
+ };
256
+ readonly workspace: {
257
+ readonly type: "object";
258
+ readonly required: readonly ["packages", "isMonorepo"];
259
+ readonly properties: {
260
+ readonly packages: {
261
+ readonly type: "array";
262
+ readonly items: {
263
+ readonly type: "string";
264
+ };
265
+ readonly description: "Relative paths to workspace packages.";
266
+ };
267
+ readonly isMonorepo: {
268
+ readonly type: "boolean";
269
+ readonly description: "Whether this project is a monorepo with multiple packages.";
270
+ };
271
+ };
272
+ readonly additionalProperties: false;
273
+ readonly description: "Workspace configuration for monorepo projects.";
274
+ };
275
+ };
276
+ readonly additionalProperties: false;
277
+ readonly definitions: {
278
+ readonly conventionValue: {
279
+ readonly description: "A convention value — either a plain string (user-confirmed) or an object with scanner metadata.";
280
+ readonly oneOf: readonly [{
281
+ readonly type: "string";
282
+ }, {
283
+ readonly type: "object";
284
+ readonly required: readonly ["value", "_confidence", "_consistency"];
285
+ readonly properties: {
286
+ readonly value: {
287
+ readonly type: "string";
288
+ readonly description: "The convention value.";
289
+ };
290
+ readonly _confidence: {
291
+ readonly type: "string";
292
+ readonly enum: readonly ["high", "medium", "low"];
293
+ readonly description: "Scanner confidence level.";
294
+ };
295
+ readonly _consistency: {
296
+ readonly type: "number";
297
+ readonly minimum: 0;
298
+ readonly maximum: 100;
299
+ readonly description: "Scanner consistency percentage.";
300
+ };
301
+ readonly _detected: {
302
+ readonly type: "boolean";
303
+ readonly description: "Set by mergeConfig when a convention is newly detected during sync.";
304
+ };
305
+ };
306
+ readonly additionalProperties: false;
307
+ }];
308
+ };
309
+ };
310
+ };
311
+
312
+ declare const VERSION = "0.1.0";
313
+
314
+ export { DEFAULT_IGNORE, DEFAULT_RULES, VERSION, configSchema, generateConfig, loadConfig, loadConfigSafe, mergeConfig };
@@ -0,0 +1,314 @@
1
+ import { ConfigRules, ScanResult, ViberailsConfig } from '@viberails/types';
2
+
3
+ /**
4
+ * Default rule thresholds and toggles for a new viberails config.
5
+ * These values are intentionally conservative to build trust on first run.
6
+ */
7
+ declare const DEFAULT_RULES: ConfigRules;
8
+ /**
9
+ * Default glob patterns for files and directories to ignore.
10
+ */
11
+ declare const DEFAULT_IGNORE: string[];
12
+
13
+ /**
14
+ * Generate a ViberailsConfig from scan results.
15
+ *
16
+ * Maps the scanner's DetectedStack, DetectedStructure, and conventions
17
+ * into the config format with smart defaults. Low-confidence conventions
18
+ * are omitted. The project name is derived from the root directory basename.
19
+ *
20
+ * @param scanResult - The output of scanning a project
21
+ * @returns A complete ViberailsConfig ready to be written as JSON
22
+ */
23
+ declare function generateConfig(scanResult: ScanResult): ViberailsConfig;
24
+
25
+ /**
26
+ * Load and parse a viberails config file.
27
+ *
28
+ * Reads the JSON file at the given path, validates that it contains
29
+ * the required fields (version, name, stack, rules), and returns
30
+ * the parsed config.
31
+ *
32
+ * @param configPath - Absolute or relative path to viberails.config.json
33
+ * @returns The parsed ViberailsConfig
34
+ * @throws If the file doesn't exist, contains invalid JSON, or is missing required fields
35
+ */
36
+ declare function loadConfig(configPath: string): Promise<ViberailsConfig>;
37
+ /**
38
+ * Safely load a viberails config file, returning null on any error.
39
+ *
40
+ * Used by the CLI for "does config already exist?" checks where
41
+ * failure is an expected case, not an error.
42
+ *
43
+ * @param configPath - Absolute or relative path to viberails.config.json
44
+ * @returns The parsed ViberailsConfig, or null if loading fails
45
+ */
46
+ declare function loadConfigSafe(configPath: string): Promise<ViberailsConfig | null>;
47
+
48
+ /**
49
+ * Merge a new scan result into an existing config for `viberails sync`.
50
+ *
51
+ * Preserves all developer-confirmed values from the existing config.
52
+ * Adds newly detected conventions with a `_detected: true` annotation
53
+ * so the developer can review them. Never removes rules or values
54
+ * the developer has set.
55
+ *
56
+ * @param existing - The current ViberailsConfig (from viberails.config.json)
57
+ * @param scanResult - Fresh scan results from re-scanning the project
58
+ * @returns A merged config that preserves existing values and adds new detections
59
+ */
60
+ declare function mergeConfig(existing: ViberailsConfig, scanResult: ScanResult): ViberailsConfig;
61
+
62
+ /**
63
+ * JSON Schema (draft-07) definition for viberails.config.json.
64
+ *
65
+ * This schema will eventually be hosted at https://viberails.sh/schema/v1.json.
66
+ * For now it is exported as a TypeScript object that can be serialized to JSON.
67
+ */
68
+ declare const configSchema: {
69
+ readonly $schema: "http://json-schema.org/draft-07/schema#";
70
+ readonly $id: "https://viberails.sh/schema/v1.json";
71
+ readonly title: "viberails configuration";
72
+ readonly description: "Configuration file for viberails — guardrails for vibe coding.";
73
+ readonly type: "object";
74
+ readonly required: readonly ["version", "name", "stack", "rules"];
75
+ readonly properties: {
76
+ readonly $schema: {
77
+ readonly type: "string";
78
+ readonly description: "JSON Schema URL for editor validation.";
79
+ };
80
+ readonly version: {
81
+ readonly type: "number";
82
+ readonly const: 1;
83
+ readonly description: "Config format version. Always 1 for V1.0.";
84
+ };
85
+ readonly name: {
86
+ readonly type: "string";
87
+ readonly description: "Project name, typically from package.json.";
88
+ };
89
+ readonly enforcement: {
90
+ readonly type: "string";
91
+ readonly enum: readonly ["warn", "enforce"];
92
+ readonly default: "warn";
93
+ readonly description: "Whether conventions are warned about or enforced as errors.";
94
+ };
95
+ readonly stack: {
96
+ readonly type: "object";
97
+ readonly required: readonly ["language", "packageManager"];
98
+ readonly properties: {
99
+ readonly framework: {
100
+ readonly type: "string";
101
+ readonly description: "Primary framework identifier (e.g. \"nextjs@15\", \"remix@2\").";
102
+ };
103
+ readonly language: {
104
+ readonly type: "string";
105
+ readonly description: "Primary language (e.g. \"typescript\", \"javascript\").";
106
+ };
107
+ readonly styling: {
108
+ readonly type: "string";
109
+ readonly description: "Styling solution (e.g. \"tailwindcss@4\", \"css-modules\").";
110
+ };
111
+ readonly backend: {
112
+ readonly type: "string";
113
+ readonly description: "Backend framework (e.g. \"express@5\", \"fastify\").";
114
+ };
115
+ readonly packageManager: {
116
+ readonly type: "string";
117
+ readonly description: "Package manager (e.g. \"pnpm\", \"npm\", \"yarn\").";
118
+ };
119
+ readonly linter: {
120
+ readonly type: "string";
121
+ readonly description: "Linter (e.g. \"eslint@9\", \"biome\").";
122
+ };
123
+ readonly testRunner: {
124
+ readonly type: "string";
125
+ readonly description: "Test runner (e.g. \"vitest\", \"jest\").";
126
+ };
127
+ };
128
+ readonly additionalProperties: false;
129
+ readonly description: "Detected or configured technology stack.";
130
+ };
131
+ readonly structure: {
132
+ readonly type: "object";
133
+ readonly properties: {
134
+ readonly srcDir: {
135
+ readonly type: "string";
136
+ readonly description: "Source directory (e.g. \"src\"), or omit for flat structure.";
137
+ };
138
+ readonly pages: {
139
+ readonly type: "string";
140
+ readonly description: "Pages or routes directory (e.g. \"src/app\").";
141
+ };
142
+ readonly components: {
143
+ readonly type: "string";
144
+ readonly description: "Components directory (e.g. \"src/components\").";
145
+ };
146
+ readonly hooks: {
147
+ readonly type: "string";
148
+ readonly description: "Hooks directory (e.g. \"src/hooks\").";
149
+ };
150
+ readonly utils: {
151
+ readonly type: "string";
152
+ readonly description: "Utilities directory (e.g. \"src/utils\", \"src/lib\").";
153
+ };
154
+ readonly types: {
155
+ readonly type: "string";
156
+ readonly description: "Type definitions directory (e.g. \"src/types\").";
157
+ };
158
+ readonly tests: {
159
+ readonly type: "string";
160
+ readonly description: "Tests directory (e.g. \"tests\", \"__tests__\").";
161
+ };
162
+ readonly testPattern: {
163
+ readonly type: "string";
164
+ readonly description: "Test file naming pattern (e.g. \"*.test.ts\", \"*.spec.ts\").";
165
+ };
166
+ };
167
+ readonly additionalProperties: false;
168
+ readonly description: "Detected or configured directory structure.";
169
+ };
170
+ readonly conventions: {
171
+ readonly type: "object";
172
+ readonly properties: {
173
+ readonly fileNaming: {
174
+ readonly $ref: "#/definitions/conventionValue";
175
+ };
176
+ readonly componentNaming: {
177
+ readonly $ref: "#/definitions/conventionValue";
178
+ };
179
+ readonly hookNaming: {
180
+ readonly $ref: "#/definitions/conventionValue";
181
+ };
182
+ readonly importAlias: {
183
+ readonly $ref: "#/definitions/conventionValue";
184
+ };
185
+ };
186
+ readonly additionalProperties: false;
187
+ readonly description: "Detected or configured coding conventions.";
188
+ };
189
+ readonly rules: {
190
+ readonly type: "object";
191
+ readonly required: readonly ["maxFileLines", "maxFunctionLines", "requireTests", "enforceNaming", "enforceBoundaries"];
192
+ readonly properties: {
193
+ readonly maxFileLines: {
194
+ readonly type: "number";
195
+ readonly default: 300;
196
+ readonly description: "Maximum number of lines allowed per file.";
197
+ };
198
+ readonly maxFunctionLines: {
199
+ readonly type: "number";
200
+ readonly default: 50;
201
+ readonly description: "Maximum number of lines allowed per function.";
202
+ };
203
+ readonly requireTests: {
204
+ readonly type: "boolean";
205
+ readonly default: true;
206
+ readonly description: "Whether to require test files for source modules.";
207
+ };
208
+ readonly enforceNaming: {
209
+ readonly type: "boolean";
210
+ readonly default: true;
211
+ readonly description: "Whether to enforce detected file naming conventions.";
212
+ };
213
+ readonly enforceBoundaries: {
214
+ readonly type: "boolean";
215
+ readonly default: false;
216
+ readonly description: "Whether to enforce module boundary rules.";
217
+ };
218
+ };
219
+ readonly additionalProperties: false;
220
+ readonly description: "Rule thresholds and toggles for enforcement.";
221
+ };
222
+ readonly ignore: {
223
+ readonly type: "array";
224
+ readonly items: {
225
+ readonly type: "string";
226
+ };
227
+ readonly description: "Glob patterns for files and directories to ignore.";
228
+ };
229
+ readonly boundaries: {
230
+ readonly type: "array";
231
+ readonly items: {
232
+ readonly type: "object";
233
+ readonly required: readonly ["from", "to", "allow"];
234
+ readonly properties: {
235
+ readonly from: {
236
+ readonly type: "string";
237
+ readonly description: "Source package or directory pattern.";
238
+ };
239
+ readonly to: {
240
+ readonly type: "string";
241
+ readonly description: "Target package or directory pattern.";
242
+ };
243
+ readonly allow: {
244
+ readonly type: "boolean";
245
+ readonly description: "Whether this import direction is allowed or disallowed.";
246
+ };
247
+ readonly reason: {
248
+ readonly type: "string";
249
+ readonly description: "Human-readable explanation of why this boundary exists.";
250
+ };
251
+ };
252
+ readonly additionalProperties: false;
253
+ };
254
+ readonly description: "Module boundary rules for import enforcement.";
255
+ };
256
+ readonly workspace: {
257
+ readonly type: "object";
258
+ readonly required: readonly ["packages", "isMonorepo"];
259
+ readonly properties: {
260
+ readonly packages: {
261
+ readonly type: "array";
262
+ readonly items: {
263
+ readonly type: "string";
264
+ };
265
+ readonly description: "Relative paths to workspace packages.";
266
+ };
267
+ readonly isMonorepo: {
268
+ readonly type: "boolean";
269
+ readonly description: "Whether this project is a monorepo with multiple packages.";
270
+ };
271
+ };
272
+ readonly additionalProperties: false;
273
+ readonly description: "Workspace configuration for monorepo projects.";
274
+ };
275
+ };
276
+ readonly additionalProperties: false;
277
+ readonly definitions: {
278
+ readonly conventionValue: {
279
+ readonly description: "A convention value — either a plain string (user-confirmed) or an object with scanner metadata.";
280
+ readonly oneOf: readonly [{
281
+ readonly type: "string";
282
+ }, {
283
+ readonly type: "object";
284
+ readonly required: readonly ["value", "_confidence", "_consistency"];
285
+ readonly properties: {
286
+ readonly value: {
287
+ readonly type: "string";
288
+ readonly description: "The convention value.";
289
+ };
290
+ readonly _confidence: {
291
+ readonly type: "string";
292
+ readonly enum: readonly ["high", "medium", "low"];
293
+ readonly description: "Scanner confidence level.";
294
+ };
295
+ readonly _consistency: {
296
+ readonly type: "number";
297
+ readonly minimum: 0;
298
+ readonly maximum: 100;
299
+ readonly description: "Scanner consistency percentage.";
300
+ };
301
+ readonly _detected: {
302
+ readonly type: "boolean";
303
+ readonly description: "Set by mergeConfig when a convention is newly detected during sync.";
304
+ };
305
+ };
306
+ readonly additionalProperties: false;
307
+ }];
308
+ };
309
+ };
310
+ };
311
+
312
+ declare const VERSION = "0.1.0";
313
+
314
+ export { DEFAULT_IGNORE, DEFAULT_RULES, VERSION, configSchema, generateConfig, loadConfig, loadConfigSafe, mergeConfig };