@foldkit/oxlint-plugin 0.11.0 → 0.12.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 (38) hide show
  1. package/all.json +26 -2
  2. package/dist/guards.d.ts +25 -7
  3. package/dist/guards.d.ts.map +1 -1
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1640 -288
  7. package/dist/message.d.ts +4 -2
  8. package/dist/message.d.ts.map +1 -1
  9. package/dist/rules/command-binding-matches-name.d.ts.map +1 -1
  10. package/dist/rules/command-define-pascal-const.d.ts.map +1 -1
  11. package/dist/rules/got-prefix-requires-submodel-payload.d.ts.map +1 -1
  12. package/dist/rules/got-submodel-message-name.d.ts.map +1 -1
  13. package/dist/rules/got-wrapper-carries-only-routing.d.ts.map +1 -1
  14. package/dist/rules/keyed-required-for-mapped-rows.d.ts.map +1 -1
  15. package/dist/rules/lazy-view-stable-references.d.ts.map +1 -1
  16. package/dist/rules/mount-factory-must-use-element.d.ts.map +1 -1
  17. package/dist/rules/no-array-index-view-keys.d.ts.map +1 -1
  18. package/dist/rules/no-child-message-construction-in-root.d.ts.map +1 -1
  19. package/dist/rules/no-disabling-dev-guardrails.d.ts.map +1 -1
  20. package/dist/rules/no-duplicate-onmount-per-element.d.ts.map +1 -1
  21. package/dist/rules/no-empty-children-array.d.ts.map +1 -1
  22. package/dist/rules/no-empty-commands-array.d.ts.map +1 -1
  23. package/dist/rules/no-empty-object-tagged-call.d.ts.map +1 -1
  24. package/dist/rules/no-empty-to-parent-out-message.d.ts.map +1 -1
  25. package/dist/rules/no-hardcoded-route-strings.d.ts.map +1 -1
  26. package/dist/rules/no-impure-call-at-decision-time.d.ts +7 -0
  27. package/dist/rules/no-impure-call-at-decision-time.d.ts.map +1 -0
  28. package/dist/rules/no-nonportable-server-globals.d.ts.map +1 -1
  29. package/dist/rules/no-noop-message.d.ts.map +1 -1
  30. package/dist/rules/no-raw-dom-event-attributes.d.ts.map +1 -1
  31. package/dist/rules/no-spread-in-evo.d.ts.map +1 -1
  32. package/dist/rules/prefer-effect-module-names.d.ts +3 -0
  33. package/dist/rules/prefer-effect-module-names.d.ts.map +1 -0
  34. package/dist/rules/require-rel-for-external-link.d.ts.map +1 -1
  35. package/dist/rules/selection-submodel-factory-at-module-scope.d.ts.map +1 -1
  36. package/dist/rules/wrap-child-output-in-got-message.d.ts.map +1 -1
  37. package/package.json +1 -1
  38. package/recommended.json +26 -2
package/dist/index.js CHANGED
@@ -8300,7 +8300,7 @@ var Objects = class _Objects extends Base2 {
8300
8300
  if (!hasProperties && !indexCount) {
8301
8301
  return fromRefinement(ast, isNotNullish);
8302
8302
  }
8303
- let properties;
8303
+ let properties2;
8304
8304
  let indexes;
8305
8305
  const finishIndex = (s, key, k2, inputValue, exitValue) => {
8306
8306
  if (exitValue._tag === "Failure") {
@@ -8339,8 +8339,8 @@ var Objects = class _Objects extends Base2 {
8339
8339
  step: (_s, _, exit3) => exit3._tag === "Failure" ? exit3 : void 0
8340
8340
  }) : void 0;
8341
8341
  const compileMembers = () => {
8342
- if (!properties) {
8343
- properties = ast.propertySignatures.map((ps) => ({
8342
+ if (!properties2) {
8343
+ properties2 = ast.propertySignatures.map((ps) => ({
8344
8344
  parser: compileConstructorDefault2(ps.type),
8345
8345
  name: ps.name,
8346
8346
  type: ps.type
@@ -8351,7 +8351,7 @@ var Objects = class _Objects extends Base2 {
8351
8351
  parserValue: compileConstructorDefault2(is2.type)
8352
8352
  })) : void 0;
8353
8353
  }
8354
- return properties;
8354
+ return properties2;
8355
8355
  };
8356
8356
  const fallback = fnUntracedEager2(function* (input, options) {
8357
8357
  if (input === missing) {
@@ -8401,7 +8401,7 @@ var Objects = class _Objects extends Base2 {
8401
8401
  }
8402
8402
  const concurrency = resolveConcurrency(options?.concurrency);
8403
8403
  if (hasProperties) {
8404
- const eff = parseProperties(state, properties, concurrency);
8404
+ const eff = parseProperties(state, properties2, concurrency);
8405
8405
  if (eff) yield* eff;
8406
8406
  }
8407
8407
  if (indexCount && !concurrency) {
@@ -8444,12 +8444,12 @@ var Objects = class _Objects extends Base2 {
8444
8444
  });
8445
8445
  if (indexCount) return fallback;
8446
8446
  const resume = (state, index, pending) => {
8447
- const property = properties[index];
8447
+ const property = properties2[index];
8448
8448
  return flatMap5(exit2(pending), (exit3) => {
8449
8449
  const terminal = stepProperty(state, property, exit3);
8450
8450
  if (terminal) return terminal;
8451
8451
  const done4 = () => succeed6(state.out);
8452
- const eff = parseProperties(state, properties.slice(index + 1));
8452
+ const eff = parseProperties(state, properties2.slice(index + 1));
8453
8453
  return eff ? flatMapEager2(eff, done4) : done4();
8454
8454
  });
8455
8455
  };
@@ -10387,11 +10387,13 @@ var isPunctuator = dual(2, (token, value) => token.type === "Punctuator" && toke
10387
10387
 
10388
10388
  // src/guards.ts
10389
10389
  var isIdentifier = (node, name) => typeof node === "object" && node !== null && "type" in node && node.type === "Identifier" && "name" in node && typeof node.name === "string" && (name === void 0 || node.name === name);
10390
+ var isIdentifierReference = (node) => isIdentifier(node);
10390
10391
  var isStringLiteral = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "Literal" && "value" in node && typeof node.value === "string";
10391
10392
  var isTemplateLiteral = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "TemplateLiteral";
10392
10393
  var isCallExpression = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "CallExpression";
10393
10394
  var isMemberExpression = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "MemberExpression";
10394
10395
  var isObjectExpression = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "ObjectExpression";
10396
+ var isObjectProperty = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "Property";
10395
10397
  var isArrayExpression = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "ArrayExpression";
10396
10398
  var isSpreadElement = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "SpreadElement";
10397
10399
  var helperCalleeName = (callee) => {
@@ -10403,6 +10405,31 @@ var helperCalleeName = (callee) => {
10403
10405
  }
10404
10406
  return Option_exports.none();
10405
10407
  };
10408
+ var isTransparentExpression = (node) => typeof node === "object" && node !== null && "type" in node && (node.type === "ChainExpression" || node.type === "ParenthesizedExpression" || node.type === "TSAsExpression" || node.type === "TSInstantiationExpression" || node.type === "TSNonNullExpression" || node.type === "TSSatisfiesExpression" || node.type === "TSTypeAssertion");
10409
+ var innermostExpression = (node) => isTransparentExpression(node) ? innermostExpression(node.expression) : node;
10410
+ var isTSQualifiedName = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "TSQualifiedName";
10411
+ var staticMemberPath = (node) => {
10412
+ const expression = innermostExpression(node);
10413
+ if (isIdentifierReference(expression)) {
10414
+ return Option_exports.some({ root: expression, members: [] });
10415
+ }
10416
+ if (isTSQualifiedName(expression)) {
10417
+ return Option_exports.map(staticMemberPath(expression.left), (path) => ({
10418
+ root: path.root,
10419
+ members: [...path.members, expression.right.name]
10420
+ }));
10421
+ }
10422
+ if (!isMemberExpression(expression)) {
10423
+ return Option_exports.none();
10424
+ }
10425
+ return Option_exports.flatMap(
10426
+ staticMemberPath(expression.object),
10427
+ (path) => Option_exports.map(staticMemberName(expression), (member) => ({
10428
+ root: path.root,
10429
+ members: [...path.members, member]
10430
+ }))
10431
+ );
10432
+ };
10406
10433
  var calleeMatchesHelperName = (callee, helperName) => Option_exports.exists(helperCalleeName(callee), (name) => name === helperName);
10407
10434
  var staticStringValue = (node) => {
10408
10435
  if (isStringLiteral(node)) {
@@ -10416,6 +10443,152 @@ var staticStringValue = (node) => {
10416
10443
  }
10417
10444
  return Option_exports.none();
10418
10445
  };
10446
+ var staticMemberName = (node) => {
10447
+ if (!node.computed && isIdentifier(node.property)) {
10448
+ return Option_exports.some(node.property.name);
10449
+ }
10450
+ return staticStringValue(node.property);
10451
+ };
10452
+ var staticPropertyName = (property) => {
10453
+ if (!property.computed && isIdentifier(property.key)) {
10454
+ return Option_exports.some(property.key.name);
10455
+ }
10456
+ return staticStringValue(property.key);
10457
+ };
10458
+ var indexReferences = (scopes) => {
10459
+ const references = /* @__PURE__ */ new WeakMap();
10460
+ for (const scope3 of scopes) {
10461
+ for (const reference of scope3.references) {
10462
+ references.set(reference.identifier, reference);
10463
+ }
10464
+ }
10465
+ return references;
10466
+ };
10467
+ var resolvedVariable = (references, node) => Option_exports.flatMap(
10468
+ Option_exports.fromNullishOr(references.get(node)),
10469
+ (reference) => Option_exports.fromNullishOr(reference.resolved)
10470
+ );
10471
+ var importedName = (specifier) => specifier.imported.type === "Identifier" ? specifier.imported.name : specifier.imported.value;
10472
+ var resolveImportedPath = (references, node) => Option_exports.gen(function* () {
10473
+ const path = yield* staticMemberPath(node);
10474
+ const variable = yield* resolvedVariable(references, path.root);
10475
+ const definition = yield* Array_exports.findFirst(
10476
+ variable.defs,
10477
+ (definition2) => definition2.type === "ImportBinding"
10478
+ );
10479
+ if (definition.parent?.type !== "ImportDeclaration") {
10480
+ return yield* Option_exports.none();
10481
+ }
10482
+ const localMembers = [path.root.name, ...path.members];
10483
+ if (definition.node.type === "ImportNamespaceSpecifier") {
10484
+ return {
10485
+ source: definition.parent.source.value,
10486
+ members: path.members,
10487
+ localMembers
10488
+ };
10489
+ }
10490
+ if (definition.node.type !== "ImportSpecifier") {
10491
+ return yield* Option_exports.none();
10492
+ }
10493
+ return {
10494
+ source: definition.parent.source.value,
10495
+ members: [importedName(definition.node), ...path.members],
10496
+ localMembers
10497
+ };
10498
+ });
10499
+ var foldkitNamespaceBySource = {
10500
+ "foldkit/command": "Command",
10501
+ "foldkit/html": "Html",
10502
+ "foldkit/managedResource": "ManagedResource",
10503
+ "foldkit/message": "Message",
10504
+ "foldkit/mount": "Mount",
10505
+ "foldkit/navigation": "Navigation",
10506
+ "foldkit/route": "Route",
10507
+ "foldkit/runtime": "Runtime",
10508
+ "foldkit/schema": "Schema",
10509
+ "foldkit/struct": "Struct",
10510
+ "foldkit/submodel": "Submodel",
10511
+ "foldkit/subscription": "Subscription"
10512
+ };
10513
+ var resolveFoldkitApiPath = (references, node) => Option_exports.flatMap(resolveImportedPath(references, node), (path) => {
10514
+ if (path.source === "foldkit") {
10515
+ return Option_exports.some(path.members);
10516
+ }
10517
+ const namespace = foldkitNamespaceBySource[path.source];
10518
+ return namespace === void 0 ? Option_exports.none() : Option_exports.some([namespace, ...path.members]);
10519
+ });
10520
+ var isTypeAnnotatedIdentifier = (node) => isIdentifier(node);
10521
+ var isFunctionWithParameters = (node) => typeof node === "object" && node !== null && "type" in node && (node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression");
10522
+ var isFoldkitDefineViewCallback = (references, functionNode) => {
10523
+ const parent = functionNode.parent;
10524
+ if (!isCallExpression(parent) || !parent.arguments.includes(functionNode)) {
10525
+ return false;
10526
+ }
10527
+ return Option_exports.exists(
10528
+ resolveFoldkitApiPath(references, parent.callee),
10529
+ (path) => {
10530
+ const [namespace, helperName, extraMember] = path;
10531
+ return namespace === "Submodel" && helperName === "defineView" && extraMember === void 0;
10532
+ }
10533
+ );
10534
+ };
10535
+ var hasHtmlBuilderTypeAnnotation = (references, identifier2) => {
10536
+ const typeAnnotation = identifier2.typeAnnotation?.typeAnnotation;
10537
+ if (typeAnnotation?.type !== "TSTypeReference") {
10538
+ return false;
10539
+ }
10540
+ return Option_exports.exists(
10541
+ resolveFoldkitApiPath(references, typeAnnotation.typeName),
10542
+ (path) => {
10543
+ const [namespace, typeName, extraMember] = path;
10544
+ return namespace === "Html" && typeName === "HtmlBuilder" && extraMember === void 0;
10545
+ }
10546
+ );
10547
+ };
10548
+ var isHtmlBuilderParameter = (references, root) => Option_exports.exists(
10549
+ resolvedVariable(references, root),
10550
+ (variable) => variable.defs.some((definition) => {
10551
+ if (definition.type !== "Parameter" || !isTypeAnnotatedIdentifier(definition.name)) {
10552
+ return false;
10553
+ }
10554
+ if (hasHtmlBuilderTypeAnnotation(references, definition.name)) {
10555
+ return true;
10556
+ }
10557
+ if (!isFunctionWithParameters(definition.node)) {
10558
+ return false;
10559
+ }
10560
+ return Option_exports.exists(
10561
+ Array_exports.last(definition.node.params),
10562
+ (parameter) => parameter === definition.name
10563
+ ) && isFoldkitDefineViewCallback(references, definition.node);
10564
+ })
10565
+ );
10566
+ var isFoldkitHtmlBuilderMember = (callee, memberName, references) => {
10567
+ if (references === void 0) {
10568
+ return calleeMatchesHelperName(callee, memberName);
10569
+ }
10570
+ const isFoldkitInertHtmlMember = Option_exports.exists(
10571
+ resolveFoldkitApiPath(references, callee),
10572
+ (path) => {
10573
+ const [namespace, builderName, importedMember, extraImportedMember] = path;
10574
+ return namespace === "Html" && builderName === "inertHtml" && importedMember === memberName && extraImportedMember === void 0;
10575
+ }
10576
+ );
10577
+ if (isFoldkitInertHtmlMember) {
10578
+ return true;
10579
+ }
10580
+ return Option_exports.exists(staticMemberPath(callee), (path) => {
10581
+ const [member, extraMember] = path.members;
10582
+ return member === memberName && extraMember === void 0 && isHtmlBuilderParameter(references, path.root);
10583
+ });
10584
+ };
10585
+ var isUnshadowedReference = (references, node) => {
10586
+ if (references === void 0) {
10587
+ return true;
10588
+ }
10589
+ const reference = references.get(node);
10590
+ return reference !== void 0 && (reference.resolved === null || Array_exports.isArrayEmpty(reference.resolved.defs));
10591
+ };
10419
10592
  var isVariableDeclarator = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "VariableDeclarator";
10420
10593
  var isVariableDeclaration = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "VariableDeclaration";
10421
10594
  var isProgram = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "Program";
@@ -10425,14 +10598,23 @@ var firstStringArgument = (node) => {
10425
10598
  };
10426
10599
 
10427
10600
  // src/rules/command-binding-matches-name.ts
10428
- var innerCommandDefineCall = (node) => {
10601
+ var isCommandDefineCall = (node, references) => {
10602
+ if (references === void 0) {
10603
+ return AST_exports.isCallOf(node, "Command", "define");
10604
+ }
10605
+ return Option_exports.exists(resolveFoldkitApiPath(references, node.callee), (path) => {
10606
+ const [namespace, methodName, extraMember] = path;
10607
+ return namespace === "Command" && methodName === "define" && extraMember === void 0;
10608
+ });
10609
+ };
10610
+ var innerCommandDefineCall = (node, references) => {
10429
10611
  if (!isCallExpression(node)) return void 0;
10430
- if (AST_exports.isCallOf(node, "Command", "define")) {
10612
+ if (isCommandDefineCall(node, references)) {
10431
10613
  return node;
10432
10614
  }
10433
10615
  const callee = node.callee;
10434
10616
  if (!isCallExpression(callee)) return void 0;
10435
- if (!AST_exports.isCallOf(callee, "Command", "define")) return void 0;
10617
+ if (!isCommandDefineCall(callee, references)) return void 0;
10436
10618
  return callee;
10437
10619
  };
10438
10620
  var commandBindingMatchesName = Rule_exports.define({
@@ -10443,12 +10625,14 @@ var commandBindingMatchesName = Rule_exports.define({
10443
10625
  }),
10444
10626
  create: function* () {
10445
10627
  const ctx = yield* RuleContext;
10628
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
10629
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
10446
10630
  return {
10447
10631
  VariableDeclarator: (node) => {
10448
10632
  if (!isVariableDeclarator(node)) return Effect_exports.void;
10449
10633
  const init2 = node.init;
10450
10634
  if (init2 === null || init2 === void 0) return Effect_exports.void;
10451
- const innerCall = innerCommandDefineCall(init2);
10635
+ const innerCall = innerCommandDefineCall(init2, references);
10452
10636
  if (innerCall === void 0) return Effect_exports.void;
10453
10637
  const nameArgument = firstStringArgument(innerCall);
10454
10638
  if (nameArgument === void 0 || !isIdentifier(node.id) || node.id.name === nameArgument.value) {
@@ -10477,21 +10661,30 @@ var nearestVariableDeclarator = (node) => {
10477
10661
  }
10478
10662
  return "parent" in node ? nearestVariableDeclarator(node.parent) : Option_exports.none();
10479
10663
  };
10480
- var headCommandDefineCall = (node) => {
10664
+ var isCommandDefineCall2 = (node, references) => {
10665
+ if (references === void 0) {
10666
+ return AST_exports.isCallOf(node, "Command", "define");
10667
+ }
10668
+ return Option_exports.exists(resolveFoldkitApiPath(references, node.callee), (path) => {
10669
+ const [namespace, methodName, extraMember] = path;
10670
+ return namespace === "Command" && methodName === "define" && extraMember === void 0;
10671
+ });
10672
+ };
10673
+ var headCommandDefineCall = (node, references) => {
10481
10674
  if (!isCallExpression(node)) {
10482
10675
  return Option_exports.none();
10483
10676
  }
10484
- if (AST_exports.isCallOf(node, "Command", "define")) {
10677
+ if (isCommandDefineCall2(node, references)) {
10485
10678
  return Option_exports.some(node);
10486
10679
  }
10487
- return headCommandDefineCall(node.callee);
10680
+ return headCommandDefineCall(node.callee, references);
10488
10681
  };
10489
10682
  var missingLiteralNameMessage = "Command.define needs a literal string name as its first argument. The name is the Command's identity and cannot be computed.";
10490
10683
  var nonPascalCaseMessage = (name) => `Command.define('${name}', ...) must use a PascalCase name, like FetchWeather or FocusInput.`;
10491
10684
  var notAssignedMessage = (name) => `Command.define('${name}', ...) must be assigned to a PascalCase const, never inlined in a pipe or expression. Write const ${name} = Command.define('${name}', ...).`;
10492
10685
  var mismatchedConstMessage = (name, actualName) => `Command.define('${name}', ...) should be assigned to a const named ${name}, not ${actualName}. The const name mirrors the Command identity.`;
10493
10686
  var notConstMessage = (name) => `Command.define('${name}', ...) must be assigned to a const, not let or var. Write const ${name} = Command.define('${name}', ...).`;
10494
- var diagnosticMessage = (node) => {
10687
+ var diagnosticMessage = (node, references) => {
10495
10688
  const [firstArgument] = node.arguments;
10496
10689
  if (!isStringLiteral(firstArgument)) {
10497
10690
  return Option_exports.some(missingLiteralNameMessage);
@@ -10504,7 +10697,7 @@ var diagnosticMessage = (node) => {
10504
10697
  onNone: () => Option_exports.some(notAssignedMessage(name)),
10505
10698
  onSome: (declarator) => {
10506
10699
  const headsInitializer = Option_exports.exists(
10507
- headCommandDefineCall(declarator.init),
10700
+ headCommandDefineCall(declarator.init, references),
10508
10701
  (call) => call === node
10509
10702
  );
10510
10703
  if (!headsInitializer) {
@@ -10528,12 +10721,14 @@ var commandDefinePascalConst = Rule_exports.define({
10528
10721
  }),
10529
10722
  create: function* () {
10530
10723
  const ctx = yield* RuleContext;
10724
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
10725
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
10531
10726
  return {
10532
10727
  CallExpression: (node) => {
10533
- if (!isCallExpression(node) || !AST_exports.isCallOf(node, "Command", "define")) {
10728
+ if (!isCallExpression(node) || !isCommandDefineCall2(node, references)) {
10534
10729
  return Effect_exports.void;
10535
10730
  }
10536
- return Option_exports.match(diagnosticMessage(node), {
10731
+ return Option_exports.match(diagnosticMessage(node, references), {
10537
10732
  onNone: () => Effect_exports.void,
10538
10733
  onSome: (message) => ctx.report(Diagnostic_exports.make({ node, message }))
10539
10734
  });
@@ -10544,18 +10739,6 @@ var commandDefinePascalConst = Rule_exports.define({
10544
10739
 
10545
10740
  // src/message.ts
10546
10741
  var foldkitMessageModule = "foldkit/message";
10547
- var staticPropertyName = (property) => {
10548
- if (property.type !== "Property") {
10549
- return Option_exports.none();
10550
- }
10551
- if (!property.computed && isIdentifier(property.key)) {
10552
- return Option_exports.some({ name: property.key.name, node: property.key });
10553
- }
10554
- if (isStringLiteral(property.key)) {
10555
- return Option_exports.some({ name: property.key.value, node: property.key });
10556
- }
10557
- return Option_exports.none();
10558
- };
10559
10742
  var recordFoldkitMessageUnionBindings = (bindings, node) => {
10560
10743
  if (node.type !== "Program") {
10561
10744
  return;
@@ -10571,8 +10754,17 @@ var recordFoldkitMessageUnionBindings = (bindings, node) => {
10571
10754
  }
10572
10755
  }
10573
10756
  };
10574
- var messageCases = (node, bindings) => {
10575
- if (!isIdentifier(node.callee) || !bindings.has(node.callee.name)) {
10757
+ var isFoldkitMessageUnionCall = (node, bindings, references) => {
10758
+ if (references === void 0) {
10759
+ return isIdentifier(node.callee) && bindings.has(node.callee.name);
10760
+ }
10761
+ return Option_exports.exists(resolveFoldkitApiPath(references, node.callee), (path) => {
10762
+ const [namespace, helperName, extraMember] = path;
10763
+ return namespace === "Message" && helperName === "defineMessageUnion" && extraMember === void 0;
10764
+ });
10765
+ };
10766
+ var messageCases = (node, bindings, references) => {
10767
+ if (!isFoldkitMessageUnionCall(node, bindings, references)) {
10576
10768
  return [];
10577
10769
  }
10578
10770
  const [casesByTag] = node.arguments;
@@ -10580,14 +10772,17 @@ var messageCases = (node, bindings) => {
10580
10772
  return [];
10581
10773
  }
10582
10774
  return casesByTag.properties.flatMap((property) => {
10775
+ if (property.type !== "Property") {
10776
+ return [];
10777
+ }
10583
10778
  const maybeName = staticPropertyName(property);
10584
- if (property.type !== "Property" || Option_exports.isNone(maybeName) || !isObjectExpression(property.value)) {
10779
+ if (Option_exports.isNone(maybeName) || !isObjectExpression(property.value)) {
10585
10780
  return [];
10586
10781
  }
10587
10782
  return [
10588
10783
  {
10589
- name: maybeName.value.name,
10590
- nameNode: maybeName.value.node,
10784
+ name: maybeName.value,
10785
+ nameNode: property.key,
10591
10786
  fields: property.value
10592
10787
  }
10593
10788
  ];
@@ -10596,6 +10791,38 @@ var messageCases = (node, bindings) => {
10596
10791
  var hasMessagePayloadProperty = (fields) => fields.properties.some(
10597
10792
  (property) => property.type === "Property" && (isIdentifier(property.key, "message") || isStringLiteral(property.key) && property.key.value === "message")
10598
10793
  );
10794
+ var containsImportedMessageReference = (node, references, visited) => {
10795
+ if (typeof node !== "object" || node === null || visited.has(node)) {
10796
+ return false;
10797
+ }
10798
+ visited.add(node);
10799
+ if (Option_exports.exists(resolveImportedPath(references, node), (path) => {
10800
+ const [messageName] = path.members.slice(-1);
10801
+ return messageName === "Message";
10802
+ })) {
10803
+ return true;
10804
+ }
10805
+ return Object.entries(node).some(
10806
+ ([key, value]) => key !== "parent" && (Array.isArray(value) ? value.some(
10807
+ (element) => containsImportedMessageReference(element, references, visited)
10808
+ ) : containsImportedMessageReference(value, references, visited))
10809
+ );
10810
+ };
10811
+ var hasSubmodelMessagePayload = (fields, references) => {
10812
+ if (references === void 0) {
10813
+ return hasMessagePayloadProperty(fields);
10814
+ }
10815
+ return fields.properties.some((property) => {
10816
+ if (property.type !== "Property" || !(isIdentifier(property.key, "message") || isStringLiteral(property.key) && property.key.value === "message")) {
10817
+ return false;
10818
+ }
10819
+ return containsImportedMessageReference(
10820
+ property.value,
10821
+ references,
10822
+ /* @__PURE__ */ new WeakSet()
10823
+ );
10824
+ });
10825
+ };
10599
10826
 
10600
10827
  // src/rules/got-prefix-requires-submodel-payload.ts
10601
10828
  var gotPrefixRequiresSubmodelPayload = Rule_exports.define({
@@ -10606,6 +10833,8 @@ var gotPrefixRequiresSubmodelPayload = Rule_exports.define({
10606
10833
  }),
10607
10834
  create: function* () {
10608
10835
  const ctx = yield* RuleContext;
10836
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
10837
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
10609
10838
  const messageUnionBindings = /* @__PURE__ */ new Set();
10610
10839
  return {
10611
10840
  Program: (node) => {
@@ -10615,8 +10844,8 @@ var gotPrefixRequiresSubmodelPayload = Rule_exports.define({
10615
10844
  CallExpression: (node) => {
10616
10845
  if (!isCallExpression(node)) return Effect_exports.void;
10617
10846
  return Effect_exports.forEach(
10618
- messageCases(node, messageUnionBindings),
10619
- (messageCase) => /^Got[A-Z]/.test(messageCase.name) && !hasMessagePayloadProperty(messageCase.fields) ? ctx.report(
10847
+ messageCases(node, messageUnionBindings, references),
10848
+ (messageCase) => /^Got[A-Z]/.test(messageCase.name) && !hasSubmodelMessagePayload(messageCase.fields, references) ? ctx.report(
10620
10849
  Diagnostic_exports.make({
10621
10850
  node: messageCase.nameNode,
10622
10851
  message: "Got* is reserved for Submodel wrappers. Add a { message: Child.Message } payload or choose a Message name that does not start with Got."
@@ -10638,6 +10867,8 @@ var gotSubmodelMessageName = Rule_exports.define({
10638
10867
  }),
10639
10868
  create: function* () {
10640
10869
  const ctx = yield* RuleContext;
10870
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
10871
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
10641
10872
  const messageUnionBindings = /* @__PURE__ */ new Set();
10642
10873
  return {
10643
10874
  Program: (node) => {
@@ -10647,8 +10878,8 @@ var gotSubmodelMessageName = Rule_exports.define({
10647
10878
  CallExpression: (node) => {
10648
10879
  if (!isCallExpression(node)) return Effect_exports.void;
10649
10880
  return Effect_exports.forEach(
10650
- messageCases(node, messageUnionBindings),
10651
- (messageCase) => hasMessagePayloadProperty(messageCase.fields) && !/^Got[A-Z].*Message$/.test(messageCase.name) ? ctx.report(
10881
+ messageCases(node, messageUnionBindings, references),
10882
+ (messageCase) => hasSubmodelMessagePayload(messageCase.fields, references) && !/^Got[A-Z].*Message$/.test(messageCase.name) ? ctx.report(
10652
10883
  Diagnostic_exports.make({
10653
10884
  node: messageCase.nameNode,
10654
10885
  message: "Submodel wrapper Messages should be named Got*Message so Foldkit DevTools can filter them."
@@ -10686,6 +10917,8 @@ var gotWrapperCarriesOnlyRouting = Rule_exports.define({
10686
10917
  }),
10687
10918
  create: function* () {
10688
10919
  const ctx = yield* RuleContext;
10920
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
10921
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
10689
10922
  const messageUnionBindings = /* @__PURE__ */ new Set();
10690
10923
  return {
10691
10924
  Program: (node) => {
@@ -10697,7 +10930,7 @@ var gotWrapperCarriesOnlyRouting = Rule_exports.define({
10697
10930
  return Effect_exports.void;
10698
10931
  }
10699
10932
  return Effect_exports.forEach(
10700
- messageCases(node, messageUnionBindings),
10933
+ messageCases(node, messageUnionBindings, references),
10701
10934
  (messageCase) => gotWrapperTagPattern.test(messageCase.name) ? Effect_exports.forEach(
10702
10935
  messageCase.fields.properties,
10703
10936
  (property) => pipe(
@@ -10741,7 +10974,33 @@ var isArrowFunctionExpression = (node) => typeof node === "object" && node !== n
10741
10974
  var isBlockStatement = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "BlockStatement";
10742
10975
  var isReturnStatement = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "ReturnStatement";
10743
10976
  var isObjectPattern = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "ObjectPattern";
10744
- var isSingleValueMapCallee = (callee) => isMemberExpression(callee) && !callee.computed && isIdentifier(callee.property, "map") && isIdentifier(callee.object) && singleValueMapNamespaces.includes(callee.object.name);
10977
+ var isSingleValueMapCallee = (callee, references) => {
10978
+ if (references === void 0) {
10979
+ return isMemberExpression(callee) && !callee.computed && isIdentifier(callee.property, "map") && isIdentifier(callee.object) && singleValueMapNamespaces.includes(callee.object.name);
10980
+ }
10981
+ return Option_exports.exists(resolveImportedPath(references, callee), (path) => {
10982
+ const isEffectModule = path.source === "effect" || path.source.startsWith("effect/");
10983
+ const members = path.source.startsWith("effect/") ? [path.source.slice("effect/".length), ...path.members] : path.members;
10984
+ const [namespace, methodName, extraMember] = members;
10985
+ return isEffectModule && namespace !== void 0 && singleValueMapNamespaces.includes(namespace) && methodName === "map" && extraMember === void 0;
10986
+ });
10987
+ };
10988
+ var isMapCallee = (callee, references) => {
10989
+ if (calleeMatchesHelperName(callee, "map")) {
10990
+ return true;
10991
+ }
10992
+ if (references === void 0) {
10993
+ return false;
10994
+ }
10995
+ return Option_exports.exists(resolveImportedPath(references, callee), (path) => {
10996
+ if (path.source !== "effect" && !path.source.startsWith("effect/")) {
10997
+ return false;
10998
+ }
10999
+ const members = path.source.startsWith("effect/") ? [path.source.slice("effect/".length), ...path.members] : path.members;
11000
+ const [namespace, methodName, extraMember] = members;
11001
+ return namespace === "Array" && methodName === "map" && extraMember === void 0;
11002
+ });
11003
+ };
10745
11004
  var arrowCallback = (node) => {
10746
11005
  const [firstArgument, secondArgument] = node.arguments;
10747
11006
  if (isArrowFunctionExpression(firstArgument)) {
@@ -10752,30 +11011,51 @@ var arrowCallback = (node) => {
10752
11011
  }
10753
11012
  return Option_exports.none();
10754
11013
  };
10755
- var referencesIdOfParameter = (value, parameterName) => {
11014
+ var referencesIdOfParameter = (value, parameterName, references, parameterVariable) => {
10756
11015
  if (Array_exports.isArray(value)) {
10757
11016
  return value.some(
10758
- (element) => referencesIdOfParameter(element, parameterName)
11017
+ (element) => referencesIdOfParameter(
11018
+ element,
11019
+ parameterName,
11020
+ references,
11021
+ parameterVariable
11022
+ )
10759
11023
  );
10760
11024
  }
10761
11025
  if (typeof value !== "object" || value === null) {
10762
11026
  return false;
10763
11027
  }
10764
- if (isMemberExpression(value) && isIdentifier(value.object, parameterName) && isIdentifier(value.property, "id")) {
11028
+ if (isMemberExpression(value) && isIdentifier(value.object, parameterName) && isIdentifier(value.property, "id") && (references === void 0 || parameterVariable !== void 0 && Option_exports.exists(
11029
+ resolvedVariable(references, value.object),
11030
+ (variable) => variable === parameterVariable
11031
+ ))) {
10765
11032
  return true;
10766
11033
  }
10767
11034
  const fieldEntries = Object.entries(value);
10768
11035
  return fieldEntries.some(
10769
- ([fieldName, fieldValue]) => fieldName !== "parent" && referencesIdOfParameter(fieldValue, parameterName)
11036
+ ([fieldName, fieldValue]) => fieldName !== "parent" && referencesIdOfParameter(
11037
+ fieldValue,
11038
+ parameterName,
11039
+ references,
11040
+ parameterVariable
11041
+ )
10770
11042
  );
10771
11043
  };
10772
11044
  var destructuresId = (pattern) => pattern.properties.some(
10773
11045
  (property) => typeof property === "object" && property !== null && "key" in property && isIdentifier(property.key, "id")
10774
11046
  );
10775
- var isIdentityBearing = (callback3) => {
11047
+ var isIdentityBearing = (callback3, references, declaredVariables) => {
10776
11048
  const [firstParameter] = callback3.params;
10777
11049
  if (isIdentifier(firstParameter)) {
10778
- return referencesIdOfParameter(callback3.body, firstParameter.name);
11050
+ const parameterVariable = declaredVariables.find(
11051
+ (variable) => variable.identifiers.some((identifier2) => identifier2 === firstParameter)
11052
+ );
11053
+ return referencesIdOfParameter(
11054
+ callback3.body,
11055
+ firstParameter.name,
11056
+ references,
11057
+ parameterVariable
11058
+ );
10779
11059
  }
10780
11060
  if (isObjectPattern(firstParameter)) {
10781
11061
  return destructuresId(firstParameter);
@@ -10794,26 +11074,29 @@ var callbackReturnExpression = (callback3) => {
10794
11074
  )
10795
11075
  );
10796
11076
  };
10797
- var isKeyedWrapped = (node) => isCallExpression(node.callee) && calleeMatchesHelperName(node.callee.callee, "keyed");
10798
- var hasKeyAttribute = (rowElementCall) => {
11077
+ var isKeyedWrapped = (node, references) => isCallExpression(node.callee) && isFoldkitHtmlBuilderMember(node.callee.callee, "keyed", references);
11078
+ var hasKeyAttribute = (rowElementCall, references) => {
10799
11079
  const [attributesArgument] = rowElementCall.arguments;
10800
11080
  if (!isArrayExpression(attributesArgument)) {
10801
11081
  return false;
10802
11082
  }
10803
11083
  return attributesArgument.elements.some(
10804
- (element) => isCallExpression(element) && calleeMatchesHelperName(element.callee, "Key")
11084
+ (element) => isCallExpression(element) && isFoldkitHtmlBuilderMember(element.callee, "Key", references)
10805
11085
  );
10806
11086
  };
10807
- var unkeyedRowElement = (returnExpression) => {
11087
+ var unkeyedRowElement = (returnExpression, references) => {
10808
11088
  if (!isCallExpression(returnExpression)) {
10809
11089
  return Option_exports.none();
10810
11090
  }
10811
- if (isKeyedWrapped(returnExpression) || hasKeyAttribute(returnExpression)) {
11091
+ if (isKeyedWrapped(returnExpression, references) || hasKeyAttribute(returnExpression, references)) {
10812
11092
  return Option_exports.none();
10813
11093
  }
10814
11094
  return pipe(
10815
11095
  helperCalleeName(returnExpression.callee),
10816
11096
  Option_exports.filter((tagName) => rowElementTagNames.includes(tagName)),
11097
+ Option_exports.filter(
11098
+ (tagName) => isFoldkitHtmlBuilderMember(returnExpression.callee, tagName, references)
11099
+ ),
10817
11100
  Option_exports.map((tagName) => ({ rowElementCall: returnExpression, tagName }))
10818
11101
  );
10819
11102
  };
@@ -10825,16 +11108,26 @@ var keyedRequiredForMappedRows = Rule_exports.define({
10825
11108
  }),
10826
11109
  create: function* () {
10827
11110
  const ctx = yield* RuleContext;
11111
+ const scopeManager = ctx.sourceCode.scopeManager;
11112
+ const references = scopeManager === void 0 ? void 0 : indexReferences(scopeManager.scopes);
10828
11113
  return {
10829
11114
  CallExpression: (node) => {
10830
- if (!isCallExpression(node) || !calleeMatchesHelperName(node.callee, "map") || isSingleValueMapCallee(node.callee)) {
11115
+ if (!isCallExpression(node) || !isMapCallee(node.callee, references) || isSingleValueMapCallee(node.callee, references)) {
10831
11116
  return Effect_exports.void;
10832
11117
  }
10833
11118
  return pipe(
10834
11119
  arrowCallback(node),
10835
- Option_exports.filter(isIdentityBearing),
11120
+ Option_exports.filter(
11121
+ (callback3) => isIdentityBearing(
11122
+ callback3,
11123
+ references,
11124
+ scopeManager?.getDeclaredVariables(callback3) ?? []
11125
+ )
11126
+ ),
10836
11127
  Option_exports.flatMap(callbackReturnExpression),
10837
- Option_exports.flatMap(unkeyedRowElement),
11128
+ Option_exports.flatMap(
11129
+ (returnExpression) => unkeyedRowElement(returnExpression, references)
11130
+ ),
10838
11131
  Option_exports.match({
10839
11132
  onNone: () => Effect_exports.void,
10840
11133
  onSome: ({ rowElementCall, tagName }) => ctx.report(
@@ -10877,16 +11170,19 @@ var childValuesOf = (node) => {
10877
11170
  Array_exports.flatMap(([key, value]) => key === "parent" ? [] : [value])
10878
11171
  );
10879
11172
  };
10880
- var matchLazyFactoryCall = (node) => {
11173
+ var matchLazyFactoryCall = (node, references) => {
10881
11174
  const unwrapped = unwrapExpression(node);
10882
11175
  if (unwrapped.type !== "CallExpression") {
10883
11176
  return Option_exports.none();
10884
11177
  }
10885
11178
  const callee = unwrapExpression(unwrapped.callee);
10886
- if (callee.type !== "Identifier" || !isLazyFactoryName(callee.name)) {
10887
- return Option_exports.none();
11179
+ if (references === void 0) {
11180
+ return callee.type === "Identifier" && isLazyFactoryName(callee.name) ? Option_exports.some({ call: unwrapped, factoryName: callee.name }) : Option_exports.none();
10888
11181
  }
10889
- return Option_exports.some({ call: unwrapped, factoryName: callee.name });
11182
+ return Option_exports.flatMap(resolveFoldkitApiPath(references, callee), (path) => {
11183
+ const [namespace, factoryName, extraMember] = path;
11184
+ return namespace === "Html" && factoryName !== void 0 && isLazyFactoryName(factoryName) && extraMember === void 0 ? Option_exports.some({ call: unwrapped, factoryName }) : Option_exports.none();
11185
+ });
10890
11186
  };
10891
11187
  var declarationOf = (statement) => {
10892
11188
  if (statement.type === "VariableDeclaration") {
@@ -10897,7 +11193,7 @@ var declarationOf = (statement) => {
10897
11193
  }
10898
11194
  return Option_exports.none();
10899
11195
  };
10900
- var registeredSlotsOf = (program) => pipe(
11196
+ var registeredSlotsOf = (program, references, scopeManager) => pipe(
10901
11197
  program.body,
10902
11198
  Array_exports.flatMap(
10903
11199
  (statement) => pipe(
@@ -10915,12 +11211,13 @@ var registeredSlotsOf = (program) => pipe(
10915
11211
  }
10916
11212
  const slotName = declarator.id.name;
10917
11213
  return pipe(
10918
- matchLazyFactoryCall(declarator.init),
11214
+ matchLazyFactoryCall(declarator.init, references),
10919
11215
  Option_exports.match({
10920
11216
  onNone: () => [],
10921
11217
  onSome: (factoryCall) => [
10922
11218
  {
10923
11219
  slotName,
11220
+ variable: scopeManager?.getDeclaredVariables(declarator).find((variable) => variable.name === slotName),
10924
11221
  viewArgumentIndex: VIEW_ARGUMENT_INDEX_BY_FACTORY[factoryCall.factoryName],
10925
11222
  initializerCall: factoryCall.call
10926
11223
  }
@@ -10965,12 +11262,16 @@ var functionBindingNames = (functionNode) => /* @__PURE__ */ new Set([
10965
11262
  ...bodyBindingNames(functionNode.body)
10966
11263
  ]);
10967
11264
  var isFunctionScopedName = (name, functionScopes) => functionScopes.some((scope3) => scope3.has(name));
11265
+ var isNestedInFunctionScope = (scope3) => scope3.type === "function" || scope3.upper !== null && isNestedInFunctionScope(scope3.upper);
11266
+ var isFunctionScopedView = (identifier2, context3) => context3.references === void 0 ? isFunctionScopedName(identifier2.name, context3.functionScopes) : Option_exports.exists(
11267
+ resolvedVariable(context3.references, identifier2),
11268
+ (variable) => isNestedInFunctionScope(variable.scope)
11269
+ );
10968
11270
  var MISPLACED_CREATION_MESSAGE = "`createLazy()` and `createKeyedLazy()` must be assigned directly to a module-scope `const`. A slot recreated inside a function starts with a cold cache on every call, so the memoization never hits.";
10969
11271
  var inlineViewFunctionMessage = (slotName) => `Lazy slot \`${slotName}\` is called with an inline view function. An inline function is a new reference on every render, so the cache never hits. Define the view function at module scope and pass its identifier.`;
10970
11272
  var functionScopedViewMessage = (slotName, viewName) => `Lazy slot \`${slotName}\` is called with \`${viewName}\`, which is bound inside an enclosing function. Function-scoped view functions get a fresh identity per render, so the cache never hits. Move \`${viewName}\` to module scope.`;
10971
11273
  var misplacedCreationOffenses = (node, context3) => {
10972
- const callee = unwrapExpression(node.callee);
10973
- if (callee.type !== "Identifier" || !isLazyFactoryName(callee.name)) {
11274
+ if (Option_exports.isNone(matchLazyFactoryCall(node, context3.references))) {
10974
11275
  return [];
10975
11276
  }
10976
11277
  if (context3.registeredInitializers.has(node)) {
@@ -10980,7 +11281,7 @@ var misplacedCreationOffenses = (node, context3) => {
10980
11281
  };
10981
11282
  var unstableViewOffenses = (node, context3) => {
10982
11283
  const callee = unwrapExpression(node.callee);
10983
- if (callee.type !== "Identifier") {
11284
+ if (!isIdentifierReference(callee)) {
10984
11285
  return [];
10985
11286
  }
10986
11287
  const maybeSlot = Option_exports.fromNullishOr(context3.slotsByName.get(callee.name));
@@ -10988,6 +11289,12 @@ var unstableViewOffenses = (node, context3) => {
10988
11289
  return [];
10989
11290
  }
10990
11291
  const { value: slot } = maybeSlot;
11292
+ if (context3.references !== void 0 && (slot.variable === void 0 || !Option_exports.exists(
11293
+ resolvedVariable(context3.references, callee),
11294
+ (variable) => variable === slot.variable
11295
+ ))) {
11296
+ return [];
11297
+ }
10991
11298
  const maybeViewArgument = Array_exports.get(node.arguments, slot.viewArgumentIndex);
10992
11299
  if (Option_exports.isNone(maybeViewArgument)) {
10993
11300
  return [];
@@ -11002,7 +11309,7 @@ var unstableViewOffenses = (node, context3) => {
11002
11309
  { node: viewArgument, message: inlineViewFunctionMessage(slot.slotName) }
11003
11310
  ];
11004
11311
  }
11005
- if (unwrappedViewArgument.type === "Identifier" && isFunctionScopedName(unwrappedViewArgument.name, context3.functionScopes)) {
11312
+ if (isIdentifierReference(unwrappedViewArgument) && isFunctionScopedView(unwrappedViewArgument, context3)) {
11006
11313
  return [
11007
11314
  {
11008
11315
  node: viewArgument,
@@ -11056,12 +11363,18 @@ var lazyViewStableReferences = Rule_exports.define({
11056
11363
  }),
11057
11364
  create: function* () {
11058
11365
  const ctx = yield* RuleContext;
11366
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
11367
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
11059
11368
  return {
11060
11369
  "Program:exit": (node) => {
11061
11370
  if (!isProgram2(node)) {
11062
11371
  return Effect_exports.void;
11063
11372
  }
11064
- const registeredSlots = registeredSlotsOf(node);
11373
+ const registeredSlots = registeredSlotsOf(
11374
+ node,
11375
+ references,
11376
+ ctx.sourceCode.scopeManager
11377
+ );
11065
11378
  const slotsByName = new Map(
11066
11379
  Array_exports.map(
11067
11380
  registeredSlots,
@@ -11074,7 +11387,8 @@ var lazyViewStableReferences = Rule_exports.define({
11074
11387
  const offenses = collectOffenses(node, {
11075
11388
  slotsByName,
11076
11389
  registeredInitializers,
11077
- functionScopes: []
11390
+ functionScopes: [],
11391
+ references
11078
11392
  });
11079
11393
  return Effect_exports.forEach(
11080
11394
  offenses,
@@ -11088,6 +11402,15 @@ var lazyViewStableReferences = Rule_exports.define({
11088
11402
 
11089
11403
  // src/rules/mount-factory-must-use-element.ts
11090
11404
  var MOUNT_DEFINITION_METHODS = ["define", "defineStream"];
11405
+ var isMountDefinitionCall = (node, references) => {
11406
+ if (references === void 0) {
11407
+ return AST_exports.isCallOf(node, "Mount", MOUNT_DEFINITION_METHODS);
11408
+ }
11409
+ return Option_exports.exists(resolveFoldkitApiPath(references, node.callee), (path) => {
11410
+ const [namespace, methodName, extraMember] = path;
11411
+ return namespace === "Mount" && methodName !== void 0 && MOUNT_DEFINITION_METHODS.includes(methodName) && extraMember === void 0;
11412
+ });
11413
+ };
11091
11414
  var ELEMENT_FIELD = "element";
11092
11415
  var NO_ELEMENT_BINDING_MESSAGE = `This Mount's \`execute\` never receives the element: it does not destructure \`element\` from its input. A Mount exists for element-caused, element-targeted work. If the element is irrelevant, use a Command, Subscription, or ManagedResource instead.`;
11093
11416
  var ignoredElementBindingMessage = (bindingName) => `The element binding \`${bindingName}\` is named as ignored. A Mount's \`execute\` must read or write its live element; if the element does not matter here, the side effect has a different cause and belongs in a Command, Subscription, or ManagedResource.`;
@@ -11205,9 +11528,11 @@ var mountFactoryMustUseElement = Rule_exports.define({
11205
11528
  }),
11206
11529
  create: function* () {
11207
11530
  const ctx = yield* RuleContext;
11531
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
11532
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
11208
11533
  return {
11209
11534
  CallExpression: (node) => {
11210
- if (!isCallExpression(node) || !AST_exports.isCallOf(node, "Mount", MOUNT_DEFINITION_METHODS)) {
11535
+ if (!isCallExpression(node) || !isMountDefinitionCall(node, references)) {
11211
11536
  return Effect_exports.void;
11212
11537
  }
11213
11538
  return Option_exports.match(executeFunction(node), {
@@ -11226,7 +11551,16 @@ var mountFactoryMustUseElement = Rule_exports.define({
11226
11551
  var isProperty = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "Property";
11227
11552
  var isArrowFunctionExpression2 = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "ArrowFunctionExpression";
11228
11553
  var isVariableDeclarator2 = (node) => node.type === "VariableDeclarator";
11229
- var mapCallbackIndexParameterName = (node) => {
11554
+ var isCreateKeyedLazyCall = (node, references) => {
11555
+ if (references === void 0) {
11556
+ return calleeMatchesHelperName(node.callee, "createKeyedLazy");
11557
+ }
11558
+ return Option_exports.exists(resolveFoldkitApiPath(references, node.callee), (path) => {
11559
+ const [namespace, factoryName, extraMember] = path;
11560
+ return namespace === "Html" && factoryName === "createKeyedLazy" && extraMember === void 0;
11561
+ });
11562
+ };
11563
+ var mapCallbackIndexParameter = (node, scopeManager) => {
11230
11564
  if (!isArrowFunctionExpression2(node)) {
11231
11565
  return Option_exports.none();
11232
11566
  }
@@ -11246,7 +11580,9 @@ var mapCallbackIndexParameterName = (node) => {
11246
11580
  if (!isIdentifier(secondParameter)) {
11247
11581
  return Option_exports.none();
11248
11582
  }
11249
- return Option_exports.some(secondParameter.name);
11583
+ const name = secondParameter.name;
11584
+ const variable = scopeManager?.getDeclaredVariables(node).find((candidate) => candidate.name === name);
11585
+ return Option_exports.some({ name, variable });
11250
11586
  };
11251
11587
  var firstNonSpreadArgument = (node) => {
11252
11588
  const [firstArgument] = node.arguments;
@@ -11261,61 +11597,75 @@ var slotIdValue = (configObject) => Option_exports.map(
11261
11597
  Array_exports.findFirst(configObject.properties, isSlotIdProperty),
11262
11598
  (property) => property.value
11263
11599
  );
11264
- var keySinkExpression = (node, slotNames) => {
11265
- if (isCallExpression(node.callee) && calleeMatchesHelperName(node.callee.callee, "keyed")) {
11600
+ var keySinkExpression = (node, slots, references) => {
11601
+ if (isCallExpression(node.callee) && isFoldkitHtmlBuilderMember(node.callee.callee, "keyed", references)) {
11266
11602
  return firstNonSpreadArgument(node);
11267
11603
  }
11268
- if (calleeMatchesHelperName(node.callee, "Key")) {
11604
+ if (isFoldkitHtmlBuilderMember(node.callee, "Key", references)) {
11269
11605
  return firstNonSpreadArgument(node);
11270
11606
  }
11271
- if (calleeMatchesHelperName(node.callee, "submodel")) {
11607
+ if (isFoldkitHtmlBuilderMember(node.callee, "submodel", references)) {
11272
11608
  const [configArgument] = node.arguments;
11273
11609
  if (isObjectExpression(configArgument)) {
11274
11610
  return slotIdValue(configArgument);
11275
11611
  }
11276
11612
  }
11277
- if (isIdentifier(node.callee) && slotNames.includes(node.callee.name)) {
11278
- return firstNonSpreadArgument(node);
11613
+ if (isIdentifierReference(node.callee)) {
11614
+ const slotCallee = node.callee;
11615
+ const isRegisteredSlot = slots.some(
11616
+ (slot) => slot.name === slotCallee.name && (references === void 0 || slot.variable !== void 0 && Option_exports.exists(
11617
+ resolvedVariable(references, slotCallee),
11618
+ (variable) => variable === slot.variable
11619
+ ))
11620
+ );
11621
+ if (isRegisteredSlot) {
11622
+ return firstNonSpreadArgument(node);
11623
+ }
11279
11624
  }
11280
11625
  return Option_exports.none();
11281
11626
  };
11282
- var referencesIndexName = (value, indexName) => {
11627
+ var referencesIndexBinding = (value, indexBinding, references) => {
11283
11628
  if (Array_exports.isArray(value)) {
11284
- return value.some((element) => referencesIndexName(element, indexName));
11629
+ return value.some(
11630
+ (element) => referencesIndexBinding(element, indexBinding, references)
11631
+ );
11285
11632
  }
11286
11633
  if (typeof value !== "object" || value === null) {
11287
11634
  return false;
11288
11635
  }
11289
- if (isIdentifier(value, indexName)) {
11290
- return true;
11636
+ if (isIdentifierReference(value) && value.name === indexBinding.name) {
11637
+ return references === void 0 || indexBinding.variable !== void 0 && Option_exports.exists(
11638
+ resolvedVariable(references, value),
11639
+ (variable) => variable === indexBinding.variable
11640
+ );
11291
11641
  }
11292
11642
  if (isMemberExpression(value)) {
11293
- if (referencesIndexName(value.object, indexName)) {
11643
+ if (referencesIndexBinding(value.object, indexBinding, references)) {
11294
11644
  return true;
11295
11645
  }
11296
- return value.computed === true && referencesIndexName(value.property, indexName);
11646
+ return value.computed === true && referencesIndexBinding(value.property, indexBinding, references);
11297
11647
  }
11298
11648
  if (isProperty(value)) {
11299
- if (value.computed === true && referencesIndexName(value.key, indexName)) {
11649
+ if (value.computed === true && referencesIndexBinding(value.key, indexBinding, references)) {
11300
11650
  return true;
11301
11651
  }
11302
- return referencesIndexName(value.value, indexName);
11652
+ return referencesIndexBinding(value.value, indexBinding, references);
11303
11653
  }
11304
- if (isArrowFunctionExpression2(value)) {
11654
+ if (references === void 0 && isArrowFunctionExpression2(value)) {
11305
11655
  const parameters = value.params;
11306
11656
  const isShadowed = parameters.some(
11307
- (parameter) => isIdentifier(parameter, indexName)
11657
+ (parameter) => isIdentifier(parameter, indexBinding.name)
11308
11658
  );
11309
11659
  if (isShadowed) {
11310
11660
  return false;
11311
11661
  }
11312
11662
  }
11313
- return referencesIndexNameAcrossFields(value, indexName);
11663
+ return referencesIndexBindingAcrossFields(value, indexBinding, references);
11314
11664
  };
11315
- var referencesIndexNameAcrossFields = (value, indexName) => {
11665
+ var referencesIndexBindingAcrossFields = (value, indexBinding, references) => {
11316
11666
  const fieldEntries = Object.entries(value);
11317
11667
  return fieldEntries.some(
11318
- ([fieldName, fieldValue]) => fieldName !== "parent" && referencesIndexName(fieldValue, indexName)
11668
+ ([fieldName, fieldValue]) => fieldName !== "parent" && referencesIndexBinding(fieldValue, indexBinding, references)
11319
11669
  );
11320
11670
  };
11321
11671
  var noArrayIndexViewKeys = Rule_exports.define({
@@ -11326,24 +11676,31 @@ var noArrayIndexViewKeys = Rule_exports.define({
11326
11676
  }),
11327
11677
  create: function* () {
11328
11678
  const ctx = yield* RuleContext;
11329
- const indexNameStack = yield* Ref_exports.make([]);
11330
- const slotNames = yield* Ref_exports.make([]);
11679
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
11680
+ const scopeManager = ctx.sourceCode.scopeManager;
11681
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
11682
+ const indexBindingStack = yield* Ref_exports.make(
11683
+ []
11684
+ );
11685
+ const slots = yield* Ref_exports.make([]);
11331
11686
  return {
11332
11687
  VariableDeclarator: (node) => {
11333
- if (!isVariableDeclarator2(node) || !isIdentifier(node.id) || !isCallExpression(node.init) || !calleeMatchesHelperName(node.init.callee, "createKeyedLazy")) {
11688
+ if (!isVariableDeclarator2(node) || node.id.type !== "Identifier" || !isCallExpression(node.init) || !isCreateKeyedLazyCall(node.init, references)) {
11334
11689
  return Effect_exports.void;
11335
11690
  }
11336
- return Ref_exports.update(slotNames, Array_exports.append(node.id.name));
11691
+ const slotName = node.id.name;
11692
+ const variable = scopeManager?.getDeclaredVariables(node).find((candidate) => candidate.name === slotName);
11693
+ return Ref_exports.update(slots, Array_exports.append({ name: slotName, variable }));
11337
11694
  },
11338
- ArrowFunctionExpression: (node) => Option_exports.match(mapCallbackIndexParameterName(node), {
11695
+ ArrowFunctionExpression: (node) => Option_exports.match(mapCallbackIndexParameter(node, scopeManager), {
11339
11696
  onNone: () => Effect_exports.void,
11340
- onSome: (indexName) => Ref_exports.update(indexNameStack, Array_exports.append(indexName))
11697
+ onSome: (indexBinding) => Ref_exports.update(indexBindingStack, Array_exports.append(indexBinding))
11341
11698
  }),
11342
- "ArrowFunctionExpression:exit": (node) => Option_exports.match(mapCallbackIndexParameterName(node), {
11699
+ "ArrowFunctionExpression:exit": (node) => Option_exports.match(mapCallbackIndexParameter(node, scopeManager), {
11343
11700
  onNone: () => Effect_exports.void,
11344
11701
  onSome: () => Ref_exports.update(
11345
- indexNameStack,
11346
- (activeIndexNames) => Array_exports.dropRight(activeIndexNames, 1)
11702
+ indexBindingStack,
11703
+ (activeIndexBindings) => Array_exports.dropRight(activeIndexBindings, 1)
11347
11704
  )
11348
11705
  }),
11349
11706
  CallExpression: (node) => {
@@ -11351,30 +11708,31 @@ var noArrayIndexViewKeys = Rule_exports.define({
11351
11708
  return Effect_exports.void;
11352
11709
  }
11353
11710
  return Effect_exports.gen(function* () {
11354
- const activeIndexNames = yield* Ref_exports.get(indexNameStack);
11355
- if (Array_exports.isReadonlyArrayEmpty(activeIndexNames)) {
11711
+ const activeIndexBindings = yield* Ref_exports.get(indexBindingStack);
11712
+ if (Array_exports.isReadonlyArrayEmpty(activeIndexBindings)) {
11356
11713
  return;
11357
11714
  }
11358
- const registeredSlotNames = yield* Ref_exports.get(slotNames);
11715
+ const registeredSlots = yield* Ref_exports.get(slots);
11359
11716
  const maybeKeyExpression = keySinkExpression(
11360
11717
  node,
11361
- registeredSlotNames
11718
+ registeredSlots,
11719
+ references
11362
11720
  );
11363
11721
  if (Option_exports.isNone(maybeKeyExpression)) {
11364
11722
  return;
11365
11723
  }
11366
11724
  const { value: keyExpression } = maybeKeyExpression;
11367
- const maybeIndexName = Array_exports.findFirst(
11368
- activeIndexNames,
11369
- (indexName) => referencesIndexName(keyExpression, indexName)
11725
+ const maybeIndexBinding = Array_exports.findFirst(
11726
+ activeIndexBindings,
11727
+ (indexBinding) => referencesIndexBinding(keyExpression, indexBinding, references)
11370
11728
  );
11371
- if (Option_exports.isNone(maybeIndexName)) {
11729
+ if (Option_exports.isNone(maybeIndexBinding)) {
11372
11730
  return;
11373
11731
  }
11374
11732
  yield* ctx.report(
11375
11733
  Diagnostic_exports.make({
11376
11734
  node: keyExpression,
11377
- message: `The array index parameter \`${maybeIndexName.value}\` is used as a view key. Positions shift when the list reorders or loses an item, so the runtime patches the wrong rows. Key this row or Submodel by a stable Model identifier such as \`item.id\` instead.`
11735
+ message: `The array index parameter \`${maybeIndexBinding.value.name}\` is used as a view key. Positions shift when the list reorders or loses an item, so the runtime patches the wrong rows. Key this row or Submodel by a stable Model identifier such as \`item.id\` instead.`
11378
11736
  })
11379
11737
  );
11380
11738
  });
@@ -11385,40 +11743,211 @@ var noArrayIndexViewKeys = Rule_exports.define({
11385
11743
 
11386
11744
  // src/rules/no-child-message-construction-in-root.ts
11387
11745
  var pascalIdentifierPattern = /^[A-Z][A-Za-z0-9]*$/;
11388
- var childMessageConstructionMessage = (namespace, constructorName2) => `Do not construct the child Message \`${namespace}.Message.${constructorName2}(...)\` from outside the child. Have the child export a helper that produces or applies this Message, and route child output back through the parent's Got*Message wrapper.`;
11746
+ var childMessageConstructionMessage = (calleeLabel) => `Do not construct the child Message \`${calleeLabel}(...)\` from a parent. Expose a child update capability that applies this fact, then invoke it with Update.foldChild or Update.foldChildStep. Child-owned views, Commands, and Subscriptions may construct their own Messages.`;
11747
+ var moduleExtensionPattern = /\.(?:cjs|cts|js|jsx|mjs|mts|ts|tsx)$/;
11748
+ var moduleSegmentName = (segment) => segment.replace(moduleExtensionPattern, "");
11749
+ var messageModuleSegmentNames = /* @__PURE__ */ new Set([
11750
+ "index",
11751
+ "main",
11752
+ "message",
11753
+ "schema"
11754
+ ]);
11755
+ var isMessageModuleSegment = (segment) => segment !== void 0 && messageModuleSegmentNames.has(moduleSegmentName(segment).toLowerCase());
11756
+ var isFunction2 = (node) => typeof node === "object" && node !== null && "type" in node && (node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression");
11757
+ var isTypeReference = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "TSTypeReference";
11758
+ var isTypeAnnotatedIdentifier2 = (node) => isIdentifier(node);
11759
+ var importedMessagePath = (references, node) => isTypeReference(node) ? Option_exports.map(resolveImportedPath(references, node.typeName), (path) => ({
11760
+ source: path.source,
11761
+ members: path.members
11762
+ })) : Option_exports.none();
11763
+ var pascalCaseModuleSegment = (segment) => moduleSegmentName(segment).split(/[-_]/).map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("");
11764
+ var messageModuleSegments = (path) => {
11765
+ const sourceSegments = path.source.split("/").filter((segment) => segment !== ".");
11766
+ const [lastSourceSegment] = sourceSegments.slice(-1);
11767
+ const moduleSourceSegments = isMessageModuleSegment(lastSourceSegment) ? sourceSegments.slice(0, -1) : sourceSegments;
11768
+ const namespaceMembers = path.members.slice(0, -1);
11769
+ const [firstNamespaceMember] = namespaceMembers;
11770
+ const [moduleSourceName] = moduleSourceSegments.slice(-1);
11771
+ const remainingNamespaceMembers = firstNamespaceMember !== void 0 && moduleSourceName !== void 0 && pascalCaseModuleSegment(firstNamespaceMember) === pascalCaseModuleSegment(moduleSourceName) ? namespaceMembers.slice(1) : namespaceMembers;
11772
+ return [...moduleSourceSegments, ...remainingNamespaceMembers].map(
11773
+ pascalCaseModuleSegment
11774
+ );
11775
+ };
11776
+ var sameSegments = (a, b) => Array_exports.length(a) === Array_exports.length(b) && Array_exports.every(Array_exports.zip(a, b), ([aSegment, bSegment]) => aSegment === bSegment);
11777
+ var sameImportedMessagePath = (a, b) => {
11778
+ if (a.source === b.source && sameSegments(a.members, b.members)) {
11779
+ return true;
11780
+ }
11781
+ const aSegments = messageModuleSegments(a);
11782
+ const bSegments = messageModuleSegments(b);
11783
+ return sameSegments(aSegments, bSegments);
11784
+ };
11785
+ var htmlBuilderMessagePath = (references, parameter) => {
11786
+ if (!isTypeAnnotatedIdentifier2(parameter)) {
11787
+ return Option_exports.none();
11788
+ }
11789
+ const typeAnnotation = parameter.typeAnnotation?.typeAnnotation;
11790
+ if (!isTypeReference(typeAnnotation)) {
11791
+ return Option_exports.none();
11792
+ }
11793
+ const isHtmlBuilder = Option_exports.exists(
11794
+ resolveFoldkitApiPath(references, typeAnnotation.typeName),
11795
+ (path) => {
11796
+ const [namespace, typeName, extraMember] = path;
11797
+ return namespace === "Html" && typeName === "HtmlBuilder" && extraMember === void 0;
11798
+ }
11799
+ );
11800
+ if (!isHtmlBuilder) {
11801
+ return Option_exports.none();
11802
+ }
11803
+ return Option_exports.gen(function* () {
11804
+ const typeArguments = yield* Option_exports.fromNullishOr(
11805
+ typeAnnotation.typeArguments
11806
+ );
11807
+ const messageType = yield* Option_exports.fromNullishOr(typeArguments.params[0]);
11808
+ return yield* importedMessagePath(references, messageType);
11809
+ });
11810
+ };
11811
+ var defineViewMessagePath = (references, functionNode) => {
11812
+ const parent = functionNode.parent;
11813
+ if (!isCallExpression(parent) || !parent.arguments.includes(functionNode)) {
11814
+ return Option_exports.none();
11815
+ }
11816
+ const isDefineView = Option_exports.exists(
11817
+ resolveFoldkitApiPath(references, parent.callee),
11818
+ (path) => {
11819
+ const [namespace, helperName, extraMember] = path;
11820
+ return namespace === "Submodel" && helperName === "defineView" && extraMember === void 0;
11821
+ }
11822
+ );
11823
+ if (!isDefineView) {
11824
+ return Option_exports.none();
11825
+ }
11826
+ return Option_exports.gen(function* () {
11827
+ const typeArguments = yield* Option_exports.fromNullishOr(parent.typeArguments);
11828
+ const messageType = yield* Option_exports.fromNullishOr(typeArguments.params[1]);
11829
+ return yield* importedMessagePath(references, messageType);
11830
+ });
11831
+ };
11832
+ var isOwnedByEnclosingView = (node, references, messagePath) => {
11833
+ const ownsMessage = (ancestor) => {
11834
+ if (ancestor === null || ancestor === void 0) {
11835
+ return false;
11836
+ }
11837
+ if (isFunction2(ancestor)) {
11838
+ const ownsAnnotatedBuilder = ancestor.params.some(
11839
+ (parameter) => Option_exports.exists(
11840
+ htmlBuilderMessagePath(references, parameter),
11841
+ (builderMessagePath) => sameImportedMessagePath(builderMessagePath, messagePath)
11842
+ )
11843
+ );
11844
+ if (ownsAnnotatedBuilder) {
11845
+ return true;
11846
+ }
11847
+ const ownsDefinedView = Option_exports.exists(
11848
+ defineViewMessagePath(references, ancestor),
11849
+ (viewMessagePath) => sameImportedMessagePath(viewMessagePath, messagePath)
11850
+ );
11851
+ if (ownsDefinedView) {
11852
+ return true;
11853
+ }
11854
+ }
11855
+ return ownsMessage(ancestor.parent);
11856
+ };
11857
+ return ownsMessage(node.parent);
11858
+ };
11859
+ var hasComputedMember = (node) => isMemberExpression(node) && (node.computed || hasComputedMember(node.object));
11860
+ var relativeModuleSegments = (source) => source.split("/").filter((segment) => segment !== "." && segment !== "..");
11861
+ var isTopLevelRootAlias = (source) => {
11862
+ if (!source.startsWith("@/") && !source.startsWith("~/")) {
11863
+ return false;
11864
+ }
11865
+ return !source.slice(2).includes("/");
11866
+ };
11867
+ var isRootMessageModule = (source) => {
11868
+ const sourceSegments = relativeModuleSegments(source);
11869
+ const [lastSourceSegment] = sourceSegments.slice(-1);
11870
+ const [parentSourceSegment] = sourceSegments.slice(-2, -1);
11871
+ if (lastSourceSegment === void 0) {
11872
+ return true;
11873
+ }
11874
+ if (!isMessageModuleSegment(lastSourceSegment)) {
11875
+ return false;
11876
+ }
11877
+ return source.startsWith(".") ? parentSourceSegment === void 0 : isTopLevelRootAlias(source);
11878
+ };
11879
+ var childNamespace = (source, importedMembers, localMembers) => {
11880
+ const namespaceMembers = importedMembers.slice(0, -2);
11881
+ const [importedNamespace] = namespaceMembers.slice(-1);
11882
+ if (importedNamespace !== void 0) {
11883
+ return importedNamespace;
11884
+ }
11885
+ const sourceSegments = relativeModuleSegments(source);
11886
+ const [lastSourceSegment] = sourceSegments.slice(-1);
11887
+ const [parentSourceSegment] = sourceSegments.slice(-2, -1);
11888
+ const sourceNamespace = isMessageModuleSegment(lastSourceSegment) ? parentSourceSegment : lastSourceSegment;
11889
+ if (sourceNamespace !== void 0) {
11890
+ return pascalCaseModuleSegment(sourceNamespace);
11891
+ }
11892
+ const [localRoot] = localMembers;
11893
+ return localRoot ?? "Child";
11894
+ };
11895
+ var childMessageConstruction = (callee, references) => {
11896
+ if (hasComputedMember(callee)) {
11897
+ return Option_exports.none();
11898
+ }
11899
+ if (references === void 0) {
11900
+ return Option_exports.flatMap(staticMemberPath(callee), (path) => {
11901
+ const [namespace, middle, constructorName2, extraSegment] = [
11902
+ path.root.name,
11903
+ ...path.members
11904
+ ];
11905
+ return namespace !== void 0 && middle === "Message" && constructorName2 !== void 0 && constructorName2 !== "Message" && extraSegment === void 0 && pascalIdentifierPattern.test(namespace) && pascalIdentifierPattern.test(constructorName2) ? Option_exports.some({
11906
+ calleeLabel: `${namespace}.Message.${constructorName2}`
11907
+ }) : Option_exports.none();
11908
+ });
11909
+ }
11910
+ return Option_exports.flatMap(resolveImportedPath(references, callee), (path) => {
11911
+ const [messageNamespace, constructorName2] = path.members.slice(-2);
11912
+ if (messageNamespace !== "Message" || constructorName2 === void 0 || constructorName2 === "Message" || !pascalIdentifierPattern.test(constructorName2) || isRootMessageModule(path.source)) {
11913
+ return Option_exports.none();
11914
+ }
11915
+ return Option_exports.some({
11916
+ calleeLabel: `${childNamespace(path.source, path.members, path.localMembers)}.Message.${constructorName2}`,
11917
+ messagePath: {
11918
+ source: path.source,
11919
+ members: path.members.slice(0, -1)
11920
+ }
11921
+ });
11922
+ });
11923
+ };
11389
11924
  var noChildMessageConstructionInRoot = Rule_exports.define({
11390
11925
  name: "no-child-message-construction-in-root",
11391
11926
  meta: Rule_exports.meta({
11392
11927
  type: "suggestion",
11393
- description: "Construct child Submodel Messages through child-exported helpers instead of reaching into the child Message namespace."
11928
+ description: "Drive child Submodels through child-owned update capabilities instead of constructing their Messages from a parent."
11394
11929
  }),
11395
11930
  create: function* () {
11396
11931
  const ctx = yield* RuleContext;
11932
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
11933
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
11397
11934
  return {
11398
11935
  CallExpression: (node) => {
11399
11936
  if (!isCallExpression(node)) {
11400
11937
  return Effect_exports.void;
11401
11938
  }
11402
- const callee = node.callee;
11403
- if (callee.type !== "MemberExpression") {
11404
- return Effect_exports.void;
11405
- }
11406
11939
  return pipe(
11407
- AST_exports.memberPath(callee),
11940
+ childMessageConstruction(node.callee, references),
11408
11941
  Option_exports.match({
11409
11942
  onNone: () => Effect_exports.void,
11410
- onSome: (path) => {
11411
- const [namespace, middle, constructorName2, extraSegment] = path;
11412
- if (namespace === void 0 || middle !== "Message" || constructorName2 === void 0 || constructorName2 === "Message" || extraSegment !== void 0 || !pascalIdentifierPattern.test(namespace) || !pascalIdentifierPattern.test(constructorName2)) {
11943
+ onSome: ({ calleeLabel, messagePath }) => {
11944
+ if (references !== void 0 && messagePath !== void 0 && isOwnedByEnclosingView(node, references, messagePath)) {
11413
11945
  return Effect_exports.void;
11414
11946
  }
11415
11947
  return ctx.report(
11416
11948
  Diagnostic_exports.make({
11417
11949
  node,
11418
- message: childMessageConstructionMessage(
11419
- namespace,
11420
- constructorName2
11421
- )
11950
+ message: childMessageConstructionMessage(calleeLabel)
11422
11951
  })
11423
11952
  );
11424
11953
  }
@@ -11433,7 +11962,13 @@ var noChildMessageConstructionInRoot = Rule_exports.define({
11433
11962
  var FACTORY_NAMES = ["makeApplication", "makeElement"];
11434
11963
  var FREEZE_MODEL_MESSAGE = "`freezeModel: false` turns off Foldkit's dev mutation guard. When on, the runtime deep-freezes the Model after init and after every update, so an accidental mutation throws at the exact write site during development and costs nothing in production. Fix the mutation instead of disabling the guard. A deliberate disable belongs behind an oxlint-disable comment at this line.";
11435
11964
  var SLOW_MESSAGE = "`slow: false` turns off Foldkit's dev performance warnings, which flag update, view, and patch phases that blow their budgets. Tune instead of disabling: pass an object with thresholdOverrides, measuredPhases, show, or onSlow. A deliberate disable belongs behind an oxlint-disable comment at this line.";
11436
- var isFactoryCallee = (callee) => {
11965
+ var isFactoryCallee = (callee, references) => {
11966
+ if (references !== void 0) {
11967
+ return Option_exports.exists(resolveFoldkitApiPath(references, callee), (path) => {
11968
+ const [namespace, factoryName, extraMember] = path;
11969
+ return namespace === "Runtime" && factoryName !== void 0 && FACTORY_NAMES.includes(factoryName) && extraMember === void 0;
11970
+ });
11971
+ }
11437
11972
  if (callee.type === "Identifier") {
11438
11973
  return FACTORY_NAMES.includes(callee.name);
11439
11974
  }
@@ -11475,9 +12010,11 @@ var noDisablingDevGuardrails = Rule_exports.define({
11475
12010
  }),
11476
12011
  create: function* () {
11477
12012
  const ctx = yield* RuleContext;
12013
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
12014
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
11478
12015
  return {
11479
12016
  CallExpression: (node) => {
11480
- if (!isCallExpression(node) || !isFactoryCallee(node.callee)) {
12017
+ if (!isCallExpression(node) || !isFactoryCallee(node.callee, references)) {
11481
12018
  return Effect_exports.void;
11482
12019
  }
11483
12020
  const disabledGuardrails = node.arguments.flatMap((argument) => {
@@ -11501,19 +12038,8 @@ var noDisablingDevGuardrails = Rule_exports.define({
11501
12038
 
11502
12039
  // src/rules/no-duplicate-onmount-per-element.ts
11503
12040
  var DUPLICATE_ON_MOUNT_MESSAGE = "Only one OnMount attribute can attach to an element. Foldkit installs a single insert hook and tracks a single Mount fiber per element, so a later OnMount replaces the earlier one and its `execute` never runs. Combine the behaviors into one Mount definition.";
11504
- var isOnMountCallee = (callee) => {
11505
- if (callee.type === "Identifier") {
11506
- return callee.name === "OnMount";
11507
- }
11508
- if (callee.type === "MemberExpression") {
11509
- return Option_exports.match(AST_exports.memberPath(callee), {
11510
- onNone: () => false,
11511
- onSome: (path) => Array_exports.lastNonEmpty(path) === "OnMount"
11512
- });
11513
- }
11514
- return false;
11515
- };
11516
- var isOnMountCall = (element) => element !== null && element.type === "CallExpression" && isOnMountCallee(element.callee);
12041
+ var isOnMountCallee = (callee, references) => isFoldkitHtmlBuilderMember(callee, "OnMount", references);
12042
+ var isOnMountCall = (element, references) => element !== null && element.type === "CallExpression" && isOnMountCallee(element.callee, references);
11517
12043
  var noDuplicateOnmountPerElement = Rule_exports.define({
11518
12044
  name: "no-duplicate-onmount-per-element",
11519
12045
  meta: Rule_exports.meta({
@@ -11522,10 +12048,14 @@ var noDuplicateOnmountPerElement = Rule_exports.define({
11522
12048
  }),
11523
12049
  create: function* () {
11524
12050
  const ctx = yield* RuleContext;
12051
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
12052
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
11525
12053
  return {
11526
12054
  ArrayExpression: (node) => {
11527
12055
  if (!isArrayExpression(node)) return Effect_exports.void;
11528
- const onMountCallCount = node.elements.filter(isOnMountCall).length;
12056
+ const onMountCallCount = node.elements.filter(
12057
+ (element) => isOnMountCall(element, references)
12058
+ ).length;
11529
12059
  if (onMountCallCount <= 1) return Effect_exports.void;
11530
12060
  return ctx.report(
11531
12061
  Diagnostic_exports.make({ node, message: DUPLICATE_ON_MOUNT_MESSAGE })
@@ -11757,27 +12287,38 @@ var ELEMENT_BUILDER_NAMES = /* @__PURE__ */ new Set([
11757
12287
  // src/rules/no-empty-children-array.ts
11758
12288
  var BUILDER_BINDINGS = /* @__PURE__ */ new Set(["h", "ih", "inertHtml"]);
11759
12289
  var KEYED_PROPERTY = "keyed";
11760
- var builderCallee = (callee) => {
12290
+ var builderCallee = (callee, references) => {
11761
12291
  if (!isMemberExpression(callee) || callee.computed === true) {
11762
12292
  return Option_exports.none();
11763
12293
  }
11764
- if (!isIdentifier(callee.object) || !BUILDER_BINDINGS.has(callee.object.name) || !isIdentifier(callee.property)) {
12294
+ if (!isIdentifier(callee.property)) {
12295
+ return Option_exports.none();
12296
+ }
12297
+ const maybePath = staticMemberPath(callee);
12298
+ if (Option_exports.isNone(maybePath)) {
12299
+ return Option_exports.none();
12300
+ }
12301
+ const path = maybePath.value;
12302
+ const binding = [path.root.name, ...Array_exports.dropRight(path.members, 1)].join(
12303
+ "."
12304
+ );
12305
+ if (references === void 0 ? !BUILDER_BINDINGS.has(binding) : !isFoldkitHtmlBuilderMember(callee, callee.property.name, references)) {
11765
12306
  return Option_exports.none();
11766
12307
  }
11767
12308
  return Option_exports.some({
11768
- binding: callee.object.name,
12309
+ binding,
11769
12310
  property: callee.property.name
11770
12311
  });
11771
12312
  };
11772
- var elementCallTarget = (node) => node.arguments.length === 2 ? builderCallee(node.callee).pipe(
12313
+ var elementCallTarget = (node, references) => node.arguments.length === 2 ? builderCallee(node.callee, references).pipe(
11773
12314
  Option_exports.filter(({ property }) => ELEMENT_BUILDER_NAMES.has(property)),
11774
12315
  Option_exports.map(({ binding, property }) => `${binding}.${property}([...])`)
11775
12316
  ) : Option_exports.none();
11776
- var keyedCallTarget = (node) => {
12317
+ var keyedCallTarget = (node, references) => {
11777
12318
  if (node.arguments.length !== 3 || !isCallExpression(node.callee)) {
11778
12319
  return Option_exports.none();
11779
12320
  }
11780
- return builderCallee(node.callee.callee).pipe(
12321
+ return builderCallee(node.callee.callee, references).pipe(
11781
12322
  Option_exports.filter(({ property }) => property === KEYED_PROPERTY),
11782
12323
  Option_exports.map(
11783
12324
  ({ binding }) => `${binding}.${KEYED_PROPERTY}(tag)(key, [...])`
@@ -11794,14 +12335,16 @@ var noEmptyChildrenArray = Rule_exports.define({
11794
12335
  }),
11795
12336
  create: function* () {
11796
12337
  const ctx = yield* RuleContext;
12338
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
12339
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
11797
12340
  return {
11798
12341
  CallExpression: (node) => {
11799
12342
  if (!isCallExpression(node)) {
11800
12343
  return Effect_exports.void;
11801
12344
  }
11802
12345
  const maybeTarget = Option_exports.orElse(
11803
- elementCallTarget(node),
11804
- () => keyedCallTarget(node)
12346
+ elementCallTarget(node, references),
12347
+ () => keyedCallTarget(node, references)
11805
12348
  );
11806
12349
  if (Option_exports.isNone(maybeTarget)) {
11807
12350
  return Effect_exports.void;
@@ -11828,14 +12371,7 @@ var noEmptyChildrenArray = Rule_exports.define({
11828
12371
 
11829
12372
  // src/rules/no-empty-commands-array.ts
11830
12373
  var COMMANDS_PROPERTY = "commands";
11831
- var isObjectProperty = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "Property";
11832
- var staticPropertyName2 = (property) => {
11833
- if (!property.computed && isIdentifier(property.key)) {
11834
- return Option_exports.some(property.key.name);
11835
- }
11836
- return staticStringValue(property.key);
11837
- };
11838
- var isEmptyCommandsProperty = (property) => Option_exports.contains(staticPropertyName2(property), COMMANDS_PROPERTY) && isArrayExpression(property.value) && Array_exports.isReadonlyArrayEmpty(property.value.elements);
12374
+ var isEmptyCommandsProperty = (property) => Option_exports.contains(staticPropertyName(property), COMMANDS_PROPERTY) && isArrayExpression(property.value) && Array_exports.isReadonlyArrayEmpty(property.value.elements);
11839
12375
  var removalRange = (sourceText, object, property, index) => {
11840
12376
  const maybePrevious = Array_exports.get(object.properties, index - 1);
11841
12377
  if (Option_exports.isSome(maybePrevious)) {
@@ -11876,11 +12412,11 @@ var noEmptyCommandsArray = Rule_exports.define({
11876
12412
  );
11877
12413
  const hasDynamicComputedProperty = Array_exports.some(
11878
12414
  node.properties,
11879
- (property) => isObjectProperty(property) && property.computed && Option_exports.isNone(staticPropertyName2(property))
12415
+ (property) => isObjectProperty(property) && property.computed && Option_exports.isNone(staticPropertyName(property))
11880
12416
  );
11881
12417
  const commandProperties = Array_exports.filter(
11882
12418
  node.properties,
11883
- (property) => isObjectProperty(property) && Option_exports.contains(staticPropertyName2(property), COMMANDS_PROPERTY)
12419
+ (property) => isObjectProperty(property) && Option_exports.contains(staticPropertyName(property), COMMANDS_PROPERTY)
11884
12420
  );
11885
12421
  const hasComments = Array_exports.isReadonlyArrayNonEmpty(
11886
12422
  ctx.sourceCode.getCommentsInside(node)
@@ -11941,12 +12477,32 @@ var recordUnionHelperBindings = (bindings, node) => {
11941
12477
  }
11942
12478
  };
11943
12479
  var isConventionalUnionNamespace = (name) => PASCAL_CASE.test(name) && /(?:Message|Route|State)$/.test(name);
11944
- var constructorName = (callee, unionNamespaces) => {
12480
+ var isUnionHelperCall = (node, bindings, references) => {
12481
+ if (references === void 0) {
12482
+ return isIdentifier(node.callee) && bindings.has(node.callee.name);
12483
+ }
12484
+ return Option_exports.exists(resolveFoldkitApiPath(references, node.callee), (path) => {
12485
+ const [namespace, helperName, extraMember] = path;
12486
+ const expectedHelperByNamespace = {
12487
+ Message: "defineMessageUnion",
12488
+ Route: "defineRouteUnion",
12489
+ Schema: "defineTaggedUnion"
12490
+ };
12491
+ return namespace !== void 0 && expectedHelperByNamespace[namespace] === helperName && extraMember === void 0;
12492
+ });
12493
+ };
12494
+ var constructorName = (callee, unionNamespaceNames, unionNamespaceVariables, references) => {
11945
12495
  if (isIdentifier(callee) && PASCAL_CASE.test(callee.name)) {
11946
12496
  return callee.name;
11947
12497
  }
11948
- if (isMemberExpression(callee) && callee.computed !== true && isIdentifier(callee.object) && (unionNamespaces.has(callee.object.name) || isConventionalUnionNamespace(callee.object.name)) && isIdentifier(callee.property) && PASCAL_CASE.test(callee.property.name)) {
11949
- return `${callee.object.name}.${callee.property.name}`;
12498
+ if (isMemberExpression(callee) && callee.computed !== true && isIdentifierReference(callee.object) && isIdentifier(callee.property) && PASCAL_CASE.test(callee.property.name)) {
12499
+ const namespace = callee.object;
12500
+ const isUnionNamespace = references === void 0 ? unionNamespaceNames.has(namespace.name) || isConventionalUnionNamespace(namespace.name) : Option_exports.exists(resolvedVariable(references, namespace), (variable) => {
12501
+ return unionNamespaceVariables.has(variable) || isConventionalUnionNamespace(namespace.name) && variable.defs.some(
12502
+ (definition) => definition.type === "ImportBinding"
12503
+ );
12504
+ });
12505
+ return isUnionNamespace ? `${namespace.name}.${callee.property.name}` : void 0;
11950
12506
  }
11951
12507
  return void 0;
11952
12508
  };
@@ -11958,16 +12514,24 @@ var noEmptyObjectTaggedCall = Rule_exports.define({
11958
12514
  }),
11959
12515
  create: function* () {
11960
12516
  const ctx = yield* RuleContext;
12517
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
12518
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
11961
12519
  const unionHelperBindings = /* @__PURE__ */ new Set();
11962
- const unionNamespaces = /* @__PURE__ */ new Set();
12520
+ const unionNamespaceNames = /* @__PURE__ */ new Set();
12521
+ const unionNamespaceVariables = /* @__PURE__ */ new Set();
11963
12522
  return {
11964
12523
  Program: (node) => {
11965
12524
  recordUnionHelperBindings(unionHelperBindings, node);
11966
12525
  return Effect_exports.void;
11967
12526
  },
11968
12527
  VariableDeclarator: (node) => {
11969
- if (isVariableDeclarator(node) && isIdentifier(node.id) && isCallExpression(node.init) && isIdentifier(node.init.callee) && unionHelperBindings.has(node.init.callee.name)) {
11970
- unionNamespaces.add(node.id.name);
12528
+ if (isVariableDeclarator(node) && node.id.type === "Identifier" && isCallExpression(node.init) && isUnionHelperCall(node.init, unionHelperBindings, references)) {
12529
+ const unionName = node.id.name;
12530
+ unionNamespaceNames.add(unionName);
12531
+ const unionVariable = ctx.sourceCode.scopeManager?.getDeclaredVariables(node).find((variable) => variable.name === unionName);
12532
+ if (unionVariable !== void 0) {
12533
+ unionNamespaceVariables.add(unionVariable);
12534
+ }
11971
12535
  }
11972
12536
  return Effect_exports.void;
11973
12537
  },
@@ -11975,7 +12539,12 @@ var noEmptyObjectTaggedCall = Rule_exports.define({
11975
12539
  if (!isCallExpression(node)) {
11976
12540
  return Effect_exports.void;
11977
12541
  }
11978
- const name = constructorName(node.callee, unionNamespaces);
12542
+ const name = constructorName(
12543
+ node.callee,
12544
+ unionNamespaceNames,
12545
+ unionNamespaceVariables,
12546
+ references
12547
+ );
11979
12548
  if (name === void 0 || node.arguments.length !== 1) {
11980
12549
  return Effect_exports.void;
11981
12550
  }
@@ -11996,35 +12565,14 @@ var noEmptyObjectTaggedCall = Rule_exports.define({
11996
12565
 
11997
12566
  // src/rules/no-empty-to-parent-out-message.ts
11998
12567
  var TO_PARENT_OUT_MESSAGE_PROPERTY = "toParentOutMessage";
11999
- var isObjectProperty2 = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "Property";
12000
- var staticPropertyName3 = (property) => {
12001
- if (!property.computed && isIdentifier(property.key)) {
12002
- return Option_exports.some(property.key.name);
12003
- }
12004
- return staticStringValue(property.key);
12005
- };
12006
12568
  var isArrowFunctionExpression3 = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "ArrowFunctionExpression";
12007
12569
  var isFunctionExpression = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "FunctionExpression";
12008
12570
  var isMapperFunction = (node) => isArrowFunctionExpression3(node) && !node.async || isFunctionExpression(node) && !node.async && !node.generator;
12009
- var isIdentifierReference = (node) => isIdentifier(node);
12010
- var indexReferences = (scopes) => {
12011
- const references = /* @__PURE__ */ new WeakMap();
12012
- for (const scope3 of scopes) {
12013
- for (const reference of scope3.references) {
12014
- references.set(reference.identifier, reference);
12015
- }
12016
- }
12017
- return references;
12018
- };
12019
12571
  var isUnshadowedUndefined = (references, node) => {
12020
12572
  if (!isIdentifierReference(node) || node.name !== "undefined") {
12021
12573
  return false;
12022
12574
  }
12023
- if (references === void 0) {
12024
- return true;
12025
- }
12026
- const reference = references.get(node);
12027
- return reference !== void 0 && (reference.resolved === null || Array_exports.isArrayEmpty(reference.resolved.defs));
12575
+ return isUnshadowedReference(references, node);
12028
12576
  };
12029
12577
  var directlyReturnsUndefined = (references, mapper) => {
12030
12578
  if (mapper.body === null) {
@@ -12037,7 +12585,7 @@ var directlyReturnsUndefined = (references, mapper) => {
12037
12585
  return firstStatement?.type === "ReturnStatement" && secondStatement === void 0 && isUnshadowedUndefined(references, firstStatement.argument);
12038
12586
  };
12039
12587
  var isEmptyMapperProperty = (references, property) => property.kind === "init" && Option_exports.contains(
12040
- staticPropertyName3(property),
12588
+ staticPropertyName(property),
12041
12589
  TO_PARENT_OUT_MESSAGE_PROPERTY
12042
12590
  ) && isMapperFunction(property.value) && directlyReturnsUndefined(references, property.value);
12043
12591
  var removalRange2 = (sourceText, object, property, index) => {
@@ -12082,12 +12630,12 @@ var noEmptyToParentOutMessage = Rule_exports.define({
12082
12630
  );
12083
12631
  const hasDynamicComputedProperty = Array_exports.some(
12084
12632
  node.properties,
12085
- (property) => isObjectProperty2(property) && property.computed && Option_exports.isNone(staticPropertyName3(property))
12633
+ (property) => isObjectProperty(property) && property.computed && Option_exports.isNone(staticPropertyName(property))
12086
12634
  );
12087
12635
  const mapperProperties = Array_exports.filter(
12088
12636
  node.properties,
12089
- (property) => isObjectProperty2(property) && Option_exports.contains(
12090
- staticPropertyName3(property),
12637
+ (property) => isObjectProperty(property) && Option_exports.contains(
12638
+ staticPropertyName(property),
12091
12639
  TO_PARENT_OUT_MESSAGE_PROPERTY
12092
12640
  )
12093
12641
  );
@@ -12097,7 +12645,7 @@ var noEmptyToParentOutMessage = Rule_exports.define({
12097
12645
  return Effect_exports.forEach(
12098
12646
  node.properties.entries(),
12099
12647
  ([index, property]) => {
12100
- if (!isObjectProperty2(property) || !isEmptyMapperProperty(references, property)) {
12648
+ if (!isObjectProperty(property) || !isEmptyMapperProperty(references, property)) {
12101
12649
  return Effect_exports.void;
12102
12650
  }
12103
12651
  const diagnostic = Diagnostic_exports.make({
@@ -12194,6 +12742,21 @@ var INTERNAL_NAVIGATION_FUNCTION_NAMES = [
12194
12742
  ];
12195
12743
  var INTERNAL_PATH_PATTERN = /^\//;
12196
12744
  var ABSOLUTE_URL_PATTERN = /^https?:\/\//;
12745
+ var routingFunctionName = (callee, references) => {
12746
+ if (references === void 0) {
12747
+ return pipe(
12748
+ helperCalleeName(callee),
12749
+ Option_exports.filter((name) => Array_exports.contains(ROUTING_FUNCTION_NAMES, name))
12750
+ );
12751
+ }
12752
+ if (isFoldkitHtmlBuilderMember(callee, "Href", references)) {
12753
+ return Option_exports.some("Href");
12754
+ }
12755
+ return Option_exports.flatMap(resolveFoldkitApiPath(references, callee), (path) => {
12756
+ const [namespace, functionName, extraMember] = path;
12757
+ return namespace === "Navigation" && functionName !== void 0 && Array_exports.contains(INTERNAL_NAVIGATION_FUNCTION_NAMES, functionName) && extraMember === void 0 ? Option_exports.some(functionName) : Option_exports.none();
12758
+ });
12759
+ };
12197
12760
  var isHardcodedRouteString = (functionName, value) => INTERNAL_PATH_PATTERN.test(value) || Array_exports.contains(INTERNAL_NAVIGATION_FUNCTION_NAMES, functionName) && ABSOLUTE_URL_PATTERN.test(value);
12198
12761
  var templateCookedHead = (node) => pipe(
12199
12762
  Array_exports.head(node.quasis),
@@ -12209,15 +12772,14 @@ var noHardcodedRouteStrings = Rule_exports.define({
12209
12772
  }),
12210
12773
  create: function* () {
12211
12774
  const ctx = yield* RuleContext;
12775
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
12776
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
12212
12777
  return {
12213
12778
  CallExpression: (node) => {
12214
12779
  if (!isCallExpression2(node)) {
12215
12780
  return Effect_exports.void;
12216
12781
  }
12217
- const maybeFunctionName = pipe(
12218
- helperCalleeName(node.callee),
12219
- Option_exports.filter((name) => Array_exports.contains(ROUTING_FUNCTION_NAMES, name))
12220
- );
12782
+ const maybeFunctionName = routingFunctionName(node.callee, references);
12221
12783
  if (Option_exports.isNone(maybeFunctionName)) {
12222
12784
  return Effect_exports.void;
12223
12785
  }
@@ -12260,6 +12822,602 @@ var noHardcodedRouteStrings = Rule_exports.define({
12260
12822
  }
12261
12823
  });
12262
12824
 
12825
+ // src/rules/no-impure-call-at-decision-time.ts
12826
+ var globalContainers = /* @__PURE__ */ new Set(["globalThis", "self", "window"]);
12827
+ var impureCallByPath = /* @__PURE__ */ new Map([
12828
+ [
12829
+ "Date",
12830
+ {
12831
+ display: "Date()",
12832
+ guidance: "Use Clock.currentTimeMillis and construct the Date from that value."
12833
+ }
12834
+ ],
12835
+ [
12836
+ "Date.now",
12837
+ {
12838
+ display: "Date.now()",
12839
+ guidance: "Use Clock.currentTimeMillis."
12840
+ }
12841
+ ],
12842
+ [
12843
+ "Math.random",
12844
+ {
12845
+ display: "Math.random()",
12846
+ guidance: "Use Random."
12847
+ }
12848
+ ],
12849
+ [
12850
+ "performance.now",
12851
+ {
12852
+ display: "performance.now()",
12853
+ guidance: "Use Clock."
12854
+ }
12855
+ ],
12856
+ [
12857
+ "crypto.randomUUID",
12858
+ {
12859
+ display: "crypto.randomUUID()",
12860
+ guidance: "Use Crypto.Crypto's randomUUIDv4 Effect with a platform Crypto layer."
12861
+ }
12862
+ ],
12863
+ [
12864
+ "crypto.getRandomValues",
12865
+ {
12866
+ display: "crypto.getRandomValues()",
12867
+ guidance: "Use Random or Crypto.Crypto with a platform Crypto layer."
12868
+ }
12869
+ ]
12870
+ ]);
12871
+ var newDateOperation = {
12872
+ display: "new Date()",
12873
+ guidance: "Use Clock.currentTimeMillis and construct the Date from that value."
12874
+ };
12875
+ var isFunction3 = (node) => typeof node === "object" && node !== null && "type" in node && (node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression" || node.type === "FunctionDeclaration");
12876
+ var isTransparentExpression2 = (node) => {
12877
+ if (typeof node !== "object" || node === null || !("type" in node)) {
12878
+ return false;
12879
+ }
12880
+ return node.type === "ChainExpression" || node.type === "ParenthesizedExpression" || node.type === "TSAsExpression" || node.type === "TSInstantiationExpression" || node.type === "TSNonNullExpression" || node.type === "TSSatisfiesExpression" || node.type === "TSTypeAssertion";
12881
+ };
12882
+ var innermostExpression2 = (node) => isTransparentExpression2(node) ? innermostExpression2(node.expression) : node;
12883
+ var outermostExpression = (node) => {
12884
+ const parent = node.parent;
12885
+ return isTransparentExpression2(parent) && parent.expression === node ? outermostExpression(parent) : node;
12886
+ };
12887
+ var staticPath = (node) => {
12888
+ const expression = innermostExpression2(node);
12889
+ if (isIdentifierReference(expression)) {
12890
+ return Option_exports.some({ root: expression, members: [] });
12891
+ }
12892
+ if (!isMemberExpression(expression)) {
12893
+ return Option_exports.none();
12894
+ }
12895
+ return Option_exports.flatMap(
12896
+ staticPath(expression.object),
12897
+ (path) => Option_exports.map(staticMemberName(expression), (member) => ({
12898
+ root: path.root,
12899
+ members: [...path.members, member]
12900
+ }))
12901
+ );
12902
+ };
12903
+ var globalPathKey = (references, node) => Option_exports.flatMap(staticPath(node), (path) => {
12904
+ if (!isUnshadowedReference(references, path.root)) {
12905
+ return Option_exports.none();
12906
+ }
12907
+ const members = globalContainers.has(path.root.name) ? path.members : [path.root.name, ...path.members];
12908
+ return Option_exports.some(members.join("."));
12909
+ });
12910
+ var importedPath = (references, node) => references === void 0 ? Option_exports.map(staticPath(node), (path) => ({
12911
+ source: "",
12912
+ members: [path.root.name, ...path.members]
12913
+ })) : Option_exports.map(resolveImportedPath(references, node), (path) => ({
12914
+ source: path.source,
12915
+ members: path.members
12916
+ }));
12917
+ var normalizedApiPath = (path) => {
12918
+ if (path.source === "" || path.source === "effect" || path.source === "foldkit") {
12919
+ return Option_exports.some(path.members);
12920
+ }
12921
+ if (path.source === "effect/Effect") {
12922
+ return Option_exports.some(["Effect", ...path.members]);
12923
+ }
12924
+ if (path.source === "effect/Stream") {
12925
+ return Option_exports.some(["Stream", ...path.members]);
12926
+ }
12927
+ if (path.source === "foldkit/command") {
12928
+ return Option_exports.some(["Command", ...path.members]);
12929
+ }
12930
+ if (path.source === "foldkit/managedResource") {
12931
+ return Option_exports.some(["ManagedResource", ...path.members]);
12932
+ }
12933
+ if (path.source === "foldkit/mount") {
12934
+ return Option_exports.some(["Mount", ...path.members]);
12935
+ }
12936
+ if (path.source === "foldkit/subscription") {
12937
+ return Option_exports.some(["Subscription", ...path.members]);
12938
+ }
12939
+ return Option_exports.none();
12940
+ };
12941
+ var headCall = (node) => node.callee.type === "CallExpression" ? headCall(node.callee) : node;
12942
+ var apiCallKey = (references, node) => Option_exports.flatMap(
12943
+ importedPath(references, headCall(node).callee),
12944
+ (path) => Option_exports.map(normalizedApiPath(path), (members) => members.join("."))
12945
+ );
12946
+ var enclosingCallArgument = (node) => {
12947
+ const argument = outermostExpression(node);
12948
+ const parent = argument.parent;
12949
+ return parent?.type === "CallExpression" && parent.arguments.some((candidate) => candidate === argument) ? Option_exports.some({ call: parent, argument }) : Option_exports.none();
12950
+ };
12951
+ var enclosingPropertyValue = (node) => {
12952
+ const value = outermostExpression(node);
12953
+ const parent = value.parent;
12954
+ return isObjectProperty(parent) && parent.value === value ? Option_exports.some(parent) : Option_exports.none();
12955
+ };
12956
+ var effectFunctionFactories = /* @__PURE__ */ new Set(["Effect.fn", "Effect.fnUntraced"]);
12957
+ var directByArity = (...entries) => new Map(
12958
+ entries.map(([arity, ...argumentIndices]) => [
12959
+ arity,
12960
+ new Set(argumentIndices)
12961
+ ])
12962
+ );
12963
+ var propertiesByArity = (...entries) => {
12964
+ const properties2 = /* @__PURE__ */ new Map();
12965
+ for (const [arity, argumentIndex, ...propertyNames] of entries) {
12966
+ const byArgument = properties2.get(arity) ?? /* @__PURE__ */ new Map();
12967
+ byArgument.set(
12968
+ argumentIndex,
12969
+ Array_exports.isArrayEmpty(propertyNames) ? true : new Set(propertyNames)
12970
+ );
12971
+ properties2.set(arity, byArgument);
12972
+ }
12973
+ return properties2;
12974
+ };
12975
+ var direct = (...entries) => ({ direct: directByArity(...entries) });
12976
+ var properties = (...entries) => ({
12977
+ properties: propertiesByArity(...entries)
12978
+ });
12979
+ var unaryCallback = direct([1, 0]);
12980
+ var unaryDualCallback = direct([1, 0], [2, 1]);
12981
+ var unaryDualCallbackWithOptions = direct([1, 0], [2, 0, 1], [3, 1]);
12982
+ var binaryDualCallback = direct([2, 1], [3, 2]);
12983
+ var binaryDualCallbackWithOptions = direct([2, 1], [3, 1, 2], [4, 2]);
12984
+ var successAndFailureProperties = properties(
12985
+ [1, 0, "onFailure", "onSuccess"],
12986
+ [2, 1, "onFailure", "onSuccess"]
12987
+ );
12988
+ var taggedCallback = direct([2, 1], [3, 1, 2], [4, 2, 3]);
12989
+ var taggedCallbackMap = {
12990
+ direct: directByArity([2, 1], [3, 2]),
12991
+ properties: propertiesByArity([1, 0], [2, 0], [2, 1], [3, 1])
12992
+ };
12993
+ var reasonCallback = direct([3, 2], [4, 2, 3], [5, 3, 4]);
12994
+ var reasonCallbackMap = {
12995
+ direct: directByArity([3, 2], [4, 3]),
12996
+ properties: propertiesByArity([2, 1], [3, 1], [3, 2], [4, 2])
12997
+ };
12998
+ var predicateAndCallback = direct([2, 0, 1], [3, 0, 1, 2], [4, 1, 2, 3]);
12999
+ var deferredCallbackByApi = /* @__PURE__ */ new Map([
13000
+ ["Effect.acquireRelease", direct([2, 1], [3, 1])],
13001
+ ["Effect.acquireUseRelease", direct([3, 1, 2])],
13002
+ ["Effect.addFinalizer", unaryCallback],
13003
+ ["Effect.andThen", unaryDualCallback],
13004
+ ["Effect.bind", binaryDualCallback],
13005
+ ["Effect.callback", unaryCallback],
13006
+ ["Effect.catch", unaryDualCallback],
13007
+ ["Effect.catchCause", unaryDualCallback],
13008
+ ["Effect.catchCauseFilter", predicateAndCallback],
13009
+ ["Effect.catchCauseIf", predicateAndCallback],
13010
+ ["Effect.catchDefect", unaryDualCallback],
13011
+ ["Effect.catchFilter", predicateAndCallback],
13012
+ ["Effect.catchIf", predicateAndCallback],
13013
+ ["Effect.catchReason", reasonCallback],
13014
+ ["Effect.catchReasons", reasonCallbackMap],
13015
+ ["Effect.catchTag", taggedCallback],
13016
+ ["Effect.catchTags", taggedCallbackMap],
13017
+ ["Effect.clockWith", unaryCallback],
13018
+ ["Effect.contextWith", unaryCallback],
13019
+ ["Effect.effectify", direct([1, 0], [2, 0, 1], [3, 0, 1, 2])],
13020
+ ["Effect.failCauseSync", unaryCallback],
13021
+ ["Effect.failSync", unaryCallback],
13022
+ ["Effect.filter", unaryDualCallbackWithOptions],
13023
+ ["Effect.filterMap", unaryDualCallback],
13024
+ ["Effect.filterMapEffect", unaryDualCallbackWithOptions],
13025
+ ["Effect.filterMapOrElse", direct([2, 0, 1], [3, 1, 2])],
13026
+ ["Effect.filterMapOrFail", direct([1, 0], [2, 0, 1], [3, 1, 2])],
13027
+ ["Effect.filterOrElse", direct([2, 0, 1], [3, 1, 2])],
13028
+ ["Effect.filterOrFail", direct([1, 0], [2, 0, 1], [3, 1, 2])],
13029
+ ["Effect.findFirst", unaryDualCallback],
13030
+ ["Effect.findFirstFilter", unaryDualCallback],
13031
+ ["Effect.flatMap", unaryDualCallback],
13032
+ ["Effect.forEach", unaryDualCallbackWithOptions],
13033
+ ["Effect.gen", direct([1, 0], [2, 1])],
13034
+ ["Effect.interruptibleMask", unaryCallback],
13035
+ ["Effect.let", binaryDualCallback],
13036
+ ["Effect.map", unaryDualCallback],
13037
+ ["Effect.mapBoth", successAndFailureProperties],
13038
+ ["Effect.mapError", unaryDualCallback],
13039
+ ["Effect.match", successAndFailureProperties],
13040
+ ["Effect.matchCause", successAndFailureProperties],
13041
+ ["Effect.matchCauseEffect", successAndFailureProperties],
13042
+ ["Effect.matchEffect", successAndFailureProperties],
13043
+ ["Effect.onError", unaryDualCallback],
13044
+ ["Effect.onErrorFilter", predicateAndCallback],
13045
+ ["Effect.onErrorIf", predicateAndCallback],
13046
+ ["Effect.onExit", unaryDualCallback],
13047
+ ["Effect.onExitFilter", predicateAndCallback],
13048
+ ["Effect.onExitIf", predicateAndCallback],
13049
+ ["Effect.onExitPrimitive", direct([2, 1], [3, 1])],
13050
+ ["Effect.onInterrupt", unaryDualCallback],
13051
+ ["Effect.orElseSucceed", unaryDualCallback],
13052
+ ["Effect.partition", unaryDualCallbackWithOptions],
13053
+ ["Effect.promise", unaryCallback],
13054
+ ["Effect.reduce", direct([2, 0, 1], [3, 1, 2])],
13055
+ [
13056
+ "Effect.repeat",
13057
+ properties([1, 0, "while", "until"], [2, 1, "while", "until"])
13058
+ ],
13059
+ ["Effect.repeatOrElse", binaryDualCallback],
13060
+ [
13061
+ "Effect.retry",
13062
+ properties([1, 0, "while", "until"], [2, 1, "while", "until"])
13063
+ ],
13064
+ ["Effect.retryOrElse", binaryDualCallback],
13065
+ ["Effect.scopedWith", unaryCallback],
13066
+ ["Effect.suspend", unaryCallback],
13067
+ ["Effect.sync", unaryCallback],
13068
+ ["Effect.tap", unaryDualCallback],
13069
+ ["Effect.tapCause", unaryDualCallback],
13070
+ ["Effect.tapCauseFilter", predicateAndCallback],
13071
+ ["Effect.tapCauseIf", predicateAndCallback],
13072
+ ["Effect.tapDefect", unaryDualCallback],
13073
+ ["Effect.tapError", unaryDualCallback],
13074
+ ["Effect.tapErrorTag", taggedCallback],
13075
+ ["Effect.timeoutOrElse", properties([1, 0, "orElse"], [2, 1, "orElse"])],
13076
+ ["Effect.track", direct([2, 1], [3, 2])],
13077
+ ["Effect.trackDefects", direct([2, 1], [3, 2])],
13078
+ ["Effect.trackDuration", direct([2, 1], [3, 2])],
13079
+ ["Effect.trackErrors", direct([2, 1], [3, 2])],
13080
+ ["Effect.trackSuccesses", direct([2, 1], [3, 2])],
13081
+ [
13082
+ "Effect.try",
13083
+ {
13084
+ direct: directByArity([1, 0]),
13085
+ properties: propertiesByArity([1, 0, "try", "catch"])
13086
+ }
13087
+ ],
13088
+ [
13089
+ "Effect.tryPromise",
13090
+ {
13091
+ direct: directByArity([1, 0]),
13092
+ properties: propertiesByArity([1, 0, "try", "catch"])
13093
+ }
13094
+ ],
13095
+ ["Effect.uninterruptibleMask", unaryCallback],
13096
+ ["Effect.updateContext", unaryDualCallback],
13097
+ ["Effect.updateService", binaryDualCallback],
13098
+ [
13099
+ "Effect.updateServiceScoped",
13100
+ {
13101
+ direct: directByArity([2, 1], [3, 1]),
13102
+ properties: propertiesByArity([3, 2, "reset"])
13103
+ }
13104
+ ],
13105
+ ["Effect.useSpan", direct([2, 1], [3, 2])],
13106
+ ["Effect.validate", unaryDualCallbackWithOptions],
13107
+ ["Effect.whileLoop", properties([1, 0, "while", "body", "step"])],
13108
+ [
13109
+ "Effect.withExecutionPlan",
13110
+ properties([2, 1, "onEvent"], [3, 2, "onEvent"])
13111
+ ],
13112
+ ["Effect.withFiber", unaryCallback],
13113
+ ["Effect.zipWith", binaryDualCallbackWithOptions],
13114
+ ["Effect.race", properties([2, 1, "onWinner"], [3, 2, "onWinner"])],
13115
+ ["Effect.raceFirst", properties([2, 1, "onWinner"], [3, 2, "onWinner"])],
13116
+ ["Effect.raceAll", properties([2, 1, "onWinner"])],
13117
+ ["Effect.raceAllFirst", properties([2, 1, "onWinner"])],
13118
+ ["Stream.bind", binaryDualCallbackWithOptions],
13119
+ ["Stream.bindEffect", binaryDualCallbackWithOptions],
13120
+ ["Stream.callback", unaryCallback],
13121
+ ["Stream.catch", unaryDualCallback],
13122
+ ["Stream.catchCause", unaryDualCallback],
13123
+ ["Stream.catchCauseFilter", predicateAndCallback],
13124
+ ["Stream.catchCauseIf", predicateAndCallback],
13125
+ ["Stream.catchFilter", predicateAndCallback],
13126
+ ["Stream.catchIf", predicateAndCallback],
13127
+ ["Stream.catchReason", reasonCallback],
13128
+ ["Stream.catchReasons", reasonCallbackMap],
13129
+ ["Stream.catchTag", taggedCallback],
13130
+ ["Stream.catchTags", taggedCallbackMap],
13131
+ ["Stream.changesWith", unaryDualCallback],
13132
+ ["Stream.changesWithEffect", unaryDualCallback],
13133
+ ["Stream.combine", direct([3, 1, 2], [4, 2, 3])],
13134
+ ["Stream.combineArray", direct([3, 1, 2], [4, 2, 3])],
13135
+ ["Stream.crossWith", binaryDualCallback],
13136
+ ["Stream.dropUntil", unaryDualCallback],
13137
+ ["Stream.dropUntilEffect", unaryDualCallback],
13138
+ ["Stream.dropWhile", unaryDualCallback],
13139
+ ["Stream.dropWhileEffect", unaryDualCallback],
13140
+ ["Stream.dropWhileFilter", unaryDualCallback],
13141
+ ["Stream.failCauseSync", unaryCallback],
13142
+ ["Stream.failSync", unaryCallback],
13143
+ ["Stream.filter", unaryDualCallback],
13144
+ ["Stream.filterEffect", unaryDualCallback],
13145
+ ["Stream.filterMap", unaryDualCallback],
13146
+ ["Stream.filterMapEffect", unaryDualCallback],
13147
+ ["Stream.flatMap", unaryDualCallbackWithOptions],
13148
+ ["Stream.fromAsyncIterable", direct([2, 1])],
13149
+ ["Stream.fromReadableStream", properties([1, 0, "evaluate", "onError"])],
13150
+ ["Stream.groupAdjacentBy", unaryDualCallback],
13151
+ ["Stream.groupBy", unaryDualCallbackWithOptions],
13152
+ ["Stream.groupByKey", unaryDualCallbackWithOptions],
13153
+ ["Stream.iterate", direct([2, 1])],
13154
+ ["Stream.limitBytes", direct([2, 1], [3, 2])],
13155
+ ["Stream.map", unaryDualCallback],
13156
+ [
13157
+ "Stream.mapAccum",
13158
+ {
13159
+ direct: directByArity([2, 0, 1], [3, 0, 1, 2], [4, 1, 2]),
13160
+ properties: propertiesByArity([3, 2, "onHalt"], [4, 3, "onHalt"])
13161
+ }
13162
+ ],
13163
+ [
13164
+ "Stream.mapAccumArray",
13165
+ {
13166
+ direct: directByArity([2, 0, 1], [3, 0, 1, 2], [4, 1, 2]),
13167
+ properties: propertiesByArity([3, 2, "onHalt"], [4, 3, "onHalt"])
13168
+ }
13169
+ ],
13170
+ [
13171
+ "Stream.mapAccumArrayEffect",
13172
+ {
13173
+ direct: directByArity([2, 0, 1], [3, 0, 1, 2], [4, 1, 2]),
13174
+ properties: propertiesByArity([3, 2, "onHalt"], [4, 3, "onHalt"])
13175
+ }
13176
+ ],
13177
+ [
13178
+ "Stream.mapAccumEffect",
13179
+ {
13180
+ direct: directByArity([2, 0, 1], [3, 0, 1, 2], [4, 1, 2]),
13181
+ properties: propertiesByArity([3, 2, "onHalt"], [4, 3, "onHalt"])
13182
+ }
13183
+ ],
13184
+ ["Stream.mapArray", unaryDualCallback],
13185
+ ["Stream.mapArrayEffect", unaryDualCallback],
13186
+ ["Stream.mapBoth", successAndFailureProperties],
13187
+ ["Stream.mapEffect", unaryDualCallbackWithOptions],
13188
+ ["Stream.mapError", unaryDualCallback],
13189
+ ["Stream.let", binaryDualCallback],
13190
+ ["Stream.onError", unaryDualCallback],
13191
+ ["Stream.onExit", unaryDualCallback],
13192
+ ["Stream.onFirst", unaryDualCallback],
13193
+ ["Stream.orElseIfEmpty", unaryDualCallback],
13194
+ ["Stream.orElseSucceed", unaryDualCallback],
13195
+ ["Stream.paginate", direct([2, 1])],
13196
+ ["Stream.partition", unaryDualCallbackWithOptions],
13197
+ ["Stream.partitionEffect", unaryDualCallbackWithOptions],
13198
+ ["Stream.partitionQueue", unaryDualCallbackWithOptions],
13199
+ ["Stream.runFold", direct([2, 0, 1], [3, 1, 2])],
13200
+ ["Stream.runFoldEffect", direct([2, 0, 1], [3, 1, 2])],
13201
+ ["Stream.runForEach", unaryDualCallback],
13202
+ ["Stream.runForEachArray", unaryDualCallback],
13203
+ ["Stream.runForEachWhile", unaryDualCallback],
13204
+ ["Stream.scan", direct([2, 1], [3, 2])],
13205
+ ["Stream.scanEffect", direct([2, 1], [3, 2])],
13206
+ ["Stream.split", unaryDualCallback],
13207
+ ["Stream.suspend", unaryCallback],
13208
+ ["Stream.switchMap", unaryDualCallbackWithOptions],
13209
+ ["Stream.sync", unaryCallback],
13210
+ ["Stream.takeUntil", unaryDualCallbackWithOptions],
13211
+ ["Stream.takeUntilEffect", unaryDualCallbackWithOptions],
13212
+ ["Stream.takeWhile", unaryDualCallback],
13213
+ ["Stream.takeWhileEffect", unaryDualCallback],
13214
+ ["Stream.takeWhileFilter", unaryDualCallback],
13215
+ ["Stream.tap", unaryDualCallbackWithOptions],
13216
+ [
13217
+ "Stream.tapBoth",
13218
+ properties([1, 0, "onElement", "onError"], [2, 1, "onElement", "onError"])
13219
+ ],
13220
+ ["Stream.tapCause", unaryDualCallback],
13221
+ ["Stream.tapError", unaryDualCallback],
13222
+ ["Stream.throttle", properties([1, 0, "cost"], [2, 1, "cost"])],
13223
+ ["Stream.throttleEffect", properties([1, 0, "cost"], [2, 1, "cost"])],
13224
+ ["Stream.timeoutOrElse", properties([1, 0, "orElse"], [2, 1, "orElse"])],
13225
+ ["Stream.transformPull", direct([2, 1])],
13226
+ ["Stream.transformPullBracket", direct([2, 1])],
13227
+ ["Stream.unfold", direct([2, 1])],
13228
+ ["Stream.updateContext", unaryDualCallback],
13229
+ ["Stream.updateService", binaryDualCallback],
13230
+ [
13231
+ "Stream.withExecutionPlan",
13232
+ properties([2, 1, "onEvent"], [3, 2, "onEvent"])
13233
+ ],
13234
+ ["Stream.zipLatestWith", binaryDualCallback],
13235
+ ["Stream.zipWith", binaryDualCallback],
13236
+ ["Stream.zipWithArray", binaryDualCallback]
13237
+ ]);
13238
+ var isEffectFunctionBody = (argument, call) => {
13239
+ const maybeFirstArgument = Array_exports.head(call.arguments);
13240
+ if (Option_exports.contains(maybeFirstArgument, argument)) {
13241
+ return true;
13242
+ }
13243
+ return Option_exports.exists(
13244
+ maybeFirstArgument,
13245
+ (argument2) => isObjectExpression(innermostExpression2(argument2))
13246
+ ) && Option_exports.contains(Array_exports.get(call.arguments, 1), argument);
13247
+ };
13248
+ var isDeferredDirectEffectApiCallback = (argument, call, key) => {
13249
+ if (effectFunctionFactories.has(key)) {
13250
+ return isEffectFunctionBody(argument, call);
13251
+ }
13252
+ const maybeArgumentIndex = Array_exports.findFirstIndex(
13253
+ call.arguments,
13254
+ (candidate) => candidate === argument
13255
+ );
13256
+ const maybePositions = Option_exports.fromNullishOr(
13257
+ deferredCallbackByApi.get(key)?.direct?.get(call.arguments.length)
13258
+ );
13259
+ return Option_exports.exists(
13260
+ maybeArgumentIndex,
13261
+ (argumentIndex) => Option_exports.exists(maybePositions, (positions) => positions.has(argumentIndex))
13262
+ );
13263
+ };
13264
+ var isDeferredObjectEffectApiCallback = (property, argument, call, key) => {
13265
+ const maybeArgumentIndex = Array_exports.findFirstIndex(
13266
+ call.arguments,
13267
+ (candidate) => candidate === argument
13268
+ );
13269
+ const maybePropertyName = staticPropertyName(property);
13270
+ const propertiesByArgument = deferredCallbackByApi.get(key)?.properties?.get(call.arguments.length);
13271
+ return Option_exports.exists(maybeArgumentIndex, (argumentIndex) => {
13272
+ const propertyNames = propertiesByArgument?.get(argumentIndex);
13273
+ return propertyNames === true || propertyNames !== void 0 && Option_exports.exists(
13274
+ maybePropertyName,
13275
+ (propertyName) => propertyNames.has(propertyName)
13276
+ );
13277
+ });
13278
+ };
13279
+ var isEffectOrStreamCallback = (references, fn3) => {
13280
+ const maybeDirectCall = enclosingCallArgument(fn3);
13281
+ if (Option_exports.isSome(maybeDirectCall)) {
13282
+ return Option_exports.exists(
13283
+ apiCallKey(references, maybeDirectCall.value.call),
13284
+ (key) => isDeferredDirectEffectApiCallback(
13285
+ maybeDirectCall.value.argument,
13286
+ maybeDirectCall.value.call,
13287
+ key
13288
+ )
13289
+ );
13290
+ }
13291
+ const maybeProperty = enclosingPropertyValue(fn3);
13292
+ if (Option_exports.isNone(maybeProperty)) {
13293
+ return false;
13294
+ }
13295
+ const property = maybeProperty.value;
13296
+ const object = property.parent;
13297
+ if (object.type !== "ObjectExpression") {
13298
+ return false;
13299
+ }
13300
+ const maybeCall = enclosingCallArgument(object);
13301
+ if (Option_exports.isNone(maybeCall)) {
13302
+ return false;
13303
+ }
13304
+ const { argument, call } = maybeCall.value;
13305
+ return Option_exports.exists(
13306
+ apiCallKey(references, call),
13307
+ (key) => isDeferredObjectEffectApiCallback(property, argument, call, key)
13308
+ );
13309
+ };
13310
+ var isInlineConfigFunction = (references, fn3, propertyNames, factoryKeys) => {
13311
+ const maybeProperty = enclosingPropertyValue(fn3);
13312
+ if (Option_exports.isNone(maybeProperty)) {
13313
+ return false;
13314
+ }
13315
+ const property = maybeProperty.value;
13316
+ if (property.parent.type !== "ObjectExpression" || !Option_exports.exists(
13317
+ staticPropertyName(property),
13318
+ (name) => propertyNames.has(name)
13319
+ )) {
13320
+ return false;
13321
+ }
13322
+ const maybeCall = enclosingCallArgument(property.parent);
13323
+ if (Option_exports.isNone(maybeCall)) {
13324
+ return false;
13325
+ }
13326
+ return Option_exports.exists(
13327
+ apiCallKey(references, maybeCall.value.call),
13328
+ (key) => factoryKeys.has(key)
13329
+ );
13330
+ };
13331
+ var hasFactoryAncestor = (references, node, factoryKey) => {
13332
+ const parent = node.parent;
13333
+ if (parent === null) {
13334
+ return false;
13335
+ }
13336
+ if (parent.type === "CallExpression" && Option_exports.contains(apiCallKey(references, parent), factoryKey)) {
13337
+ return true;
13338
+ }
13339
+ return hasFactoryAncestor(references, parent, factoryKey);
13340
+ };
13341
+ var isNestedLifecycleFunction = (references, fn3) => {
13342
+ const maybeProperty = enclosingPropertyValue(fn3);
13343
+ if (Option_exports.isNone(maybeProperty)) {
13344
+ return false;
13345
+ }
13346
+ const property = maybeProperty.value;
13347
+ if (property.parent.type !== "ObjectExpression") {
13348
+ return false;
13349
+ }
13350
+ if (Option_exports.isNone(enclosingCallArgument(property.parent))) {
13351
+ return false;
13352
+ }
13353
+ const maybePropertyName = staticPropertyName(property);
13354
+ const isSubscriptionEffect = Option_exports.contains(
13355
+ maybePropertyName,
13356
+ "dependenciesToStream"
13357
+ );
13358
+ if (isSubscriptionEffect && hasFactoryAncestor(references, fn3, "Subscription.make")) {
13359
+ return true;
13360
+ }
13361
+ const isManagedResourceEffect = Option_exports.exists(
13362
+ maybePropertyName,
13363
+ (name) => name === "acquire" || name === "release"
13364
+ );
13365
+ return isManagedResourceEffect && hasFactoryAncestor(references, fn3, "ManagedResource.make");
13366
+ };
13367
+ var commandAndMountEffectProperties = /* @__PURE__ */ new Set(["execute"]);
13368
+ var commandAndMountFactories = /* @__PURE__ */ new Set([
13369
+ "Command.define",
13370
+ "Mount.define",
13371
+ "Mount.defineStream"
13372
+ ]);
13373
+ var isDeferredFunction = (references, fn3) => isEffectOrStreamCallback(references, fn3) || isInlineConfigFunction(
13374
+ references,
13375
+ fn3,
13376
+ commandAndMountEffectProperties,
13377
+ commandAndMountFactories
13378
+ ) || isNestedLifecycleFunction(references, fn3);
13379
+ var isInsideEffectBoundary = (references, node) => {
13380
+ const parent = node.parent;
13381
+ if (parent === null) {
13382
+ return false;
13383
+ }
13384
+ if (isFunction3(parent) && isDeferredFunction(references, parent)) {
13385
+ return true;
13386
+ }
13387
+ return isInsideEffectBoundary(references, parent);
13388
+ };
13389
+ var callOperation = (references, node) => Option_exports.flatMap(
13390
+ globalPathKey(references, node.callee),
13391
+ (key) => Option_exports.fromNullishOr(impureCallByPath.get(key))
13392
+ );
13393
+ var newOperation = (references, node) => Array_exports.isArrayEmpty(node.arguments) && Option_exports.contains(globalPathKey(references, node.callee), "Date") ? Option_exports.some(newDateOperation) : Option_exports.none();
13394
+ var diagnosticMessage2 = ({ display, guidance }) => `${display} is outside a recognized callback that Effect or Foldkit defers until execution. ${guidance} Obtain the value in a deferred Effect or lifecycle execution callback and return it in a Message. Assigning it to a local variable or passing it as a Command argument does not defer the call.`;
13395
+ var noImpureCallAtDecisionTime = Rule_exports.define({
13396
+ name: "no-impure-call-at-decision-time",
13397
+ meta: Rule_exports.meta({
13398
+ type: "problem",
13399
+ description: "Keep direct time and randomness calls inside deferred Effect and lifecycle execution callbacks."
13400
+ }),
13401
+ create: function* () {
13402
+ const ctx = yield* RuleContext;
13403
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
13404
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
13405
+ const report = (node, maybeOperation) => Option_exports.match(maybeOperation, {
13406
+ onNone: () => Effect_exports.void,
13407
+ onSome: (operation) => isInsideEffectBoundary(references, node) ? Effect_exports.void : ctx.report(
13408
+ Diagnostic_exports.make({
13409
+ node,
13410
+ message: diagnosticMessage2(operation)
13411
+ })
13412
+ )
13413
+ });
13414
+ return {
13415
+ CallExpression: (node) => node.type === "CallExpression" ? report(node, callOperation(references, node)) : Effect_exports.void,
13416
+ NewExpression: (node) => node.type === "NewExpression" ? report(node, newOperation(references, node)) : Effect_exports.void
13417
+ };
13418
+ }
13419
+ });
13420
+
12263
13421
  // src/rules/no-module-level-mutable-state.ts
12264
13422
  var isMutableDeclaration = (node) => (node.kind === "let" || node.kind === "var") && node.declare !== true;
12265
13423
  var topLevelMutableDeclarations = (program) => program.body.flatMap((statement) => {
@@ -12329,24 +13487,6 @@ var isInsideTypeQuery = (node) => {
12329
13487
  }
12330
13488
  return false;
12331
13489
  };
12332
- var staticMemberName = (node) => {
12333
- if (!node.computed && node.property.type === "Identifier") {
12334
- return node.property.name;
12335
- }
12336
- if (node.computed && node.property.type === "Literal" && typeof node.property.value === "string") {
12337
- return node.property.value;
12338
- }
12339
- return void 0;
12340
- };
12341
- var staticPropertyName4 = (property) => {
12342
- if (property.key.type === "Identifier") {
12343
- return property.key.name;
12344
- }
12345
- if (property.key.type === "Literal" && typeof property.key.value === "string") {
12346
- return property.key.value;
12347
- }
12348
- return void 0;
12349
- };
12350
13490
  var destructuringSource = (node) => {
12351
13491
  const parent = node.parent;
12352
13492
  if (parent.type === "VariableDeclarator" && parent.id === node) {
@@ -12365,19 +13505,6 @@ var restrictedGlobalDiagnostic = (node, name) => Diagnostic_exports.make({
12365
13505
  node,
12366
13506
  message: `Global \`${name}\` is not portable across Foldkit server targets. Use a server API available everywhere you deploy or pass the value into the entry.`
12367
13507
  });
12368
- var indexReferences2 = (scopes) => {
12369
- const references = /* @__PURE__ */ new WeakMap();
12370
- for (const scope3 of scopes) {
12371
- for (const reference of scope3.references) {
12372
- references.set(reference.identifier, reference);
12373
- }
12374
- }
12375
- return references;
12376
- };
12377
- var isUnshadowedGlobalReference = (references, node) => {
12378
- const reference = references.get(node);
12379
- return reference !== void 0 && (reference.resolved === null || Array_exports.isArrayEmpty(reference.resolved.defs));
12380
- };
12381
13508
  var noNonportableServerGlobals = Rule_exports.define({
12382
13509
  name: "no-nonportable-server-globals",
12383
13510
  meta: Rule_exports.meta({
@@ -12386,23 +13513,23 @@ var noNonportableServerGlobals = Rule_exports.define({
12386
13513
  }),
12387
13514
  create: function* () {
12388
13515
  const ctx = yield* RuleContext;
12389
- const references = indexReferences2(ctx.sourceCode.scopeManager.scopes);
13516
+ const references = indexReferences(ctx.sourceCode.scopeManager.scopes);
12390
13517
  return {
12391
13518
  Identifier: (node) => {
12392
13519
  if (node.type !== "Identifier" || !restrictedGlobalNames.has(node.name) || isInsideTypeQuery(node)) {
12393
13520
  return Effect_exports.void;
12394
13521
  }
12395
- return isUnshadowedGlobalReference(references, node) ? ctx.report(restrictedGlobalDiagnostic(node, node.name)) : Effect_exports.void;
13522
+ return isUnshadowedReference(references, node) ? ctx.report(restrictedGlobalDiagnostic(node, node.name)) : Effect_exports.void;
12396
13523
  },
12397
13524
  MemberExpression: (node) => {
12398
13525
  if (node.type !== "MemberExpression" || node.object.type !== "Identifier" || node.object.name !== "globalThis") {
12399
13526
  return Effect_exports.void;
12400
13527
  }
12401
- const memberName = staticMemberName(node);
12402
- if (memberName === void 0 || !restrictedGlobalNames.has(memberName)) {
13528
+ const maybeMemberName = staticMemberName(node);
13529
+ if (Option_exports.isNone(maybeMemberName) || !restrictedGlobalNames.has(maybeMemberName.value)) {
12403
13530
  return Effect_exports.void;
12404
13531
  }
12405
- return isUnshadowedGlobalReference(references, node.object) ? ctx.report(restrictedGlobalDiagnostic(node, memberName)) : Effect_exports.void;
13532
+ return isUnshadowedReference(references, node.object) ? ctx.report(restrictedGlobalDiagnostic(node, maybeMemberName.value)) : Effect_exports.void;
12406
13533
  },
12407
13534
  ObjectPattern: (node) => {
12408
13535
  if (node.type !== "ObjectPattern") {
@@ -12416,10 +13543,10 @@ var noNonportableServerGlobals = Rule_exports.define({
12416
13543
  if (property.type !== "Property") {
12417
13544
  return [];
12418
13545
  }
12419
- const name = staticPropertyName4(property);
12420
- return name !== void 0 && restrictedGlobalNames.has(name) ? [{ name, property }] : [];
13546
+ const maybeName = staticPropertyName(property);
13547
+ return Option_exports.isSome(maybeName) && restrictedGlobalNames.has(maybeName.value) ? [{ name: maybeName.value, property }] : [];
12421
13548
  });
12422
- return isUnshadowedGlobalReference(references, source) ? Effect_exports.forEach(
13549
+ return isUnshadowedReference(references, source) ? Effect_exports.forEach(
12423
13550
  restrictedProperties,
12424
13551
  ({ name, property }) => ctx.report(restrictedGlobalDiagnostic(property, name)),
12425
13552
  { discard: true }
@@ -12438,6 +13565,8 @@ var noNoopMessage = Rule_exports.define({
12438
13565
  }),
12439
13566
  create: function* () {
12440
13567
  const ctx = yield* RuleContext;
13568
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
13569
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
12441
13570
  const messageUnionBindings = /* @__PURE__ */ new Set();
12442
13571
  return {
12443
13572
  Program: (node) => {
@@ -12447,7 +13576,7 @@ var noNoopMessage = Rule_exports.define({
12447
13576
  CallExpression: (node) => {
12448
13577
  if (!isCallExpression(node)) return Effect_exports.void;
12449
13578
  return Effect_exports.forEach(
12450
- messageCases(node, messageUnionBindings),
13579
+ messageCases(node, messageUnionBindings, references),
12451
13580
  (messageCase) => ["NoOp", "Noop", "NoOperation"].includes(messageCase.name) ? ctx.report(
12452
13581
  Diagnostic_exports.make({
12453
13582
  node: messageCase.nameNode,
@@ -12586,15 +13715,15 @@ var keyPropertyValue = (configObject) => Option_exports.map(
12586
13715
  Array_exports.findFirst(configObject.properties, isKeyProperty),
12587
13716
  (property) => property.value
12588
13717
  );
12589
- var attributeEventName = (node) => {
12590
- if (!calleeMatchesHelperName(node.callee, "Attribute")) {
13718
+ var attributeEventName = (node, references) => {
13719
+ if (!isFoldkitHtmlBuilderMember(node.callee, "Attribute", references)) {
12591
13720
  return Option_exports.none();
12592
13721
  }
12593
13722
  const [firstArgument] = node.arguments;
12594
13723
  return Option_exports.filter(staticStringValue(firstArgument), isRawEventName);
12595
13724
  };
12596
- var propEventName = (node) => {
12597
- if (!calleeMatchesHelperName(node.callee, "Prop")) {
13725
+ var propEventName = (node, references) => {
13726
+ if (!isFoldkitHtmlBuilderMember(node.callee, "Prop", references)) {
12598
13727
  return Option_exports.none();
12599
13728
  }
12600
13729
  const [configArgument] = node.arguments;
@@ -12615,14 +13744,16 @@ var noRawDomEventAttributes = Rule_exports.define({
12615
13744
  }),
12616
13745
  create: function* () {
12617
13746
  const ctx = yield* RuleContext;
13747
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
13748
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
12618
13749
  return {
12619
13750
  CallExpression: (node) => {
12620
13751
  if (!isCallExpression(node)) {
12621
13752
  return Effect_exports.void;
12622
13753
  }
12623
13754
  return pipe(
12624
- attributeEventName(node),
12625
- Option_exports.orElse(() => propEventName(node)),
13755
+ attributeEventName(node, references),
13756
+ Option_exports.orElse(() => propEventName(node, references)),
12626
13757
  Option_exports.match({
12627
13758
  onNone: () => Effect_exports.void,
12628
13759
  onSome: (attributeName) => ctx.report(
@@ -12640,7 +13771,16 @@ var noRawDomEventAttributes = Rule_exports.define({
12640
13771
 
12641
13772
  // src/rules/no-spread-in-evo.ts
12642
13773
  var nestedEvoMessage = (fieldName) => `The updater for field \`${fieldName}\` rebuilds the record with a spread, stepping outside the strict Model update path. Use a nested \`evo\` instead: \`${fieldName}: () => evo(model.${fieldName}, { ... })\`.`;
12643
- var isEvoCall = (node) => {
13774
+ var isEvoCall = (node, references) => {
13775
+ if (references !== void 0) {
13776
+ return Option_exports.exists(
13777
+ resolveFoldkitApiPath(references, node.callee),
13778
+ (path) => {
13779
+ const [namespace, methodName, extraMember] = path;
13780
+ return namespace === "Struct" && methodName === "evo" && extraMember === void 0;
13781
+ }
13782
+ );
13783
+ }
12644
13784
  const callee = node.callee;
12645
13785
  if (callee.type === "Identifier") {
12646
13786
  return callee.name === "evo";
@@ -12670,8 +13810,8 @@ var hasComputedKey = (objectExpression) => objectExpression.properties.some(
12670
13810
  (property) => property.type === "Property" && property.computed
12671
13811
  );
12672
13812
  var updaterFieldName = (property) => !property.computed && property.key.type === "Identifier" ? property.key.name : "<key>";
12673
- var spreadRebuiltFields = (node) => {
12674
- if (!isEvoCall(node)) return [];
13813
+ var spreadRebuiltFields = (node, references) => {
13814
+ if (!isEvoCall(node, references)) return [];
12675
13815
  const [, updates] = node.arguments;
12676
13816
  if (updates === void 0 || updates.type !== "ObjectExpression") return [];
12677
13817
  return updates.properties.flatMap((property) => {
@@ -12698,11 +13838,13 @@ var noSpreadInEvo = Rule_exports.define({
12698
13838
  }),
12699
13839
  create: function* () {
12700
13840
  const ctx = yield* RuleContext;
13841
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
13842
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
12701
13843
  return {
12702
13844
  CallExpression: (node) => {
12703
13845
  if (!isCallExpression(node)) return Effect_exports.void;
12704
13846
  return Effect_exports.forEach(
12705
- spreadRebuiltFields(node),
13847
+ spreadRebuiltFields(node, references),
12706
13848
  ({ fieldName, bodyObject }) => ctx.report(
12707
13849
  Diagnostic_exports.make({
12708
13850
  node: bodyObject,
@@ -12776,16 +13918,149 @@ var preferCallableMessageConstructor = Rule_exports.define({
12776
13918
  }
12777
13919
  });
12778
13920
 
13921
+ // src/rules/prefer-effect-module-names.ts
13922
+ var EFFECT_MODULE_NAME = /^[A-Z]/;
13923
+ var isSemanticConflictAlias = (name, localName) => localName === `Effect${name}`;
13924
+ var importedName2 = (specifier) => {
13925
+ if (isIdentifier(specifier.imported)) {
13926
+ return Option_exports.some(specifier.imported.name);
13927
+ }
13928
+ if (isStringLiteral(specifier.imported)) {
13929
+ return Option_exports.some(specifier.imported.value);
13930
+ }
13931
+ return Option_exports.none();
13932
+ };
13933
+ var importVariable = (ctx, specifier) => {
13934
+ const scopeManager = ctx.sourceCode.scopeManager;
13935
+ if (scopeManager === void 0) {
13936
+ return void 0;
13937
+ }
13938
+ return Array_exports.findFirst(
13939
+ scopeManager.getDeclaredVariables(specifier),
13940
+ (variable) => variable.name === specifier.local.name
13941
+ ).pipe(Option_exports.getOrUndefined);
13942
+ };
13943
+ var hasUnshadowedReference = (ctx, name) => Array_exports.some(
13944
+ ctx.sourceCode.scopeManager?.scopes ?? [],
13945
+ (scope3) => Array_exports.some(
13946
+ scope3.references,
13947
+ (reference) => reference.identifier.name === name && (reference.resolved === null || Array_exports.isArrayEmpty(reference.resolved.defs))
13948
+ )
13949
+ );
13950
+ var preservesObservableName = (node) => {
13951
+ const parent = node.parent;
13952
+ if (parent === null) {
13953
+ return true;
13954
+ }
13955
+ if (parent.type === "Property" && parent.shorthand) {
13956
+ return false;
13957
+ }
13958
+ return parent.type !== "ExportSpecifier";
13959
+ };
13960
+ var hasInterveningBinding = (scope3, importScope, name) => {
13961
+ if (scope3 === importScope) {
13962
+ return false;
13963
+ }
13964
+ if (scope3.set.get(name) !== void 0 || scope3.upper === null) {
13965
+ return true;
13966
+ }
13967
+ return hasInterveningBinding(scope3.upper, importScope, name);
13968
+ };
13969
+ var referenceCanBeRenamed = (reference, importScope, name) => preservesObservableName(reference.identifier) && !hasInterveningBinding(reference.from, importScope, name);
13970
+ var aliasedEffectModule = (specifier) => {
13971
+ if (specifier.type !== "ImportSpecifier" || specifier.importKind === "type") {
13972
+ return Option_exports.none();
13973
+ }
13974
+ return Option_exports.flatMap(
13975
+ importedName2(specifier),
13976
+ (name) => EFFECT_MODULE_NAME.test(name) && specifier.local.name !== name && !isSemanticConflictAlias(name, specifier.local.name) ? Option_exports.some({ specifier, name }) : Option_exports.none()
13977
+ );
13978
+ };
13979
+ var importsEffectModuleAsAlias = (variable, name) => Array_exports.some(variable.defs, (definition) => {
13980
+ if (definition.type !== "ImportBinding" || definition.node.type !== "ImportSpecifier") {
13981
+ return false;
13982
+ }
13983
+ const declaration = definition.node.parent;
13984
+ if (declaration.type !== "ImportDeclaration" || declaration.source.value !== "effect" || declaration.importKind === "type") {
13985
+ return false;
13986
+ }
13987
+ return Option_exports.match(aliasedEffectModule(definition.node), {
13988
+ onNone: () => false,
13989
+ onSome: (alias) => alias.name === name
13990
+ });
13991
+ });
13992
+ var hasCompetingRenameTarget = (variable, name) => Array_exports.some(
13993
+ variable.scope.variables,
13994
+ (candidate) => candidate !== variable && importsEffectModuleAsAlias(candidate, name)
13995
+ );
13996
+ var canRenameBinding = (ctx, variable, name) => variable.scope.set.get(name) === void 0 && !hasUnshadowedReference(ctx, name) && !hasCompetingRenameTarget(variable, name) && Array_exports.every(
13997
+ variable.references,
13998
+ (reference) => referenceCanBeRenamed(reference, variable.scope, name)
13999
+ );
14000
+ var fixesForAlias = (ctx, { specifier, name }) => {
14001
+ const variable = importVariable(ctx, specifier);
14002
+ if (variable === void 0 || Array_exports.isArrayNonEmpty(ctx.sourceCode.getCommentsInside(specifier)) || !canRenameBinding(ctx, variable, name)) {
14003
+ return [];
14004
+ }
14005
+ return [
14006
+ Diagnostic_exports.replaceText(specifier, name),
14007
+ ...Array_exports.map(
14008
+ variable.references,
14009
+ (reference) => Diagnostic_exports.replaceText(reference.identifier, name)
14010
+ )
14011
+ ];
14012
+ };
14013
+ var preferEffectModuleNames = Rule_exports.define({
14014
+ name: "prefer-effect-module-names",
14015
+ meta: Rule_exports.meta({
14016
+ type: "suggestion",
14017
+ description: "Use Effect module names without import aliases.",
14018
+ fixable: "code"
14019
+ }),
14020
+ create: function* () {
14021
+ const ctx = yield* RuleContext;
14022
+ return {
14023
+ ImportDeclaration: (node) => {
14024
+ if (node.type !== "ImportDeclaration" || node.source.value !== "effect" || node.importKind === "type") {
14025
+ return Effect_exports.void;
14026
+ }
14027
+ const aliases = Array_exports.flatMap(
14028
+ node.specifiers,
14029
+ (specifier) => Option_exports.match(aliasedEffectModule(specifier), {
14030
+ onNone: () => [],
14031
+ onSome: (alias) => [alias]
14032
+ })
14033
+ );
14034
+ if (Array_exports.isReadonlyArrayEmpty(aliases)) {
14035
+ return Effect_exports.void;
14036
+ }
14037
+ const replacements = Array_exports.map(
14038
+ aliases,
14039
+ ({ specifier, name }) => `\`${name}\` instead of \`${specifier.local.name}\``
14040
+ );
14041
+ const diagnostic = Diagnostic_exports.make({
14042
+ node,
14043
+ message: `Use Effect module names without aliases: ${replacements.join(", ")}. Qualify same-named globals through \`globalThis\`.`
14044
+ });
14045
+ const fixes = Array_exports.flatMap(aliases, (alias) => fixesForAlias(ctx, alias));
14046
+ return ctx.report(
14047
+ Array_exports.isReadonlyArrayEmpty(fixes) ? diagnostic : Diagnostic_exports.withFix(diagnostic, Diagnostic_exports.composeFixes(...fixes))
14048
+ );
14049
+ }
14050
+ };
14051
+ }
14052
+ });
14053
+
12779
14054
  // src/rules/require-rel-for-external-link.ts
12780
14055
  var protectiveRelSubstrings = ["noopener", "noreferrer"];
12781
- var isTargetBlankElement = (element) => {
12782
- if (!isCallExpression(element) || !calleeMatchesHelperName(element.callee, "Target")) {
14056
+ var isTargetBlankElement = (element, references) => {
14057
+ if (!isCallExpression(element) || !isFoldkitHtmlBuilderMember(element.callee, "Target", references)) {
12783
14058
  return false;
12784
14059
  }
12785
14060
  const [firstArgument] = element.arguments;
12786
14061
  return isStringLiteral(firstArgument) && firstArgument.value === "_blank";
12787
14062
  };
12788
- var isRelElement = (element) => isCallExpression(element) && calleeMatchesHelperName(element.callee, "Rel");
14063
+ var isRelElement = (element, references) => isCallExpression(element) && isFoldkitHtmlBuilderMember(element.callee, "Rel", references);
12789
14064
  var relStaticValue = (relElement) => {
12790
14065
  const [firstArgument] = relElement.arguments;
12791
14066
  return staticStringValue(firstArgument);
@@ -12801,6 +14076,8 @@ var requireRelForExternalLink = Rule_exports.define({
12801
14076
  }),
12802
14077
  create: function* () {
12803
14078
  const ctx = yield* RuleContext;
14079
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
14080
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
12804
14081
  return {
12805
14082
  ArrayExpression: (node) => {
12806
14083
  if (!isArrayExpression(node)) {
@@ -12811,12 +14088,15 @@ var requireRelForExternalLink = Rule_exports.define({
12811
14088
  }
12812
14089
  const maybeTargetBlank = Array_exports.findFirst(
12813
14090
  node.elements,
12814
- isTargetBlankElement
14091
+ (element) => isTargetBlankElement(element, references)
12815
14092
  );
12816
14093
  if (Option_exports.isNone(maybeTargetBlank)) {
12817
14094
  return Effect_exports.void;
12818
14095
  }
12819
- const relElements = Array_exports.filter(node.elements, isRelElement);
14096
+ const relElements = Array_exports.filter(
14097
+ node.elements,
14098
+ (element) => isRelElement(element, references)
14099
+ );
12820
14100
  if (Array_exports.isArrayEmpty(relElements)) {
12821
14101
  return ctx.report(
12822
14102
  Diagnostic_exports.make({
@@ -12905,39 +14185,57 @@ var isSelectionFactoryPath = (path) => {
12905
14185
  return first === "Ui" && second !== void 0 && multiSelectComponents.includes(second) && third === "Multi" && fourth === "create";
12906
14186
  }
12907
14187
  if (third !== void 0) {
12908
- const isMultiForm = second === "Multi" && multiSelectComponents.includes(first) && third === "create";
14188
+ const isMultiForm = second === "Multi" && first !== void 0 && multiSelectComponents.includes(first) && third === "create";
12909
14189
  const isUiNamespaceForm = first === "Ui" && second !== void 0 && singleSelectComponents.includes(second) && third === "create";
12910
14190
  return isMultiForm || isUiNamespaceForm;
12911
14191
  }
12912
- return second === "create" && singleSelectComponents.includes(first);
14192
+ return first !== void 0 && second === "create" && singleSelectComponents.includes(first);
12913
14193
  };
12914
- var selectionFactoryLabel = (call) => pipe(
12915
- resolveMemberPath(call.callee),
12916
- Option_exports.filter(isSelectionFactoryPath),
12917
- Option_exports.map(Array_exports.join("."))
12918
- );
12919
- var selectionFactorySelfMatch = (value) => {
14194
+ var selectionFactoryLabel = (call, references) => {
14195
+ const maybePath = references === void 0 ? resolveMemberPath(call.callee) : pipe(
14196
+ resolveImportedPath(references, call.callee),
14197
+ Option_exports.flatMap((path) => {
14198
+ if (path.source === "@foldkit/ui") {
14199
+ return Option_exports.some(path.members);
14200
+ }
14201
+ const componentBySource = {
14202
+ "@foldkit/ui/combobox": "Combobox",
14203
+ "@foldkit/ui/listbox": "Listbox",
14204
+ "@foldkit/ui/menu": "Menu",
14205
+ "@foldkit/ui/tabs": "Tabs"
14206
+ };
14207
+ const component = componentBySource[path.source];
14208
+ return component === void 0 ? Option_exports.none() : Option_exports.some([component, ...path.members]);
14209
+ })
14210
+ );
14211
+ return pipe(
14212
+ maybePath,
14213
+ Option_exports.filter(isSelectionFactoryPath),
14214
+ Option_exports.map(Array_exports.join("."))
14215
+ );
14216
+ };
14217
+ var selectionFactorySelfMatch = (value, references) => {
12920
14218
  if (!isCallExpression(value)) {
12921
14219
  return [];
12922
14220
  }
12923
14221
  const call = value;
12924
14222
  return pipe(
12925
- selectionFactoryLabel(call),
14223
+ selectionFactoryLabel(call, references),
12926
14224
  Option_exports.match({
12927
14225
  onNone: () => [],
12928
14226
  onSome: (label) => [{ call, label }]
12929
14227
  })
12930
14228
  );
12931
14229
  };
12932
- var collectSelectionFactoryCalls = (value) => {
14230
+ var collectSelectionFactoryCalls = (value, references) => {
12933
14231
  if (typeof value !== "object" || value === null) {
12934
14232
  return [];
12935
14233
  }
12936
14234
  const childEntries = Object.entries(value);
12937
14235
  const childMatches = childEntries.flatMap(
12938
- ([key, child]) => key === "parent" ? [] : collectSelectionFactoryCalls(child)
14236
+ ([key, child]) => key === "parent" ? [] : collectSelectionFactoryCalls(child, references)
12939
14237
  );
12940
- return [...selectionFactorySelfMatch(value), ...childMatches];
14238
+ return [...selectionFactorySelfMatch(value, references), ...childMatches];
12941
14239
  };
12942
14240
  var topLevelInitializerCalls = (program) => {
12943
14241
  const statements = program.body;
@@ -12962,12 +14260,14 @@ var selectionSubmodelFactoryAtModuleScope = Rule_exports.define({
12962
14260
  }),
12963
14261
  create: function* () {
12964
14262
  const ctx = yield* RuleContext;
14263
+ const scopes = ctx.sourceCode.scopeManager?.scopes;
14264
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
12965
14265
  return Visitor_exports.onExit("Program", (node) => {
12966
14266
  if (!isProgram(node)) {
12967
14267
  return Effect_exports.void;
12968
14268
  }
12969
14269
  const allowedCalls = topLevelInitializerCalls(node);
12970
- const factoryCalls = collectSelectionFactoryCalls(node);
14270
+ const factoryCalls = collectSelectionFactoryCalls(node, references);
12971
14271
  const offendingCalls = factoryCalls.filter(
12972
14272
  (factoryCall) => !allowedCalls.includes(factoryCall.call)
12973
14273
  );
@@ -13001,6 +14301,7 @@ var commandMapperPaths = [
13001
14301
  ];
13002
14302
  var gotMessagePattern = /^Got\w*Message$/;
13003
14303
  var dynamicCalleeLabel = "<dynamic call>";
14304
+ var emptyMessageUnionBindings = /* @__PURE__ */ new Set();
13004
14305
  var isWrapperExpression3 = (node) => typeof node === "object" && node !== null && "type" in node && typeof node.type === "string" && mapperWrapperTypes.includes(node.type) && "expression" in node;
13005
14306
  var unwrapExpression3 = (node) => isWrapperExpression3(node) ? unwrapExpression3(node.expression) : node;
13006
14307
  var isArrowFunctionExpression4 = (node) => typeof node === "object" && node !== null && "type" in node && node.type === "ArrowFunctionExpression";
@@ -13024,8 +14325,14 @@ var resolveMemberPath2 = (node) => {
13024
14325
  return Option_exports.none();
13025
14326
  };
13026
14327
  var isPropertyKeyNamed = (key, name) => isIdentifier(key, name) || isStringLiteral(key) && key.value === name;
13027
- var commandMapperArrow = (node) => pipe(
13028
- resolveMemberPath2(node.callee),
14328
+ var foldkitApiPath = (node, references) => {
14329
+ if (references === void 0) {
14330
+ return resolveMemberPath2(node);
14331
+ }
14332
+ return resolveFoldkitApiPath(references, node);
14333
+ };
14334
+ var commandMapperArrow = (node, references) => pipe(
14335
+ foldkitApiPath(node.callee, references),
13029
14336
  Option_exports.map(Array_exports.join(".")),
13030
14337
  Option_exports.filter((calleePath) => commandMapperPaths.includes(calleePath)),
13031
14338
  Option_exports.flatMap(() => {
@@ -13033,13 +14340,13 @@ var commandMapperArrow = (node) => pipe(
13033
14340
  return isArrowFunctionExpression4(mapperArgument) ? Option_exports.some(mapperArgument) : Option_exports.none();
13034
14341
  })
13035
14342
  );
13036
- var subscriptionLiftMapperArrow = (node) => {
14343
+ var subscriptionLiftMapperArrow = (node, references) => {
13037
14344
  const innerCall = unwrapExpression3(node.callee);
13038
14345
  if (!isCallExpression(innerCall)) {
13039
14346
  return Option_exports.none();
13040
14347
  }
13041
14348
  return pipe(
13042
- resolveMemberPath2(innerCall.callee),
14349
+ foldkitApiPath(innerCall.callee, references),
13043
14350
  Option_exports.map(Array_exports.join(".")),
13044
14351
  Option_exports.filter((calleePath) => calleePath === "Subscription.lift"),
13045
14352
  Option_exports.flatMap(() => {
@@ -13082,20 +14389,44 @@ var analyzableMapperCall = (arrow) => {
13082
14389
  })
13083
14390
  );
13084
14391
  };
13085
- var nonGotMapperOffense = (arrow) => pipe(
14392
+ var isFoldkitMessageUnionVariable = (variable, references) => variable.defs.some(
14393
+ (definition) => definition.type === "Variable" && isVariableDeclarator(definition.node) && isCallExpression(definition.node.init) && isFoldkitMessageUnionCall(
14394
+ definition.node.init,
14395
+ emptyMessageUnionBindings,
14396
+ references
14397
+ )
14398
+ );
14399
+ var nonGotMapperOffense = (arrow, references) => pipe(
13086
14400
  analyzableMapperCall(arrow),
13087
- Option_exports.flatMap(
13088
- (call) => pipe(
13089
- resolveMemberPath2(call.callee),
13090
- Option_exports.match({
13091
- onNone: () => Option_exports.some({ call, calleeLabel: dynamicCalleeLabel }),
13092
- onSome: (calleePath) => gotMessagePattern.test(Array_exports.lastNonEmpty(calleePath)) ? Option_exports.none() : Option_exports.some({
13093
- call,
13094
- calleeLabel: `${Array_exports.join(calleePath, ".")}(...)`
13095
- })
14401
+ Option_exports.flatMap((call) => {
14402
+ const maybeCalleePath = resolveMemberPath2(call.callee);
14403
+ const isGotWrapper = references === void 0 ? Option_exports.exists(
14404
+ maybeCalleePath,
14405
+ (calleePath) => gotMessagePattern.test(Array_exports.lastNonEmpty(calleePath))
14406
+ ) : Option_exports.exists(
14407
+ resolveImportedPath(references, call.callee),
14408
+ (importedPath2) => {
14409
+ const [constructorName2] = importedPath2.members.slice(-1);
14410
+ return constructorName2 !== void 0 && gotMessagePattern.test(constructorName2);
14411
+ }
14412
+ ) || Option_exports.exists(staticMemberPath(call.callee), (calleePath) => {
14413
+ const [constructorName2, extraMember] = calleePath.members;
14414
+ return constructorName2 !== void 0 && extraMember === void 0 && gotMessagePattern.test(constructorName2) && Option_exports.exists(
14415
+ resolvedVariable(references, calleePath.root),
14416
+ (variable) => isFoldkitMessageUnionVariable(variable, references)
14417
+ );
14418
+ });
14419
+ if (isGotWrapper) {
14420
+ return Option_exports.none();
14421
+ }
14422
+ return Option_exports.some({
14423
+ call,
14424
+ calleeLabel: Option_exports.match(maybeCalleePath, {
14425
+ onNone: () => dynamicCalleeLabel,
14426
+ onSome: (calleePath) => `${Array_exports.join(calleePath, ".")}(...)`
13096
14427
  })
13097
- )
13098
- )
14428
+ });
14429
+ })
13099
14430
  );
13100
14431
  var commandMapperMessage = (calleeLabel) => `This Command mapper must wrap child output in a Got*Message constructor. \`${calleeLabel}\` is not a Got wrapper, so this Submodel level never wraps its child's Messages. Route the child Message through the parent's Got*Message wrapper.`;
13101
14432
  var subscriptionMapperMessage = (calleeLabel) => `The toParentMessage mapper in Subscription.lift must wrap child output in a Got*Message constructor. \`${calleeLabel}\` is not a Got wrapper. Return the parent's Got*Message wrapper so each Submodel level wraps exactly once.`;
@@ -13107,6 +14438,9 @@ var wrapChildOutputInGotMessage = Rule_exports.define({
13107
14438
  }),
13108
14439
  create: function* () {
13109
14440
  const ctx = yield* RuleContext;
14441
+ const scopeManager = ctx.sourceCode.scopeManager;
14442
+ const scopes = scopeManager?.scopes;
14443
+ const references = scopes === void 0 ? void 0 : indexReferences(scopes);
13110
14444
  const reportOffense = (offense, renderMessage) => ctx.report(
13111
14445
  Diagnostic_exports.make({
13112
14446
  node: offense.call,
@@ -13119,13 +14453,13 @@ var wrapChildOutputInGotMessage = Rule_exports.define({
13119
14453
  return Effect_exports.void;
13120
14454
  }
13121
14455
  return pipe(
13122
- commandMapperArrow(node),
13123
- Option_exports.flatMap(nonGotMapperOffense),
14456
+ commandMapperArrow(node, references),
14457
+ Option_exports.flatMap((arrow) => nonGotMapperOffense(arrow, references)),
13124
14458
  Option_exports.match({
13125
14459
  onSome: (offense) => reportOffense(offense, commandMapperMessage),
13126
14460
  onNone: () => pipe(
13127
- subscriptionLiftMapperArrow(node),
13128
- Option_exports.flatMap(nonGotMapperOffense),
14461
+ subscriptionLiftMapperArrow(node, references),
14462
+ Option_exports.flatMap((arrow) => nonGotMapperOffense(arrow, references)),
13129
14463
  Option_exports.match({
13130
14464
  onSome: (offense) => reportOffense(offense, subscriptionMapperMessage),
13131
14465
  onNone: () => Effect_exports.void
@@ -13161,12 +14495,14 @@ var basePlugin = Plugin_exports.define({
13161
14495
  "no-empty-object-tagged-call": noEmptyObjectTaggedCall,
13162
14496
  "no-hand-rolled-command-struct": noHandRolledCommandStruct,
13163
14497
  "no-hardcoded-route-strings": noHardcodedRouteStrings,
14498
+ "no-impure-call-at-decision-time": noImpureCallAtDecisionTime,
13164
14499
  "no-module-level-mutable-state": noModuleLevelMutableState,
13165
14500
  "no-nonportable-server-globals": noNonportableServerGlobals,
13166
14501
  "no-noop-message": noNoopMessage,
13167
14502
  "no-raw-dom-event-attributes": noRawDomEventAttributes,
13168
14503
  "no-spread-in-evo": noSpreadInEvo,
13169
14504
  "prefer-callable-message-constructor": preferCallableMessageConstructor,
14505
+ "prefer-effect-module-names": preferEffectModuleNames,
13170
14506
  "require-rel-for-external-link": requireRelForExternalLink,
13171
14507
  "selection-submodel-factory-at-module-scope": selectionSubmodelFactoryAtModuleScope,
13172
14508
  "wrap-child-output-in-got-message": wrapChildOutputInGotMessage
@@ -13183,22 +14519,38 @@ var serverFilePatterns = [
13183
14519
  "**/entry.server.tsx",
13184
14520
  "**/server/**/*.ts",
13185
14521
  "**/server/**/*.tsx",
13186
- "**/prerender.ts"
14522
+ "**/prerender.ts",
14523
+ "**/prerender.tsx"
14524
+ ];
14525
+ var entryFilePatterns = [
14526
+ "**/entry.ts",
14527
+ "**/entry.tsx",
14528
+ "**/entry.client.ts",
14529
+ "**/entry.client.tsx",
14530
+ "**/entry.server.ts",
14531
+ "**/entry.server.tsx"
13187
14532
  ];
14533
+ var decisionTimeRuleId = "foldkit/no-impure-call-at-decision-time";
13188
14534
  var serverOverride = {
13189
14535
  files: serverFilePatterns,
13190
14536
  excludeFiles: testFilePatterns,
13191
14537
  rules: {
13192
- "foldkit/no-nonportable-server-globals": "error"
14538
+ "foldkit/no-nonportable-server-globals": "error",
14539
+ [decisionTimeRuleId]: "off"
14540
+ }
14541
+ };
14542
+ var entryOverride = {
14543
+ files: entryFilePatterns,
14544
+ excludeFiles: testFilePatterns,
14545
+ rules: {
14546
+ [decisionTimeRuleId]: "off"
13193
14547
  }
13194
14548
  };
14549
+ var rulesApplicableToTests = /* @__PURE__ */ new Set(["foldkit/prefer-effect-module-names"]);
13195
14550
  var testOverride = (config) => ({
13196
14551
  files: testFilePatterns,
13197
14552
  rules: Object.fromEntries(
13198
- Object.keys(config.rules).map((id) => [
13199
- id,
13200
- "off"
13201
- ])
14553
+ Object.keys(config.rules).filter((id) => !rulesApplicableToTests.has(id)).map((id) => [id, "off"])
13202
14554
  )
13203
14555
  });
13204
14556
  var withOverrides = (config) => ({
@@ -13207,7 +14559,7 @@ var withOverrides = (config) => ({
13207
14559
  ...config.rules,
13208
14560
  "foldkit/no-nonportable-server-globals": "off"
13209
14561
  },
13210
- overrides: [serverOverride, testOverride(config)]
14562
+ overrides: [serverOverride, entryOverride, testOverride(config)]
13211
14563
  });
13212
14564
  var index_default = {
13213
14565
  ...basePlugin,