sizuku 0.0.7 → 0.2.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/README.md +96 -344
- package/dist/cli/main.d.ts +10 -0
- package/dist/cli/main.js +61 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +51 -0
- package/dist/config/index.d.ts +18 -0
- package/dist/config/index.js +13 -0
- package/dist/config/loader.d.ts +19 -0
- package/dist/config/loader.js +30 -0
- package/dist/generator/engine.d.ts +3 -0
- package/dist/generator/engine.js +63 -0
- package/dist/generator/mermaid-er/config/index.d.ts +4 -4
- package/dist/generator/mermaid-er/config/index.js +4 -10
- package/dist/generator/mermaid-er/core/extract-relations.d.ts +1 -1
- package/dist/generator/mermaid-er/core/extract-relations.js +3 -6
- package/dist/generator/mermaid-er/core.d.ts +6 -0
- package/dist/generator/mermaid-er/core.js +54 -0
- package/dist/generator/mermaid-er/generator/er-content.d.ts +20 -0
- package/dist/generator/mermaid-er/generator/{generate-er-content.js → er-content.js} +3 -7
- package/dist/generator/mermaid-er/generator/index.d.ts +2 -0
- package/dist/generator/mermaid-er/generator/index.js +2 -0
- package/dist/generator/mermaid-er/generator/relation-line.d.ts +12 -0
- package/dist/generator/mermaid-er/generator/{generate-relation-line.js → relation-line.js} +3 -6
- package/dist/generator/mermaid-er/generator.d.ts +3 -0
- package/dist/generator/mermaid-er/generator.js +14 -0
- package/dist/generator/mermaid-er/index.d.ts +12 -5
- package/dist/generator/mermaid-er/index.js +30 -74
- package/dist/generator/mermaid-er/relationship/build-relation-line.js +3 -6
- package/dist/generator/mermaid-er/types.js +1 -0
- package/dist/generator/mermaid-er/validator/index.d.ts +8 -0
- package/dist/generator/mermaid-er/validator/index.js +71 -0
- package/dist/generator/mermaid-er/validator/is-relationship.d.ts +1 -1
- package/dist/generator/mermaid-er/validator/is-relationship.js +1 -4
- package/dist/generator/mermaid-er/validator/parse-relation-line.js +1 -4
- package/dist/generator/mermaid-er/validator/parse-table-info.d.ts +1 -7
- package/dist/generator/mermaid-er/validator/parse-table-info.js +69 -89
- package/dist/generator/mermaid-er/validator/remove-duplicate-relations.js +1 -4
- package/dist/generator/valibot/config/index.d.ts +2 -2
- package/dist/generator/valibot/config/index.js +6 -12
- package/dist/generator/valibot/core/extract-schema.d.ts +2 -5
- package/dist/generator/valibot/core/extract-schema.js +162 -81
- package/dist/generator/valibot/core.d.ts +5 -0
- package/dist/generator/valibot/core.js +39 -0
- package/dist/generator/valibot/generator/infer-input.d.ts +5 -0
- package/dist/generator/valibot/generator/infer-input.js +8 -0
- package/dist/generator/valibot/generator/relation-valibot-code.d.ts +13 -0
- package/dist/generator/valibot/generator/relation-valibot-code.js +19 -0
- package/dist/generator/valibot/generator/valibot-code.d.ts +15 -0
- package/dist/generator/valibot/generator/valibot-code.js +16 -0
- package/dist/generator/valibot/generator/valibot.d.ts +14 -0
- package/dist/generator/valibot/generator/valibot.js +15 -0
- package/dist/generator/valibot/generator.d.ts +3 -0
- package/dist/generator/valibot/generator.js +14 -0
- package/dist/generator/valibot/index.d.ts +14 -3
- package/dist/generator/valibot/index.js +46 -73
- package/dist/generator/zod/config/index.d.ts +2 -2
- package/dist/generator/zod/config/index.js +6 -12
- package/dist/generator/zod/core/extract-schema.d.ts +1 -2
- package/dist/generator/zod/core/extract-schema.js +228 -81
- package/dist/generator/zod/core.d.ts +5 -0
- package/dist/generator/zod/core.js +39 -0
- package/dist/generator/zod/generator/infer.d.ts +5 -0
- package/dist/generator/zod/generator/infer.js +8 -0
- package/dist/generator/zod/generator/relation-zod-code.d.ts +13 -0
- package/dist/generator/zod/generator/relation-zod-code.js +19 -0
- package/dist/generator/zod/generator/zod-code.d.ts +17 -0
- package/dist/generator/zod/generator/zod-code.js +18 -0
- package/dist/generator/zod/generator/zod.d.ts +16 -0
- package/dist/generator/zod/generator/zod.js +16 -0
- package/dist/generator/zod/generator.d.ts +3 -0
- package/dist/generator/zod/generator.js +14 -0
- package/dist/generator/zod/index.d.ts +15 -3
- package/dist/generator/zod/index.js +50 -73
- package/dist/index.d.ts +8 -0
- package/dist/index.js +71 -0
- package/dist/shared/config/index.d.ts +13 -0
- package/dist/{common → shared}/config/index.js +1 -4
- package/dist/shared/format/index.d.ts +15 -0
- package/dist/shared/format/index.js +24 -0
- package/dist/shared/fs/index.d.ts +7 -0
- package/dist/shared/fs/index.js +16 -0
- package/dist/shared/fsp/index.d.ts +27 -0
- package/dist/shared/fsp/index.js +38 -0
- package/dist/shared/generator/field-definitions.d.ts +12 -0
- package/dist/shared/generator/field-definitions.js +12 -0
- package/dist/shared/helper/ast-parser.d.ts +3 -0
- package/dist/shared/helper/ast-parser.js +202 -0
- package/dist/shared/helper/build-schema-extractor.d.ts +25 -0
- package/dist/shared/helper/build-schema-extractor.js +33 -0
- package/dist/shared/helper/create-extract-field-from-property.d.ts +15 -0
- package/dist/shared/helper/create-extract-field-from-property.js +20 -0
- package/dist/shared/helper/create-extract-fields-from-call-expression.d.ts +14 -0
- package/dist/shared/helper/create-extract-fields-from-call-expression.js +14 -0
- package/dist/shared/helper/create-extract-relation-field-from-property.d.ts +12 -0
- package/dist/shared/helper/create-extract-relation-field-from-property.js +27 -0
- package/dist/shared/helper/extract-schemas.d.ts +133 -0
- package/dist/shared/helper/extract-schemas.js +445 -0
- package/dist/shared/helper/file-writer.d.ts +3 -0
- package/dist/shared/helper/file-writer.js +25 -0
- package/dist/shared/helper/find-object-literal-expression.d.ts +12 -0
- package/dist/shared/helper/find-object-literal-expression.js +31 -0
- package/dist/shared/helper/find-object-literalIn-args.d.ts +2 -0
- package/dist/shared/helper/find-object-literalIn-args.js +8 -0
- package/dist/shared/helper/is-relation-function.d.ts +10 -0
- package/dist/shared/helper/is-relation-function.js +16 -0
- package/dist/shared/types.js +1 -0
- package/dist/{common/text → shared/utils}/capitalize.js +1 -4
- package/dist/shared/utils/compose.d.ts +101 -0
- package/dist/shared/utils/compose.js +124 -0
- package/dist/shared/utils/file.d.ts +92 -0
- package/dist/shared/utils/file.js +177 -0
- package/dist/shared/utils/functional.d.ts +118 -0
- package/dist/shared/utils/functional.js +96 -0
- package/dist/shared/utils/index.d.ts +20 -0
- package/dist/shared/utils/index.js +48 -0
- package/dist/shared/utils/string-utils.d.ts +8 -0
- package/dist/shared/utils/string-utils.js +28 -0
- package/dist/shared/utils/types.d.ts +32 -0
- package/dist/shared/utils/types.js +2 -0
- package/dist/shared/utils/validation-utils.d.ts +8 -0
- package/dist/shared/utils/validation-utils.js +25 -0
- package/dist/src/config/index.d.ts +18 -0
- package/dist/src/config/index.js +13 -0
- package/dist/src/generator/mermaid-er/core/extract-relations.d.ts +8 -0
- package/dist/src/generator/mermaid-er/core/extract-relations.js +12 -0
- package/dist/src/generator/mermaid-er/generator/er-content.d.ts +9 -0
- package/dist/src/generator/mermaid-er/generator/er-content.js +25 -0
- package/dist/src/generator/mermaid-er/generator/index.d.ts +2 -0
- package/dist/src/generator/mermaid-er/generator/index.js +2 -0
- package/dist/src/generator/mermaid-er/generator/relation-line.d.ts +8 -0
- package/dist/src/generator/mermaid-er/generator/relation-line.js +14 -0
- package/dist/src/generator/mermaid-er/index.d.ts +6 -0
- package/dist/src/generator/mermaid-er/index.js +16 -0
- package/dist/src/generator/mermaid-er/relationship/build-relation-line.d.ts +15 -0
- package/dist/src/generator/mermaid-er/relationship/build-relation-line.js +35 -0
- package/dist/src/generator/mermaid-er/types.d.ts +21 -0
- package/dist/src/generator/mermaid-er/types.js +1 -0
- package/dist/src/generator/mermaid-er/validator/index.d.ts +4 -0
- package/dist/src/generator/mermaid-er/validator/index.js +4 -0
- package/dist/src/generator/mermaid-er/validator/is-relationship.d.ts +8 -0
- package/dist/src/generator/mermaid-er/validator/is-relationship.js +9 -0
- package/dist/src/generator/mermaid-er/validator/parse-relation-line.d.ts +13 -0
- package/dist/src/generator/mermaid-er/validator/parse-relation-line.js +21 -0
- package/dist/src/generator/mermaid-er/validator/parse-table-info.d.ts +8 -0
- package/dist/src/generator/mermaid-er/validator/parse-table-info.js +91 -0
- package/dist/src/generator/mermaid-er/validator/remove-duplicate-relations.d.ts +7 -0
- package/dist/src/generator/mermaid-er/validator/remove-duplicate-relations.js +9 -0
- package/dist/src/generator/valibot/generator/infer-input.d.ts +5 -0
- package/dist/src/generator/valibot/generator/infer-input.js +8 -0
- package/dist/src/generator/valibot/generator/valibot-code.d.ts +14 -0
- package/dist/src/generator/valibot/generator/valibot-code.js +16 -0
- package/dist/src/generator/valibot/generator/valibot.d.ts +13 -0
- package/dist/src/generator/valibot/generator/valibot.js +11 -0
- package/dist/src/generator/valibot/index.d.ts +9 -0
- package/dist/src/generator/valibot/index.js +34 -0
- package/dist/src/generator/zod/generator/infer.d.ts +5 -0
- package/dist/src/generator/zod/generator/infer.js +8 -0
- package/dist/{generator/zod/generator/generate-zod-code.d.ts → src/generator/zod/generator/zod-code.d.ts} +8 -3
- package/dist/src/generator/zod/generator/zod-code.js +18 -0
- package/dist/{generator/zod/generator/generate-zod-schema.d.ts → src/generator/zod/generator/zod.d.ts} +8 -4
- package/dist/src/generator/zod/generator/zod.js +12 -0
- package/dist/src/generator/zod/index.d.ts +10 -0
- package/dist/src/generator/zod/index.js +40 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.js +35 -0
- package/dist/src/shared/format/index.d.ts +2 -0
- package/dist/src/shared/format/index.js +10 -0
- package/dist/src/shared/fs/index.d.ts +2 -0
- package/dist/src/shared/fs/index.js +10 -0
- package/dist/src/shared/fsp/index.d.ts +3 -0
- package/dist/src/shared/fsp/index.js +8 -0
- package/dist/src/shared/generator/field-definitions.d.ts +12 -0
- package/dist/src/shared/generator/field-definitions.js +12 -0
- package/dist/src/shared/helper/build-schema-extractor.d.ts +25 -0
- package/dist/src/shared/helper/build-schema-extractor.js +33 -0
- package/dist/src/shared/helper/create-extract-field-from-property.d.ts +15 -0
- package/dist/src/shared/helper/create-extract-field-from-property.js +20 -0
- package/dist/src/shared/helper/create-extract-fields-from-call-expression.d.ts +14 -0
- package/dist/src/shared/helper/create-extract-fields-from-call-expression.js +14 -0
- package/dist/src/shared/helper/create-extract-relation-field-from-property.d.ts +12 -0
- package/dist/src/shared/helper/create-extract-relation-field-from-property.js +27 -0
- package/dist/src/shared/helper/extract-schemas.d.ts +16 -0
- package/dist/src/shared/helper/extract-schemas.js +19 -0
- package/dist/src/shared/helper/find-object-literal-expression.d.ts +12 -0
- package/dist/src/shared/helper/find-object-literal-expression.js +31 -0
- package/dist/src/shared/helper/find-object-literalIn-args.d.ts +2 -0
- package/dist/src/shared/helper/find-object-literalIn-args.js +8 -0
- package/dist/src/shared/helper/is-relation-function.d.ts +10 -0
- package/dist/src/shared/helper/is-relation-function.js +16 -0
- package/dist/src/shared/utils/index.d.ts +33 -0
- package/dist/src/shared/utils/index.js +61 -0
- package/dist/utils/index.d.ts +144 -0
- package/dist/utils/index.js +301 -0
- package/package.json +10 -13
- package/dist/common/config/index.d.ts +0 -13
- package/dist/common/format/index.d.ts +0 -1
- package/dist/common/format/index.js +0 -12
- package/dist/common/generator/generate-field-definitions.d.ts +0 -8
- package/dist/common/generator/generate-field-definitions.js +0 -16
- package/dist/common/helper/get-camel-case-schema-name-helper.d.ts +0 -7
- package/dist/common/helper/get-camel-case-schema-name-helper.js +0 -14
- package/dist/common/helper/get-pascal-case-schema-name-helper.d.ts +0 -8
- package/dist/common/helper/get-pascal-case-schema-name-helper.js +0 -15
- package/dist/common/helper/get-variable-name-helper.d.ts +0 -9
- package/dist/common/helper/get-variable-name-helper.js +0 -15
- package/dist/common/helper/get-variable-schema-name-helper.d.ts +0 -9
- package/dist/common/helper/get-variable-schema-name-helper.js +0 -17
- package/dist/common/text/decapitalize.d.ts +0 -17
- package/dist/common/text/decapitalize.js +0 -22
- package/dist/common/type/index.js +0 -2
- package/dist/generator/mermaid-er/generator/generate-er-content.d.ts +0 -9
- package/dist/generator/mermaid-er/generator/generate-relation-line.d.ts +0 -7
- package/dist/generator/mermaid-er/type/index.js +0 -2
- package/dist/generator/mermaid-er/validator/is-relation.d.ts +0 -7
- package/dist/generator/mermaid-er/validator/is-relation.js +0 -40
- package/dist/generator/valibot/generator/generate-valibot-code.d.ts +0 -11
- package/dist/generator/valibot/generator/generate-valibot-code.js +0 -21
- package/dist/generator/valibot/generator/generate-valibot-infer-input.d.ts +0 -9
- package/dist/generator/valibot/generator/generate-valibot-infer-input.js +0 -16
- package/dist/generator/valibot/generator/generate-valibot-schema.d.ts +0 -9
- package/dist/generator/valibot/generator/generate-valibot-schema.js +0 -16
- package/dist/generator/zod/generator/generate-z-infer.d.ts +0 -11
- package/dist/generator/zod/generator/generate-z-infer.js +0 -18
- package/dist/generator/zod/generator/generate-zod-code.js +0 -21
- package/dist/generator/zod/generator/generate-zod-schema.js +0 -17
- /package/dist/generator/mermaid-er/{type/index.d.ts → types.d.ts} +0 -0
- /package/dist/{common/type/index.d.ts → shared/types.d.ts} +0 -0
- /package/dist/{common/text → shared/utils}/capitalize.d.ts +0 -0
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
import { Node, Project } from 'ts-morph';
|
|
2
|
+
import { capitalize, containsSubstring, extractFieldComments, parseFieldComments, removeOptionalSuffix, splitByDot, splitByTo, splitByWhitespace, startsWith, trimString, } from '../../utils/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Generates relation definition based on function name and reference table.
|
|
5
|
+
*
|
|
6
|
+
* @param fnName - The relation function name ('many' or 'one')
|
|
7
|
+
* @param refTable - The referenced table name
|
|
8
|
+
* @param prefix - Schema prefix ('v' or 'z') for validation library
|
|
9
|
+
* @returns The generated relation definition string
|
|
10
|
+
*/
|
|
11
|
+
function generateRelationDefinition(fnName, refTable, prefix) {
|
|
12
|
+
const schema = `${capitalize(refTable)}Schema`;
|
|
13
|
+
return fnName === 'many' ? `${prefix}.array(${schema})` : fnName === 'one' ? schema : '';
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Processes arrow function body to find object literal expression.
|
|
17
|
+
*
|
|
18
|
+
* @param body - The arrow function body node
|
|
19
|
+
* @returns The found object literal expression, or null if not found
|
|
20
|
+
*/
|
|
21
|
+
function processArrowFunctionBody(body) {
|
|
22
|
+
if (Node.isObjectLiteralExpression(body))
|
|
23
|
+
return body;
|
|
24
|
+
if (Node.isParenthesizedExpression(body)) {
|
|
25
|
+
return findObjectLiteralExpression(body.getExpression());
|
|
26
|
+
}
|
|
27
|
+
if (Node.isBlock(body)) {
|
|
28
|
+
const ret = body.getStatements().find(Node.isReturnStatement);
|
|
29
|
+
if (ret && Node.isReturnStatement(ret)) {
|
|
30
|
+
const re = ret.getExpression();
|
|
31
|
+
return re && Node.isObjectLiteralExpression(re) ? re : null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Recursively extracts an `ObjectLiteralExpression` from a given AST node.
|
|
38
|
+
*
|
|
39
|
+
* @param expr - The root `Node` to search for object literals
|
|
40
|
+
* @returns The found `ObjectLiteralExpression`, or `null` if not found
|
|
41
|
+
*/
|
|
42
|
+
function findObjectLiteralExpression(expr) {
|
|
43
|
+
if (Node.isObjectLiteralExpression(expr))
|
|
44
|
+
return expr;
|
|
45
|
+
if (Node.isParenthesizedExpression(expr)) {
|
|
46
|
+
return findObjectLiteralExpression(expr.getExpression());
|
|
47
|
+
}
|
|
48
|
+
if (Node.isArrowFunction(expr)) {
|
|
49
|
+
return processArrowFunctionBody(expr.getBody());
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Finds an object literal expression in call expression arguments.
|
|
55
|
+
*
|
|
56
|
+
* @param call - The call expression to search for object literals in its arguments
|
|
57
|
+
* @param finder - Function to find object literal in a node
|
|
58
|
+
* @returns The found object literal, or `null` if not found in any argument
|
|
59
|
+
*/
|
|
60
|
+
function findObjectLiteralInArgs(call, finder) {
|
|
61
|
+
for (const arg of call.getArguments()) {
|
|
62
|
+
const obj = finder(arg);
|
|
63
|
+
if (obj)
|
|
64
|
+
return obj;
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Determines whether a given `CallExpression` is a relation-related function call.
|
|
70
|
+
*
|
|
71
|
+
* @param callExpr - The call expression node to check for relation functions
|
|
72
|
+
* @returns `true` if the function is a relation function; otherwise, `false`
|
|
73
|
+
*/
|
|
74
|
+
function isRelationFunctionCall(callExpr) {
|
|
75
|
+
const expression = callExpr.getExpression();
|
|
76
|
+
if (!Node.isIdentifier(expression))
|
|
77
|
+
return false;
|
|
78
|
+
const functionName = expression.getText();
|
|
79
|
+
return functionName === 'relations' || functionName.includes('relation');
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Creates a field extractor function using a custom parseFieldComments implementation.
|
|
83
|
+
*
|
|
84
|
+
* @param parseFieldComments - A function that parses comment lines into { definition, description, objectType }
|
|
85
|
+
* @returns A property node extractor function
|
|
86
|
+
*/
|
|
87
|
+
function createExtractFieldFromProperty(parseFieldComments) {
|
|
88
|
+
return (property, sourceText) => {
|
|
89
|
+
if (!Node.isPropertyAssignment(property))
|
|
90
|
+
return null;
|
|
91
|
+
const name = property.getName();
|
|
92
|
+
if (!name)
|
|
93
|
+
return null;
|
|
94
|
+
const commentLines = extractFieldComments(sourceText, property.getStart());
|
|
95
|
+
const { definition, description } = parseFieldComments(commentLines);
|
|
96
|
+
return { name, definition, description };
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Creates a relation field extractor function.
|
|
101
|
+
*
|
|
102
|
+
* @param parseFieldComments - Function to parse field comments
|
|
103
|
+
* @param prefix - Schema prefix ('v' or 'z') for validation library
|
|
104
|
+
* @returns Function that extracts relation fields from property
|
|
105
|
+
*/
|
|
106
|
+
function createExtractRelationFieldFromProperty(parseFieldComments, prefix) {
|
|
107
|
+
return (property, sourceText) => {
|
|
108
|
+
if (!Node.isPropertyAssignment(property))
|
|
109
|
+
return null;
|
|
110
|
+
const name = property.getName();
|
|
111
|
+
if (!name)
|
|
112
|
+
return null;
|
|
113
|
+
const init = property.getInitializer();
|
|
114
|
+
if (!Node.isCallExpression(init)) {
|
|
115
|
+
return { name, definition: '', description: undefined };
|
|
116
|
+
}
|
|
117
|
+
const expr = init.getExpression();
|
|
118
|
+
if (!Node.isIdentifier(expr)) {
|
|
119
|
+
return { name, definition: '', description: undefined };
|
|
120
|
+
}
|
|
121
|
+
const fnName = expr.getText();
|
|
122
|
+
const args = init.getArguments();
|
|
123
|
+
if (!(args.length && Node.isIdentifier(args[0]))) {
|
|
124
|
+
return { name, definition: '', description: undefined };
|
|
125
|
+
}
|
|
126
|
+
const refTable = args[0].getText();
|
|
127
|
+
const definition = generateRelationDefinition(fnName, refTable, prefix);
|
|
128
|
+
const { description } = parseFieldComments(extractFieldComments(sourceText, property.getStart()));
|
|
129
|
+
return { name, definition, description };
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Extracts fields from object literal properties using appropriate extractor.
|
|
134
|
+
*
|
|
135
|
+
* @param properties - Array of object literal properties
|
|
136
|
+
* @param isRelation - Whether this is a relation function call
|
|
137
|
+
* @param extractFieldFromProperty - Function to extract regular fields
|
|
138
|
+
* @param extractRelationFieldFromProperty - Function to extract relation fields
|
|
139
|
+
* @param sourceText - The source text for comment extraction
|
|
140
|
+
* @returns Array of extracted field results
|
|
141
|
+
*/
|
|
142
|
+
function extractFieldsFromProperties(properties, isRelation, extractFieldFromProperty, extractRelationFieldFromProperty, sourceText) {
|
|
143
|
+
return properties
|
|
144
|
+
.map((prop) => isRelation
|
|
145
|
+
? extractRelationFieldFromProperty(prop, sourceText)
|
|
146
|
+
: extractFieldFromProperty(prop, sourceText))
|
|
147
|
+
.filter((field) => field !== null);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Creates a field extractor for call expressions with customizable strategies.
|
|
151
|
+
*
|
|
152
|
+
* @param extractFieldFromProperty - Function to extract field from property
|
|
153
|
+
* @param extractRelationFieldFromProperty - Function to extract relation field from property
|
|
154
|
+
* @param findObjectLiteralExpression - Function to find object literal expression
|
|
155
|
+
* @param findObjectLiteralInArgs - Function to find object literal in call arguments
|
|
156
|
+
* @param isRelationFunctionCall - Function to check if call is relation function
|
|
157
|
+
* @returns Function that extracts fields from call expression
|
|
158
|
+
*/
|
|
159
|
+
function createExtractFieldsFromCallExpression(extractFieldFromProperty, extractRelationFieldFromProperty, findObjectLiteralExpression, findObjectLiteralInArgs, isRelationFunctionCall) {
|
|
160
|
+
return (callExpr, sourceText) => {
|
|
161
|
+
const objectLiteral = findObjectLiteralInArgs(callExpr, findObjectLiteralExpression);
|
|
162
|
+
if (!objectLiteral)
|
|
163
|
+
return [];
|
|
164
|
+
const isRelation = isRelationFunctionCall(callExpr);
|
|
165
|
+
const properties = objectLiteral.getProperties();
|
|
166
|
+
return extractFieldsFromProperties(properties, isRelation, extractFieldFromProperty, extractRelationFieldFromProperty, sourceText);
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Creates a schema extractor from customizable strategies.
|
|
171
|
+
*
|
|
172
|
+
* @param extractFieldsFromCall - Function to extract fields from a call expression
|
|
173
|
+
* @param extractFieldFromProperty - Function to extract a single field from an object literal property
|
|
174
|
+
* @param parseFieldComments - Function to parse field comments with object type support
|
|
175
|
+
* @param commentPrefix - The comment prefix to use for parsing
|
|
176
|
+
* @returns A function that extracts a schema from a variable declaration node
|
|
177
|
+
*/
|
|
178
|
+
function buildSchemaExtractor(extractFieldsFromCall, extractFieldFromProperty, parseFieldComments, commentPrefix) {
|
|
179
|
+
return (variableStatement, sourceText, originalSourceCode) => {
|
|
180
|
+
if (!Node.isVariableStatement(variableStatement))
|
|
181
|
+
return null;
|
|
182
|
+
const declarations = variableStatement.getDeclarations();
|
|
183
|
+
if (declarations.length === 0)
|
|
184
|
+
return null;
|
|
185
|
+
const declaration = declarations[0];
|
|
186
|
+
const name = declaration.getName();
|
|
187
|
+
if (!name)
|
|
188
|
+
return null;
|
|
189
|
+
// Extract object type from table-level comments
|
|
190
|
+
// Since ts-morph doesn't capture all comments properly, we'll parse the original source
|
|
191
|
+
const statementStart = variableStatement.getStart();
|
|
192
|
+
const originalSourceLines = originalSourceCode.split('\n'); // Use original source, not AST sourceText
|
|
193
|
+
const commentLines = [];
|
|
194
|
+
// Find the line number where this statement starts
|
|
195
|
+
let lineNumber = 0;
|
|
196
|
+
let charCount = 0;
|
|
197
|
+
for (let i = 0; i < originalSourceLines.length; i++) {
|
|
198
|
+
if (charCount >= statementStart) {
|
|
199
|
+
lineNumber = i;
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
charCount += originalSourceLines[i].length + 1; // +1 for newline
|
|
203
|
+
}
|
|
204
|
+
// Collect comments immediately before the statement
|
|
205
|
+
for (let i = lineNumber - 1; i >= 0; i--) {
|
|
206
|
+
const line = originalSourceLines[i];
|
|
207
|
+
const trimmedLine = trimString(line);
|
|
208
|
+
// Skip empty lines
|
|
209
|
+
if (trimmedLine === '')
|
|
210
|
+
continue;
|
|
211
|
+
// If it's a comment line, add it to our collection
|
|
212
|
+
if (startsWith(trimmedLine, '///')) {
|
|
213
|
+
commentLines.unshift(line);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
// If we hit a non-comment line, stop collecting
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
const { objectType } = parseFieldComments(commentLines, commentPrefix);
|
|
221
|
+
const initializer = declaration.getInitializer();
|
|
222
|
+
if (Node.isCallExpression(initializer)) {
|
|
223
|
+
if (isRelationFunctionCall(initializer))
|
|
224
|
+
return null;
|
|
225
|
+
const fields = extractFieldsFromCall(initializer, sourceText);
|
|
226
|
+
return { name, fields, objectType };
|
|
227
|
+
}
|
|
228
|
+
if (Node.isObjectLiteralExpression(initializer)) {
|
|
229
|
+
const fields = initializer
|
|
230
|
+
.getProperties()
|
|
231
|
+
.map((prop) => extractFieldFromProperty(prop, sourceText))
|
|
232
|
+
.filter((field) => field !== null);
|
|
233
|
+
return { name, fields, objectType };
|
|
234
|
+
}
|
|
235
|
+
return { name, fields: [], objectType };
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Extracts schemas from TypeScript source code using AST analysis.
|
|
240
|
+
*
|
|
241
|
+
* This function processes exported variable declarations to extract table schemas
|
|
242
|
+
* with their field definitions and comments. It supports both Zod and Valibot schema extraction.
|
|
243
|
+
*
|
|
244
|
+
* @param lines - Array of source code lines to process
|
|
245
|
+
* @param library - The validation library to extract schemas for ('zod' or 'valibot')
|
|
246
|
+
* @returns Array of extracted schemas with field definitions
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```typescript
|
|
250
|
+
* // For Zod schemas
|
|
251
|
+
* const zodSchemas = extractSchemas(sourceLines, 'zod')
|
|
252
|
+
*
|
|
253
|
+
* // For Valibot schemas
|
|
254
|
+
* const valibotSchemas = extractSchemas(sourceLines, 'valibot')
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
export function extractSchemas(lines, library) {
|
|
258
|
+
const sourceCode = lines.join('\n');
|
|
259
|
+
const project = new Project({
|
|
260
|
+
useInMemoryFileSystem: true,
|
|
261
|
+
compilerOptions: {
|
|
262
|
+
allowJs: true,
|
|
263
|
+
skipLibCheck: true,
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
const sourceFile = project.createSourceFile('temp.ts', sourceCode);
|
|
267
|
+
const sourceText = sourceFile.getFullText();
|
|
268
|
+
const commentPrefix = library === 'zod' ? '@z.' : '@v.';
|
|
269
|
+
const schemaPrefix = library === 'zod' ? 'z' : 'v';
|
|
270
|
+
const extractField = createExtractFieldFromProperty((lines) => parseFieldComments(lines, commentPrefix));
|
|
271
|
+
const extractRelationField = createExtractRelationFieldFromProperty((lines) => parseFieldComments(lines, commentPrefix), schemaPrefix);
|
|
272
|
+
const extractFieldsFromCall = createExtractFieldsFromCallExpression(extractField, extractRelationField, findObjectLiteralExpression, findObjectLiteralInArgs, isRelationFunctionCall);
|
|
273
|
+
const extractSchema = buildSchemaExtractor(extractFieldsFromCall, extractField, parseFieldComments, commentPrefix);
|
|
274
|
+
return sourceFile
|
|
275
|
+
.getVariableStatements()
|
|
276
|
+
.filter((stmt) => stmt.hasExportKeyword())
|
|
277
|
+
.map((stmt) => extractSchema(stmt, sourceText, sourceCode))
|
|
278
|
+
.filter((schema) => schema !== null);
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Extracts Zod schemas from TypeScript source code using AST analysis.
|
|
282
|
+
*
|
|
283
|
+
* This function processes exported variable declarations to extract table schemas
|
|
284
|
+
* with their field definitions and comments. It automatically handles Zod schema extraction.
|
|
285
|
+
*
|
|
286
|
+
* @param lines - Array of source code lines to process
|
|
287
|
+
* @returns Array of extracted schemas with field definitions
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```typescript
|
|
291
|
+
* const schemas = extractZodSchemas(sourceLines)
|
|
292
|
+
* // Returns: [{ name: 'user', fields: [{ name: 'id', definition: 'z.uuid()', description: 'Primary key' }] }]
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
export function extractZodSchemas(lines) {
|
|
296
|
+
return extractSchemas(lines, 'zod');
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Extracts Valibot schemas from TypeScript source code using AST analysis.
|
|
300
|
+
*
|
|
301
|
+
* This function processes exported variable declarations to extract table schemas
|
|
302
|
+
* with their field definitions and comments. It automatically handles Valibot schema extraction.
|
|
303
|
+
*
|
|
304
|
+
* @param lines - Array of source code lines to process
|
|
305
|
+
* @returns Array of extracted schemas with field definitions
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```typescript
|
|
309
|
+
* const schemas = extractValibotSchemas(sourceLines)
|
|
310
|
+
* // Returns: [{ name: 'user', fields: [{ name: 'id', definition: 'v.pipe(v.string(), v.uuid())', description: 'Primary key' }] }]
|
|
311
|
+
* ```
|
|
312
|
+
*/
|
|
313
|
+
export function extractValibotSchemas(lines) {
|
|
314
|
+
return extractSchemas(lines, 'valibot');
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Extracts relation schemas from `relations(...)` declarations using AST analysis.
|
|
318
|
+
*
|
|
319
|
+
* This returns entries like `userRelations` and `postRelations` with fields
|
|
320
|
+
* resolved to either `z.array(OtherSchema)` / `v.array(OtherSchema)` or direct
|
|
321
|
+
* `OtherSchema` based on `many`/`one`.
|
|
322
|
+
*
|
|
323
|
+
* Note: Base table schemas are not included here; use `extractSchemas` for those.
|
|
324
|
+
*/
|
|
325
|
+
export function extractRelationSchemas(lines, library) {
|
|
326
|
+
const sourceCode = lines.join('\n');
|
|
327
|
+
const project = new Project({
|
|
328
|
+
useInMemoryFileSystem: true,
|
|
329
|
+
compilerOptions: { allowJs: true, skipLibCheck: true },
|
|
330
|
+
});
|
|
331
|
+
const sourceFile = project.createSourceFile('temp.ts', sourceCode);
|
|
332
|
+
const sourceText = sourceFile.getFullText();
|
|
333
|
+
const commentPrefix = library === 'zod' ? '@z.' : '@v.';
|
|
334
|
+
const schemaPrefix = library === 'zod' ? 'z' : 'v';
|
|
335
|
+
// First, extract base schemas to get their objectType
|
|
336
|
+
const baseSchemas = extractSchemas(lines, library);
|
|
337
|
+
const baseSchemaMap = new Map(baseSchemas.map((schema) => [schema.name, schema.objectType]));
|
|
338
|
+
const extractField = createExtractFieldFromProperty((lines) => parseFieldComments(lines, commentPrefix));
|
|
339
|
+
const extractRelationField = createExtractRelationFieldFromProperty((lines) => parseFieldComments(lines, commentPrefix), schemaPrefix);
|
|
340
|
+
const extractFieldsFromCall = createExtractFieldsFromCallExpression(extractField, extractRelationField, findObjectLiteralExpression, findObjectLiteralInArgs, isRelationFunctionCall);
|
|
341
|
+
function extract(declaration) {
|
|
342
|
+
if (!Node.isVariableDeclaration(declaration))
|
|
343
|
+
return null;
|
|
344
|
+
const name = declaration.getName();
|
|
345
|
+
if (!name)
|
|
346
|
+
return null;
|
|
347
|
+
const initializer = declaration.getInitializer();
|
|
348
|
+
if (!Node.isCallExpression(initializer))
|
|
349
|
+
return null;
|
|
350
|
+
if (!isRelationFunctionCall(initializer))
|
|
351
|
+
return null;
|
|
352
|
+
const relArgs = initializer.getArguments();
|
|
353
|
+
const baseIdentifier = relArgs.length && Node.isIdentifier(relArgs[0]) ? relArgs[0] : undefined;
|
|
354
|
+
if (!baseIdentifier)
|
|
355
|
+
return null;
|
|
356
|
+
const baseName = baseIdentifier.getText();
|
|
357
|
+
const fields = extractFieldsFromCall(initializer, sourceText);
|
|
358
|
+
// Inherit objectType from the base schema
|
|
359
|
+
const objectType = baseSchemaMap.get(baseName);
|
|
360
|
+
return { name, baseName, fields, objectType };
|
|
361
|
+
}
|
|
362
|
+
return sourceFile
|
|
363
|
+
.getVariableStatements()
|
|
364
|
+
.filter((stmt) => stmt.hasExportKeyword())
|
|
365
|
+
.flatMap((stmt) => stmt.getDeclarations())
|
|
366
|
+
.map((decl) => extract(decl))
|
|
367
|
+
.filter((schema) => schema !== null);
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Extracts relations from the given code.
|
|
371
|
+
*
|
|
372
|
+
* @param code - The code to extract relations from.
|
|
373
|
+
* @returns The extracted relations.
|
|
374
|
+
*/
|
|
375
|
+
export function extractRelations(code) {
|
|
376
|
+
const relations = [];
|
|
377
|
+
for (const line of code) {
|
|
378
|
+
const relation = parseRelationLine(line);
|
|
379
|
+
if (relation) {
|
|
380
|
+
relations.push(relation);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return relations;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Parse relation line and extract components.
|
|
387
|
+
*
|
|
388
|
+
* @param line - The line to parse.
|
|
389
|
+
* @returns Parsed relation or null if not a relation line.
|
|
390
|
+
*/
|
|
391
|
+
export function parseRelationLine(line) {
|
|
392
|
+
const trimmedLine = trimString(line);
|
|
393
|
+
const cleanLine = startsWith(trimmedLine, '///') ? trimmedLine.substring(3) : trimmedLine;
|
|
394
|
+
const finalLine = trimString(cleanLine);
|
|
395
|
+
if (!startsWith(finalLine, '@relation'))
|
|
396
|
+
return null;
|
|
397
|
+
const parts = splitByWhitespace(finalLine);
|
|
398
|
+
if (parts.length < 4)
|
|
399
|
+
return null;
|
|
400
|
+
const fromParts = splitByDot(parts[1]);
|
|
401
|
+
const toParts = splitByDot(parts[2]);
|
|
402
|
+
if (fromParts.length !== 2 || toParts.length !== 2)
|
|
403
|
+
return null;
|
|
404
|
+
return {
|
|
405
|
+
fromModel: fromParts[0],
|
|
406
|
+
fromField: fromParts[1],
|
|
407
|
+
toModel: toParts[0],
|
|
408
|
+
toField: toParts[1],
|
|
409
|
+
type: parts[3],
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Build a relation line from a string.
|
|
414
|
+
*
|
|
415
|
+
* @param input - The input string.
|
|
416
|
+
* @returns The built relation line.
|
|
417
|
+
*/
|
|
418
|
+
export function buildRelationLine(input) {
|
|
419
|
+
const toSymbol = (r) => r === 'zero-one'
|
|
420
|
+
? '|o'
|
|
421
|
+
: r === 'one'
|
|
422
|
+
? '||'
|
|
423
|
+
: r === 'zero-many'
|
|
424
|
+
? '}o'
|
|
425
|
+
: r === 'many'
|
|
426
|
+
? '}|'
|
|
427
|
+
: (() => {
|
|
428
|
+
throw new Error(`Invalid relationship: ${r}`);
|
|
429
|
+
})();
|
|
430
|
+
const isRelationship = (r) => ['zero-one', 'one', 'zero-many', 'many'].includes(r);
|
|
431
|
+
const parts = splitByTo(input);
|
|
432
|
+
if (!parts)
|
|
433
|
+
throw new Error(`Invalid input format: ${input}`);
|
|
434
|
+
const [fromRaw, toRawWithOptional] = parts;
|
|
435
|
+
const [toRaw, isOptional] = containsSubstring(toRawWithOptional, '-optional')
|
|
436
|
+
? [removeOptionalSuffix(toRawWithOptional), true]
|
|
437
|
+
: [toRawWithOptional, false];
|
|
438
|
+
if (!(isRelationship(fromRaw) && isRelationship(toRaw))) {
|
|
439
|
+
throw new Error(`Invalid relationship string: ${input}`);
|
|
440
|
+
}
|
|
441
|
+
const fromSymbol = toSymbol(fromRaw);
|
|
442
|
+
const toSymbolStr = toSymbol(toRaw);
|
|
443
|
+
const connector = isOptional ? '..' : '--';
|
|
444
|
+
return `${fromSymbol}${connector}${toSymbolStr}`;
|
|
445
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { writeFile, mkdir } from 'fs/promises';
|
|
2
|
+
import { dirname } from 'path';
|
|
3
|
+
import { Result, err, ok } from 'neverthrow';
|
|
4
|
+
export const writeFileSafely = async (filePath, content) => {
|
|
5
|
+
try {
|
|
6
|
+
// ディレクトリが存在しない場合は作成
|
|
7
|
+
const directory = dirname(filePath);
|
|
8
|
+
await mkdir(directory, { recursive: true });
|
|
9
|
+
// ファイルを書き込み
|
|
10
|
+
await writeFile(filePath, content, 'utf-8');
|
|
11
|
+
return ok(undefined);
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
return err(new Error(`Failed to write file ${filePath}: ${error instanceof Error ? error.message : String(error)}`));
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export const ensureDirectoryExists = async (directory) => {
|
|
18
|
+
try {
|
|
19
|
+
await mkdir(directory, { recursive: true });
|
|
20
|
+
return ok(undefined);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
return err(new Error(`Failed to create directory ${directory}: ${error instanceof Error ? error.message : String(error)}`));
|
|
24
|
+
}
|
|
25
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ObjectLiteralExpression } from 'ts-morph';
|
|
2
|
+
import { Node } from 'ts-morph';
|
|
3
|
+
/**
|
|
4
|
+
* Recursively extracts an `ObjectLiteralExpression` from a given AST node.
|
|
5
|
+
*
|
|
6
|
+
* Supports direct object literals, parenthesized expressions,
|
|
7
|
+
* arrow functions returning object literals (including wrapped and block bodies).
|
|
8
|
+
*
|
|
9
|
+
* @param expr - The root `Node` to search.
|
|
10
|
+
* @returns The found `ObjectLiteralExpression`, or `null` if not found.
|
|
11
|
+
*/
|
|
12
|
+
export declare function findObjectLiteralExpression(expr: Node): ObjectLiteralExpression | null;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Node } from 'ts-morph';
|
|
2
|
+
/**
|
|
3
|
+
* Recursively extracts an `ObjectLiteralExpression` from a given AST node.
|
|
4
|
+
*
|
|
5
|
+
* Supports direct object literals, parenthesized expressions,
|
|
6
|
+
* arrow functions returning object literals (including wrapped and block bodies).
|
|
7
|
+
*
|
|
8
|
+
* @param expr - The root `Node` to search.
|
|
9
|
+
* @returns The found `ObjectLiteralExpression`, or `null` if not found.
|
|
10
|
+
*/
|
|
11
|
+
export function findObjectLiteralExpression(expr) {
|
|
12
|
+
if (Node.isObjectLiteralExpression(expr))
|
|
13
|
+
return expr;
|
|
14
|
+
if (Node.isParenthesizedExpression(expr))
|
|
15
|
+
return findObjectLiteralExpression(expr.getExpression());
|
|
16
|
+
if (Node.isArrowFunction(expr)) {
|
|
17
|
+
const body = expr.getBody();
|
|
18
|
+
if (Node.isObjectLiteralExpression(body))
|
|
19
|
+
return body;
|
|
20
|
+
if (Node.isParenthesizedExpression(body))
|
|
21
|
+
return findObjectLiteralExpression(body.getExpression());
|
|
22
|
+
if (Node.isBlock(body)) {
|
|
23
|
+
const ret = body.getStatements().find(Node.isReturnStatement);
|
|
24
|
+
if (ret && Node.isReturnStatement(ret)) {
|
|
25
|
+
const re = ret.getExpression();
|
|
26
|
+
return re && Node.isObjectLiteralExpression(re) ? re : null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CallExpression } from 'ts-morph';
|
|
2
|
+
/**
|
|
3
|
+
* Determines whether a given `CallExpression` is a relation-related function call.
|
|
4
|
+
*
|
|
5
|
+
* This checks if the function name is either `"relations"` or contains the substring `"relation"`.
|
|
6
|
+
*
|
|
7
|
+
* @param callExpr - The call expression node to check.
|
|
8
|
+
* @returns `true` if the function is a relation function; otherwise, `false`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isRelationFunctionCall(callExpr: CallExpression): boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Node } from 'ts-morph';
|
|
2
|
+
/**
|
|
3
|
+
* Determines whether a given `CallExpression` is a relation-related function call.
|
|
4
|
+
*
|
|
5
|
+
* This checks if the function name is either `"relations"` or contains the substring `"relation"`.
|
|
6
|
+
*
|
|
7
|
+
* @param callExpr - The call expression node to check.
|
|
8
|
+
* @returns `true` if the function is a relation function; otherwise, `false`.
|
|
9
|
+
*/
|
|
10
|
+
export function isRelationFunctionCall(callExpr) {
|
|
11
|
+
const expression = callExpr.getExpression();
|
|
12
|
+
if (!Node.isIdentifier(expression))
|
|
13
|
+
return false;
|
|
14
|
+
const functionName = expression.getText();
|
|
15
|
+
return functionName === 'relations' || functionName.includes('relation');
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.capitalize = capitalize;
|
|
4
1
|
/**
|
|
5
2
|
* Capitalizes the first letter of a string
|
|
6
3
|
*
|
|
@@ -18,6 +15,6 @@ exports.capitalize = capitalize;
|
|
|
18
15
|
* - Returns empty string if input is empty
|
|
19
16
|
* - Commonly used for generating type names and class names
|
|
20
17
|
*/
|
|
21
|
-
function capitalize(str) {
|
|
18
|
+
export function capitalize(str) {
|
|
22
19
|
return `${str.charAt(0).toUpperCase()}${str.slice(1)}`;
|
|
23
20
|
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Functional composition utilities for cleaner code
|
|
3
|
+
*
|
|
4
|
+
* @module compose
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Pipes a value through a series of functions from left to right
|
|
8
|
+
*
|
|
9
|
+
* @template T - Initial value type
|
|
10
|
+
* @param value - The initial value
|
|
11
|
+
* @param fns - Functions to apply in sequence
|
|
12
|
+
* @returns The final transformed value
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* const result = pipe(
|
|
16
|
+
* "hello",
|
|
17
|
+
* str => str.toUpperCase(),
|
|
18
|
+
* str => str + "!",
|
|
19
|
+
* str => str.repeat(2)
|
|
20
|
+
* ) // "HELLO!HELLO!"
|
|
21
|
+
*/
|
|
22
|
+
export declare function pipe<T>(value: T, ...fns: Array<(arg: any) => any>): any
|
|
23
|
+
/**
|
|
24
|
+
* Composes functions from right to left
|
|
25
|
+
*
|
|
26
|
+
* @param fns - Functions to compose
|
|
27
|
+
* @returns A new function that applies all functions in sequence
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* const transform = compose(
|
|
31
|
+
* str => str.repeat(2),
|
|
32
|
+
* str => str + "!",
|
|
33
|
+
* str => str.toUpperCase()
|
|
34
|
+
* )
|
|
35
|
+
* transform("hello") // "HELLO!HELLO!"
|
|
36
|
+
*/
|
|
37
|
+
export declare function compose<T>(...fns: Array<(arg: any) => any>): (arg: T) => any
|
|
38
|
+
/**
|
|
39
|
+
* Maybe monad for handling nullable values
|
|
40
|
+
*
|
|
41
|
+
* @template T - The wrapped value type
|
|
42
|
+
*/
|
|
43
|
+
export declare class Maybe<T> {
|
|
44
|
+
private value
|
|
45
|
+
private constructor()
|
|
46
|
+
/**
|
|
47
|
+
* Creates a Maybe from a value
|
|
48
|
+
*/
|
|
49
|
+
static of<T>(value: T | null | undefined): Maybe<T>
|
|
50
|
+
/**
|
|
51
|
+
* Creates a Maybe with no value
|
|
52
|
+
*/
|
|
53
|
+
static none<T>(): Maybe<T>
|
|
54
|
+
/**
|
|
55
|
+
* Maps a function over the Maybe value
|
|
56
|
+
*/
|
|
57
|
+
map<U>(fn: (value: T) => U): Maybe<U>
|
|
58
|
+
/**
|
|
59
|
+
* Flat maps a function that returns a Maybe
|
|
60
|
+
*/
|
|
61
|
+
flatMap<U>(fn: (value: T) => Maybe<U>): Maybe<U>
|
|
62
|
+
/**
|
|
63
|
+
* Returns the value or a default
|
|
64
|
+
*/
|
|
65
|
+
getOrElse(defaultValue: T): T
|
|
66
|
+
/**
|
|
67
|
+
* Returns the value or null
|
|
68
|
+
*/
|
|
69
|
+
getOrNull(): T | null
|
|
70
|
+
/**
|
|
71
|
+
* Checks if the Maybe has a value
|
|
72
|
+
*/
|
|
73
|
+
isSome(): boolean
|
|
74
|
+
/**
|
|
75
|
+
* Checks if the Maybe has no value
|
|
76
|
+
*/
|
|
77
|
+
isNone(): boolean
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Helper function to create a Maybe
|
|
81
|
+
*/
|
|
82
|
+
export declare const maybe: <T>(value: T | null | undefined) => Maybe<T>
|
|
83
|
+
/**
|
|
84
|
+
* Applies a function only if the condition is true
|
|
85
|
+
*
|
|
86
|
+
* @param condition - The condition to check
|
|
87
|
+
* @param fn - The function to apply
|
|
88
|
+
* @returns A function that conditionally applies the transformation
|
|
89
|
+
*/
|
|
90
|
+
export declare function when<T>(condition: boolean, fn: (value: T) => T): (value: T) => T
|
|
91
|
+
/**
|
|
92
|
+
* Applies a function only if the predicate returns true
|
|
93
|
+
*
|
|
94
|
+
* @param predicate - The predicate function
|
|
95
|
+
* @param fn - The function to apply
|
|
96
|
+
* @returns A function that conditionally applies the transformation
|
|
97
|
+
*/
|
|
98
|
+
export declare function whenPredicate<T>(
|
|
99
|
+
predicate: (value: T) => boolean,
|
|
100
|
+
fn: (value: T) => T,
|
|
101
|
+
): (value: T) => T
|