@likec4/config 1.45.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 +21 -1
- 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.BF5VHDtl.mjs → config.CUC_rqhf.mjs} +69 -5
- package/package.json +11 -11
- package/schema.json +38 -0
- package/src/index.ts +6 -0
- 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 +5 -0
package/dist/index.d.mts
CHANGED
|
@@ -14,6 +14,11 @@ declare const LikeC4ProjectJsonConfigSchema: z.ZodObject<{
|
|
|
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<{
|
|
@@ -913,6 +918,21 @@ type LikeC4ProjectConfigInput = SimplifyDeep<z.input<typeof LikeC4ProjectJsonCon
|
|
|
913
918
|
*/
|
|
914
919
|
declare function validateProjectConfig<C extends string | Record<string, unknown>>(config: C): LikeC4ProjectConfig;
|
|
915
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;
|
|
935
|
+
|
|
916
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<{
|
|
917
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<{
|
|
918
938
|
fill: z.ZodPipe<z.ZodString, z.ZodTransform<`#${string}` | `rgb(${number},${number},${number})` | `rgba(${number},${number},${number},${number})`, string>>;
|
|
@@ -2372,4 +2392,4 @@ declare function defineTheme<const S extends LikeC4ConfigThemeInput>(theme: S):
|
|
|
2372
2392
|
*/
|
|
2373
2393
|
declare function defineStyle<const S extends LikeC4StylesConfigInput>(styles: S): LikeC4ProjectStylesConfig;
|
|
2374
2394
|
|
|
2375
|
-
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, validateProjectConfig };
|
|
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, validateProjectConfig } from '../index.mjs';
|
|
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
|
});
|
|
@@ -234,6 +294,7 @@ const LikeC4ProjectJsonConfigSchema = z.object({
|
|
|
234
294
|
title: z.string().nonempty("Project title cannot be empty if specified").optional().meta({ description: "A human readable title for the project" }),
|
|
235
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" }),
|
|
236
296
|
imageAliases: ImageAliasesSchema.optional(),
|
|
297
|
+
include: IncludeSchema,
|
|
237
298
|
styles: LikeC4StylesConfigSchema.optional(),
|
|
238
299
|
exclude: z.array(z.string()).optional().meta({ description: 'List of file patterns to exclude from the project, default is ["**/node_modules/**"]' }),
|
|
239
300
|
manualLayouts: ManualLayoutsConfigSchema.optional()
|
|
@@ -255,6 +316,9 @@ function validateProjectConfig(config) {
|
|
|
255
316
|
if (parsed.data.imageAliases) {
|
|
256
317
|
validateImageAliases(parsed.data.imageAliases);
|
|
257
318
|
}
|
|
319
|
+
if (parsed.data.include) {
|
|
320
|
+
validateIncludePaths(parsed.data.include);
|
|
321
|
+
}
|
|
258
322
|
return parsed.data;
|
|
259
323
|
}
|
|
260
324
|
|
|
@@ -309,4 +373,4 @@ function defineStyle(styles) {
|
|
|
309
373
|
return LikeC4StylesConfigSchema.parse(styles);
|
|
310
374
|
}
|
|
311
375
|
|
|
312
|
-
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,17 +73,17 @@
|
|
|
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/
|
|
85
|
-
"@likec4/
|
|
86
|
-
"@likec4/tsconfig": "1.
|
|
83
|
+
"vitest": "4.0.15",
|
|
84
|
+
"@likec4/core": "1.46.0",
|
|
85
|
+
"@likec4/log": "1.46.0",
|
|
86
|
+
"@likec4/tsconfig": "1.46.0",
|
|
87
87
|
"@likec4/devops": "1.42.0"
|
|
88
88
|
},
|
|
89
89
|
"scripts": {
|
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",
|
package/src/index.ts
CHANGED
|
@@ -9,6 +9,10 @@ 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,
|
|
@@ -16,6 +20,8 @@ export type {
|
|
|
16
20
|
|
|
17
21
|
export { validateProjectConfig } from './schema'
|
|
18
22
|
|
|
23
|
+
export { normalizeIncludeConfig, validateIncludePaths } from './schema.include'
|
|
24
|
+
|
|
19
25
|
export {
|
|
20
26
|
ConfigFilenames,
|
|
21
27
|
isLikeC4Config,
|
|
@@ -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,6 +15,7 @@ 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
|
|
@@ -59,6 +60,7 @@ export const LikeC4ProjectJsonConfigSchema = z.object({
|
|
|
59
60
|
.meta({ description: 'A person who has been involved in creating or maintaining this project' }),
|
|
60
61
|
imageAliases: ImageAliasesSchema
|
|
61
62
|
.optional(),
|
|
63
|
+
include: IncludeSchema,
|
|
62
64
|
styles: LikeC4StylesConfigSchema
|
|
63
65
|
.optional(),
|
|
64
66
|
exclude: z.array(z.string())
|
|
@@ -247,5 +249,8 @@ export function validateProjectConfig<C extends string | Record<string, unknown>
|
|
|
247
249
|
if (parsed.data.imageAliases) {
|
|
248
250
|
validateImageAliases(parsed.data.imageAliases)
|
|
249
251
|
}
|
|
252
|
+
if (parsed.data.include) {
|
|
253
|
+
validateIncludePaths(parsed.data.include)
|
|
254
|
+
}
|
|
250
255
|
return parsed.data as unknown as LikeC4ProjectConfig
|
|
251
256
|
}
|