@exadev/build-identity 2.1.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -118,6 +118,23 @@ const predictedVersion = await predictNextVersion(process.cwd(), releaseRules, a
118
118
  const identity = resolvePredictedIdentity(build, predictedVersion);
119
119
  ```
120
120
 
121
+ ## `readPackageVersion(repoRoot)`
122
+
123
+ ```ts
124
+ function readPackageVersion(repoRoot: string): string;
125
+ ```
126
+
127
+ The plain `"version"` field from `package.json` at `repoRoot`, read unconditionally and with no git access at all. This is deliberately not the same thing as `resolveBuildIdentity(...).version`, which is a build *identity* -- the released version only when a tag genuinely points at HEAD, and a short commit hash otherwise. Reach for this one when you want the last released semantic version regardless of whether this checkout happens to be sitting on its tag: an OpenAPI document's `info.version`, a user agent string, anything wanting a stable semver rather than an honest answer about what is deployed.
128
+
129
+ Throws rather than defaulting when `package.json` is missing or its `"version"` is absent, non-string, or empty -- the same stance every other export in this package takes. `defaultTagName` (`v${version}`) is the shared convention `resolveBuildIdentity` and `predictNextVersion` both apply to this value.
130
+
131
+ ```ts
132
+ import { readPackageVersion, resolveBuildIdentity } from '@exadev/build-identity';
133
+
134
+ const appVersion = readPackageVersion(process.cwd()); // "1.4.0", tagged or not
135
+ const build = resolveBuildIdentity(process.cwd(), 'exadev/example'); // "1.4.0" or "a1b2c3d"
136
+ ```
137
+
121
138
  ## `build-identity` (CLI)
122
139
 
123
140
  The same three functions, wired together, as a command. It exists for build and deploy steps that are a shell invocation rather than a JavaScript config file, so nothing in them can `import` this package at all -- `wrangler deploy --var RELEASE_VERSION:...` being the case it was built for. A step that *is* a JavaScript config file (`next.config.ts`, `vite.config.ts`) should import the functions directly instead; see [Framework-agnosticism](#framework-agnosticism) below.
package/dist/cli.js CHANGED
@@ -5,7 +5,7 @@ import { Command, InvalidArgumentError, Option } from "commander";
5
5
  import { join } from "node:path";
6
6
  import { execFileSync } from "node:child_process";
7
7
  //#region package.json
8
- var version = "2.1.0";
8
+ var version = "2.2.1";
9
9
  //#endregion
10
10
  //#region src/format-identity.ts
11
11
  const OUTPUT_FORMATS = ["json", "env"];
@@ -128,10 +128,9 @@ const NOOP_LOGGER = {
128
128
  * Predicts the version this repo's next release would be, from commits since the last tagged release -- WITHOUT running semantic-release's own top-level orchestrator. That orchestrator's core (not any plugin) verifies push access to the remote as part of resolving branches before analysis ever runs: genuinely slow, and needing credentials a prediction has no real reason to hold. This calls `analyzeCommits` directly instead -- no network, no registry lookups -- exactly the same hook `@semantic-release/commit-analyzer` exports, supplied by the caller (see `AnalyzeCommits`'s own doc comment for why this package never imports that module itself).
129
129
  *
130
130
  * Returns `undefined` when there is genuinely no predicted release -- no commits since the last tag, or none of them are release-worthy under `releaseRules` -- the same "nothing to report" case `resolvePredictedIdentity` already treats as valid, not an error. Throws for a genuine setup problem instead of defaulting: `repoRoot` isn't a git repository, or `package.json` has no usable version.
131
- *
132
- * @param repoRoot Path to the git working tree to inspect (must contain `package.json` at its root, same as `resolveBuildIdentity`).
133
- * @param releaseRules The commit-analyzer release rules this repo's own commit convention defines.
134
- * @param analyzeCommits `@semantic-release/commit-analyzer`'s own `analyzeCommits` export -- `loadCommitAnalyzer` (`./load-commit-analyzer`) is the tested way to obtain one.
131
+ * @param repoRoot - Path to the git working tree to inspect (must contain `package.json` at its root, same as `resolveBuildIdentity`).
132
+ * @param releaseRules - The commit-analyzer release rules this repo's own commit convention defines.
133
+ * @param analyzeCommits - `@semantic-release/commit-analyzer`'s own `analyzeCommits` export -- `loadCommitAnalyzer` (`./load-commit-analyzer`) is the tested way to obtain one.
135
134
  */
136
135
  async function predictNextVersion(repoRoot, releaseRules, analyzeCommits, options = {}) {
137
136
  const lastVersion = readPackageVersion(repoRoot);
@@ -231,9 +230,8 @@ function assertRepoSlug(repoSlug) {
231
230
  * Resolves what the current build actually is: a real, already-tagged release, or a build made from a commit that hasn't been released yet.
232
231
  *
233
232
  * This is the one property the whole package exists to guarantee: `kind: 'release'` is returned if and only if a tag named `tagName(version)` (default `v${version}`) provably points at the exact commit HEAD is on right now, checked live against git -- never inferred from `package.json` alone, a CI environment variable, or any other proxy that could be true before the tag actually exists. A caller can render `url` as a link the moment it gets a result back, in either case, without first checking whether that link is real.
234
- *
235
- * @param repoRoot Path to the git working tree to inspect (must contain `package.json` at its root).
236
- * @param repoSlug The GitHub `owner/repo` slug used to build both release and commit URLs.
233
+ * @param repoRoot - Path to the git working tree to inspect (must contain `package.json` at its root).
234
+ * @param repoSlug - The GitHub `owner/repo` slug used to build both release and commit URLs.
237
235
  */
238
236
  function resolveBuildIdentity(repoRoot, repoSlug, options = {}) {
239
237
  assertRepoSlug(repoSlug);
package/dist/index.cjs CHANGED
@@ -69,9 +69,8 @@ function assertRepoSlug(repoSlug) {
69
69
  * Resolves what the current build actually is: a real, already-tagged release, or a build made from a commit that hasn't been released yet.
70
70
  *
71
71
  * This is the one property the whole package exists to guarantee: `kind: 'release'` is returned if and only if a tag named `tagName(version)` (default `v${version}`) provably points at the exact commit HEAD is on right now, checked live against git -- never inferred from `package.json` alone, a CI environment variable, or any other proxy that could be true before the tag actually exists. A caller can render `url` as a link the moment it gets a result back, in either case, without first checking whether that link is real.
72
- *
73
- * @param repoRoot Path to the git working tree to inspect (must contain `package.json` at its root).
74
- * @param repoSlug The GitHub `owner/repo` slug used to build both release and commit URLs.
72
+ * @param repoRoot - Path to the git working tree to inspect (must contain `package.json` at its root).
73
+ * @param repoSlug - The GitHub `owner/repo` slug used to build both release and commit URLs.
75
74
  */
76
75
  function resolveBuildIdentity(repoRoot, repoSlug, options = {}) {
77
76
  assertRepoSlug(repoSlug);
@@ -159,10 +158,9 @@ const NOOP_LOGGER = {
159
158
  * Predicts the version this repo's next release would be, from commits since the last tagged release -- WITHOUT running semantic-release's own top-level orchestrator. That orchestrator's core (not any plugin) verifies push access to the remote as part of resolving branches before analysis ever runs: genuinely slow, and needing credentials a prediction has no real reason to hold. This calls `analyzeCommits` directly instead -- no network, no registry lookups -- exactly the same hook `@semantic-release/commit-analyzer` exports, supplied by the caller (see `AnalyzeCommits`'s own doc comment for why this package never imports that module itself).
160
159
  *
161
160
  * Returns `undefined` when there is genuinely no predicted release -- no commits since the last tag, or none of them are release-worthy under `releaseRules` -- the same "nothing to report" case `resolvePredictedIdentity` already treats as valid, not an error. Throws for a genuine setup problem instead of defaulting: `repoRoot` isn't a git repository, or `package.json` has no usable version.
162
- *
163
- * @param repoRoot Path to the git working tree to inspect (must contain `package.json` at its root, same as `resolveBuildIdentity`).
164
- * @param releaseRules The commit-analyzer release rules this repo's own commit convention defines.
165
- * @param analyzeCommits `@semantic-release/commit-analyzer`'s own `analyzeCommits` export -- `loadCommitAnalyzer` (`./load-commit-analyzer`) is the tested way to obtain one.
161
+ * @param repoRoot - Path to the git working tree to inspect (must contain `package.json` at its root, same as `resolveBuildIdentity`).
162
+ * @param releaseRules - The commit-analyzer release rules this repo's own commit convention defines.
163
+ * @param analyzeCommits - `@semantic-release/commit-analyzer`'s own `analyzeCommits` export -- `loadCommitAnalyzer` (`./load-commit-analyzer`) is the tested way to obtain one.
166
164
  */
167
165
  async function predictNextVersion(repoRoot, releaseRules, analyzeCommits, options = {}) {
168
166
  const lastVersion = readPackageVersion(repoRoot);
@@ -204,5 +202,6 @@ async function loadCommitAnalyzer() {
204
202
  //#endregion
205
203
  exports.loadCommitAnalyzer = loadCommitAnalyzer;
206
204
  exports.predictNextVersion = predictNextVersion;
205
+ exports.readPackageVersion = readPackageVersion;
207
206
  exports.resolveBuildIdentity = resolveBuildIdentity;
208
207
  exports.resolvePredictedIdentity = resolvePredictedIdentity;
package/dist/index.d.cts CHANGED
@@ -27,7 +27,7 @@ type BuildIdentity = {
27
27
  };
28
28
  interface ResolveBuildIdentityOptions {
29
29
  /**
30
- * Turns the version read from `package.json` into the git tag name that is expected to mark its release. Defaults to a `v` prefix (`"1.4.0"` -> `"v1.4.0"`), the convention this package's own release tooling and GitHub's own release UI both use -- override it for a repo that tags releases differently (a bare version, a package-scoped prefix in a monorepo, and so on).
30
+ * Turns the version read from `package.json` into the git tag name that is expected to mark its release. Defaults to a `v` prefix (`"1.4.0"` -\> `"v1.4.0"`), the convention this package's own release tooling and GitHub's own release UI both use -- override it for a repo that tags releases differently (a bare version, a package-scoped prefix in a monorepo, and so on).
31
31
  */
32
32
  readonly tagName?: (version: string) => string;
33
33
  }
@@ -47,9 +47,8 @@ interface DisplayIdentity {
47
47
  * Resolves what the current build actually is: a real, already-tagged release, or a build made from a commit that hasn't been released yet.
48
48
  *
49
49
  * This is the one property the whole package exists to guarantee: `kind: 'release'` is returned if and only if a tag named `tagName(version)` (default `v${version}`) provably points at the exact commit HEAD is on right now, checked live against git -- never inferred from `package.json` alone, a CI environment variable, or any other proxy that could be true before the tag actually exists. A caller can render `url` as a link the moment it gets a result back, in either case, without first checking whether that link is real.
50
- *
51
- * @param repoRoot Path to the git working tree to inspect (must contain `package.json` at its root).
52
- * @param repoSlug The GitHub `owner/repo` slug used to build both release and commit URLs.
50
+ * @param repoRoot - Path to the git working tree to inspect (must contain `package.json` at its root).
51
+ * @param repoSlug - The GitHub `owner/repo` slug used to build both release and commit URLs.
53
52
  */
54
53
  declare function resolveBuildIdentity(repoRoot: string, repoSlug: string, options?: ResolveBuildIdentityOptions): BuildIdentity;
55
54
  //#endregion
@@ -65,7 +64,7 @@ declare function resolvePredictedIdentity(build: BuildIdentity, predictedVersion
65
64
  //#endregion
66
65
  //#region src/predict-next-version.d.ts
67
66
  type ReleaseLevel = 'major' | 'minor' | 'patch';
68
- /** One @semantic-release/commit-analyzer release rule -- either `{ type, release }` (a conventional-commit type, e.g. `"feat"`) or `{ breaking: true, release }` (any commit whose footer/body declares a breaking change, regardless of type). `release` also accepts `false`, commit-analyzer's own way to say "this type never triggers a release" -- needed to override a broader rule or preset default, distinct from simply omitting the type (which instead falls through to whatever the preset's own default is). This package hardcodes no rules of its own: a repo's commit-type-to-release-level convention is real, repo-specific configuration. */
67
+ /** One `@semantic-release/commit-analyzer` release rule -- either `{ type, release }` (a conventional-commit type, e.g. `"feat"`) or `{ breaking: true, release }` (any commit whose footer/body declares a breaking change, regardless of type). `release` also accepts `false`, commit-analyzer's own way to say "this type never triggers a release" -- needed to override a broader rule or preset default, distinct from simply omitting the type (which instead falls through to whatever the preset's own default is). This package hardcodes no rules of its own: a repo's commit-type-to-release-level convention is real, repo-specific configuration. */
69
68
  type ReleaseRule = {
70
69
  readonly type: string;
71
70
  readonly release: ReleaseLevel | false;
@@ -80,7 +79,7 @@ type AnalyzeCommits = (pluginConfig: unknown, context: unknown) => Promise<unkno
80
79
  interface PredictNextVersionOptions {
81
80
  /** Matches `resolveBuildIdentity`'s own option of the same name -- pass the same function to both when a repo tags non-default, so "which tag marks the last release" stays one convention rather than two that could drift apart. Defaults to the `v${version}` convention. */
82
81
  tagName?: (version: string) => string;
83
- /** Receives @semantic-release/commit-analyzer's own per-commit narration (e.g. "Analyzing commit: ...", "The release type for the commit is minor"). Defaults to discarding it. Pass your own to route it to stderr or a real logger -- never stdout, so a caller parsing a single predicted-version line from this process's own stdout is never at risk of it being contaminated. */
82
+ /** Receives `@semantic-release/commit-analyzer`'s own per-commit narration (e.g. "Analyzing commit: ...", "The release type for the commit is minor"). Defaults to discarding it. Pass your own to route it to stderr or a real logger -- never stdout, so a caller parsing a single predicted-version line from this process's own stdout is never at risk of it being contaminated. */
84
83
  logger?: {
85
84
  log: (...args: readonly unknown[]) => void;
86
85
  error: (...args: readonly unknown[]) => void;
@@ -90,10 +89,9 @@ interface PredictNextVersionOptions {
90
89
  * Predicts the version this repo's next release would be, from commits since the last tagged release -- WITHOUT running semantic-release's own top-level orchestrator. That orchestrator's core (not any plugin) verifies push access to the remote as part of resolving branches before analysis ever runs: genuinely slow, and needing credentials a prediction has no real reason to hold. This calls `analyzeCommits` directly instead -- no network, no registry lookups -- exactly the same hook `@semantic-release/commit-analyzer` exports, supplied by the caller (see `AnalyzeCommits`'s own doc comment for why this package never imports that module itself).
91
90
  *
92
91
  * Returns `undefined` when there is genuinely no predicted release -- no commits since the last tag, or none of them are release-worthy under `releaseRules` -- the same "nothing to report" case `resolvePredictedIdentity` already treats as valid, not an error. Throws for a genuine setup problem instead of defaulting: `repoRoot` isn't a git repository, or `package.json` has no usable version.
93
- *
94
- * @param repoRoot Path to the git working tree to inspect (must contain `package.json` at its root, same as `resolveBuildIdentity`).
95
- * @param releaseRules The commit-analyzer release rules this repo's own commit convention defines.
96
- * @param analyzeCommits `@semantic-release/commit-analyzer`'s own `analyzeCommits` export -- `loadCommitAnalyzer` (`./load-commit-analyzer`) is the tested way to obtain one.
92
+ * @param repoRoot - Path to the git working tree to inspect (must contain `package.json` at its root, same as `resolveBuildIdentity`).
93
+ * @param releaseRules - The commit-analyzer release rules this repo's own commit convention defines.
94
+ * @param analyzeCommits - `@semantic-release/commit-analyzer`'s own `analyzeCommits` export -- `loadCommitAnalyzer` (`./load-commit-analyzer`) is the tested way to obtain one.
97
95
  */
98
96
  declare function predictNextVersion(repoRoot: string, releaseRules: readonly ReleaseRule[], analyzeCommits: AnalyzeCommits, options?: PredictNextVersionOptions): Promise<string | undefined>;
99
97
  //#endregion
@@ -105,4 +103,8 @@ declare function predictNextVersion(repoRoot: string, releaseRules: readonly Rel
105
103
  */
106
104
  declare function loadCommitAnalyzer(): Promise<AnalyzeCommits>;
107
105
  //#endregion
108
- export { type AnalyzeCommits, type BuildIdentity, type DisplayIdentity, type PredictNextVersionOptions, type ReleaseLevel, type ReleaseRule, type ResolveBuildIdentityOptions, loadCommitAnalyzer, predictNextVersion, resolveBuildIdentity, resolvePredictedIdentity };
106
+ //#region src/package-version.d.ts
107
+ /** The single semantic-release-managed version, read from `package.json` at `repoRoot`'s root -- shared by `resolveBuildIdentity` (what this build's version is, if released) and `predictNextVersion` (the version to diff commits since). Throws rather than defaulting, matching this package's own "no sensible placeholder identity" stance. */
108
+ declare function readPackageVersion(repoRoot: string): string;
109
+ //#endregion
110
+ export { type AnalyzeCommits, type BuildIdentity, type DisplayIdentity, type PredictNextVersionOptions, type ReleaseLevel, type ReleaseRule, type ResolveBuildIdentityOptions, loadCommitAnalyzer, predictNextVersion, readPackageVersion, resolveBuildIdentity, resolvePredictedIdentity };
package/dist/index.d.ts CHANGED
@@ -27,7 +27,7 @@ type BuildIdentity = {
27
27
  };
28
28
  interface ResolveBuildIdentityOptions {
29
29
  /**
30
- * Turns the version read from `package.json` into the git tag name that is expected to mark its release. Defaults to a `v` prefix (`"1.4.0"` -> `"v1.4.0"`), the convention this package's own release tooling and GitHub's own release UI both use -- override it for a repo that tags releases differently (a bare version, a package-scoped prefix in a monorepo, and so on).
30
+ * Turns the version read from `package.json` into the git tag name that is expected to mark its release. Defaults to a `v` prefix (`"1.4.0"` -\> `"v1.4.0"`), the convention this package's own release tooling and GitHub's own release UI both use -- override it for a repo that tags releases differently (a bare version, a package-scoped prefix in a monorepo, and so on).
31
31
  */
32
32
  readonly tagName?: (version: string) => string;
33
33
  }
@@ -47,9 +47,8 @@ interface DisplayIdentity {
47
47
  * Resolves what the current build actually is: a real, already-tagged release, or a build made from a commit that hasn't been released yet.
48
48
  *
49
49
  * This is the one property the whole package exists to guarantee: `kind: 'release'` is returned if and only if a tag named `tagName(version)` (default `v${version}`) provably points at the exact commit HEAD is on right now, checked live against git -- never inferred from `package.json` alone, a CI environment variable, or any other proxy that could be true before the tag actually exists. A caller can render `url` as a link the moment it gets a result back, in either case, without first checking whether that link is real.
50
- *
51
- * @param repoRoot Path to the git working tree to inspect (must contain `package.json` at its root).
52
- * @param repoSlug The GitHub `owner/repo` slug used to build both release and commit URLs.
50
+ * @param repoRoot - Path to the git working tree to inspect (must contain `package.json` at its root).
51
+ * @param repoSlug - The GitHub `owner/repo` slug used to build both release and commit URLs.
53
52
  */
54
53
  declare function resolveBuildIdentity(repoRoot: string, repoSlug: string, options?: ResolveBuildIdentityOptions): BuildIdentity;
55
54
  //#endregion
@@ -65,7 +64,7 @@ declare function resolvePredictedIdentity(build: BuildIdentity, predictedVersion
65
64
  //#endregion
66
65
  //#region src/predict-next-version.d.ts
67
66
  type ReleaseLevel = 'major' | 'minor' | 'patch';
68
- /** One @semantic-release/commit-analyzer release rule -- either `{ type, release }` (a conventional-commit type, e.g. `"feat"`) or `{ breaking: true, release }` (any commit whose footer/body declares a breaking change, regardless of type). `release` also accepts `false`, commit-analyzer's own way to say "this type never triggers a release" -- needed to override a broader rule or preset default, distinct from simply omitting the type (which instead falls through to whatever the preset's own default is). This package hardcodes no rules of its own: a repo's commit-type-to-release-level convention is real, repo-specific configuration. */
67
+ /** One `@semantic-release/commit-analyzer` release rule -- either `{ type, release }` (a conventional-commit type, e.g. `"feat"`) or `{ breaking: true, release }` (any commit whose footer/body declares a breaking change, regardless of type). `release` also accepts `false`, commit-analyzer's own way to say "this type never triggers a release" -- needed to override a broader rule or preset default, distinct from simply omitting the type (which instead falls through to whatever the preset's own default is). This package hardcodes no rules of its own: a repo's commit-type-to-release-level convention is real, repo-specific configuration. */
69
68
  type ReleaseRule = {
70
69
  readonly type: string;
71
70
  readonly release: ReleaseLevel | false;
@@ -80,7 +79,7 @@ type AnalyzeCommits = (pluginConfig: unknown, context: unknown) => Promise<unkno
80
79
  interface PredictNextVersionOptions {
81
80
  /** Matches `resolveBuildIdentity`'s own option of the same name -- pass the same function to both when a repo tags non-default, so "which tag marks the last release" stays one convention rather than two that could drift apart. Defaults to the `v${version}` convention. */
82
81
  tagName?: (version: string) => string;
83
- /** Receives @semantic-release/commit-analyzer's own per-commit narration (e.g. "Analyzing commit: ...", "The release type for the commit is minor"). Defaults to discarding it. Pass your own to route it to stderr or a real logger -- never stdout, so a caller parsing a single predicted-version line from this process's own stdout is never at risk of it being contaminated. */
82
+ /** Receives `@semantic-release/commit-analyzer`'s own per-commit narration (e.g. "Analyzing commit: ...", "The release type for the commit is minor"). Defaults to discarding it. Pass your own to route it to stderr or a real logger -- never stdout, so a caller parsing a single predicted-version line from this process's own stdout is never at risk of it being contaminated. */
84
83
  logger?: {
85
84
  log: (...args: readonly unknown[]) => void;
86
85
  error: (...args: readonly unknown[]) => void;
@@ -90,10 +89,9 @@ interface PredictNextVersionOptions {
90
89
  * Predicts the version this repo's next release would be, from commits since the last tagged release -- WITHOUT running semantic-release's own top-level orchestrator. That orchestrator's core (not any plugin) verifies push access to the remote as part of resolving branches before analysis ever runs: genuinely slow, and needing credentials a prediction has no real reason to hold. This calls `analyzeCommits` directly instead -- no network, no registry lookups -- exactly the same hook `@semantic-release/commit-analyzer` exports, supplied by the caller (see `AnalyzeCommits`'s own doc comment for why this package never imports that module itself).
91
90
  *
92
91
  * Returns `undefined` when there is genuinely no predicted release -- no commits since the last tag, or none of them are release-worthy under `releaseRules` -- the same "nothing to report" case `resolvePredictedIdentity` already treats as valid, not an error. Throws for a genuine setup problem instead of defaulting: `repoRoot` isn't a git repository, or `package.json` has no usable version.
93
- *
94
- * @param repoRoot Path to the git working tree to inspect (must contain `package.json` at its root, same as `resolveBuildIdentity`).
95
- * @param releaseRules The commit-analyzer release rules this repo's own commit convention defines.
96
- * @param analyzeCommits `@semantic-release/commit-analyzer`'s own `analyzeCommits` export -- `loadCommitAnalyzer` (`./load-commit-analyzer`) is the tested way to obtain one.
92
+ * @param repoRoot - Path to the git working tree to inspect (must contain `package.json` at its root, same as `resolveBuildIdentity`).
93
+ * @param releaseRules - The commit-analyzer release rules this repo's own commit convention defines.
94
+ * @param analyzeCommits - `@semantic-release/commit-analyzer`'s own `analyzeCommits` export -- `loadCommitAnalyzer` (`./load-commit-analyzer`) is the tested way to obtain one.
97
95
  */
98
96
  declare function predictNextVersion(repoRoot: string, releaseRules: readonly ReleaseRule[], analyzeCommits: AnalyzeCommits, options?: PredictNextVersionOptions): Promise<string | undefined>;
99
97
  //#endregion
@@ -105,4 +103,8 @@ declare function predictNextVersion(repoRoot: string, releaseRules: readonly Rel
105
103
  */
106
104
  declare function loadCommitAnalyzer(): Promise<AnalyzeCommits>;
107
105
  //#endregion
108
- export { type AnalyzeCommits, type BuildIdentity, type DisplayIdentity, type PredictNextVersionOptions, type ReleaseLevel, type ReleaseRule, type ResolveBuildIdentityOptions, loadCommitAnalyzer, predictNextVersion, resolveBuildIdentity, resolvePredictedIdentity };
106
+ //#region src/package-version.d.ts
107
+ /** The single semantic-release-managed version, read from `package.json` at `repoRoot`'s root -- shared by `resolveBuildIdentity` (what this build's version is, if released) and `predictNextVersion` (the version to diff commits since). Throws rather than defaulting, matching this package's own "no sensible placeholder identity" stance. */
108
+ declare function readPackageVersion(repoRoot: string): string;
109
+ //#endregion
110
+ export { type AnalyzeCommits, type BuildIdentity, type DisplayIdentity, type PredictNextVersionOptions, type ReleaseLevel, type ReleaseRule, type ResolveBuildIdentityOptions, loadCommitAnalyzer, predictNextVersion, readPackageVersion, resolveBuildIdentity, resolvePredictedIdentity };
package/dist/index.js CHANGED
@@ -68,9 +68,8 @@ function assertRepoSlug(repoSlug) {
68
68
  * Resolves what the current build actually is: a real, already-tagged release, or a build made from a commit that hasn't been released yet.
69
69
  *
70
70
  * This is the one property the whole package exists to guarantee: `kind: 'release'` is returned if and only if a tag named `tagName(version)` (default `v${version}`) provably points at the exact commit HEAD is on right now, checked live against git -- never inferred from `package.json` alone, a CI environment variable, or any other proxy that could be true before the tag actually exists. A caller can render `url` as a link the moment it gets a result back, in either case, without first checking whether that link is real.
71
- *
72
- * @param repoRoot Path to the git working tree to inspect (must contain `package.json` at its root).
73
- * @param repoSlug The GitHub `owner/repo` slug used to build both release and commit URLs.
71
+ * @param repoRoot - Path to the git working tree to inspect (must contain `package.json` at its root).
72
+ * @param repoSlug - The GitHub `owner/repo` slug used to build both release and commit URLs.
74
73
  */
75
74
  function resolveBuildIdentity(repoRoot, repoSlug, options = {}) {
76
75
  assertRepoSlug(repoSlug);
@@ -158,10 +157,9 @@ const NOOP_LOGGER = {
158
157
  * Predicts the version this repo's next release would be, from commits since the last tagged release -- WITHOUT running semantic-release's own top-level orchestrator. That orchestrator's core (not any plugin) verifies push access to the remote as part of resolving branches before analysis ever runs: genuinely slow, and needing credentials a prediction has no real reason to hold. This calls `analyzeCommits` directly instead -- no network, no registry lookups -- exactly the same hook `@semantic-release/commit-analyzer` exports, supplied by the caller (see `AnalyzeCommits`'s own doc comment for why this package never imports that module itself).
159
158
  *
160
159
  * Returns `undefined` when there is genuinely no predicted release -- no commits since the last tag, or none of them are release-worthy under `releaseRules` -- the same "nothing to report" case `resolvePredictedIdentity` already treats as valid, not an error. Throws for a genuine setup problem instead of defaulting: `repoRoot` isn't a git repository, or `package.json` has no usable version.
161
- *
162
- * @param repoRoot Path to the git working tree to inspect (must contain `package.json` at its root, same as `resolveBuildIdentity`).
163
- * @param releaseRules The commit-analyzer release rules this repo's own commit convention defines.
164
- * @param analyzeCommits `@semantic-release/commit-analyzer`'s own `analyzeCommits` export -- `loadCommitAnalyzer` (`./load-commit-analyzer`) is the tested way to obtain one.
160
+ * @param repoRoot - Path to the git working tree to inspect (must contain `package.json` at its root, same as `resolveBuildIdentity`).
161
+ * @param releaseRules - The commit-analyzer release rules this repo's own commit convention defines.
162
+ * @param analyzeCommits - `@semantic-release/commit-analyzer`'s own `analyzeCommits` export -- `loadCommitAnalyzer` (`./load-commit-analyzer`) is the tested way to obtain one.
165
163
  */
166
164
  async function predictNextVersion(repoRoot, releaseRules, analyzeCommits, options = {}) {
167
165
  const lastVersion = readPackageVersion(repoRoot);
@@ -201,4 +199,4 @@ async function loadCommitAnalyzer() {
201
199
  return commitAnalyzerModule.analyzeCommits;
202
200
  }
203
201
  //#endregion
204
- export { loadCommitAnalyzer, predictNextVersion, resolveBuildIdentity, resolvePredictedIdentity };
202
+ export { loadCommitAnalyzer, predictNextVersion, readPackageVersion, resolveBuildIdentity, resolvePredictedIdentity };
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@exadev/build-identity",
3
- "version": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "description": "Resolve a build's true identity (a real release tag, or the commit it was built from) from git state, with an optional predicted-version display layer",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "license": "MIT",
8
- "packageManager": "pnpm@11.6.0",
8
+ "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
9
9
  "engines": {
10
10
  "node": ">=20"
11
11
  },
@@ -55,7 +55,7 @@
55
55
  "@arethetypeswrong/cli": "0.18.5",
56
56
  "@commitlint/cli": "21.2.1",
57
57
  "@commitlint/config-conventional": "21.2.0",
58
- "@exadev/eslint-config": "^2.10.4",
58
+ "@exadev/eslint-config": "2.12.1",
59
59
  "@semantic-release/changelog": "7.0.0",
60
60
  "@semantic-release/commit-analyzer": "13.0.1",
61
61
  "@semantic-release/git": "11.0.1",