@dereekb/dbx-components-mcp 14.15.0 → 14.16.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 (2) hide show
  1. package/dbx-components-mcp.js +114 -16
  2. package/package.json +3 -3
@@ -10,7 +10,7 @@ var __export = (target, all) => {
10
10
  // packages/dbx-components-mcp/package.json
11
11
  var package_default = {
12
12
  name: "@dereekb/dbx-components-mcp",
13
- version: "14.15.0",
13
+ version: "14.16.0",
14
14
  sideEffects: false,
15
15
  type: "module",
16
16
  bin: {
@@ -22,8 +22,8 @@ var package_default = {
22
22
  "ts-morph": "^21.0.0"
23
23
  },
24
24
  peerDependencies: {
25
- "@dereekb/dbx-cli": "14.15.0",
26
- "@dereekb/util": "14.15.0"
25
+ "@dereekb/dbx-cli": "14.16.0",
26
+ "@dereekb/util": "14.16.0"
27
27
  }
28
28
  };
29
29
 
@@ -24883,11 +24883,43 @@ var RULE_CATALOG = [
24883
24883
  code: "NOTIF_TEMPLATE_FACTORY_UNLISTED_DELIVERY_METHOD",
24884
24884
  source: "dbx_notification_m_validate_app",
24885
24885
  severity: "warning",
24886
- title: "A template's message factory returns channel content for a delivery method its `NotificationTemplateTypeInfo` does not list in `userConfigurableDeliveryMethods`",
24887
- whatItFlags: "A template's message factory returns channel content for a delivery method its `NotificationTemplateTypeInfo` does not list in `userConfigurableDeliveryMethods`.",
24888
- whenItApplies: "Template types whose info declares an explicit `userConfigurableDeliveryMethods` array and whose handler factory (or the function its `factory:` names) builds an object literal with `emailContent`, `textContent` or `notificationSummaryContent` for a method the array leaves out.",
24889
- whenItDoesNotApply: "Infos without `userConfigurableDeliveryMethods` (the defaults list email, text and notification summary), lists the scanner cannot read statically, and content built outside the factory's own source \u2014 the send pipeline's runtime warning (`notificationMessageFunctionWithUnlistedDeliveryMethodsWarning`) still covers those.",
24890
- canonicalFix: "Stop returning the unlisted content from the factory, or add the delivery method to the info's `userConfigurableDeliveryMethods`.",
24886
+ title: "A template's message factory returns channel content for a delivery method its `NotificationTemplateTypeInfo` does not list in `userConfigurableDeliveryMethods` or `forcedDeliveryMethods`",
24887
+ whatItFlags: "A template's message factory returns channel content for a delivery method its `NotificationTemplateTypeInfo` does not list in `userConfigurableDeliveryMethods` or `forcedDeliveryMethods`.",
24888
+ whenItApplies: "Template types whose info declares an explicit `userConfigurableDeliveryMethods` array, or only a `forcedDeliveryMethods` array (forcing a method changes the `userConfigurableDeliveryMethods` default to none), and whose handler factory (or the function its `factory:` names) builds an object literal with `emailContent`, `textContent` or `notificationSummaryContent` for a method neither array lists.",
24889
+ whenItDoesNotApply: "Infos with neither `userConfigurableDeliveryMethods` nor `forcedDeliveryMethods` (the defaults list email, text and notification summary), lists the scanner cannot read statically (including a `forcedDeliveryMethods` it cannot read), and content built outside the factory's own source \u2014 the send pipeline's runtime warning (`notificationMessageFunctionWithUnlistedDeliveryMethodsWarning`) still covers those.",
24890
+ canonicalFix: "Stop returning the unlisted content from the factory, or add the delivery method to the info's `userConfigurableDeliveryMethods` (or `forcedDeliveryMethods`).",
24891
+ seeAlso: [
24892
+ {
24893
+ kind: "artifact",
24894
+ target: "notification-template"
24895
+ }
24896
+ ]
24897
+ },
24898
+ {
24899
+ code: "NOTIF_TEMPLATE_FORCED_DELIVERY_METHOD_EXPLICIT_OPT_IN",
24900
+ source: "dbx_notification_m_validate_app",
24901
+ severity: "error",
24902
+ title: "A `NotificationTemplateTypeInfo` forces a delivery method while `onlySendToExplicitlyEnabledRecipients` is `true`. A forced method is on by default, which an opt-in only type cannot be, and the app throws at startup when the info record is built",
24903
+ whatItFlags: "A `NotificationTemplateTypeInfo` forces a delivery method while `onlySendToExplicitlyEnabledRecipients` is `true`. A forced method is on by default, which an opt-in only type cannot be, and the app throws at startup when the info record is built.",
24904
+ whenItApplies: "Infos with a non-empty statically read `forcedDeliveryMethods` array and `onlySendToExplicitlyEnabledRecipients: true`.",
24905
+ whenItDoesNotApply: "Infos without `forcedDeliveryMethods`, lists the scanner cannot read statically, and `onlySendToExplicitlyEnabledRecipients` values other than a `true` literal.",
24906
+ canonicalFix: "Remove `forcedDeliveryMethods`, or remove `onlySendToExplicitlyEnabledRecipients` from the info.",
24907
+ seeAlso: [
24908
+ {
24909
+ kind: "artifact",
24910
+ target: "notification-template"
24911
+ }
24912
+ ]
24913
+ },
24914
+ {
24915
+ code: "NOTIF_TEMPLATE_FORCED_TEXT_DELIVERY_METHOD",
24916
+ source: "dbx_notification_m_validate_app",
24917
+ severity: "error",
24918
+ title: "A `NotificationTemplateTypeInfo` lists the text delivery method in `forcedDeliveryMethods`. Texts cannot be forced, and the app throws at startup when the info record is built",
24919
+ whatItFlags: "A `NotificationTemplateTypeInfo` lists the text delivery method in `forcedDeliveryMethods`. Texts cannot be forced, and the app throws at startup when the info record is built.",
24920
+ whenItApplies: "Infos whose statically read `forcedDeliveryMethods` array contains `NotificationDeliveryMethod.TEXT`.",
24921
+ whenItDoesNotApply: "Infos without `forcedDeliveryMethods`, and lists the scanner cannot read statically.",
24922
+ canonicalFix: "Remove `NotificationDeliveryMethod.TEXT` from `forcedDeliveryMethods`. Texts stay opt-in for the recipient.",
24891
24923
  seeAlso: [
24892
24924
  {
24893
24925
  kind: "artifact",
@@ -30865,6 +30897,16 @@ function readStringProperty2(obj, name) {
30865
30897
  }
30866
30898
  return void 0;
30867
30899
  }
30900
+ function readBooleanProperty2(obj, name) {
30901
+ const init = unwrapAsExpressions(getPropertyInitializer(obj, name));
30902
+ let result;
30903
+ if (init?.getKind() === SyntaxKind11.TrueKeyword) {
30904
+ result = true;
30905
+ } else if (init?.getKind() === SyntaxKind11.FalseKeyword) {
30906
+ result = false;
30907
+ }
30908
+ return result;
30909
+ }
30868
30910
  function readIdentifierProperty(obj, name) {
30869
30911
  const init = unwrapAsExpressions(getPropertyInitializer(obj, name));
30870
30912
  if (init && Node26.isIdentifier(init)) {
@@ -31614,6 +31656,8 @@ var TEMPLATE_CONFIGS_ARRAY_TOKEN = "NOTIFICATION_TEMPLATE_SERVICE_CONFIGS_ARRAY_
31614
31656
  var CHECKPOINT_ALIAS_SUFFIX = "NotificationTaskCheckpoint";
31615
31657
  var TASK_DATA_INTERFACE_SUFFIX = "NotificationTaskData";
31616
31658
  var USER_CONFIGURABLE_DELIVERY_METHODS_PROPERTY = "userConfigurableDeliveryMethods";
31659
+ var FORCED_DELIVERY_METHODS_PROPERTY = "forcedDeliveryMethods";
31660
+ var ONLY_SEND_TO_EXPLICITLY_ENABLED_RECIPIENTS_PROPERTY = "onlySendToExplicitlyEnabledRecipients";
31617
31661
  var DELIVERY_METHOD_ENUM = "NotificationDeliveryMethod";
31618
31662
  var DELIVERY_METHOD_BY_MEMBER = /* @__PURE__ */ new Map([
31619
31663
  ["EMAIL", "EMAIL"],
@@ -31705,7 +31749,8 @@ function extractTemplateTypeInfos(sources) {
31705
31749
  if (!nameMatches && !typeMatches) continue;
31706
31750
  const obj = asObjectLiteral(decl.getInitializer());
31707
31751
  if (!obj) continue;
31708
- const deliveryMethods = readUserConfigurableDeliveryMethods(obj, sf);
31752
+ const deliveryMethods = readDeliveryMethodsProperty(obj, sf, USER_CONFIGURABLE_DELIVERY_METHODS_PROPERTY);
31753
+ const forcedDeliveryMethods = readDeliveryMethodsProperty(obj, sf, FORCED_DELIVERY_METHODS_PROPERTY);
31709
31754
  const entry = {
31710
31755
  symbolName: name,
31711
31756
  typeConstantName: readIdentifierProperty(obj, "type"),
@@ -31715,6 +31760,9 @@ function extractTemplateTypeInfos(sources) {
31715
31760
  targetModelIdentity: readIdentifierProperty(obj, "targetModelIdentity"),
31716
31761
  userConfigurableDeliveryMethods: deliveryMethods.methods,
31717
31762
  userConfigurableDeliveryMethodsSource: deliveryMethods.source,
31763
+ forcedDeliveryMethods: forcedDeliveryMethods.methods,
31764
+ forcedDeliveryMethodsSource: forcedDeliveryMethods.source,
31765
+ onlySendToExplicitlyEnabledRecipients: readBooleanProperty2(obj, ONLY_SEND_TO_EXPLICITLY_ENABLED_RECIPIENTS_PROPERTY),
31718
31766
  sourceFile: rel,
31719
31767
  line: decl.getStartLineNumber()
31720
31768
  };
@@ -31724,8 +31772,8 @@ function extractTemplateTypeInfos(sources) {
31724
31772
  }
31725
31773
  return out;
31726
31774
  }
31727
- function readUserConfigurableDeliveryMethods(obj, sf) {
31728
- const value = unwrapAsExpressions(getPropertyInitializer(obj, USER_CONFIGURABLE_DELIVERY_METHODS_PROPERTY));
31775
+ function readDeliveryMethodsProperty(obj, sf, propertyName) {
31776
+ const value = unwrapAsExpressions(getPropertyInitializer(obj, propertyName));
31729
31777
  let result;
31730
31778
  if (!value || isNullishLiteral(value)) {
31731
31779
  result = { methods: void 0, source: "default" };
@@ -32489,6 +32537,7 @@ function runRules6(inspection, extracted) {
32489
32537
  checkTemplateInfoRecord(extracted, violations);
32490
32538
  checkTemplateHandlerFactory(extracted, violations);
32491
32539
  checkTemplateDeliveryMethods(extracted, violations);
32540
+ checkTemplateForcedDeliveryMethods(extracted, violations);
32492
32541
  checkTasks(extracted, violations);
32493
32542
  checkDuplicates2(extracted, violations);
32494
32543
  return violations;
@@ -32664,20 +32713,56 @@ function checkTemplateDeliveryMethods(extracted, violations) {
32664
32713
  }
32665
32714
  for (const entry of extracted.templateHandlerEntries) {
32666
32715
  const info = infoByTypeConstant.get(entry.typeIdentifier);
32667
- const listed = info?.userConfigurableDeliveryMethodsSource === "declared" ? info.userConfigurableDeliveryMethods : void 0;
32668
- if (!listed) continue;
32716
+ const userConfigurable = info ? staticUserConfigurableDeliveryMethods(info) : void 0;
32717
+ if (!info || !userConfigurable) continue;
32718
+ const forced = info.forcedDeliveryMethods ?? [];
32719
+ const listed = [...userConfigurable, ...forced.filter((method) => !userConfigurable.includes(method))];
32669
32720
  const unlisted = entry.contentDeliveryMethods.filter((method) => !listed.includes(method));
32670
32721
  if (unlisted.length === 0) continue;
32671
32722
  const listedText = listed.length > 0 ? listed.join(", ") : "none";
32723
+ const forcedSuffix = forced.length > 0 ? " and `forcedDeliveryMethods`" : "";
32724
+ const listedIn = info.userConfigurableDeliveryMethodsSource === "declared" ? `\`userConfigurableDeliveryMethods\`${forcedSuffix}` : "`forcedDeliveryMethods` (it leaves `userConfigurableDeliveryMethods` out, so it is only sent by its forced methods)";
32672
32725
  pushViolation8(violations, {
32673
32726
  code: "NOTIF_TEMPLATE_FACTORY_UNLISTED_DELIVERY_METHOD",
32674
32727
  severity: "warning",
32675
- message: `Template handler factory \`${entry.factoryFunctionName ?? "<anonymous>"}\` for \`${entry.typeIdentifier}\` builds content for ${unlisted.join(", ")}, but \`${info?.symbolName}\` only lists ${listedText} in \`userConfigurableDeliveryMethods\`. This is the build-time counterpart of the send pipeline's runtime unlisted-delivery-method warning.`,
32728
+ message: `Template handler factory \`${entry.factoryFunctionName ?? "<anonymous>"}\` for \`${entry.typeIdentifier}\` builds content for ${unlisted.join(", ")}, but \`${info.symbolName}\` only lists ${listedText} in ${listedIn}. This is the build-time counterpart of the send pipeline's runtime unlisted-delivery-method warning.`,
32676
32729
  side: "api",
32677
32730
  file: entry.sourceFile
32678
32731
  });
32679
32732
  }
32680
32733
  }
32734
+ function staticUserConfigurableDeliveryMethods(info) {
32735
+ let result;
32736
+ if (info.forcedDeliveryMethodsSource !== "unresolved") {
32737
+ if (info.userConfigurableDeliveryMethodsSource === "declared") {
32738
+ result = info.userConfigurableDeliveryMethods;
32739
+ } else if (info.userConfigurableDeliveryMethodsSource === "default" && (info.forcedDeliveryMethods ?? []).some((method) => method !== "TEXT")) {
32740
+ result = [];
32741
+ }
32742
+ }
32743
+ return result;
32744
+ }
32745
+ function checkTemplateForcedDeliveryMethods(extracted, violations) {
32746
+ for (const info of extracted.templateTypeInfos) {
32747
+ const forced = info.forcedDeliveryMethodsSource === "declared" ? info.forcedDeliveryMethods ?? [] : [];
32748
+ if (forced.includes("TEXT")) {
32749
+ pushViolation8(violations, {
32750
+ code: "NOTIF_TEMPLATE_FORCED_TEXT_DELIVERY_METHOD",
32751
+ message: `Info \`${info.symbolName}\` lists TEXT in \`forcedDeliveryMethods\`. Texts cannot be forced; the info record throws at startup.`,
32752
+ side: "component",
32753
+ file: info.sourceFile
32754
+ });
32755
+ }
32756
+ if (forced.length > 0 && info.onlySendToExplicitlyEnabledRecipients === true) {
32757
+ pushViolation8(violations, {
32758
+ code: "NOTIF_TEMPLATE_FORCED_DELIVERY_METHOD_EXPLICIT_OPT_IN",
32759
+ message: `Info \`${info.symbolName}\` forces ${forced.join(", ")} while \`onlySendToExplicitlyEnabledRecipients\` is true. A forced method is on by default, so the info record throws at startup.`,
32760
+ side: "component",
32761
+ file: info.sourceFile
32762
+ });
32763
+ }
32764
+ }
32765
+ }
32681
32766
  function checkTasks(extracted, violations) {
32682
32767
  if (extracted.taskTypeConstants.length === 0) return;
32683
32768
  flagTasksMissingFromAllArrays(extracted, violations);
@@ -38203,6 +38288,8 @@ function buildTemplateSummaries(extracted) {
38203
38288
  targetModelIdentity: info?.targetModelIdentity,
38204
38289
  userConfigurableDeliveryMethods: info?.userConfigurableDeliveryMethods,
38205
38290
  userConfigurableDeliveryMethodsSource: info?.userConfigurableDeliveryMethodsSource,
38291
+ forcedDeliveryMethods: info?.forcedDeliveryMethods,
38292
+ forcedDeliveryMethodsSource: info?.forcedDeliveryMethodsSource,
38206
38293
  factoryContentDeliveryMethods: unionContentDeliveryMethods(handlerEntriesByType.get(constant.symbolName) ?? []),
38207
38294
  inInfoRecord: info ? resolved.has(info.symbolName) : false,
38208
38295
  hasFactory: handler !== void 0,
@@ -38352,6 +38439,8 @@ function formatTemplateBlock(t) {
38352
38439
  if (t.targetModelIdentity) parts.push(`- Target model: \`${t.targetModelIdentity}\``);
38353
38440
  const deliveryMethodsText = formatUserConfigurableDeliveryMethods(t);
38354
38441
  if (deliveryMethodsText) parts.push(`- User-configurable delivery methods: ${deliveryMethodsText}`);
38442
+ const forcedDeliveryMethodsText = formatForcedDeliveryMethods(t);
38443
+ if (forcedDeliveryMethodsText) parts.push(`- Forced (always on) delivery methods: ${forcedDeliveryMethodsText}`);
38355
38444
  if (t.factoryContentDeliveryMethods.length > 0) parts.push(`- Factory returns content for: ${t.factoryContentDeliveryMethods.join(", ")}`);
38356
38445
  const infoText = t.infoSymbolName ? code6(t.infoSymbolName) : "_Missing._";
38357
38446
  const factorySuffix = t.factoryFunctionName ? ` (${code6(t.factoryFunctionName)})` : "";
@@ -38365,7 +38454,7 @@ function formatUserConfigurableDeliveryMethods(t) {
38365
38454
  result = t.userConfigurableDeliveryMethods && t.userConfigurableDeliveryMethods.length > 0 ? t.userConfigurableDeliveryMethods.join(", ") : "_none_";
38366
38455
  break;
38367
38456
  case "default":
38368
- result = "default";
38457
+ result = t.forcedDeliveryMethodsSource === "declared" && (t.forcedDeliveryMethods ?? []).some((method) => method !== "TEXT") ? "_none_ (the default when the info forces a method)" : "default";
38369
38458
  break;
38370
38459
  case "unresolved":
38371
38460
  result = "_unresolved_";
@@ -38376,6 +38465,15 @@ function formatUserConfigurableDeliveryMethods(t) {
38376
38465
  }
38377
38466
  return result;
38378
38467
  }
38468
+ function formatForcedDeliveryMethods(t) {
38469
+ let result;
38470
+ if (t.forcedDeliveryMethodsSource === "declared" && t.forcedDeliveryMethods && t.forcedDeliveryMethods.length > 0) {
38471
+ result = t.forcedDeliveryMethods.join(", ");
38472
+ } else if (t.forcedDeliveryMethodsSource === "unresolved") {
38473
+ result = "_unresolved_";
38474
+ }
38475
+ return result;
38476
+ }
38379
38477
  function formatTaskBlock(t) {
38380
38478
  const parts = [];
38381
38479
  const heading = t.typeCode ? `### ${t.typeCode} \u2014 \`${t.symbolName}\`` : `### \`${t.symbolName}\``;
@@ -44833,7 +44931,7 @@ var { formatReportAsJson: formatReportAsJson11, formatReportAsMarkdown: formatRe
44833
44931
  var DBX_NOTIFICATION_M_LIST_APP_TOOL = {
44834
44932
  name: "dbx_notification_m_list_app",
44835
44933
  description: [
44836
- "List every notification template + notification task configured in a downstream `-firebase` component + API app pair. Each entry reports its type code, metadata (human name, description, notification/target model identity), and registration flags \u2014 `inInfoRecord` + `hasFactory` for templates, `inAllArray` + `inValidateList` + `hasHandler` for tasks. Templates also report `userConfigurableDeliveryMethods` (with a `default` / `declared` / `unresolved` source) and `factoryContentDeliveryMethods`, the channels their factory builds content for.",
44934
+ "List every notification template + notification task configured in a downstream `-firebase` component + API app pair. Each entry reports its type code, metadata (human name, description, notification/target model identity), and registration flags \u2014 `inInfoRecord` + `hasFactory` for templates, `inAllArray` + `inValidateList` + `hasHandler` for tasks. Templates also report `userConfigurableDeliveryMethods` (with a `default` / `declared` / `unresolved` source), `forcedDeliveryMethods` (always-on methods, with the same kind of source) and `factoryContentDeliveryMethods`, the channels their factory builds content for.",
44837
44935
  "",
44838
44936
  "Its JSON is the report part of the `notification.manifest.json` that `dbx-cli-generate-notification-manifest` writes at build time; this tool always scans the current source.",
44839
44937
  "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-components-mcp",
3
- "version": "14.15.0",
3
+ "version": "14.16.0",
4
4
  "sideEffects": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,7 +12,7 @@
12
12
  "ts-morph": "^21.0.0"
13
13
  },
14
14
  "peerDependencies": {
15
- "@dereekb/dbx-cli": "14.15.0",
16
- "@dereekb/util": "14.15.0"
15
+ "@dereekb/dbx-cli": "14.16.0",
16
+ "@dereekb/util": "14.16.0"
17
17
  }
18
18
  }