@nx/react 19.7.0-canary.20240820-0853690 → 19.7.0-canary.20240821-2065033

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/react",
3
- "version": "19.7.0-canary.20240820-0853690",
3
+ "version": "19.7.0-canary.20240821-2065033",
4
4
  "private": false,
5
5
  "description": "The React plugin for Nx contains executors and generators for managing React applications and libraries within an Nx workspace. It provides:\n\n\n- Integration with libraries such as Jest, Vitest, Playwright, Cypress, and Storybook.\n\n- Generators for applications, libraries, components, hooks, and more.\n\n- Library build support for publishing packages to npm or other registries.\n\n- Utilities for automatic workspace refactoring.",
6
6
  "repository": {
@@ -39,11 +39,11 @@
39
39
  "minimatch": "9.0.3",
40
40
  "tslib": "^2.3.0",
41
41
  "@module-federation/enhanced": "~0.2.3",
42
- "@nx/devkit": "19.7.0-canary.20240820-0853690",
43
- "@nx/js": "19.7.0-canary.20240820-0853690",
44
- "@nx/eslint": "19.7.0-canary.20240820-0853690",
45
- "@nx/web": "19.7.0-canary.20240820-0853690",
46
- "@nrwl/react": "19.7.0-canary.20240820-0853690"
42
+ "@nx/devkit": "19.7.0-canary.20240821-2065033",
43
+ "@nx/js": "19.7.0-canary.20240821-2065033",
44
+ "@nx/eslint": "19.7.0-canary.20240821-2065033",
45
+ "@nx/web": "19.7.0-canary.20240821-2065033",
46
+ "@nrwl/react": "19.7.0-canary.20240821-2065033"
47
47
  },
48
48
  "publishConfig": {
49
49
  "access": "public"
@@ -25,7 +25,7 @@ function getArgsDefaultValue(property) {
25
25
  [tsModule.SyntaxKind.BooleanKeyword]: false,
26
26
  };
27
27
  const resolvedValue = typeNameToDefault[property];
28
- if (typeof resolvedValue === undefined) {
28
+ if (resolvedValue === undefined) {
29
29
  return '';
30
30
  }
31
31
  else if (typeof resolvedValue === 'string') {
@@ -74,13 +74,18 @@ function createComponentSpecFile(tree, { project, componentPath, js, cypressProj
74
74
  }
75
75
  }
76
76
  function findPropsAndGenerateFileForCypress(tree, sourceFile, cmpDeclaration, e2eLibIntegrationFolderPath, componentName, project, js, fromNodeArray) {
77
- const propsInterface = (0, ast_utils_1.getComponentPropsInterface)(sourceFile, cmpDeclaration);
77
+ const info = (0, ast_utils_1.parseComponentPropsInfo)(sourceFile, cmpDeclaration);
78
78
  let props = [];
79
- if (propsInterface) {
80
- props = propsInterface.members.map((member) => {
79
+ if (info) {
80
+ if (!tsModule) {
81
+ tsModule = (0, ensure_typescript_1.ensureTypescript)();
82
+ }
83
+ props = info.props.map((member) => {
81
84
  return {
82
85
  name: member.name.text,
83
- defaultValue: getArgsDefaultValue(member.type.kind),
86
+ defaultValue: tsModule.isBindingElement(member)
87
+ ? getArgsDefaultValue(member.kind)
88
+ : getArgsDefaultValue(member.type.kind),
84
89
  };
85
90
  });
86
91
  }
@@ -45,14 +45,13 @@ function createComponentStoriesFile(host, { project, componentPath, interactionT
45
45
  }
46
46
  }
47
47
  function findPropsAndGenerateFile(host, sourceFile, cmpDeclaration, componentDirectory, name, interactionTests, isPlainJs, fromNodeArray) {
48
- const { propsTypeName, props, argTypes } = (0, component_props_1.getDefaultsForComponent)(sourceFile, cmpDeclaration);
48
+ const { props, argTypes } = (0, component_props_1.getComponentPropDefaults)(sourceFile, cmpDeclaration);
49
49
  (0, devkit_1.generateFiles)(host, (0, devkit_1.joinPathFragments)(__dirname, `./files${isPlainJs ? '/jsx' : '/tsx'}`), (0, devkit_1.normalizePath)(componentDirectory), {
50
50
  tmpl: '',
51
51
  componentFileName: fromNodeArray
52
52
  ? `${name}--${cmpDeclaration.name.text}`
53
53
  : name,
54
54
  componentImportFileName: name,
55
- propsTypeName,
56
55
  props,
57
56
  argTypes,
58
57
  componentName: cmpDeclaration.name.text,
@@ -38,7 +38,7 @@ function generateSpecsForComponents(tree, filePath) {
38
38
  const defaultExport = (0, ast_utils_1.getComponentNode)(sourceFile);
39
39
  if (cmpNodes?.length) {
40
40
  const components = cmpNodes.map((cmp) => {
41
- const defaults = (0, component_props_1.getDefaultsForComponent)(sourceFile, cmp);
41
+ const defaults = (0, component_props_1.getComponentPropDefaults)(sourceFile, cmp);
42
42
  const isDefaultExport = defaultExport
43
43
  ? defaultExport.name.text === cmp.name.text
44
44
  : false;
@@ -47,6 +47,7 @@ function generateSpecsForComponents(tree, filePath) {
47
47
  props: [...defaults.props, ...defaults.argTypes],
48
48
  name: cmp.name.text,
49
49
  typeName: defaults.propsTypeName,
50
+ inlineTypeString: defaults.inlineTypeString,
50
51
  };
51
52
  });
52
53
  const namedImports = components
@@ -2,8 +2,8 @@ import * as React from 'react'
2
2
  <%- importStatement %>
3
3
 
4
4
  <% for (let cmp of components) { %>
5
- describe(<%= cmp.name %>.name, () => {<% if (cmp.typeName) { %>
6
- let props: <%= cmp.typeName%>;
5
+ describe(<%= cmp.name %>.name, () => {<% if (cmp.props.length > 0) { %>
6
+ let props: <% if (cmp.typeName) { %><%= cmp.typeName %><% } else if (cmp.inlineTypeString) { %><%- cmp.inlineTypeString %><% } else { %>unknown<% } %>;
7
7
 
8
8
  beforeEach(() => {
9
9
  props = {<% for (let prop of cmp.props) { %>
@@ -26,4 +26,8 @@ export declare function updateReduxStore(sourcePath: string, source: ts.SourceFi
26
26
  modulePath: string;
27
27
  }): StringChange[];
28
28
  export declare function getComponentNode(sourceFile: ts.SourceFile): ts.Node | null;
29
- export declare function getComponentPropsInterface(sourceFile: ts.SourceFile, cmpDeclaration: ts.Node): ts.InterfaceDeclaration | null;
29
+ export declare function parseComponentPropsInfo(sourceFile: ts.SourceFile, cmpDeclaration: ts.Node): {
30
+ props: Array<ts.PropertySignature | ts.BindingElement>;
31
+ propsTypeName: string | null;
32
+ inlineTypeString: string | null;
33
+ } | null;
@@ -18,7 +18,7 @@ exports.addStaticRouter = addStaticRouter;
18
18
  exports.addReduxStoreToMain = addReduxStoreToMain;
19
19
  exports.updateReduxStore = updateReduxStore;
20
20
  exports.getComponentNode = getComponentNode;
21
- exports.getComponentPropsInterface = getComponentPropsInterface;
21
+ exports.parseComponentPropsInfo = parseComponentPropsInfo;
22
22
  const js_1 = require("@nx/js");
23
23
  const devkit_1 = require("@nx/devkit");
24
24
  const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
@@ -470,24 +470,58 @@ function getComponentNode(sourceFile) {
470
470
  }
471
471
  return defaultExport;
472
472
  }
473
- function getComponentPropsInterface(sourceFile, cmpDeclaration) {
473
+ function parseComponentPropsInfo(sourceFile, cmpDeclaration) {
474
474
  if (!tsModule) {
475
475
  tsModule = (0, ensure_typescript_1.ensureTypescript)();
476
476
  }
477
477
  let propsTypeName = null;
478
+ let inlineTypeString = null;
479
+ const props = [];
480
+ const processParameters = (parameters) => {
481
+ if (!parameters.length) {
482
+ return null;
483
+ }
484
+ const propsParam = parameters[0];
485
+ if (propsParam.type) {
486
+ if (tsModule.isTypeReferenceNode(propsParam.type)) {
487
+ // function Cmp(props: Props) {}
488
+ propsTypeName = propsParam.type.typeName.getText();
489
+ }
490
+ else if (tsModule.isTypeLiteralNode(propsParam.type)) {
491
+ // function Cmp(props: {a: string, b: number}) {}
492
+ props.push(...propsParam.type.members);
493
+ inlineTypeString = propsParam.type.getText();
494
+ }
495
+ else {
496
+ // we don't support other types (e.g. union types)
497
+ return false;
498
+ }
499
+ }
500
+ else if (tsModule.isObjectBindingPattern(propsParam.name)) {
501
+ // function Cmp({a, b}) {}
502
+ props.push(...propsParam.name.elements);
503
+ inlineTypeString = `{\n${propsParam.name.elements
504
+ .map((x) => `${x.name.getText()}: unknown;\n`)
505
+ .join('')}}`;
506
+ }
507
+ else {
508
+ // function Cmp(props) {}
509
+ return false;
510
+ }
511
+ return true;
512
+ };
478
513
  if (tsModule.isFunctionDeclaration(cmpDeclaration)) {
479
- const propsParam = cmpDeclaration.parameters.find((x) => tsModule.isParameter(x) && x.name.text === 'props');
480
- if (propsParam?.type?.['typeName']) {
481
- propsTypeName = propsParam.type.typeName.text;
514
+ const result = processParameters(cmpDeclaration.parameters);
515
+ if (!result) {
516
+ return null;
482
517
  }
483
518
  }
484
- else if (cmpDeclaration.initializer &&
519
+ else if (tsModule.isVariableDeclaration(cmpDeclaration) &&
520
+ cmpDeclaration.initializer &&
485
521
  tsModule.isArrowFunction(cmpDeclaration.initializer)) {
486
- const arrowFn = cmpDeclaration
487
- .initializer;
488
- const propsParam = arrowFn.parameters.find((x) => tsModule.isParameter(x) && x.name.text === 'props');
489
- if (propsParam?.type?.['typeName']) {
490
- propsTypeName = propsParam.type.typeName.text;
522
+ const result = processParameters(cmpDeclaration.initializer.parameters);
523
+ if (!result) {
524
+ return null;
491
525
  }
492
526
  }
493
527
  else if (
@@ -511,11 +545,56 @@ function getComponentPropsInterface(sourceFile, cmpDeclaration) {
511
545
  return null;
512
546
  }
513
547
  if (propsTypeName) {
514
- return (0, js_1.findNodes)(sourceFile, tsModule.SyntaxKind.InterfaceDeclaration).find((x) => {
548
+ const foundProps = getPropsFromTypeName(sourceFile, propsTypeName);
549
+ if (!foundProps) {
550
+ return null;
551
+ }
552
+ for (const prop of foundProps) {
553
+ props.push(prop);
554
+ }
555
+ }
556
+ return {
557
+ propsTypeName,
558
+ props,
559
+ inlineTypeString,
560
+ };
561
+ }
562
+ function getPropsFromTypeName(sourceFile, propsTypeName) {
563
+ const matchingNode = (0, js_1.findNodes)(sourceFile, [
564
+ tsModule.SyntaxKind.InterfaceDeclaration,
565
+ tsModule.SyntaxKind.TypeAliasDeclaration,
566
+ ]).find((x) => {
567
+ if (tsModule.isTypeAliasDeclaration(x) ||
568
+ tsModule.isInterfaceDeclaration(x)) {
515
569
  return x.name.getText() === propsTypeName;
516
- });
570
+ }
571
+ return false;
572
+ });
573
+ if (!matchingNode) {
574
+ return null;
575
+ }
576
+ const props = [];
577
+ if (tsModule.isTypeAliasDeclaration(matchingNode)) {
578
+ if (tsModule.isTypeLiteralNode(matchingNode.type)) {
579
+ for (const prop of matchingNode.type.members) {
580
+ props.push(prop);
581
+ }
582
+ }
583
+ else if (tsModule.isTypeReferenceNode(matchingNode.type)) {
584
+ const result = getPropsFromTypeName(sourceFile, matchingNode.type.typeName.getText());
585
+ if (result) {
586
+ props.push(...result);
587
+ }
588
+ }
589
+ else {
590
+ // we don't support other types of type aliases (e.g. union types)
591
+ return null;
592
+ }
517
593
  }
518
594
  else {
519
- return null;
595
+ for (const prop of matchingNode.members) {
596
+ props.push(prop);
597
+ }
520
598
  }
599
+ return props;
521
600
  }
@@ -1,7 +1,8 @@
1
1
  import type * as ts from 'typescript';
2
2
  export declare function getArgsDefaultValue(property: ts.SyntaxKind): string;
3
- export declare function getDefaultsForComponent(sourceFile: ts.SourceFile, cmpDeclaration: ts.Node): {
4
- propsTypeName: string;
3
+ export declare function getComponentPropDefaults(sourceFile: ts.SourceFile, cmpDeclaration: ts.Node): {
4
+ propsTypeName: string | null;
5
+ inlineTypeString: string | null;
5
6
  props: {
6
7
  name: string;
7
8
  defaultValue: any;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getArgsDefaultValue = getArgsDefaultValue;
4
- exports.getDefaultsForComponent = getDefaultsForComponent;
4
+ exports.getComponentPropDefaults = getComponentPropDefaults;
5
5
  exports.getImportForType = getImportForType;
6
6
  const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
7
7
  const ast_utils_1 = require("./ast-utils");
@@ -17,41 +17,53 @@ function getArgsDefaultValue(property) {
17
17
  [tsModule.SyntaxKind.BooleanKeyword]: false,
18
18
  };
19
19
  const resolvedValue = typeNameToDefault[property];
20
- if (typeof resolvedValue === undefined) {
20
+ if (resolvedValue === undefined) {
21
21
  return "''";
22
22
  }
23
23
  else {
24
24
  return resolvedValue;
25
25
  }
26
26
  }
27
- function getDefaultsForComponent(sourceFile, cmpDeclaration) {
27
+ function getComponentPropDefaults(sourceFile, cmpDeclaration) {
28
28
  if (!tsModule) {
29
29
  tsModule = (0, ensure_typescript_1.ensureTypescript)();
30
30
  }
31
- const propsInterface = (0, ast_utils_1.getComponentPropsInterface)(sourceFile, cmpDeclaration);
31
+ const info = (0, ast_utils_1.parseComponentPropsInfo)(sourceFile, cmpDeclaration);
32
32
  let propsTypeName = null;
33
+ let inlineTypeString = null;
33
34
  let props = [];
34
35
  let argTypes = [];
35
- if (propsInterface) {
36
- propsTypeName = propsInterface.name.text;
37
- props = propsInterface.members.map((member) => {
38
- if (member.type.kind === tsModule.SyntaxKind.FunctionType) {
39
- argTypes.push({
40
- name: member.name.text,
41
- type: 'action',
42
- actionText: `${member.name.text} executed!`,
43
- });
36
+ if (info) {
37
+ propsTypeName = info.propsTypeName;
38
+ inlineTypeString = info.inlineTypeString;
39
+ props = info.props.map((member) => {
40
+ if (tsModule.isPropertySignature(member)) {
41
+ if (member.type.kind === tsModule.SyntaxKind.FunctionType) {
42
+ argTypes.push({
43
+ name: member.name.getText(),
44
+ type: 'action',
45
+ actionText: `${member.name.getText()} executed!`,
46
+ });
47
+ }
48
+ else {
49
+ return {
50
+ name: member.name.getText(),
51
+ defaultValue: getArgsDefaultValue(member.type.kind),
52
+ };
53
+ }
44
54
  }
45
55
  else {
56
+ // it's a binding element, which doesn't have a type, e.g.:
57
+ // const Cmp = ({ a, b }) => {}
46
58
  return {
47
- name: member.name.text,
48
- defaultValue: getArgsDefaultValue(member.type.kind),
59
+ name: member.name.getText(),
60
+ defaultValue: getArgsDefaultValue(member.kind),
49
61
  };
50
62
  }
51
63
  });
52
64
  props = props.filter((p) => p && p.defaultValue !== undefined);
53
65
  }
54
- return { propsTypeName, props, argTypes };
66
+ return { propsTypeName, inlineTypeString, props, argTypes };
55
67
  }
56
68
  function getImportForType(sourceFile, typeName) {
57
69
  return sourceFile.statements.find((statement) => tsModule.isImportDeclaration(statement) &&