@likec4/config 1.44.0 → 1.46.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/dist/index.d.mts +23 -9
- package/dist/index.mjs +1 -1
- package/dist/node/index.d.mts +1 -1
- package/dist/node/index.mjs +2 -2
- package/dist/shared/{config.FegrYs1S.mjs → config.CUC_rqhf.mjs} +76 -14
- package/package.json +12 -12
- package/schema.json +41 -5
- package/src/index.ts +7 -1
- package/src/schema.image-alias.ts +3 -3
- package/src/schema.include.ts +97 -0
- package/src/schema.theme.ts +2 -2
- package/src/schema.ts +12 -13
package/dist/index.d.mts
CHANGED
|
@@ -7,13 +7,18 @@ import * as z from 'zod';
|
|
|
7
7
|
import { ElementColorValues, RelationshipColorValues, ThemeColorValues, ColorLiteral } from '@likec4/core/styles';
|
|
8
8
|
|
|
9
9
|
declare const ManualLayoutsConfigSchema: z.ZodObject<{
|
|
10
|
-
outDir: z.ZodString
|
|
10
|
+
outDir: z.ZodDefault<z.ZodString>;
|
|
11
11
|
}, z.core.$strip>;
|
|
12
12
|
declare const LikeC4ProjectJsonConfigSchema: z.ZodObject<{
|
|
13
13
|
name: z.ZodString;
|
|
14
14
|
title: z.ZodOptional<z.ZodString>;
|
|
15
15
|
contactPerson: z.ZodOptional<z.ZodString>;
|
|
16
16
|
imageAliases: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
17
|
+
include: z.ZodOptional<z.ZodObject<{
|
|
18
|
+
paths: z.ZodArray<z.ZodString>;
|
|
19
|
+
maxDepth: z.ZodDefault<z.ZodNumber>;
|
|
20
|
+
fileThreshold: z.ZodDefault<z.ZodNumber>;
|
|
21
|
+
}, z.core.$strip>>;
|
|
17
22
|
styles: z.ZodOptional<z.ZodPipe<z.ZodObject<{
|
|
18
23
|
theme: z.ZodOptional<z.ZodPipe<z.ZodObject<{
|
|
19
24
|
colors: z.ZodOptional<z.ZodUnion<readonly [z.ZodRecord<z.ZodPipe<z.ZodUnion<readonly [z.ZodLiteral<"amber" | "blue" | "gray" | "slate" | "green" | "indigo" | "muted" | "primary" | "red" | "secondary" | "sky">, z.ZodString]>, z.ZodTransform<"amber" | "blue" | "gray" | "slate" | "green" | "indigo" | "muted" | "primary" | "red" | "secondary" | "sky", string>>, z.ZodPipe<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<`#${string}` | `rgb(${number},${number},${number})` | `rgba(${number},${number},${number},${number})`, string>>, z.ZodObject<{
|
|
@@ -779,7 +784,7 @@ declare const LikeC4ProjectJsonConfigSchema: z.ZodObject<{
|
|
|
779
784
|
}>>>;
|
|
780
785
|
exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
781
786
|
manualLayouts: z.ZodOptional<z.ZodObject<{
|
|
782
|
-
outDir: z.ZodString
|
|
787
|
+
outDir: z.ZodDefault<z.ZodString>;
|
|
783
788
|
}, z.core.$strip>>;
|
|
784
789
|
}, z.core.$strip>;
|
|
785
790
|
type LikeC4ProjectJsonConfig = SimplifyDeep<z.input<typeof LikeC4ProjectJsonConfigSchema>>;
|
|
@@ -912,12 +917,21 @@ type LikeC4ProjectConfigInput = SimplifyDeep<z.input<typeof LikeC4ProjectJsonCon
|
|
|
912
917
|
* Validates JSON string or JSON object into a LikeC4ProjectConfig object.
|
|
913
918
|
*/
|
|
914
919
|
declare function validateProjectConfig<C extends string | Record<string, unknown>>(config: C): LikeC4ProjectConfig;
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
920
|
+
|
|
921
|
+
declare const IncludeConfigSchema: z.ZodObject<{
|
|
922
|
+
paths: z.ZodArray<z.ZodString>;
|
|
923
|
+
maxDepth: z.ZodDefault<z.ZodNumber>;
|
|
924
|
+
fileThreshold: z.ZodDefault<z.ZodNumber>;
|
|
925
|
+
}, z.core.$strip>;
|
|
926
|
+
type IncludeConfig = z.infer<typeof IncludeConfigSchema>;
|
|
927
|
+
declare const IncludeSchema: z.ZodOptional<z.ZodObject<{
|
|
928
|
+
paths: z.ZodArray<z.ZodString>;
|
|
929
|
+
maxDepth: z.ZodDefault<z.ZodNumber>;
|
|
930
|
+
fileThreshold: z.ZodDefault<z.ZodNumber>;
|
|
931
|
+
}, z.core.$strip>>;
|
|
932
|
+
type LikeC4IncludeConfig = z.infer<typeof IncludeSchema>;
|
|
933
|
+
declare function normalizeIncludeConfig(include?: LikeC4IncludeConfig): IncludeConfig;
|
|
934
|
+
declare function validateIncludePaths(include?: LikeC4IncludeConfig): void;
|
|
921
935
|
|
|
922
936
|
declare const ThemeColorValuesSchema: z.ZodPipe<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<`#${string}` | `rgb(${number},${number},${number})` | `rgba(${number},${number},${number},${number})`, string>>, z.ZodObject<{
|
|
923
937
|
elements: z.ZodPipe<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<`#${string}` | `rgb(${number},${number},${number})` | `rgba(${number},${number},${number},${number})`, string>>, z.ZodPipe<z.ZodObject<{
|
|
@@ -2378,4 +2392,4 @@ declare function defineTheme<const S extends LikeC4ConfigThemeInput>(theme: S):
|
|
|
2378
2392
|
*/
|
|
2379
2393
|
declare function defineStyle<const S extends LikeC4StylesConfigInput>(styles: S): LikeC4ProjectStylesConfig;
|
|
2380
2394
|
|
|
2381
|
-
export { ConfigFilenames, type GeneratorFn, type GeneratorFnContext, type GeneratorFnParams, type LikeC4ProjectConfig, type LikeC4ProjectConfigInput, type LikeC4ProjectJsonConfig, type LikeC4StylesConfig, type LikeC4StylesConfigInput, type LocateResult, ManualLayoutsConfigSchema, defineConfig, defineGenerators, defineStyle, defineTheme, defineThemeColor, isLikeC4Config, isLikeC4JsonConfig, isLikeC4NonJsonConfig,
|
|
2395
|
+
export { ConfigFilenames, type GeneratorFn, type GeneratorFnContext, type GeneratorFnParams, type IncludeConfig, type LikeC4ProjectConfig, type LikeC4ProjectConfigInput, type LikeC4ProjectJsonConfig, type LikeC4StylesConfig, type LikeC4StylesConfigInput, type LocateResult, ManualLayoutsConfigSchema, defineConfig, defineGenerators, defineStyle, defineTheme, defineThemeColor, isLikeC4Config, isLikeC4JsonConfig, isLikeC4NonJsonConfig, normalizeIncludeConfig, validateIncludePaths, validateProjectConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { C as ConfigFilenames, d as defineConfig,
|
|
1
|
+
export { C as ConfigFilenames, d as defineConfig, e as defineGenerators, f as defineStyle, g as defineTheme, h as defineThemeColor, i as isLikeC4Config, b as isLikeC4JsonConfig, c as isLikeC4NonJsonConfig, n as normalizeIncludeConfig, a as validateIncludePaths, v as validateProjectConfig } from './shared/config.CUC_rqhf.mjs';
|
package/dist/node/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { URI } from 'vscode-uri';
|
|
2
2
|
import { LikeC4ProjectConfig } from '../index.mjs';
|
|
3
|
-
export { ConfigFilenames, GeneratorFn, GeneratorFnContext, GeneratorFnParams, LikeC4ProjectConfigInput, LikeC4ProjectJsonConfig, LikeC4StylesConfig, LikeC4StylesConfigInput, LocateResult, ManualLayoutsConfigSchema, defineConfig, defineGenerators, defineStyle, defineTheme, defineThemeColor, isLikeC4Config, isLikeC4JsonConfig, isLikeC4NonJsonConfig,
|
|
3
|
+
export { ConfigFilenames, GeneratorFn, GeneratorFnContext, GeneratorFnParams, IncludeConfig, LikeC4ProjectConfigInput, LikeC4ProjectJsonConfig, LikeC4StylesConfig, LikeC4StylesConfigInput, LocateResult, ManualLayoutsConfigSchema, defineConfig, defineGenerators, defineStyle, defineTheme, defineThemeColor, isLikeC4Config, isLikeC4JsonConfig, isLikeC4NonJsonConfig, normalizeIncludeConfig, validateIncludePaths, validateProjectConfig } from '../index.mjs';
|
|
4
4
|
import '@likec4/core';
|
|
5
5
|
import '@likec4/core/model';
|
|
6
6
|
import '@likec4/core/types';
|
package/dist/node/index.mjs
CHANGED
|
@@ -2,8 +2,8 @@ import { invariant } from '@likec4/core';
|
|
|
2
2
|
import { bundleRequire } from 'bundle-require';
|
|
3
3
|
import * as fs from 'node:fs/promises';
|
|
4
4
|
import { dirname } from 'node:path';
|
|
5
|
-
import {
|
|
6
|
-
export { C as ConfigFilenames,
|
|
5
|
+
import { b as isLikeC4JsonConfig, v as validateProjectConfig, c as isLikeC4NonJsonConfig, d as defineConfig } from '../shared/config.CUC_rqhf.mjs';
|
|
6
|
+
export { C as ConfigFilenames, e as defineGenerators, f as defineStyle, g as defineTheme, h as defineThemeColor, i as isLikeC4Config, n as normalizeIncludeConfig, a as validateIncludePaths } from '../shared/config.CUC_rqhf.mjs';
|
|
7
7
|
import { rootLogger } from '@likec4/log';
|
|
8
8
|
|
|
9
9
|
const logger = rootLogger.getChild("config");
|
|
@@ -5,13 +5,13 @@ import { exact } from '@likec4/core/types';
|
|
|
5
5
|
|
|
6
6
|
const IMAGE_ALIAS_KEY_REGEX = /^@[A-Za-z0-9_-]*$/;
|
|
7
7
|
const IMAGE_ALIAS_VALUE_REGEX = /^(?!\/|[A-Za-z]:[\\\/])(?!.*:\/\/).*$/;
|
|
8
|
-
const ImageAliasValue = z.string().
|
|
8
|
+
const ImageAliasValue = z.string().min(1, "Image alias value cannot be empty").regex(
|
|
9
9
|
IMAGE_ALIAS_VALUE_REGEX,
|
|
10
10
|
"Image alias value must be a relative path (no leading slash or protocol)"
|
|
11
11
|
);
|
|
12
12
|
const ImageAliasesSchema = z.record(
|
|
13
13
|
z.string(),
|
|
14
|
-
// PLAIN key schema -
|
|
14
|
+
// PLAIN key schema - zod JSON schema export-safe.
|
|
15
15
|
ImageAliasValue
|
|
16
16
|
).meta({
|
|
17
17
|
description: "Map of image alias prefixes to relative paths (keys must match /^@\\w+$/; values must be relative paths without protocol or leading slash)."
|
|
@@ -45,6 +45,66 @@ function validateImageAliases(imageAliases) {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
const RELATIVE_PATH_REGEX = /^(?!\/|[A-Za-z]:[\\\/])(?!.*:\/\/).*$/;
|
|
49
|
+
const IncludePathValue = z.string().min(1, "Include path cannot be empty").regex(
|
|
50
|
+
RELATIVE_PATH_REGEX,
|
|
51
|
+
"Include path must be a relative path (no leading slash, drive letter, or protocol)"
|
|
52
|
+
);
|
|
53
|
+
const IncludeConfigSchema = z.object({
|
|
54
|
+
paths: z.array(IncludePathValue).min(1, "Include paths cannot be empty").meta({
|
|
55
|
+
description: [
|
|
56
|
+
"Additional relative directory paths to include LikeC4 source files from, searched recursively.",
|
|
57
|
+
"Paths are relative to the project folder (the folder containing this config file).",
|
|
58
|
+
'Example: ["../shared", "../common/specs"]'
|
|
59
|
+
].join("\n")
|
|
60
|
+
}),
|
|
61
|
+
maxDepth: z.number().int().min(1).max(20).default(3).meta({
|
|
62
|
+
description: [
|
|
63
|
+
"Maximum directory depth to scan when searching for .c4 files in include paths.",
|
|
64
|
+
"Prevents excessive scanning of deeply nested directories.",
|
|
65
|
+
"Default: 3"
|
|
66
|
+
].join("\n")
|
|
67
|
+
}),
|
|
68
|
+
fileThreshold: z.number().int().min(1).default(30).meta({
|
|
69
|
+
description: [
|
|
70
|
+
"Maximum number of files to load from include paths before warning.",
|
|
71
|
+
"Helps identify performance issues from accidentally including large directories.",
|
|
72
|
+
"Default: 30"
|
|
73
|
+
].join("\n")
|
|
74
|
+
})
|
|
75
|
+
}).meta({
|
|
76
|
+
id: "include-config",
|
|
77
|
+
description: "Configuration for including additional LikeC4 source files"
|
|
78
|
+
});
|
|
79
|
+
const IncludeSchema = IncludeConfigSchema.optional().meta({
|
|
80
|
+
description: [
|
|
81
|
+
"Configuration for including additional LikeC4 source files from other directories.",
|
|
82
|
+
'Example: { "paths": ["../shared", "../common/specs"], "maxDepth": 5, "fileThreshold": 50 }'
|
|
83
|
+
].join("\n")
|
|
84
|
+
});
|
|
85
|
+
function normalizeIncludeConfig(include) {
|
|
86
|
+
if (!include) {
|
|
87
|
+
return { paths: [], maxDepth: 3, fileThreshold: 30 };
|
|
88
|
+
}
|
|
89
|
+
return include;
|
|
90
|
+
}
|
|
91
|
+
function validateIncludePaths(include) {
|
|
92
|
+
if (!include?.paths) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const invalidPaths = [];
|
|
96
|
+
for (const path of include.paths) {
|
|
97
|
+
if (!RELATIVE_PATH_REGEX.test(path)) {
|
|
98
|
+
invalidPaths.push(path);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (invalidPaths.length) {
|
|
102
|
+
throw new Error(
|
|
103
|
+
`Invalid include path(s): ${invalidPaths.map((p) => JSON.stringify(p)).join(", ")} (must be relative paths without leading slash, drive letter, or protocol)`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
48
108
|
function e(e,t,n){let r=n=>e(n,...t);return n===void 0?r:Object.assign(r,{lazy:n,lazyArgs:t})}
|
|
49
109
|
|
|
50
110
|
function t$1(t,n,r){let i=t.length-n.length;if(i===0)return t(...n);if(i===1)return e(t,n,r);throw Error(`Wrong number of arguments`)}
|
|
@@ -63,9 +123,9 @@ const line = z.literal(["dashed", "solid", "dotted"]).meta({ id: "LineType" });
|
|
|
63
123
|
const themeColor = z.literal(ThemeColors).meta({ id: "ThemeColor" });
|
|
64
124
|
const color = z.union([
|
|
65
125
|
themeColor,
|
|
66
|
-
z.string().
|
|
126
|
+
z.string().min(1, "Color name cannot be empty")
|
|
67
127
|
]).transform((value) => value).meta({ id: "ColorName" });
|
|
68
|
-
const colorValue = z.string().
|
|
128
|
+
const colorValue = z.string().min(1, "Color value cannot be empty").transform((value) => value).meta({
|
|
69
129
|
id: "ColorLiteral",
|
|
70
130
|
description: "Color value in any valid CSS format: hex, rgb, rgba, hsl, hsla ..."
|
|
71
131
|
});
|
|
@@ -211,8 +271,13 @@ function normalizeDefaults(defaults) {
|
|
|
211
271
|
}
|
|
212
272
|
|
|
213
273
|
const ManualLayoutsConfigSchema = z.object({
|
|
214
|
-
outDir: z.string().meta({
|
|
215
|
-
description:
|
|
274
|
+
outDir: z.string().default(".likec4").meta({
|
|
275
|
+
description: [
|
|
276
|
+
"Path to the directory where manual layouts will be stored,",
|
|
277
|
+
"relative to the folder containing the project config. ",
|
|
278
|
+
"",
|
|
279
|
+
"Defaults to '.likec4'."
|
|
280
|
+
].join("\n")
|
|
216
281
|
})
|
|
217
282
|
}).meta({
|
|
218
283
|
id: "manual-layouts-config",
|
|
@@ -229,6 +294,7 @@ const LikeC4ProjectJsonConfigSchema = z.object({
|
|
|
229
294
|
title: z.string().nonempty("Project title cannot be empty if specified").optional().meta({ description: "A human readable title for the project" }),
|
|
230
295
|
contactPerson: z.string().nonempty("Contact person cannot be empty if specified").optional().meta({ description: "A person who has been involved in creating or maintaining this project" }),
|
|
231
296
|
imageAliases: ImageAliasesSchema.optional(),
|
|
297
|
+
include: IncludeSchema,
|
|
232
298
|
styles: LikeC4StylesConfigSchema.optional(),
|
|
233
299
|
exclude: z.array(z.string()).optional().meta({ description: 'List of file patterns to exclude from the project, default is ["**/node_modules/**"]' }),
|
|
234
300
|
manualLayouts: ManualLayoutsConfigSchema.optional()
|
|
@@ -250,15 +316,11 @@ function validateProjectConfig(config) {
|
|
|
250
316
|
if (parsed.data.imageAliases) {
|
|
251
317
|
validateImageAliases(parsed.data.imageAliases);
|
|
252
318
|
}
|
|
319
|
+
if (parsed.data.include) {
|
|
320
|
+
validateIncludePaths(parsed.data.include);
|
|
321
|
+
}
|
|
253
322
|
return parsed.data;
|
|
254
323
|
}
|
|
255
|
-
function serializableLikeC4ProjectConfig({
|
|
256
|
-
generators: _,
|
|
257
|
-
// omit
|
|
258
|
-
...config
|
|
259
|
-
}) {
|
|
260
|
-
return LikeC4ProjectJsonConfigSchema.parse(config);
|
|
261
|
-
}
|
|
262
324
|
|
|
263
325
|
const configJsonFilenames = [
|
|
264
326
|
".likec4rc",
|
|
@@ -311,4 +373,4 @@ function defineStyle(styles) {
|
|
|
311
373
|
return LikeC4StylesConfigSchema.parse(styles);
|
|
312
374
|
}
|
|
313
375
|
|
|
314
|
-
export { ConfigFilenames as C,
|
|
376
|
+
export { ConfigFilenames as C, validateIncludePaths as a, isLikeC4JsonConfig as b, isLikeC4NonJsonConfig as c, defineConfig as d, defineGenerators as e, defineStyle as f, defineTheme as g, defineThemeColor as h, isLikeC4Config as i, normalizeIncludeConfig as n, validateProjectConfig as v };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@likec4/config",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.46.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"homepage": "https://likec4.dev",
|
|
6
6
|
"author": "Denis Davydkov <denis@davydkov.com>",
|
|
@@ -58,14 +58,14 @@
|
|
|
58
58
|
"bundle-require": "^5.1.0",
|
|
59
59
|
"defu": "^6.1.4",
|
|
60
60
|
"json5": "^2.2.3",
|
|
61
|
-
"zod": "^4.1.
|
|
61
|
+
"zod": "^4.1.13",
|
|
62
62
|
"type-fest": "^4.41.0"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"esbuild": "^0.25.11",
|
|
66
66
|
"vscode-uri": "3.1.0",
|
|
67
|
-
"@likec4/core": "1.
|
|
68
|
-
"@likec4/log": "1.
|
|
67
|
+
"@likec4/core": "1.46.0",
|
|
68
|
+
"@likec4/log": "1.46.0"
|
|
69
69
|
},
|
|
70
70
|
"peerDependenciesMeta": {
|
|
71
71
|
"vscode-uri": {
|
|
@@ -73,18 +73,18 @@
|
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
|
-
"@types/node": "~
|
|
76
|
+
"@types/node": "~22.19.1",
|
|
77
77
|
"remeda": "^2.32.0",
|
|
78
|
-
"tsx": "4.
|
|
79
|
-
"turbo": "2.6.
|
|
78
|
+
"tsx": "4.21.0",
|
|
79
|
+
"turbo": "2.6.3",
|
|
80
80
|
"typescript": "5.9.3",
|
|
81
81
|
"unbuild": "3.5.0",
|
|
82
82
|
"nano-spawn": "^1.0.3",
|
|
83
|
-
"vitest": "4.0.
|
|
84
|
-
"@likec4/core": "1.
|
|
85
|
-
"@likec4/
|
|
86
|
-
"@likec4/
|
|
87
|
-
"@likec4/
|
|
83
|
+
"vitest": "4.0.15",
|
|
84
|
+
"@likec4/core": "1.46.0",
|
|
85
|
+
"@likec4/log": "1.46.0",
|
|
86
|
+
"@likec4/tsconfig": "1.46.0",
|
|
87
|
+
"@likec4/devops": "1.42.0"
|
|
88
88
|
},
|
|
89
89
|
"scripts": {
|
|
90
90
|
"typecheck": "tsc -b --verbose",
|
package/schema.json
CHANGED
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"pattern": "^(?!\\/|[A-Za-z]:[\\\\\\/])(?!.*:\\/\\/).*$"
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
|
+
"include": {
|
|
34
|
+
"description": "Configuration for including additional LikeC4 source files from other directories.\nExample: { \"paths\": [\"../shared\", \"../common/specs\"], \"maxDepth\": 5, \"fileThreshold\": 50 }",
|
|
35
|
+
"$ref": "#/$defs/include-config"
|
|
36
|
+
},
|
|
33
37
|
"styles": {
|
|
34
38
|
"$ref": "#/$defs/StylesConfiguration"
|
|
35
39
|
},
|
|
@@ -48,6 +52,40 @@
|
|
|
48
52
|
"name"
|
|
49
53
|
],
|
|
50
54
|
"$defs": {
|
|
55
|
+
"include-config": {
|
|
56
|
+
"id": "include-config",
|
|
57
|
+
"description": "Configuration for including additional LikeC4 source files",
|
|
58
|
+
"type": "object",
|
|
59
|
+
"properties": {
|
|
60
|
+
"paths": {
|
|
61
|
+
"description": "Additional relative directory paths to include LikeC4 source files from, searched recursively.\nPaths are relative to the project folder (the folder containing this config file).\nExample: [\"../shared\", \"../common/specs\"]",
|
|
62
|
+
"minItems": 1,
|
|
63
|
+
"type": "array",
|
|
64
|
+
"items": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"minLength": 1,
|
|
67
|
+
"pattern": "^(?!\\/|[A-Za-z]:[\\\\\\/])(?!.*:\\/\\/).*$"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"maxDepth": {
|
|
71
|
+
"description": "Maximum directory depth to scan when searching for .c4 files in include paths.\nPrevents excessive scanning of deeply nested directories.\nDefault: 3",
|
|
72
|
+
"default": 3,
|
|
73
|
+
"type": "integer",
|
|
74
|
+
"minimum": 1,
|
|
75
|
+
"maximum": 20
|
|
76
|
+
},
|
|
77
|
+
"fileThreshold": {
|
|
78
|
+
"description": "Maximum number of files to load from include paths before warning.\nHelps identify performance issues from accidentally including large directories.\nDefault: 30",
|
|
79
|
+
"default": 30,
|
|
80
|
+
"type": "integer",
|
|
81
|
+
"minimum": 1,
|
|
82
|
+
"maximum": 9007199254740991
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"required": [
|
|
86
|
+
"paths"
|
|
87
|
+
]
|
|
88
|
+
},
|
|
51
89
|
"StylesConfiguration": {
|
|
52
90
|
"id": "StylesConfiguration",
|
|
53
91
|
"description": "Project styles customization",
|
|
@@ -448,13 +486,11 @@
|
|
|
448
486
|
"type": "object",
|
|
449
487
|
"properties": {
|
|
450
488
|
"outDir": {
|
|
451
|
-
"description": "Path to the directory where manual layouts will be stored
|
|
489
|
+
"description": "Path to the directory where manual layouts will be stored,\nrelative to the folder containing the project config. \n\nDefaults to '.likec4'.",
|
|
490
|
+
"default": ".likec4",
|
|
452
491
|
"type": "string"
|
|
453
492
|
}
|
|
454
|
-
}
|
|
455
|
-
"required": [
|
|
456
|
-
"outDir"
|
|
457
|
-
]
|
|
493
|
+
}
|
|
458
494
|
}
|
|
459
495
|
}
|
|
460
496
|
}
|
package/src/index.ts
CHANGED
|
@@ -9,12 +9,18 @@ export type {
|
|
|
9
9
|
ManualLayoutsConfigSchema,
|
|
10
10
|
} from './schema'
|
|
11
11
|
|
|
12
|
+
export type {
|
|
13
|
+
IncludeConfig,
|
|
14
|
+
} from './schema.include'
|
|
15
|
+
|
|
12
16
|
export type {
|
|
13
17
|
LikeC4StylesConfig,
|
|
14
18
|
LikeC4StylesConfigInput,
|
|
15
19
|
} from './schema.theme'
|
|
16
20
|
|
|
17
|
-
export {
|
|
21
|
+
export { validateProjectConfig } from './schema'
|
|
22
|
+
|
|
23
|
+
export { normalizeIncludeConfig, validateIncludePaths } from './schema.include'
|
|
18
24
|
|
|
19
25
|
export {
|
|
20
26
|
ConfigFilenames,
|
|
@@ -8,14 +8,14 @@ const IMAGE_ALIAS_VALUE_REGEX = /^(?!\/|[A-Za-z]:[\\\/])(?!.*:\/\/).*$/
|
|
|
8
8
|
// Schema for an image alias value: must be a non-empty string representing a relative path (no leading slash, drive letter, or protocol).
|
|
9
9
|
const ImageAliasValue = z
|
|
10
10
|
.string()
|
|
11
|
-
.
|
|
11
|
+
.min(1, 'Image alias value cannot be empty')
|
|
12
12
|
.regex(
|
|
13
13
|
IMAGE_ALIAS_VALUE_REGEX,
|
|
14
14
|
'Image alias value must be a relative path (no leading slash or protocol)',
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
export const ImageAliasesSchema = z.record(
|
|
18
|
-
z.string(), // PLAIN key schema -
|
|
18
|
+
z.string(), // PLAIN key schema - zod JSON schema export-safe.
|
|
19
19
|
ImageAliasValue,
|
|
20
20
|
).meta({
|
|
21
21
|
description:
|
|
@@ -34,7 +34,7 @@ export function validateImageAliases(imageAliases?: LikeC4ImageAliasConfig) {
|
|
|
34
34
|
if (!IMAGE_ALIAS_KEY_REGEX.test(key)) {
|
|
35
35
|
invalidKeys.push(key)
|
|
36
36
|
}
|
|
37
|
-
// Value regex is technically already enforced by
|
|
37
|
+
// Value regex is technically already enforced by zod,
|
|
38
38
|
// so this check is purely defensive.
|
|
39
39
|
if (!IMAGE_ALIAS_VALUE_REGEX.test(value)) {
|
|
40
40
|
invalidValues.push(`${key} -> ${value}`)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as z from 'zod'
|
|
2
|
+
|
|
3
|
+
// Relative path (no leading slash, drive letter, or protocol)
|
|
4
|
+
// eslint-disable-next-line no-useless-escape
|
|
5
|
+
const RELATIVE_PATH_REGEX = /^(?!\/|[A-Za-z]:[\\\/])(?!.*:\/\/).*$/
|
|
6
|
+
|
|
7
|
+
// Schema for an include path value: must be a non-empty string representing a relative path
|
|
8
|
+
const IncludePathValue = z
|
|
9
|
+
.string()
|
|
10
|
+
.min(1, 'Include path cannot be empty')
|
|
11
|
+
.regex(
|
|
12
|
+
RELATIVE_PATH_REGEX,
|
|
13
|
+
'Include path must be a relative path (no leading slash, drive letter, or protocol)',
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
export const IncludeConfigSchema = z.object({
|
|
17
|
+
paths: z.array(IncludePathValue)
|
|
18
|
+
.min(1, 'Include paths cannot be empty')
|
|
19
|
+
.meta({
|
|
20
|
+
description: [
|
|
21
|
+
'Additional relative directory paths to include LikeC4 source files from, searched recursively.',
|
|
22
|
+
'Paths are relative to the project folder (the folder containing this config file).',
|
|
23
|
+
'Example: ["../shared", "../common/specs"]',
|
|
24
|
+
].join('\n'),
|
|
25
|
+
}),
|
|
26
|
+
maxDepth: z.number()
|
|
27
|
+
.int()
|
|
28
|
+
.min(1)
|
|
29
|
+
.max(20)
|
|
30
|
+
.default(3)
|
|
31
|
+
.meta({
|
|
32
|
+
description: [
|
|
33
|
+
'Maximum directory depth to scan when searching for .c4 files in include paths.',
|
|
34
|
+
'Prevents excessive scanning of deeply nested directories.',
|
|
35
|
+
'Default: 3',
|
|
36
|
+
].join('\n'),
|
|
37
|
+
}),
|
|
38
|
+
fileThreshold: z.number()
|
|
39
|
+
.int()
|
|
40
|
+
.min(1)
|
|
41
|
+
.default(30)
|
|
42
|
+
.meta({
|
|
43
|
+
description: [
|
|
44
|
+
'Maximum number of files to load from include paths before warning.',
|
|
45
|
+
'Helps identify performance issues from accidentally including large directories.',
|
|
46
|
+
'Default: 30',
|
|
47
|
+
].join('\n'),
|
|
48
|
+
}),
|
|
49
|
+
})
|
|
50
|
+
.meta({
|
|
51
|
+
id: 'include-config',
|
|
52
|
+
description: 'Configuration for including additional LikeC4 source files',
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
export type IncludeConfig = z.infer<typeof IncludeConfigSchema>
|
|
56
|
+
|
|
57
|
+
export const IncludeSchema = IncludeConfigSchema
|
|
58
|
+
.optional()
|
|
59
|
+
.meta({
|
|
60
|
+
description: [
|
|
61
|
+
'Configuration for including additional LikeC4 source files from other directories.',
|
|
62
|
+
'Example: { "paths": ["../shared", "../common/specs"], "maxDepth": 5, "fileThreshold": 50 }',
|
|
63
|
+
].join('\n'),
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
type LikeC4IncludeConfig = z.infer<typeof IncludeSchema>
|
|
67
|
+
|
|
68
|
+
export function normalizeIncludeConfig(include?: LikeC4IncludeConfig): IncludeConfig {
|
|
69
|
+
if (!include) {
|
|
70
|
+
return { paths: [], maxDepth: 3, fileThreshold: 30 }
|
|
71
|
+
}
|
|
72
|
+
return include
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function validateIncludePaths(include?: LikeC4IncludeConfig) {
|
|
76
|
+
if (!include?.paths) {
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const invalidPaths: string[] = []
|
|
81
|
+
|
|
82
|
+
for (const path of include.paths) {
|
|
83
|
+
if (!RELATIVE_PATH_REGEX.test(path)) {
|
|
84
|
+
invalidPaths.push(path)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (invalidPaths.length) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`Invalid include path(s): ${
|
|
91
|
+
invalidPaths
|
|
92
|
+
.map((p) => JSON.stringify(p))
|
|
93
|
+
.join(', ')
|
|
94
|
+
} (must be relative paths without leading slash, drive letter, or protocol)`,
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
}
|
package/src/schema.theme.ts
CHANGED
|
@@ -56,14 +56,14 @@ const themeColor = z
|
|
|
56
56
|
const color = z
|
|
57
57
|
.union([
|
|
58
58
|
themeColor,
|
|
59
|
-
z.string().
|
|
59
|
+
z.string().min(1, 'Color name cannot be empty'),
|
|
60
60
|
])
|
|
61
61
|
.transform(value => value as ThemeColor)
|
|
62
62
|
.meta({ id: 'ColorName' })
|
|
63
63
|
|
|
64
64
|
const colorValue = z
|
|
65
65
|
.string()
|
|
66
|
-
.
|
|
66
|
+
.min(1, 'Color value cannot be empty')
|
|
67
67
|
.transform(value => value as ColorLiteral)
|
|
68
68
|
.meta({
|
|
69
69
|
id: 'ColorLiteral',
|
package/src/schema.ts
CHANGED
|
@@ -15,14 +15,20 @@ import type { SimplifyDeep } from 'type-fest'
|
|
|
15
15
|
import type { URI } from 'vscode-uri'
|
|
16
16
|
import * as z from 'zod'
|
|
17
17
|
import { ImageAliasesSchema, validateImageAliases } from './schema.image-alias'
|
|
18
|
+
import { IncludeSchema, validateIncludePaths } from './schema.include'
|
|
18
19
|
import { LikeC4StylesConfigSchema } from './schema.theme'
|
|
19
20
|
|
|
20
21
|
export const ManualLayoutsConfigSchema = z
|
|
21
22
|
.object({
|
|
22
23
|
outDir: z.string()
|
|
24
|
+
.default('.likec4')
|
|
23
25
|
.meta({
|
|
24
|
-
description:
|
|
25
|
-
'Path to the directory where manual layouts will be stored,
|
|
26
|
+
description: [
|
|
27
|
+
'Path to the directory where manual layouts will be stored,',
|
|
28
|
+
'relative to the folder containing the project config. ',
|
|
29
|
+
'',
|
|
30
|
+
'Defaults to \'.likec4\'.',
|
|
31
|
+
].join('\n'),
|
|
26
32
|
}),
|
|
27
33
|
})
|
|
28
34
|
.meta({
|
|
@@ -54,6 +60,7 @@ export const LikeC4ProjectJsonConfigSchema = z.object({
|
|
|
54
60
|
.meta({ description: 'A person who has been involved in creating or maintaining this project' }),
|
|
55
61
|
imageAliases: ImageAliasesSchema
|
|
56
62
|
.optional(),
|
|
63
|
+
include: IncludeSchema,
|
|
57
64
|
styles: LikeC4StylesConfigSchema
|
|
58
65
|
.optional(),
|
|
59
66
|
exclude: z.array(z.string())
|
|
@@ -242,16 +249,8 @@ export function validateProjectConfig<C extends string | Record<string, unknown>
|
|
|
242
249
|
if (parsed.data.imageAliases) {
|
|
243
250
|
validateImageAliases(parsed.data.imageAliases)
|
|
244
251
|
}
|
|
252
|
+
if (parsed.data.include) {
|
|
253
|
+
validateIncludePaths(parsed.data.include)
|
|
254
|
+
}
|
|
245
255
|
return parsed.data as unknown as LikeC4ProjectConfig
|
|
246
256
|
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Converts a LikeC4ProjectConfig object into a LikeC4ProjectJsonConfig object.
|
|
250
|
-
* Omit generators property (as it is not serializable)
|
|
251
|
-
*/
|
|
252
|
-
export function serializableLikeC4ProjectConfig({
|
|
253
|
-
generators: _, // omit
|
|
254
|
-
...config
|
|
255
|
-
}: LikeC4ProjectConfig): LikeC4ProjectJsonConfig {
|
|
256
|
-
return LikeC4ProjectJsonConfigSchema.parse(config) as unknown as LikeC4ProjectJsonConfig
|
|
257
|
-
}
|