@flink-app/flink 0.13.3 → 0.13.5
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/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/CHANGELOG.md +18 -0
- package/dist/src/FlinkApp.js +5 -6
- package/dist/src/FlinkHttpHandler.d.ts +2 -1
- package/dist/src/FlinkHttpHandler.js +1 -0
- package/dist/src/TypeScriptCompiler.d.ts +4 -0
- package/dist/src/TypeScriptCompiler.js +123 -11
- package/dist/src/utils.d.ts +12 -0
- package/dist/src/utils.js +73 -0
- package/package.json +1 -1
- package/spec/mock-project/dist/src/handlers/PatchCar.js +58 -0
- package/spec/mock-project/dist/src/handlers/PatchOnboardingSession.js +76 -0
- package/spec/mock-project/dist/src/handlers/PatchOrderWithComplexTypes.js +58 -0
- package/spec/mock-project/dist/src/handlers/PatchProductWithIntersection.js +59 -0
- package/spec/mock-project/dist/src/handlers/PatchUserWithUnion.js +59 -0
- package/spec/mock-project/src/handlers/PatchCar.ts +25 -0
- package/spec/mock-project/src/handlers/PatchOnboardingSession.ts +66 -0
- package/spec/mock-project/src/handlers/PatchOrderWithComplexTypes.ts +79 -0
- package/spec/mock-project/src/handlers/PatchProductWithIntersection.ts +49 -0
- package/spec/mock-project/src/handlers/PatchUserWithUnion.ts +46 -0
- package/spec/utils.spec.ts +135 -1
- package/src/FlinkApp.ts +5 -7
- package/src/FlinkHttpHandler.ts +1 -0
- package/src/TypeScriptCompiler.ts +128 -5
- package/src/utils.ts +75 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Changesets
|
|
2
|
+
|
|
3
|
+
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
|
4
|
+
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
|
5
|
+
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
|
6
|
+
|
|
7
|
+
We have a quick list of common questions to get you started engaging with this project in
|
|
8
|
+
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json",
|
|
3
|
+
"changelog": "@changesets/cli/changelog",
|
|
4
|
+
"commit": false,
|
|
5
|
+
"fixed": [],
|
|
6
|
+
"linked": [],
|
|
7
|
+
"access": "restricted",
|
|
8
|
+
"baseBranch": "main",
|
|
9
|
+
"updateInternalDependencies": "patch",
|
|
10
|
+
"ignore": []
|
|
11
|
+
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @flink-app/flink
|
|
2
2
|
|
|
3
|
+
## 0.13.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Schema error DX improvement - i.e. better logs
|
|
8
|
+
|
|
9
|
+
## 0.13.4
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Add PATCH HTTP method support and fix schema generation for utility types
|
|
14
|
+
|
|
15
|
+
- Add PATCH HTTP method to HttpMethod enum and auto-detection from handler filenames
|
|
16
|
+
- Fix schema generation to support nested Partial types with indexed access (e.g., `Partial<Interface["property"]>`)
|
|
17
|
+
- Add recursive dependency resolution for interface copying in TypeScript compiler
|
|
18
|
+
- Add support for union and intersection types with utility type patterns
|
|
19
|
+
- Add test coverage for complex type scenarios (union, intersection, nested utility types)
|
|
20
|
+
|
|
3
21
|
## 0.13.3
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/dist/src/FlinkApp.js
CHANGED
|
@@ -341,7 +341,7 @@ var FlinkApp = /** @class */ (function () {
|
|
|
341
341
|
validateRes_1 = ajv.compile(schema.resSchema);
|
|
342
342
|
}
|
|
343
343
|
this.expressApp[method](routeProps.path, function (req, res) { return __awaiter(_this, void 0, void 0, function () {
|
|
344
|
-
var valid, data, handlerRes, err_1, valid;
|
|
344
|
+
var valid, formattedErrors, data, handlerRes, err_1, valid, formattedErrors;
|
|
345
345
|
return __generator(this, function (_a) {
|
|
346
346
|
switch (_a.label) {
|
|
347
347
|
case 0:
|
|
@@ -356,8 +356,8 @@ var FlinkApp = /** @class */ (function () {
|
|
|
356
356
|
if (validateReq_1) {
|
|
357
357
|
valid = validateReq_1(req.body);
|
|
358
358
|
if (!valid) {
|
|
359
|
-
|
|
360
|
-
FlinkLog_1.log.
|
|
359
|
+
formattedErrors = (0, utils_1.formatValidationErrors)(validateReq_1.errors, req.body);
|
|
360
|
+
FlinkLog_1.log.warn("[".concat(req.reqId, "] ").concat(methodAndRoute_1, ": Bad request\n").concat(formattedErrors));
|
|
361
361
|
return [2 /*return*/, res.status(400).json({
|
|
362
362
|
status: 400,
|
|
363
363
|
error: {
|
|
@@ -410,9 +410,8 @@ var FlinkApp = /** @class */ (function () {
|
|
|
410
410
|
if (validateRes_1 && !(0, utils_1.isError)(handlerRes)) {
|
|
411
411
|
valid = validateRes_1(JSON.parse(JSON.stringify(handlerRes.data)));
|
|
412
412
|
if (!valid) {
|
|
413
|
-
|
|
414
|
-
FlinkLog_1.log.
|
|
415
|
-
// log.debug(JSON.stringify(schema, null, 2));
|
|
413
|
+
formattedErrors = (0, utils_1.formatValidationErrors)(validateRes_1.errors, handlerRes.data);
|
|
414
|
+
FlinkLog_1.log.warn("[".concat(req.reqId, "] ").concat(methodAndRoute_1, ": Bad response\n").concat(formattedErrors));
|
|
416
415
|
return [2 /*return*/, res.status(500).json({
|
|
417
416
|
status: 500,
|
|
418
417
|
error: {
|
|
@@ -89,6 +89,10 @@ declare class TypeScriptCompiler {
|
|
|
89
89
|
* Return names of req and/or res schema types.
|
|
90
90
|
*/
|
|
91
91
|
private extractSchemasFromHandlerSourceFile;
|
|
92
|
+
/**
|
|
93
|
+
* Recursively copies an interface and all its dependencies from the same file
|
|
94
|
+
*/
|
|
95
|
+
private copyInterfaceWithDependencies;
|
|
92
96
|
private saveIntermediateTsSchema;
|
|
93
97
|
private initJsonSchemaGenerator;
|
|
94
98
|
private generateAndSaveJsonSchemas;
|
|
@@ -480,10 +480,50 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
480
480
|
});
|
|
481
481
|
});
|
|
482
482
|
};
|
|
483
|
+
/**
|
|
484
|
+
* Recursively copies an interface and all its dependencies from the same file
|
|
485
|
+
*/
|
|
486
|
+
TypeScriptCompiler.prototype.copyInterfaceWithDependencies = function (interfaceDecl, handlerFile) {
|
|
487
|
+
var _a, _b, _c;
|
|
488
|
+
var interfaceName = ((_a = interfaceDecl.getName) === null || _a === void 0 ? void 0 : _a.call(interfaceDecl)) || ((_b = interfaceDecl.getFirstChildByKind(ts_morph_1.SyntaxKind.Identifier)) === null || _b === void 0 ? void 0 : _b.getText());
|
|
489
|
+
if (!interfaceName)
|
|
490
|
+
return;
|
|
491
|
+
// Check if already copied
|
|
492
|
+
var existingInterface = this.parsedTsSchemas.find(function (s) { return s.includes("interface ".concat(interfaceName, " ")) || s.includes("type ".concat(interfaceName, " =")); });
|
|
493
|
+
if (existingInterface)
|
|
494
|
+
return;
|
|
495
|
+
// Copy the interface
|
|
496
|
+
this.parsedTsSchemas.push(interfaceDecl.getText());
|
|
497
|
+
// Find and recursively copy dependencies from the same file
|
|
498
|
+
// First, find direct type references in this interface
|
|
499
|
+
var typeRefIdentifiers = interfaceDecl
|
|
500
|
+
.getDescendantsOfKind(ts_morph_1.SyntaxKind.TypeReference)
|
|
501
|
+
.filter(function (typeRefNode) { return !!typeRefNode.getFirstChildIfKind(ts_morph_1.SyntaxKind.Identifier); })
|
|
502
|
+
.map(function (typeRefNode) { return typeRefNode.getFirstChildIfKindOrThrow(ts_morph_1.SyntaxKind.Identifier); });
|
|
503
|
+
for (var _i = 0, typeRefIdentifiers_1 = typeRefIdentifiers; _i < typeRefIdentifiers_1.length; _i++) {
|
|
504
|
+
var typeRefIdentifier = typeRefIdentifiers_1[_i];
|
|
505
|
+
var typeSymbol = typeRefIdentifier.getSymbol();
|
|
506
|
+
if (typeSymbol) {
|
|
507
|
+
var declaredType = typeSymbol.getDeclaredType();
|
|
508
|
+
var declaration = (_c = declaredType.getSymbol()) === null || _c === void 0 ? void 0 : _c.getDeclarations()[0];
|
|
509
|
+
if (declaration && declaration.getSourceFile() === handlerFile) {
|
|
510
|
+
// Same file - recursively copy this dependency
|
|
511
|
+
this.copyInterfaceWithDependencies(declaration, handlerFile);
|
|
512
|
+
}
|
|
513
|
+
else if (declaration && declaration.getSourceFile() !== handlerFile) {
|
|
514
|
+
// Different file - add to imports
|
|
515
|
+
var declaredTypeSymbol = declaredType.getSymbol();
|
|
516
|
+
if (declaredTypeSymbol) {
|
|
517
|
+
this.tsSchemasSymbolsToImports.push(declaredTypeSymbol);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
};
|
|
483
523
|
TypeScriptCompiler.prototype.saveIntermediateTsSchema = function (schema, handlerFile, suffix) {
|
|
484
524
|
return __awaiter(this, void 0, void 0, function () {
|
|
485
|
-
var handlerFileName, generatedSchemaInterfaceStr, schemaInterfaceName, schemaSymbol, interfaceName, declaration, _i, _a, typeToImport, arrayTypeArg, schemaSymbol, interfaceName, declaration, props,
|
|
486
|
-
return __generator(this, function (
|
|
525
|
+
var handlerFileName, generatedSchemaInterfaceStr, schemaInterfaceName, schemaSymbol, interfaceName, declaration, _i, _a, typeToImport, typeSymbol, declaredTypeSymbol, _b, _c, prop, propDecl, propText, interfaceNameMatches, _d, interfaceNameMatches_1, match, referencedInterfaceName, referencedInterfaceDecl, arrayTypeArg, schemaSymbol, interfaceName, declaration, props, _e, _f, typeToImport, typeSymbol, declaredTypeSymbol, schemaSymbol, declarations, declaration, propertySignatures, _g, _h, prop, propType, typeSymbol, typeDeclaration, elementType, elementSymbol, elementDeclaration, currentPropTypeText, interfaceNameMatches, _j, interfaceNameMatches_2, match, interfaceName, interfaceDecl, typeArgs, _k, typeArgs_1, typeArg, argSymbol, argDeclaration, _l, _m, typeToImport, typeSymbol, declaredTypeSymbol;
|
|
526
|
+
return __generator(this, function (_o) {
|
|
487
527
|
if (schema.isAny()) {
|
|
488
528
|
return [2 /*return*/]; // 'any' indicates that no schema is used
|
|
489
529
|
}
|
|
@@ -496,13 +536,39 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
496
536
|
declaration = schemaSymbol.getDeclarations()[0];
|
|
497
537
|
if (declaration.getSourceFile() === handlerFile) {
|
|
498
538
|
// Interface is declared within handler file
|
|
499
|
-
generatedSchemaInterfaceStr = "export interface ".concat(schemaInterfaceName, " {
|
|
539
|
+
generatedSchemaInterfaceStr = "export interface ".concat(schemaInterfaceName, " {\n ").concat(schema
|
|
500
540
|
.getProperties()
|
|
501
541
|
.map(function (p) { return p.getValueDeclarationOrThrow().getText(); })
|
|
502
542
|
.join("\n"), "\n }");
|
|
503
543
|
for (_i = 0, _a = (0, TypeScriptUtils_1.getTypesToImport)(declaration); _i < _a.length; _i++) {
|
|
504
544
|
typeToImport = _a[_i];
|
|
505
|
-
|
|
545
|
+
typeSymbol = typeToImport.getSymbol();
|
|
546
|
+
if (typeSymbol) {
|
|
547
|
+
declaredTypeSymbol = typeSymbol.getDeclaredType().getSymbol();
|
|
548
|
+
if (declaredTypeSymbol) {
|
|
549
|
+
this.tsSchemasSymbolsToImports.push(declaredTypeSymbol);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
// Also check for utility types with indexed access patterns like Partial<Foo["bar"]>
|
|
554
|
+
for (_b = 0, _c = schema.getProperties(); _b < _c.length; _b++) {
|
|
555
|
+
prop = _c[_b];
|
|
556
|
+
propDecl = prop.getValueDeclaration();
|
|
557
|
+
if (propDecl) {
|
|
558
|
+
propText = propDecl.getText();
|
|
559
|
+
interfaceNameMatches = propText.match(/\b([A-Z][a-zA-Z0-9]*)\s*\[/g);
|
|
560
|
+
if (interfaceNameMatches) {
|
|
561
|
+
for (_d = 0, interfaceNameMatches_1 = interfaceNameMatches; _d < interfaceNameMatches_1.length; _d++) {
|
|
562
|
+
match = interfaceNameMatches_1[_d];
|
|
563
|
+
referencedInterfaceName = match.replace(/\s*\[$/, '').trim();
|
|
564
|
+
referencedInterfaceDecl = handlerFile.getInterface(referencedInterfaceName) || handlerFile.getTypeAlias(referencedInterfaceName);
|
|
565
|
+
if (referencedInterfaceDecl) {
|
|
566
|
+
// Interface is in same file - copy it and all its dependencies recursively
|
|
567
|
+
this.copyInterfaceWithDependencies(referencedInterfaceDecl, handlerFile);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
506
572
|
}
|
|
507
573
|
}
|
|
508
574
|
else {
|
|
@@ -531,15 +597,22 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
531
597
|
else {
|
|
532
598
|
generatedSchemaInterfaceStr = "export interface ".concat(schemaInterfaceName, " extends Array<").concat(declaration.getText(), "> {}");
|
|
533
599
|
}
|
|
534
|
-
for (
|
|
535
|
-
typeToImport =
|
|
536
|
-
|
|
600
|
+
for (_e = 0, _f = (0, TypeScriptUtils_1.getTypesToImport)(declaration); _e < _f.length; _e++) {
|
|
601
|
+
typeToImport = _f[_e];
|
|
602
|
+
typeSymbol = typeToImport.getSymbol();
|
|
603
|
+
if (typeSymbol) {
|
|
604
|
+
declaredTypeSymbol = typeSymbol.getDeclaredType().getSymbol();
|
|
605
|
+
if (declaredTypeSymbol) {
|
|
606
|
+
this.tsSchemasSymbolsToImports.push(declaredTypeSymbol);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
537
609
|
}
|
|
538
610
|
}
|
|
539
611
|
}
|
|
540
612
|
else if (schema.isObject()) {
|
|
541
|
-
|
|
542
|
-
|
|
613
|
+
schemaSymbol = schema.getSymbol();
|
|
614
|
+
declarations = schemaSymbol === null || schemaSymbol === void 0 ? void 0 : schemaSymbol.getDeclarations();
|
|
615
|
+
declaration = declarations === null || declarations === void 0 ? void 0 : declarations[0];
|
|
543
616
|
propertySignatures = schema.getProperties().map(function (prop) {
|
|
544
617
|
var propName = prop.getName();
|
|
545
618
|
var propType = prop.getTypeAtLocation(handlerFile);
|
|
@@ -560,8 +633,8 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
560
633
|
return "".concat(propName).concat(isOptional ? "?" : "", ": ").concat(propTypeText);
|
|
561
634
|
});
|
|
562
635
|
// Extract type references for imports from resolved types
|
|
563
|
-
for (
|
|
564
|
-
prop =
|
|
636
|
+
for (_g = 0, _h = schema.getProperties(); _g < _h.length; _g++) {
|
|
637
|
+
prop = _h[_g];
|
|
565
638
|
propType = prop.getTypeAtLocation(handlerFile);
|
|
566
639
|
typeSymbol = propType.getSymbol();
|
|
567
640
|
if (typeSymbol) {
|
|
@@ -581,6 +654,45 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
581
654
|
}
|
|
582
655
|
}
|
|
583
656
|
}
|
|
657
|
+
currentPropTypeText = propType.getText(undefined, ts_morph_1.ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope);
|
|
658
|
+
interfaceNameMatches = currentPropTypeText.match(/\b([A-Z][a-zA-Z0-9]*)\s*\[/g);
|
|
659
|
+
if (interfaceNameMatches) {
|
|
660
|
+
for (_j = 0, interfaceNameMatches_2 = interfaceNameMatches; _j < interfaceNameMatches_2.length; _j++) {
|
|
661
|
+
match = interfaceNameMatches_2[_j];
|
|
662
|
+
interfaceName = match.replace(/\s*\[$/, '').trim();
|
|
663
|
+
interfaceDecl = handlerFile.getInterface(interfaceName) || handlerFile.getTypeAlias(interfaceName);
|
|
664
|
+
if (interfaceDecl) {
|
|
665
|
+
// Interface is in same file - copy it and all its dependencies recursively
|
|
666
|
+
this.copyInterfaceWithDependencies(interfaceDecl, handlerFile);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
typeArgs = propType.getTypeArguments();
|
|
671
|
+
if (typeArgs && typeArgs.length > 0) {
|
|
672
|
+
for (_k = 0, typeArgs_1 = typeArgs; _k < typeArgs_1.length; _k++) {
|
|
673
|
+
typeArg = typeArgs_1[_k];
|
|
674
|
+
argSymbol = typeArg.getSymbol();
|
|
675
|
+
if (argSymbol) {
|
|
676
|
+
argDeclaration = argSymbol.getDeclarations()[0];
|
|
677
|
+
if (argDeclaration && argDeclaration.getSourceFile() !== handlerFile) {
|
|
678
|
+
this.tsSchemasSymbolsToImports.push(argSymbol);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
// If we have a declaration, check if we need to import any types
|
|
685
|
+
if (declaration) {
|
|
686
|
+
for (_l = 0, _m = (0, TypeScriptUtils_1.getTypesToImport)(declaration); _l < _m.length; _l++) {
|
|
687
|
+
typeToImport = _m[_l];
|
|
688
|
+
typeSymbol = typeToImport.getSymbol();
|
|
689
|
+
if (typeSymbol) {
|
|
690
|
+
declaredTypeSymbol = typeSymbol.getDeclaredType().getSymbol();
|
|
691
|
+
if (declaredTypeSymbol) {
|
|
692
|
+
this.tsSchemasSymbolsToImports.push(declaredTypeSymbol);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
584
696
|
}
|
|
585
697
|
generatedSchemaInterfaceStr = "export interface ".concat(schemaInterfaceName, " { ").concat(propertySignatures.join(";\n"), " }");
|
|
586
698
|
}
|
package/dist/src/utils.d.ts
CHANGED
|
@@ -25,3 +25,15 @@ export declare function getJsDocComment(comment: string): string;
|
|
|
25
25
|
* @returns
|
|
26
26
|
*/
|
|
27
27
|
export declare function getPathParams(path: string): string[];
|
|
28
|
+
/**
|
|
29
|
+
* Extracts data at a given JSON path (e.g., "/jobs/5/result")
|
|
30
|
+
* Returns the value at that path, or undefined if not found
|
|
31
|
+
*/
|
|
32
|
+
export declare function getDataAtPath(data: any, instancePath: string): any;
|
|
33
|
+
/**
|
|
34
|
+
* Formats validation errors with context about the problematic data
|
|
35
|
+
* @param errors AJV validation errors
|
|
36
|
+
* @param data The full data object that failed validation
|
|
37
|
+
* @param maxDataLength Maximum length of data to show (default 500)
|
|
38
|
+
*/
|
|
39
|
+
export declare function formatValidationErrors(errors: any[] | null | undefined, data: any, maxDataLength?: number): string;
|
package/dist/src/utils.js
CHANGED
|
@@ -50,6 +50,8 @@ exports.getRepoInstanceName = getRepoInstanceName;
|
|
|
50
50
|
exports.getHttpMethodFromHandlerName = getHttpMethodFromHandlerName;
|
|
51
51
|
exports.getJsDocComment = getJsDocComment;
|
|
52
52
|
exports.getPathParams = getPathParams;
|
|
53
|
+
exports.getDataAtPath = getDataAtPath;
|
|
54
|
+
exports.formatValidationErrors = formatValidationErrors;
|
|
53
55
|
var path_1 = require("path");
|
|
54
56
|
var tiny_glob_1 = __importDefault(require("tiny-glob"));
|
|
55
57
|
var FlinkHttpHandler_1 = require("./FlinkHttpHandler");
|
|
@@ -138,6 +140,8 @@ function getHttpMethodFromHandlerName(handlerFilename) {
|
|
|
138
140
|
return FlinkHttpHandler_1.HttpMethod.put;
|
|
139
141
|
if (handlerFilename.startsWith(FlinkHttpHandler_1.HttpMethod.delete))
|
|
140
142
|
return FlinkHttpHandler_1.HttpMethod.delete;
|
|
143
|
+
if (handlerFilename.startsWith(FlinkHttpHandler_1.HttpMethod.patch))
|
|
144
|
+
return FlinkHttpHandler_1.HttpMethod.patch;
|
|
141
145
|
}
|
|
142
146
|
function getJsDocComment(comment) {
|
|
143
147
|
var rows = comment.split("\n").map(function (line) {
|
|
@@ -160,3 +164,72 @@ function getPathParams(path) {
|
|
|
160
164
|
var _a;
|
|
161
165
|
return ((_a = path.match(pathParamsRegex)) === null || _a === void 0 ? void 0 : _a.map(function (match) { return match.slice(1); })) || [];
|
|
162
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Extracts data at a given JSON path (e.g., "/jobs/5/result")
|
|
169
|
+
* Returns the value at that path, or undefined if not found
|
|
170
|
+
*/
|
|
171
|
+
function getDataAtPath(data, instancePath) {
|
|
172
|
+
if (!instancePath || instancePath === "/") {
|
|
173
|
+
return data;
|
|
174
|
+
}
|
|
175
|
+
var parts = instancePath.split("/").filter(function (p) { return p.length > 0; });
|
|
176
|
+
var current = data;
|
|
177
|
+
for (var _i = 0, parts_1 = parts; _i < parts_1.length; _i++) {
|
|
178
|
+
var part = parts_1[_i];
|
|
179
|
+
if (current === undefined || current === null) {
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
current = current[part];
|
|
183
|
+
}
|
|
184
|
+
return current;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Formats validation errors with context about the problematic data
|
|
188
|
+
* @param errors AJV validation errors
|
|
189
|
+
* @param data The full data object that failed validation
|
|
190
|
+
* @param maxDataLength Maximum length of data to show (default 500)
|
|
191
|
+
*/
|
|
192
|
+
function formatValidationErrors(errors, data, maxDataLength) {
|
|
193
|
+
if (maxDataLength === void 0) { maxDataLength = 500; }
|
|
194
|
+
if (!errors || errors.length === 0) {
|
|
195
|
+
return "Unknown validation error";
|
|
196
|
+
}
|
|
197
|
+
var formatted = [];
|
|
198
|
+
// Group errors by instance path to avoid repetition
|
|
199
|
+
var errorsByPath = new Map();
|
|
200
|
+
for (var _i = 0, errors_1 = errors; _i < errors_1.length; _i++) {
|
|
201
|
+
var error = errors_1[_i];
|
|
202
|
+
var path = error.instancePath || "/";
|
|
203
|
+
if (!errorsByPath.has(path)) {
|
|
204
|
+
errorsByPath.set(path, []);
|
|
205
|
+
}
|
|
206
|
+
errorsByPath.get(path).push(error);
|
|
207
|
+
}
|
|
208
|
+
errorsByPath.forEach(function (pathErrors, path) {
|
|
209
|
+
var dataAtPath = getDataAtPath(data, path);
|
|
210
|
+
var dataStr = JSON.stringify(dataAtPath);
|
|
211
|
+
// Truncate if too long
|
|
212
|
+
if (dataStr.length > maxDataLength) {
|
|
213
|
+
dataStr = dataStr.substring(0, maxDataLength) + "... (truncated)";
|
|
214
|
+
}
|
|
215
|
+
formatted.push("\nPath: ".concat(path));
|
|
216
|
+
formatted.push("Data: ".concat(dataStr));
|
|
217
|
+
formatted.push("Errors:");
|
|
218
|
+
for (var _i = 0, pathErrors_1 = pathErrors; _i < pathErrors_1.length; _i++) {
|
|
219
|
+
var error = pathErrors_1[_i];
|
|
220
|
+
if (error.keyword === "required") {
|
|
221
|
+
formatted.push(" - Missing required property: ".concat(error.params.missingProperty));
|
|
222
|
+
}
|
|
223
|
+
else if (error.keyword === "type") {
|
|
224
|
+
formatted.push(" - Invalid type at ".concat(error.schemaPath, ": expected ").concat(error.params.type, ", got ").concat(typeof dataAtPath));
|
|
225
|
+
}
|
|
226
|
+
else if (error.keyword === "anyOf" || error.keyword === "oneOf") {
|
|
227
|
+
formatted.push(" - ".concat(error.message));
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
formatted.push(" - ".concat(error.message, " (").concat(error.keyword, ")"));
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
return formatted.join("\n");
|
|
235
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.__schemas = exports.__params = exports.__query = exports.__file = exports.__assumedHttpMethod = exports.Route = void 0;
|
|
40
|
+
var flink_1 = require("@flink-app/flink");
|
|
41
|
+
exports.Route = {
|
|
42
|
+
path: "/car/:id",
|
|
43
|
+
method: flink_1.HttpMethod.patch,
|
|
44
|
+
};
|
|
45
|
+
var PatchCar = function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
|
|
46
|
+
var req = _b.req;
|
|
47
|
+
return __generator(this, function (_c) {
|
|
48
|
+
return [2 /*return*/, {
|
|
49
|
+
data: {
|
|
50
|
+
model: req.body.model || "Updated Model",
|
|
51
|
+
year: req.body.year || 2024,
|
|
52
|
+
},
|
|
53
|
+
}];
|
|
54
|
+
});
|
|
55
|
+
}); };
|
|
56
|
+
exports.default = PatchCar;
|
|
57
|
+
exports.__assumedHttpMethod = "patch", exports.__file = "PatchCar.ts", exports.__query = [], exports.__params = [{ description: "", name: "id" }];
|
|
58
|
+
exports.__schemas = { reqSchema: { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "model": { "type": "string" }, "year": { "type": "number" } }, "additionalProperties": false, "definitions": {} }, resSchema: { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "model": { "type": "string" }, "year": { "type": "number" } }, "required": ["model", "year"], "additionalProperties": false, "definitions": {} } };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.__schemas = exports.__params = exports.__query = exports.__file = exports.__assumedHttpMethod = exports.Route = void 0;
|
|
40
|
+
var flink_1 = require("@flink-app/flink");
|
|
41
|
+
exports.Route = {
|
|
42
|
+
path: "/onboarding/:sessionId",
|
|
43
|
+
method: flink_1.HttpMethod.patch,
|
|
44
|
+
};
|
|
45
|
+
var PatchOnboardingSession = function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
|
|
46
|
+
var _c, _d;
|
|
47
|
+
var req = _b.req;
|
|
48
|
+
return __generator(this, function (_e) {
|
|
49
|
+
return [2 /*return*/, {
|
|
50
|
+
data: {
|
|
51
|
+
sessionId: req.params.sessionId,
|
|
52
|
+
status: req.body.status || "pending",
|
|
53
|
+
extractedData: {
|
|
54
|
+
companyName: ((_c = req.body.extractedData) === null || _c === void 0 ? void 0 : _c.companyName) || "Test Company",
|
|
55
|
+
orgNumber: ((_d = req.body.extractedData) === null || _d === void 0 ? void 0 : _d.orgNumber) || "123456",
|
|
56
|
+
address: {
|
|
57
|
+
street: "Main St",
|
|
58
|
+
city: "Stockholm",
|
|
59
|
+
postalCode: "12345",
|
|
60
|
+
},
|
|
61
|
+
contactInfo: {
|
|
62
|
+
email: "test@example.com",
|
|
63
|
+
phone: "+46701234567",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
metadata: {
|
|
67
|
+
createdAt: new Date(),
|
|
68
|
+
updatedAt: new Date(),
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
}];
|
|
72
|
+
});
|
|
73
|
+
}); };
|
|
74
|
+
exports.default = PatchOnboardingSession;
|
|
75
|
+
exports.__assumedHttpMethod = "patch", exports.__file = "PatchOnboardingSession.ts", exports.__query = [], exports.__params = [{ description: "", name: "sessionId" }];
|
|
76
|
+
exports.__schemas = { reqSchema: { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "status": { "type": "string" }, "extractedData": { "type": "object", "properties": { "companyName": { "type": "string" }, "orgNumber": { "type": "string" }, "address": { "type": "object", "properties": { "street": { "type": "string" }, "city": { "type": "string" }, "postalCode": { "type": "string" } }, "required": ["street", "city", "postalCode"], "additionalProperties": false }, "contactInfo": { "type": "object", "properties": { "email": { "type": "string" }, "phone": { "type": "string" } }, "required": ["email", "phone"], "additionalProperties": false } }, "additionalProperties": false }, "metadata": { "type": "object", "properties": { "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "additionalProperties": false } }, "additionalProperties": false, "definitions": {} }, resSchema: { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "sessionId": { "type": "string" }, "status": { "type": "string" }, "extractedData": { "type": "object", "properties": { "companyName": { "type": "string" }, "orgNumber": { "type": "string" }, "address": { "type": "object", "properties": { "street": { "type": "string" }, "city": { "type": "string" }, "postalCode": { "type": "string" } }, "required": ["street", "city", "postalCode"], "additionalProperties": false }, "contactInfo": { "type": "object", "properties": { "email": { "type": "string" }, "phone": { "type": "string" } }, "required": ["email", "phone"], "additionalProperties": false } }, "required": ["companyName", "orgNumber", "address", "contactInfo"], "additionalProperties": false }, "metadata": { "type": "object", "properties": { "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" } }, "required": ["createdAt", "updatedAt"], "additionalProperties": false } }, "required": ["sessionId", "status", "extractedData", "metadata"], "additionalProperties": false, "definitions": {} } };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.__schemas = exports.__params = exports.__query = exports.__file = exports.__assumedHttpMethod = exports.Route = void 0;
|
|
40
|
+
var flink_1 = require("@flink-app/flink");
|
|
41
|
+
exports.Route = {
|
|
42
|
+
path: "/order/:orderId",
|
|
43
|
+
method: flink_1.HttpMethod.patch,
|
|
44
|
+
};
|
|
45
|
+
var PatchOrderWithComplexTypes = function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
|
|
46
|
+
var req = _b.req;
|
|
47
|
+
return __generator(this, function (_c) {
|
|
48
|
+
return [2 /*return*/, {
|
|
49
|
+
data: {
|
|
50
|
+
orderId: req.params.orderId,
|
|
51
|
+
status: "updated",
|
|
52
|
+
},
|
|
53
|
+
}];
|
|
54
|
+
});
|
|
55
|
+
}); };
|
|
56
|
+
exports.default = PatchOrderWithComplexTypes;
|
|
57
|
+
exports.__assumedHttpMethod = "patch", exports.__file = "PatchOrderWithComplexTypes.ts", exports.__query = [], exports.__params = [{ description: "", name: "orderId" }];
|
|
58
|
+
exports.__schemas = { reqSchema: { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "customerCity": { "type": "object", "properties": { "street": { "type": "string" }, "city": { "type": "string" }, "country": { "type": "string" } }, "additionalProperties": false }, "items": { "type": "object", "additionalProperties": false, "properties": { "items": { "type": "array", "items": { "type": "object", "properties": { "productId": { "type": "string" }, "quantity": { "type": "number" }, "price": { "type": "number" } }, "required": ["productId", "quantity", "price"], "additionalProperties": false } }, "subtotal": { "type": "number" } }, "required": ["items", "subtotal"] }, "shipping": { "type": "object", "additionalProperties": false, "properties": { "method": { "type": "string" } }, "required": ["method"] }, "paymentOrShipping": { "type": "object", "additionalProperties": false }, "itemUpdates": { "type": "array", "items": { "type": "object", "properties": { "productId": { "type": "string" }, "quantity": { "type": "number" }, "price": { "type": "number" } }, "additionalProperties": false } } }, "additionalProperties": false, "definitions": {} }, resSchema: { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "orderId": { "type": "string" }, "status": { "type": "string" } }, "required": ["orderId", "status"], "additionalProperties": false, "definitions": {} } };
|