utils-lab 0.0.1
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/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/index.d.mts +184 -0
- package/dist/index.mjs +305 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 - present, nakita628
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
//#region src/helper/makePropertiesGenerator.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Create a properties generator for a specific validation library
|
|
4
|
+
* Combines field filtering, comment cleaning, and code generation
|
|
5
|
+
* @param libraryPrefix - The library prefix (e.g., 'z', 'v')
|
|
6
|
+
* @returns A function that generates property definitions
|
|
7
|
+
*/
|
|
8
|
+
declare function makePropertiesGenerator(libraryPrefix: string): (modelFields: readonly {
|
|
9
|
+
readonly documentation: string;
|
|
10
|
+
readonly modelName: string;
|
|
11
|
+
readonly fieldName: string;
|
|
12
|
+
readonly validation: string | null;
|
|
13
|
+
readonly comment: readonly string[];
|
|
14
|
+
}[], includeComments: boolean) => string;
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/utils/index.d.ts
|
|
17
|
+
/**
|
|
18
|
+
* Capitalize the first character
|
|
19
|
+
*/
|
|
20
|
+
declare function makeCapitalized(str: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Convert camelCase/PascalCase to snake_case
|
|
23
|
+
*/
|
|
24
|
+
declare function makeSnakeCase(name: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Generate schema variable name
|
|
27
|
+
*/
|
|
28
|
+
declare function makeSchemaVarName(modelName: string): `${string}Schema`;
|
|
29
|
+
/**
|
|
30
|
+
* Generate relations variable name
|
|
31
|
+
*/
|
|
32
|
+
declare function makeRelationsVarName(modelName: string): `${string}Relations`;
|
|
33
|
+
/**
|
|
34
|
+
* Generate field reference
|
|
35
|
+
*/
|
|
36
|
+
declare function makeFieldReference(model: string, field: string): `${string}.${string}`;
|
|
37
|
+
/**
|
|
38
|
+
* Generate export const statement
|
|
39
|
+
*/
|
|
40
|
+
declare function makeExportConst(name: string, value: string): `export const ${string}=${string}`;
|
|
41
|
+
/**
|
|
42
|
+
* Generate export type statement
|
|
43
|
+
*/
|
|
44
|
+
declare function makeExportType(name: string, value: string): `export type ${string}=${string}`;
|
|
45
|
+
/**
|
|
46
|
+
* Check if string is a valid model name (PascalCase)
|
|
47
|
+
*/
|
|
48
|
+
declare function isModelName(str: string): str is `${Uppercase<string>}${string}`;
|
|
49
|
+
/**
|
|
50
|
+
* Check if string is a valid field name (camelCase)
|
|
51
|
+
*/
|
|
52
|
+
declare function isFieldName(str: string): str is `${Lowercase<string>}${string}`;
|
|
53
|
+
/**
|
|
54
|
+
* Check if string is a valid schema variable name
|
|
55
|
+
*/
|
|
56
|
+
declare function isSchemaVarName(str: string): str is `${Uppercase<string>}${string}Schema`;
|
|
57
|
+
/**
|
|
58
|
+
* Check if string is a valid relations variable name
|
|
59
|
+
*/
|
|
60
|
+
declare function isRelationsVarName(str: string): str is `${Lowercase<string>}${string}Relations`;
|
|
61
|
+
declare const RELATIONSHIP_SYMBOLS: {
|
|
62
|
+
readonly 'zero-one': "|o";
|
|
63
|
+
readonly one: "||";
|
|
64
|
+
readonly 'zero-many': "}o";
|
|
65
|
+
readonly many: "}|";
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Generate relationship symbol
|
|
69
|
+
*/
|
|
70
|
+
declare function makeRelationshipSymbol<T extends 'zero-one' | 'one' | 'zero-many' | 'many'>(type: T): (typeof RELATIONSHIP_SYMBOLS)[T];
|
|
71
|
+
/**
|
|
72
|
+
* Generate Mermaid connector
|
|
73
|
+
*/
|
|
74
|
+
declare function makeMermaidConnector<F extends 'zero-one' | 'one' | 'zero-many' | 'many', T extends 'zero-one' | 'one' | 'zero-many' | 'many'>(from: F, to: T, isOptional?: boolean): `${'|o' | '||' | '}o' | '}|'}${'--' | '..'}${'|o' | '||' | '}o' | '}|'}`;
|
|
75
|
+
/**
|
|
76
|
+
* Generate relation type
|
|
77
|
+
*/
|
|
78
|
+
declare function makeRelationType<F extends 'zero-one' | 'one' | 'zero-many' | 'many', T extends 'zero-one' | 'one' | 'zero-many' | 'many'>(from: F, to: T): `${F}-to-${T}`;
|
|
79
|
+
/**
|
|
80
|
+
* Generate parsed relation
|
|
81
|
+
*/
|
|
82
|
+
declare function makeParsedRelation<FM extends string, FF extends string, TM extends string, TF extends string, RT extends `${'zero-one' | 'one' | 'zero-many' | 'many'}-to-${'zero-one' | 'one' | 'zero-many' | 'many'}`>(fromModel: FM, fromField: FF, toModel: TM, toField: TF, type: RT): {
|
|
83
|
+
readonly from: `${FM}.${FF}`;
|
|
84
|
+
readonly to: `${TM}.${TF}`;
|
|
85
|
+
readonly type: RT;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Check if string is a valid relationship type
|
|
89
|
+
*/
|
|
90
|
+
declare function isRelationshipType(type: string): type is 'zero-one' | 'one' | 'zero-many' | 'many';
|
|
91
|
+
/**
|
|
92
|
+
* Check if string is a valid relation type
|
|
93
|
+
*/
|
|
94
|
+
declare function isRelationType(type: string): type is `${'zero-one' | 'one' | 'zero-many' | 'many'}-to-${'zero-one' | 'one' | 'zero-many' | 'many'}`;
|
|
95
|
+
/**
|
|
96
|
+
* Check if string is a valid Mermaid connector
|
|
97
|
+
*/
|
|
98
|
+
declare function isMermaidConnector(str: string): str is `${'|o' | '||' | '}o' | '}|'}${'--' | '..'}${'|o' | '||' | '}o' | '}|'}`;
|
|
99
|
+
/**
|
|
100
|
+
* Create a document parser that filters out annotation lines
|
|
101
|
+
*/
|
|
102
|
+
declare function makeDocumentParser(annotationPrefix: `@${string}.`): (documentation: string | undefined) => readonly string[];
|
|
103
|
+
/**
|
|
104
|
+
* Create a validation extractor for a specific annotation prefix
|
|
105
|
+
*/
|
|
106
|
+
declare function makeValidationExtractor(annotationPrefix: `@${string}.`): (documentation: string | undefined) => string | null;
|
|
107
|
+
/**
|
|
108
|
+
* Create an annotation extractor for a specific prefix
|
|
109
|
+
*/
|
|
110
|
+
declare function makeAnnotationExtractor(annotationPrefix: `@${string}.`): (documentation: string) => string | null;
|
|
111
|
+
/**
|
|
112
|
+
* Create a JSDoc string from documentation lines
|
|
113
|
+
*/
|
|
114
|
+
declare function makeJsDoc(documentation: string | undefined, excludePrefixes?: readonly `@${string}.`[]): string;
|
|
115
|
+
/**
|
|
116
|
+
* Create a comment cleaner that removes triple-slash prefixes
|
|
117
|
+
*/
|
|
118
|
+
declare function makeCleanedCommentLines(lines: readonly string[]): readonly string[];
|
|
119
|
+
/**
|
|
120
|
+
* Create a clean documentation comment from model fields
|
|
121
|
+
*/
|
|
122
|
+
declare function makeCleanDocComment(commentLines: readonly string[], annotationPrefixes?: readonly string[]): string;
|
|
123
|
+
/**
|
|
124
|
+
* Check if string is a valid annotation prefix
|
|
125
|
+
*/
|
|
126
|
+
declare function isAnnotationPrefix(str: string): str is `@${string}.`;
|
|
127
|
+
/**
|
|
128
|
+
* Check if documentation contains a specific annotation
|
|
129
|
+
*/
|
|
130
|
+
declare function hasAnnotation(documentation: string | undefined, prefix: `@${string}.`): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Create Zod type inference line
|
|
133
|
+
*/
|
|
134
|
+
declare function makeZodInfer(modelName: string): `export type ${string} = z.infer<typeof ${string}Schema>`;
|
|
135
|
+
/**
|
|
136
|
+
* Create Valibot type inference line
|
|
137
|
+
*/
|
|
138
|
+
declare function makeValibotInfer(modelName: string): `export type ${string} = v.InferInput<typeof ${string}Schema>`;
|
|
139
|
+
/**
|
|
140
|
+
* Create ArkType type inference line
|
|
141
|
+
*/
|
|
142
|
+
declare function makeArkTypeInfer(modelName: string): `export type ${string} = typeof ${string}Schema.infer`;
|
|
143
|
+
/**
|
|
144
|
+
* Create Effect Schema type inference line
|
|
145
|
+
*/
|
|
146
|
+
declare function makeEffectSchemaInfer(modelName: string): `export type ${string} = Schema.Schema.Type<typeof ${string}Schema>`;
|
|
147
|
+
/**
|
|
148
|
+
* Create Zod import statement
|
|
149
|
+
*/
|
|
150
|
+
declare function makeZodImport(variant?: 'v4' | 'mini' | '@hono/zod-openapi'): string;
|
|
151
|
+
/**
|
|
152
|
+
* Create Valibot import statement
|
|
153
|
+
*/
|
|
154
|
+
declare function makeValibotImport(): string;
|
|
155
|
+
/**
|
|
156
|
+
* Create ArkType import statement
|
|
157
|
+
*/
|
|
158
|
+
declare function makeArkTypeImport(): string;
|
|
159
|
+
/**
|
|
160
|
+
* Create Effect Schema import statement
|
|
161
|
+
*/
|
|
162
|
+
declare function makeEffectSchemaImport(): string;
|
|
163
|
+
/**
|
|
164
|
+
* Create Zod object wrapper
|
|
165
|
+
*/
|
|
166
|
+
declare function makeZodObject(inner: string, wrapperType?: 'object' | 'strictObject' | 'looseObject'): string;
|
|
167
|
+
/**
|
|
168
|
+
* Create Valibot object wrapper
|
|
169
|
+
*/
|
|
170
|
+
declare function makeValibotObject(inner: string, wrapperType?: 'object' | 'strictObject' | 'looseObject'): string;
|
|
171
|
+
/**
|
|
172
|
+
* Create Zod cardinality wrapper (array + optional)
|
|
173
|
+
*/
|
|
174
|
+
declare function makeZodCardinality(expr: string, isList: boolean, isRequired: boolean): string;
|
|
175
|
+
/**
|
|
176
|
+
* Create Valibot cardinality wrapper (array + optional)
|
|
177
|
+
*/
|
|
178
|
+
declare function makeValibotCardinality(expr: string, isList: boolean, isRequired: boolean): string;
|
|
179
|
+
/**
|
|
180
|
+
* Check if string is a valid object wrapper type
|
|
181
|
+
*/
|
|
182
|
+
declare function isObjectWrapperType(type: string): type is 'object' | 'strictObject' | 'looseObject';
|
|
183
|
+
//#endregion
|
|
184
|
+
export { hasAnnotation, isAnnotationPrefix, isFieldName, isMermaidConnector, isModelName, isObjectWrapperType, isRelationType, isRelationsVarName, isRelationshipType, isSchemaVarName, makeAnnotationExtractor, makeArkTypeImport, makeArkTypeInfer, makeCapitalized, makeCleanDocComment, makeCleanedCommentLines, makeDocumentParser, makeEffectSchemaImport, makeEffectSchemaInfer, makeExportConst, makeExportType, makeFieldReference, makeJsDoc, makeMermaidConnector, makeParsedRelation, makePropertiesGenerator, makeRelationType, makeRelationsVarName, makeRelationshipSymbol, makeSchemaVarName, makeSnakeCase, makeValibotCardinality, makeValibotImport, makeValibotInfer, makeValibotObject, makeValidationExtractor, makeZodCardinality, makeZodImport, makeZodInfer, makeZodObject };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
//#region src/helper/makePropertiesGenerator.ts
|
|
2
|
+
/**
|
|
3
|
+
* Create a properties generator for a specific validation library
|
|
4
|
+
* Combines field filtering, comment cleaning, and code generation
|
|
5
|
+
* @param libraryPrefix - The library prefix (e.g., 'z', 'v')
|
|
6
|
+
* @returns A function that generates property definitions
|
|
7
|
+
*/
|
|
8
|
+
function makePropertiesGenerator(libraryPrefix) {
|
|
9
|
+
return function generateProperties(modelFields, includeComments) {
|
|
10
|
+
return modelFields.filter((field) => field.validation).map((field) => {
|
|
11
|
+
const cleanLines = field.comment.filter((line) => !(line.includes("@relation") || line.includes("@v") || line.includes("@z")));
|
|
12
|
+
return `${includeComments && cleanLines.length > 0 ? ` /**\n${cleanLines.map((line) => ` * ${line}`).join("\n")}\n */\n` : ""} ${field.fieldName}: ${libraryPrefix}.${field.validation}`;
|
|
13
|
+
}).join(",\n");
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/utils/index.ts
|
|
19
|
+
/**
|
|
20
|
+
* Capitalize the first character
|
|
21
|
+
*/
|
|
22
|
+
function makeCapitalized(str) {
|
|
23
|
+
return `${str.charAt(0).toUpperCase()}${str.slice(1)}`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Convert camelCase/PascalCase to snake_case
|
|
27
|
+
*/
|
|
28
|
+
function makeSnakeCase(name) {
|
|
29
|
+
return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generate schema variable name
|
|
33
|
+
*/
|
|
34
|
+
function makeSchemaVarName(modelName) {
|
|
35
|
+
return `${makeCapitalized(modelName)}Schema`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Generate relations variable name
|
|
39
|
+
*/
|
|
40
|
+
function makeRelationsVarName(modelName) {
|
|
41
|
+
return `${modelName.charAt(0).toLowerCase()}${modelName.slice(1)}Relations`;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Generate field reference
|
|
45
|
+
*/
|
|
46
|
+
function makeFieldReference(model, field) {
|
|
47
|
+
return `${model}.${field}`;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Generate export const statement
|
|
51
|
+
*/
|
|
52
|
+
function makeExportConst(name, value) {
|
|
53
|
+
return `export const ${name}=${value}`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Generate export type statement
|
|
57
|
+
*/
|
|
58
|
+
function makeExportType(name, value) {
|
|
59
|
+
return `export type ${name}=${value}`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if string is a valid model name (PascalCase)
|
|
63
|
+
*/
|
|
64
|
+
function isModelName(str) {
|
|
65
|
+
return /^[A-Z][a-zA-Z0-9]*$/.test(str);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Check if string is a valid field name (camelCase)
|
|
69
|
+
*/
|
|
70
|
+
function isFieldName(str) {
|
|
71
|
+
return /^[a-z][a-zA-Z0-9]*$/.test(str);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Check if string is a valid schema variable name
|
|
75
|
+
*/
|
|
76
|
+
function isSchemaVarName(str) {
|
|
77
|
+
return /^[A-Z][a-zA-Z0-9]*Schema$/.test(str);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Check if string is a valid relations variable name
|
|
81
|
+
*/
|
|
82
|
+
function isRelationsVarName(str) {
|
|
83
|
+
return /^[a-z][a-zA-Z0-9]*Relations$/.test(str);
|
|
84
|
+
}
|
|
85
|
+
const RELATIONSHIP_SYMBOLS = {
|
|
86
|
+
"zero-one": "|o",
|
|
87
|
+
one: "||",
|
|
88
|
+
"zero-many": "}o",
|
|
89
|
+
many: "}|"
|
|
90
|
+
};
|
|
91
|
+
const RELATIONSHIP_TYPES = [
|
|
92
|
+
"zero-one",
|
|
93
|
+
"one",
|
|
94
|
+
"zero-many",
|
|
95
|
+
"many"
|
|
96
|
+
];
|
|
97
|
+
/**
|
|
98
|
+
* Generate relationship symbol
|
|
99
|
+
*/
|
|
100
|
+
function makeRelationshipSymbol(type) {
|
|
101
|
+
return RELATIONSHIP_SYMBOLS[type];
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Generate Mermaid connector
|
|
105
|
+
*/
|
|
106
|
+
function makeMermaidConnector(from, to, isOptional) {
|
|
107
|
+
const fromSymbol = makeRelationshipSymbol(from);
|
|
108
|
+
const toSymbol = makeRelationshipSymbol(to);
|
|
109
|
+
return `${fromSymbol}${isOptional ? ".." : "--"}${toSymbol}`;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Generate relation type
|
|
113
|
+
*/
|
|
114
|
+
function makeRelationType(from, to) {
|
|
115
|
+
return `${from}-to-${to}`;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Generate parsed relation
|
|
119
|
+
*/
|
|
120
|
+
function makeParsedRelation(fromModel, fromField, toModel, toField, type) {
|
|
121
|
+
return {
|
|
122
|
+
from: `${fromModel}.${fromField}`,
|
|
123
|
+
to: `${toModel}.${toField}`,
|
|
124
|
+
type
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Check if string is a valid relationship type
|
|
129
|
+
*/
|
|
130
|
+
function isRelationshipType(type) {
|
|
131
|
+
return RELATIONSHIP_TYPES.includes(type);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check if string is a valid relation type
|
|
135
|
+
*/
|
|
136
|
+
function isRelationType(type) {
|
|
137
|
+
const match = type.match(/^(.+)-to-(.+)$/);
|
|
138
|
+
if (!(match?.[1] && match[2])) return false;
|
|
139
|
+
return isRelationshipType(match[1]) && isRelationshipType(match[2]);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Check if string is a valid Mermaid connector
|
|
143
|
+
*/
|
|
144
|
+
function isMermaidConnector(str) {
|
|
145
|
+
return /^(\|o|\|\||\}o|\}\|)(--|\.\.)(\|o|\|\||\}o|\}\|)$/.test(str);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Create a document parser that filters out annotation lines
|
|
149
|
+
*/
|
|
150
|
+
function makeDocumentParser(annotationPrefix) {
|
|
151
|
+
return function parseDocument(documentation) {
|
|
152
|
+
return documentation?.split("\n").map((line) => line.trim()).filter((line) => line && !line.includes(annotationPrefix)) ?? [];
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Create a validation extractor for a specific annotation prefix
|
|
157
|
+
*/
|
|
158
|
+
function makeValidationExtractor(annotationPrefix) {
|
|
159
|
+
const escaped = annotationPrefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
160
|
+
const regex = new RegExp(`${escaped}(.+?)(?:\\n|$)`);
|
|
161
|
+
return function extractValidation(documentation) {
|
|
162
|
+
if (!documentation) return null;
|
|
163
|
+
return documentation.match(regex)?.[1]?.trim() ?? null;
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Create an annotation extractor for a specific prefix
|
|
168
|
+
*/
|
|
169
|
+
function makeAnnotationExtractor(annotationPrefix) {
|
|
170
|
+
return function extractAnnotation(documentation) {
|
|
171
|
+
const line = documentation.split("\n").map((s) => s.trim()).find((l) => l.startsWith(annotationPrefix));
|
|
172
|
+
return line ? line.slice(annotationPrefix.length) : null;
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Create a JSDoc string from documentation lines
|
|
177
|
+
*/
|
|
178
|
+
function makeJsDoc(documentation, excludePrefixes = ["@z.", "@v."]) {
|
|
179
|
+
const lines = (documentation ?? "").split("\n").map((s) => s.trim()).filter((l) => l && !excludePrefixes.some((prefix) => l.startsWith(prefix)));
|
|
180
|
+
return lines.length ? `/**\n * ${lines.join("\n * ")}\n */\n` : "";
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Create a comment cleaner that removes triple-slash prefixes
|
|
184
|
+
*/
|
|
185
|
+
function makeCleanedCommentLines(lines) {
|
|
186
|
+
return lines.map((line) => line.replace(/^\/\/\/\s*/, "").trim()).filter(Boolean);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Create a clean documentation comment from model fields
|
|
190
|
+
*/
|
|
191
|
+
function makeCleanDocComment(commentLines, annotationPrefixes = [
|
|
192
|
+
"@relation",
|
|
193
|
+
"@v",
|
|
194
|
+
"@z"
|
|
195
|
+
]) {
|
|
196
|
+
return commentLines.filter((line) => !annotationPrefixes.some((prefix) => line.includes(prefix))).join("\n").trim();
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Check if string is a valid annotation prefix
|
|
200
|
+
*/
|
|
201
|
+
function isAnnotationPrefix(str) {
|
|
202
|
+
return /^@[a-z]+\.$/.test(str);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Check if documentation contains a specific annotation
|
|
206
|
+
*/
|
|
207
|
+
function hasAnnotation(documentation, prefix) {
|
|
208
|
+
if (!documentation) return false;
|
|
209
|
+
return documentation.includes(prefix);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Create Zod type inference line
|
|
213
|
+
*/
|
|
214
|
+
function makeZodInfer(modelName) {
|
|
215
|
+
return `export type ${modelName} = z.infer<typeof ${modelName}Schema>`;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Create Valibot type inference line
|
|
219
|
+
*/
|
|
220
|
+
function makeValibotInfer(modelName) {
|
|
221
|
+
return `export type ${modelName} = v.InferInput<typeof ${modelName}Schema>`;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Create ArkType type inference line
|
|
225
|
+
*/
|
|
226
|
+
function makeArkTypeInfer(modelName) {
|
|
227
|
+
return `export type ${modelName} = typeof ${modelName}Schema.infer`;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Create Effect Schema type inference line
|
|
231
|
+
*/
|
|
232
|
+
function makeEffectSchemaInfer(modelName) {
|
|
233
|
+
return `export type ${modelName} = Schema.Schema.Type<typeof ${modelName}Schema>`;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Create Zod import statement
|
|
237
|
+
*/
|
|
238
|
+
function makeZodImport(variant) {
|
|
239
|
+
switch (variant) {
|
|
240
|
+
case "mini": return `import * as z from 'zod/mini'`;
|
|
241
|
+
case "@hono/zod-openapi": return `import { z } from '@hono/zod-openapi'`;
|
|
242
|
+
default: return `import * as z from 'zod'`;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Create Valibot import statement
|
|
247
|
+
*/
|
|
248
|
+
function makeValibotImport() {
|
|
249
|
+
return `import * as v from 'valibot'`;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Create ArkType import statement
|
|
253
|
+
*/
|
|
254
|
+
function makeArkTypeImport() {
|
|
255
|
+
return `import { type } from 'arktype'`;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Create Effect Schema import statement
|
|
259
|
+
*/
|
|
260
|
+
function makeEffectSchemaImport() {
|
|
261
|
+
return `import { Schema } from 'effect'`;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Create Zod object wrapper
|
|
265
|
+
*/
|
|
266
|
+
function makeZodObject(inner, wrapperType = "object") {
|
|
267
|
+
switch (wrapperType) {
|
|
268
|
+
case "strictObject": return `z.strictObject({${inner}})`;
|
|
269
|
+
case "looseObject": return `z.looseObject({${inner}})`;
|
|
270
|
+
default: return `z.object({${inner}})`;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Create Valibot object wrapper
|
|
275
|
+
*/
|
|
276
|
+
function makeValibotObject(inner, wrapperType = "object") {
|
|
277
|
+
switch (wrapperType) {
|
|
278
|
+
case "strictObject": return `v.strictObject({${inner}})`;
|
|
279
|
+
case "looseObject": return `v.looseObject({${inner}})`;
|
|
280
|
+
default: return `v.object({${inner}})`;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Create Zod cardinality wrapper (array + optional)
|
|
285
|
+
*/
|
|
286
|
+
function makeZodCardinality(expr, isList, isRequired) {
|
|
287
|
+
const withList = isList ? `z.array(${expr})` : expr;
|
|
288
|
+
return isRequired ? withList : `${withList}.optional()`;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Create Valibot cardinality wrapper (array + optional)
|
|
292
|
+
*/
|
|
293
|
+
function makeValibotCardinality(expr, isList, isRequired) {
|
|
294
|
+
const withList = isList ? `v.array(${expr})` : expr;
|
|
295
|
+
return isRequired ? withList : `v.optional(${withList})`;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Check if string is a valid object wrapper type
|
|
299
|
+
*/
|
|
300
|
+
function isObjectWrapperType(type) {
|
|
301
|
+
return type === "object" || type === "strictObject" || type === "looseObject";
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
//#endregion
|
|
305
|
+
export { hasAnnotation, isAnnotationPrefix, isFieldName, isMermaidConnector, isModelName, isObjectWrapperType, isRelationType, isRelationsVarName, isRelationshipType, isSchemaVarName, makeAnnotationExtractor, makeArkTypeImport, makeArkTypeInfer, makeCapitalized, makeCleanDocComment, makeCleanedCommentLines, makeDocumentParser, makeEffectSchemaImport, makeEffectSchemaInfer, makeExportConst, makeExportType, makeFieldReference, makeJsDoc, makeMermaidConnector, makeParsedRelation, makePropertiesGenerator, makeRelationType, makeRelationsVarName, makeRelationshipSymbol, makeSchemaVarName, makeSnakeCase, makeValibotCardinality, makeValibotImport, makeValibotInfer, makeValibotObject, makeValidationExtractor, makeZodCardinality, makeZodImport, makeZodInfer, makeZodObject };
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "utils-lab",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Utility functions for schema code generation (Zod, Valibot, ArkType, Effect Schema)",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"zod",
|
|
8
|
+
"valibot",
|
|
9
|
+
"arktype",
|
|
10
|
+
"effect-schema",
|
|
11
|
+
"mermaid",
|
|
12
|
+
"schema",
|
|
13
|
+
"codegen"
|
|
14
|
+
],
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"author": "nakita628",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/nakita628/utils-lab"
|
|
20
|
+
},
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"import": "./dist/index.mjs",
|
|
24
|
+
"types": "./dist/index.d.mts"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"main": "./dist/index.mjs",
|
|
28
|
+
"types": "./dist/index.d.mts",
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"files": [
|
|
31
|
+
"dist"
|
|
32
|
+
],
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@biomejs/biome": "^2.3.13",
|
|
35
|
+
"@types/node": "^25.1.0",
|
|
36
|
+
"@typescript/native-preview": "7.0.0-dev.20260129.1",
|
|
37
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
38
|
+
"tsdown": "^0.20.1",
|
|
39
|
+
"typescript": "^5.9.3",
|
|
40
|
+
"vitest": "^4.0.18"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsdown",
|
|
44
|
+
"check": "pnpm biome check --write ./",
|
|
45
|
+
"typecheck": "tsgo --noEmit",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"coverage": "vitest run --coverage",
|
|
48
|
+
"release": "pnpm build && pnpm publish"
|
|
49
|
+
}
|
|
50
|
+
}
|