@savvy-web/rslib-builder 0.17.0 → 0.18.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 (3) hide show
  1. package/index.d.ts +51 -0
  2. package/index.js +40 -0
  3. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -135,6 +135,32 @@ export declare interface ApiModelOptions {
135
135
  * `"include"` otherwise
136
136
  */
137
137
  forgottenExports?: "include" | "error" | "ignore";
138
+ /**
139
+ * Declarative rules for suppressing specific API Extractor warning messages.
140
+ *
141
+ * @remarks
142
+ * Each rule matches on `messageId` (exact), `pattern` (RegExp with substring fallback),
143
+ * or both (AND logic). Suppression is evaluated before `forgottenExports` and TSDoc
144
+ * warning handling and takes priority over both.
145
+ *
146
+ * After each entry, the number of suppressed messages is logged at info level.
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * import type { ApiModelOptions } from '@savvy-web/rslib-builder';
151
+ *
152
+ * const apiModel: ApiModelOptions = {
153
+ * forgottenExports: 'error',
154
+ * suppressWarnings: [
155
+ * // Suppress forgotten-export for Effect _base symbols
156
+ * { messageId: 'ae-forgotten-export', pattern: '_base' },
157
+ * // Suppress a specific TSDoc warning category
158
+ * { messageId: 'tsdoc-param-tag-missing-hyphen' },
159
+ * ],
160
+ * };
161
+ * ```
162
+ */
163
+ suppressWarnings?: WarningSuppressionRule[];
138
164
  }
139
165
 
140
166
  /**
@@ -3373,4 +3399,29 @@ export declare class TsconfigResolver {
3373
3399
  virtualEntryNames: Set<string>;
3374
3400
  }
3375
3401
 
3402
+ /**
3403
+ * A declarative rule for suppressing a specific API Extractor warning message.
3404
+ *
3405
+ * @remarks
3406
+ * Both `messageId` and `pattern` must match when both are specified (AND logic).
3407
+ * Specify at least one field per rule — a rule with neither field matches all messages.
3408
+ *
3409
+ * `pattern` is first tried as a RegExp. If the string is not a valid regular
3410
+ * expression it falls back to substring matching.
3411
+ *
3412
+ * @public
3413
+ */
3414
+ export declare interface WarningSuppressionRule {
3415
+ /**
3416
+ * Exact match against the message's `messageId` property
3417
+ * (e.g., `"ae-forgotten-export"`, `"tsdoc-param-tag-missing-hyphen"`).
3418
+ */
3419
+ messageId?: string;
3420
+ /**
3421
+ * Pattern matched against the message's `text` property.
3422
+ * Tried as a RegExp first; falls back to case-sensitive substring match.
3423
+ */
3424
+ pattern?: string;
3425
+ }
3426
+
3376
3427
  export { }
package/index.js CHANGED
@@ -597,6 +597,34 @@ const TSConfigs = {
597
597
  }
598
598
  }
599
599
  };
600
+ function compileRule(rule) {
601
+ let regex = null;
602
+ let literal;
603
+ if (void 0 !== rule.pattern) try {
604
+ regex = new RegExp(rule.pattern);
605
+ } catch {
606
+ literal = rule.pattern;
607
+ }
608
+ return {
609
+ messageId: rule.messageId,
610
+ regex,
611
+ literal
612
+ };
613
+ }
614
+ function matchesCompiled(rule, messageId, text) {
615
+ if (void 0 !== rule.messageId && messageId !== rule.messageId) return false;
616
+ if (null !== rule.regex) return rule.regex.test(text ?? "");
617
+ if (void 0 !== rule.literal) return (text ?? "").includes(rule.literal);
618
+ return true;
619
+ }
620
+ function createMessageSuppressor(rules) {
621
+ const compiled = rules.map(compileRule);
622
+ return {
623
+ matches (messageId, text) {
624
+ return compiled.some((rule)=>matchesCompiled(rule, messageId, text));
625
+ }
626
+ };
627
+ }
600
628
  class TsconfigResolverError extends Error {
601
629
  option;
602
630
  value;
@@ -1120,6 +1148,8 @@ async function bundleDtsFiles(options) {
1120
1148
  const tsdocMetadataOption = "object" == typeof apiModel ? apiModel.tsdocMetadata : void 0;
1121
1149
  const tsdocWarnings = tsdocOptions?.warnings ?? (TsDocConfigBuilder.isCI() ? "fail" : "log");
1122
1150
  const forgottenExports = ("object" == typeof apiModel ? apiModel.forgottenExports : void 0) ?? (TsDocConfigBuilder.isCI() ? "error" : "include");
1151
+ const suppressWarnings = "object" == typeof apiModel ? apiModel.suppressWarnings ?? [] : [];
1152
+ const suppressor = createMessageSuppressor(suppressWarnings);
1123
1153
  const tsdocMetadataEnabled = apiModelEnabled && (void 0 === tsdocMetadataOption || true === tsdocMetadataOption || "object" == typeof tsdocMetadataOption && false !== tsdocMetadataOption.enabled);
1124
1154
  const tsdocMetadataFilename = resolveTsdocMetadataFilename(apiModel);
1125
1155
  getApiExtractorPath();
@@ -1196,10 +1226,16 @@ async function bundleDtsFiles(options) {
1196
1226
  const extractorConfig = ExtractorConfig.prepare(prepareOptions);
1197
1227
  const collectedTsdocWarnings = [];
1198
1228
  const collectedForgottenExports = [];
1229
+ const suppressedMessages = [];
1199
1230
  const extractorResult = Extractor.invoke(extractorConfig, {
1200
1231
  localBuild: true,
1201
1232
  showVerboseMessages: false,
1202
1233
  messageCallback: (message)=>{
1234
+ if (suppressor.matches(message.messageId, message.text)) {
1235
+ message.logLevel = ExtractorLogLevel.None;
1236
+ suppressedMessages.push(`[${message.messageId ?? "unknown"}] ${message.text ?? ""}`);
1237
+ return;
1238
+ }
1203
1239
  if (message.text?.includes("Analysis will use the bundled TypeScript version") || message.text?.includes("The target project appears to use TypeScript")) {
1204
1240
  message.logLevel = ExtractorLogLevel.None;
1205
1241
  return;
@@ -1244,6 +1280,10 @@ async function bundleDtsFiles(options) {
1244
1280
  }
1245
1281
  });
1246
1282
  if (!extractorResult.succeeded) throw new Error(`API Extractor failed for entry "${entryName}"`);
1283
+ if (suppressedMessages.length > 0) {
1284
+ const list = suppressedMessages.map((t)=>` ${picocolors.dim(t)}`).join("\n");
1285
+ core_logger.info(`Suppressed ${suppressedMessages.length} API Extractor message${1 === suppressedMessages.length ? "" : "s"} for entry "${entryName}":\n${list}`);
1286
+ }
1247
1287
  const formatWarning = (warning)=>{
1248
1288
  const location = warning.sourceFilePath ? `${picocolors.cyan(relative(cwd, warning.sourceFilePath))}${warning.sourceFileLine ? `:${warning.sourceFileLine}` : ""}${warning.sourceFileColumn ? `:${warning.sourceFileColumn}` : ""}` : null;
1249
1289
  return location ? `${location}: ${picocolors.yellow(warning.text)}` : picocolors.yellow(warning.text);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvy-web/rslib-builder",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "private": false,
5
5
  "description": "RSlib-based build system for Node.js libraries with automatic package.json transformation, TypeScript declaration bundling, and multi-target support",
6
6
  "keywords": [