@bridge-ds/mcp 0.5.0 → 0.7.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.
@@ -188,7 +188,7 @@ export declare function tryBranch(ctx: BridgeContext, a: {
188
188
  }[];
189
189
  share: {
190
190
  message?: import("@bridge-ds/core").ShareMessage | undefined;
191
- state: "ready" | "building" | "failed" | "closed" | "no-packages" | "shipped";
191
+ state: "ready" | "building" | "failed" | "closed" | "shipped" | "no-packages";
192
192
  install: string | null;
193
193
  sentence: string;
194
194
  };
package/dist/brand.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type BrandRadiusInput } from '@bridge-ds/core';
1
+ import { type ChangesMode, type BrandRadiusInput } from '@bridge-ds/core';
2
2
  import type { BridgeContext } from './context.js';
3
3
  export interface BrandArgs {
4
4
  slug: string;
@@ -62,6 +62,8 @@ export declare function planBrand(ctx: BridgeContext, a: BrandArgs): Promise<{
62
62
  }>;
63
63
  export declare function proposeBrand(ctx: BridgeContext, a: BrandArgs & {
64
64
  dryRun?: boolean;
65
+ changes?: ChangesMode | undefined;
66
+ source?: 'mcp' | 'cli' | undefined;
65
67
  }): Promise<{
66
68
  hint: string;
67
69
  ok: boolean;
@@ -99,6 +101,135 @@ export declare function proposeBrand(ctx: BridgeContext, a: BrandArgs & {
99
101
  prBody: string;
100
102
  status: string;
101
103
  why: string;
104
+ } | {
105
+ changesMode: string;
106
+ suggestion: {
107
+ title: string;
108
+ labels: string[];
109
+ body: string;
110
+ parts: number;
111
+ };
112
+ fileContents: {
113
+ path: string;
114
+ content: string | null;
115
+ }[];
116
+ ok: boolean;
117
+ slug: string;
118
+ name: string;
119
+ from: string;
120
+ title: string;
121
+ tier: import("@bridge-ds/core").RiskTier;
122
+ bump: "minor";
123
+ label: string;
124
+ reasons: string[];
125
+ files: {
126
+ path: string;
127
+ action: "create" | "modify";
128
+ }[];
129
+ actionStep: number;
130
+ ramps: {
131
+ [k: string]: {
132
+ [k: string]: string;
133
+ };
134
+ };
135
+ contrast: {
136
+ checks: number;
137
+ passing: number;
138
+ themes: string[];
139
+ line: string;
140
+ failing: {
141
+ pair: string;
142
+ modes: string;
143
+ ratio: number | null;
144
+ min: number;
145
+ }[];
146
+ };
147
+ issues: import("@bridge-ds/core").BrandIssue[];
148
+ prBody: string;
149
+ status: string;
150
+ } | {
151
+ changesMode: string;
152
+ fileContents: {
153
+ path: string;
154
+ content: string | null;
155
+ }[];
156
+ ok: boolean;
157
+ slug: string;
158
+ name: string;
159
+ from: string;
160
+ title: string;
161
+ tier: import("@bridge-ds/core").RiskTier;
162
+ bump: "minor";
163
+ label: string;
164
+ reasons: string[];
165
+ files: {
166
+ path: string;
167
+ action: "create" | "modify";
168
+ }[];
169
+ actionStep: number;
170
+ ramps: {
171
+ [k: string]: {
172
+ [k: string]: string;
173
+ };
174
+ };
175
+ contrast: {
176
+ checks: number;
177
+ passing: number;
178
+ themes: string[];
179
+ line: string;
180
+ failing: {
181
+ pair: string;
182
+ modes: string;
183
+ ratio: number | null;
184
+ min: number;
185
+ }[];
186
+ };
187
+ issues: import("@bridge-ds/core").BrandIssue[];
188
+ prBody: string;
189
+ status: string;
190
+ message: string;
191
+ } | {
192
+ next: string;
193
+ warnings?: string[] | undefined;
194
+ changesMode: string;
195
+ number: number;
196
+ url: string;
197
+ version: string;
198
+ labels: string[];
199
+ ok: boolean;
200
+ slug: string;
201
+ name: string;
202
+ from: string;
203
+ title: string;
204
+ tier: import("@bridge-ds/core").RiskTier;
205
+ bump: "minor";
206
+ label: string;
207
+ reasons: string[];
208
+ files: {
209
+ path: string;
210
+ action: "create" | "modify";
211
+ }[];
212
+ actionStep: number;
213
+ ramps: {
214
+ [k: string]: {
215
+ [k: string]: string;
216
+ };
217
+ };
218
+ contrast: {
219
+ checks: number;
220
+ passing: number;
221
+ themes: string[];
222
+ line: string;
223
+ failing: {
224
+ pair: string;
225
+ modes: string;
226
+ ratio: number | null;
227
+ min: number;
228
+ }[];
229
+ };
230
+ issues: import("@bridge-ds/core").BrandIssue[];
231
+ prBody: string;
232
+ status: string;
102
233
  } | {
103
234
  branch: string;
104
235
  fileContents: {
@@ -416,6 +416,10 @@ function holdersOf(right, owners, rights) {
416
416
  const groups = (rights ?? DEFAULT_RIGHTS)[right];
417
417
  return uniq(groups.flatMap((g) => owners[g] ?? []));
418
418
  }
419
+ function approverLists(owners, rights, teams) {
420
+ const entries = approverEntries(owners, rights);
421
+ return teams === void 0 ? entries : expandOwners(entries, teams);
422
+ }
419
423
  function approverEntries(owners, rights) {
420
424
  if (!rights) return { design: [...owners.design], tech: [...owners.tech] };
421
425
  return { design: holdersOf("approveDesign", owners, rights), tech: holdersOf("approveTech", owners, rights) };
@@ -558,6 +562,8 @@ function sameProducts(a, b) {
558
562
 
559
563
  // ../core/src/config.ts
560
564
  var CONFIG_FILE = "bridge.config.json";
565
+ var CHANGES_MODES = ["suggest", "direct"];
566
+ var DEFAULT_CHANGES_MODE = "suggest";
561
567
  var DEFAULT_OVERRIDE = { allowed: [], requireReason: true, minReasonLength: 20 };
562
568
  var DEFAULT_TOKEN_PATHS = {
563
569
  root: "tokens",
@@ -697,6 +703,8 @@ function defineConfig(input) {
697
703
  ...g.rights ? { rights: normalizeRights(g.rights) } : {}
698
704
  },
699
705
  products: input.products?.length ? input.products.map((p) => ({ ...p })) : DEFAULT_PRODUCTS.map((p) => ({ ...p })),
706
+ changes: input.changes === "direct" ? "direct" : DEFAULT_CHANGES_MODE,
707
+ ...input.storybook?.url ? { storybook: { url: input.storybook.url.trim().replace(/\/+$/, "") } } : {},
700
708
  ...input.audit ? { audit: { ...input.audit } } : {},
701
709
  ...input.visualImpact ? { visualImpact: { mode: input.visualImpact.mode === "on-demand" ? "on-demand" : "auto" } } : {},
702
710
  ...input.integrations ? { integrations: { ...input.integrations } } : {},
@@ -819,6 +827,13 @@ function loadConfig(source) {
819
827
  }
820
828
  }
821
829
  problems.push(...visualImpactProblems(d.visualImpact));
830
+ if (d.changes !== void 0 && !CHANGES_MODES.includes(d.changes)) problems.push(`"changes" must be "suggest" or "direct" (got ${JSON.stringify(d.changes)})`);
831
+ const sb = d.storybook;
832
+ if (sb !== void 0) {
833
+ if (!isObj(sb) || !isStr(sb.url)) problems.push('"storybook" must be { "url" } with the deployed Storybook address');
834
+ else if (!/^https:\/\/[^\s/]+/.test(sb.url.trim())) problems.push('"storybook.url" must start with https://, for example https://storybook.example.com');
835
+ else for (const k of Object.keys(sb)) if (k !== "url") problems.push(`"storybook.${k}" is not a known key`);
836
+ }
822
837
  problems.push(...productProblems(d.products));
823
838
  const audit = d.audit;
824
839
  if (audit !== void 0) {
@@ -851,6 +866,7 @@ function loadConfig(source) {
851
866
  var tokensPath = (config, rel = "") => [config.tokens.root === "." ? "" : config.tokens.root, rel].filter(Boolean).join("/");
852
867
  var protectedBranchesOf = (config) => [.../* @__PURE__ */ new Set([...config.governance.protectedBranches, ...config.repo ? [config.repo.defaultBranch] : []])];
853
868
  var baseBranchOf = (config) => config.repo?.defaultBranch ?? "main";
869
+ var changesMode = (config) => config?.changes === "direct" ? "direct" : DEFAULT_CHANGES_MODE;
854
870
  function toConfigJson(config, schema = "./packages/core/bridge.config.schema.json") {
855
871
  return {
856
872
  $schema: schema,
@@ -867,6 +883,8 @@ function toConfigJson(config, schema = "./packages/core/bridge.config.schema.jso
867
883
  ...config.audit ? { audit: config.audit } : {},
868
884
  ...config.previews ? { previews: config.previews } : {},
869
885
  ...config.visualImpact ? { visualImpact: config.visualImpact } : {},
886
+ changes: changesMode(config),
887
+ ...config.storybook ? { storybook: config.storybook } : {},
870
888
  ...config.products && !sameProducts(config.products, DEFAULT_PRODUCTS) ? { products: config.products } : {}
871
889
  };
872
890
  }
@@ -1943,11 +1961,17 @@ async function commitToNewLocalBranch(root, args) {
1943
1961
  throw new Error(`Refusing to write branch "${args.branch}": ${err.message}`);
1944
1962
  }
1945
1963
  if (await branchExists(root, args.branch)) throw new Error(`Branch "${args.branch}" already exists. Pick another title or delete it first.`);
1946
- const baseSha = (await git(root, ["rev-parse", "--verify", `${args.base}^{commit}`])).trim();
1964
+ const { sha, parent } = await commitTree(root, args);
1965
+ await git(root, ["update-ref", `refs/heads/${args.branch}`, sha, ""]);
1966
+ const diff = await git(root, ["diff", parent, sha]);
1967
+ return { sha, diff };
1968
+ }
1969
+ async function commitTree(root, args) {
1970
+ const parent = (await git(root, ["rev-parse", "--verify", `${args.base}^{commit}`])).trim();
1947
1971
  const dir = await mkdtemp(join(tmpdir(), "bridge-index-"));
1948
1972
  const env = { GIT_INDEX_FILE: join(dir, "index") };
1949
1973
  try {
1950
- await git(root, ["read-tree", baseSha], { env });
1974
+ await git(root, ["read-tree", parent], { env });
1951
1975
  for (const f of args.files) {
1952
1976
  if (f.content === null) {
1953
1977
  await git(root, ["update-index", "--force-remove", f.path], { env });
@@ -1958,10 +1982,8 @@ async function commitToNewLocalBranch(root, args) {
1958
1982
  }
1959
1983
  const tree = (await git(root, ["write-tree"], { env })).trim();
1960
1984
  const ident = await identityEnv(root);
1961
- const sha = (await git(root, ["commit-tree", tree, "-p", baseSha, "-F", "-"], { input: args.message, env: ident })).trim();
1962
- await git(root, ["update-ref", `refs/heads/${args.branch}`, sha, ""]);
1963
- const diff = await git(root, ["diff", baseSha, sha]);
1964
- return { sha, diff };
1985
+ const sha = (await git(root, ["commit-tree", tree, "-p", parent, "-F", "-"], { input: args.message, env: ident })).trim();
1986
+ return { sha, parent };
1965
1987
  } finally {
1966
1988
  await rm(dir, { recursive: true, force: true });
1967
1989
  }
@@ -1986,6 +2008,7 @@ export {
1986
2008
  unreadableTeams,
1987
2009
  TeamDirectory,
1988
2010
  DEFAULT_RIGHTS,
2011
+ approverLists,
1989
2012
  approverEntries,
1990
2013
  shipPolicy,
1991
2014
  unreadableShipTeams,
@@ -2004,6 +2027,7 @@ export {
2004
2027
  tokensPath,
2005
2028
  protectedBranchesOf,
2006
2029
  baseBranchOf,
2030
+ changesMode,
2007
2031
  toConfigJson,
2008
2032
  hexToRgba,
2009
2033
  rgbaToHex,
@@ -2035,6 +2059,7 @@ export {
2035
2059
  assertSafeBranch,
2036
2060
  DEFAULT_COMPONENT_SPECS_FILE,
2037
2061
  coverageSummary,
2062
+ variantKeyOf,
2038
2063
  parseComponentSpecs,
2039
2064
  figmaCell,
2040
2065
  FIGMA_REFERENCES_BRANCH,
@@ -2049,5 +2074,6 @@ export {
2049
2074
  showFile,
2050
2075
  listFilesAt,
2051
2076
  originRepo,
2052
- commitToNewLocalBranch
2077
+ commitToNewLocalBranch,
2078
+ commitTree
2053
2079
  };