@runtime-type-inspector/transpiler 3.3.7 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.cjs +193 -12
  2. package/index.mjs +185 -13
  3. package/package.json +2 -2
package/index.cjs CHANGED
@@ -1263,6 +1263,10 @@
1263
1263
  _defineProperty(this, "forceCurly", false);
1264
1264
  /** @type {Node[]} */
1265
1265
  _defineProperty(this, "parents", []);
1266
+ /**
1267
+ * If we encounter JSX elements, we add React's createElement as import.
1268
+ */
1269
+ _defineProperty(this, "addReactImport", false);
1266
1270
  _defineProperty(this, "lastCommentBlockIndex", -1);
1267
1271
  _defineProperty(this, "lastCommentLineIndex", -1);
1268
1272
  _defineProperty(this, "numSpaces", 0);
@@ -1519,6 +1523,17 @@
1519
1523
  }
1520
1524
  return out;
1521
1525
  }
1526
+ /**
1527
+ * @returns {string} The header.
1528
+ */
1529
+ }, {
1530
+ key: "getHeader",
1531
+ value: function getHeader() {
1532
+ if (!this.addReactImport) {
1533
+ return '';
1534
+ }
1535
+ return "import {createElement} from 'react';\n";
1536
+ }
1522
1537
  }, {
1523
1538
  key: "parent",
1524
1539
  get: function get() {
@@ -1901,7 +1916,10 @@
1901
1916
  out += ' * ';
1902
1917
  }
1903
1918
  out += this.FunctionDeclarationParams(params);
1904
- out += ' => ';
1919
+ out += ' =>';
1920
+ if (body.type !== 'BlockStatement') {
1921
+ out += ' ';
1922
+ }
1905
1923
  out += this.toSource(body);
1906
1924
  return out;
1907
1925
  }
@@ -2535,6 +2553,154 @@
2535
2553
  // createMesh: createMesh$1\n
2536
2554
  return "".concat(spaces).concat(right, " as ").concat(left);
2537
2555
  }
2556
+ /**
2557
+ * @param {import("@babel/types").JSXAttribute} node - The Babel AST node.
2558
+ * @returns {string} Stringification of the node.
2559
+ */
2560
+ }, {
2561
+ key: "JSXAttribute",
2562
+ value: function JSXAttribute(node) {
2563
+ var name = node.name,
2564
+ value = node.value;
2565
+ // console.log("JSXAttribute", {name, value});
2566
+ var keySource = this.toSource(name);
2567
+ // E.g. <audio controls/>
2568
+ if (value === null) {
2569
+ return "".concat(this.spaces).concat(keySource, ": true");
2570
+ }
2571
+ var valSource = this.toSource(value);
2572
+ if (keySource === valSource) {
2573
+ return this.spaces + keySource;
2574
+ }
2575
+ return "".concat(this.spaces).concat(keySource, ": ").concat(valSource);
2576
+ }
2577
+ /**
2578
+ * @param {import("@babel/types").JSXElement} node - The Babel AST node.
2579
+ * @returns {string} Stringification of the node.
2580
+ */
2581
+ }, {
2582
+ key: "JSXElement",
2583
+ value: function JSXElement(node) {
2584
+ var _this4 = this;
2585
+ this.addReactImport = true;
2586
+ var openingElement = node.openingElement;
2587
+ node.closingElement;
2588
+ var children = node.children;
2589
+ // console.log("JSXElement", {openingElement, closingElement, children});
2590
+ if (openingElement.type !== 'JSXOpeningElement') {
2591
+ debugger;
2592
+ }
2593
+ var spaces = this.spaces;
2594
+ var name = openingElement.name,
2595
+ attributes = openingElement.attributes;
2596
+ var out = '';
2597
+ out += 'createElement(';
2598
+ this.numSpaces++;
2599
+ spaces = this.spaces;
2600
+ out += '\n';
2601
+ out += spaces;
2602
+ var sourceName = this.toSource(name);
2603
+ if (sourceName[0] === sourceName[0].toLowerCase()) {
2604
+ // If something like 'div', it has to become "'div'"
2605
+ sourceName = JSON.stringify(sourceName);
2606
+ }
2607
+ out += sourceName;
2608
+ out += ',';
2609
+ if (attributes.length) {
2610
+ out += '\n';
2611
+ out += spaces;
2612
+ out += '{\n';
2613
+ this.numSpaces++;
2614
+ out += attributes.map(function (attr) {
2615
+ return _this4.toSource(attr) + ',\n';
2616
+ }).join('');
2617
+ this.numSpaces--;
2618
+ out += spaces;
2619
+ out += '}';
2620
+ } else {
2621
+ out += '\n';
2622
+ out += spaces;
2623
+ out += 'null';
2624
+ }
2625
+ if (children.length) {
2626
+ out += ',\n';
2627
+ var _iterator2 = _createForOfIteratorHelper(children),
2628
+ _step2;
2629
+ try {
2630
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
2631
+ var child = _step2.value;
2632
+ var source = this.toSource(child);
2633
+ if (!source.length) {
2634
+ continue;
2635
+ }
2636
+ out += spaces;
2637
+ out += source;
2638
+ out += ',\n';
2639
+ }
2640
+ } catch (err) {
2641
+ _iterator2.e(err);
2642
+ } finally {
2643
+ _iterator2.f();
2644
+ }
2645
+ } else {
2646
+ out += '\n';
2647
+ }
2648
+ this.numSpaces--;
2649
+ out += this.spaces;
2650
+ out += ')';
2651
+ return out;
2652
+ }
2653
+ /**
2654
+ * @param {import("@babel/types").JSXIdentifier} node - The Babel AST node.
2655
+ * @returns {string} Stringification of the node.
2656
+ */
2657
+ }, {
2658
+ key: "JSXIdentifier",
2659
+ value: function JSXIdentifier(node) {
2660
+ var name = node.name;
2661
+ // console.log('JSXIdentifier', {name});
2662
+ return name;
2663
+ }
2664
+ /**
2665
+ * @param {import("@babel/types").JSXExpressionContainer} node - The Babel AST node.
2666
+ * @returns {string} Stringification of the node.
2667
+ */
2668
+ }, {
2669
+ key: "JSXExpressionContainer",
2670
+ value: function JSXExpressionContainer(node) {
2671
+ var expression = node.expression;
2672
+ // console.log('JSXExpressionContainer', {expression});
2673
+ return this.toSource(expression);
2674
+ }
2675
+ /**
2676
+ * @param {import("@babel/types").JSXMemberExpression} node - The Babel AST node.
2677
+ * @returns {string} Stringification of the node.
2678
+ */
2679
+ }, {
2680
+ key: "JSXMemberExpression",
2681
+ value: function JSXMemberExpression(node) {
2682
+ var object = node.object,
2683
+ property = node.property;
2684
+ // console.log('JSXMemberExpression', 'object', object, 'property', property);
2685
+ var o = this.toSource(object);
2686
+ var p = this.toSource(property);
2687
+ return "".concat(o, ".").concat(p);
2688
+ }
2689
+ /**
2690
+ * @param {import("@babel/types").JSXText} node - The Babel AST node.
2691
+ * @returns {string} Stringification of the node.
2692
+ */
2693
+ }, {
2694
+ key: "JSXText",
2695
+ value: function JSXText(node) {
2696
+ node.extra;
2697
+ var value = node.value;
2698
+ // console.log('JSXText', {extra, value});
2699
+ if (!value.trim().length) {
2700
+ return '';
2701
+ }
2702
+ return JSON.stringify(value);
2703
+ }
2538
2704
  /**
2539
2705
  * @param {import("@babel/types").Super} node - The Babel AST node.
2540
2706
  * @returns {string} Stringification of the node.
@@ -3216,7 +3382,11 @@
3216
3382
  } else {
3217
3383
  out += ' {\n';
3218
3384
  out += this.generateTypeChecks(node);
3385
+ var spaces = this.spaces;
3386
+ this.numSpaces++;
3219
3387
  out += this.spaces + 'return ' + this.toSource(body) + ';\n';
3388
+ this.numSpaces--;
3389
+ out += spaces;
3220
3390
  out += '}';
3221
3391
  }
3222
3392
  return out;
@@ -3262,6 +3432,7 @@
3262
3432
  * @todo
3263
3433
  * Once we went over every node, we can see if we really require registerTypef, registerClass etc.
3264
3434
  * @returns {string} The import declaration header for importing RTI.
3435
+ * @override
3265
3436
  */
3266
3437
  }, {
3267
3438
  key: "getHeader",
@@ -3269,7 +3440,8 @@
3269
3440
  if (!this.addHeader) {
3270
3441
  return '';
3271
3442
  }
3272
- var header = "import {inspectType, inspectTypeWithTemplates, youCanAddABreakpointHere, registerVariable";
3443
+ var header = _get(_getPrototypeOf(Asserter.prototype), "getHeader", this).call(this);
3444
+ header += "import {inspectType, inspectTypeWithTemplates, youCanAddABreakpointHere, registerVariable";
3273
3445
  if (this.validateDivision) {
3274
3446
  header += ", validateDivision";
3275
3447
  }
@@ -4001,6 +4173,17 @@
4001
4173
  return Asserter;
4002
4174
  }(Stringifier);
4003
4175
 
4176
+ /**
4177
+ * We use the same options in different places, so it's nice to keep them in sync without
4178
+ * changing them in multiple locations.
4179
+ * @type {import('@babel/parser').ParserOptions}
4180
+ */
4181
+ var parserOptions = {
4182
+ sourceType: 'module',
4183
+ createParenthesizedExpressions: true,
4184
+ plugins: ['jsx']
4185
+ };
4186
+
4004
4187
  /**
4005
4188
  * Simple facade which does all the processing. Processes the input
4006
4189
  * source string, adding runtime type checks based on JSDoc comments.
@@ -4020,11 +4203,10 @@
4020
4203
  function addTypeChecks(src, options) {
4021
4204
  try {
4022
4205
  var asserter = new Asserter(options);
4023
- var ast = parser.parse(src, {
4024
- sourceType: 'module',
4025
- createParenthesizedExpressions: true
4026
- });
4027
- var out = asserter.getHeader() + asserter.toSource(ast);
4206
+ var ast = parser.parse(src, parserOptions);
4207
+ // Must be called before getHeader since it's keeping an eye open for JSX elements.
4208
+ var source = asserter.toSource(ast);
4209
+ var out = asserter.getHeader() + source;
4028
4210
  return out;
4029
4211
  } catch (e) {
4030
4212
  console.error(e);
@@ -4072,15 +4254,13 @@
4072
4254
  * @returns {string | undefined} The new and once parsed and stringified code.
4073
4255
  */
4074
4256
  function code2ast2code(code) {
4075
- var stringifier = new Stringifier();
4076
- var ast = parser.parse(code, {
4077
- sourceType: 'module'
4078
- });
4257
+ var ast = parser.parse(code, parserOptions);
4079
4258
  if (!ast) {
4080
4259
  return;
4081
4260
  }
4261
+ var stringifier = new Stringifier();
4082
4262
  var out = stringifier.toSource(ast);
4083
- return out;
4263
+ return stringifier.getHeader() + out;
4084
4264
  }
4085
4265
 
4086
4266
  /**
@@ -4361,6 +4541,7 @@
4361
4541
  exports.parseJSDocTypedef = parseJSDocTypedef;
4362
4542
  exports.parseType = parseType;
4363
4543
  exports.parseTypeBabelTS = parseTypeBabelTS;
4544
+ exports.parserOptions = parserOptions;
4364
4545
  exports.requiredTypeofs = requiredTypeofs;
4365
4546
  exports.simplifyType = simplifyType;
4366
4547
  exports.toSourceBabelTS = toSourceBabelTS;
package/index.mjs CHANGED
@@ -1021,6 +1021,10 @@ class Stringifier {
1021
1021
  this.forceCurly = false;
1022
1022
  /** @type {Node[]} */
1023
1023
  this.parents = [];
1024
+ /**
1025
+ * If we encounter JSX elements, we add React's createElement as import.
1026
+ */
1027
+ this.addReactImport = false;
1024
1028
  this.lastCommentBlockIndex = -1;
1025
1029
  this.lastCommentLineIndex = -1;
1026
1030
  this.numSpaces = 0;
@@ -1258,6 +1262,15 @@ class Stringifier {
1258
1262
  }
1259
1263
  return out;
1260
1264
  }
1265
+ /**
1266
+ * @returns {string} The header.
1267
+ */
1268
+ getHeader() {
1269
+ if (!this.addReactImport) {
1270
+ return '';
1271
+ }
1272
+ return "import {createElement} from 'react';\n";
1273
+ }
1261
1274
  get parent() {
1262
1275
  return this.parents[this.parents.length - 2];
1263
1276
  }
@@ -1618,7 +1631,10 @@ class Stringifier {
1618
1631
  out += ' * ';
1619
1632
  }
1620
1633
  out += this.FunctionDeclarationParams(params);
1621
- out += ' => ';
1634
+ out += ' =>';
1635
+ if (body.type !== 'BlockStatement') {
1636
+ out += ' ';
1637
+ }
1622
1638
  out += this.toSource(body);
1623
1639
  return out;
1624
1640
  }
@@ -2249,6 +2265,146 @@ class Stringifier {
2249
2265
  // createMesh: createMesh$1\n
2250
2266
  return `${spaces}${right} as ${left}`;
2251
2267
  }
2268
+ /**
2269
+ * @param {import("@babel/types").JSXAttribute} node - The Babel AST node.
2270
+ * @returns {string} Stringification of the node.
2271
+ */
2272
+ JSXAttribute(node) {
2273
+ const {
2274
+ name,
2275
+ value
2276
+ } = node;
2277
+ // console.log("JSXAttribute", {name, value});
2278
+ const keySource = this.toSource(name);
2279
+ // E.g. <audio controls/>
2280
+ if (value === null) {
2281
+ return `${this.spaces}${keySource}: true`;
2282
+ }
2283
+ const valSource = this.toSource(value);
2284
+ if (keySource === valSource) {
2285
+ return this.spaces + keySource;
2286
+ }
2287
+ return `${this.spaces}${keySource}: ${valSource}`;
2288
+ }
2289
+ /**
2290
+ * @param {import("@babel/types").JSXElement} node - The Babel AST node.
2291
+ * @returns {string} Stringification of the node.
2292
+ */
2293
+ JSXElement(node) {
2294
+ this.addReactImport = true;
2295
+ const {
2296
+ openingElement,
2297
+ closingElement,
2298
+ children
2299
+ } = node;
2300
+ // console.log("JSXElement", {openingElement, closingElement, children});
2301
+ if (openingElement.type !== 'JSXOpeningElement') {
2302
+ debugger;
2303
+ }
2304
+ let {
2305
+ spaces
2306
+ } = this;
2307
+ const {
2308
+ name,
2309
+ attributes
2310
+ } = openingElement;
2311
+ let out = '';
2312
+ out += 'createElement(';
2313
+ this.numSpaces++;
2314
+ spaces = this.spaces;
2315
+ out += '\n';
2316
+ out += spaces;
2317
+ let sourceName = this.toSource(name);
2318
+ if (sourceName[0] === sourceName[0].toLowerCase()) {
2319
+ // If something like 'div', it has to become "'div'"
2320
+ sourceName = JSON.stringify(sourceName);
2321
+ }
2322
+ out += sourceName;
2323
+ out += ',';
2324
+ if (attributes.length) {
2325
+ out += '\n';
2326
+ out += spaces;
2327
+ out += '{\n';
2328
+ this.numSpaces++;
2329
+ out += attributes.map(attr => this.toSource(attr) + ',\n').join('');
2330
+ this.numSpaces--;
2331
+ out += spaces;
2332
+ out += '}';
2333
+ } else {
2334
+ out += '\n';
2335
+ out += spaces;
2336
+ out += 'null';
2337
+ }
2338
+ if (children.length) {
2339
+ out += ',\n';
2340
+ for (const child of children) {
2341
+ const source = this.toSource(child);
2342
+ if (!source.length) {
2343
+ continue;
2344
+ }
2345
+ out += spaces;
2346
+ out += source;
2347
+ out += ',\n';
2348
+ }
2349
+ } else {
2350
+ out += '\n';
2351
+ }
2352
+ this.numSpaces--;
2353
+ out += this.spaces;
2354
+ out += ')';
2355
+ return out;
2356
+ }
2357
+ /**
2358
+ * @param {import("@babel/types").JSXIdentifier} node - The Babel AST node.
2359
+ * @returns {string} Stringification of the node.
2360
+ */
2361
+ JSXIdentifier(node) {
2362
+ const {
2363
+ name
2364
+ } = node;
2365
+ // console.log('JSXIdentifier', {name});
2366
+ return name;
2367
+ }
2368
+ /**
2369
+ * @param {import("@babel/types").JSXExpressionContainer} node - The Babel AST node.
2370
+ * @returns {string} Stringification of the node.
2371
+ */
2372
+ JSXExpressionContainer(node) {
2373
+ const {
2374
+ expression
2375
+ } = node;
2376
+ // console.log('JSXExpressionContainer', {expression});
2377
+ return this.toSource(expression);
2378
+ }
2379
+ /**
2380
+ * @param {import("@babel/types").JSXMemberExpression} node - The Babel AST node.
2381
+ * @returns {string} Stringification of the node.
2382
+ */
2383
+ JSXMemberExpression(node) {
2384
+ const {
2385
+ object,
2386
+ property
2387
+ } = node;
2388
+ // console.log('JSXMemberExpression', 'object', object, 'property', property);
2389
+ const o = this.toSource(object);
2390
+ const p = this.toSource(property);
2391
+ return `${o}.${p}`;
2392
+ }
2393
+ /**
2394
+ * @param {import("@babel/types").JSXText} node - The Babel AST node.
2395
+ * @returns {string} Stringification of the node.
2396
+ */
2397
+ JSXText(node) {
2398
+ const {
2399
+ extra,
2400
+ value
2401
+ } = node;
2402
+ // console.log('JSXText', {extra, value});
2403
+ if (!value.trim().length) {
2404
+ return '';
2405
+ }
2406
+ return JSON.stringify(value);
2407
+ }
2252
2408
  /**
2253
2409
  * @param {import("@babel/types").Super} node - The Babel AST node.
2254
2410
  * @returns {string} Stringification of the node.
@@ -2917,7 +3073,13 @@ class Asserter extends Stringifier {
2917
3073
  } else {
2918
3074
  out += ' {\n';
2919
3075
  out += this.generateTypeChecks(node);
3076
+ const {
3077
+ spaces
3078
+ } = this;
3079
+ this.numSpaces++;
2920
3080
  out += this.spaces + 'return ' + this.toSource(body) + ';\n';
3081
+ this.numSpaces--;
3082
+ out += spaces;
2921
3083
  out += '}';
2922
3084
  }
2923
3085
  return out;
@@ -2959,12 +3121,14 @@ class Asserter extends Stringifier {
2959
3121
  * @todo
2960
3122
  * Once we went over every node, we can see if we really require registerTypef, registerClass etc.
2961
3123
  * @returns {string} The import declaration header for importing RTI.
3124
+ * @override
2962
3125
  */
2963
3126
  getHeader() {
2964
3127
  if (!this.addHeader) {
2965
3128
  return '';
2966
3129
  }
2967
- let header = "import {inspectType, inspectTypeWithTemplates, youCanAddABreakpointHere, registerVariable";
3130
+ let header = super.getHeader();
3131
+ header += "import {inspectType, inspectTypeWithTemplates, youCanAddABreakpointHere, registerVariable";
2968
3132
  if (this.validateDivision) {
2969
3133
  header += ", validateDivision";
2970
3134
  }
@@ -3631,6 +3795,17 @@ class Asserter extends Stringifier {
3631
3795
  }
3632
3796
  }
3633
3797
 
3798
+ /**
3799
+ * We use the same options in different places, so it's nice to keep them in sync without
3800
+ * changing them in multiple locations.
3801
+ * @type {import('@babel/parser').ParserOptions}
3802
+ */
3803
+ const parserOptions = {
3804
+ sourceType: 'module',
3805
+ createParenthesizedExpressions: true,
3806
+ plugins: ['jsx']
3807
+ };
3808
+
3634
3809
  /**
3635
3810
  * Simple facade which does all the processing. Processes the input
3636
3811
  * source string, adding runtime type checks based on JSDoc comments.
@@ -3650,11 +3825,10 @@ class Asserter extends Stringifier {
3650
3825
  function addTypeChecks(src, options) {
3651
3826
  try {
3652
3827
  const asserter = new Asserter(options);
3653
- const ast = parse(src, {
3654
- sourceType: 'module',
3655
- createParenthesizedExpressions: true
3656
- });
3657
- const out = asserter.getHeader() + asserter.toSource(ast);
3828
+ const ast = parse(src, parserOptions);
3829
+ // Must be called before getHeader since it's keeping an eye open for JSX elements.
3830
+ const source = asserter.toSource(ast);
3831
+ const out = asserter.getHeader() + source;
3658
3832
  return out;
3659
3833
  } catch (e) {
3660
3834
  console.error(e);
@@ -3702,15 +3876,13 @@ function ast2jsonForComparison(ast) {
3702
3876
  * @returns {string | undefined} The new and once parsed and stringified code.
3703
3877
  */
3704
3878
  function code2ast2code(code) {
3705
- const stringifier = new Stringifier();
3706
- const ast = parse(code, {
3707
- sourceType: 'module'
3708
- });
3879
+ const ast = parse(code, parserOptions);
3709
3880
  if (!ast) {
3710
3881
  return;
3711
3882
  }
3883
+ const stringifier = new Stringifier();
3712
3884
  const out = stringifier.toSource(ast);
3713
- return out;
3885
+ return stringifier.getHeader() + out;
3714
3886
  }
3715
3887
 
3716
3888
  /**
@@ -3972,4 +4144,4 @@ function toSourceBabelTS(node) {
3972
4144
  }
3973
4145
  }
3974
4146
 
3975
- export { Asserter, Stringifier, addTypeChecks, ast2json, ast2jsonForComparison, code2ast2code, compareAST, expandType, expandTypeBabelTS, expandTypeDepFree, extractCurlyContent, extractNameAndOptionality, nodeIsFunction, parseJSDoc, parseJSDocSetter, parseJSDocTemplates, parseJSDocTypedef, parseType, parseTypeBabelTS, requiredTypeofs, simplifyType, toSourceBabelTS, toSourceTS, trimEndSpaces };
4147
+ export { Asserter, Stringifier, addTypeChecks, ast2json, ast2jsonForComparison, code2ast2code, compareAST, expandType, expandTypeBabelTS, expandTypeDepFree, extractCurlyContent, extractNameAndOptionality, nodeIsFunction, parseJSDoc, parseJSDocSetter, parseJSDocTemplates, parseJSDocTypedef, parseType, parseTypeBabelTS, parserOptions, requiredTypeofs, simplifyType, toSourceBabelTS, toSourceTS, trimEndSpaces };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "bin": "bin.js",
3
3
  "name": "@runtime-type-inspector/transpiler",
4
- "version": "3.3.7",
4
+ "version": "4.0.0",
5
5
  "description": "Validating JSDoc types at runtime for high-quality types - Trust is good, control is better.",
6
6
  "main": "index.cjs",
7
7
  "module": "index.mjs",
@@ -19,7 +19,7 @@
19
19
  "homepage": "https://github.com/kungfooman/RuntimeTypeInspector.js#readme",
20
20
  "dependencies": {
21
21
  "@babel/parser": "^7.23.0",
22
- "@runtime-type-inspector/runtime": "^3.3.7",
22
+ "@runtime-type-inspector/runtime": "^4.0.0",
23
23
  "typescript": "^5.1.6"
24
24
  },
25
25
  "files": [