@savvy-web/tsdown-plugins 2.9.3 → 2.10.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 (59) hide show
  1. package/build/build-target-groups.js +1 -2
  2. package/build/cjs-default-interop.js +1 -2
  3. package/build/loose-files.js +1 -2
  4. package/build/node-builtin-default-interop.js +1 -2
  5. package/build/strip-maps.js +1 -2
  6. package/build/sync-public.js +1 -2
  7. package/build/target-groups.js +1 -2
  8. package/catalog/resolve-catalogs.js +1 -2
  9. package/changesets/next-versions.js +1 -2
  10. package/config-validation/ConfigValidator.js +1 -2
  11. package/dts/reexport-stub.js +1 -2
  12. package/dts/relative-imports.js +1 -2
  13. package/dts/resolved-tsconfig.js +1 -2
  14. package/entry/ambient-dts.js +1 -2
  15. package/entry/extract.js +1 -2
  16. package/entry/package-json-entries.js +1 -2
  17. package/errors.js +1 -2
  18. package/exe/build.js +1 -2
  19. package/exe/config.js +1 -2
  20. package/exe/filename.js +1 -2
  21. package/index.d.ts +41 -108
  22. package/index.js +3 -3
  23. package/jsx/config.js +1 -2
  24. package/manifest/emit-manifest.js +1 -2
  25. package/manifest/transform.js +1 -2
  26. package/meta/api-extractor.js +27 -6
  27. package/meta/config.js +1 -2
  28. package/meta/generate.js +11 -3
  29. package/meta/merge-models.js +1 -2
  30. package/meta/message-suppressor.js +1 -2
  31. package/meta/og-image.js +1 -2
  32. package/meta/optimistic.js +1 -2
  33. package/meta/run-pass.js +1 -2
  34. package/meta/tsconfig-resolver.js +1 -2
  35. package/meta/tsdoc-config.js +1 -2
  36. package/meta/tsdoctor-manifest.js +1 -2
  37. package/meta/tsdoctor-source.js +1 -2
  38. package/package.json +14 -14
  39. package/report/collector.js +1 -2
  40. package/report/formatters/ci-annotations.js +1 -2
  41. package/report/formatters/diagnostics.js +1 -2
  42. package/report/formatters/json.js +1 -2
  43. package/report/formatters/markdown.js +1 -2
  44. package/report/formatters/silent.js +1 -2
  45. package/report/formatters/terminal.js +1 -2
  46. package/report/issues-artifact.js +1 -2
  47. package/report/metrics-plugin.js +1 -2
  48. package/report/pipeline.js +1 -2
  49. package/report/schema.js +6 -5
  50. package/report/services/EnvironmentDetector.js +1 -2
  51. package/report/services/ExecutorResolver.js +1 -2
  52. package/report/services/FormatSelector.js +1 -2
  53. package/report/services/OutputRenderer.js +1 -2
  54. package/report/timer.js +1 -2
  55. package/report/tsdown-logger.js +1 -2
  56. package/targets/binding.js +1 -2
  57. package/targets/config.js +12 -3
  58. package/targets/resolve-targets.js +44 -9
  59. package/tsconfig/sync-options.js +1 -2
package/meta/generate.js CHANGED
@@ -10,7 +10,7 @@ import { join } from "node:path";
10
10
  import { Effect } from "effect";
11
11
  import { TSDOCTOR_MANIFEST_FILENAME, encodeBundleManifest } from "@tsdoctor/manifest";
12
12
 
13
- //#region src/meta/generate.ts
13
+ // src/meta/generate.ts
14
14
  function unscopedName(name) {
15
15
  const slash = name.lastIndexOf("/");
16
16
  return slash >= 0 ? name.slice(slash + 1) : name;
@@ -55,12 +55,19 @@ async function generateMeta(options) {
55
55
  ...e.code !== void 0 ? { code: e.code } : {},
56
56
  ...e.ciFatal !== void 0 ? { ciFatal: e.ciFatal } : {}
57
57
  });
58
+ const exportPathFor = (entryName) => exportPaths[entryName] ?? (entryName === "index" ? "." : `./${entryName}`);
59
+ const selfReferencePaths = {};
60
+ if (splitDiagnostics) for (const name of entryNames) {
61
+ const exportPath = exportPathFor(name);
62
+ const specifier = exportPath === "." ? packageName : packageName + exportPath.slice(1);
63
+ selfReferencePaths[specifier] = [join(aeInputDir, `${entries[name]}.d.ts`)];
64
+ }
58
65
  for (const entryName of entryNames) {
59
66
  const modelEntryDts = join(dtsDir, `${entries[entryName]}.d.ts`);
60
67
  const safeEntry = entryName.replace(/[\\/]/g, "__");
61
68
  const perEntryApiJson = join(outMetaDir, `${safeEntry}.entry.api.json`);
62
69
  intermediateApiJsons.push(perEntryApiJson);
63
- const isMain = (exportPaths[entryName] ?? (entryName === "index" ? "." : `./${entryName}`)) === ".";
70
+ const isMain = exportPathFor(entryName) === ".";
64
71
  const captureRollupOnlyFatal = splitDiagnostics && onMessage !== void 0 && ci !== true;
65
72
  const rollupFatal = [];
66
73
  const runBReported = /* @__PURE__ */ new Set();
@@ -98,6 +105,7 @@ async function generateMeta(options) {
98
105
  tsdocConfigPath,
99
106
  apiJsonPath: perEntryApiJson,
100
107
  emitDocModel: false,
108
+ selfReferencePaths,
101
109
  suppressWarnings: tsdoc.suppressWarnings,
102
110
  ...runBOnMessage !== void 0 ? { onMessage: runBOnMessage } : {},
103
111
  ...onSuppressed !== void 0 ? { onSuppressed } : {}
@@ -106,6 +114,7 @@ async function generateMeta(options) {
106
114
  if (onMessage !== void 0) onMessage({
107
115
  source: "api-extractor",
108
116
  level: "warn",
117
+ code: "diagnostics-harvest-failed",
109
118
  text: `Could not harvest per-module source locations for "${entryName}": ${String(err)}`
110
119
  });
111
120
  }
@@ -208,5 +217,4 @@ async function generateMeta(options) {
208
217
  };
209
218
  }
210
219
 
211
- //#endregion
212
220
  export { generateMeta };
@@ -1,4 +1,4 @@
1
- //#region src/meta/merge-models.ts
1
+ // src/meta/merge-models.ts
2
2
  /** Rewrite every nested member canonicalReference that starts with originalPrefix to use newPrefix. Skips the EntryPoint node itself. */
3
3
  function rewriteCanonicalReferences(node, originalPrefix, newPrefix) {
4
4
  if (!node || typeof node !== "object") return;
@@ -40,5 +40,4 @@ function mergeApiModels(options) {
40
40
  return merged;
41
41
  }
42
42
 
43
- //#endregion
44
43
  export { mergeApiModels };
@@ -1,4 +1,4 @@
1
- //#region src/meta/message-suppressor.ts
1
+ // src/meta/message-suppressor.ts
2
2
  function compileRule(rule) {
3
3
  if (rule.pattern === void 0) return {
4
4
  messageId: rule.messageId,
@@ -33,5 +33,4 @@ function createMessageSuppressor(rules) {
33
33
  } };
34
34
  }
35
35
 
36
- //#endregion
37
36
  export { createMessageSuppressor };
package/meta/og-image.js CHANGED
@@ -4,7 +4,7 @@ import { Data, Effect, Layer, Option, Result, Schema } from "effect";
4
4
  import * as NodeServices from "@effect/platform-node/NodeServices";
5
5
  import { ImageBackend, ImageCache, ImageCacheKey } from "@effected/images/cache";
6
6
 
7
- //#region src/meta/og-image.ts
7
+ // src/meta/og-image.ts
8
8
  /**
9
9
  * A configured `openGraph.generate` renderer threw, returned no bytes, or returned bytes that are
10
10
  * not an image. Fails the build: a half-written OG image is worse than none.
@@ -103,5 +103,4 @@ async function writeGeneratedOgImage(options) {
103
103
  };
104
104
  }
105
105
 
106
- //#endregion
107
106
  export { OgGenerateError, resolveOgCacheSalt, writeGeneratedOgImage };
@@ -1,4 +1,4 @@
1
- //#region src/meta/optimistic.ts
1
+ // src/meta/optimistic.ts
2
2
  /** Dependency map fields whose workspace-sibling versions get the optimistic bump. */
3
3
  const DEP_FIELDS = [
4
4
  "dependencies",
@@ -29,5 +29,4 @@ function rewriteMetaVersions(pkg, versions, selfName) {
29
29
  return out;
30
30
  }
31
31
 
32
- //#endregion
33
32
  export { rewriteMetaVersions };
package/meta/run-pass.js CHANGED
@@ -9,7 +9,7 @@ import { rewriteMetaVersions } from "./optimistic.js";
9
9
  import { TsdoctorSourceError, loadTsdoctorSources } from "./tsdoctor-source.js";
10
10
  import { join } from "node:path";
11
11
 
12
- //#region src/meta/run-pass.ts
12
+ // src/meta/run-pass.ts
13
13
  /**
14
14
  * Meta-pass orchestrator: derives export paths, filters bin/ entries, resolves optimistic
15
15
  * next-versions, and calls generateMeta once per publish group.
@@ -125,5 +125,4 @@ function applySubdirMetaEntries(overrides, dtsBasenames, exportPaths) {
125
125
  }
126
126
  }
127
127
 
128
- //#endregion
129
128
  export { applySubdirMetaEntries, deriveExportPaths, runMetaPass };
@@ -3,7 +3,7 @@ import { existsSync } from "node:fs";
3
3
  import * as nodePath from "node:path";
4
4
  import { PortableTsconfig, TsconfigLoaderSync } from "@effected/tsconfig-json";
5
5
 
6
- //#region src/meta/tsconfig-resolver.ts
6
+ // src/meta/tsconfig-resolver.ts
7
7
  /**
8
8
  * JSON schema URL for tsconfig.json files.
9
9
  * @internal
@@ -52,5 +52,4 @@ function resolvePortableTsconfig(cwd, fallbackConfigPath) {
52
52
  }
53
53
  }
54
54
 
55
- //#endregion
56
55
  export { resolvePortableTsconfig };
@@ -3,7 +3,7 @@ import { join } from "node:path";
3
3
  import { isDeepStrictEqual } from "node:util";
4
4
  import { StandardTags } from "@microsoft/tsdoc";
5
5
 
6
- //#region src/meta/tsdoc-config.ts
6
+ // src/meta/tsdoc-config.ts
7
7
  const TSDOC_SCHEMA = "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json";
8
8
  const SYNTAX_KIND_MAP = {
9
9
  block: "block",
@@ -44,5 +44,4 @@ function writeTsdocConfig(cwd, tsdoc) {
44
44
  return path;
45
45
  }
46
46
 
47
- //#endregion
48
47
  export { buildTsdocConfig, writeTsdocConfig };
@@ -1,6 +1,6 @@
1
1
  import { MANIFEST_SPEC } from "@tsdoctor/manifest";
2
2
 
3
- //#region src/meta/tsdoctor-manifest.ts
3
+ // src/meta/tsdoctor-manifest.ts
4
4
  const first = (...values) => values.find((v) => v !== void 0);
5
5
  /**
6
6
  * `owner/repo` from any of the GitHub URL spellings a `repository.url` carries (https, `git+https`,
@@ -131,5 +131,4 @@ function ogImageInfoOf(input) {
131
131
  };
132
132
  }
133
133
 
134
- //#endregion
135
134
  export { composeTsdoctorManifest, githubOwnerRepo, ogImageInfoOf, registriesFromTargets };
@@ -6,7 +6,7 @@ import * as NodePath from "@effect/platform-node/NodePath";
6
6
  import { WorkspaceDiscovery, WorkspaceRootNotFoundError, Workspaces } from "@effected/workspaces";
7
7
  import { TSDOCTOR_MANIFEST_FILENAME, decodeManifestSource } from "@tsdoctor/manifest";
8
8
 
9
- //#region src/meta/tsdoctor-source.ts
9
+ // src/meta/tsdoctor-source.ts
10
10
  /**
11
11
  * A present `tsdoctor.json` source file that could not be parsed or decoded. Absence is never
12
12
  * this error — a missing source tier is the normal case.
@@ -90,5 +90,4 @@ async function loadTsdoctorSources(cwd) {
90
90
  };
91
91
  }
92
92
 
93
- //#endregion
94
93
  export { TsdoctorSourceError, loadTsdoctorSources };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvy-web/tsdown-plugins",
3
- "version": "2.9.3",
3
+ "version": "2.10.0",
4
4
  "private": false,
5
5
  "description": "Interface-only tsdown/rolldown plugin pack powering @savvy-web/bundler",
6
6
  "homepage": "https://github.com/savvy-web/systems/tree/main/packages/tsdown-plugins",
@@ -30,24 +30,24 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@changesets/get-release-plan": "^5.0.2",
33
- "@effect/platform-node": "^4.0.4",
34
- "@effected/glob": "^0.12.0",
35
- "@effected/images": "^0.3.0",
36
- "@effected/jsonc": "^0.17.0",
37
- "@effected/npm": "^0.22.0",
38
- "@effected/package-json": "^0.22.0",
39
- "@effected/semver": "^0.13.0",
40
- "@effected/tsconfig-json": "^0.15.0",
41
- "@effected/walker": "^0.17.0",
42
- "@effected/workspaces": "^0.34.0",
33
+ "@effect/platform-node": "^4.0.6",
34
+ "@effected/glob": "^0.14.0",
35
+ "@effected/images": "^0.5.0",
36
+ "@effected/jsonc": "^0.19.0",
37
+ "@effected/npm": "^0.25.0",
38
+ "@effected/package-json": "^0.24.1",
39
+ "@effected/semver": "^0.15.0",
40
+ "@effected/tsconfig-json": "^0.17.0",
41
+ "@effected/walker": "^0.19.0",
42
+ "@effected/workspaces": "^0.36.1",
43
43
  "@microsoft/api-extractor": "7.59.1",
44
44
  "@microsoft/tsdoc": "~0.16.0",
45
45
  "@microsoft/tsdoc-config": "0.18.1",
46
- "@tsdoctor/manifest": "^0.2.8",
47
- "effect": "^4.0.4",
46
+ "@tsdoctor/manifest": "^0.2.10",
47
+ "effect": "^4.0.6",
48
48
  "picocolors": "^1.1.1",
49
49
  "std-env": "^4.3.0",
50
- "tsdown": "^0.23.0",
50
+ "tsdown": "^0.23.1",
51
51
  "typescript": "^6.0.3"
52
52
  }
53
53
  }
@@ -1,7 +1,7 @@
1
1
  import { BuildReport, DiagnosticEntry, EmittedFile, PassReport, ReportTimings, TargetGroupReport } from "./schema.js";
2
2
  import { Context } from "effect";
3
3
 
4
- //#region src/report/collector.ts
4
+ // src/report/collector.ts
5
5
  /**
6
6
  * Stateful build-event accumulator. The write surface is synchronous so it can be called directly
7
7
  * from tsdown's customLogger and API Extractor's messageCallback (both invoked synchronously).
@@ -137,5 +137,4 @@ function toEntry(input) {
137
137
  /** @public */
138
138
  var BuildCollectorTag = class extends Context.Service()("@savvy-web/tsdown-plugins/BuildCollector") {};
139
139
 
140
- //#endregion
141
140
  export { BuildCollector, BuildCollectorTag };
@@ -1,4 +1,4 @@
1
- //#region src/report/formatters/ci-annotations.ts
1
+ // src/report/formatters/ci-annotations.ts
2
2
  const esc = (s) => s.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A");
3
3
  /** @public */
4
4
  const CiAnnotationsFormatter = {
@@ -23,5 +23,4 @@ const CiAnnotationsFormatter = {
23
23
  }
24
24
  };
25
25
 
26
- //#endregion
27
26
  export { CiAnnotationsFormatter };
@@ -1,4 +1,4 @@
1
- //#region src/report/formatters/diagnostics.ts
1
+ // src/report/formatters/diagnostics.ts
2
2
  /** "code ×N, code2 ×M", sorted by count desc then code asc. */
3
3
  function suppressedSummary(entries) {
4
4
  const counts = /* @__PURE__ */ new Map();
@@ -19,5 +19,4 @@ function ciFatalCallout(n) {
19
19
  return `⛔ ${n} ${n === 1 ? "issue" : "issues"} here ${n === 1 ? "becomes" : "become"} a hard error in CI and will fail the build. Fix before pushing.`;
20
20
  }
21
21
 
22
- //#endregion
23
22
  export { ciFatalCallout, ciFatalCountForPackage, suppressedSummary };
@@ -1,4 +1,4 @@
1
- //#region src/report/formatters/json.ts
1
+ // src/report/formatters/json.ts
2
2
  /** @public */
3
3
  const JsonFormatter = {
4
4
  format: "json",
@@ -9,5 +9,4 @@ const JsonFormatter = {
9
9
  }]
10
10
  };
11
11
 
12
- //#endregion
13
12
  export { JsonFormatter };
@@ -1,6 +1,6 @@
1
1
  import { ciFatalCallout, ciFatalCountForPackage, suppressedSummary } from "./diagnostics.js";
2
2
 
3
- //#region src/report/formatters/markdown.ts
3
+ // src/report/formatters/markdown.ts
4
4
  /** @public */
5
5
  const MarkdownFormatter = {
6
6
  format: "markdown",
@@ -33,5 +33,4 @@ const MarkdownFormatter = {
33
33
  }
34
34
  };
35
35
 
36
- //#endregion
37
36
  export { MarkdownFormatter };
@@ -1,9 +1,8 @@
1
- //#region src/report/formatters/silent.ts
1
+ // src/report/formatters/silent.ts
2
2
  /** @public */
3
3
  const SilentFormatter = {
4
4
  format: "silent",
5
5
  render: () => []
6
6
  };
7
7
 
8
- //#endregion
9
8
  export { SilentFormatter };
@@ -2,7 +2,7 @@ import { formatTime } from "../timer.js";
2
2
  import { ciFatalCallout, ciFatalCountForPackage, suppressedSummary } from "./diagnostics.js";
3
3
  import pc from "picocolors";
4
4
 
5
- //#region src/report/formatters/terminal.ts
5
+ // src/report/formatters/terminal.ts
6
6
  const fmtBytes = (n) => n < 1024 ? `${n} B` : `${(n / 1024).toFixed(2)} kB`;
7
7
  const fileCount = (g) => g.passes.reduce((sum, p) => sum + p.files.length, 0);
8
8
  const diagLine = (d) => {
@@ -56,5 +56,4 @@ const TerminalFormatter = {
56
56
  }
57
57
  };
58
58
 
59
- //#endregion
60
59
  export { TerminalFormatter };
@@ -1,7 +1,7 @@
1
1
  import { mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
2
2
  import { dirname, join } from "node:path";
3
3
 
4
- //#region src/report/issues-artifact.ts
4
+ // src/report/issues-artifact.ts
5
5
  /** Copy a DiagnosticEntry to a plain object, omitting undefined optionals for stable output. */
6
6
  function toPlain(d) {
7
7
  const out = {
@@ -114,5 +114,4 @@ function writeIssuesArtifact(opts) {
114
114
  return outPath;
115
115
  }
116
116
 
117
- //#endregion
118
117
  export { flattenIssues, serializeIssues, writeIssuesArtifact };
@@ -1,6 +1,6 @@
1
1
  import { gzipSync } from "node:zlib";
2
2
 
3
- //#region src/report/metrics-plugin.ts
3
+ // src/report/metrics-plugin.ts
4
4
  function contentOf(chunk) {
5
5
  const c = chunk;
6
6
  if (c.type === "chunk") return c.code;
@@ -73,5 +73,4 @@ function buildMetricsPlugin(collector, groupId, pass, verbose, suppressMixedExpo
73
73
  };
74
74
  }
75
75
 
76
- //#endregion
77
76
  export { buildMetricsPlugin };
@@ -4,7 +4,7 @@ import { FormatSelector } from "./services/FormatSelector.js";
4
4
  import { OutputRenderer } from "./services/OutputRenderer.js";
5
5
  import { Effect, Layer } from "effect";
6
6
 
7
- //#region src/report/pipeline.ts
7
+ // src/report/pipeline.ts
8
8
  /** @public */
9
9
  const ReportPipeline = Layer.mergeAll(EnvironmentDetector.layer, ExecutorResolver.layer, FormatSelector.layer, OutputRenderer.layer);
10
10
  /** @public */
@@ -22,5 +22,4 @@ const renderReport = (reports, options) => Effect.gen(function* () {
22
22
  });
23
23
  });
24
24
 
25
- //#endregion
26
25
  export { ReportPipeline, renderReport };
package/report/schema.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import { Schema } from "effect";
2
2
 
3
- //#region src/report/schema.ts
3
+ // src/report/schema.ts
4
4
  /** @public */
5
5
  var ReportTimings = class extends Schema.Class("ReportTimings")({ totalMs: Schema.Number }) {};
6
6
  /**
7
- * A captured warning or error, from tsdown's logger, rolldown's onLog, API Extractor, or the meta
8
- * pass's own sidecar work (`tsdoctor.json` sources, Open Graph generation).
7
+ * A captured warning or error, from tsdown's logger, rolldown's onLog, API Extractor, the meta
8
+ * pass's own sidecar work (`tsdoctor.json` sources, Open Graph generation), or an advisory finding
9
+ * about the build config itself (`config`, e.g. a `publishConfig.targets` set no final release reaches).
9
10
  *
10
11
  * @public
11
12
  */
@@ -14,7 +15,8 @@ var DiagnosticEntry = class extends Schema.Class("DiagnosticEntry")({
14
15
  "tsdown",
15
16
  "rolldown",
16
17
  "api-extractor",
17
- "meta"
18
+ "meta",
19
+ "config"
18
20
  ]),
19
21
  level: Schema.Literals(["warn", "error"]),
20
22
  text: Schema.String,
@@ -72,5 +74,4 @@ var BuildReport = class extends Schema.Class("BuildReport")({
72
74
  targetGroups: Schema.Array(TargetGroupReport)
73
75
  }) {};
74
76
 
75
- //#endregion
76
77
  export { BuildReport, DiagnosticEntry, EmittedFile, PassReport, ReportTimings, TargetGroupReport };
@@ -1,7 +1,7 @@
1
1
  import { Context, Effect, Layer } from "effect";
2
2
  import { isAgent, isCI } from "std-env";
3
3
 
4
- //#region src/report/services/EnvironmentDetector.ts
4
+ // src/report/services/EnvironmentDetector.ts
5
5
  const isGitHub = () => process.env.GITHUB_ACTIONS === "true" || process.env.GITHUB_ACTIONS === "1";
6
6
  /** @public */
7
7
  var EnvironmentDetector = class extends Context.Service()("@savvy-web/tsdown-plugins/EnvironmentDetector") {
@@ -13,5 +13,4 @@ var EnvironmentDetector = class extends Context.Service()("@savvy-web/tsdown-plu
13
13
  }) });
14
14
  };
15
15
 
16
- //#endregion
17
16
  export { EnvironmentDetector };
@@ -1,10 +1,9 @@
1
1
  import { Context, Effect, Layer } from "effect";
2
2
 
3
- //#region src/report/services/ExecutorResolver.ts
3
+ // src/report/services/ExecutorResolver.ts
4
4
  /** @public */
5
5
  var ExecutorResolver = class extends Context.Service()("@savvy-web/tsdown-plugins/ExecutorResolver") {
6
6
  static layer = Layer.succeed(this, { resolve: (env) => Effect.succeed(env === "agent-shell" ? "agent" : env === "terminal" ? "human" : "ci") });
7
7
  };
8
8
 
9
- //#endregion
10
9
  export { ExecutorResolver };
@@ -1,10 +1,9 @@
1
1
  import { Context, Effect, Layer } from "effect";
2
2
 
3
- //#region src/report/services/FormatSelector.ts
3
+ // src/report/services/FormatSelector.ts
4
4
  /** @public */
5
5
  var FormatSelector = class extends Context.Service()("@savvy-web/tsdown-plugins/FormatSelector") {
6
6
  static layer = Layer.succeed(this, { select: (executor, explicit, env) => Effect.succeed(explicit ?? (env === "ci-github" && executor === "ci" ? "ci-annotations" : executor === "agent" ? "markdown" : executor === "ci" ? "json" : "terminal")) });
7
7
  };
8
8
 
9
- //#endregion
10
9
  export { FormatSelector };
@@ -5,7 +5,7 @@ import { SilentFormatter } from "../formatters/silent.js";
5
5
  import { TerminalFormatter } from "../formatters/terminal.js";
6
6
  import { Context, Effect, Layer } from "effect";
7
7
 
8
- //#region src/report/services/OutputRenderer.ts
8
+ // src/report/services/OutputRenderer.ts
9
9
  const formatters = /* @__PURE__ */ new Map([
10
10
  ["terminal", TerminalFormatter],
11
11
  ["json", JsonFormatter],
@@ -21,5 +21,4 @@ var OutputRenderer = class extends Context.Service()("@savvy-web/tsdown-plugins/
21
21
  }) });
22
22
  };
23
23
 
24
- //#endregion
25
24
  export { OutputRenderer };
package/report/timer.js CHANGED
@@ -1,4 +1,4 @@
1
- //#region src/report/timer.ts
1
+ // src/report/timer.ts
2
2
  /** @public */
3
3
  function formatTime(ms) {
4
4
  return ms < 1e3 ? `${Math.round(ms)}ms` : `${(ms / 1e3).toFixed(2)}s`;
@@ -16,5 +16,4 @@ function createTimer(now = Date.now) {
16
16
  };
17
17
  }
18
18
 
19
- //#endregion
20
19
  export { createTimer, formatTime };
@@ -1,4 +1,4 @@
1
- //#region src/report/tsdown-logger.ts
1
+ // src/report/tsdown-logger.ts
2
2
  const ANSI = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g");
3
3
  const join = (args) => args.map((a) => String(a)).join(" ").replace(ANSI, "").trim();
4
4
  /**
@@ -38,5 +38,4 @@ function createTsdownLogger(collector, groupId) {
38
38
  };
39
39
  }
40
40
 
41
- //#endregion
42
41
  export { createTsdownLogger };
@@ -1,7 +1,7 @@
1
1
  import { mkdirSync, writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
 
4
- //#region src/targets/binding.ts
4
+ // src/targets/binding.ts
5
5
  /**
6
6
  * Write the target-to-group binding to dist/prod/targets.json for the release action to consume. Returns the path.
7
7
  *
@@ -15,5 +15,4 @@ function writeTargetsBinding(cwd, resolution) {
15
15
  return path;
16
16
  }
17
17
 
18
- //#endregion
19
18
  export { writeTargetsBinding };
package/targets/config.js CHANGED
@@ -1,4 +1,14 @@
1
- //#region src/targets/config.ts
1
+ // src/targets/config.ts
2
+ /**
3
+ * Every {@link ReleaseChannel} value, in declaration order.
4
+ *
5
+ * @public
6
+ */
7
+ const RELEASE_CHANNELS = [
8
+ "all",
9
+ "stable",
10
+ "prerelease"
11
+ ];
2
12
  /**
3
13
  * True when a target value is the object form (carries registry/name/from).
4
14
  *
@@ -8,5 +18,4 @@ function isTargetObject(value) {
8
18
  return typeof value === "object" && value !== null;
9
19
  }
10
20
 
11
- //#endregion
12
- export { isTargetObject };
21
+ export { RELEASE_CHANNELS, isTargetObject };
@@ -1,7 +1,7 @@
1
1
  import { ConfigValidationError } from "../errors.js";
2
- import { isTargetObject } from "./config.js";
2
+ import { RELEASE_CHANNELS, isTargetObject } from "./config.js";
3
3
 
4
- //#region src/targets/resolve-targets.ts
4
+ // src/targets/resolve-targets.ts
5
5
  /** Default registry endpoints for the well-known target keys. */
6
6
  const DEFAULT_REGISTRIES = {
7
7
  npm: "https://registry.npmjs.org",
@@ -29,6 +29,22 @@ function resolveTargets(options) {
29
29
  });
30
30
  return registry;
31
31
  };
32
+ const optionsFor = (id, value) => {
33
+ if (!isTargetObject(value)) return { releases: "all" };
34
+ const { releases, provenance } = value;
35
+ if (releases !== void 0 && !RELEASE_CHANNELS.includes(releases)) throw new ConfigValidationError({
36
+ path: `publishConfig.targets.${id}.releases`,
37
+ reason: `Target "${id}" has releases "${String(releases)}"; expected one of ${RELEASE_CHANNELS.map((c) => `"${c}"`).join(", ")}`
38
+ });
39
+ if (provenance !== void 0 && typeof provenance !== "boolean") throw new ConfigValidationError({
40
+ path: `publishConfig.targets.${id}.provenance`,
41
+ reason: `Target "${id}" has a non-boolean provenance; expected true or false`
42
+ });
43
+ return {
44
+ releases: releases ?? "all",
45
+ ...provenance !== void 0 ? { provenance } : {}
46
+ };
47
+ };
32
48
  const groups = /* @__PURE__ */ new Map();
33
49
  const addGroup = (id, name) => {
34
50
  if (!groups.has(id)) groups.set(id, {
@@ -56,7 +72,8 @@ function resolveTargets(options) {
56
72
  id,
57
73
  group: gid,
58
74
  name: baseName,
59
- registry: registryFor(id, void 0)
75
+ registry: registryFor(id, void 0),
76
+ ...optionsFor(id, value)
60
77
  });
61
78
  } else if (typeof value === "string") {
62
79
  if (DEFAULT_REGISTRIES[id] === void 0) throw new ConfigValidationError({
@@ -68,7 +85,8 @@ function resolveTargets(options) {
68
85
  id,
69
86
  group: id,
70
87
  name: value,
71
- registry: registryFor(id, void 0)
88
+ registry: registryFor(id, void 0),
89
+ ...optionsFor(id, value)
72
90
  });
73
91
  } else if (isTargetObject(value)) {
74
92
  if (value.from !== void 0 && value.name !== void 0) throw new ConfigValidationError({
@@ -85,7 +103,8 @@ function resolveTargets(options) {
85
103
  id,
86
104
  group: id,
87
105
  name: value.name,
88
- registry: registryFor(id, value.registry)
106
+ registry: registryFor(id, value.registry),
107
+ ...optionsFor(id, value)
89
108
  });
90
109
  } else {
91
110
  addGroup(id, baseName);
@@ -93,7 +112,8 @@ function resolveTargets(options) {
93
112
  id,
94
113
  group: id,
95
114
  name: baseName,
96
- registry: registryFor(id, value.registry)
115
+ registry: registryFor(id, value.registry),
116
+ ...optionsFor(id, value)
97
117
  });
98
118
  }
99
119
  }
@@ -117,7 +137,8 @@ function resolveTargets(options) {
117
137
  id,
118
138
  group: ref.group,
119
139
  name: ref.name,
120
- registry: registryFor(id, obj.registry)
140
+ registry: registryFor(id, obj.registry),
141
+ ...optionsFor(id, obj)
121
142
  });
122
143
  }
123
144
  return {
@@ -125,6 +146,20 @@ function resolveTargets(options) {
125
146
  targets: resolved
126
147
  };
127
148
  }
149
+ /**
150
+ * Advisory warnings for a resolved target set that is valid but probably not what was meant.
151
+ *
152
+ * @remarks
153
+ * Today the only one is a set whose every target is `releases: "prerelease"`, which leaves final
154
+ * versions with nowhere to publish. A warning rather than a {@link ConfigValidationError}, since a
155
+ * prerelease-only package is a legitimate if unusual setup. Pure; returns one message per finding.
156
+ *
157
+ * @public
158
+ */
159
+ function releaseWarnings(resolution) {
160
+ const { targets } = resolution;
161
+ if (targets.length > 0 && targets.every((t) => t.releases === "prerelease")) return [`Every publish target sets releases: "prerelease", so final versions publish nowhere; set "all" or "stable" on at least one target`];
162
+ return [];
163
+ }
128
164
 
129
- //#endregion
130
- export { resolveTargets };
165
+ export { releaseWarnings, resolveTargets };
@@ -1,7 +1,7 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import * as nodePath from "node:path";
3
3
 
4
- //#region src/tsconfig/sync-options.ts
4
+ // src/tsconfig/sync-options.ts
5
5
  /**
6
6
  * The consumer-supplied sync operations backing every `TsconfigLoaderSync` call in this
7
7
  * package: Node's `existsSync`/`readFileSync` satisfy the loader's `SyncFileSystem`, and
@@ -17,5 +17,4 @@ const tsconfigSyncOptions = {
17
17
  path: nodePath
18
18
  };
19
19
 
20
- //#endregion
21
20
  export { tsconfigSyncOptions };