@instruments/materialgraph 0.25.0 → 0.27.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 (158) hide show
  1. package/association-types.d.ts +38 -27
  2. package/associations-client.d.ts +4 -4
  3. package/associations-client.js +3 -10
  4. package/attribution-types.d.ts +4 -4
  5. package/brand-types.d.ts +14 -6
  6. package/brands-client.d.ts +7 -38
  7. package/brands-client.js +10 -40
  8. package/by-colour-types.d.ts +58 -31
  9. package/by-spec-types.d.ts +6 -73
  10. package/by-spec-types.js +7 -5
  11. package/catalog-discovery-types.d.ts +11 -26
  12. package/catalogue-client.d.ts +16 -35
  13. package/catalogue-client.js +32 -67
  14. package/catalogue-types.d.ts +44 -4
  15. package/categories-client.d.ts +63 -0
  16. package/categories-client.js +48 -0
  17. package/category-types.d.ts +114 -0
  18. package/citation-types.d.ts +4 -4
  19. package/client-config.d.ts +4 -6
  20. package/client-config.js +2 -4
  21. package/client-source-material-comments.d.ts +4 -4
  22. package/client-source-material-comments.js +4 -38
  23. package/client-vocabulary.d.ts +7 -9
  24. package/client-vocabulary.js +22 -30
  25. package/client.d.ts +110 -244
  26. package/client.js +217 -387
  27. package/codes-client.d.ts +2 -2
  28. package/codes-client.js +8 -8
  29. package/codes-types.d.ts +55 -34
  30. package/colour-aggregate-types.d.ts +24 -24
  31. package/colours-client.d.ts +6 -11
  32. package/colours-client.js +11 -19
  33. package/coordinate-client.d.ts +2 -2
  34. package/coordinate-client.js +1 -13
  35. package/corpus-scope-types.d.ts +3 -3
  36. package/corpus-scope-types.js +1 -25
  37. package/demand-batch-types.d.ts +18 -18
  38. package/demand-types.d.ts +24 -24
  39. package/errors.d.ts +13 -13
  40. package/errors.js +54 -52
  41. package/http-transport.d.ts +13 -21
  42. package/http-transport.js +31 -28
  43. package/identify-types.d.ts +54 -44
  44. package/identify-types.js +5 -3
  45. package/index.d.ts +11 -27
  46. package/index.js +4 -6
  47. package/list-variant-facets-types.d.ts +60 -0
  48. package/list-variants-types.d.ts +142 -0
  49. package/list-variants-types.js +12 -0
  50. package/match-stream-types.d.ts +45 -32
  51. package/match-stream-types.js +2 -0
  52. package/match-stream.d.ts +2 -2
  53. package/match-stream.js +67 -49
  54. package/match-types.d.ts +32 -8
  55. package/material-asset-types.d.ts +89 -69
  56. package/material-block-types.d.ts +8 -6
  57. package/material-composition-client.d.ts +21 -0
  58. package/material-composition-client.js +13 -0
  59. package/material-composition-types.d.ts +403 -0
  60. package/material-query-plan-types.d.ts +61 -145
  61. package/material-resources-client.d.ts +12 -10
  62. package/material-resources-client.js +27 -22
  63. package/material-types.d.ts +16 -24
  64. package/ndjson.js +16 -8
  65. package/operations.d.ts +6 -6
  66. package/operations.js +29 -156
  67. package/package.json +5 -1
  68. package/palette-search-types.d.ts +87 -52
  69. package/query-understanding-types.d.ts +65 -40
  70. package/resolve-client.d.ts +8 -12
  71. package/resolve-client.js +9 -13
  72. package/resolve-colour-types.d.ts +8 -8
  73. package/resolve-types.d.ts +10 -10
  74. package/response-schemas.d.ts +20 -0
  75. package/response-schemas.generated.d.ts +5 -0
  76. package/response-schemas.generated.js +160 -0
  77. package/response-schemas.js +113 -0
  78. package/run-types.d.ts +64 -145
  79. package/runs.d.ts +9 -58
  80. package/runs.js +60 -149
  81. package/samplize-catalogue-types.d.ts +18 -18
  82. package/samplize-colorvec.d.ts +20 -20
  83. package/samplize-colorvec.js +66 -42
  84. package/schema-resource-types.d.ts +52 -39
  85. package/schema-resource-types.js +5 -5
  86. package/search-card-types.d.ts +26 -4
  87. package/search-index-plan-types.d.ts +70 -0
  88. package/search-refinement-types.d.ts +10 -40
  89. package/search-refinement-types.js +1 -0
  90. package/search-request-types.d.ts +121 -204
  91. package/search-response-receipt-types.d.ts +13 -253
  92. package/search-response-types.d.ts +2 -2
  93. package/search-result-validation.d.ts +3 -19
  94. package/search-result-validation.js +42 -183
  95. package/source-material-validation.d.ts +3 -3
  96. package/source-material-validation.js +35 -39
  97. package/spec-facet-types.d.ts +11 -16
  98. package/spec-types.d.ts +23 -16
  99. package/spec-types.js +8 -7
  100. package/specifications.d.ts +14 -72
  101. package/specifications.js +39 -89
  102. package/sse.d.ts +2 -2
  103. package/sse.js +32 -16
  104. package/substitute-types.d.ts +22 -22
  105. package/suggest-types.d.ts +11 -17
  106. package/suggest-types.js +3 -3
  107. package/taxonomy-coverage-types.d.ts +8 -8
  108. package/types.d.ts +202 -405
  109. package/validation.d.ts +26 -26
  110. package/validation.js +97 -92
  111. package/webmcp.d.ts +3 -3
  112. package/webmcp.generated.js +10 -93
  113. package/brand-most-sampled-types.d.ts +0 -33
  114. package/browse-types.d.ts +0 -236
  115. package/client-browse.d.ts +0 -78
  116. package/client-browse.js +0 -72
  117. package/client-exploration.d.ts +0 -9
  118. package/client-exploration.js +0 -7
  119. package/compare-types.d.ts +0 -89
  120. package/composition-client.d.ts +0 -33
  121. package/composition-client.js +0 -27
  122. package/composition-types.d.ts +0 -455
  123. package/composition-types.js +0 -10
  124. package/correction-types.d.ts +0 -88
  125. package/exploration-types.d.ts +0 -118
  126. package/exploration-types.js +0 -1
  127. package/fan-deck-types.d.ts +0 -42
  128. package/fan-deck-types.js +0 -9
  129. package/match-rejection-types.d.ts +0 -43
  130. package/match-rejection-types.js +0 -7
  131. package/palette-completion-types.d.ts +0 -115
  132. package/palette-completion-types.js +0 -1
  133. package/project-types.d.ts +0 -79
  134. package/project-types.js +0 -9
  135. package/projects.d.ts +0 -13
  136. package/projects.js +0 -46
  137. package/render-assets-types.d.ts +0 -65
  138. package/render-assets-types.js +0 -1
  139. package/run-events.d.ts +0 -106
  140. package/run-events.js +0 -32
  141. package/schedule-reference-types.d.ts +0 -46
  142. package/schedule-reference-types.js +0 -1
  143. package/schedule-references-client.d.ts +0 -14
  144. package/schedule-references-client.js +0 -26
  145. package/schedule-types.d.ts +0 -261
  146. package/schedule-types.js +0 -1
  147. package/search-collapse-types.d.ts +0 -69
  148. package/search-collapse-types.js +0 -1
  149. package/search-mood-types.d.ts +0 -6
  150. package/search-mood-types.js +0 -1
  151. package/search-window-types.d.ts +0 -25
  152. package/search-window-types.js +0 -1
  153. package/slot-pool-types.d.ts +0 -372
  154. package/slot-pool-types.js +0 -1
  155. /package/{brand-most-sampled-types.js → category-types.js} +0 -0
  156. /package/{browse-types.js → list-variant-facets-types.js} +0 -0
  157. /package/{compare-types.js → material-composition-types.js} +0 -0
  158. /package/{correction-types.js → search-index-plan-types.js} +0 -0
@@ -10,6 +10,7 @@
10
10
  * with {@link PairingItem}, so the two can never be concatenated into one list.
11
11
  * Present them as separate sections, and never describe a pairing as available.
12
12
  */
13
+ import type { CorpusScope } from "./corpus-scope-types.js";
13
14
  import type { Cursor, VariantId } from "./identifiers.js";
14
15
  import type { ProductTypeReceipt } from "./material-types.js";
15
16
  /**
@@ -21,24 +22,24 @@ import type { ProductTypeReceipt } from "./material-types.js";
21
22
  * score or used to rank. Declared associations carry no ranking at all: that is
22
23
  * the point of them.
23
24
  */
24
- export interface DeclaredProvenance {
25
+ export type DeclaredProvenance = {
25
26
  /** The stored convention value (0.9 today). Never a per-edge measurement. */
26
27
  confidence: number;
27
28
  /** The manufacturer enumerated this association in their own catalog data. */
28
29
  basis: "manufacturer_declared";
29
30
  /** The provenance recorded on the edge — the manufacturer catalog feed. */
30
31
  source: "warehouse";
31
- }
32
+ };
32
33
  /** The material the question was asked about, resolved to its identity. */
33
- export interface DeclaredAssociationSubject {
34
+ export type DeclaredAssociationSubject = {
34
35
  variantId: VariantId;
35
36
  brand: string;
36
37
  product: string;
37
38
  /** The variant's own name; null when it is unnamed. */
38
39
  variantName: string | null;
39
- }
40
+ };
40
41
  /** One declared association, plus why it is believed. */
41
- export interface DeclaredAssociation {
42
+ export type DeclaredAssociation = {
42
43
  variantId: VariantId;
43
44
  brand: string;
44
45
  product: string;
@@ -54,16 +55,25 @@ export interface DeclaredAssociation {
54
55
  /** Review receipt; proposed types are never accepted categories. */
55
56
  productTypeReceipt: ProductTypeReceipt;
56
57
  declared: DeclaredProvenance;
57
- }
58
+ /** The accepted display category, for a card's kind pill. Null when none is accepted. */
59
+ kindLabel: string | null;
60
+ /** The accepted `price_tier` term (`$` to `$$$$$`). Absent means unknown, never cheap. */
61
+ priceTier?: string;
62
+ /**
63
+ * The eligible variants of this association's product, the set `listVariants`
64
+ * pages. Absent when the product has no eligible variant.
65
+ */
66
+ colourwayCount?: number;
67
+ };
58
68
  /**
59
69
  * One page of declared associations.
60
70
  *
61
71
  * READ `totalAssociations`, NOT `associations.length`, when rendering a count
62
72
  * like "Compatible Finishes (128)": the array is one page (up to 48), the total
63
- * is the whole set for this subject, direction and corpus. A page is not a
73
+ * is the whole set for this subject, direction and corpus scope. A page is not a
64
74
  * corpus — walk `nextCursor` before making any claim about the full set.
65
75
  */
66
- export interface DeclaredAssociationsResponse {
76
+ export type DeclaredAssociationsResponse = {
67
77
  subject: DeclaredAssociationSubject;
68
78
  /**
69
79
  * Constant discriminator. Its presence is how a caller tells a declared fact
@@ -71,35 +81,36 @@ export interface DeclaredAssociationsResponse {
71
81
  */
72
82
  kind: "declared_association";
73
83
  associations: DeclaredAssociation[];
74
- /** The TRUE count for this subject, direction and corpus. Not the page size. */
84
+ /** The TRUE count for this subject, direction and corpus scope. Not the page size. */
75
85
  totalAssociations: number;
76
86
  /** How many associations this page carries. */
77
87
  returnedCount: number;
78
88
  /** Present only when another page exists; pass back verbatim as `cursor`. */
79
89
  nextCursor?: Cursor;
80
- }
90
+ };
81
91
  /** Options for a declared-association read. */
82
- export interface AssociatedOptions {
92
+ export type AssociatedOptions = {
83
93
  /**
84
94
  * Page size, 1–48 inclusive (default 24). The server rejects (400), not
85
95
  * clamps, values outside this range.
86
96
  */
87
97
  limit?: number;
88
98
  /**
89
- * Source identity scope. `material_bank` returns associations pointing at a
90
- * variant carrying a Material Bank SKU. A SKU alone does not establish current
91
- * sampleability; use `sampleableOnly` for an accepted availability fact.
99
+ * Narrows the associations, `totalAssociations` and the cursor to one corpus
100
+ * scope. `materialBankOrderable` keeps associations pointing at a variant
101
+ * carrying a Material Bank id; absent or `all` is the whole declared set.
102
+ * Membership does not establish sampleability; use `sampleableOnly` for that.
92
103
  */
93
- corpus?: "all" | "material_bank";
104
+ corpusScope?: CorpusScope;
94
105
  /** Return only associations whose effective sampleability is true. */
95
106
  sampleableOnly?: boolean;
96
107
  /**
97
108
  * The previous response's `nextCursor`, passed back verbatim. A cursor is
98
- * bound to its subject, direction and corpus — replaying it against a
109
+ * bound to its subject, direction and corpus scope - replaying it against a
99
110
  * different one is a 400, never a silently different page.
100
111
  */
101
112
  cursor?: Cursor;
102
- }
113
+ };
103
114
  export type ApplicabilitySubject = {
104
115
  kind: "product";
105
116
  id: string;
@@ -108,15 +119,15 @@ export type ApplicabilitySubject = {
108
119
  id: VariantId;
109
120
  };
110
121
  export type ApplicabilityCoverageState = "available" | "partial" | "none_declared" | "not_ingested" | "source_not_applicable" | "unavailable";
111
- export interface ApplicabilityCoverage {
122
+ export type ApplicabilityCoverage = {
112
123
  state: ApplicabilityCoverageState;
113
124
  countKind: "exact" | "partial";
114
125
  declaredCount: number | null;
115
126
  sourceAuthority: string;
116
127
  sourceLocator: string;
117
128
  sourceRevision: string;
118
- }
119
- export interface ApplicabilityFact {
129
+ };
130
+ export type ApplicabilityFact = {
120
131
  id: string;
121
132
  subject: ApplicabilitySubject;
122
133
  finish: {
@@ -132,8 +143,8 @@ export interface ApplicabilityFact {
132
143
  revision: string;
133
144
  };
134
145
  lifecycle: "active";
135
- }
136
- export interface ApplicabilitySourceEntry {
146
+ };
147
+ export type ApplicabilitySourceEntry = {
137
148
  scope: {
138
149
  sourceAuthority: string;
139
150
  sourceLocator: string;
@@ -146,8 +157,8 @@ export interface ApplicabilitySourceEntry {
146
157
  facts: ApplicabilityFact[];
147
158
  /** Source endpoints that could not be resolved during reconciliation. */
148
159
  unresolved: UnresolvedApplicabilityEndpoint[];
149
- }
150
- export interface UnresolvedApplicabilityEndpoint {
160
+ };
161
+ export type UnresolvedApplicabilityEndpoint = {
151
162
  subjectLocator: string;
152
163
  subjectKind: "product" | "variant" | "unknown";
153
164
  finishLocator: string;
@@ -159,14 +170,14 @@ export interface UnresolvedApplicabilityEndpoint {
159
170
  locator: string;
160
171
  revision: string;
161
172
  };
162
- }
173
+ };
163
174
  /** Source-grained response; sources are never merged or given hidden precedence. */
164
- export interface ApplicabilityResponse {
175
+ export type ApplicabilityResponse = {
165
176
  kind: "manufacturer_declared_applicability";
166
177
  requestedSubject: ApplicabilitySubject;
167
178
  direction: "forward" | "reverse";
168
179
  sources: ApplicabilitySourceEntry[];
169
- }
180
+ };
170
181
  export type ApplicabilityOptions = {
171
182
  subjectKind: "product";
172
183
  subjectId: string;
@@ -13,7 +13,7 @@
13
13
  * "available on".
14
14
  */
15
15
  import type { ApplicabilityOptions, ApplicabilityResponse, AssociatedOptions, DeclaredAssociationsResponse } from "./association-types.js";
16
- import { HttpTransport } from "./http-transport.js";
16
+ import type { HttpTransport } from "./http-transport.js";
17
17
  import type { VariantId } from "./identifiers.js";
18
18
  /**
19
19
  * THE QUESTION: "what finishes can I get on THIS chair?" — the fabrics,
@@ -33,7 +33,7 @@ import type { VariantId } from "./identifiers.js";
33
33
  *
34
34
  * @param variantId The PRODUCT variant. Opaque — pass back exactly what you were given.
35
35
  */
36
- export declare function declaredFinishes(transport: HttpTransport, variantId: VariantId, options?: AssociatedOptions, signal?: AbortSignal): Promise<DeclaredAssociationsResponse>;
36
+ export declare const declaredFinishes: (transport: HttpTransport, variantId: VariantId, options?: AssociatedOptions, signal?: AbortSignal) => Promise<DeclaredAssociationsResponse>;
37
37
  /**
38
38
  * THE QUESTION: "what furniture takes THIS fabric?" — the products the
39
39
  * MANUFACTURER declares a finish variant is available on (GET
@@ -48,6 +48,6 @@ export declare function declaredFinishes(transport: HttpTransport, variantId: Va
48
48
  *
49
49
  * @param variantId The FINISH variant. Opaque — pass back exactly what you were given.
50
50
  */
51
- export declare function declaredProducts(transport: HttpTransport, variantId: VariantId, options?: AssociatedOptions, signal?: AbortSignal): Promise<DeclaredAssociationsResponse>;
51
+ export declare const declaredProducts: (transport: HttpTransport, variantId: VariantId, options?: AssociatedOptions, signal?: AbortSignal) => Promise<DeclaredAssociationsResponse>;
52
52
  /** Read manufacturer-declared applicability without collapsing Product/Variant grain. */
53
- export declare function applicability(transport: HttpTransport, options: ApplicabilityOptions, signal?: AbortSignal): Promise<ApplicabilityResponse>;
53
+ export declare const applicability: (transport: HttpTransport, options: ApplicabilityOptions, signal?: AbortSignal) => Promise<ApplicabilityResponse>;
@@ -1,4 +1,3 @@
1
- import { HttpTransport } from "./http-transport.js";
2
1
  import { resolveOperation } from "./operations.js";
3
2
  /**
4
3
  * THE QUESTION: "what finishes can I get on THIS chair?" — the fabrics,
@@ -18,9 +17,7 @@ import { resolveOperation } from "./operations.js";
18
17
  *
19
18
  * @param variantId The PRODUCT variant. Opaque — pass back exactly what you were given.
20
19
  */
21
- export function declaredFinishes(transport, variantId, options, signal) {
22
- return transport.requestJson(resolveOperation("list_associated_finishes"), { query: { variantId, ...options }, signal });
23
- }
20
+ export const declaredFinishes = async (transport, variantId, options, signal) => await transport.requestJson(resolveOperation("list_associated_finishes"), { query: { variantId, ...options }, signal });
24
21
  /**
25
22
  * THE QUESTION: "what furniture takes THIS fabric?" — the products the
26
23
  * MANUFACTURER declares a finish variant is available on (GET
@@ -35,10 +32,6 @@ export function declaredFinishes(transport, variantId, options, signal) {
35
32
  *
36
33
  * @param variantId The FINISH variant. Opaque — pass back exactly what you were given.
37
34
  */
38
- export function declaredProducts(transport, variantId, options, signal) {
39
- return transport.requestJson(resolveOperation("list_associated_products"), { query: { variantId, ...options }, signal });
40
- }
35
+ export const declaredProducts = async (transport, variantId, options, signal) => await transport.requestJson(resolveOperation("list_associated_products"), { query: { variantId, ...options }, signal });
41
36
  /** Read manufacturer-declared applicability without collapsing Product/Variant grain. */
42
- export function applicability(transport, options, signal) {
43
- return transport.requestJson(resolveOperation("get_applicability"), { query: options, signal });
44
- }
37
+ export const applicability = async (transport, options, signal) => await transport.requestJson(resolveOperation("get_applicability"), { query: options, signal });
@@ -13,12 +13,12 @@
13
13
  /**
14
14
  * The ranking basis, in one vocabulary across both ranked routes.
15
15
  *
16
- * The first five values are `search()`'s `mode` verbatim, and there
16
+ * The first seven values are `search()`'s `mode` verbatim, and there
17
17
  * `attribution.basis === mode` always. `"match"` is what `match()` reports;
18
18
  * that route has no `mode`, so this is the only field its outcomes can be
19
19
  * grouped by.
20
20
  */
21
- export type AttributionBasis = "image" | "colour" | "text" | "lexical" | "entity-browse" | "match";
21
+ export type AttributionBasis = "image" | "colour" | "text" | "lexical" | "entity-browse" | "agent" | "attribute" | "match";
22
22
  /**
23
23
  * Envelope-level attribution receipt, on every successful ranked response.
24
24
  *
@@ -37,7 +37,7 @@ export type AttributionBasis = "image" | "colour" | "text" | "lexical" | "entity
37
37
  * Both fields are optional in the SDK types for one reason only: a server
38
38
  * predating MG-1131 does not send them. Every current response does.
39
39
  */
40
- export interface ResponseAttribution {
40
+ export type ResponseAttribution = {
41
41
  /**
42
42
  * This response's stable id — the same value as the `X-Request-Id` header.
43
43
  * Opaque: store it verbatim, never parse it. Group your stored outcomes by
@@ -48,4 +48,4 @@ export interface ResponseAttribution {
48
48
  basis: AttributionBasis;
49
49
  /** ISO-8601 timestamp of when the response was assembled. */
50
50
  issuedAt: string;
51
- }
51
+ };
package/brand-types.d.ts CHANGED
@@ -5,15 +5,21 @@
5
5
  * The SDK's one OFFSET-paginated surface — everything else that pages uses an
6
6
  * opaque cursor. `meta` is where the page/corpus distinction is settled here.
7
7
  */
8
- export interface BrandsOptions {
8
+ import type { CorpusScope, CorpusScopeReceipt } from "./corpus-scope-types.js";
9
+ export type BrandsOptions = {
10
+ /**
11
+ * Which corpus to list from. Narrows the brands AND the corpus their counts
12
+ * are drawn from, inside the query. Absent or `"all"` is the whole graph.
13
+ */
14
+ corpusScope?: CorpusScope;
9
15
  /** Fuzzy name filter. Omit for the whole collection. */
10
16
  q?: string;
11
17
  /** Page size. Never a bound on the collection. */
12
18
  limit?: number;
13
19
  /** Row offset for the next page. Paired with `meta.hasMore`. */
14
20
  offset?: number;
15
- }
16
- export interface BrandCatalogListItem {
21
+ };
22
+ export type BrandCatalogListItem = {
17
23
  id: string;
18
24
  slug: string;
19
25
  name: string;
@@ -23,8 +29,10 @@ export interface BrandCatalogListItem {
23
29
  productCount: number;
24
30
  /** Variants ingested into MaterialGraph. A coverage figure, not a claim about the brand. */
25
31
  variantCount: number;
26
- }
27
- export interface BrandCatalogListPage {
32
+ };
33
+ export type BrandCatalogListPage = {
34
+ /** Present only when a narrowing scope applied; absence means the whole graph. */
35
+ corpusScope?: CorpusScopeReceipt;
28
36
  /** THIS PAGE. Its length is `meta.count`, never `meta.total`. */
29
37
  items: BrandCatalogListItem[];
30
38
  /**
@@ -41,4 +49,4 @@ export interface BrandCatalogListPage {
41
49
  offset: number;
42
50
  hasMore: boolean;
43
51
  };
44
- }
52
+ };
@@ -1,48 +1,17 @@
1
1
  /**
2
- * The BRAND lens: the catalogue collection, one brand's profile, and one
3
- * brand's whole colour range, as thin wrappers over the shared
4
- * {@link HttpTransport}. `MaterialGraphClient.brands` / `.brand` /
5
- * `.brandColourDeck` delegate here; the contract lives in this file.
2
+ * The BRAND lens: the catalogue collection, as a thin wrapper over the shared
3
+ * {@link HttpTransport}. `MaterialGraphClient.brands` delegates here; the
4
+ * contract lives in this file.
6
5
  *
7
- * A brand is a COMPANY, not a catalogue. Every count these reads return is
6
+ * A brand is a COMPANY, not a catalogue. Every count this read returns is
8
7
  * coverage — what MaterialGraph has ingested — and never a claim about how
9
8
  * many products the maker sells.
10
9
  */
11
10
  import type { BrandCatalogListPage, BrandsOptions } from "./brand-types.js";
12
- import type { BrandFanDeck } from "./fan-deck-types.js";
13
- import { HttpTransport } from "./http-transport.js";
14
- import type { BrandOptions, BrandProfileResponse } from "./types.js";
11
+ import type { HttpTransport } from "./http-transport.js";
15
12
  /**
16
13
  * THE QUESTION: "whose catalogs are in here, and how big is each?" The SDK's
17
14
  * one OFFSET-paginated surface: read `meta.total` for the collection size and
18
- * `meta.hasMore` to keep walking. Instead use {@link brandProfile} for one
19
- * brand's profile and trade signals.
15
+ * `meta.hasMore` to keep walking.
20
16
  */
21
- export declare function listBrands(transport: HttpTransport, options?: BrandsOptions, signal?: AbortSignal): Promise<BrandCatalogListPage>;
22
- /**
23
- * THE QUESTION: "who is this brand, and what do they claim?" — profile plus the
24
- * trade/spec signals ON RECORD. `trade` is keyed by attribute id and an ABSENT
25
- * key means no value is held — never infer `false`. Instead use `search()` to
26
- * find their materials; this describes the company, not the catalog.
27
- */
28
- export declare function brandProfile(transport: HttpTransport, brandSlug: string, options?: BrandOptions, signal?: AbortSignal): Promise<BrandProfileResponse>;
29
- /**
30
- * THE QUESTION: "show me this maker's whole range, the way a fan deck reads."
31
- * Colours grouped by family — creams together, then greys, then browns — and
32
- * ordered light to dark within each. No stored scalar produces that order: a
33
- * lightness sort interleaves the whites and the creams, and a reader loses the
34
- * sense that they are looking at two different families.
35
- *
36
- * Deliberately unpaginated, so there is no cursor to walk and no all-brands
37
- * form: family order is only correct over a COMPLETE range, because the greys
38
- * cannot be placed against the browns while holding one page of each. A range
39
- * past the server ceiling reports `truncatedAt` rather than being quietly cut,
40
- * and an absent `truncatedAt` means the deck is whole.
41
- *
42
- * Every swatch carries the maker's PUBLISHED hex — this read never returns a
43
- * colour derived from imagery. For "what is near this colour, across makers"
44
- * use `byColour()` instead.
45
- *
46
- * @param brandSlug The brand's slug, as `listBrands()` reports it.
47
- */
48
- export declare function brandColourDeck(transport: HttpTransport, brandSlug: string, signal?: AbortSignal): Promise<BrandFanDeck>;
17
+ export declare const listBrands: (transport: HttpTransport, options?: BrandsOptions, signal?: AbortSignal) => Promise<BrandCatalogListPage>;
package/brands-client.js CHANGED
@@ -1,45 +1,15 @@
1
- import { HttpTransport } from "./http-transport.js";
2
1
  import { resolveOperation } from "./operations.js";
3
2
  /**
4
3
  * THE QUESTION: "whose catalogs are in here, and how big is each?" The SDK's
5
4
  * one OFFSET-paginated surface: read `meta.total` for the collection size and
6
- * `meta.hasMore` to keep walking. Instead use {@link brandProfile} for one
7
- * brand's profile and trade signals.
5
+ * `meta.hasMore` to keep walking.
8
6
  */
9
- export function listBrands(transport, options = {}, signal) {
10
- return transport.requestJson(resolveOperation("list_brands"), {
11
- query: { q: options.q, limit: options.limit, offset: options.offset },
12
- signal,
13
- });
14
- }
15
- /**
16
- * THE QUESTION: "who is this brand, and what do they claim?" — profile plus the
17
- * trade/spec signals ON RECORD. `trade` is keyed by attribute id and an ABSENT
18
- * key means no value is held — never infer `false`. Instead use `search()` to
19
- * find their materials; this describes the company, not the catalog.
20
- */
21
- export function brandProfile(transport, brandSlug, options, signal) {
22
- return transport.requestJson(resolveOperation("get_brand_profile"), { query: { q: options?.q }, pathParams: { brandSlug }, signal });
23
- }
24
- /**
25
- * THE QUESTION: "show me this maker's whole range, the way a fan deck reads."
26
- * Colours grouped by family — creams together, then greys, then browns — and
27
- * ordered light to dark within each. No stored scalar produces that order: a
28
- * lightness sort interleaves the whites and the creams, and a reader loses the
29
- * sense that they are looking at two different families.
30
- *
31
- * Deliberately unpaginated, so there is no cursor to walk and no all-brands
32
- * form: family order is only correct over a COMPLETE range, because the greys
33
- * cannot be placed against the browns while holding one page of each. A range
34
- * past the server ceiling reports `truncatedAt` rather than being quietly cut,
35
- * and an absent `truncatedAt` means the deck is whole.
36
- *
37
- * Every swatch carries the maker's PUBLISHED hex — this read never returns a
38
- * colour derived from imagery. For "what is near this colour, across makers"
39
- * use `byColour()` instead.
40
- *
41
- * @param brandSlug The brand's slug, as `listBrands()` reports it.
42
- */
43
- export function brandColourDeck(transport, brandSlug, signal) {
44
- return transport.requestJson(resolveOperation("brand_colour_deck"), { pathParams: { brandSlug }, signal });
45
- }
7
+ export const listBrands = async (transport, options = {}, signal) => await transport.requestJson(resolveOperation("list_brands"), {
8
+ query: {
9
+ corpusScope: options.corpusScope,
10
+ limit: options.limit,
11
+ offset: options.offset,
12
+ q: options.q,
13
+ },
14
+ signal,
15
+ });
@@ -11,10 +11,10 @@ import type { VariantId } from "./identifiers.js";
11
11
  import type { QueryUnderstanding } from "./query-understanding-types.js";
12
12
  import type { OklabTriple, OpenEnum, PaletteSwatch } from "./types.js";
13
13
  /** Coarse group + fine type of a colour match's primary product type. */
14
- export interface MatchCategory {
14
+ export type MatchCategory = {
15
15
  group: string | null;
16
16
  type: string | null;
17
- }
17
+ };
18
18
  /**
19
19
  * One colour-palette match.
20
20
  *
@@ -23,7 +23,7 @@ export interface MatchCategory {
23
23
  * colour"), never as a stated colour specification. `hex` itself may be the
24
24
  * manufacturer's published colour — read `sourceBasis` before repeating it.
25
25
  */
26
- export interface ByColourMatch {
26
+ export type ByColourMatch = {
27
27
  /** Opaque — round-trip verbatim. */
28
28
  variantId: VariantId;
29
29
  brand: string;
@@ -37,11 +37,22 @@ export interface ByColourMatch {
37
37
  color: string | null;
38
38
  variantName: string | null;
39
39
  imageUrl: string | null;
40
+ /**
41
+ * SHA-256 of the displayed image `imageUrl` points at, as a hex digest.
42
+ * ABSENT means no hash is on record, never that there is no image.
43
+ */
44
+ imageSha256?: string;
40
45
  hex: string | null;
41
46
  distance: number;
42
47
  closeness: number;
43
48
  category: MatchCategory | null;
44
49
  oklab: OklabTriple | null;
50
+ /**
51
+ * Whether the reported `hex` has a hue compatible with the query colour, by
52
+ * colorscope's `isHueCompatible` at its default thresholds. A flag, never a
53
+ * gate. ABSENT when the match has no hex or the query was a palette.
54
+ */
55
+ hueCompatible?: boolean;
45
56
  /**
46
57
  * Where `hex` came from — PER MATCH, never per response. `"declared"`: the
47
58
  * manufacturer published it (a paint's own colour system), so it may be
@@ -78,17 +89,17 @@ export interface ByColourMatch {
78
89
  * manufacturer.
79
90
  */
80
91
  palette?: ByColourSwatch[];
81
- }
92
+ };
82
93
  /** A {@link PaletteSwatch} on the colour lane, where `oklab` is always derived. */
83
- export interface ByColourSwatch extends PaletteSwatch {
94
+ export type ByColourSwatch = {
84
95
  /** `hex` in OKLab — guaranteed present on this surface. */
85
96
  oklab: OklabTriple;
86
- }
97
+ } & PaletteSwatch;
87
98
  /**
88
99
  * Receipt for the `family` filter — ABSENT when none was asked for, so absence
89
100
  * means "no gate ran", never "a gate that dropped nothing".
90
101
  */
91
- export interface ColourFamilyGate {
102
+ export type ColourFamilyGate = {
92
103
  /** The colorscope taxonomy family id the gate kept (normalised). */
93
104
  family: string;
94
105
  /** Candidates the gate examined — the retrieved pool. NOT a corpus total. */
@@ -108,45 +119,49 @@ export interface ColourFamilyGate {
108
119
  * boundary.
109
120
  */
110
121
  droppedOnPublishedHex?: number;
111
- }
122
+ };
112
123
  /** Receipt for the hard category gate and its treatment of unknown typing. */
113
- export interface ColourCategoryGate {
114
- /** Category names or keys the caller asked the gate to keep. */
124
+ export type ColourCategoryGate = {
125
+ /**
126
+ * Present when the caller named no category: the page then holds surface
127
+ * materials only (the `materials` product-type groups, listed in
128
+ * `requested`), so lights, taps and furniture do not answer a colour.
129
+ */
130
+ defaulted?: true;
131
+ /** Category names or keys the gate kept: the caller's, or the default groups. */
115
132
  requested: string[];
116
133
  /** Only accepted primary product types can establish membership. */
117
134
  requiresAcceptedPrimaryProductType: true;
118
135
  /** Unknown/unclassified variants were ineligible, not proven non-members. */
119
136
  unclassifiedVariantsExcluded: true;
120
- }
137
+ };
121
138
  /**
122
139
  * Receipt for the colour-identity collapse that turns a variant-grain ranking
123
140
  * into a page of TILES — one per (brand, product, dominant hex), one per stored
124
- * photograph. The live endpoint always sends it; it is optional here only so
125
- * responses captured before the collapse existed still type-check.
141
+ * photograph. Only responses stored before the one search carry it: the one
142
+ * search pages one row per product, so nothing collapses now.
126
143
  */
127
- export interface ColourCollapse {
144
+ export type ColourCollapse = {
128
145
  /** Ranked rows the collapse examined — this page's pool, never a corpus total. */
129
146
  considered: number;
130
147
  /** Rows dropped for repeating a better-ranked row's brand, product and hex. */
131
148
  droppedByIdentity: number;
132
149
  /** Rows dropped for resolving to a better-ranked row's stored photograph. */
133
150
  droppedBySharedImage: number;
134
- }
151
+ };
135
152
  /**
136
153
  * Receipt naming which retrieval lane answered, and the colours it actually ran
137
154
  * on. The live endpoint always sends it.
138
155
  *
139
- * Two lanes answer two different questions. A ONE-COLOUR query is a CONTAINMENT
140
- * question — which materials hold a swatch near this colour — and is answered as
141
- * a bounded OKLab ball over stored palette swatches. A multi-colour query is a
142
- * SIMILARITY question — which palettes as a whole resemble this palette — and is
143
- * answered by nearest-neighbour over the palette embedding. The two rank on
144
- * different geometries, so `colourDistance` on a match means a different thing
145
- * in each and is NOT comparable across them.
156
+ * Every live page says `index`: the one search's colour key, the colour's
157
+ * family on the search index, nearest first by OKLab distance. A palette is
158
+ * ordered by its first colour, and `droppedColours` names the rest.
159
+ * `containment` and `palette` appear only on responses stored before the one
160
+ * search.
146
161
  */
147
- export interface ColourLaneReceipt {
162
+ export type ColourLaneReceipt = {
148
163
  /** Which lane answered. Widened so a new server lane still type-checks. */
149
- lane: OpenEnum<"containment" | "palette">;
164
+ lane: OpenEnum<"index" | "containment" | "palette">;
150
165
  /** Why this lane, in one sentence, for a human reader. */
151
166
  reason: string;
152
167
  /**
@@ -169,9 +184,9 @@ export interface ColourLaneReceipt {
169
184
  * result is not evidence that nothing holds them.
170
185
  */
171
186
  droppedColours: string[];
172
- }
187
+ };
173
188
  /** The `search/colours` response. */
174
- export interface ByColourResponse {
189
+ export type ByColourResponse = {
175
190
  query: {
176
191
  /** Raw query provenance, when supplied. */
177
192
  q?: string;
@@ -234,9 +249,9 @@ export interface ByColourResponse {
234
249
  corpusScope?: CorpusScopeReceipt;
235
250
  /** Shared standard-search query-understanding receipt. */
236
251
  understanding?: QueryUnderstanding;
237
- }
252
+ };
238
253
  /** Params for `search/colours`. */
239
- export interface ByColourParams {
254
+ export type ByColourParams = {
240
255
  /** Raw material-domain query provenance for shared query understanding. */
241
256
  q?: string;
242
257
  /** A single hex (with or without `#`). */
@@ -247,7 +262,11 @@ export interface ByColourParams {
247
262
  l?: number;
248
263
  a?: number;
249
264
  b?: number;
250
- /** HARD category filter — display names or taxonomy ids (repeatable). */
265
+ /**
266
+ * HARD category filter — display names or taxonomy ids (repeatable). Absent,
267
+ * the page holds surface materials only (`categoryGate.defaulted`), so
268
+ * lights, taps and furniture do not answer a colour.
269
+ */
251
270
  category?: string | string[];
252
271
  /**
253
272
  * HARD brand filter (repeatable) — a canonical brand id, exact brand SLUG
@@ -283,11 +302,19 @@ export interface ByColourParams {
283
302
  * drop.
284
303
  */
285
304
  family?: string;
286
- /** Single-colour order; omitted keeps representative browsing order. */
305
+ /**
306
+ * Kept so existing callers still parse: every page is ordered nearest first
307
+ * by the one search's colour key, so both values return the same page.
308
+ */
287
309
  order?: "representative" | "nearest";
310
+ /**
311
+ * Order by the colour of an existing Variant: materials the same colour as
312
+ * this one. Used when no hex, colour or OKLab triple is given.
313
+ */
314
+ variantId?: string;
288
315
  /** Maximum OKLab distance to each match's reported hex. Single-colour only. */
289
316
  maxColourDistance?: number;
290
317
  /** Narrow retrieval inside the server query; absent means the whole graph. */
291
318
  corpusScope?: CorpusScope;
292
319
  limit?: number;
293
- }
320
+ };