@tallyrelease/core 0.1.0 → 0.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.1](https://github.com/abinnovision/tally-release/compare/core-v0.1.0...core-v0.1.1) (2026-10-15)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * add unit tags and an affected --tag filter ([#14](https://github.com/abinnovision/tally-release/issues/14)) ([733e556](https://github.com/abinnovision/tally-release/commit/733e55642dc582e24e06d2e2b118110547ace742))
9
+
3
10
  ## 0.1.0 (2026-10-15)
4
11
 
5
12
 
@@ -11,6 +11,10 @@ export interface AffectedUnit {
11
11
  reason: AffectedReason;
12
12
  /** Affected direct dependencies that made a dependent affected. */
13
13
  via: string[];
14
+ /** True unless the unit's version is `none`. */
15
+ released: boolean;
16
+ /** Sorted unit tags. */
17
+ tags: string[];
14
18
  }
15
19
  /** `tallyrelease affected --json`, schema 1. */
16
20
  export interface AffectedDoc {
package/dist/affected.js CHANGED
@@ -14,13 +14,16 @@ export const computeAffected = async (workspace, git, opts) => {
14
14
  unattributed,
15
15
  warnings: [...workspace.warnings],
16
16
  });
17
- const everything = (reason) => units.map((u) => ({
17
+ const entry = (u, reason, via) => ({
18
18
  id: u.id,
19
19
  path: u.root,
20
20
  plugin: u.plugin,
21
21
  reason,
22
- via: [],
23
- }));
22
+ via,
23
+ released: u.version !== "none",
24
+ tags: [...u.tags],
25
+ });
26
+ const everything = (reason) => units.map((u) => entry(u, reason, []));
24
27
  if (opts.base === null) {
25
28
  return doc(everything("all"), { all: true, globalInputs: [] }, []);
26
29
  }
@@ -58,17 +61,8 @@ export const computeAffected = async (workspace, git, opts) => {
58
61
  }
59
62
  const result = units
60
63
  .filter((u) => affected.has(u.id))
61
- .map((u) => {
62
- const isDirect = direct.has(u.id);
63
- return {
64
- id: u.id,
65
- path: u.root,
66
- plugin: u.plugin,
67
- reason: isDirect ? "direct" : "dependent",
68
- via: isDirect
69
- ? []
70
- : (graph.dependencies.get(u.id) ?? []).filter((d) => affected.has(d)),
71
- };
72
- });
64
+ .map((u) => direct.has(u.id)
65
+ ? entry(u, "direct", [])
66
+ : entry(u, "dependent", (graph.dependencies.get(u.id) ?? []).filter((d) => affected.has(d))));
73
67
  return doc(result, { all: false, globalInputs: [] }, uniqueSorted(unattributed));
74
68
  };
package/dist/config.d.ts CHANGED
@@ -11,6 +11,8 @@ export interface UnitOverlay {
11
11
  scheme?: string;
12
12
  tagFormat?: string;
13
13
  propagate?: Propagate;
14
+ /** Labels for filtering, each matching `/^[A-Za-z0-9._-]+$/`. */
15
+ tags?: string[];
14
16
  }
15
17
  export interface DepConfig {
16
18
  from: string;
package/dist/discover.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { TallyError } from "./errors.js";
2
2
  import { defaultUnitId } from "./plugin.js";
3
3
  import { runHook } from "./plugins.js";
4
- import { compare } from "./util.js";
4
+ import { compare, uniqueSorted } from "./util.js";
5
5
  const UNIT_ID = /^(?!\.\.?$)[A-Za-z0-9._-]+$/;
6
+ const UNIT_TAG = /^[A-Za-z0-9._-]+$/;
6
7
  /** Drops `.` and empty segments; rejects absolute roots and `..` segments. */
7
8
  const normalizeRoot = (root) => {
8
9
  const segments = root.split("/");
@@ -40,12 +41,17 @@ export const discoverUnits = async (active, env) => {
40
41
  });
41
42
  }
42
43
  }
43
- for (const [key, { release, ...overlay }] of Object.entries(env.config.units ?? {})) {
44
+ for (const [key, { release, tags, ...overlay }] of Object.entries(env.config.units ?? {})) {
44
45
  const root = normalizeRoot(key);
46
+ const invalid = tags?.find((t) => !UNIT_TAG.test(t));
47
+ if (invalid !== undefined) {
48
+ throw new TallyError("E_UNIT_TAG", `tag "${invalid}" of unit at "${root}" must match ${UNIT_TAG.source}`, { tag: invalid, root });
49
+ }
45
50
  const entry = byRoot.get(root);
46
51
  if (entry) {
47
52
  entry.draft = { ...entry.draft, ...overlay };
48
53
  entry.release = release;
54
+ entry.tags = tags;
49
55
  }
50
56
  else {
51
57
  byRoot.set(root, {
@@ -57,6 +63,7 @@ export const discoverUnits = async (active, env) => {
57
63
  },
58
64
  meta: {},
59
65
  release,
66
+ tags,
60
67
  });
61
68
  }
62
69
  }
@@ -84,7 +91,7 @@ export const discoverUnits = async (active, env) => {
84
91
  const roots = [...byRoot.keys()].sort(compare);
85
92
  const { defaults } = env.config;
86
93
  return [...byId.values()]
87
- .map(({ plugin, draft, meta, release }) => {
94
+ .map(({ plugin, draft, meta, release, tags }) => {
88
95
  const { root } = draft;
89
96
  const nested = roots
90
97
  .filter((r) => isInside(r, root))
@@ -107,6 +114,7 @@ export const discoverUnits = async (active, env) => {
107
114
  defaults?.tagFormat ??
108
115
  (root === "." ? "v{version}" : "{id}-v{version}"),
109
116
  propagate: draft.propagate ?? defaults?.propagate ?? "auto",
117
+ tags: Object.freeze(uniqueSorted(tags ?? [])),
110
118
  meta: Object.freeze(meta),
111
119
  });
112
120
  })
package/dist/plugin.d.ts CHANGED
@@ -97,6 +97,8 @@ export interface Unit {
97
97
  readonly scheme: string;
98
98
  readonly tagFormat: string;
99
99
  readonly propagate: Propagate;
100
+ /** From the config overlay; sorted, unique. */
101
+ readonly tags: readonly string[];
100
102
  readonly meta: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
101
103
  }
102
104
  /** `to` depends on `from`. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tallyrelease/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Pure planning core of tallyrelease",
5
5
  "repository": {
6
6
  "type": "git",