@bridge-ds/core 0.3.0 → 0.4.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.
@@ -0,0 +1,78 @@
1
+ import { type FlatToken } from './types';
2
+ /** What one change brings: its token files where it started and now, and the token files it edits. */
3
+ export interface CombineSource {
4
+ number: number;
5
+ /** Token file texts where the change started (relative to the tokens root). Undefined: the file did not exist. */
6
+ base: Record<string, string | undefined>;
7
+ /** Token file texts in the change now. Undefined: the change removes the file. */
8
+ head: Record<string, string | undefined>;
9
+ /** Token files the change edits, relative to the tokens root. */
10
+ files: string[];
11
+ }
12
+ export interface CombineEdit {
13
+ /** `<file>#<token id>`: the same token in the same file across changes. */
14
+ key: string;
15
+ file: string;
16
+ /** The token's path in the change (its old path when the change removes it). */
17
+ path: string;
18
+ change: number;
19
+ /** The change's version of the token; undefined when the change removes it. */
20
+ token: FlatToken | undefined;
21
+ }
22
+ export interface ChangeEdits {
23
+ number: number;
24
+ edits: CombineEdit[];
25
+ /** Files that could not be read (not JSON). */
26
+ problems: string[];
27
+ }
28
+ /** The token edits of one change: every token whose version differs between where the change started and now. */
29
+ export declare function changeEdits(src: CombineSource): ChangeEdits;
30
+ /** One value a conflicting token can take, and the changes that set it. */
31
+ export interface CombineOption {
32
+ changes: number[];
33
+ token: FlatToken | undefined;
34
+ }
35
+ /** A token two or more changes set differently: the designer picks one change's value. */
36
+ export interface CombineConflict {
37
+ key: string;
38
+ file: string;
39
+ path: string;
40
+ /** Distinct values, in the order of the changes. */
41
+ options: CombineOption[];
42
+ }
43
+ /** The pick of each conflict: the change whose value the combination uses. */
44
+ export type CombinePicks = Record<string, number>;
45
+ export interface Combination {
46
+ /** Every token file of the latest library, with the combined edits applied (unchanged files as they are). */
47
+ files: Record<string, string>;
48
+ /** The changes combined, in order. */
49
+ included: number[];
50
+ /** Token values the combination edits (one per token and file: a token edited in light and dark counts twice). */
51
+ edits: number;
52
+ /** Tokens the combination edits, by name. */
53
+ tokens: number;
54
+ conflicts: CombineConflict[];
55
+ /** Conflicts without a pick that counts: left at the library's value ('skip') or given the first change's ('first'). */
56
+ missing: CombineConflict[];
57
+ /** Token path -> the changes whose value the combination uses for it. */
58
+ from: Record<string, number[]>;
59
+ problems: string[];
60
+ }
61
+ /** Tokens that two or more of these changes set differently. */
62
+ export declare function combineConflicts(changes: ChangeEdits[]): CombineConflict[];
63
+ /** The option a pick selects, or null when the picked change is not among them (not picked, or switched off). */
64
+ export declare function pickedOption(c: CombineConflict, picks: CombinePicks): CombineOption | null;
65
+ /** Conflicts that still need a pick. */
66
+ export declare const unpicked: (conflicts: CombineConflict[], picks: CombinePicks) => CombineConflict[];
67
+ /**
68
+ * The latest library plus the edits of the included changes (all of them by default, in their order). A conflict
69
+ * uses the picked change's value. Without a pick that counts, `unpicked: 'skip'` (Studio, before opening) leaves the
70
+ * token at the library's value and lists it in `missing`; `'first'` (the toolbar, when a picked change is switched
71
+ * off) uses the first included change's value and still lists it.
72
+ */
73
+ export declare function combineChanges(latest: Record<string, string>, changes: ChangeEdits[], picks?: CombinePicks, opts?: {
74
+ include?: number[];
75
+ unpicked?: 'skip' | 'first';
76
+ }): Combination;
77
+ export declare function encodePicks(picks: CombinePicks): string;
78
+ export declare function decodePicks(raw: string | null | undefined): CombinePicks;
@@ -0,0 +1,72 @@
1
+ import { type TokenDocument } from './dtcg-codec';
2
+ import { type FlatToken } from './types';
3
+ /** Which side a conflict keeps: this change ("Keep mine") or the latest library ("Use the library's"). */
4
+ export type MergeSide = 'mine' | 'theirs';
5
+ export interface TokenMergeConflict {
6
+ /** Stable key for the choice: `<file>#<token id>`. */
7
+ key: string;
8
+ /** Token file, relative to the tokens root. */
9
+ file: string;
10
+ /** Display path: this change's name, else the library's, else the shared one. */
11
+ path: string;
12
+ base?: FlatToken | undefined;
13
+ mine?: FlatToken | undefined;
14
+ theirs?: FlatToken | undefined;
15
+ /** The side that removed the token while the other changed it. Null when both sides kept it. */
16
+ removedOn: MergeSide | null;
17
+ /** "Keep mine" by default; null when the token was removed on one side and changed on the other. */
18
+ defaultChoice: MergeSide | null;
19
+ }
20
+ export interface TokenMergePlan {
21
+ /** Token files both sides changed, relative to the tokens root. */
22
+ files: string[];
23
+ conflicts: TokenMergeConflict[];
24
+ /** Tokens only this change touched: applied on top of the library as they are. */
25
+ mineOnly: number;
26
+ /** Tokens only the library touched: kept as the library has them. */
27
+ theirsOnly: number;
28
+ /** Files that could not be read (not JSON): nothing can be merged while there is one. */
29
+ problems: string[];
30
+ }
31
+ export interface TokenMergeInput {
32
+ /** File texts at the commit both sides share. Undefined: the file did not exist there. */
33
+ base: Record<string, string | undefined>;
34
+ /** File texts in the change. */
35
+ mine: Record<string, string | undefined>;
36
+ /** File texts in the latest library. */
37
+ theirs: Record<string, string | undefined>;
38
+ /** Token files both sides changed (the others need no merge). */
39
+ files: string[];
40
+ }
41
+ export type MergeChoices = Record<string, MergeSide | undefined>;
42
+ /** The side that removed a token the other side changed, or null. */
43
+ export declare function removedSide(c: {
44
+ base?: unknown;
45
+ mine?: unknown;
46
+ theirs?: unknown;
47
+ }): MergeSide | null;
48
+ /** "Keep mine" by default, except for a token removed on one side and changed on the other: no default there. */
49
+ export declare const defaultChoiceFor: (c: {
50
+ base?: unknown;
51
+ mine?: unknown;
52
+ theirs?: unknown;
53
+ }) => MergeSide | null;
54
+ /** What both sides did to the token files they both changed, and which tokens need a decision. */
55
+ export declare function planTokenMerge(input: TokenMergeInput): TokenMergePlan;
56
+ /** The side a conflict keeps: the designer's pick, else its default (null: still to pick). */
57
+ export declare const choiceFor: (c: TokenMergeConflict, choices: MergeChoices) => MergeSide | null;
58
+ /** Conflicts that still need a pick: removed on one side, changed on the other, and not decided yet. */
59
+ export declare function missingChoices(plan: Pick<TokenMergePlan, 'conflicts'>, choices: MergeChoices): TokenMergeConflict[];
60
+ /** Puts this change's version of a token into the library's file: its value, type, description and extensions. Also used by token-combine. */
61
+ export declare function takeMine(doc: TokenDocument, mine: FlatToken | undefined, existing: FlatToken | undefined): boolean;
62
+ export interface TokenMergeResult {
63
+ /** Merged text per file (relative to the tokens root); null when the merged file holds no token and is removed. */
64
+ files: Record<string, string | null>;
65
+ /** How many conflicts kept each side. */
66
+ kept: Record<MergeSide, number>;
67
+ }
68
+ /**
69
+ * The merged token files: the latest library's text, plus every token only this change touched, plus each conflict
70
+ * as chosen. Throws when a file could not be read or a conflict still needs a pick.
71
+ */
72
+ export declare function applyTokenMerge(input: TokenMergeInput, choices: MergeChoices): TokenMergeResult;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bridge-ds/core",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "Bridge core: bridge.config.json, DTCG token loading (tiers and layered modes), alias resolution, WCAG contrast, diffs, minimal-diff edits, PR body, the shared risk tier classifier, changesets and a fetch-based GitHub client. No Figma API, no DOM; Node-only helpers (git, reading a product folder) under @bridge-ds/core/node; the adoption audit under @bridge-ds/core/audit.",
6
6
  "license": "MIT",