wrec 0.35.1 → 0.35.3

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "wrec",
3
3
  "description": "a library that greatly simplifies building web components",
4
4
  "author": "R. Mark Volkmann",
5
- "version": "0.35.1",
5
+ "version": "0.35.3",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
@@ -83,7 +83,12 @@ function analyzeSourceFile(sourceFile) {
83
83
  }
84
84
 
85
85
  // Builds the `declare` block that should appear after `static properties`.
86
- function buildDeclareBlock(sourceFile, classNode, propertiesMember, declareLines) {
86
+ function buildDeclareBlock(
87
+ sourceFile,
88
+ classNode,
89
+ propertiesMember,
90
+ declareLines
91
+ ) {
87
92
  const {text} = sourceFile;
88
93
  const memberIndent = getIndent(text, propertiesMember.getStart(sourceFile));
89
94
  const startIndex = classNode.members.indexOf(propertiesMember) + 1;
@@ -105,9 +110,7 @@ function buildDeclareBlock(sourceFile, classNode, propertiesMember, declareLines
105
110
  return nextMember ? `\n\n${nextIndent}` : '\n';
106
111
  }
107
112
 
108
- const content = declareLines
109
- .map(line => `${memberIndent}${line}`)
110
- .join('\n');
113
+ const content = declareLines.map(line => `${memberIndent}${line}`).join('\n');
111
114
  return nextMember ? `\n${content}\n\n${nextIndent}` : `\n${content}\n`;
112
115
  }
113
116
 
@@ -138,15 +141,12 @@ export function evaluateSourceFile(filePath, options = {}) {
138
141
 
139
142
  // Determines what changes, if any, should be made in source file text.
140
143
  export function evaluateSourceText(filePath, text) {
141
- const scriptKind = filePath.endsWith('.ts')
142
- ? ts.ScriptKind.TS
143
- : ts.ScriptKind.JS;
144
144
  const sourceFile = ts.createSourceFile(
145
145
  filePath,
146
146
  text,
147
147
  ts.ScriptTarget.Latest,
148
148
  true,
149
- scriptKind
149
+ ts.ScriptKind.TS
150
150
  );
151
151
  return analyzeSourceFile(sourceFile);
152
152
  }
@@ -258,8 +258,8 @@ function validateFile(absFilePath) {
258
258
  const stat = fs.statSync(absFilePath);
259
259
  if (!stat.isFile()) throw new Error('Not a file');
260
260
 
261
- if (!/\.(js|ts)$/.test(absFilePath) || /\.d\.ts$/.test(absFilePath)) {
262
- throw new Error('Unsupported file type');
261
+ if (!/\.ts$/.test(absFilePath)) {
262
+ throw new Error('validate statements can only be added in .ts files');
263
263
  }
264
264
  }
265
265
 
package/scripts/lint.js CHANGED
@@ -1602,6 +1602,23 @@ function requiresContextFunction(symbol, sourceFile) {
1602
1602
  });
1603
1603
  }
1604
1604
 
1605
+ // Returns whether a type represents an object-like value other than an array.
1606
+ function isNonArrayObjectLikeType(checker, type) {
1607
+ if (type.isUnion()) {
1608
+ return type.types.every(member => isNonArrayObjectLikeType(checker, member));
1609
+ }
1610
+
1611
+ if (type.isIntersection()) {
1612
+ return type.types.every(member => isNonArrayObjectLikeType(checker, member));
1613
+ }
1614
+
1615
+ return (
1616
+ Boolean(type.flags & (ts.TypeFlags.Object | ts.TypeFlags.NonPrimitive)) &&
1617
+ !checker.isArrayType(type) &&
1618
+ !checker.isTupleType(type)
1619
+ );
1620
+ }
1621
+
1605
1622
  // Resolves a relative import path to an existing source file.
1606
1623
  function resolveImportPath(baseDir, importPath) {
1607
1624
  if (!importPath.startsWith('.')) return undefined;
@@ -1622,6 +1639,22 @@ function toUserFacingExpression(text) {
1622
1639
  return text.replaceAll(WREC_REF_NAME, 'this');
1623
1640
  }
1624
1641
 
1642
+ // Returns whether a static property config type is compatible with a declare type.
1643
+ function typeExpressionMatchesDeclaredType(
1644
+ checker,
1645
+ typeExpression,
1646
+ declaredTypeNode
1647
+ ) {
1648
+ const declaredType = checker.getTypeFromTypeNode(declaredTypeNode);
1649
+
1650
+ if (typeExpressionKind(typeExpression) === 'Object') {
1651
+ return isNonArrayObjectLikeType(checker, declaredType);
1652
+ }
1653
+
1654
+ const runtimeType = checker.getTypeAtLocation(typeExpression);
1655
+ return checker.isTypeAssignableTo(runtimeType, declaredType);
1656
+ }
1657
+
1625
1658
  // Classifies a constructor-based type expression by its identifier name.
1626
1659
  function typeExpressionKind(expression) {
1627
1660
  if (!expression) return undefined;
@@ -1776,11 +1809,7 @@ function validateDefaultValue(checker, typeExpression, valueExpression) {
1776
1809
  }
1777
1810
 
1778
1811
  if (typeKind === 'Object') {
1779
- const isObjectLike =
1780
- Boolean(valueType.flags & ts.TypeFlags.Object) &&
1781
- !checker.isArrayType(valueType) &&
1782
- !checker.isTupleType(valueType);
1783
- if (!isObjectLike) {
1812
+ if (!isNonArrayObjectLikeType(checker, valueType)) {
1784
1813
  return {typeName: 'Object', valueTypeName};
1785
1814
  }
1786
1815
  }
@@ -1942,9 +1971,7 @@ function validatePropertyConfigs(
1942
1971
  'Boolean, Number, String, Object, or Array'
1943
1972
  );
1944
1973
  } else if (declaredTypeNode) {
1945
- const runtimeType = checker.getTypeAtLocation(typeExpression);
1946
- const declaredType = checker.getTypeFromTypeNode(declaredTypeNode);
1947
- if (!checker.isTypeAssignableTo(runtimeType, declaredType)) {
1974
+ if (!typeExpressionMatchesDeclaredType(checker, typeExpression, declaredTypeNode)) {
1948
1975
  findings.incompatibleDeclareTypes.push(
1949
1976
  `property "${propName}" declare type ` +
1950
1977
  `"${getPropertyTypeTextFromNode(sourceFile, declaredTypeNode)}" ` +
@@ -723,7 +723,7 @@ function validateFile(absFilePath) {
723
723
  const stat = fs.statSync(absFilePath);
724
724
  if (!stat.isFile()) throw new Error('Not a file');
725
725
 
726
- if (!/\.(js|ts)$/.test(absFilePath) || /\.d\.ts$/.test(absFilePath)) {
726
+ if (!/\.(js|ts)$/.test(absFilePath)) {
727
727
  throw new Error('Unsupported file type');
728
728
  }
729
729
  }