@nestia/core 13.0.4 → 14.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/MIGRATION.md +20 -0
- package/README.md +1 -1
- package/lib/adaptors/McpAdaptor.d.ts +5 -0
- package/lib/adaptors/McpAdaptor.js +114 -26
- package/lib/adaptors/McpAdaptor.js.map +1 -1
- package/lib/adaptors/WebSocketAdaptor.js +124 -32
- package/lib/adaptors/WebSocketAdaptor.js.map +1 -1
- package/lib/adaptors/internal/RoutePathMatcher.d.ts +1 -0
- package/lib/adaptors/internal/RoutePathMatcher.js +88 -0
- package/lib/adaptors/internal/RoutePathMatcher.js.map +1 -0
- package/lib/adaptors/internal/external_context.d.ts +1 -0
- package/lib/adaptors/internal/external_context.js +43 -0
- package/lib/adaptors/internal/external_context.js.map +1 -0
- package/lib/decorators/EncryptedBody.js +2 -2
- package/lib/decorators/EncryptedBody.js.map +1 -1
- package/lib/decorators/EncryptedController.js +1 -1
- package/lib/decorators/EncryptedController.js.map +1 -1
- package/lib/decorators/EncryptedModule.d.ts +7 -3
- package/lib/decorators/EncryptedModule.js +69 -15
- package/lib/decorators/EncryptedModule.js.map +1 -1
- package/lib/decorators/EncryptedRoute.js +7 -2
- package/lib/decorators/EncryptedRoute.js.map +1 -1
- package/lib/decorators/TypedBody.d.ts +1 -1
- package/lib/decorators/TypedBody.js +1 -1
- package/lib/decorators/TypedFormData.d.ts +22 -8
- package/lib/decorators/TypedFormData.js +116 -31
- package/lib/decorators/TypedFormData.js.map +1 -1
- package/lib/decorators/TypedParam.d.ts +3 -3
- package/lib/decorators/TypedParam.js +3 -3
- package/lib/decorators/TypedQuery.d.ts +1 -1
- package/lib/decorators/TypedQuery.js +9 -4
- package/lib/decorators/TypedQuery.js.map +1 -1
- package/lib/decorators/internal/EncryptedConstant.js +13 -2
- package/lib/decorators/internal/EncryptedConstant.js.map +1 -1
- package/lib/decorators/internal/get_encryption_password.d.ts +1 -0
- package/lib/decorators/internal/get_encryption_password.js +14 -0
- package/lib/decorators/internal/get_encryption_password.js.map +1 -0
- package/lib/decorators/internal/get_path_and_querify.js +21 -3
- package/lib/decorators/internal/get_path_and_querify.js.map +1 -1
- package/lib/decorators/internal/get_text_body.js +9 -3
- package/lib/decorators/internal/get_text_body.js.map +1 -1
- package/lib/decorators/internal/group_entries.d.ts +1 -0
- package/lib/decorators/internal/group_entries.js +19 -0
- package/lib/decorators/internal/group_entries.js.map +1 -0
- package/lib/decorators/internal/validate_request_form_data.js +3 -1
- package/lib/decorators/internal/validate_request_form_data.js.map +1 -1
- package/lib/decorators/internal/validate_request_headers.js +2 -1
- package/lib/decorators/internal/validate_request_headers.js.map +1 -1
- package/lib/decorators/internal/validate_request_query.js +3 -1
- package/lib/decorators/internal/validate_request_query.js.map +1 -1
- package/lib/options/IResponseBodyQuerifier.d.ts +5 -1
- package/lib/utils/ExceptionManager.d.ts +3 -4
- package/lib/utils/ExceptionManager.js +10 -6
- package/lib/utils/ExceptionManager.js.map +1 -1
- package/lib/utils/SourceFinder.js +26 -3
- package/lib/utils/SourceFinder.js.map +1 -1
- package/lib/utils/VersioningStrategy.d.ts +9 -1
- package/lib/utils/VersioningStrategy.js +18 -6
- package/lib/utils/VersioningStrategy.js.map +1 -1
- package/native/go.mod +1 -1
- package/native/go.sum +2 -2
- package/native/transform/ast.go +4 -2
- package/native/transform/core_querify.go +26 -6
- package/native/transform/core_transform.go +76 -1
- package/native/transform/core_websocket.go +94 -13
- package/native/transform/node_transform.go +6 -0
- package/native/transform/transform.go +8 -18
- package/native/transform/typia_fast.go +6 -0
- package/native/transform.cjs +49 -0
- package/package.json +14 -17
- package/src/adaptors/McpAdaptor.ts +150 -28
- package/src/adaptors/WebSocketAdaptor.ts +136 -38
- package/src/adaptors/internal/RoutePathMatcher.ts +91 -0
- package/src/adaptors/internal/external_context.ts +50 -0
- package/src/decorators/EncryptedBody.ts +2 -2
- package/src/decorators/EncryptedController.ts +6 -2
- package/src/decorators/EncryptedModule.ts +71 -15
- package/src/decorators/EncryptedRoute.ts +7 -5
- package/src/decorators/TypedBody.ts +1 -1
- package/src/decorators/TypedFormData.ts +148 -44
- package/src/decorators/TypedParam.ts +3 -3
- package/src/decorators/TypedQuery.ts +19 -7
- package/src/decorators/internal/EncryptedConstant.ts +14 -1
- package/src/decorators/internal/get_encryption_password.ts +19 -0
- package/src/decorators/internal/get_path_and_querify.ts +29 -2
- package/src/decorators/internal/get_text_body.ts +8 -4
- package/src/decorators/internal/group_entries.ts +17 -0
- package/src/decorators/internal/validate_request_form_data.ts +3 -1
- package/src/decorators/internal/validate_request_headers.ts +2 -2
- package/src/decorators/internal/validate_request_query.ts +3 -2
- package/src/options/IResponseBodyQuerifier.ts +6 -1
- package/src/utils/ExceptionManager.ts +10 -6
- package/src/utils/SourceFinder.ts +24 -3
- package/src/utils/VersioningStrategy.ts +21 -7
- package/lib/transform.d.ts +0 -10
- package/lib/transform.js +0 -25
- package/lib/transform.js.map +0 -1
- package/src/transform.ts +0 -26
|
@@ -11,18 +11,17 @@ import { Creator } from "../typings/Creator";
|
|
|
11
11
|
* {@link EncryptedRoute} instead of the basic router decorator functions like
|
|
12
12
|
* {@link nest.Get} or {@link nest.Post} and the API function throws a custom
|
|
13
13
|
* error whose class has been {@link ExceptionManager.insert inserted} in this
|
|
14
|
-
* `
|
|
14
|
+
* `ExceptionManager`, the error would be automatically converted to the regular
|
|
15
15
|
* {@link nest.HttpException} instance by the {@link ExceptionManager.Closure}
|
|
16
16
|
* function.
|
|
17
17
|
*
|
|
18
18
|
* Therefore, with this `ExceptionManager` and {@link TypedRoute} or
|
|
19
19
|
* {@link EncryptedRoute}, you can manage your custom error classes much
|
|
20
|
-
*
|
|
20
|
+
* systematically. You can avoid 500 internal server error or hard coding
|
|
21
21
|
* implementation about the custom error classes.
|
|
22
22
|
*
|
|
23
|
-
* Below error
|
|
23
|
+
* Below error class is configured in this `ExceptionManager` by default.
|
|
24
24
|
*
|
|
25
|
-
* - `typia.TypeGuardError`
|
|
26
25
|
* - `@nestia/fetcher.HttpError`
|
|
27
26
|
*
|
|
28
27
|
* @author Jeongho Nam - https://github.com/samchon
|
|
@@ -14,18 +14,17 @@ const common_1 = require("@nestjs/common");
|
|
|
14
14
|
* {@link EncryptedRoute} instead of the basic router decorator functions like
|
|
15
15
|
* {@link nest.Get} or {@link nest.Post} and the API function throws a custom
|
|
16
16
|
* error whose class has been {@link ExceptionManager.insert inserted} in this
|
|
17
|
-
* `
|
|
17
|
+
* `ExceptionManager`, the error would be automatically converted to the regular
|
|
18
18
|
* {@link nest.HttpException} instance by the {@link ExceptionManager.Closure}
|
|
19
19
|
* function.
|
|
20
20
|
*
|
|
21
21
|
* Therefore, with this `ExceptionManager` and {@link TypedRoute} or
|
|
22
22
|
* {@link EncryptedRoute}, you can manage your custom error classes much
|
|
23
|
-
*
|
|
23
|
+
* systematically. You can avoid 500 internal server error or hard coding
|
|
24
24
|
* implementation about the custom error classes.
|
|
25
25
|
*
|
|
26
|
-
* Below error
|
|
26
|
+
* Below error class is configured in this `ExceptionManager` by default.
|
|
27
27
|
*
|
|
28
|
-
* - `typia.TypeGuardError`
|
|
29
28
|
* - `@nestia/fetcher.HttpError`
|
|
30
29
|
*
|
|
31
30
|
* @author Jeongho Nam - https://github.com/samchon
|
|
@@ -45,8 +44,13 @@ var ExceptionManager;
|
|
|
45
44
|
const index = ExceptionManager.tuples.findIndex((tuple) => tuple[0] === creator);
|
|
46
45
|
if (index !== -1)
|
|
47
46
|
ExceptionManager.tuples.splice(index, 1);
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
// an error converts by the first class it is an instance of, so a class
|
|
48
|
+
// must precede every superclass of it: insert before the first one
|
|
49
|
+
const ancestor = ExceptionManager.tuples.findIndex(([registered]) => creator.prototype instanceof registered);
|
|
50
|
+
if (ancestor === -1)
|
|
51
|
+
ExceptionManager.tuples.push([creator, closure]);
|
|
52
|
+
else
|
|
53
|
+
ExceptionManager.tuples.splice(ancestor, 0, [creator, closure]);
|
|
50
54
|
}
|
|
51
55
|
ExceptionManager.insert = insert;
|
|
52
56
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExceptionManager.js","sourceRoot":"","sources":["../../src/utils/ExceptionManager.ts"],"names":[],"mappings":";;;AAAA,6CAA4C;AAC5C,2CAA+C;AAI/C
|
|
1
|
+
{"version":3,"file":"ExceptionManager.js","sourceRoot":"","sources":["../../src/utils/ExceptionManager.ts"],"names":[],"mappings":";;;AAAA,6CAA4C;AAC5C,2CAA+C;AAI/C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,IAAiB,gBAAgB,CA2EhC;AA3ED,WAAiB,gBAAgB;IAC/B;;;;;;;;OAQG;IACH,SAAgB,MAAM,CACpB,OAAmB,EACnB,OAAmB;QAEnB,MAAM,KAAK,GAAW,uBAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;QACxE,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,uBAAM,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAE1C,wEAAwE;QACxE,mEAAmE;QACnE,MAAM,QAAQ,GAAW,uBAAM,CAAC,SAAS,CACvC,CAAC,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,YAAY,UAAU,CAC1D,CAAC;QACF,IAAI,QAAQ,KAAK,CAAC,CAAC;YAAE,uBAAM,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;;YAChD,uBAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,CAAC;IAde,iBAAA,MAAM,SAcrB,CAAA;IAED;;;;;OAKG;IACH,SAAgB,KAAK,CAAkB,OAAmB;QACxD,MAAM,KAAK,GAAW,uBAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;QACxE,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAE/B,uBAAM,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IANe,iBAAA,KAAK,QAMpB,CAAA;IAED,SAAgB,EAAE,CAAC,OAA4B;QAC7C,0BAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAFe,iBAAA,EAAE,KAEjB,CAAA;IAED,SAAgB,GAAG,CAAC,OAA4B;QAC9C,0BAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAFe,iBAAA,GAAG,MAElB,CAAA;IAwBD,gBAAgB;IACH,uBAAM,GAAwC,EAAE,CAAC;IAE9D,gBAAgB;IACH,0BAAS,GAA6B,IAAI,GAAG,EAAE,CAAC;AAC/D,CAAC,EA3EgB,gBAAgB,aAAhB,gBAAgB,GAAhB,gBAAgB,QA2EhC;AAED,gBAAgB,CAAC,MAAM,CACrB,mBAAS,EACT,CAAC,KAAK,EAAE,EAAE,CACR,IAAI,sBAAa,CACf;IACE,IAAI,EAAE,KAAK,CAAC,IAAI;IAChB,OAAO,EAAE,KAAK,CAAC,OAAO;CACvB,EACD,KAAK,CAAC,MAAM,CACb,CACJ,CAAC"}
|
|
@@ -28,7 +28,7 @@ var SourceFinder;
|
|
|
28
28
|
});
|
|
29
29
|
const emplace = (filter) => (input) => (closure) => __awaiter(this, void 0, void 0, function* () {
|
|
30
30
|
for (const pattern of input) {
|
|
31
|
-
for (const file of yield _Glob(
|
|
31
|
+
for (const file of yield _Glob(pattern)) {
|
|
32
32
|
const stats = yield fs_1.default.promises.stat(file);
|
|
33
33
|
if (stats.isDirectory() === true)
|
|
34
34
|
yield iterate(filter)(closure)(file);
|
|
@@ -48,9 +48,32 @@ var SourceFinder;
|
|
|
48
48
|
closure(next);
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
|
+
/**
|
|
52
|
+
* Files and directories a path or glob pattern names.
|
|
53
|
+
*
|
|
54
|
+
* An existing path is taken literally, whatever characters it holds, as a
|
|
55
|
+
* directory such as `app [v2]` would otherwise read as a character class. For
|
|
56
|
+
* a pattern, the longest existing ancestor is the literal base and only the
|
|
57
|
+
* rest is globbed, with `/` separators, since glob reads a Windows backslash
|
|
58
|
+
* as an escape.
|
|
59
|
+
*/
|
|
51
60
|
const _Glob = (pattern) => __awaiter(this, void 0, void 0, function* () {
|
|
52
|
-
const
|
|
53
|
-
|
|
61
|
+
const absolute = path_1.default.resolve(pattern);
|
|
62
|
+
if (fs_1.default.existsSync(absolute))
|
|
63
|
+
return [absolute];
|
|
64
|
+
let base = absolute;
|
|
65
|
+
while (fs_1.default.existsSync(base) === false) {
|
|
66
|
+
const parent = path_1.default.dirname(base);
|
|
67
|
+
if (parent === base)
|
|
68
|
+
return [];
|
|
69
|
+
base = parent;
|
|
70
|
+
}
|
|
71
|
+
const rest = path_1.default
|
|
72
|
+
.relative(base, absolute)
|
|
73
|
+
.split(path_1.default.sep)
|
|
74
|
+
.join("/");
|
|
75
|
+
const matches = yield (0, glob_1.glob)(rest, { cwd: base });
|
|
76
|
+
return matches.map((str) => path_1.default.resolve(base, str));
|
|
54
77
|
});
|
|
55
78
|
})(SourceFinder || (exports.SourceFinder = SourceFinder = {}));
|
|
56
79
|
//# sourceMappingURL=SourceFinder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SourceFinder.js","sourceRoot":"","sources":["../../src/utils/SourceFinder.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,4CAAoB;AACpB,+BAA4B;AAC5B,gDAAwB;AAExB,IAAiB,YAAY,
|
|
1
|
+
{"version":3,"file":"SourceFinder.js","sourceRoot":"","sources":["../../src/utils/SourceFinder.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,5 +5,13 @@ export declare namespace VersioningStrategy {
|
|
|
5
5
|
defaultVersion?: VersionValue;
|
|
6
6
|
}
|
|
7
7
|
const cast: (value: VersionValue | undefined) => Array<string | typeof VERSION_NEUTRAL>;
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Version path segments of a route, resolved as NestJS resolves them: the
|
|
10
|
+
* method's versions, else the controller's, else the default version, and no
|
|
11
|
+
* version at all is the unversioned path (#1735).
|
|
12
|
+
*/
|
|
13
|
+
const merge: (config: IConfig | undefined) => (props: {
|
|
14
|
+
controller: Array<string | typeof VERSION_NEUTRAL> | undefined;
|
|
15
|
+
method: Array<string | typeof VERSION_NEUTRAL> | undefined;
|
|
16
|
+
}) => string[];
|
|
9
17
|
}
|
|
@@ -4,14 +4,26 @@ exports.VersioningStrategy = void 0;
|
|
|
4
4
|
var VersioningStrategy;
|
|
5
5
|
(function (VersioningStrategy) {
|
|
6
6
|
VersioningStrategy.cast = (value) => value === undefined ? [] : Array.isArray(value) ? value : [value];
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Version path segments of a route, resolved as NestJS resolves them: the
|
|
9
|
+
* method's versions, else the controller's, else the default version, and no
|
|
10
|
+
* version at all is the unversioned path (#1735).
|
|
11
|
+
*/
|
|
12
|
+
VersioningStrategy.merge = (config) => (props) => {
|
|
13
|
+
var _a, _b;
|
|
8
14
|
if (config === undefined)
|
|
9
15
|
return [""];
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
const chosen = ((_a = props.method) === null || _a === void 0 ? void 0 : _a.length)
|
|
17
|
+
? props.method
|
|
18
|
+
: ((_b = props.controller) === null || _b === void 0 ? void 0 : _b.length)
|
|
19
|
+
? props.controller
|
|
20
|
+
: VersioningStrategy.cast(config.defaultVersion);
|
|
21
|
+
const unique = [
|
|
22
|
+
...new Set(chosen),
|
|
23
|
+
];
|
|
24
|
+
return unique.length
|
|
25
|
+
? unique.map((x) => typeof x === "symbol" ? "" : `${config.prefix}${x}`)
|
|
26
|
+
: [""];
|
|
15
27
|
};
|
|
16
28
|
})(VersioningStrategy || (exports.VersioningStrategy = VersioningStrategy = {}));
|
|
17
29
|
//# sourceMappingURL=VersioningStrategy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VersioningStrategy.js","sourceRoot":"","sources":["../../src/utils/VersioningStrategy.ts"],"names":[],"mappings":";;;AAEA,IAAiB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"VersioningStrategy.js","sourceRoot":"","sources":["../../src/utils/VersioningStrategy.ts"],"names":[],"mappings":";;;AAEA,IAAiB,kBAAkB,CAsClC;AAtCD,WAAiB,kBAAkB;IAMpB,uBAAI,GAAG,CAClB,KAA+B,EACS,EAAE,CAC1C,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAEpE;;;;OAIG;IACU,wBAAK,GAChB,CAAC,MAA2B,EAAE,EAAE,CAChC,CAAC,KAGA,EAAY,EAAE;;QACb,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QACtC,MAAM,MAAM,GAA2C,CAAA,MAAA,KAAK,CAAC,MAAM,0CAC/D,MAAM;YACR,CAAC,CAAC,KAAK,CAAC,MAAM;YACd,CAAC,CAAC,CAAA,MAAA,KAAK,CAAC,UAAU,0CAAE,MAAM;gBACxB,CAAC,CAAC,KAAK,CAAC,UAAU;gBAClB,CAAC,CAAC,uBAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAClC,MAAM,MAAM,GAA2C;YACrD,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC;SACnB,CAAC;QACF,OAAO,MAAM,CAAC,MAAM;YAClB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACf,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CACpD;YACH,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACX,CAAC,CAAC;AACN,CAAC,EAtCgB,kBAAkB,aAAlB,kBAAkB,GAAlB,kBAAkB,QAsClC"}
|
package/native/go.mod
CHANGED
|
@@ -10,7 +10,7 @@ require (
|
|
|
10
10
|
github.com/microsoft/typescript-go/shim/printer v0.0.0
|
|
11
11
|
github.com/microsoft/typescript-go/shim/scanner v0.0.0
|
|
12
12
|
github.com/samchon/ttsc/packages/ttsc v0.0.0
|
|
13
|
-
github.com/samchon/typia/packages/typia/native v0.0.0-
|
|
13
|
+
github.com/samchon/typia/packages/typia/native v0.0.0-20260922081121-78124b0523b4
|
|
14
14
|
)
|
|
15
15
|
|
|
16
16
|
require (
|
package/native/go.sum
CHANGED
|
@@ -38,8 +38,8 @@ github.com/samchon/ttsc/packages/ttsc/shim/vfs/cachedvfs v0.0.0-20260820075544-3
|
|
|
38
38
|
github.com/samchon/ttsc/packages/ttsc/shim/vfs/cachedvfs v0.0.0-20260820075544-3fe6b732f888/go.mod h1:XS3LhXkn5xadyRe3tW+9+suW/7gh7dPdL43Q+s/lUDo=
|
|
39
39
|
github.com/samchon/ttsc/packages/ttsc/shim/vfs/osvfs v0.0.0-20260820075544-3fe6b732f888 h1:ihiKD2OhuYc7Dngxw3uFYbVoiA/xuPwwQoUakB59E40=
|
|
40
40
|
github.com/samchon/ttsc/packages/ttsc/shim/vfs/osvfs v0.0.0-20260820075544-3fe6b732f888/go.mod h1:otX+qw8aZLNCoBmCwMAn53Nw0RQTPzSoId3DxmE67So=
|
|
41
|
-
github.com/samchon/typia/packages/typia/native v0.0.0-
|
|
42
|
-
github.com/samchon/typia/packages/typia/native v0.0.0-
|
|
41
|
+
github.com/samchon/typia/packages/typia/native v0.0.0-20260922081121-78124b0523b4 h1:ZL20GliY1kZk/PYHwJX+n5cp8ljx8YToGP1wWFtaOYs=
|
|
42
|
+
github.com/samchon/typia/packages/typia/native v0.0.0-20260922081121-78124b0523b4/go.mod h1:pUTSG5IZxw8Hohle//RsDXnE+8ZhAus7mPDKFqzvZnk=
|
|
43
43
|
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
|
44
44
|
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
|
45
45
|
github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs=
|
package/native/transform/ast.go
CHANGED
|
@@ -7,12 +7,14 @@ import (
|
|
|
7
7
|
)
|
|
8
8
|
|
|
9
9
|
// NodeName returns the trimmed identifier text of a named AST node
|
|
10
|
-
// (method, parameter, ...). Empty when the node has no name.
|
|
10
|
+
// (method, parameter, ...). Empty when the node has no name. A name that is no
|
|
11
|
+
// identifier, a destructured parameter's `{ a }` or a computed method name's
|
|
12
|
+
// `[key]`, reads as its source, since typescript-go's `Text()` panics on it.
|
|
11
13
|
func NodeName(node *shimast.Node) string {
|
|
12
14
|
if node == nil || node.Name() == nil {
|
|
13
15
|
return ""
|
|
14
16
|
}
|
|
15
|
-
return strings.Trim(node.Name()
|
|
17
|
+
return strings.Trim(shimast.NodeText(node.Name()), "\"'")
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
// NodeText returns the verbatim source slice spanned by a node.
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
package transform
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
-
"fmt"
|
|
5
|
-
|
|
6
4
|
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
7
5
|
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
8
6
|
shimprinter "github.com/microsoft/typescript-go/shim/printer"
|
|
@@ -44,7 +42,13 @@ func nestiaCoreHttpQuerifyProgrammer(prog *driver.Program, ec *shimprinter.EmitC
|
|
|
44
42
|
Type: typ,
|
|
45
43
|
})
|
|
46
44
|
if result.Success == false {
|
|
47
|
-
panic(
|
|
45
|
+
panic(nativecontext.TransformerError_from(struct {
|
|
46
|
+
Code string
|
|
47
|
+
Errors []nativecontext.TransformerError_MetadataFactory_IError
|
|
48
|
+
}{
|
|
49
|
+
Code: "nestia.core.TypedQueryRoute",
|
|
50
|
+
Errors: nestiaCoreMetadataErrors(result.Errors),
|
|
51
|
+
}))
|
|
48
52
|
}
|
|
49
53
|
statements := []*shimast.Node{
|
|
50
54
|
nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
|
|
@@ -149,12 +153,28 @@ func nestiaCoreHttpValidateQuerifyProgrammer(prog *driver.Program, importer *nat
|
|
|
149
153
|
Name: "query",
|
|
150
154
|
Value: nestiaCoreHttpQuerifyProgrammer(prog, ec, typ),
|
|
151
155
|
}),
|
|
156
|
+
// the object is validated, then querified: validating the
|
|
157
|
+
// URLSearchParams against the object type found every property absent
|
|
152
158
|
nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
|
|
153
|
-
Name: "
|
|
154
|
-
Value: nestiaCoreCall("
|
|
159
|
+
Name: "result",
|
|
160
|
+
Value: nestiaCoreCall("validate", nestiaCoreFactory.NewIdentifier("input")),
|
|
155
161
|
}),
|
|
156
162
|
nestiaCoreFactory.NewReturnStatement(nestiaCoreFactory.NewAsExpression(
|
|
157
|
-
|
|
163
|
+
nestiaCoreFactory.NewConditionalExpression(
|
|
164
|
+
nestiaCoreFactory.NewPropertyAccessExpression(
|
|
165
|
+
nestiaCoreFactory.NewIdentifier("result"),
|
|
166
|
+
nil,
|
|
167
|
+
nestiaCoreFactory.NewIdentifier("success"),
|
|
168
|
+
shimast.NodeFlagsNone,
|
|
169
|
+
),
|
|
170
|
+
nil,
|
|
171
|
+
nestiaCoreFactory.NewObjectLiteralExpression(nestiaCoreFactory.NewNodeList([]*shimast.Node{
|
|
172
|
+
nestiaCoreProperty("success", nestiaCoreFactory.NewKeywordExpression(shimast.KindTrueKeyword), ec),
|
|
173
|
+
nestiaCoreProperty("data", nestiaCoreCall("query", nestiaCoreFactory.NewIdentifier("input")), ec),
|
|
174
|
+
}), false),
|
|
175
|
+
nil,
|
|
176
|
+
nestiaCoreFactory.NewIdentifier("result"),
|
|
177
|
+
),
|
|
158
178
|
nativefactories.TypeFactory.Keyword("any"),
|
|
159
179
|
)),
|
|
160
180
|
})
|
|
@@ -94,6 +94,60 @@ type nestiaCoreFileContext struct {
|
|
|
94
94
|
coreImports map[string]string
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
// The values the validate and stringify options accept.
|
|
98
|
+
var (
|
|
99
|
+
nestiaCoreValidateModes = []string{
|
|
100
|
+
"assert", "is", "validate", "equals",
|
|
101
|
+
"assertEquals", "validateEquals",
|
|
102
|
+
"assertClone", "validateClone",
|
|
103
|
+
"assertPrune", "validatePrune",
|
|
104
|
+
}
|
|
105
|
+
nestiaCoreStringifyModes = []string{"stringify", "assert", "is", "validate", "validate.log"}
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
// nestiaCoreOptionErrors reports each validate or stringify option value that
|
|
109
|
+
// is no mode: a generator would otherwise take its default branch, and a typo
|
|
110
|
+
// such as "assertEqual" silently weakens validation.
|
|
111
|
+
func nestiaCoreOptionErrors(plan plugin.Plan) []string {
|
|
112
|
+
errors := []string{}
|
|
113
|
+
check := func(name string, value any, modes []string, nullable bool) {
|
|
114
|
+
if value == nil && nullable {
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
if text, ok := value.(string); ok {
|
|
118
|
+
for _, mode := range modes {
|
|
119
|
+
if mode == text {
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
accepted := "\"" + strings.Join(modes, "\", \"") + "\""
|
|
125
|
+
if nullable {
|
|
126
|
+
accepted += ", or null"
|
|
127
|
+
}
|
|
128
|
+
errors = append(errors, fmt.Sprintf("invalid %q option %s: it must be one of %s.", name, nestiaCoreOptionText(value), accepted))
|
|
129
|
+
}
|
|
130
|
+
for _, entry := range plan.Entries {
|
|
131
|
+
if entry.Name != "@nestia/core" && !strings.Contains(entry.Transform, "@nestia/core") {
|
|
132
|
+
continue
|
|
133
|
+
}
|
|
134
|
+
if value, ok := entry.Config["validate"]; ok {
|
|
135
|
+
check("validate", value, nestiaCoreValidateModes, false)
|
|
136
|
+
}
|
|
137
|
+
if value, ok := entry.Config["stringify"]; ok {
|
|
138
|
+
check("stringify", value, nestiaCoreStringifyModes, true)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return errors
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
func nestiaCoreOptionText(value any) string {
|
|
145
|
+
if text, ok := value.(string); ok {
|
|
146
|
+
return fmt.Sprintf("%q", text)
|
|
147
|
+
}
|
|
148
|
+
return fmt.Sprintf("%v", value)
|
|
149
|
+
}
|
|
150
|
+
|
|
97
151
|
func readNestiaCoreOptions(plan plugin.Plan) nestiaCoreOptions {
|
|
98
152
|
options := nestiaCoreOptions{}
|
|
99
153
|
for _, entry := range plan.Entries {
|
|
@@ -174,6 +228,19 @@ func nestiaCoreDecoratorCall(prog *driver.Program, decorator *shimast.Node) (*sh
|
|
|
174
228
|
return call, canonical, true
|
|
175
229
|
}
|
|
176
230
|
|
|
231
|
+
// NestiaCoreCanonicalDecoratorSegments names a decorator call's callee by the
|
|
232
|
+
// @nestia/core export its import binds, so `import { TypedException as TE }`
|
|
233
|
+
// reads `TE<T>()` as `TypedException`. It returns nil for a decorator that is
|
|
234
|
+
// no call.
|
|
235
|
+
func NestiaCoreCanonicalDecoratorSegments(decorator *shimast.Node) []string {
|
|
236
|
+
_, segments, ok := nestiaCoreRawDecoratorCall(decorator)
|
|
237
|
+
if !ok {
|
|
238
|
+
return nil
|
|
239
|
+
}
|
|
240
|
+
context := newNestiaCoreFileContext(shimast.GetSourceFileOfNode(decorator))
|
|
241
|
+
return nestiaCoreCanonicalSegments(context, segments)
|
|
242
|
+
}
|
|
243
|
+
|
|
177
244
|
func newNestiaCoreFileContext(file *shimast.SourceFile) nestiaCoreFileContext {
|
|
178
245
|
context := nestiaCoreFileContext{
|
|
179
246
|
file: file,
|
|
@@ -538,7 +605,13 @@ func nestiaCoreFormDataFiles(prog *driver.Program, typ *shimchecker.Type) []nest
|
|
|
538
605
|
Type: typ,
|
|
539
606
|
})
|
|
540
607
|
if result.Success == false {
|
|
541
|
-
panic(
|
|
608
|
+
panic(nativecontext.TransformerError_from(struct {
|
|
609
|
+
Code string
|
|
610
|
+
Errors []nativecontext.TransformerError_MetadataFactory_IError
|
|
611
|
+
}{
|
|
612
|
+
Code: "nestia.core.TypedFormDataBody",
|
|
613
|
+
Errors: nestiaCoreMetadataErrors(result.Errors),
|
|
614
|
+
}))
|
|
542
615
|
}
|
|
543
616
|
files := []nestiaCoreFormDataFile{}
|
|
544
617
|
if result.Data == nil || len(result.Data.Objects) == 0 || result.Data.Objects[0] == nil || result.Data.Objects[0].Type == nil {
|
|
@@ -678,6 +751,8 @@ func nestiaCoreGenerateTypedQueryRoute(prog *driver.Program, importer *nativecon
|
|
|
678
751
|
return nestiaCoreValidatorObject("type", "validate", nestiaCoreHttpValidateQuerifyProgrammer(prog, importer, ec, modulo, typ), ec)
|
|
679
752
|
case "stringify":
|
|
680
753
|
return nestiaCoreValidatorObject("type", "stringify", nestiaCoreHttpQuerifyProgrammer(prog, ec, typ), ec)
|
|
754
|
+
case "validate.log":
|
|
755
|
+
return nestiaCoreValidatorObjectWithKey("type", "validate.log", "validate", nestiaCoreHttpValidateQuerifyProgrammer(prog, importer, ec, modulo, typ), ec)
|
|
681
756
|
default:
|
|
682
757
|
return nestiaCoreValidatorObject("type", "assert", nestiaCoreHttpAssertQuerifyProgrammer(prog, importer, ec, modulo, typ), ec)
|
|
683
758
|
}
|
|
@@ -2,9 +2,11 @@ package transform
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"fmt"
|
|
5
|
+
"path/filepath"
|
|
5
6
|
"strings"
|
|
6
7
|
|
|
7
8
|
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
9
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
8
10
|
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
9
11
|
"github.com/samchon/ttsc/packages/ttsc/driver"
|
|
10
12
|
)
|
|
@@ -42,14 +44,14 @@ func validateNestiaCoreWebSocketRoute(
|
|
|
42
44
|
switch category {
|
|
43
45
|
case "Acceptor":
|
|
44
46
|
accepted = true
|
|
45
|
-
if
|
|
47
|
+
if _, target := NestiaCoreWebSocketTypeReference(prog, nestiaCoreWebSocketParameterTypeNode(param)); target != "WebSocketAcceptor" {
|
|
46
48
|
diagnostics = append(diagnostics, nestiaCoreWebSocketDiagnostic(context.file, param, "WebSocketRoute", fmt.Sprintf(
|
|
47
49
|
"parameter %q must have WebSocketAcceptor<Header, Provider, Listener> type.",
|
|
48
50
|
name,
|
|
49
51
|
)))
|
|
50
52
|
}
|
|
51
53
|
case "Driver":
|
|
52
|
-
if
|
|
54
|
+
if _, target := NestiaCoreWebSocketTypeReference(prog, nestiaCoreWebSocketParameterTypeNode(param)); target != "Driver" {
|
|
53
55
|
diagnostics = append(diagnostics, nestiaCoreWebSocketDiagnostic(context.file, param, "WebSocketRoute", fmt.Sprintf(
|
|
54
56
|
"parameter %q must have Driver<Listener> type.",
|
|
55
57
|
name,
|
|
@@ -66,6 +68,12 @@ func validateNestiaCoreWebSocketRoute(
|
|
|
66
68
|
return diagnostics
|
|
67
69
|
}
|
|
68
70
|
|
|
71
|
+
// NestiaCoreWebSocketParameterCategory names the WebSocketRoute parameter
|
|
72
|
+
// decorator on a parameter, such as "Acceptor" or "Driver", or "" for none.
|
|
73
|
+
func NestiaCoreWebSocketParameterCategory(prog *driver.Program, param *shimast.Node) string {
|
|
74
|
+
return nestiaCoreWebSocketParameterCategory(prog, param)
|
|
75
|
+
}
|
|
76
|
+
|
|
69
77
|
func nestiaCoreWebSocketParameterCategory(prog *driver.Program, param *shimast.Node) string {
|
|
70
78
|
if param == nil || len(param.Decorators()) != 1 {
|
|
71
79
|
return ""
|
|
@@ -78,19 +86,90 @@ func nestiaCoreWebSocketParameterCategory(prog *driver.Program, param *shimast.N
|
|
|
78
86
|
return segments[len(segments)-1]
|
|
79
87
|
}
|
|
80
88
|
|
|
81
|
-
func
|
|
82
|
-
if param == nil || param.AsParameterDeclaration() == nil
|
|
83
|
-
return
|
|
89
|
+
func nestiaCoreWebSocketParameterTypeNode(param *shimast.Node) *shimast.Node {
|
|
90
|
+
if param == nil || param.AsParameterDeclaration() == nil {
|
|
91
|
+
return nil
|
|
92
|
+
}
|
|
93
|
+
return param.AsParameterDeclaration().Type
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// NestiaCoreWebSocketTypeReference follows a parameter's type annotation
|
|
97
|
+
// through renamed imports, import types, and type aliases to the tgrid type
|
|
98
|
+
// reference it spells, such as `WebSocketAcceptor<Header, Provider, Listener>`
|
|
99
|
+
// or `Driver<Listener>`, so the transform and the SDK accept every spelling of
|
|
100
|
+
// the same type and still reject another type of the same name. It returns the
|
|
101
|
+
// type references it passed, each a type reference or an import type such as
|
|
102
|
+
// `import("tgrid").Driver<Listener>`, from the annotation to the tgrid
|
|
103
|
+
// reference, each after the first written in the type alias the one before it
|
|
104
|
+
// names, and the name tgrid declares the type by; or nil and "" when the
|
|
105
|
+
// annotation leads to no tgrid type.
|
|
106
|
+
func NestiaCoreWebSocketTypeReference(prog *driver.Program, node *shimast.Node) ([]*shimast.Node, string) {
|
|
107
|
+
chain := []*shimast.Node{}
|
|
108
|
+
for depth := 0; node != nil && depth < 32; depth++ {
|
|
109
|
+
if node.Kind == shimast.KindParenthesizedType {
|
|
110
|
+
node = node.AsParenthesizedTypeNode().Type
|
|
111
|
+
continue
|
|
112
|
+
}
|
|
113
|
+
name := nestiaCoreTypeReferenceName(node)
|
|
114
|
+
if name == nil || prog == nil || prog.Checker == nil {
|
|
115
|
+
return nil, ""
|
|
116
|
+
}
|
|
117
|
+
chain = append(chain, node)
|
|
118
|
+
symbol := prog.Checker.GetSymbolAtLocation(name)
|
|
119
|
+
if symbol != nil && symbol.Flags&shimast.SymbolFlagsAlias != 0 {
|
|
120
|
+
if aliased := shimchecker.Checker_getAliasedSymbol(prog.Checker, symbol); aliased != nil {
|
|
121
|
+
symbol = aliased
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if symbol == nil {
|
|
125
|
+
return nil, ""
|
|
126
|
+
}
|
|
127
|
+
if nestiaCoreIsTgridDeclarations(symbol.Declarations) {
|
|
128
|
+
return chain, symbol.Name
|
|
129
|
+
}
|
|
130
|
+
if symbol.Flags&shimast.SymbolFlagsTypeAlias == 0 {
|
|
131
|
+
return nil, ""
|
|
132
|
+
}
|
|
133
|
+
var alias *shimast.Node
|
|
134
|
+
for _, declaration := range symbol.Declarations {
|
|
135
|
+
if declaration != nil && declaration.Kind == shimast.KindTypeAliasDeclaration {
|
|
136
|
+
alias = declaration
|
|
137
|
+
break
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if alias == nil {
|
|
141
|
+
return nil, ""
|
|
142
|
+
}
|
|
143
|
+
node = alias.AsTypeAliasDeclaration().Type
|
|
84
144
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
145
|
+
return nil, ""
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// nestiaCoreTypeReferenceName is the entity a type names: the `A.B` of
|
|
149
|
+
// `A.B<T>`, or the qualifier of an import type such as `import("m").A.B<T>`.
|
|
150
|
+
// It is nil for any other type, including `typeof import("m")`, the type of a
|
|
151
|
+
// module's value.
|
|
152
|
+
func nestiaCoreTypeReferenceName(node *shimast.Node) *shimast.Node {
|
|
153
|
+
switch node.Kind {
|
|
154
|
+
case shimast.KindTypeReference:
|
|
155
|
+
return node.AsTypeReferenceNode().TypeName
|
|
156
|
+
case shimast.KindImportType:
|
|
157
|
+
if node.AsImportTypeNode().IsTypeOf {
|
|
158
|
+
return nil
|
|
159
|
+
}
|
|
160
|
+
return node.AsImportTypeNode().Qualifier
|
|
89
161
|
}
|
|
90
|
-
|
|
91
|
-
|
|
162
|
+
return nil
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
func nestiaCoreIsTgridDeclarations(declarations []*shimast.Node) bool {
|
|
166
|
+
for _, declaration := range declarations {
|
|
167
|
+
source := shimast.GetSourceFileOfNode(declaration)
|
|
168
|
+
if source != nil && strings.Contains(filepath.ToSlash(source.FileName()), "/tgrid/") {
|
|
169
|
+
return true
|
|
170
|
+
}
|
|
92
171
|
}
|
|
93
|
-
return
|
|
172
|
+
return false
|
|
94
173
|
}
|
|
95
174
|
|
|
96
175
|
func nestiaCoreWebSocketDiagnostic(file *shimast.SourceFile, node *shimast.Node, kind string, message string) Diagnostic {
|
|
@@ -99,7 +178,9 @@ func nestiaCoreWebSocketDiagnostic(file *shimast.SourceFile, node *shimast.Node,
|
|
|
99
178
|
if file != nil {
|
|
100
179
|
filePath = file.FileName()
|
|
101
180
|
if node != nil {
|
|
102
|
-
|
|
181
|
+
// the first token's position: Pos() starts at the leading trivia,
|
|
182
|
+
// the previous line's end and any JSDoc
|
|
183
|
+
if pos := shimscanner.GetTokenPosOfNode(node, file, false); pos >= 0 {
|
|
103
184
|
l, c := shimscanner.GetECMALineAndByteOffsetOfPosition(file, pos)
|
|
104
185
|
line, column = l+1, c+1
|
|
105
186
|
}
|
|
@@ -30,6 +30,7 @@ func nestiaCoreNodeTransform(
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
options := readNestiaCoreOptions(plan)
|
|
33
|
+
optionErrors := nestiaCoreOptionErrors(plan)
|
|
33
34
|
strictReported := false
|
|
34
35
|
return func(ec *shimprinter.EmitContext, sf *shimast.SourceFile) *shimast.SourceFile {
|
|
35
36
|
if sf == nil || sf.IsDeclarationFile {
|
|
@@ -39,6 +40,11 @@ func nestiaCoreNodeTransform(
|
|
|
39
40
|
strictReported = true
|
|
40
41
|
addDiagnostic(nestiaCoreGlobalDiagnostic("@nestia/core", "strict mode is required."))
|
|
41
42
|
}
|
|
43
|
+
// reported once, with the first file transformed
|
|
44
|
+
for _, message := range optionErrors {
|
|
45
|
+
addDiagnostic(nestiaCoreGlobalDiagnostic("@nestia/core", message))
|
|
46
|
+
}
|
|
47
|
+
optionErrors = nil
|
|
42
48
|
importer := nativecontext.NewImportProgrammer(nativecontext.ImportProgrammer_IOptions{
|
|
43
49
|
InternalPrefix: "typia_transform_",
|
|
44
50
|
Runtime: "typia",
|
|
@@ -7,7 +7,6 @@ import (
|
|
|
7
7
|
"fmt"
|
|
8
8
|
"os"
|
|
9
9
|
"path/filepath"
|
|
10
|
-
"regexp"
|
|
11
10
|
"strings"
|
|
12
11
|
|
|
13
12
|
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
@@ -169,7 +168,14 @@ func runTransformProject(
|
|
|
169
168
|
sf := prog.SourceFile(fileName)
|
|
170
169
|
return sf != nil && prog.TSProgram.IsLibFile(sf)
|
|
171
170
|
})
|
|
172
|
-
|
|
171
|
+
// `File` alone is the whole listener this host needs. `Callee` falls back
|
|
172
|
+
// to it, and the two channels differ only in whether a default library
|
|
173
|
+
// withholds a completeness declaration, which this host never makes;
|
|
174
|
+
// `Unbounded` is ignorable for the same reason, since an unreported input
|
|
175
|
+
// is still watched through the reference graph.
|
|
176
|
+
schemametadata.MetadataDependency_listen(prog.Checker, schemametadata.MetadataDependency_IListener{
|
|
177
|
+
File: collector.Touch,
|
|
178
|
+
})
|
|
173
179
|
defer schemametadata.MetadataDependency_release(prog.Checker)
|
|
174
180
|
for _, sf := range prog.SourceFiles() {
|
|
175
181
|
if sf.IsDeclarationFile {
|
|
@@ -256,22 +262,6 @@ func SourceFileText(target any) (string, bool) {
|
|
|
256
262
|
return file.Text(), true
|
|
257
263
|
}
|
|
258
264
|
|
|
259
|
-
// These patterns run once per transformed file in cleanupTypeScriptTransformText
|
|
260
|
-
// / normalizeParenthesizedTypeAnnotations. Compiling them at package scope keeps
|
|
261
|
-
// the per-file cost to a match instead of a recompile (the SDK `transform` path
|
|
262
|
-
// runs this for every emitted source file).
|
|
263
|
-
var (
|
|
264
|
-
cleanupImportTypeBlockPattern = regexp.MustCompile(`(?m)^import type \{([^{}\n]+)\} from`)
|
|
265
|
-
cleanupImportTypeLinePattern = regexp.MustCompile(`^import type \{\s*([^{}\n]+?)\s*\} from`)
|
|
266
|
-
cleanupImportBlankLinePattern = regexp.MustCompile(`(?m)(^import [^\n]+;\n)\n+(const |let |var |export )`)
|
|
267
|
-
cleanupInputIsParenPattern = regexp.MustCompile(`input is \(([A-Za-z_$][A-Za-z0-9_$.]*)\)`)
|
|
268
|
-
cleanupCollapseBlankCallPattern = regexp.MustCompile(`\n\n([A-Za-z_$][A-Za-z0-9_$]*\([^;\n]*\);?)`)
|
|
269
|
-
)
|
|
270
|
-
var (
|
|
271
|
-
normalizeParenArrowTypePattern = regexp.MustCompile(`: \(([A-Za-z_$][A-Za-z0-9_$.]*(<[^()\n;{}]*>)?)\)(\s*=>)`)
|
|
272
|
-
normalizeParenNullishPattern = regexp.MustCompile(`\| \((null|undefined)\)`)
|
|
273
|
-
)
|
|
274
|
-
|
|
275
265
|
func transformDiagnosticToCompilerDiagnostic(
|
|
276
266
|
diag Diagnostic,
|
|
277
267
|
) transformCompilerDiagnostic {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
package transform
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
+
"sync"
|
|
5
|
+
|
|
4
6
|
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
5
7
|
shimprinter "github.com/microsoft/typescript-go/shim/printer"
|
|
6
8
|
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
@@ -22,6 +24,10 @@ func nestiaTypiaNodeTransform(
|
|
|
22
24
|
) driver.PluginTransform {
|
|
23
25
|
transformOptions := pluginOptions.TransformOptions()
|
|
24
26
|
extras := nativecontext.ITypiaContext_Extras{
|
|
27
|
+
// One cache for the whole program, as typia's own hosts share it: left
|
|
28
|
+
// nil, typia makes one per file, and a program-wide analysis such as
|
|
29
|
+
// `llm.evaluation`'s `@probability` scan reruns for every file.
|
|
30
|
+
Shared: &sync.Map{},
|
|
25
31
|
AddDiagnostic: func(diag *nativecontext.ITypiaDiagnostic) int {
|
|
26
32
|
addDiagnostic(nestiaTypiaDiagnosticFrom(diag))
|
|
27
33
|
return 1
|