@instruments/materialgraph 3.1.0 → 3.2.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 (55) hide show
  1. package/association-types.d.ts +20 -20
  2. package/brand-types.d.ts +6 -6
  3. package/by-spec-types.d.ts +6 -6
  4. package/catalog-discovery-types.d.ts +4 -4
  5. package/categories-client.d.ts +3 -3
  6. package/category-types.d.ts +18 -18
  7. package/client-config.d.ts +2 -2
  8. package/client-response-schema.d.ts +2 -2
  9. package/client-response-schema.js +4 -4
  10. package/client-vocabulary.js +1 -1
  11. package/client.js +8 -10
  12. package/color-profiles-types.d.ts +8 -8
  13. package/color-wire-types.d.ts +6 -6
  14. package/colors-client.d.ts +3 -3
  15. package/discovery-context-types.d.ts +8 -8
  16. package/errors.d.ts +12 -13
  17. package/errors.js +84 -74
  18. package/find-sampled-together-types.d.ts +6 -6
  19. package/find-variants-by-color-types.d.ts +30 -30
  20. package/find-variants-by-vector-types.d.ts +13 -13
  21. package/get-variant-types.d.ts +6 -6
  22. package/http-transport.d.ts +14 -10
  23. package/http-transport.js +14 -12
  24. package/image-reference-types.d.ts +2 -2
  25. package/json.d.ts +18 -0
  26. package/json.js +36 -0
  27. package/list-enum-values-types.d.ts +8 -8
  28. package/list-sampled-together-pairs-types.d.ts +6 -6
  29. package/list-variant-facets-types.d.ts +8 -8
  30. package/list-variants-types.d.ts +40 -31
  31. package/material-asset-types.d.ts +26 -26
  32. package/material-block-types.d.ts +6 -6
  33. package/material-types.d.ts +6 -6
  34. package/nearest-paints-types.d.ts +8 -8
  35. package/operation-responses.d.ts +2 -2
  36. package/operations.d.ts +1 -1
  37. package/operations.js +1 -1
  38. package/package.json +1 -1
  39. package/parse-operation-response.d.ts +4 -3
  40. package/parse-operation-response.js +112 -135
  41. package/resolve-color-types.d.ts +6 -6
  42. package/resolve-variant-types.d.ts +10 -10
  43. package/response-schema-catalog.d.ts +8 -0
  44. package/response-schema-catalog.js +82 -0
  45. package/response-schemas.d.ts +32 -3
  46. package/response-schemas.generated.js +26 -26
  47. package/response-schemas.js +5 -77
  48. package/schema-resource-types.d.ts +12 -12
  49. package/search-catalog-subset-types.d.ts +2 -2
  50. package/search-variants-types.d.ts +12 -12
  51. package/source-material-types.d.ts +6 -6
  52. package/source-material.js +2 -32
  53. package/types.d.ts +38 -38
  54. package/webmcp.d.ts +10 -4
  55. package/webmcp.generated.js +5 -4
@@ -22,24 +22,24 @@ import type { SearchCatalogSubset } from "./search-catalog-subset-types.js";
22
22
  * score or used to rank. Declared associations carry no ranking at all: that is
23
23
  * the point of them.
24
24
  */
25
- export type DeclaredProvenance = {
25
+ export interface DeclaredProvenance {
26
26
  /** The stored convention value (0.9 today). Never a per-edge measurement. */
27
27
  confidence: number;
28
28
  /** The brand enumerated this association in its own catalog data. */
29
29
  basis: "manufacturer_declared";
30
30
  /** The provenance recorded on the edge - the brand catalog feed. */
31
31
  source: "warehouse";
32
- };
32
+ }
33
33
  /** The material the question was asked about, resolved to its identity. */
34
- export type DeclaredAssociationSubject = {
34
+ export interface DeclaredAssociationSubject {
35
35
  variantId: VariantId;
36
36
  brand: string;
37
37
  product: string;
38
38
  /** The variant's own name; null when it is unnamed. */
39
39
  variantName: string | null;
40
- };
40
+ }
41
41
  /** One declared association, plus why it is believed. */
42
- export type DeclaredAssociation = {
42
+ export interface DeclaredAssociation {
43
43
  variantId: VariantId;
44
44
  brand: string;
45
45
  product: string;
@@ -65,7 +65,7 @@ export type DeclaredAssociation = {
65
65
  * pages. Absent when the product has no eligible variant.
66
66
  */
67
67
  colorwayCount?: number;
68
- };
68
+ }
69
69
  /**
70
70
  * One page of declared associations.
71
71
  *
@@ -74,7 +74,7 @@ export type DeclaredAssociation = {
74
74
  * is the whole set for this subject, direction and corpus scope. A page is not a
75
75
  * corpus — walk `nextCursor` before making any claim about the full set.
76
76
  */
77
- export type DeclaredAssociationsResponse = {
77
+ export interface DeclaredAssociationsResponse {
78
78
  subject: DeclaredAssociationSubject;
79
79
  /**
80
80
  * Constant discriminator. Its presence is how a caller tells a declared fact
@@ -88,9 +88,9 @@ export type DeclaredAssociationsResponse = {
88
88
  returnedCount: number;
89
89
  /** Present only when another page exists; pass back verbatim as `cursor`. */
90
90
  nextCursor?: Cursor;
91
- };
91
+ }
92
92
  /** Options for a declared-association read. */
93
- export type AssociatedOptions = {
93
+ export interface AssociatedOptions {
94
94
  /**
95
95
  * Page size, 1–48 inclusive (default 24). The server rejects (400), not
96
96
  * clamps, values outside this range.
@@ -111,7 +111,7 @@ export type AssociatedOptions = {
111
111
  * different one is a 400, never a silently different page.
112
112
  */
113
113
  cursor?: Cursor;
114
- };
114
+ }
115
115
  export type ApplicabilitySubject = {
116
116
  kind: "product";
117
117
  id: string;
@@ -120,15 +120,15 @@ export type ApplicabilitySubject = {
120
120
  id: VariantId;
121
121
  };
122
122
  export type ApplicabilityCoverageState = "available" | "partial" | "none_declared" | "not_ingested" | "source_not_applicable" | "unavailable";
123
- export type ApplicabilityCoverage = {
123
+ export interface ApplicabilityCoverage {
124
124
  state: ApplicabilityCoverageState;
125
125
  countKind: "exact" | "partial";
126
126
  declaredCount: number | null;
127
127
  sourceAuthority: string;
128
128
  sourceLocator: string;
129
129
  sourceRevision: string;
130
- };
131
- export type ApplicabilityFact = {
130
+ }
131
+ export interface ApplicabilityFact {
132
132
  id: string;
133
133
  subject: ApplicabilitySubject;
134
134
  finish: {
@@ -144,8 +144,8 @@ export type ApplicabilityFact = {
144
144
  revision: string;
145
145
  };
146
146
  lifecycle: "active";
147
- };
148
- export type ApplicabilitySourceEntry = {
147
+ }
148
+ export interface ApplicabilitySourceEntry {
149
149
  scope: {
150
150
  sourceAuthority: string;
151
151
  sourceLocator: string;
@@ -158,8 +158,8 @@ export type ApplicabilitySourceEntry = {
158
158
  facts: ApplicabilityFact[];
159
159
  /** Source endpoints that could not be resolved during reconciliation. */
160
160
  unresolved: UnresolvedApplicabilityEndpoint[];
161
- };
162
- export type UnresolvedApplicabilityEndpoint = {
161
+ }
162
+ export interface UnresolvedApplicabilityEndpoint {
163
163
  subjectLocator: string;
164
164
  subjectKind: "product" | "variant" | "unknown";
165
165
  finishLocator: string;
@@ -171,14 +171,14 @@ export type UnresolvedApplicabilityEndpoint = {
171
171
  locator: string;
172
172
  revision: string;
173
173
  };
174
- };
174
+ }
175
175
  /** Source-grained response; sources are never merged or given hidden precedence. */
176
- export type ApplicabilityResponse = {
176
+ export interface ApplicabilityResponse {
177
177
  kind: "manufacturer_declared_applicability";
178
178
  requestedSubject: ApplicabilitySubject;
179
179
  direction: "forward" | "reverse";
180
180
  sources: ApplicabilitySourceEntry[];
181
- };
181
+ }
182
182
  export type ApplicabilityOptions = {
183
183
  subjectKind: "product";
184
184
  subjectId: string;
package/brand-types.d.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * `list_brands` tool and the `mg brand list` command take.
5
5
  */
6
6
  import type { SearchCatalogSubset } from "./search-catalog-subset-types.js";
7
- export type BrandsOptions = {
7
+ export interface BrandsOptions {
8
8
  /**
9
9
  * A brand name, alias or misspelling, e.g. `"Kvadrat"`. Omit to browse the
10
10
  * list by name. Every brand the text matches comes back, so an ambiguous name
@@ -26,8 +26,8 @@ export type BrandsOptions = {
26
26
  limit?: number;
27
27
  /** The previous page's `pageInfo.endCursor`, with the same `query`, `categoryId` and `searchCatalogSubset`. */
28
28
  cursor?: string;
29
- };
30
- export type BrandItem = {
29
+ }
30
+ export interface BrandItem {
31
31
  /**
32
32
  * The brand's slug: the value `listVariants()`' `brand` filter and
33
33
  * `resolveVariant()`' `brandId` take. Never a display name.
@@ -36,8 +36,8 @@ export type BrandItem = {
36
36
  name: string;
37
37
  /** The brand's homepage, or null when none is on record. */
38
38
  website: string | null;
39
- };
40
- export type ListBrandsPage = {
39
+ }
40
+ export interface ListBrandsPage {
41
41
  /** THIS PAGE. Follow `pageInfo.endCursor` for the rest; a page is not a total. */
42
42
  items: BrandItem[];
43
43
  pageInfo: {
@@ -45,4 +45,4 @@ export type ListBrandsPage = {
45
45
  endCursor: string | null;
46
46
  hasNextPage: boolean;
47
47
  };
48
- };
48
+ }
@@ -22,7 +22,7 @@ export type BySpecVerdictState = "matched" | "deviated" | "failed" | "unverified
22
22
  * Hand-mirrors the `AttributeVerdict` contract from `@materialgraph/contracts`;
23
23
  * the OpenAPI `CatalogBySpecResponse` schema is the source of truth on the wire.
24
24
  */
25
- export type BySpecVerdictCell = {
25
+ export interface BySpecVerdictCell {
26
26
  attributeId: string;
27
27
  state: BySpecVerdictState;
28
28
  strength: "required" | "preferred";
@@ -57,7 +57,7 @@ export type BySpecVerdictCell = {
57
57
  * - `basis_unmet` — the value's source is weaker than the criterion demanded.
58
58
  */
59
59
  trustGap: "below_confidence" | "basis_unmet" | null;
60
- };
60
+ }
61
61
  /**
62
62
  * A match's full report card: every cell, the rolled-up grade, weakest confidence.
63
63
  *
@@ -70,11 +70,11 @@ export type BySpecVerdictCell = {
70
70
  * `minConfidence` is the WEAKEST cell's confidence — the honest ceiling on the
71
71
  * whole card, not an average. Quote it alongside the grade.
72
72
  */
73
- export type BySpecVerdict = {
73
+ export interface BySpecVerdict {
74
74
  cells: BySpecVerdictCell[];
75
75
  grade: "meets_all" | "close" | "hard_no";
76
76
  minConfidence: number | null;
77
- };
77
+ }
78
78
  /**
79
79
  * The verdict a materials-search hit carries (MG-625). It IS the shared
80
80
  * {@link BySpecVerdict} shape — the single CandidateVerdict mirror — aliased here
@@ -99,7 +99,7 @@ export type MaterialVerdict = BySpecVerdict;
99
99
  * EVERY miss is reported, not just the first, so one round trip is enough to fix
100
100
  * a whole spec.
101
101
  */
102
- export type BySpecUnresolvedCriterion = {
102
+ export interface BySpecUnresolvedCriterion {
103
103
  /** The parsed attribute id, after the route's surrounding-whitespace trim. */
104
104
  attributeId: string;
105
105
  /** The parsed value — never overwritten by the attribute id when that id is unknown. */
@@ -108,4 +108,4 @@ export type BySpecUnresolvedCriterion = {
108
108
  reason?: "unknown_attribute_or_term" | "not_a_specification";
109
109
  /** Ranked candidates for whichever half failed. See {@link ValueResolution}. */
110
110
  resolution: ValueResolution;
111
- };
111
+ }
@@ -11,7 +11,7 @@ import type { OpenEnum } from "./types.js";
11
11
  * first: `exact_id` > `exact_alias` > `lexical` > `semantic`. A `semantic` hit
12
12
  * is a guess worth confirming, not an equivalence.
13
13
  */
14
- export type ResolveValueCandidate = {
14
+ export interface ResolveValueCandidate {
15
15
  id: string;
16
16
  label: string;
17
17
  dictionaryId?: string;
@@ -19,7 +19,7 @@ export type ResolveValueCandidate = {
19
19
  tier: OpenEnum<"exact_id" | "exact_alias" | "lexical" | "semantic">;
20
20
  /** Present only for a color_family candidate resolved via the colorscope fallback. */
21
21
  via?: OpenEnum<"colorscope">;
22
- };
22
+ }
23
23
  /**
24
24
  * The resolver's verdict on ONE free-text token — the single shape every
25
25
  * resolving surface speaks, so a caller learns to read it once. Carried per bad
@@ -40,10 +40,10 @@ export type ResolveValueCandidate = {
40
40
  * `query` is the trimmed token that was actually resolved, which is how you tell
41
41
  * WHICH half of a failed `attribute:value` pair was the problem.
42
42
  */
43
- export type ValueResolution = {
43
+ export interface ValueResolution {
44
44
  status: OpenEnum<"resolved" | "ambiguous" | "unresolved">;
45
45
  query: string;
46
46
  best: ResolveValueCandidate | null;
47
47
  candidates: ResolveValueCandidate[];
48
48
  recommendedAction: OpenEnum<"use_best" | "choose_from_candidates" | "ask_user" | "none_found">;
49
- };
49
+ }
@@ -19,9 +19,9 @@ import type { CategoriesGetResult, CategoriesListInput, CategoriesListResult } f
19
19
  import type { QueryParams } from "./http-transport.js";
20
20
  import type { JsonOperationId, OperationResponses } from "./operation-responses.js";
21
21
  /** The client's own request primitive, handed down so this file owns no transport. */
22
- export type CategoriesTransport = {
23
- get<K extends JsonOperationId>(operationId: K, query?: QueryParams, signal?: AbortSignal, pathParams?: Readonly<Record<string, string>>): Promise<OperationResponses[K]>;
24
- };
22
+ export interface CategoriesTransport {
23
+ get: <K extends JsonOperationId>(operationId: K, query?: QueryParams, signal?: AbortSignal, pathParams?: Readonly<Record<string, string>>) => Promise<OperationResponses[K]>;
24
+ }
25
25
  export declare class CategoriesClient {
26
26
  #private;
27
27
  constructor(transport: CategoriesTransport);
@@ -12,22 +12,22 @@
12
12
  */
13
13
  import type { OpenEnum } from "./types.js";
14
14
  /** A category named by id, as in `ancestors` and `children`. */
15
- export type CategoryRef = {
15
+ export interface CategoryRef {
16
16
  id: string;
17
17
  name: string;
18
- };
18
+ }
19
19
  export type CategoryKind = OpenEnum<"category">;
20
20
  /** How a query matched source category names or exact paths through the lexical matcher. */
21
- export type CategoryMatch = {
21
+ export interface CategoryMatch {
22
22
  /** The name or source path that matched. */
23
23
  matchedText: string | null;
24
24
  method: OpenEnum<"exact" | "alias" | "fuzzy">;
25
- };
25
+ }
26
26
  /**
27
27
  * One item on a `categories.list` page: what picks the next call. `get(id)`
28
28
  * has the source path, depth, ancestors and children.
29
29
  */
30
- export type CategoryItem = {
30
+ export interface CategoryItem {
31
31
  /** Whether `categories.list({ parentId: this.id })` lists anything. */
32
32
  hasChildren: boolean;
33
33
  /** A source category identity, also used in product_category memberships. */
@@ -39,14 +39,14 @@ export type CategoryItem = {
39
39
  parentId: string | null;
40
40
  path: string;
41
41
  depth: number;
42
- };
43
- export type CategoriesPageInfo = {
42
+ }
43
+ export interface CategoriesPageInfo {
44
44
  /** Pass back as `cursor` with the same `query` and `parentId` for the next page. */
45
45
  nextCursor: string | null;
46
46
  returnedCount: number;
47
47
  totalMatches: number;
48
- };
49
- export type CategoriesListInput = {
48
+ }
49
+ export interface CategoriesListInput {
50
50
  /** `pageInfo.nextCursor` from the previous page, with the same `query` and `parentId`. */
51
51
  cursor?: string;
52
52
  /** Items per page, 1 to 50. Default 20. */
@@ -55,21 +55,21 @@ export type CategoriesListInput = {
55
55
  parentId?: string;
56
56
  /** A category name or description, e.g. `"wallpaper"` or `"beds"`. */
57
57
  query?: string;
58
- };
59
- export type CategoriesListResult = {
58
+ }
59
+ export interface CategoriesListResult {
60
60
  items: CategoryItem[];
61
61
  /** Present only when the query is refused as a category, and says why. */
62
62
  notice?: string;
63
63
  pageInfo: CategoriesPageInfo;
64
- };
64
+ }
65
65
  /** Independent semantic mapping metadata; it does not assert source category membership. */
66
- export type CategoryConcept = {
66
+ export interface CategoryConcept {
67
67
  label: string;
68
68
  match?: OpenEnum<"exact" | "close" | "broad" | "narrow">;
69
69
  termId: string;
70
70
  uri: string;
71
- };
72
- export type CategoryProductCategory = {
71
+ }
72
+ export interface CategoryProductCategory {
73
73
  concepts: CategoryConcept[];
74
74
  /** Legacy semantic mapping value, separate from source product_category enum[] values. */
75
75
  recordValue: string | null;
@@ -79,8 +79,8 @@ export type CategoryProductCategory = {
79
79
  * fits yet.
80
80
  */
81
81
  status: OpenEnum<"mapped" | "conditional" | "unmapped">;
82
- };
83
- export type CategoriesGetResult = {
82
+ }
83
+ export interface CategoriesGetResult {
84
84
  /** Phrases that name this category in a `query`. */
85
85
  aliases: string[];
86
86
  /** The categories above this one, root first. Empty for a top-level category. */
@@ -98,4 +98,4 @@ export type CategoriesGetResult = {
98
98
  path: string;
99
99
  /** Zero-based depth in the source hierarchy. */
100
100
  depth: number;
101
- };
101
+ }
@@ -5,7 +5,7 @@
5
5
  */
6
6
  /** The hosted API origin the client talks to unless `baseUrl` overrides it. */
7
7
  export declare const DEFAULT_BASE_URL = "https://beta.materialgraph.com";
8
- export type MaterialGraphClientOptions = {
8
+ export interface MaterialGraphClientOptions {
9
9
  /** A `mg_read_*` API key, presented as `Authorization: Bearer <key>`. */
10
10
  apiKey: string;
11
11
  /** Override the API origin. Defaults to {@link DEFAULT_BASE_URL}. */
@@ -19,4 +19,4 @@ export type MaterialGraphClientOptions = {
19
19
  * they end or the caller aborts. Absent means no deadline.
20
20
  */
21
21
  timeoutMs?: number;
22
- };
22
+ }
@@ -1,3 +1,3 @@
1
- import type { JsonSchema } from "./response-schemas.js";
1
+ import type { JsonObject } from "./json.js";
2
2
  /** Adapt a fresh producer schema to the SDK's existing open string enums. */
3
- export declare const openClientResponseEnums: (schema: JsonSchema) => void;
3
+ export declare const openClientResponseEnums: (schema: JsonObject) => void;
@@ -1,4 +1,4 @@
1
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1
+ import { isJsonObject } from "./json.js";
2
2
  // Only the fields declared as OpenEnum in the SDK are open here. Union
3
3
  // discriminants stay closed so their associated object shapes remain true.
4
4
  const openStrings = new Set([
@@ -47,19 +47,19 @@ const openStrings = new Set([
47
47
  /** Adapt a fresh producer schema to the SDK's existing open string enums. */
48
48
  export const openClientResponseEnums = (schema) => {
49
49
  const visit = (node, path) => {
50
- if (!isRecord(node)) {
50
+ if (!isJsonObject(node)) {
51
51
  return;
52
52
  }
53
53
  if (node.type === "string" && openStrings.has(path)) {
54
54
  delete node.enum;
55
55
  delete node.const;
56
56
  }
57
- if (isRecord(node.$defs)) {
57
+ if (isJsonObject(node.$defs)) {
58
58
  for (const [name, definition] of Object.entries(node.$defs)) {
59
59
  visit(definition, name);
60
60
  }
61
61
  }
62
- if (isRecord(node.properties)) {
62
+ if (isJsonObject(node.properties)) {
63
63
  for (const [name, property] of Object.entries(node.properties)) {
64
64
  visit(property, `${path}.${name}`);
65
65
  }
@@ -1,6 +1,6 @@
1
1
  import { resolveOperation } from "./operations.js";
2
2
  export const resolveColor = async (transport, name, signal, options) => await transport.requestJson(resolveOperation("resolve_color_name"), {
3
- query: { searchCatalogSubset: options?.searchCatalogSubset, name },
3
+ query: { name, searchCatalogSubset: options?.searchCatalogSubset },
4
4
  signal,
5
5
  });
6
6
  /**
package/client.js CHANGED
@@ -86,9 +86,7 @@ export class MaterialGraphClient {
86
86
  apiKey: options.apiKey,
87
87
  baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
88
88
  fetch: options.fetch ?? globalThis.fetch,
89
- ...(options.timeoutMs === undefined
90
- ? {}
91
- : { timeoutMs: options.timeoutMs }),
89
+ timeoutMs: options.timeoutMs,
92
90
  });
93
91
  this.#transport = transport;
94
92
  this.baseUrl = transport.baseUrl;
@@ -181,10 +179,10 @@ export class MaterialGraphClient {
181
179
  blocks: options?.blocks !== undefined && options.blocks.length > 0
182
180
  ? options.blocks.join(",")
183
181
  : undefined,
182
+ ifc: options?.ifc === true ? "true" : undefined,
184
183
  observations: options?.observations !== undefined && options.observations.length > 0
185
184
  ? options.observations.join(",")
186
185
  : undefined,
187
- ifc: options?.ifc === true ? "true" : undefined,
188
186
  }, signal, { variantId });
189
187
  }
190
188
  async materialBlocks(variantId, signal) {
@@ -264,7 +262,6 @@ export class MaterialGraphClient {
264
262
  colors: input.colors !== undefined && input.colors.length > 0
265
263
  ? JSON.stringify(input.colors)
266
264
  : undefined,
267
- searchCatalogSubset: input.searchCatalogSubset,
268
265
  cursor: input.cursor,
269
266
  filters: input.filters ? JSON.stringify(input.filters) : undefined,
270
267
  include: input.include !== undefined && input.include.length > 0
@@ -281,6 +278,7 @@ export class MaterialGraphClient {
281
278
  orderBy: input.orderBy !== undefined && input.orderBy.length > 0
282
279
  ? JSON.stringify(input.orderBy)
283
280
  : undefined,
281
+ searchCatalogSubset: input.searchCatalogSubset,
284
282
  words: input.words !== undefined && input.words.length > 0
285
283
  ? input.words.join(",")
286
284
  : undefined,
@@ -363,11 +361,11 @@ export class MaterialGraphClient {
363
361
  */
364
362
  async listSampledTogetherPairs(input = {}, signal) {
365
363
  return await this.#get("list_sampled_together_pairs", {
366
- ...(input.cursor === undefined ? {} : { cursor: input.cursor }),
367
- ...(input.limit === undefined ? {} : { limit: String(input.limit) }),
368
- ...(input.minProjects === undefined
369
- ? {}
370
- : { minProjects: String(input.minProjects) }),
364
+ cursor: input.cursor,
365
+ limit: input.limit === undefined ? undefined : String(input.limit),
366
+ minProjects: input.minProjects === undefined
367
+ ? undefined
368
+ : String(input.minProjects),
371
369
  }, signal);
372
370
  }
373
371
  /**
@@ -14,7 +14,7 @@ import type { OpenEnum } from "./types.js";
14
14
  */
15
15
  export type CategoryTier = OpenEnum<"group" | "type" | "merged">;
16
16
  /** One representative color bucket of a category. */
17
- export type CategoryColor = {
17
+ export interface CategoryColor {
18
18
  hex: string;
19
19
  oklab: {
20
20
  l: number;
@@ -24,8 +24,8 @@ export type CategoryColor = {
24
24
  variantCount: number;
25
25
  /** This bucket's share of the selection's colored variants, 0 to 1. */
26
26
  proportion: number;
27
- };
28
- export type CategoryColorProfile = {
27
+ }
28
+ export interface CategoryColorProfile {
29
29
  categoryKey: string;
30
30
  level: CategoryTier;
31
31
  name: string;
@@ -39,12 +39,12 @@ export type CategoryColorProfile = {
39
39
  avgLightness: number;
40
40
  avgChroma: number;
41
41
  colors: CategoryColor[];
42
- };
43
- export type CategoryColorProfilesResponse = {
42
+ }
43
+ export interface CategoryColorProfilesResponse {
44
44
  profiles: CategoryColorProfile[];
45
- };
45
+ }
46
46
  /** Request parameters for `colors.profiles()`. */
47
- export type ColorProfilesParams = {
47
+ export interface ColorProfilesParams {
48
48
  /** 1 to 8 category keys, at the tier named by `groupBy`. */
49
49
  productTypeIds: readonly string[];
50
50
  /**
@@ -57,4 +57,4 @@ export type ColorProfilesParams = {
57
57
  topN?: number;
58
58
  /** `"diverse"` maximizes visual distinctness instead of frequency. */
59
59
  select?: "frequency" | "diverse";
60
- };
60
+ }
@@ -5,28 +5,28 @@
5
5
  */
6
6
  import type { OpenEnum } from "./types.js";
7
7
  /** A color in OKLab: lightness 0 to 1, and the green-red and blue-yellow axes. */
8
- export type OKLab = {
8
+ export interface OKLab {
9
9
  L: number;
10
10
  a: number;
11
11
  b: number;
12
- };
12
+ }
13
13
  /** A region of color: chroma, hue (null for neutrals) and lightness bounds. */
14
- export type ColorRegion = {
14
+ export interface ColorRegion {
15
15
  chroma: [number, number];
16
16
  hue: [number, number] | null;
17
17
  lightness: [number, number];
18
- };
18
+ }
19
19
  /** One of ColorScope's fifteen color families. */
20
20
  export type ColorFamilyId = OpenEnum<"beige" | "black" | "blue" | "brown" | "cream" | "gray" | "green" | "orange" | "pink" | "purple" | "red" | "taupe" | "teal" | "white" | "yellow">;
21
21
  /** A named color a resolution lands on, and how close the input is to it. */
22
- export type ColorResolutionMatch = {
22
+ export interface ColorResolutionMatch {
23
23
  band: OpenEnum<"inside" | "near" | "far">;
24
24
  family: ColorFamilyId;
25
25
  hex: string;
26
26
  id: string;
27
27
  name: string;
28
28
  range: ColorRegion;
29
- };
29
+ }
30
30
  /** What ColorScope makes of a color name: resolved to a color, or why not. */
31
31
  export type ColorResolution = {
32
32
  kind: "resolved";
@@ -29,9 +29,9 @@ import type { JsonOperationId, OperationResponses } from "./operation-responses.
29
29
  * likeness, never a stated color specification.
30
30
  */
31
31
  /** The client's own request primitives, handed down so this file owns no transport. */
32
- export type ColorsTransport = {
33
- get<K extends JsonOperationId>(operationId: K, query?: QueryParams, signal?: AbortSignal): Promise<OperationResponses[K]>;
34
- };
32
+ export interface ColorsTransport {
33
+ get: <K extends JsonOperationId>(operationId: K, query?: QueryParams, signal?: AbortSignal) => Promise<OperationResponses[K]>;
34
+ }
35
35
  export declare class ColorsClient {
36
36
  #private;
37
37
  constructor(transport: ColorsTransport);
@@ -1,6 +1,6 @@
1
1
  import type { MaterialTile } from "./material-types.js";
2
2
  /** Static registry definitions and MG-owned discovery policy, without product counts. */
3
- export type DiscoveryReference = {
3
+ export interface DiscoveryReference {
4
4
  attributes: {
5
5
  id: string;
6
6
  name: string;
@@ -23,21 +23,21 @@ export type DiscoveryReference = {
23
23
  description: string;
24
24
  }[];
25
25
  admittedBrandIds: string[];
26
- };
27
- export type InterpretDiscoveryTermsInput = {
26
+ }
27
+ export interface InterpretDiscoveryTermsInput {
28
28
  text: string;
29
29
  categoryIds: readonly string[];
30
- };
31
- export type DiscoveryTerms = {
30
+ }
31
+ export interface DiscoveryTerms {
32
32
  categories: {
33
33
  categoryIds: string[];
34
34
  words: string[];
35
35
  } | null;
36
36
  colorWordHexes: string[];
37
- };
38
- export type ColorlessVariantsResult = {
37
+ }
38
+ export interface ColorlessVariantsResult {
39
39
  variantIds: string[];
40
- };
40
+ }
41
41
  /** A sibling uses the same tile contract as the catalog's material cards. */
42
42
  export type VariantSibling = MaterialTile & {
43
43
  distinction?: string;
package/errors.d.ts CHANGED
@@ -1,12 +1,11 @@
1
- /** Error and rate-limit contracts for the retry-free MaterialGraph SDK. */
2
1
  export type MaterialGraphErrorKind = "problem" | "simple" | "network" | "timeout" | "aborted" | "rate_limited" | "unexpected";
3
2
  export type SanitizedErrorValue = null | boolean | number | string | SanitizedErrorValue[] | SanitizedIssue;
4
3
  /** A bounded, recursively sanitized validation-issue record. */
5
- export type SanitizedIssue = {
4
+ export interface SanitizedIssue {
6
5
  [key: string]: SanitizedErrorValue;
7
- };
6
+ }
8
7
  /** Normalized RFC 7807 body. Unknown response fields are intentionally discarded. */
9
- export type ProblemDetail = {
8
+ export interface ProblemDetail {
10
9
  type: string;
11
10
  title: string;
12
11
  status: number;
@@ -23,27 +22,27 @@ export type ProblemDetail = {
23
22
  * not carry them. See {@link MATERIALGRAPH_PROBLEM_EXTENSIONS}.
24
23
  */
25
24
  readonly [extension: string]: unknown;
26
- };
25
+ }
27
26
  /** Normalized residual `{ error }` body. Unknown response fields are discarded. */
28
- export type SimpleErrorBody = {
27
+ export interface SimpleErrorBody {
29
28
  /** The vector and variant routes' machine-readable code, when the body is `{ code, message }`. */
30
29
  code?: string;
31
30
  error: string;
32
31
  issues?: SanitizedIssue[];
33
- };
32
+ }
34
33
  /** Parsed `X-RateLimit-*` / `Retry-After` headers. `null` means absent. */
35
- export type RateLimit = {
34
+ export interface RateLimit {
36
35
  limit: number | null;
37
36
  remaining: number | null;
38
37
  reset: number | null;
39
38
  retryAfter: number | null;
40
- };
41
- export type MaterialGraphRequestMetadata = {
39
+ }
40
+ export interface MaterialGraphRequestMetadata {
42
41
  method: string;
43
42
  origin: string;
44
43
  path: string;
45
- };
46
- export type MaterialGraphErrorInit = {
44
+ }
45
+ export interface MaterialGraphErrorInit {
47
46
  kind: MaterialGraphErrorKind;
48
47
  status?: number;
49
48
  retriable: boolean;
@@ -56,7 +55,7 @@ export type MaterialGraphErrorInit = {
56
55
  path?: string;
57
56
  /** Accepted for compatibility but deliberately never retained on the public error. */
58
57
  cause?: unknown;
59
- };
58
+ }
60
59
  type ResponseErrorInput = {
61
60
  status: number;
62
61
  body: unknown;