@likec4/config 1.39.4 → 1.40.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@likec4/config",
3
- "version": "1.39.4",
3
+ "version": "1.40.0",
4
4
  "license": "MIT",
5
5
  "homepage": "https://likec4.dev",
6
6
  "author": "Denis Davydkov <denis@davydkov.com>",
@@ -27,20 +27,20 @@
27
27
  "node": {
28
28
  "sources": "./src/node/index.ts",
29
29
  "default": {
30
- "types": "./dist/node/index.d.ts",
30
+ "types": "./dist/node/index.d.mts",
31
31
  "default": "./dist/node/index.mjs"
32
32
  }
33
33
  },
34
34
  "sources": "./src/index.ts",
35
35
  "default": {
36
- "types": "./dist/index.d.ts",
36
+ "types": "./dist/index.d.mts",
37
37
  "default": "./dist/index.mjs"
38
38
  }
39
39
  },
40
40
  "./node": {
41
41
  "sources": "./src/node/index.ts",
42
42
  "default": {
43
- "types": "./dist/node/index.d.ts",
43
+ "types": "./dist/node/index.d.mts",
44
44
  "default": "./dist/node/index.mjs"
45
45
  }
46
46
  },
@@ -56,14 +56,13 @@
56
56
  "dependencies": {
57
57
  "bundle-require": "^5.1.0",
58
58
  "defu": "^6.1.4",
59
- "json5": "^2.2.3",
60
- "zod": "^4.0.17"
59
+ "json5": "^2.2.3"
61
60
  },
62
61
  "peerDependencies": {
63
- "esbuild": ">=0.25",
62
+ "esbuild": "^0.25.9",
64
63
  "vscode-uri": "3.1.0",
65
- "@likec4/core": "1.39.4",
66
- "@likec4/log": "1.39.4"
64
+ "@likec4/core": "1.40.0",
65
+ "@likec4/log": "1.40.0"
67
66
  },
68
67
  "peerDependenciesMeta": {
69
68
  "@likec4/core": {
@@ -79,8 +78,9 @@
79
78
  "turbo": "2.5.6",
80
79
  "typescript": "5.9.2",
81
80
  "unbuild": "3.5.0",
81
+ "zod4": "npm:zod@^4.0.17",
82
82
  "vitest": "3.2.4",
83
- "@likec4/tsconfig": "1.39.4"
83
+ "@likec4/tsconfig": "1.40.0"
84
84
  },
85
85
  "scripts": {
86
86
  "generate": "tsx scripts/generate.mts",
@@ -90,6 +90,6 @@
90
90
  "clean": "pnpm rimraf dist lib",
91
91
  "pack": "pnpm pack"
92
92
  },
93
- "types": "./dist/index.d.ts",
93
+ "types": "./dist/index.d.mts",
94
94
  "module": "./dist/index.mjs"
95
95
  }
@@ -1,4 +1,4 @@
1
- import * as z from 'zod'
1
+ import * as z from 'zod4'
2
2
 
3
3
  // Key must be prefixed with "@" and contain only allowed characters
4
4
  const IMAGE_ALIAS_KEY_REGEX = /^@[A-Za-z0-9_-]*$/
package/src/schema.ts CHANGED
@@ -11,9 +11,8 @@ import type {
11
11
  ProjectId,
12
12
  } from '@likec4/core/types'
13
13
  import JSON5 from 'json5'
14
- import type Stream from 'node:stream'
15
14
  import type { URI } from 'vscode-uri'
16
- import * as z from 'zod'
15
+ import * as z from 'zod4'
17
16
  import { ImageAliasesSchema, validateImageAliases } from './schema.image-alias'
18
17
 
19
18
  export const LikeC4ProjectJsonConfigSchema = z.object({
@@ -133,7 +132,7 @@ export interface GeneratorFnContext {
133
132
  | NodeJS.ArrayBufferView
134
133
  | Iterable<string | NodeJS.ArrayBufferView>
135
134
  | AsyncIterable<string | NodeJS.ArrayBufferView>
136
- | Stream
135
+ | NodeJS.ReadableStream
137
136
  }): Promise<void>
138
137
 
139
138
  /**
@@ -1,45 +0,0 @@
1
- import { type GeneratorFn, type LikeC4ProjectConfig } from './schema';
2
- /**
3
- * Defines LikeC4 Project, allows custom generators that can be executed using CLI:
4
- *
5
- * `$ likec4 gen <generator-name>`
6
- *
7
- * or VSCode command `LikeC4: Run code generator`
8
- *
9
- * @example
10
- * ```ts
11
- * export default defineConfig({
12
- * name: 'my-project',
13
- * title: 'My Project',
14
- * exclude: ['picomatch pattern'],
15
- * generators: {
16
- * 'my-generator': async ({ likec4model, ctx }) => {
17
- * await ctx.write('my-generator.txt', likec4model.project.id)
18
- * }
19
- * }
20
- * })
21
- * ```
22
- */
23
- export declare function defineConfig<const C extends LikeC4ProjectConfig>(config: C): C;
24
- /**
25
- * Define reusable custom generators
26
- *
27
- * @example
28
- * ```ts
29
- * // generators.ts
30
- * export default defineGenerators({
31
- * 'my-generator': async ({ likec4model, ctx }) => {
32
- * await ctx.write('my-generator.txt', likec4model.project.id)
33
- * }
34
- * })
35
- *
36
- * // likec4.config.ts
37
- * import generators from './generators'
38
- *
39
- * export default defineConfig({
40
- * name: 'my-project',
41
- * generators,
42
- * })
43
- * ```
44
- */
45
- export declare function defineGenerators<const G extends Record<string, GeneratorFn>>(generators: G): G;
@@ -1,7 +0,0 @@
1
- import { GeneratorsSchema, LikeC4ProjectConfigSchema } from "./schema.mjs";
2
- export function defineConfig(config) {
3
- return LikeC4ProjectConfigSchema.parse(config);
4
- }
5
- export function defineGenerators(generators) {
6
- return GeneratorsSchema.parse(generators);
7
- }
@@ -1,16 +0,0 @@
1
- declare const configJsonFilenames: readonly [".likec4rc", ".likec4.config.json", "likec4.config.json"];
2
- declare const configNonJsonFilenames: readonly ["likec4.config.js", "likec4.config.mjs", "likec4.config.ts", "likec4.config.mts"];
3
- export declare const ConfigFilenames: readonly [".likec4rc", ".likec4.config.json", "likec4.config.json", "likec4.config.js", "likec4.config.mjs", "likec4.config.ts", "likec4.config.mts"];
4
- /**
5
- * Checks if the given filename is a LikeC4 JSON config file (JSON, RC).
6
- */
7
- export declare function isLikeC4JsonConfig(filename: string): filename is typeof configJsonFilenames[number];
8
- /**
9
- * Checks if the given filename is a LikeC4 non-JSON config file (JS, MJS, TS, MTS)
10
- */
11
- export declare function isLikeC4NonJsonConfig(filename: string): filename is typeof configNonJsonFilenames[number];
12
- /**
13
- * Checks if the given filename is a LikeC4 config file (JSON or non-JSON)
14
- */
15
- export declare function isLikeC4Config(filename: string): filename is typeof ConfigFilenames[number];
16
- export {};
@@ -1,34 +0,0 @@
1
- const configJsonFilenames = [
2
- ".likec4rc",
3
- ".likec4.config.json",
4
- "likec4.config.json"
5
- ];
6
- const configNonJsonFilenames = [
7
- "likec4.config.js",
8
- "likec4.config.mjs",
9
- "likec4.config.ts",
10
- "likec4.config.mts"
11
- ];
12
- export const ConfigFilenames = [
13
- ...configJsonFilenames,
14
- ...configNonJsonFilenames
15
- ];
16
- export function isLikeC4JsonConfig(filename) {
17
- for (const ext of configJsonFilenames) {
18
- if (filename.endsWith(ext)) {
19
- return true;
20
- }
21
- }
22
- return false;
23
- }
24
- export function isLikeC4NonJsonConfig(filename) {
25
- for (const ext of configNonJsonFilenames) {
26
- if (filename.endsWith(ext)) {
27
- return true;
28
- }
29
- }
30
- return false;
31
- }
32
- export function isLikeC4Config(filename) {
33
- return isLikeC4JsonConfig(filename) || isLikeC4NonJsonConfig(filename);
34
- }
package/dist/index.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export type { GeneratorFn, GeneratorFnContext, GeneratorFnParams, LikeC4ProjectConfig, LikeC4ProjectJsonConfig, } from './schema';
2
- export { serializableLikeC4ProjectConfig, validateProjectConfig } from './schema';
3
- export { ConfigFilenames, isLikeC4Config, isLikeC4JsonConfig, isLikeC4NonJsonConfig, } from './filenames';
4
- export { defineConfig, defineGenerators, } from './define-config';
package/dist/logger.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare const logger: any;
package/dist/logger.mjs DELETED
@@ -1,2 +0,0 @@
1
- import { rootLogger } from "@likec4/log";
2
- export const logger = rootLogger.getChild("config");
@@ -1,2 +0,0 @@
1
- export * from '../index';
2
- export { loadConfig } from './load-config';
@@ -1,7 +0,0 @@
1
- import type { URI } from 'vscode-uri';
2
- import { type LikeC4ProjectConfig } from '../schema';
3
- /**
4
- * Load LikeC4 Project config file.
5
- * If filepath is a non-JSON file, it will be bundled and required
6
- */
7
- export declare function loadConfig(filepath: URI): Promise<LikeC4ProjectConfig>;
@@ -1,55 +0,0 @@
1
- import { invariant } from "@likec4/core";
2
- import { bundleRequire } from "bundle-require";
3
- import * as fs from "node:fs/promises";
4
- import { dirname } from "node:path";
5
- import { defineConfig } from "../define-config.mjs";
6
- import { isLikeC4JsonConfig, isLikeC4NonJsonConfig } from "../filenames.mjs";
7
- import { logger } from "../logger.mjs";
8
- import { validateProjectConfig } from "../schema.mjs";
9
- export async function loadConfig(filepath) {
10
- logger.debug`Loading config file: ${filepath.fsPath}`;
11
- if (isLikeC4JsonConfig(filepath.fsPath)) {
12
- try {
13
- const content = await fs.readFile(filepath.fsPath, "utf-8");
14
- return validateProjectConfig(content);
15
- } catch (err) {
16
- logger.error(`Failed to load json config file: ${filepath.fsPath}`, { err });
17
- throw err;
18
- }
19
- }
20
- invariant(isLikeC4NonJsonConfig(filepath.fsPath), `Invalid config file: ${filepath.fsPath}`);
21
- try {
22
- const cwd = dirname(filepath.fsPath);
23
- const { mod } = await bundleRequire({
24
- filepath: filepath.fsPath,
25
- cwd,
26
- esbuildOptions: {
27
- resolveExtensions: [".mjs", ".js", ".ts", ".mts"],
28
- plugins: [{
29
- name: "likec4-config",
30
- setup(build) {
31
- build.onResolve({ filter: /^@?likec4\/config$/ }, (args) => ({
32
- path: args.path,
33
- namespace: "likec4-config"
34
- }));
35
- build.onLoad({ filter: /.*/, namespace: "likec4-config" }, (args) => {
36
- return {
37
- contents: `
38
- function mockDefineConfig(x) { return x }
39
- export {
40
- mockDefineConfig as defineConfig,
41
- mockDefineConfig as defineGenerators,
42
- }`,
43
- loader: "js"
44
- };
45
- });
46
- }
47
- }]
48
- }
49
- });
50
- return defineConfig(mod?.default ?? mod);
51
- } catch (err) {
52
- logger.error(`Failed to load config file: ${filepath.fsPath}`, { err });
53
- throw err;
54
- }
55
- }
package/dist/schema.d.ts DELETED
@@ -1,149 +0,0 @@
1
- import type { DeploymentElementModel, DeploymentRelationModel, ElementModel, LikeC4Model, LikeC4ViewModel, RelationshipModel } from '@likec4/core/model';
2
- import type { aux, ProjectId } from '@likec4/core/types';
3
- import type Stream from 'node:stream';
4
- import type { URI } from 'vscode-uri';
5
- import * as z from 'zod';
6
- export declare const LikeC4ProjectJsonConfigSchema: z.ZodObject<{
7
- name: z.ZodPipe<z.ZodString, z.ZodTransform<any, string>>;
8
- title: z.ZodOptional<z.ZodString>;
9
- contactPerson: z.ZodOptional<z.ZodString>;
10
- imageAliases: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
11
- exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
12
- }, z.z.core.$strip>;
13
- export type LikeC4ProjectJsonConfig = z.input<typeof LikeC4ProjectJsonConfigSchema>;
14
- export declare const GeneratorsSchema: z.ZodRecord<z.ZodString, z.ZodCustom<Function, Function>>;
15
- export declare const LikeC4ProjectConfigSchema: z.ZodObject<{
16
- name: z.ZodPipe<z.ZodString, z.ZodTransform<any, string>>;
17
- title: z.ZodOptional<z.ZodString>;
18
- contactPerson: z.ZodOptional<z.ZodString>;
19
- imageAliases: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
20
- exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
21
- generators: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodCustom<Function, Function>>>;
22
- }, z.z.core.$strip>;
23
- export interface GeneratorFnContext {
24
- /**
25
- * Workspace root directory
26
- */
27
- readonly workspace: URI;
28
- /**
29
- * Current project
30
- */
31
- readonly project: {
32
- /**
33
- * Project name
34
- */
35
- readonly id: ProjectId;
36
- readonly title?: string;
37
- /**
38
- * Project folder
39
- */
40
- readonly folder: URI;
41
- };
42
- /**
43
- * Returns the location of the specified element, relation, view or deployment element
44
- */
45
- locate(target: ElementModel | RelationshipModel | DeploymentRelationModel | LikeC4ViewModel | DeploymentElementModel): {
46
- /**
47
- * Range inside the source file
48
- */
49
- range: {
50
- start: {
51
- line: number;
52
- character: number;
53
- };
54
- end: {
55
- line: number;
56
- character: number;
57
- };
58
- };
59
- /**
60
- * Full path to the source file
61
- */
62
- document: URI;
63
- /**
64
- * Document path relative to the project folder
65
- */
66
- relativePath: string;
67
- /**
68
- * Folder, containing the source file ("dirname" of document)
69
- */
70
- folder: string;
71
- /**
72
- * Source file name ("basename" of document)
73
- */
74
- filename: string;
75
- };
76
- /**
77
- * Write a file
78
- * @param path - Path to the file, either absolute or relative to the project folder
79
- * All folders will be created automatically
80
- * @param content - Content of the file
81
- */
82
- write(file: {
83
- path: string | string[] | URI;
84
- content: string | NodeJS.ArrayBufferView | Iterable<string | NodeJS.ArrayBufferView> | AsyncIterable<string | NodeJS.ArrayBufferView> | Stream;
85
- }): Promise<void>;
86
- /**
87
- * Abort the process
88
- */
89
- abort(reason?: string): never;
90
- }
91
- export type GeneratorFnParams = {
92
- /**
93
- * LikeC4 model
94
- */
95
- likec4model: LikeC4Model<aux.UnknownLayouted>;
96
- /**
97
- * Generator context
98
- */
99
- ctx: GeneratorFnContext;
100
- };
101
- export interface GeneratorFn {
102
- (params: GeneratorFnParams): Promise<void> | void;
103
- }
104
- /**
105
- * LikeC4 project configuration
106
- *
107
- * @example
108
- * ```ts
109
- * export default defineConfig({
110
- * name: 'my-project',
111
- * generators: {
112
- * 'my-generator': async ({ likec4model, ctx }) => {
113
- * await ctx.write('my-generator.txt', likec4model.project.id)
114
- * }
115
- * }
116
- * })
117
- * ```
118
- */
119
- export type LikeC4ProjectConfig = z.input<typeof LikeC4ProjectJsonConfigSchema> & {
120
- /**
121
- * Add custom generators to the project
122
- * @example
123
- * ```ts
124
- * export default defineConfig({
125
- * name: 'my-project',
126
- * generators: {
127
- * 'my-generator': async ({ likec4model, ctx }) => {
128
- * await ctx.write('my-generator.txt', likec4model.project.id)
129
- * }
130
- * }
131
- * })
132
- * ```
133
- *
134
- * Execute generator:
135
- * ```bash
136
- * likec4 gen my-generator
137
- * ```
138
- */
139
- generators?: Record<string, GeneratorFn> | undefined;
140
- };
141
- /**
142
- * Validates JSON string or JSON object into a LikeC4ProjectConfig object.
143
- */
144
- export declare function validateProjectConfig<C extends string | Record<string, unknown>>(config: C): LikeC4ProjectConfig;
145
- /**
146
- * Converts a LikeC4ProjectConfig object into a LikeC4ProjectJsonConfig object.
147
- * Omit generators property (as it is not serializable)
148
- */
149
- export declare function serializableLikeC4ProjectConfig({ generators, ...config }: LikeC4ProjectConfig): LikeC4ProjectJsonConfig;
@@ -1,5 +0,0 @@
1
- import * as z from 'zod';
2
- export declare const ImageAliasesSchema: z.ZodRecord<z.ZodString, z.ZodString>;
3
- type LikeC4ImageAliasConfig = z.infer<typeof ImageAliasesSchema>;
4
- export declare function validateImageAliases(imageAliases?: LikeC4ImageAliasConfig): void;
5
- export {};
@@ -1,42 +0,0 @@
1
- import * as z from "zod";
2
- const IMAGE_ALIAS_KEY_REGEX = /^@[A-Za-z0-9_-]*$/;
3
- const IMAGE_ALIAS_VALUE_REGEX = /^(?!\/|[A-Za-z]:[\\\/])(?!.*:\/\/).*$/;
4
- const ImageAliasValue = z.string().nonempty("Image alias value cannot be empty").regex(
5
- IMAGE_ALIAS_VALUE_REGEX,
6
- "Image alias value must be a relative path (no leading slash or protocol)"
7
- );
8
- export const ImageAliasesSchema = z.record(
9
- z.string(),
10
- // PLAIN key schema - valibot JSON schema export-safe.
11
- ImageAliasValue
12
- ).meta({
13
- description: "Map of image alias prefixes to relative paths (keys must match /^@\\w+$/; values must be relative paths without protocol or leading slash)."
14
- });
15
- export function validateImageAliases(imageAliases) {
16
- const invalidKeys = [];
17
- const invalidValues = [];
18
- if (imageAliases) {
19
- for (const [key, value] of Object.entries(imageAliases)) {
20
- if (!IMAGE_ALIAS_KEY_REGEX.test(key)) {
21
- invalidKeys.push(key);
22
- }
23
- if (!IMAGE_ALIAS_VALUE_REGEX.test(value)) {
24
- invalidValues.push(`${key} -> ${value}`);
25
- }
26
- }
27
- }
28
- if (invalidKeys.length || invalidValues.length) {
29
- const parts = [];
30
- if (invalidKeys.length) {
31
- parts.push(
32
- `Invalid image alias key(s): ${invalidKeys.map((k) => JSON.stringify(k)).join(", ")} (must match ${IMAGE_ALIAS_KEY_REGEX})`
33
- );
34
- }
35
- if (invalidValues.length) {
36
- parts.push(
37
- `Invalid image alias value(s): ${invalidValues.map((kv) => JSON.stringify(kv)).join(", ")} (must match ${IMAGE_ALIAS_VALUE_REGEX})`
38
- );
39
- }
40
- throw new Error(parts.join(" | "));
41
- }
42
- }
package/dist/schema.mjs DELETED
@@ -1,38 +0,0 @@
1
- import JSON5 from "json5";
2
- import * as z from "zod";
3
- import { ImageAliasesSchema, validateImageAliases } from "./schema.image-alias.mjs";
4
- export const LikeC4ProjectJsonConfigSchema = z.object({
5
- name: z.string().nonempty("Project name cannot be empty").refine((value) => value !== "default", {
6
- abort: true,
7
- error: 'Project name cannot be "default"'
8
- }).refine((value) => !value.includes(".") && !value.includes("@") && !value.includes("#"), {
9
- abort: true,
10
- error: 'Project name cannot contain ".", "@" or "#", try to use A-z, 0-9, _ and -'
11
- }).transform((value) => value).meta({ description: "Project name, must be unique in the workspace" }),
12
- title: z.string().nonempty("Project title cannot be empty if specified").optional().meta({ description: "A human readable title for the project" }),
13
- 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" }),
14
- imageAliases: ImageAliasesSchema.optional(),
15
- exclude: z.array(z.string()).optional().meta({ description: 'List of file patterns to exclude from the project, default is ["**/node_modules/**"]' })
16
- }).meta({
17
- description: "LikeC4 project configuration"
18
- });
19
- const FunctionType = z.instanceof(Function);
20
- export const GeneratorsSchema = z.record(z.string(), FunctionType);
21
- export const LikeC4ProjectConfigSchema = LikeC4ProjectJsonConfigSchema.extend({
22
- generators: GeneratorsSchema.optional()
23
- });
24
- export function validateProjectConfig(config) {
25
- const parsed = LikeC4ProjectConfigSchema.safeParse(
26
- typeof config === "string" ? JSON5.parse(config) : config
27
- );
28
- if (!parsed.success) {
29
- throw new Error("Config validation failed:\n" + z.prettifyError(parsed.error));
30
- }
31
- if (parsed.data.imageAliases) {
32
- validateImageAliases(parsed.data.imageAliases);
33
- }
34
- return parsed.data;
35
- }
36
- export function serializableLikeC4ProjectConfig({ generators, ...config }) {
37
- return LikeC4ProjectJsonConfigSchema.parse(config);
38
- }