typia 13.0.0-dev.20260626.1 → 13.0.0-dev.20260701.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.
Files changed (31) hide show
  1. package/lib/internal/_randomArray.d.ts +2 -1
  2. package/lib/internal/_randomArray.js +8 -2
  3. package/lib/internal/_randomArray.js.map +1 -1
  4. package/lib/internal/_randomArray2.mjs +8 -2
  5. package/lib/internal/_randomArray2.mjs.map +1 -1
  6. package/lib/internal/_randomString.d.ts +1 -1
  7. package/lib/internal/_randomString.js +6 -3
  8. package/lib/internal/_randomString.js.map +1 -1
  9. package/lib/internal/_randomString2.mjs +6 -3
  10. package/lib/internal/_randomString2.mjs.map +1 -1
  11. package/lib/transform.d.ts +2 -1
  12. package/lib/transform.js +2 -1
  13. package/lib/transform.js.map +1 -1
  14. package/lib/transform.mjs +1 -1
  15. package/lib/transform2.mjs +3 -2
  16. package/lib/transform2.mjs.map +1 -1
  17. package/native/cmd/ttsc-typia/random_recursive_min_items_diagnostic_test.go +234 -0
  18. package/native/cmd/ttsc-typia/random_unsatisfiable_recursive_diagnostic_test.go +146 -0
  19. package/native/core/factories/internal/metadata/MetadataHelper.go +47 -0
  20. package/native/core/factories/internal/metadata/emplace_metadata_alias.go +7 -0
  21. package/native/core/factories/internal/metadata/emplace_metadata_object.go +17 -3
  22. package/native/core/factories/internal/metadata/iterate_metadata_collection.go +14 -13
  23. package/native/core/programmers/RandomProgrammer.go +150 -15
  24. package/native/core/programmers/helpers/RandomJoiner.go +582 -6
  25. package/native/core/programmers/helpers/random_joiner_recursive_array_guard_test.go +166 -0
  26. package/native/core/programmers/llm/LlmApplicationProgrammer.go +15 -4
  27. package/native/core/programmers/random_programmer_min_items_tag_test.go +44 -0
  28. package/package.json +4 -4
  29. package/src/internal/_randomArray.ts +34 -21
  30. package/src/internal/_randomString.ts +30 -24
  31. package/src/transform.ts +21 -19
@@ -1,4 +1,5 @@
1
- import { OpenApi } from "@typia/interface";
1
+ import type { OpenApi } from "@typia/interface";
2
2
  export declare const _randomArray: <T>(props: Omit<OpenApi.IJsonSchema.IArray, "items"> & {
3
3
  element: (index: number, count: number) => T;
4
+ recursive?: boolean;
4
5
  }) => any[];
@@ -2,12 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports._randomArray = void 0;
4
4
  const _randomInteger_1 = require("./_randomInteger");
5
+ const DEFAULT_MIN_ITEMS = 1;
6
+ const DEFAULT_RANGE = 5;
7
+ const DEFAULT_RECURSIVE_RANGE = 2;
5
8
  const _randomArray = (props) => {
6
9
  var _a, _b, _c;
10
+ const defaultMinimum = props.recursive === true ? 0 : DEFAULT_MIN_ITEMS;
11
+ const minimum = (_a = props.minItems) !== null && _a !== void 0 ? _a : Math.min((_b = props.maxItems) !== null && _b !== void 0 ? _b : defaultMinimum, defaultMinimum);
7
12
  const count = (0, _randomInteger_1._randomInteger)({
8
13
  type: "integer",
9
- minimum: ((_a = props.minItems) !== null && _a !== void 0 ? _a : 0),
10
- maximum: (_b = props.maxItems) !== null && _b !== void 0 ? _b : ((_c = props.minItems) !== null && _c !== void 0 ? _c : 0) + 5,
14
+ minimum,
15
+ maximum: (_c = props.maxItems) !== null && _c !== void 0 ? _c : minimum +
16
+ (props.recursive === true ? DEFAULT_RECURSIVE_RANGE : DEFAULT_RANGE),
11
17
  });
12
18
  if (props.uniqueItems !== true)
13
19
  return new Array(count).fill(null).map((_, i) => props.element(i, count));
@@ -1 +1 @@
1
- {"version":3,"file":"_randomArray.js","sourceRoot":"","sources":["../../src/internal/_randomArray.ts"],"names":[],"mappings":";;;AAEA,qDAAkD;AAE3C,MAAM,YAAY,GAAG,CAC1B,KAEC,EACD,EAAE;;IACF,MAAM,KAAK,GAAW,IAAA,+BAAc,EAAC;QACnC,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,OAAC,KAAK,CAAC,QAAQ,mCAAI,CAAC,CAA4B;QACzD,OAAO,QAAE,KAAK,CAAC,QAAQ,mCAAI,OAAC,KAAK,CAAC,QAAQ,mCAAI,CAAC,CAAC,GAAG,CAAC;KACrD,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,WAAW,KAAK,IAAI;QAC5B,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAC5E,MAAM,QAAQ,GAAa,IAAI,GAAG,EAAE,CAAC;IACrC,OAAO,QAAQ,CAAC,IAAI,KAAK,KAAK;QAC5B,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IACpD,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC,CAAC;AAhBW,QAAA,YAAY,GAAZ,YAAY,CAgBvB"}
1
+ {"version":3,"file":"_randomArray.js","sourceRoot":"","sources":["../../src/internal/_randomArray.ts"],"names":[],"mappings":";;;AAEA,qDAAkD;AAElD,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAC5B,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,uBAAuB,GAAG,CAAC,CAAC;AAE3B,MAAM,YAAY,GAAG,CAC1B,KAGC,EACD,EAAE;;IACF,MAAM,cAAc,GAClB,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC;IACnD,MAAM,OAAO,SACX,KAAK,CAAC,QAAQ,mCACd,IAAI,CAAC,GAAG,OAAC,KAAK,CAAC,QAAQ,mCAAI,cAAc,EAAE,cAAc,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAW,IAAA,+BAAc,EAAC;QACnC,IAAI,EAAE,SAAS;QACf,OAAO;QACP,OAAO,QACL,KAAK,CAAC,QAAQ,mCACd,OAAO;YACL,CAAC,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,aAAa,CAAC;KACzE,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,WAAW,KAAK,IAAI;QAC5B,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAC5E,MAAM,QAAQ,GAAa,IAAI,GAAG,EAAE,CAAC;IACrC,OAAO,QAAQ,CAAC,IAAI,KAAK,KAAK;QAC5B,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IACpD,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC,CAAC;AAzBW,QAAA,YAAY,GAAZ,YAAY,CAyBvB"}
@@ -5,12 +5,18 @@ import { __exports as _randomInteger } from '../_virtual/_randomInteger.mjs';
5
5
  Object.defineProperty(_randomArray$1, "__esModule", { value: true });
6
6
  var _randomArray_2 = _randomArray$1._randomArray = void 0;
7
7
  const _randomInteger_1 = _randomInteger;
8
+ const DEFAULT_MIN_ITEMS = 1;
9
+ const DEFAULT_RANGE = 5;
10
+ const DEFAULT_RECURSIVE_RANGE = 2;
8
11
  const _randomArray = (props) => {
9
12
  var _a, _b, _c;
13
+ const defaultMinimum = props.recursive === true ? 0 : DEFAULT_MIN_ITEMS;
14
+ const minimum = (_a = props.minItems) !== null && _a !== void 0 ? _a : Math.min((_b = props.maxItems) !== null && _b !== void 0 ? _b : defaultMinimum, defaultMinimum);
10
15
  const count = (0, _randomInteger_1._randomInteger)({
11
16
  type: "integer",
12
- minimum: ((_a = props.minItems) !== null && _a !== void 0 ? _a : 0),
13
- maximum: (_b = props.maxItems) !== null && _b !== void 0 ? _b : ((_c = props.minItems) !== null && _c !== void 0 ? _c : 0) + 5,
17
+ minimum,
18
+ maximum: (_c = props.maxItems) !== null && _c !== void 0 ? _c : minimum +
19
+ (props.recursive === true ? DEFAULT_RECURSIVE_RANGE : DEFAULT_RANGE),
14
20
  });
15
21
  if (props.uniqueItems !== true)
16
22
  return new Array(count).fill(null).map((_, i) => props.element(i, count));
@@ -1 +1 @@
1
- {"version":3,"file":"_randomArray2.mjs","sources":["_randomArray.js"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports._randomArray = void 0;\nconst _randomInteger_1 = require(\"./_randomInteger\");\nconst _randomArray = (props) => {\n var _a, _b, _c;\n const count = (0, _randomInteger_1._randomInteger)({\n type: \"integer\",\n minimum: ((_a = props.minItems) !== null && _a !== void 0 ? _a : 0),\n maximum: (_b = props.maxItems) !== null && _b !== void 0 ? _b : ((_c = props.minItems) !== null && _c !== void 0 ? _c : 0) + 5,\n });\n if (props.uniqueItems !== true)\n return new Array(count).fill(null).map((_, i) => props.element(i, count));\n const elements = new Set();\n while (elements.size !== count)\n elements.add(props.element(elements.size, count));\n return Array.from(elements);\n};\nexports._randomArray = _randomArray;\n//# sourceMappingURL=_randomArray.js.map"],"names":["_randomArray_1","require$$0"],"mappings":";;;;AACA,MAAM,CAAC,cAAc,CAACA,cAAO,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC7D,IAAA,cAAA,GAAAA,cAAA,CAAA,YAAoB,GAAG;AACvB,MAAM,gBAAgB,GAAGC,cAA2B;AACpD,MAAM,YAAY,GAAG,CAAC,KAAK,KAAK;AAChC,IAAI,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE;AAClB,IAAI,MAAM,KAAK,GAAG,IAAI,gBAAgB,CAAC,cAAc,EAAE;AACvD,QAAQ,IAAI,EAAE,SAAS;AACvB,QAAQ,OAAO,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,QAAQ,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,CAAC,CAAC;AAC3E,QAAQ,OAAO,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC,QAAQ,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,QAAQ,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC;AACtI,KAAK,CAAC;AACN,IAAI,IAAI,KAAK,CAAC,WAAW,KAAK,IAAI;AAClC,QAAQ,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AACjF,IAAI,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAE;AAC9B,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,KAAK;AAClC,QAAQ,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACzD,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;AAC/B,CAAC;AACD,cAAA,GAAAD,cAAA,CAAA,YAAoB,GAAG,YAAY;;;;"}
1
+ {"version":3,"file":"_randomArray2.mjs","sources":["_randomArray.js"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports._randomArray = void 0;\nconst _randomInteger_1 = require(\"./_randomInteger\");\nconst DEFAULT_MIN_ITEMS = 1;\nconst DEFAULT_RANGE = 5;\nconst DEFAULT_RECURSIVE_RANGE = 2;\nconst _randomArray = (props) => {\n var _a, _b, _c;\n const defaultMinimum = props.recursive === true ? 0 : DEFAULT_MIN_ITEMS;\n const minimum = (_a = props.minItems) !== null && _a !== void 0 ? _a : Math.min((_b = props.maxItems) !== null && _b !== void 0 ? _b : defaultMinimum, defaultMinimum);\n const count = (0, _randomInteger_1._randomInteger)({\n type: \"integer\",\n minimum,\n maximum: (_c = props.maxItems) !== null && _c !== void 0 ? _c : minimum +\n (props.recursive === true ? DEFAULT_RECURSIVE_RANGE : DEFAULT_RANGE),\n });\n if (props.uniqueItems !== true)\n return new Array(count).fill(null).map((_, i) => props.element(i, count));\n const elements = new Set();\n while (elements.size !== count)\n elements.add(props.element(elements.size, count));\n return Array.from(elements);\n};\nexports._randomArray = _randomArray;\n//# sourceMappingURL=_randomArray.js.map"],"names":["_randomArray_1","require$$0"],"mappings":";;;;AACA,MAAM,CAAC,cAAc,CAACA,cAAO,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC7D,IAAA,cAAA,GAAAA,cAAA,CAAA,YAAoB,GAAG;AACvB,MAAM,gBAAgB,GAAGC,cAA2B;AACpD,MAAM,iBAAiB,GAAG,CAAC;AAC3B,MAAM,aAAa,GAAG,CAAC;AACvB,MAAM,uBAAuB,GAAG,CAAC;AACjC,MAAM,YAAY,GAAG,CAAC,KAAK,KAAK;AAChC,IAAI,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE;AAClB,IAAI,MAAM,cAAc,GAAG,KAAK,CAAC,SAAS,KAAK,IAAI,GAAG,CAAC,GAAG,iBAAiB;AAC3E,IAAI,MAAM,OAAO,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,QAAQ,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,QAAQ,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,cAAc,EAAE,cAAc,CAAC;AAC1K,IAAI,MAAM,KAAK,GAAG,IAAI,gBAAgB,CAAC,cAAc,EAAE;AACvD,QAAQ,IAAI,EAAE,SAAS;AACvB,QAAQ,OAAO;AACf,QAAQ,OAAO,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC,QAAQ,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,OAAO;AAC/E,aAAa,KAAK,CAAC,SAAS,KAAK,IAAI,GAAG,uBAAuB,GAAG,aAAa,CAAC;AAChF,KAAK,CAAC;AACN,IAAI,IAAI,KAAK,CAAC,WAAW,KAAK,IAAI;AAClC,QAAQ,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AACjF,IAAI,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAE;AAC9B,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,KAAK;AAClC,QAAQ,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACzD,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;AAC/B,CAAC;AACD,cAAA,GAAAD,cAAA,CAAA,YAAoB,GAAG,YAAY;;;;"}
@@ -1,2 +1,2 @@
1
- import { OpenApi } from "@typia/interface";
1
+ import type { OpenApi } from "@typia/interface";
2
2
  export declare const _randomString: (props: OpenApi.IJsonSchema.IString) => string;
@@ -2,12 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports._randomString = void 0;
4
4
  const _randomInteger_1 = require("./_randomInteger");
5
+ const DEFAULT_MIN_LENGTH = 5;
6
+ const DEFAULT_RANGE = 5;
5
7
  const _randomString = (props) => {
6
- var _a;
8
+ var _a, _b, _c;
9
+ const minimum = (_a = props.minLength) !== null && _a !== void 0 ? _a : Math.min((_b = props.maxLength) !== null && _b !== void 0 ? _b : DEFAULT_MIN_LENGTH, DEFAULT_MIN_LENGTH);
7
10
  const length = (0, _randomInteger_1._randomInteger)({
8
11
  type: "integer",
9
- minimum: ((_a = props.minLength) !== null && _a !== void 0 ? _a : 0),
10
- maximum: props.maxLength,
12
+ minimum,
13
+ maximum: (_c = props.maxLength) !== null && _c !== void 0 ? _c : minimum + DEFAULT_RANGE,
11
14
  });
12
15
  return new Array(length)
13
16
  .fill(0)
@@ -1 +1 @@
1
- {"version":3,"file":"_randomString.js","sourceRoot":"","sources":["../../src/internal/_randomString.ts"],"names":[],"mappings":";;;AAEA,qDAAkD;AAE3C,MAAM,aAAa,GAAG,CAAC,KAAkC,EAAE,EAAE;;IAClE,MAAM,MAAM,GAAW,IAAA,+BAAc,EAAC;QACpC,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,OAAC,KAAK,CAAC,SAAS,mCAAI,CAAC,CAA4B;QAC1D,OAAO,EAAE,KAAK,CAAC,SAA4D;KAC5E,CAAC,CAAC;IACH,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC;SACrB,IAAI,CAAC,CAAC,CAAC;SACP,GAAG,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;SAC9B,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC,CAAC;AAVW,QAAA,aAAa,GAAb,aAAa,CAUxB;AAEF,MAAM,SAAS,GAAG,4BAA4B,CAAC;AAE/C,MAAM,MAAM,GAAG,GAAG,EAAE,CAClB,IAAA,+BAAc,EAAC;IACb,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,CAAC;IACV,OAAO,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC;CAC9B,CAAC,CAAC"}
1
+ {"version":3,"file":"_randomString.js","sourceRoot":"","sources":["../../src/internal/_randomString.ts"],"names":[],"mappings":";;;AAEA,qDAAkD;AAElD,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,MAAM,aAAa,GAAG,CAAC,CAAC;AAEjB,MAAM,aAAa,GAAG,CAAC,KAAkC,EAAE,EAAE;;IAClE,MAAM,OAAO,SACX,KAAK,CAAC,SAAS,mCACf,IAAI,CAAC,GAAG,OAAC,KAAK,CAAC,SAAS,mCAAI,kBAAkB,EAAE,kBAAkB,CAAC,CAAC;IACtE,MAAM,MAAM,GAAW,IAAA,+BAAc,EAAC;QACpC,IAAI,EAAE,SAAS;QACf,OAAO;QACP,OAAO,QAAE,KAAK,CAAC,SAAS,mCAAI,OAAO,GAAG,aAAa;KACpD,CAAC,CAAC;IACH,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC;SACrB,IAAI,CAAC,CAAC,CAAC;SACP,GAAG,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;SAC9B,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC,CAAC;AAbW,QAAA,aAAa,GAAb,aAAa,CAaxB;AAEF,MAAM,SAAS,GAAG,4BAA4B,CAAC;AAE/C,MAAM,MAAM,GAAG,GAAG,EAAE,CAClB,IAAA,+BAAc,EAAC;IACb,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,CAAC;IACV,OAAO,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC;CAC9B,CAAC,CAAC"}
@@ -5,12 +5,15 @@ import { __exports as _randomInteger } from '../_virtual/_randomInteger.mjs';
5
5
  Object.defineProperty(_randomString$1, "__esModule", { value: true });
6
6
  var _randomString_2 = _randomString$1._randomString = void 0;
7
7
  const _randomInteger_1 = _randomInteger;
8
+ const DEFAULT_MIN_LENGTH = 5;
9
+ const DEFAULT_RANGE = 5;
8
10
  const _randomString = (props) => {
9
- var _a;
11
+ var _a, _b, _c;
12
+ const minimum = (_a = props.minLength) !== null && _a !== void 0 ? _a : Math.min((_b = props.maxLength) !== null && _b !== void 0 ? _b : DEFAULT_MIN_LENGTH, DEFAULT_MIN_LENGTH);
10
13
  const length = (0, _randomInteger_1._randomInteger)({
11
14
  type: "integer",
12
- minimum: ((_a = props.minLength) !== null && _a !== void 0 ? _a : 0),
13
- maximum: props.maxLength,
15
+ minimum,
16
+ maximum: (_c = props.maxLength) !== null && _c !== void 0 ? _c : minimum + DEFAULT_RANGE,
14
17
  });
15
18
  return new Array(length)
16
19
  .fill(0)
@@ -1 +1 @@
1
- {"version":3,"file":"_randomString2.mjs","sources":["_randomString.js"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports._randomString = void 0;\nconst _randomInteger_1 = require(\"./_randomInteger\");\nconst _randomString = (props) => {\n var _a;\n const length = (0, _randomInteger_1._randomInteger)({\n type: \"integer\",\n minimum: ((_a = props.minLength) !== null && _a !== void 0 ? _a : 0),\n maximum: props.maxLength,\n });\n return new Array(length)\n .fill(0)\n .map(() => ALPHABETS[random()])\n .join(\"\");\n};\nexports._randomString = _randomString;\nconst ALPHABETS = \"abcdefghijklmnopqrstuvwxyz\";\nconst random = () => (0, _randomInteger_1._randomInteger)({\n type: \"integer\",\n minimum: 0,\n maximum: ALPHABETS.length - 1,\n});\n//# sourceMappingURL=_randomString.js.map"],"names":["_randomString_1","require$$0"],"mappings":";;;;AACA,MAAM,CAAC,cAAc,CAACA,eAAO,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC7D,IAAA,eAAA,GAAAA,eAAA,CAAA,aAAqB,GAAG;AACxB,MAAM,gBAAgB,GAAGC,cAA2B;AACpD,MAAM,aAAa,GAAG,CAAC,KAAK,KAAK;AACjC,IAAI,IAAI,EAAE;AACV,IAAI,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,cAAc,EAAE;AACxD,QAAQ,IAAI,EAAE,SAAS;AACvB,QAAQ,OAAO,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,SAAS,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,CAAC,CAAC;AAC5E,QAAQ,OAAO,EAAE,KAAK,CAAC,SAAS;AAChC,KAAK,CAAC;AACN,IAAI,OAAO,IAAI,KAAK,CAAC,MAAM;AAC3B,SAAS,IAAI,CAAC,CAAC;AACf,SAAS,GAAG,CAAC,MAAM,SAAS,CAAC,MAAM,EAAE,CAAC;AACtC,SAAS,IAAI,CAAC,EAAE,CAAC;AACjB,CAAC;AACD,eAAA,GAAAD,eAAA,CAAA,aAAqB,GAAG,aAAa;AACrC,MAAM,SAAS,GAAG,4BAA4B;AAC9C,MAAM,MAAM,GAAG,MAAM,IAAI,gBAAgB,CAAC,cAAc,EAAE;AAC1D,IAAI,IAAI,EAAE,SAAS;AACnB,IAAI,OAAO,EAAE,CAAC;AACd,IAAI,OAAO,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC;AACjC,CAAC,CAAC;;;;"}
1
+ {"version":3,"file":"_randomString2.mjs","sources":["_randomString.js"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports._randomString = void 0;\nconst _randomInteger_1 = require(\"./_randomInteger\");\nconst DEFAULT_MIN_LENGTH = 5;\nconst DEFAULT_RANGE = 5;\nconst _randomString = (props) => {\n var _a, _b, _c;\n const minimum = (_a = props.minLength) !== null && _a !== void 0 ? _a : Math.min((_b = props.maxLength) !== null && _b !== void 0 ? _b : DEFAULT_MIN_LENGTH, DEFAULT_MIN_LENGTH);\n const length = (0, _randomInteger_1._randomInteger)({\n type: \"integer\",\n minimum,\n maximum: (_c = props.maxLength) !== null && _c !== void 0 ? _c : minimum + DEFAULT_RANGE,\n });\n return new Array(length)\n .fill(0)\n .map(() => ALPHABETS[random()])\n .join(\"\");\n};\nexports._randomString = _randomString;\nconst ALPHABETS = \"abcdefghijklmnopqrstuvwxyz\";\nconst random = () => (0, _randomInteger_1._randomInteger)({\n type: \"integer\",\n minimum: 0,\n maximum: ALPHABETS.length - 1,\n});\n//# sourceMappingURL=_randomString.js.map"],"names":["_randomString_1","require$$0"],"mappings":";;;;AACA,MAAM,CAAC,cAAc,CAACA,eAAO,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC7D,IAAA,eAAA,GAAAA,eAAA,CAAA,aAAqB,GAAG;AACxB,MAAM,gBAAgB,GAAGC,cAA2B;AACpD,MAAM,kBAAkB,GAAG,CAAC;AAC5B,MAAM,aAAa,GAAG,CAAC;AACvB,MAAM,aAAa,GAAG,CAAC,KAAK,KAAK;AACjC,IAAI,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE;AAClB,IAAI,MAAM,OAAO,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,SAAS,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,SAAS,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,kBAAkB,EAAE,kBAAkB,CAAC;AACpL,IAAI,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,cAAc,EAAE;AACxD,QAAQ,IAAI,EAAE,SAAS;AACvB,QAAQ,OAAO;AACf,QAAQ,OAAO,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC,SAAS,MAAM,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,EAAE,GAAG,OAAO,GAAG,aAAa;AAChG,KAAK,CAAC;AACN,IAAI,OAAO,IAAI,KAAK,CAAC,MAAM;AAC3B,SAAS,IAAI,CAAC,CAAC;AACf,SAAS,GAAG,CAAC,MAAM,SAAS,CAAC,MAAM,EAAE,CAAC;AACtC,SAAS,IAAI,CAAC,EAAE,CAAC;AACjB,CAAC;AACD,eAAA,GAAAD,eAAA,CAAA,aAAqB,GAAG,aAAa;AACrC,MAAM,SAAS,GAAG,4BAA4B;AAC9C,MAAM,MAAM,GAAG,MAAM,IAAI,gBAAgB,CAAC,cAAc,EAAE;AAC1D,IAAI,IAAI,EAAE,SAAS;AACnB,IAAI,OAAO,EAAE,CAAC;AACd,IAAI,OAAO,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC;AACjC,CAAC,CAAC;;;;"}
@@ -1,2 +1,3 @@
1
1
  import type { ITtscPlugin, ITtscPluginFactoryContext } from "ttsc";
2
- export default function createTtscPlugin(context: ITtscPluginFactoryContext): ITtscPlugin;
2
+ export declare function createTtscPlugin(context: ITtscPluginFactoryContext): ITtscPlugin;
3
+ export default createTtscPlugin;
package/lib/transform.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.default = createTtscPlugin;
6
+ exports.createTtscPlugin = createTtscPlugin;
7
7
  const node_module_1 = require("node:module");
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  function createTtscPlugin(context) {
@@ -17,4 +17,5 @@ function createTtscPlugin(context) {
17
17
  source: node_path_1.default.resolve(root, "native", "cmd", "ttsc-typia"),
18
18
  };
19
19
  }
20
+ exports.default = createTtscPlugin;
20
21
  //# sourceMappingURL=transform.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transform.js","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":";;;;;;AAAA,6CAA4C;AAC5C,0DAA6B;AAG7B,0BACE,OAAkC;IAElC,oEAAoE;IACpE,wEAAwE;IACxE,2EAA2E;IAC3E,MAAM,WAAW,GAAG,IAAA,2BAAa,EAC/B,mBAAI,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAC/C,CAAC;IACF,MAAM,IAAI,GAAW,mBAAI,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC7E,OAAO;QACL,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,mBAAI,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,CAAC;KAC1D,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"transform.js","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":";;;;;;AAAA,6CAA4C;AAC5C,0DAA6B;AAG7B,0BACE,OAAkC;IAElC,oEAAoE;IACpE,wEAAwE;IACxE,2EAA2E;IAC3E,MAAM,WAAW,GAAG,IAAA,2BAAa,EAC/B,mBAAI,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAC/C,CAAC;IACF,MAAM,IAAI,GAAW,mBAAI,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC7E,OAAO;QACL,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,mBAAI,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,CAAC;KAC1D,CAAC;AACJ,CAAC;kBAEc,gBAAgB"}
package/lib/transform.mjs CHANGED
@@ -1,2 +1,2 @@
1
- export { default } from './transform2.mjs';
1
+ export { createTtscPlugin, default } from './transform2.mjs';
2
2
  //# sourceMappingURL=transform.mjs.map
@@ -6,7 +6,7 @@ var __importDefault = (transform && transform.__importDefault) || function (mod)
6
6
  return (mod && mod.__esModule) ? mod : { "default": mod };
7
7
  };
8
8
  Object.defineProperty(transform, "__esModule", { value: true });
9
- var _default = transform.default = createTtscPlugin;
9
+ var createTtscPlugin_1 = transform.createTtscPlugin = createTtscPlugin;
10
10
  const node_module_1 = require$$3;
11
11
  const node_path_1 = __importDefault(require$$2);
12
12
  function createTtscPlugin(context) {
@@ -20,6 +20,7 @@ function createTtscPlugin(context) {
20
20
  source: node_path_1.default.resolve(root, "native", "cmd", "ttsc-typia"),
21
21
  };
22
22
  }
23
+ var _default = transform.default = createTtscPlugin;
23
24
 
24
- export { _default as default };
25
+ export { createTtscPlugin_1 as createTtscPlugin, _default as default };
25
26
  //# sourceMappingURL=transform2.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"transform2.mjs","sources":["transform.js"],"sourcesContent":["\"use strict\";\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.default = createTtscPlugin;\nconst node_module_1 = require(\"node:module\");\nconst node_path_1 = __importDefault(require(\"node:path\"));\nfunction createTtscPlugin(context) {\n // ttsc loads this descriptor as ESM, where the ambient `require` is\n // unavailable; anchor a CJS resolver on the consuming project to locate\n // typia's own package root (not the project root, which has no `native/`).\n const requireFrom = (0, node_module_1.createRequire)(node_path_1.default.join(context.projectRoot, \"package.json\"));\n const root = node_path_1.default.dirname(requireFrom.resolve(\"typia/package.json\"));\n return {\n name: \"typia\",\n source: node_path_1.default.resolve(root, \"native\", \"cmd\", \"ttsc-typia\"),\n };\n}\n//# sourceMappingURL=transform.js.map"],"names":["this","require$$0","require$$1"],"mappings":";;;;AACA,IAAI,eAAe,GAAG,CAACA,SAAI,IAAIA,SAAI,CAAC,eAAe,KAAK,UAAU,GAAG,EAAE;AACvE,IAAI,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE;AAC7D,CAAC;AACD,MAAM,CAAC,cAAc,CAAC,SAAO,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC7D,IAAA,QAAA,GAAA,SAAA,CAAA,OAAe,GAAG;AAClB,MAAM,aAAa,GAAGC,UAAsB;AAC5C,MAAM,WAAW,GAAG,eAAe,CAACC,UAAoB,CAAC;AACzD,SAAS,gBAAgB,CAAC,OAAO,EAAE;AACnC;AACA;AACA;AACA,IAAI,MAAM,WAAW,GAAG,IAAI,aAAa,CAAC,aAAa,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;AACvH,IAAI,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;AACvF,IAAI,OAAO;AACX,QAAQ,IAAI,EAAE,OAAO;AACrB,QAAQ,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,CAAC;AAChF,KAAK;AACL;;;;"}
1
+ {"version":3,"file":"transform2.mjs","sources":["transform.js"],"sourcesContent":["\"use strict\";\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.createTtscPlugin = createTtscPlugin;\nconst node_module_1 = require(\"node:module\");\nconst node_path_1 = __importDefault(require(\"node:path\"));\nfunction createTtscPlugin(context) {\n // ttsc loads this descriptor as ESM, where the ambient `require` is\n // unavailable; anchor a CJS resolver on the consuming project to locate\n // typia's own package root (not the project root, which has no `native/`).\n const requireFrom = (0, node_module_1.createRequire)(node_path_1.default.join(context.projectRoot, \"package.json\"));\n const root = node_path_1.default.dirname(requireFrom.resolve(\"typia/package.json\"));\n return {\n name: \"typia\",\n source: node_path_1.default.resolve(root, \"native\", \"cmd\", \"ttsc-typia\"),\n };\n}\nexports.default = createTtscPlugin;\n//# sourceMappingURL=transform.js.map"],"names":["this","require$$0","require$$1"],"mappings":";;;;AACA,IAAI,eAAe,GAAG,CAACA,SAAI,IAAIA,SAAI,CAAC,eAAe,KAAK,UAAU,GAAG,EAAE;AACvE,IAAI,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE;AAC7D,CAAC;AACD,MAAM,CAAC,cAAc,CAAC,SAAO,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC7D,IAAA,kBAAA,GAAA,SAAA,CAAA,gBAAwB,GAAG;AAC3B,MAAM,aAAa,GAAGC,UAAsB;AAC5C,MAAM,WAAW,GAAG,eAAe,CAACC,UAAoB,CAAC;AACzD,SAAS,gBAAgB,CAAC,OAAO,EAAE;AACnC;AACA;AACA;AACA,IAAI,MAAM,WAAW,GAAG,IAAI,aAAa,CAAC,aAAa,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;AACvH,IAAI,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;AACvF,IAAI,OAAO;AACX,QAAQ,IAAI,EAAE,OAAO;AACrB,QAAQ,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,CAAC;AAChF,KAAK;AACL;AACA,IAAA,QAAA,GAAA,SAAA,CAAA,OAAe,GAAG;;;;"}
@@ -0,0 +1,234 @@
1
+ package main
2
+
3
+ import (
4
+ "os"
5
+ "path/filepath"
6
+ "strings"
7
+ "testing"
8
+ )
9
+
10
+ // TestRandomRecursiveMinItemsDiagnostic verifies impossible recursive arrays fail.
11
+ //
12
+ // A recursive random array can be depth-stopped to `[]`; combining that edge
13
+ // with a positive `MinItems` constraint is unsatisfiable. The build command must
14
+ // report a real transform diagnostic across direct aliases, type aliases, graph
15
+ // cycles, map-key and map-value graph cycles, nested direct aliases, and
16
+ // tuple-union nesting for both immediate and factory random entrypoints.
17
+ //
18
+ // 1. Build a recursive object whose child array has `MinItems<1>`.
19
+ // 2. Build a direct recursive array alias with `MinItems<1>`.
20
+ // 3. Build alias-property, graph, map-key graph, and nested direct alias variants.
21
+ // 4. Require each project to fail through the transform-diagnostic path.
22
+ func TestRandomRecursiveMinItemsDiagnostic(t *testing.T) {
23
+ for _, tt := range []struct {
24
+ name string
25
+ source string
26
+ }{
27
+ {"object-child", randomRecursiveMinItemsObjectSource},
28
+ {"property-alias", randomRecursiveMinItemsPropertyAliasSource},
29
+ {"mutual-graph", randomRecursiveMinItemsGraphSource},
30
+ {"map-key-graph", randomRecursiveMinItemsMapKeyGraphSource},
31
+ {"map-value-graph", randomRecursiveMinItemsMapValueGraphSource},
32
+ {"direct-alias", randomRecursiveMinItemsAliasSource},
33
+ {"direct-map-alias", randomRecursiveMinItemsMapAliasSource},
34
+ {"direct-map-value-alias", randomRecursiveMinItemsMapValueAliasSource},
35
+ {"direct-matrix-alias", randomRecursiveMinItemsMatrixAliasSource},
36
+ {"tuple-owner", randomRecursiveMinItemsTupleOwnerSource},
37
+ {"tuple-union", randomRecursiveMinItemsTupleUnionSource},
38
+ } {
39
+ randomRecursiveMinItemsExpectDiagnostic(t, tt.name, tt.source)
40
+ }
41
+ }
42
+
43
+ func randomRecursiveMinItemsExpectDiagnostic(t *testing.T, name string, source string) {
44
+ t.Helper()
45
+ project := randomRecursiveMinItemsProject(t, name, source)
46
+ _, errText, code := ttscTypiaTestCapture(func() int {
47
+ return runBuild([]string{
48
+ "--cwd", project,
49
+ "--tsconfig", "tsconfig.json",
50
+ "--emit",
51
+ "--outDir", filepath.Join(project, "dist"),
52
+ })
53
+ })
54
+ if code != 3 {
55
+ t.Fatalf("%s recursive MinItems build should fail with code 3, got %d\nstderr=%s", name, code, errText)
56
+ }
57
+ normalized := filepath.ToSlash(errText)
58
+ for _, fragment := range []string{
59
+ "error TS(typia.random):",
60
+ "error TS(typia.createRandom):",
61
+ "recursive array type cannot have MinItems<1>.",
62
+ } {
63
+ if !strings.Contains(normalized, fragment) {
64
+ t.Fatalf("%s recursive MinItems diagnostic missing %q:\n%s", name, fragment, errText)
65
+ }
66
+ }
67
+ }
68
+
69
+ func randomRecursiveMinItemsProject(t *testing.T, name string, source string) string {
70
+ t.Helper()
71
+ root := ttscTypiaTestRepoRoot(t)
72
+ base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
73
+ if err := os.MkdirAll(base, 0o755); err != nil {
74
+ t.Fatalf("mkdir temp base: %v", err)
75
+ }
76
+ dir, err := os.MkdirTemp(base, "random-recursive-min-items-"+name+"-")
77
+ if err != nil {
78
+ t.Fatalf("create temp fixture: %v", err)
79
+ }
80
+ t.Cleanup(func() {
81
+ _ = os.RemoveAll(dir)
82
+ })
83
+ src := filepath.Join(dir, "src")
84
+ if err := os.MkdirAll(src, 0o755); err != nil {
85
+ t.Fatalf("mkdir fixture src: %v", err)
86
+ }
87
+ if err := os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(randomRecursiveMinItemsTSConfig), 0o644); err != nil {
88
+ t.Fatalf("write tsconfig: %v", err)
89
+ }
90
+ if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(source), 0o644); err != nil {
91
+ t.Fatalf("write source: %v", err)
92
+ }
93
+ return dir
94
+ }
95
+
96
+ const randomRecursiveMinItemsTSConfig = `{
97
+ "compilerOptions": {
98
+ "target": "ES2022",
99
+ "module": "commonjs",
100
+ "moduleResolution": "bundler",
101
+ "ignoreDeprecations": "6.0",
102
+ "types": ["*"],
103
+ "esModuleInterop": true,
104
+ "strict": true,
105
+ "skipLibCheck": true,
106
+ "rootDir": "src",
107
+ "outDir": "dist"
108
+ },
109
+ "include": ["src"]
110
+ }
111
+ `
112
+
113
+ const randomRecursiveMinItemsObjectSource = `import typia, { tags } from "typia";
114
+
115
+ interface INode {
116
+ value: string;
117
+ children: INode[] & tags.MinItems<1>;
118
+ }
119
+
120
+ typia.random<INode>();
121
+ typia.createRandom<INode>();
122
+ `
123
+
124
+ const randomRecursiveMinItemsPropertyAliasSource = `import typia, { tags } from "typia";
125
+
126
+ type Children = INode[] & tags.MinItems<1>;
127
+
128
+ interface INode {
129
+ value: string;
130
+ children: Children;
131
+ }
132
+
133
+ typia.random<INode>();
134
+ typia.createRandom<INode>();
135
+ `
136
+
137
+ const randomRecursiveMinItemsGraphSource = `import typia, { tags } from "typia";
138
+
139
+ interface IParent {
140
+ name: string;
141
+ children: IChild[] & tags.MinItems<1>;
142
+ }
143
+
144
+ interface IChild {
145
+ name: string;
146
+ parent: IParent;
147
+ }
148
+
149
+ typia.random<IParent>();
150
+ typia.createRandom<IParent>();
151
+ `
152
+
153
+ const randomRecursiveMinItemsMapKeyGraphSource = `import typia, { tags } from "typia";
154
+
155
+ interface IParent {
156
+ name: string;
157
+ children: IChild[] & tags.MinItems<1>;
158
+ }
159
+
160
+ interface IChild {
161
+ name: string;
162
+ links: Map<IParent, string>;
163
+ }
164
+
165
+ typia.random<IParent>();
166
+ typia.createRandom<IParent>();
167
+ `
168
+
169
+ const randomRecursiveMinItemsMapValueGraphSource = `import typia, { tags } from "typia";
170
+
171
+ interface IParent {
172
+ name: string;
173
+ children: IChild[] & tags.MinItems<1>;
174
+ }
175
+
176
+ interface IChild {
177
+ name: string;
178
+ links: Map<string, IParent>;
179
+ }
180
+
181
+ typia.random<IParent>();
182
+ typia.createRandom<IParent>();
183
+ `
184
+
185
+ const randomRecursiveMinItemsAliasSource = `import typia, { tags } from "typia";
186
+
187
+ type IRecursiveArray = IRecursiveArray[] & tags.MinItems<1>;
188
+
189
+ typia.random<IRecursiveArray>();
190
+ typia.createRandom<IRecursiveArray>();
191
+ `
192
+
193
+ const randomRecursiveMinItemsMapAliasSource = `import typia, { tags } from "typia";
194
+
195
+ type IRecursiveMapArray = Map<IRecursiveMapArray, string>[] & tags.MinItems<1>;
196
+
197
+ typia.random<IRecursiveMapArray>();
198
+ typia.createRandom<IRecursiveMapArray>();
199
+ `
200
+
201
+ const randomRecursiveMinItemsMapValueAliasSource = `import typia, { tags } from "typia";
202
+
203
+ type IRecursiveMapValueArray = Map<string, IRecursiveMapValueArray>[] & tags.MinItems<1>;
204
+
205
+ typia.random<IRecursiveMapValueArray>();
206
+ typia.createRandom<IRecursiveMapValueArray>();
207
+ `
208
+
209
+ const randomRecursiveMinItemsMatrixAliasSource = `import typia, { tags } from "typia";
210
+
211
+ type IRecursiveMatrix = IRecursiveMatrix[][] & tags.MinItems<1>;
212
+
213
+ typia.random<IRecursiveMatrix>();
214
+ typia.createRandom<IRecursiveMatrix>();
215
+ `
216
+
217
+ const randomRecursiveMinItemsTupleOwnerSource = `import typia, { tags } from "typia";
218
+
219
+ type IRecursiveTuple = [IRecursiveTuple[] & tags.MinItems<1>];
220
+
221
+ typia.random<IRecursiveTuple>();
222
+ typia.createRandom<IRecursiveTuple>();
223
+ `
224
+
225
+ const randomRecursiveMinItemsTupleUnionSource = `import typia, { tags } from "typia";
226
+
227
+ interface INode {
228
+ value: string;
229
+ nested: [INode[] & tags.MinItems<1>] | null;
230
+ }
231
+
232
+ typia.random<INode>();
233
+ typia.createRandom<INode>();
234
+ `
@@ -0,0 +1,146 @@
1
+ package main
2
+
3
+ import (
4
+ "os"
5
+ "path/filepath"
6
+ "strings"
7
+ "testing"
8
+ )
9
+
10
+ // TestRandomUnsatisfiableRecursiveDiagnostic verifies non-terminating recursive
11
+ // types fail.
12
+ //
13
+ // Random generation terminates a recursive type through an escape it can take at
14
+ // the depth cutoff: an array/set/map (or a tuple rest spread) empties, a nullable
15
+ // edge becomes null, an optional or index-signature property is dropped, or a
16
+ // union picks a finite variant. A recursive cycle whose every step is a required,
17
+ // non-nullable, non-container value has no such escape, so the generated function
18
+ // would recurse until the stack overflows. The build must reject it through the
19
+ // transform diagnostic path across object, mutual-object, deep-chain, and
20
+ // array-of-owner shapes, for both immediate and factory random entrypoints.
21
+ //
22
+ // 1. Build a self-referential required object and a mutual object cycle.
23
+ // 2. Build a deep required object chain.
24
+ // 3. Build an array whose element is an unsatisfiable recursive object.
25
+ // 4. Require each project to fail through the transform-diagnostic path.
26
+ func TestRandomUnsatisfiableRecursiveDiagnostic(t *testing.T) {
27
+ for _, tt := range []struct {
28
+ name string
29
+ source string
30
+ }{
31
+ {"required-self", randomUnsatisfiableSelfSource},
32
+ {"mutual-object", randomUnsatisfiableMutualSource},
33
+ {"deep-chain", randomUnsatisfiableDeepChainSource},
34
+ {"array-of-owner", randomUnsatisfiableArrayOfOwnerSource},
35
+ } {
36
+ randomUnsatisfiableExpectDiagnostic(t, tt.name, tt.source)
37
+ }
38
+ }
39
+
40
+ func randomUnsatisfiableExpectDiagnostic(t *testing.T, name string, source string) {
41
+ t.Helper()
42
+ project := randomUnsatisfiableProject(t, name, source)
43
+ _, errText, code := ttscTypiaTestCapture(func() int {
44
+ return runBuild([]string{
45
+ "--cwd", project,
46
+ "--tsconfig", "tsconfig.json",
47
+ "--emit",
48
+ "--outDir", filepath.Join(project, "dist"),
49
+ })
50
+ })
51
+ if code != 3 {
52
+ t.Fatalf("%s unsatisfiable recursive build should fail with code 3, got %d\nstderr=%s", name, code, errText)
53
+ }
54
+ normalized := filepath.ToSlash(errText)
55
+ for _, fragment := range []string{
56
+ "error TS(typia.random):",
57
+ "error TS(typia.createRandom):",
58
+ "cannot be randomly generated because the recursion never terminates",
59
+ } {
60
+ if !strings.Contains(normalized, fragment) {
61
+ t.Fatalf("%s unsatisfiable recursive diagnostic missing %q:\n%s", name, fragment, errText)
62
+ }
63
+ }
64
+ }
65
+
66
+ func randomUnsatisfiableProject(t *testing.T, name string, source string) string {
67
+ t.Helper()
68
+ root := ttscTypiaTestRepoRoot(t)
69
+ base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
70
+ if err := os.MkdirAll(base, 0o755); err != nil {
71
+ t.Fatalf("mkdir temp base: %v", err)
72
+ }
73
+ dir, err := os.MkdirTemp(base, "random-unsatisfiable-recursive-"+name+"-")
74
+ if err != nil {
75
+ t.Fatalf("create temp fixture: %v", err)
76
+ }
77
+ t.Cleanup(func() {
78
+ _ = os.RemoveAll(dir)
79
+ })
80
+ src := filepath.Join(dir, "src")
81
+ if err := os.MkdirAll(src, 0o755); err != nil {
82
+ t.Fatalf("mkdir fixture src: %v", err)
83
+ }
84
+ if err := os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(randomRecursiveMinItemsTSConfig), 0o644); err != nil {
85
+ t.Fatalf("write tsconfig: %v", err)
86
+ }
87
+ if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(source), 0o644); err != nil {
88
+ t.Fatalf("write source: %v", err)
89
+ }
90
+ return dir
91
+ }
92
+
93
+ const randomUnsatisfiableSelfSource = `import typia from "typia";
94
+
95
+ interface INode {
96
+ value: string;
97
+ self: INode;
98
+ }
99
+
100
+ typia.random<INode>();
101
+ typia.createRandom<INode>();
102
+ `
103
+
104
+ const randomUnsatisfiableMutualSource = `import typia from "typia";
105
+
106
+ interface IParent {
107
+ name: string;
108
+ child: IChild;
109
+ }
110
+
111
+ interface IChild {
112
+ parent: IParent;
113
+ }
114
+
115
+ typia.random<IParent>();
116
+ typia.createRandom<IParent>();
117
+ `
118
+
119
+ const randomUnsatisfiableDeepChainSource = `import typia from "typia";
120
+
121
+ interface IA {
122
+ b: IB;
123
+ }
124
+
125
+ interface IB {
126
+ c: IC;
127
+ }
128
+
129
+ interface IC {
130
+ a: IA;
131
+ }
132
+
133
+ typia.random<IA>();
134
+ typia.createRandom<IA>();
135
+ `
136
+
137
+ const randomUnsatisfiableArrayOfOwnerSource = `import typia from "typia";
138
+
139
+ interface INode {
140
+ value: string;
141
+ self: INode;
142
+ }
143
+
144
+ typia.random<INode[]>();
145
+ typia.createRandom<INode[]>();
146
+ `
@@ -245,6 +245,53 @@ func metadata_node_description(symbol *nativeast.Symbol) *string {
245
245
  return nil
246
246
  }
247
247
 
248
+ // metadata_node_type_description / metadata_node_type_js_doc_tags read the JSDoc
249
+ // of a TYPE-level symbol (an interface, class, or `type` alias), skipping symbols
250
+ // declared in a TypeScript default library file. Standard-library type aliases
251
+ // carry their own JSDoc (e.g. `NonNullable`'s "Exclude null and undefined from
252
+ // T", `Record`'s "Construct a type ...") and, since the type-name symbol of an
253
+ // instantiation such as `NonNullable<...>` resolves to that library declaration,
254
+ // an unfiltered read would leak the library comment into the user's schema. A
255
+ // property's own comment is unaffected — it is read from the property symbol,
256
+ // which is declared in user code.
257
+ func metadata_node_type_description(symbol *nativeast.Symbol) *string {
258
+ if metadata_symbol_from_default_lib(symbol) {
259
+ return nil
260
+ }
261
+ return metadata_node_description(symbol)
262
+ }
263
+
264
+ func metadata_node_type_js_doc_tags(symbol *nativeast.Symbol) []schemametadata.IJsDocTagInfo {
265
+ if metadata_symbol_from_default_lib(symbol) {
266
+ return []schemametadata.IJsDocTagInfo{}
267
+ }
268
+ return metadata_node_js_doc_tags(symbol)
269
+ }
270
+
271
+ // metadata_symbol_from_default_lib reports whether the symbol's first locatable
272
+ // declaration lives in a TypeScript default library file. Default library files
273
+ // are always named `lib.<target>.d.ts` regardless of the install directory, so
274
+ // the base name alone is a stable signal.
275
+ func metadata_symbol_from_default_lib(symbol *nativeast.Symbol) bool {
276
+ for _, node := range metadata_node_declarations(symbol) {
277
+ src := nativeast.GetSourceFileOfNode(node)
278
+ if src == nil {
279
+ continue
280
+ }
281
+ return metadata_is_default_lib_file_name(src.FileName())
282
+ }
283
+ return false
284
+ }
285
+
286
+ func metadata_is_default_lib_file_name(fileName string) bool {
287
+ slash := strings.ReplaceAll(fileName, "\\", "/")
288
+ base := slash
289
+ if idx := strings.LastIndex(slash, "/"); idx >= 0 {
290
+ base = slash[idx+1:]
291
+ }
292
+ return strings.HasPrefix(base, "lib.") && strings.HasSuffix(base, ".d.ts")
293
+ }
294
+
248
295
  func metadata_is_internal(symbol *nativeast.Symbol) bool {
249
296
  for _, tag := range metadata_node_js_doc_tags(symbol) {
250
297
  if tag.Name == "internal" {
@@ -17,6 +17,13 @@ func Emplace_metadata_alias(props IMetadataIteratorProps) *schemametadata.Metada
17
17
  return alias
18
18
  }
19
19
 
20
+ // The MetadataCollection layer stubs description / tags (the AST JSDoc helpers
21
+ // live in this factory package), so fill them here from the alias symbol. The
22
+ // type-level readers skip default-library declarations, so a standard-library
23
+ // alias such as `NonNullable<...>` does not leak its own JSDoc.
24
+ alias.Description = metadata_node_type_description(symbol)
25
+ alias.JsDocTags = metadata_node_type_js_doc_tags(symbol)
26
+
20
27
  explore := props.Explore
21
28
  explore.Escaped = false
22
29
  explore.Aliased = true