@memberjunction/react-test-harness 2.99.0 → 2.100.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.
@@ -1 +1 @@
1
- {"version":3,"file":"component-linter.d.ts","sourceRoot":"","sources":["../../src/lib/component-linter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAiC,MAAM,6CAA6C,CAAC;AAG3G,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAG/D,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,gBAAgB,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,cAAc,CAAC;IACnF,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAiFD,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,cAAc,CAAqB;IAGlD,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAQhC,OAAO,CAAC,MAAM,CAAC,cAAc;IAoB7B,OAAO,CAAC,MAAM,CAAC,4BAA4B;IA2C3C,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAy0NpC;WAEkB,uBAAuB,CACzC,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;WAmC5B,aAAa,CAC/B,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EACrB,aAAa,CAAC,EAAE,aAAa,EAC7B,eAAe,CAAC,EAAE,OAAO,EACzB,WAAW,CAAC,EAAE,QAAQ,EACtB,SAAS,CAAC,EAAE,OAAO,EACnB,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC,UAAU,CAAC;IAqJtB,OAAO,CAAC,MAAM,CAAC,wBAAwB;IAoXvC,OAAO,CAAC,MAAM,CAAC,eAAe;IA2B9B,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAyBpC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,0BAA0B;IA6hCzC,OAAO,CAAC,MAAM,CAAC,8BAA8B;IA2B7C;;OAEG;mBACkB,qBAAqB;IAuJ1C;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,0BAA0B;IAiEzC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IA8ClC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IA8GpC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAoElC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,yBAAyB;CAkGzC"}
1
+ {"version":3,"file":"component-linter.d.ts","sourceRoot":"","sources":["../../src/lib/component-linter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAiC,MAAM,6CAA6C,CAAC;AAG3G,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAG/D,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,gBAAgB,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,cAAc,CAAC;IACnF,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAiFD,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,cAAc,CAAqB;IAGlD,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAQhC,OAAO,CAAC,MAAM,CAAC,cAAc;IAoB7B,OAAO,CAAC,MAAM,CAAC,4BAA4B;IA2C3C,OAAO,CAAC,MAAM,CAAC,uBAAuB,CA8hOpC;WAEkB,uBAAuB,CACzC,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;WAmC5B,aAAa,CAC/B,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EACrB,aAAa,CAAC,EAAE,aAAa,EAC7B,eAAe,CAAC,EAAE,OAAO,EACzB,WAAW,CAAC,EAAE,QAAQ,EACtB,SAAS,CAAC,EAAE,OAAO,EACnB,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC,UAAU,CAAC;IAqJtB,OAAO,CAAC,MAAM,CAAC,wBAAwB;IAoXvC,OAAO,CAAC,MAAM,CAAC,eAAe;IA2B9B,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAyBpC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,0BAA0B;IA6hCzC,OAAO,CAAC,MAAM,CAAC,8BAA8B;IA2B7C;;OAEG;mBACkB,qBAAqB;IAuJ1C;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,0BAA0B;IAiEzC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IA8ClC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IA8GpC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAoElC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,yBAAyB;CAkGzC"}
@@ -8460,6 +8460,198 @@ ${eventName}?.(data);`
8460
8460
  });
8461
8461
  return violations;
8462
8462
  }
8463
+ },
8464
+ {
8465
+ name: 'callbacks-passthrough-only',
8466
+ appliesTo: 'all',
8467
+ test: (ast, _componentName, _componentSpec) => {
8468
+ const violations = [];
8469
+ (0, traverse_1.default)(ast, {
8470
+ JSXAttribute(path) {
8471
+ // Check if this is a callbacks prop being passed to a component
8472
+ if (t.isJSXIdentifier(path.node.name) && path.node.name.name === 'callbacks') {
8473
+ const value = path.node.value;
8474
+ // Check if value is a JSXExpressionContainer
8475
+ if (t.isJSXExpressionContainer(value)) {
8476
+ const expr = value.expression;
8477
+ // Valid patterns:
8478
+ // - callbacks={callbacks}
8479
+ // - callbacks={props.callbacks}
8480
+ // - callbacks={restProps.callbacks}
8481
+ const isValidPassthrough = (t.isIdentifier(expr) && expr.name === 'callbacks') ||
8482
+ (t.isMemberExpression(expr) &&
8483
+ t.isIdentifier(expr.property) &&
8484
+ expr.property.name === 'callbacks');
8485
+ if (!isValidPassthrough) {
8486
+ // Check for spreading pattern: {...callbacks, ...}
8487
+ if (t.isObjectExpression(expr)) {
8488
+ const hasSpread = expr.properties.some(prop => t.isSpreadElement(prop) &&
8489
+ t.isIdentifier(prop.argument) &&
8490
+ prop.argument.name === 'callbacks');
8491
+ if (hasSpread) {
8492
+ // Found spreading callbacks with additional properties
8493
+ const addedProps = expr.properties
8494
+ .filter(prop => !t.isSpreadElement(prop) && t.isObjectProperty(prop))
8495
+ .map(prop => {
8496
+ if (t.isObjectProperty(prop)) {
8497
+ if (t.isIdentifier(prop.key)) {
8498
+ return prop.key.name;
8499
+ }
8500
+ else if (t.isStringLiteral(prop.key)) {
8501
+ return prop.key.value;
8502
+ }
8503
+ }
8504
+ return 'unknown';
8505
+ });
8506
+ violations.push({
8507
+ rule: 'callbacks-passthrough-only',
8508
+ severity: 'critical',
8509
+ line: path.node.loc?.start.line || 0,
8510
+ column: path.node.loc?.start.column || 0,
8511
+ message: `Callbacks must be passed through unchanged. Found spreading with additional properties: ${addedProps.join(', ')}. Component events should be passed as direct props, not added to callbacks.`,
8512
+ suggestion: {
8513
+ text: `The callbacks prop should only contain OpenEntityRecord and RegisterMethod. Pass component events as separate props.`,
8514
+ example: `// ❌ WRONG - Modifying callbacks
8515
+ <ChildComponent
8516
+ callbacks={{ ...callbacks, onOpen: handleOpen }}
8517
+ />
8518
+
8519
+ // ✅ CORRECT - Pass callbacks unchanged, events as props
8520
+ <ChildComponent
8521
+ callbacks={callbacks}
8522
+ onOpen={handleOpen}
8523
+ />`
8524
+ }
8525
+ });
8526
+ }
8527
+ else if (expr.properties.length > 0) {
8528
+ // Creating new callbacks object
8529
+ violations.push({
8530
+ rule: 'callbacks-passthrough-only',
8531
+ severity: 'critical',
8532
+ line: path.node.loc?.start.line || 0,
8533
+ column: path.node.loc?.start.column || 0,
8534
+ message: `Callbacks must be passed through unchanged. Do not create new callback objects. Pass the callbacks prop directly.`,
8535
+ suggestion: {
8536
+ text: `Pass callbacks directly without modification.`,
8537
+ example: `// ❌ WRONG - Creating new callbacks object
8538
+ <ChildComponent
8539
+ callbacks={{ OpenEntityRecord: customHandler }}
8540
+ />
8541
+
8542
+ // ✅ CORRECT - Pass callbacks unchanged
8543
+ <ChildComponent
8544
+ callbacks={callbacks}
8545
+ />`
8546
+ }
8547
+ });
8548
+ }
8549
+ }
8550
+ // Check for conditional expressions
8551
+ else if (t.isConditionalExpression(expr) || t.isLogicalExpression(expr)) {
8552
+ violations.push({
8553
+ rule: 'callbacks-passthrough-only',
8554
+ severity: 'medium',
8555
+ line: path.node.loc?.start.line || 0,
8556
+ column: path.node.loc?.start.column || 0,
8557
+ message: `Callbacks should be passed through directly without conditional logic. Consider handling the condition at a higher level.`,
8558
+ suggestion: {
8559
+ text: `Pass callbacks directly or handle conditions in parent component.`,
8560
+ example: `// ⚠️ AVOID - Conditional callbacks
8561
+ <ChildComponent
8562
+ callbacks={someCondition ? callbacks : undefined}
8563
+ />
8564
+
8565
+ // ✅ BETTER - Pass callbacks directly
8566
+ <ChildComponent
8567
+ callbacks={callbacks}
8568
+ />`
8569
+ }
8570
+ });
8571
+ }
8572
+ // Check for function calls or other expressions
8573
+ else if (!t.isIdentifier(expr) && !t.isMemberExpression(expr)) {
8574
+ violations.push({
8575
+ rule: 'callbacks-passthrough-only',
8576
+ severity: 'critical',
8577
+ line: path.node.loc?.start.line || 0,
8578
+ column: path.node.loc?.start.column || 0,
8579
+ message: `Callbacks must be passed through unchanged. Found complex expression instead of direct passthrough.`,
8580
+ suggestion: {
8581
+ text: `Pass the callbacks prop directly without modification.`,
8582
+ example: `// ✅ CORRECT
8583
+ <ChildComponent callbacks={callbacks} />`
8584
+ }
8585
+ });
8586
+ }
8587
+ }
8588
+ }
8589
+ }
8590
+ },
8591
+ // Also check for Object.assign or spread operations on callbacks
8592
+ CallExpression(path) {
8593
+ // Check for Object.assign(callbacks, ...)
8594
+ if (t.isMemberExpression(path.node.callee) &&
8595
+ t.isIdentifier(path.node.callee.object) &&
8596
+ path.node.callee.object.name === 'Object' &&
8597
+ t.isIdentifier(path.node.callee.property) &&
8598
+ path.node.callee.property.name === 'assign') {
8599
+ const args = path.node.arguments;
8600
+ if (args.length > 0) {
8601
+ // Check if callbacks is being modified
8602
+ const hasCallbacks = args.some(arg => t.isIdentifier(arg) && arg.name === 'callbacks');
8603
+ if (hasCallbacks) {
8604
+ violations.push({
8605
+ rule: 'callbacks-passthrough-only',
8606
+ severity: 'critical',
8607
+ line: path.node.loc?.start.line || 0,
8608
+ column: path.node.loc?.start.column || 0,
8609
+ message: `Do not modify callbacks with Object.assign. Callbacks should be passed through unchanged.`,
8610
+ suggestion: {
8611
+ text: `Pass callbacks directly and use separate props for component events.`,
8612
+ example: `// ❌ WRONG
8613
+ const modifiedCallbacks = Object.assign({}, callbacks, { onOpen: handler });
8614
+
8615
+ // ✅ CORRECT - Keep callbacks separate from events
8616
+ <Component callbacks={callbacks} onOpen={handler} />`
8617
+ }
8618
+ });
8619
+ }
8620
+ }
8621
+ }
8622
+ },
8623
+ // Check for variable assignments that modify callbacks
8624
+ VariableDeclarator(path) {
8625
+ if (t.isObjectExpression(path.node.init)) {
8626
+ const hasCallbacksSpread = path.node.init.properties.some(prop => t.isSpreadElement(prop) &&
8627
+ t.isIdentifier(prop.argument) &&
8628
+ prop.argument.name === 'callbacks');
8629
+ if (hasCallbacksSpread) {
8630
+ const hasAdditionalProps = path.node.init.properties.some(prop => !t.isSpreadElement(prop));
8631
+ if (hasAdditionalProps) {
8632
+ violations.push({
8633
+ rule: 'callbacks-passthrough-only',
8634
+ severity: 'critical',
8635
+ line: path.node.loc?.start.line || 0,
8636
+ column: path.node.loc?.start.column || 0,
8637
+ message: `Do not create modified copies of callbacks. Pass callbacks unchanged and use separate props for events.`,
8638
+ suggestion: {
8639
+ text: `Keep callbacks immutable and pass component events as separate props.`,
8640
+ example: `// ❌ WRONG
8641
+ const extendedCallbacks = { ...callbacks, onCustomEvent: handler };
8642
+
8643
+ // ✅ CORRECT - Keep them separate
8644
+ // Pass to child component:
8645
+ <Component callbacks={callbacks} onCustomEvent={handler} />`
8646
+ }
8647
+ });
8648
+ }
8649
+ }
8650
+ }
8651
+ }
8652
+ });
8653
+ return violations;
8654
+ }
8463
8655
  }
8464
8656
  ];
8465
8657
  //# sourceMappingURL=component-linter.js.map