@agilebot/eslint-plugin 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
package/lib/index.js CHANGED
@@ -1,52 +1,59 @@
1
- // @ts-check
2
- const path = require('path');
3
- const { globSync } = require('fast-glob');
4
-
5
- // List all rules in rules folder
6
- const rulesPath = path.join(__dirname, 'rules');
7
- const ruleFiles = globSync('**/*.js', {
8
- cwd: rulesPath
9
- });
10
- const rules = {};
11
- ruleFiles.forEach(file => {
12
- const { dir, name } = path.parse(file);
13
- const ruleName = `${dir}/${name}`;
14
- rules[ruleName] = require(path.join(rulesPath, file));
15
- });
16
-
17
- module.exports.rules = rules;
18
-
19
- module.exports.configs = {
20
- recommended: {
21
- plugins: ['@agilebot'],
22
- rules: {
23
- 'react-hooks/exhaustive-deps': 'off',
24
- '@agilebot/react/better-exhaustive-deps': [
25
- 'warn',
26
- {
27
- checkMemoizedVariableIsStatic: true,
28
- staticHooks: {
29
- useIpcSender: true,
30
- useDialog: true,
31
- useSnackbar: true,
32
- useForm: true,
33
- 'use.*Store': {
34
- value: true,
35
- regexp: true
36
- }
37
- }
38
- }
39
- ],
40
- '@agilebot/react/prefer-named-property-access': 'error',
41
- '@agilebot/react/hook-use-ref': 'warn',
42
- '@agilebot/react/no-inline-styles': 'error',
43
- '@agilebot/tss/unused-classes': 'warn',
44
- '@agilebot/tss/no-color-value': 'error',
45
- '@agilebot/tss/class-naming': 'error',
46
- '@agilebot/import/enforce-icon-alias': 'error',
47
- '@agilebot/import/monorepo': 'error',
48
- '@agilebot/others/no-unnecessary-template-literals': 'error'
49
- },
50
- settings: {}
51
- }
52
- };
1
+ // @ts-check
2
+ const path = require('node:path');
3
+ const { globSync } = require('fast-glob');
4
+
5
+ // List all rules in rules folder
6
+ const rulesPath = path.join(__dirname, 'rules');
7
+ const ruleFiles = globSync('**/*.js', {
8
+ cwd: rulesPath
9
+ });
10
+
11
+ /**
12
+ * @type {import('eslint').Linter.RulesRecord}
13
+ */
14
+ const rules = {};
15
+ ruleFiles.forEach(file => {
16
+ const { dir, name } = path.parse(file);
17
+ const ruleName = `${dir}/${name}`;
18
+ rules[ruleName] = require(path.join(rulesPath, file));
19
+ });
20
+
21
+ module.exports.rules = rules;
22
+
23
+ module.exports.configs = {
24
+ recommended: {
25
+ plugins: ['@agilebot'],
26
+ rules: {
27
+ 'react-hooks/exhaustive-deps': 'off',
28
+ '@agilebot/react/better-exhaustive-deps': [
29
+ 'warn',
30
+ {
31
+ checkMemoizedVariableIsStatic: true,
32
+ staticHooks: {
33
+ 'useIpc.*': {
34
+ value: true,
35
+ regexp: true
36
+ },
37
+ useDialog: true,
38
+ useSnackbar: true,
39
+ useForm: true,
40
+ 'use.*Store': {
41
+ value: true,
42
+ regexp: true
43
+ }
44
+ }
45
+ }
46
+ ],
47
+ '@agilebot/react/prefer-named-property-access': 'error',
48
+ '@agilebot/react/hook-use-ref': 'warn',
49
+ '@agilebot/react/no-inline-styles': 'error',
50
+ '@agilebot/tss/unused-classes': 'warn',
51
+ '@agilebot/tss/no-color-value': 'error',
52
+ '@agilebot/tss/class-naming': 'error',
53
+ '@agilebot/import/enforce-icon-alias': 'error',
54
+ '@agilebot/import/monorepo': 'error',
55
+ '@agilebot/others/no-unnecessary-template-literals': 'error'
56
+ },
57
+ settings: {}
58
+ }
59
+ };
@@ -1,6 +1,7 @@
1
- const { consola } = require('consola');
2
1
  const { getSetting } = require('../../util/settings');
3
2
 
3
+ let warnedForMissingPrefix = false;
4
+
4
5
  module.exports = {
5
6
  meta: {
6
7
  type: 'problem', // `problem`, `suggestion`, or `layout`
@@ -17,7 +18,11 @@ module.exports = {
17
18
  ImportDeclaration(node) {
18
19
  const prefix = getSetting(context, 'monorepo-prefix');
19
20
  if (!prefix) {
20
- consola.warn('agilebot/monorepo-prefix is not set');
21
+ if (!warnedForMissingPrefix) {
22
+ // eslint-disable-next-line no-console -- this is a CLI tool
23
+ console.error('Warning: agilebot/monorepo-prefix is not set.');
24
+ warnedForMissingPrefix = true;
25
+ }
21
26
  return;
22
27
  }
23
28
 
@@ -1,5 +1,5 @@
1
- const path = require('path');
2
- const fs = require('fs');
1
+ const path = require('node:path');
2
+ const fs = require('node:fs');
3
3
  const {
4
4
  sortedTemplateElements,
5
5
  findFormatMessageAttrNode,
@@ -1,6 +1,3 @@
1
- /* eslint-disable no-case-declarations */
2
- /* eslint-disable no-continue */
3
-
4
1
  /**
5
2
  * Copyright (c) Facebook, Inc. and its affiliates.
6
3
  *
@@ -96,12 +93,13 @@ module.exports = {
96
93
  };
97
94
 
98
95
  function reportProblem(problem) {
99
- if (enableDangerousAutofixThisMayCauseInfiniteLoops) {
100
- // Used to enable legacy behavior. Dangerous.
96
+ if (
97
+ enableDangerousAutofixThisMayCauseInfiniteLoops && // Used to enable legacy behavior. Dangerous.
101
98
  // Keep this as an option until major IDEs upgrade (including VSCode FB ESLint extension).
102
- if (Array.isArray(problem.suggest) && problem.suggest.length > 0) {
103
- problem.fix = problem.suggest[0].fix;
104
- }
99
+ Array.isArray(problem.suggest) &&
100
+ problem.suggest.length > 0
101
+ ) {
102
+ problem.fix = problem.suggest[0].fix;
105
103
  }
106
104
  context.report(problem);
107
105
  }
@@ -286,17 +284,14 @@ module.exports = {
286
284
  if (name === 'useState') {
287
285
  const references = resolved.references;
288
286
  let writeCount = 0;
289
- for (let i = 0; i < references.length; i++) {
290
- if (references[i].isWrite()) {
287
+ for (const reference of references) {
288
+ if (reference.isWrite()) {
291
289
  writeCount++;
292
290
  }
293
291
  if (writeCount > 1) {
294
292
  return false;
295
293
  }
296
- setStateCallSites.set(
297
- references[i].identifier,
298
- id.elements[0]
299
- );
294
+ setStateCallSites.set(reference.identifier, id.elements[0]);
300
295
  }
301
296
  }
302
297
  // Setter is stable.
@@ -304,8 +299,8 @@ module.exports = {
304
299
  } else if (id.elements[0] === resolved.identifiers[0]) {
305
300
  if (name === 'useState') {
306
301
  const references = resolved.references;
307
- for (let i = 0; i < references.length; i++) {
308
- stateVariables.add(references[i].identifier);
302
+ for (const reference of references) {
303
+ stateVariables.add(reference.identifier);
309
304
  }
310
305
  }
311
306
  // State variable itself is dynamic.
@@ -317,13 +312,11 @@ module.exports = {
317
312
  if (
318
313
  id.type === 'ArrayPattern' &&
319
314
  id.elements.length === 2 &&
320
- Array.isArray(resolved.identifiers)
315
+ Array.isArray(resolved.identifiers) && // Is second tuple value the same reference we're checking?
316
+ id.elements[1] === resolved.identifiers[0]
321
317
  ) {
322
- // Is second tuple value the same reference we're checking?
323
- if (id.elements[1] === resolved.identifiers[0]) {
324
- // Setter is stable.
325
- return true;
326
- }
318
+ // Setter is stable.
319
+ return true;
327
320
  }
328
321
  } else if (
329
322
  options.checkMemoizedVariableIsStatic &&
@@ -350,7 +343,7 @@ module.exports = {
350
343
  );
351
344
 
352
345
  if (
353
- typeof dependencyRefernece !== 'undefined' &&
346
+ dependencyRefernece !== undefined &&
354
347
  memoizedIsStableKnownHookValue(dependencyRefernece.resolved)
355
348
  ) {
356
349
  continue;
@@ -372,7 +365,6 @@ module.exports = {
372
365
  }
373
366
  });
374
367
 
375
- // eslint-disable-next-line no-lonely-if
376
368
  if (options.staticHooks[name]) {
377
369
  const staticParts = options.staticHooks[name];
378
370
  if (staticParts === true) {
@@ -386,9 +378,7 @@ module.exports = {
386
378
  Array.isArray(resolved.identifiers)
387
379
  ) {
388
380
  // find index of the resolved ident in the array pattern
389
- const idx = id.elements.findIndex(
390
- ident => ident === resolved.identifiers[0]
391
- );
381
+ const idx = id.elements.indexOf(resolved.identifiers[0]);
392
382
  if (idx >= 0) {
393
383
  return staticParts[idx];
394
384
  }
@@ -587,8 +577,7 @@ module.exports = {
587
577
  // Is React managing this ref or us?
588
578
  // Let's see if we can find a .current assignment.
589
579
  let foundCurrentAssignment = false;
590
- for (let i = 0; i < references.length; i++) {
591
- const { identifier } = references[i];
580
+ for (const { identifier } of references) {
592
581
  const { parent } = identifier;
593
582
  if (
594
583
  parent != null &&
@@ -764,8 +753,8 @@ module.exports = {
764
753
  declaredDependencyNode,
765
754
  null
766
755
  );
767
- } catch (error) {
768
- if (/Unsupported node type/.test(error.message)) {
756
+ } catch (err) {
757
+ if (/Unsupported node type/.test(err.message)) {
769
758
  if (declaredDependencyNode.type === 'Literal') {
770
759
  if (dependencies.has(declaredDependencyNode.value)) {
771
760
  reportProblem({
@@ -795,7 +784,7 @@ module.exports = {
795
784
 
796
785
  return;
797
786
  }
798
- throw error;
787
+ throw err;
799
788
  }
800
789
 
801
790
  let maybeID = declaredDependencyNode;
@@ -942,7 +931,7 @@ module.exports = {
942
931
  return true;
943
932
  }
944
933
  const declaredDepKeys = declaredDependencies.map(dep => dep.key);
945
- const sortedDeclaredDepKeys = declaredDepKeys.slice().sort();
934
+ const sortedDeclaredDepKeys = [...declaredDepKeys].sort();
946
935
  return declaredDepKeys.join(',') === sortedDeclaredDepKeys.join(',');
947
936
  }
948
937
  if (areDeclaredDepsAlphabetized()) {
@@ -978,9 +967,7 @@ module.exports = {
978
967
  (deps.size > 1 ? 'dependencies' : 'dependency') +
979
968
  ': ' +
980
969
  joinEnglish(
981
- Array.from(deps)
982
- .sort()
983
- .map(name => "'" + formatDependency(name) + "'")
970
+ [...deps].sort().map(name => "'" + formatDependency(name) + "'")
984
971
  ) +
985
972
  `. Either ${fixVerb} ${
986
973
  deps.size > 1 ? 'them' : 'it'
@@ -991,7 +978,7 @@ module.exports = {
991
978
  let extraWarning = '';
992
979
  if (unnecessaryDependencies.size > 0) {
993
980
  let badRef = null;
994
- Array.from(unnecessaryDependencies.keys()).forEach(key => {
981
+ [...unnecessaryDependencies.keys()].forEach(key => {
995
982
  if (badRef != null) {
996
983
  return;
997
984
  }
@@ -1004,7 +991,7 @@ module.exports = {
1004
991
  ` Mutable values like '${badRef}' aren't valid dependencies ` +
1005
992
  "because mutating them doesn't re-render the component.";
1006
993
  } else if (externalDependencies.size > 0) {
1007
- const dep = Array.from(externalDependencies)[0];
994
+ const dep = [...externalDependencies][0];
1008
995
  // Don't show this warning for things that likely just got moved *inside* the callback
1009
996
  // because in that case they're clearly not referring to globals.
1010
997
  if (!scope.set.has(dep)) {
@@ -1028,8 +1015,7 @@ module.exports = {
1028
1015
  return;
1029
1016
  }
1030
1017
  let isPropsOnlyUsedInMembers = true;
1031
- for (let i = 0; i < refs.length; i++) {
1032
- const ref = refs[i];
1018
+ for (const ref of refs) {
1033
1019
  const id = fastFindReferenceWithParent(
1034
1020
  componentScope.block,
1035
1021
  ref.identifier
@@ -1121,8 +1107,8 @@ module.exports = {
1121
1107
  const references = usedDep.references;
1122
1108
  let id;
1123
1109
  let maybeCall;
1124
- for (let i = 0; i < references.length; i++) {
1125
- id = references[i].identifier;
1110
+ for (const reference of references) {
1111
+ id = reference.identifier;
1126
1112
  maybeCall = id.parent;
1127
1113
  // Try to see if we have setState(someExpr(missingDep)).
1128
1114
  while (maybeCall != null && maybeCall !== componentScope.block) {
@@ -1146,7 +1132,7 @@ module.exports = {
1146
1132
  form: 'reducer'
1147
1133
  };
1148
1134
  } else {
1149
- const resolved = references[i].resolved;
1135
+ const resolved = reference.resolved;
1150
1136
  if (resolved != null) {
1151
1137
  // If it's a parameter *and* a missing dep,
1152
1138
  // it must be a prop or something inside a prop.
@@ -1189,7 +1175,7 @@ module.exports = {
1189
1175
  case 'updater':
1190
1176
  extraWarning = ` You can also do a functional update '${
1191
1177
  setStateRecommendation.setter
1192
- }(${setStateRecommendation.missingDep.substring(
1178
+ }(${setStateRecommendation.missingDep.slice(
1193
1179
  0,
1194
1180
  1
1195
1181
  )} => ...)' if you only need '${
@@ -1224,13 +1210,13 @@ module.exports = {
1224
1210
  suggest: [
1225
1211
  {
1226
1212
  desc: `Update the dependencies array to be: [${suggestedDeps
1227
- .map(formatDependency)
1213
+ .map(element => formatDependency(element))
1228
1214
  .join(', ')}]`,
1229
1215
  fix(fixer) {
1230
1216
  // TODO: consider preserving the comments or formatting?
1231
1217
  return fixer.replaceText(
1232
1218
  declaredDependenciesNode,
1233
- `[${suggestedDeps.map(formatDependency).join(', ')}]`
1219
+ `[${suggestedDeps.map(element => formatDependency(element)).join(', ')}]`
1234
1220
  );
1235
1221
  }
1236
1222
  }
@@ -1520,7 +1506,7 @@ function collectRecommendations({
1520
1506
  declaredDependencies.forEach(({ key }) => {
1521
1507
  // Does this declared dep satisfy a real need?
1522
1508
  if (satisfyingDependencies.has(key)) {
1523
- if (suggestedDependencies.indexOf(key) === -1) {
1509
+ if (!suggestedDependencies.includes(key)) {
1524
1510
  // Good one.
1525
1511
  suggestedDependencies.push(key);
1526
1512
  } else {
@@ -1536,7 +1522,7 @@ function collectRecommendations({
1536
1522
  // Such as resetting scroll when ID changes.
1537
1523
  // Consider them legit.
1538
1524
  // The exception is ref.current which is always wrong.
1539
- if (suggestedDependencies.indexOf(key) === -1) {
1525
+ if (!suggestedDependencies.includes(key)) {
1540
1526
  suggestedDependencies.push(key);
1541
1527
  }
1542
1528
  } else {
@@ -1681,12 +1667,12 @@ function scanForConstructions({
1681
1667
  while (currentScope !== scope && currentScope != null) {
1682
1668
  currentScope = currentScope.upper;
1683
1669
  }
1684
- if (currentScope !== scope) {
1685
- // This reference is outside the Hook callback.
1670
+ if (
1671
+ currentScope !== scope && // This reference is outside the Hook callback.
1686
1672
  // It can only be legit if it's the deps array.
1687
- if (!isAncestorNodeOf(declaredDependenciesNode, reference.identifier)) {
1688
- return true;
1689
- }
1673
+ !isAncestorNodeOf(declaredDependenciesNode, reference.identifier)
1674
+ ) {
1675
+ return true;
1690
1676
  }
1691
1677
  }
1692
1678
  return false;
@@ -1837,11 +1823,11 @@ function getReactiveHookCallbackIndex(calleeNode, options) {
1837
1823
  let name;
1838
1824
  try {
1839
1825
  name = analyzePropertyChain(node, null);
1840
- } catch (error) {
1841
- if (/Unsupported node type/.test(error.message)) {
1826
+ } catch (err) {
1827
+ if (/Unsupported node type/.test(err.message)) {
1842
1828
  return 0;
1843
1829
  }
1844
- throw error;
1830
+ throw err;
1845
1831
  }
1846
1832
  return options.additionalHooks.test(name) ? 0 : -1;
1847
1833
  }
@@ -1863,7 +1849,7 @@ function fastFindReferenceWithParent(start, target) {
1863
1849
  const queue = [start];
1864
1850
  let item = null;
1865
1851
 
1866
- while (queue.length) {
1852
+ while (queue.length > 0) {
1867
1853
  item = queue.shift();
1868
1854
 
1869
1855
  if (isSameIdentifier(item, target)) {
@@ -1882,7 +1868,7 @@ function fastFindReferenceWithParent(start, target) {
1882
1868
  value.parent = item;
1883
1869
  queue.push(value);
1884
1870
  } else if (Array.isArray(value)) {
1885
- // eslint-disable-next-line no-loop-func
1871
+ // eslint-disable-next-line no-loop-func -- FIXME
1886
1872
  value.forEach(val => {
1887
1873
  if (isNodeLike(val)) {
1888
1874
  val.parent = item;
@@ -40,7 +40,7 @@ function* updateImportStatement(context, fixer, key) {
40
40
  }
41
41
 
42
42
  // Named imports section is present and current key is not imported yet - add it to named imports section
43
- yield fixer.insertTextAfter(importNode.specifiers.slice().pop(), `, ${key}`);
43
+ yield fixer.insertTextAfter([...importNode.specifiers].pop(), `, ${key}`);
44
44
  }
45
45
 
46
46
  /** @type {import('eslint').Rule.RuleModule} */
@@ -9,7 +9,7 @@ module.exports = {
9
9
  CallExpression(node) {
10
10
  const stylesObj = getStyesObj(node);
11
11
 
12
- if (typeof stylesObj === 'undefined') {
12
+ if (stylesObj === undefined) {
13
13
  return;
14
14
  }
15
15
 
@@ -25,7 +25,6 @@ module.exports = {
25
25
  function checkColorLiteral(value) {
26
26
  if (value.type === 'Literal' && typeof value.value === 'string') {
27
27
  const colorCodePattern =
28
- // eslint-disable-next-line max-len
29
28
  /#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|rgb\?\(\s*(\d{1,3}\s*,\s*){2}\d{1,3}(?:\s*,\s*\d*(?:\.\d+)?)?\s*\)/g;
30
29
  const isColorCode = colorCodePattern.test(value.value);
31
30
  if (isColorCode) {
@@ -12,7 +12,7 @@ module.exports = {
12
12
  CallExpression(node) {
13
13
  const stylesObj = getStyesObj(node);
14
14
 
15
- if (typeof stylesObj === 'undefined') {
15
+ if (stylesObj === undefined) {
16
16
  return;
17
17
  }
18
18
 
package/lib/util/intl.js CHANGED
@@ -9,13 +9,13 @@ function findFormatMessageAttrNode(node, attrName) {
9
9
  // Find formatMessage usages
10
10
  if (
11
11
  node.type === 'CallExpression' &&
12
- (node.callee.name === 'formatMessage' || node.callee.name === '$t')
12
+ (node.callee.name === 'formatMessage' || node.callee.name === '$t') &&
13
+ node.arguments.length > 0 &&
14
+ node.arguments[0].properties
13
15
  ) {
14
- if (node.arguments.length && node.arguments[0].properties) {
15
- return node.arguments[0].properties.find(
16
- a => a.key && a.key.name === attrName
17
- );
18
- }
16
+ return node.arguments[0].properties.find(
17
+ a => a.key && a.key.name === attrName
18
+ );
19
19
  }
20
20
 
21
21
  // Find intl.formatMessage usages
@@ -1,7 +1,6 @@
1
- /* eslint-disable no-sync */
2
- const fs = require('fs');
3
- const path = require('path');
4
- const { tsImport } = require('./import');
1
+ const fs = require('node:fs');
2
+ const path = require('node:path');
3
+ const { tsImport } = require('@agilebot/eslint-utils');
5
4
  const { getSetting } = require('./settings');
6
5
 
7
6
  /**
package/lib/util/tss.js CHANGED
@@ -12,7 +12,7 @@ function getBasicIdentifier(node) {
12
12
 
13
13
  if (node.type === 'TemplateLiteral') {
14
14
  // Handle template literals, e.g., classes[`foo`]
15
- if (node.expressions.length) {
15
+ if (node.expressions.length > 0) {
16
16
  // Template literals with expressions, e.g., classes[`foo${bar}`]
17
17
  return null;
18
18
  }
@@ -25,12 +25,17 @@ function getBasicIdentifier(node) {
25
25
 
26
26
  // Helper function to recursively get the base identifier from a MemberExpression node
27
27
  function getBaseIdentifier(node) {
28
- if (node.type === 'Identifier') {
29
- return node;
30
- } else if (node.type === 'CallExpression') {
31
- return getBaseIdentifier(node.callee);
32
- } else if (node.type === 'MemberExpression') {
33
- return getBaseIdentifier(node.object);
28
+ switch (node.type) {
29
+ case 'Identifier': {
30
+ return node;
31
+ }
32
+ case 'CallExpression': {
33
+ return getBaseIdentifier(node.callee);
34
+ }
35
+ case 'MemberExpression': {
36
+ return getBaseIdentifier(node.object);
37
+ }
38
+ // No default
34
39
  }
35
40
  return null;
36
41
  }
package/package.json CHANGED
@@ -1,21 +1,27 @@
1
1
  {
2
2
  "name": "@agilebot/eslint-plugin",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Agilebot's ESLint plugin",
5
5
  "main": "lib",
6
6
  "license": "MIT",
7
+ "keywords": [
8
+ "eslint",
9
+ "eslint-plugin"
10
+ ],
7
11
  "repository": {
8
12
  "url": "sh-agilebot/frontend-toolkit",
9
13
  "directory": "packages/eslint-plugin"
10
14
  },
11
15
  "homepage": "https://github.com/sh-agilebot/frontend-toolkit/tree/master/packages/eslint-plugin#readme",
16
+ "engines": {
17
+ "node": "^18.18.0 || >=20.0.0"
18
+ },
12
19
  "dependencies": {
13
20
  "@typescript-eslint/utils": "^7.1.1",
14
- "consola": "^3.2.3",
15
- "fast-glob": "^3.3.2",
16
- "get-tsconfig": "^4.7.3",
17
- "jiti": "^1.21.0",
18
- "sucrase": "^3.35.0"
21
+ "fast-glob": "^3.3.2"
22
+ },
23
+ "peerDependencies": {
24
+ "eslint": "^7.0.0 || ^8.0.0"
19
25
  },
20
26
  "files": [
21
27
  "lib"
@@ -1,71 +0,0 @@
1
- const path = require('path');
2
- const jiti = require('jiti');
3
- const { transform } = require('sucrase');
4
- const { getTsconfig } = require('get-tsconfig');
5
-
6
- /**
7
- * import ts module, like require, but support ts
8
- * @param {*} modulePath - module path
9
- */
10
- function tsImport(modulePath) {
11
- if (!modulePath) {
12
- return;
13
- }
14
- /** try to delete cache first */
15
- try {
16
- if (require.cache[modulePath]) {
17
- delete require.cache[modulePath];
18
- }
19
- } catch (err) {
20
- /* empty */
21
- }
22
-
23
- try {
24
- return require(modulePath);
25
- } catch (err) {
26
- const tsconfig = getTsconfig(modulePath);
27
- const { paths, baseUrl } = tsconfig.config.compilerOptions;
28
- let basePath = path.dirname(tsconfig.path);
29
- basePath = path.resolve(basePath, baseUrl);
30
-
31
- const alias = resolveTsconfigPathsToAlias(paths, basePath);
32
-
33
- return jiti(__filename, {
34
- interopDefault: true,
35
- cache: false,
36
- debug: !!process.env.DEBUG,
37
- transform: options => {
38
- return transform(options.source, {
39
- transforms: ['imports', 'typescript']
40
- });
41
- },
42
- alias
43
- })(modulePath);
44
- }
45
- }
46
-
47
- /**
48
- * Resolve tsconfig.json paths to Webpack aliases
49
- * @param {string} paths - tsconfig.json paths
50
- * @param {string} basePath - Path from tsconfig to Webpack config to create absolute aliases
51
- * @return {object} - Webpack alias config
52
- */
53
- function resolveTsconfigPathsToAlias(paths, basePath = __dirname) {
54
- const aliases = {};
55
-
56
- Object.keys(paths).forEach(item => {
57
- const key = item.replace('/*', '');
58
- const value = path.resolve(
59
- basePath,
60
- paths[item][0].replace('/*', '').replace('*', '')
61
- );
62
-
63
- aliases[key] = value;
64
- });
65
-
66
- return aliases;
67
- }
68
-
69
- module.exports = {
70
- tsImport
71
- };