@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.
- package/association-types.d.ts +38 -27
- package/associations-client.d.ts +4 -4
- package/associations-client.js +3 -10
- package/attribution-types.d.ts +4 -4
- package/brand-types.d.ts +14 -6
- package/brands-client.d.ts +7 -38
- package/brands-client.js +10 -40
- package/by-colour-types.d.ts +58 -31
- package/by-spec-types.d.ts +6 -73
- package/by-spec-types.js +7 -5
- package/catalog-discovery-types.d.ts +11 -26
- package/catalogue-client.d.ts +16 -35
- package/catalogue-client.js +32 -67
- package/catalogue-types.d.ts +44 -4
- package/categories-client.d.ts +63 -0
- package/categories-client.js +48 -0
- package/category-types.d.ts +114 -0
- package/citation-types.d.ts +4 -4
- package/client-config.d.ts +4 -6
- package/client-config.js +2 -4
- package/client-source-material-comments.d.ts +4 -4
- package/client-source-material-comments.js +4 -38
- package/client-vocabulary.d.ts +7 -9
- package/client-vocabulary.js +22 -30
- package/client.d.ts +110 -244
- package/client.js +217 -387
- package/codes-client.d.ts +2 -2
- package/codes-client.js +8 -8
- package/codes-types.d.ts +55 -34
- package/colour-aggregate-types.d.ts +24 -24
- package/colours-client.d.ts +6 -11
- package/colours-client.js +11 -19
- package/coordinate-client.d.ts +2 -2
- package/coordinate-client.js +1 -13
- package/corpus-scope-types.d.ts +3 -3
- package/corpus-scope-types.js +1 -25
- package/demand-batch-types.d.ts +18 -18
- package/demand-types.d.ts +24 -24
- package/errors.d.ts +13 -13
- package/errors.js +54 -52
- package/http-transport.d.ts +13 -21
- package/http-transport.js +31 -28
- package/identify-types.d.ts +54 -44
- package/identify-types.js +5 -3
- package/index.d.ts +11 -27
- package/index.js +4 -6
- package/list-variant-facets-types.d.ts +60 -0
- package/list-variants-types.d.ts +142 -0
- package/list-variants-types.js +12 -0
- package/match-stream-types.d.ts +45 -32
- package/match-stream-types.js +2 -0
- package/match-stream.d.ts +2 -2
- package/match-stream.js +67 -49
- package/match-types.d.ts +32 -8
- package/material-asset-types.d.ts +89 -69
- package/material-block-types.d.ts +8 -6
- package/material-composition-client.d.ts +21 -0
- package/material-composition-client.js +13 -0
- package/material-composition-types.d.ts +403 -0
- package/material-query-plan-types.d.ts +61 -145
- package/material-resources-client.d.ts +12 -10
- package/material-resources-client.js +27 -22
- package/material-types.d.ts +16 -24
- package/ndjson.js +16 -8
- package/operations.d.ts +6 -6
- package/operations.js +29 -156
- package/package.json +5 -1
- package/palette-search-types.d.ts +87 -52
- package/query-understanding-types.d.ts +65 -40
- package/resolve-client.d.ts +8 -12
- package/resolve-client.js +9 -13
- package/resolve-colour-types.d.ts +8 -8
- package/resolve-types.d.ts +10 -10
- package/response-schemas.d.ts +20 -0
- package/response-schemas.generated.d.ts +5 -0
- package/response-schemas.generated.js +160 -0
- package/response-schemas.js +113 -0
- package/run-types.d.ts +64 -145
- package/runs.d.ts +9 -58
- package/runs.js +60 -149
- package/samplize-catalogue-types.d.ts +18 -18
- package/samplize-colorvec.d.ts +20 -20
- package/samplize-colorvec.js +66 -42
- package/schema-resource-types.d.ts +52 -39
- package/schema-resource-types.js +5 -5
- package/search-card-types.d.ts +26 -4
- package/search-index-plan-types.d.ts +70 -0
- package/search-refinement-types.d.ts +10 -40
- package/search-refinement-types.js +1 -0
- package/search-request-types.d.ts +121 -204
- package/search-response-receipt-types.d.ts +13 -253
- package/search-response-types.d.ts +2 -2
- package/search-result-validation.d.ts +3 -19
- package/search-result-validation.js +42 -183
- package/source-material-validation.d.ts +3 -3
- package/source-material-validation.js +35 -39
- package/spec-facet-types.d.ts +11 -16
- package/spec-types.d.ts +23 -16
- package/spec-types.js +8 -7
- package/specifications.d.ts +14 -72
- package/specifications.js +39 -89
- package/sse.d.ts +2 -2
- package/sse.js +32 -16
- package/substitute-types.d.ts +22 -22
- package/suggest-types.d.ts +11 -17
- package/suggest-types.js +3 -3
- package/taxonomy-coverage-types.d.ts +8 -8
- package/types.d.ts +202 -405
- package/validation.d.ts +26 -26
- package/validation.js +97 -92
- package/webmcp.d.ts +3 -3
- package/webmcp.generated.js +10 -93
- package/brand-most-sampled-types.d.ts +0 -33
- package/browse-types.d.ts +0 -236
- package/client-browse.d.ts +0 -78
- package/client-browse.js +0 -72
- package/client-exploration.d.ts +0 -9
- package/client-exploration.js +0 -7
- package/compare-types.d.ts +0 -89
- package/composition-client.d.ts +0 -33
- package/composition-client.js +0 -27
- package/composition-types.d.ts +0 -455
- package/composition-types.js +0 -10
- package/correction-types.d.ts +0 -88
- package/exploration-types.d.ts +0 -118
- package/exploration-types.js +0 -1
- package/fan-deck-types.d.ts +0 -42
- package/fan-deck-types.js +0 -9
- package/match-rejection-types.d.ts +0 -43
- package/match-rejection-types.js +0 -7
- package/palette-completion-types.d.ts +0 -115
- package/palette-completion-types.js +0 -1
- package/project-types.d.ts +0 -79
- package/project-types.js +0 -9
- package/projects.d.ts +0 -13
- package/projects.js +0 -46
- package/render-assets-types.d.ts +0 -65
- package/render-assets-types.js +0 -1
- package/run-events.d.ts +0 -106
- package/run-events.js +0 -32
- package/schedule-reference-types.d.ts +0 -46
- package/schedule-reference-types.js +0 -1
- package/schedule-references-client.d.ts +0 -14
- package/schedule-references-client.js +0 -26
- package/schedule-types.d.ts +0 -261
- package/schedule-types.js +0 -1
- package/search-collapse-types.d.ts +0 -69
- package/search-collapse-types.js +0 -1
- package/search-mood-types.d.ts +0 -6
- package/search-mood-types.js +0 -1
- package/search-window-types.d.ts +0 -25
- package/search-window-types.js +0 -1
- package/slot-pool-types.d.ts +0 -372
- package/slot-pool-types.js +0 -1
- /package/{brand-most-sampled-types.js → category-types.js} +0 -0
- /package/{browse-types.js → list-variant-facets-types.js} +0 -0
- /package/{compare-types.js → material-composition-types.js} +0 -0
- /package/{correction-types.js → search-index-plan-types.js} +0 -0
package/client.js
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
|
-
import { CatalogueClient } from "./catalogue-client.js";
|
|
2
|
-
import { DEFAULT_BASE_URL, MAX_BATCH_IDS } from "./client-config.js";
|
|
3
|
-
import { MaterialGraphError } from "./errors.js";
|
|
4
|
-
import { HttpTransport } from "./http-transport.js";
|
|
5
|
-
// Aliased to `operation` — the local name every call site here already used.
|
|
6
|
-
import { resolveOperation as operation, } from "./operations.js";
|
|
7
|
-
import { cancelRun, capabilities as capabilitiesRun, createRun, drainRunEvents, getRun, getRunSchedule, getSourceMaterialBatch as getSourceMaterialBatchCall, listRuns, resumeRun, streamRunEvents, uploadSourceMaterial, } from "./runs.js";
|
|
8
|
-
import { ScheduleReferencesClient } from "./schedule-references-client.js";
|
|
9
|
-
// Re-exported whole so `index.ts` and every existing importer keep their path.
|
|
10
|
-
export * from "./client-config.js";
|
|
11
|
-
import { browseQuery, createBrowseNamespace, } from "./client-browse.js";
|
|
12
|
-
import { createExplorationNamespace, } from "./client-exploration.js";
|
|
13
|
-
import { createSourceMaterialCommentsNamespace, } from "./client-source-material-comments.js";
|
|
14
1
|
import * as assoc from "./associations-client.js";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
2
|
+
import { listBrands } from "./brands-client.js";
|
|
3
|
+
import { CatalogueClient } from "./catalogue-client.js";
|
|
4
|
+
import { CategoriesClient } from "./categories-client.js";
|
|
5
|
+
import { DEFAULT_BASE_URL } from "./client-config.js";
|
|
6
|
+
import { createSourceMaterialCommentsNamespace } from "./client-source-material-comments.js";
|
|
7
|
+
import { listAttributes as listAttributesCall, resolveColour as resolveColourCall, suggest as suggestCall, suggestColour as suggestColourCall, } from "./client-vocabulary.js";
|
|
17
8
|
import { CodesClient } from "./codes-client.js";
|
|
18
9
|
import { ColoursClient } from "./colours-client.js";
|
|
19
|
-
import { slotPools as slotPoolsCall, varyScheme as varySchemeCall, } from "./composition-client.js";
|
|
20
10
|
import { coordinate as coordinateCall } from "./coordinate-client.js";
|
|
11
|
+
import { MaterialGraphError } from "./errors.js";
|
|
12
|
+
import { HttpTransport } from "./http-transport.js";
|
|
21
13
|
import { matchStream as matchStreamCall } from "./match-stream.js";
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
14
|
+
import { compositionReport as compositionReportCall } from "./material-composition-client.js";
|
|
15
|
+
import { listVariantAssets as listVariantAssetsCall, materialBlocks as materialBlocksCall, materialDocuments as materialDocumentsCall, } from "./material-resources-client.js";
|
|
16
|
+
// Aliased to `operation` — the local name every call site here already used.
|
|
17
|
+
import { resolveOperation as operation } from "./operations.js";
|
|
24
18
|
import { resolvePhrasesRequest as resolvePhrases, searchVocabularyRequest, } from "./resolve-client.js";
|
|
19
|
+
import { createRun, drainRunEvents, getRun, getSourceMaterialBatch as getSourceMaterialBatchCall, streamRunEvents, uploadSourceMaterial, } from "./runs.js";
|
|
25
20
|
import { SCHEMA_RESOURCE_OPERATION_IDS } from "./schema-resource-types.js";
|
|
21
|
+
// Re-exported whole so `index.ts` and every existing importer keep their path.
|
|
22
|
+
export * from "./client-config.js";
|
|
26
23
|
/**
|
|
27
24
|
* The MaterialGraph client — every lens on the graph, on one object.
|
|
28
25
|
*
|
|
@@ -33,13 +30,13 @@ import { SCHEMA_RESOURCE_OPERATION_IDS } from "./schema-resource-types.js";
|
|
|
33
30
|
* | --- | --- |
|
|
34
31
|
* | "find me something like this / matching these words" | {@link MaterialGraphClient.search} |
|
|
35
32
|
* | "what's IN this photo?" | {@link MaterialGraphClient.match} / {@link MaterialGraphClient.matchStream} |
|
|
36
|
-
* | "which materials, from anyone, meet this hard spec?" | {@link MaterialGraphClient.
|
|
33
|
+
* | "which materials, from anyone, meet this hard spec?" | {@link MaterialGraphClient.listVariants} |
|
|
37
34
|
* | "what's near this colour / this palette / this gradient?" | {@link MaterialGraphClient.byColour}, `colours.palette()`, `colours.gradient()` |
|
|
38
|
-
* | "what goes with THIS material?" | {@link MaterialGraphClient.pairings}, {@link MaterialGraphClient.
|
|
35
|
+
* | "what goes with THIS material?" | {@link MaterialGraphClient.pairings}, {@link MaterialGraphClient.listVariants} (same product, other colourways), {@link MaterialGraphClient.coordinate} |
|
|
39
36
|
* | "what does the manufacturer say is AVAILABLE on this?" | {@link MaterialGraphClient.associatedFinishes}, {@link MaterialGraphClient.associatedProducts} |
|
|
40
37
|
* | "how much is this specified?" | {@link MaterialGraphClient.demand}, {@link MaterialGraphClient.demandBatch} |
|
|
41
38
|
* | "is this allowed in an A-2 corridor?" | `codes.*` |
|
|
42
|
-
* | "what can I even ask for?" | {@link MaterialGraphClient.specificationFacets},
|
|
39
|
+
* | "what can I even ask for?" | {@link MaterialGraphClient.specificationFacets}, `categories.list()` |
|
|
43
40
|
* | "I have words — what do they mean in YOUR vocabulary?" | {@link MaterialGraphClient.resolve} |
|
|
44
41
|
* | "do the whole job for me, async" | {@link MaterialGraphClient.createRun} + `mg:compose` |
|
|
45
42
|
*
|
|
@@ -59,33 +56,28 @@ import { SCHEMA_RESOURCE_OPERATION_IDS } from "./schema-resource-types.js";
|
|
|
59
56
|
* `./identifiers.ts`), absent is not false, and a page is not a corpus.
|
|
60
57
|
*/
|
|
61
58
|
export class MaterialGraphClient extends CatalogueClient {
|
|
62
|
-
scheduleReferences;
|
|
63
59
|
baseUrl;
|
|
64
60
|
/**
|
|
65
|
-
* THE QUESTION: "
|
|
66
|
-
*
|
|
67
|
-
* `
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* `count: true` returns the total so a listing can say how many things it is
|
|
72
|
-
* listing without walking every page. `results.length` remains a PAGE.
|
|
73
|
-
*
|
|
74
|
-
* Instead use {@link MaterialGraphClient.byColour} for materials NEAR a colour,
|
|
75
|
-
* {@link MaterialGraphClient.search} when there is anything to rank against,
|
|
76
|
-
* and `colours.profiles()` for a category's palette rather than its members.
|
|
61
|
+
* THE QUESTION: "what kinds of thing exist, and what are their keys?"
|
|
62
|
+
* `categories.list()` pages the tree (roots, one node's children, or a
|
|
63
|
+
* name/meaning search), and `categories.get(id)` reads one node in full:
|
|
64
|
+
* its place, the names that find it, and the canonical taxonomy concepts it
|
|
65
|
+
* relates to. The source of every category id the other lenses accept
|
|
66
|
+
* (`search({ category })`, `listVariants({ filters })`, `colours.profiles()`).
|
|
77
67
|
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
68
|
+
* A category id is a TREE KEY, never a canonical `product_category` value:
|
|
69
|
+
* the two look alike and are not interchangeable. Discover ids here, never
|
|
70
|
+
* hand-write them. Replaces the retired `taxonomy()` (MG-2226), with no
|
|
71
|
+
* shim.
|
|
80
72
|
*/
|
|
81
|
-
|
|
73
|
+
categories;
|
|
82
74
|
/**
|
|
83
75
|
* THE QUESTION: "is this material allowed HERE?" — a jurisdiction + occupancy +
|
|
84
76
|
* finish location, not a property of the material alone. `codes.context()`
|
|
85
77
|
* discovers the vocabulary, `codes.requirements()` states a space,
|
|
86
78
|
* `codes.advisory()` badges candidates.
|
|
87
79
|
*
|
|
88
|
-
* Instead use {@link MaterialGraphClient.
|
|
80
|
+
* Instead use {@link MaterialGraphClient.listVariants} to find materials by a
|
|
89
81
|
* classification you already know you need; codes is what tells you WHICH one
|
|
90
82
|
* the space demands. ADVISORY ONLY: model code as adopted, never a
|
|
91
83
|
* determination for an authority having jurisdiction.
|
|
@@ -95,15 +87,14 @@ export class MaterialGraphClient extends CatalogueClient {
|
|
|
95
87
|
* THE QUESTION: "what colours exist here?" (`profiles`, `stats`) and "what
|
|
96
88
|
* matches this whole SET of colours?" (`palette`, `gradient`).
|
|
97
89
|
*
|
|
98
|
-
* Instead use {@link MaterialGraphClient.byColour} for ONE colour
|
|
99
|
-
* {@link MaterialGraphClient.
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
90
|
+
* Instead use {@link MaterialGraphClient.byColour} for ONE colour and
|
|
91
|
+
* {@link MaterialGraphClient.listVariants} to page through a colour's family.
|
|
92
|
+
* Colour is usually derived from product imagery, which is visual likeness,
|
|
93
|
+
* not a colour specification. A maker's declared colour, such as a paint's
|
|
94
|
+
* published hex, wins where MaterialGraph holds one, and each value's
|
|
95
|
+
* source basis says which.
|
|
103
96
|
*/
|
|
104
97
|
colours;
|
|
105
|
-
/** Discover honest graph questions, then traverse one explicit operator. */
|
|
106
|
-
exploration;
|
|
107
98
|
/**
|
|
108
99
|
* THE QUESTION: "what did people say about this uploaded file, and record what
|
|
109
100
|
* they said." Names on these remarks are REPORTED, never verified — see
|
|
@@ -123,66 +114,45 @@ export class MaterialGraphClient extends CatalogueClient {
|
|
|
123
114
|
super(transport);
|
|
124
115
|
this.#transport = transport;
|
|
125
116
|
this.baseUrl = transport.baseUrl;
|
|
126
|
-
this.
|
|
127
|
-
|
|
117
|
+
this.categories = new CategoriesClient({
|
|
118
|
+
get: async (operationId, query, signal, pathParams) => await this.#get(operationId, query, signal, pathParams),
|
|
119
|
+
});
|
|
128
120
|
this.codes = new CodesClient({
|
|
129
|
-
get: (operationId, query, signal) => this.#get(operationId, query, signal),
|
|
130
|
-
post: (operationId, body, signal) => this.#post(operationId, body, signal),
|
|
121
|
+
get: async (operationId, query, signal) => await this.#get(operationId, query, signal),
|
|
122
|
+
post: async (operationId, body, signal) => await this.#post(operationId, body, signal),
|
|
131
123
|
});
|
|
132
124
|
this.colours = new ColoursClient({
|
|
133
|
-
get: (operationId, query, signal) => this.#get(operationId, query, signal),
|
|
134
|
-
post: (operationId, body, signal) => this.#post(operationId, body, signal),
|
|
125
|
+
get: async (operationId, query, signal) => await this.#get(operationId, query, signal),
|
|
126
|
+
post: async (operationId, body, signal) => await this.#post(operationId, body, signal),
|
|
135
127
|
});
|
|
136
|
-
this.exploration = createExplorationNamespace(this.#transport);
|
|
137
128
|
this.sourceMaterialComments = createSourceMaterialCommentsNamespace(this.#transport);
|
|
138
129
|
}
|
|
139
130
|
get lastRateLimit() {
|
|
140
131
|
return this.#transport.lastRateLimit;
|
|
141
132
|
}
|
|
142
|
-
#get(operationId, query, signal, pathParams) {
|
|
143
|
-
return this.#transport.requestJson(operation(operationId), {
|
|
133
|
+
async #get(operationId, query, signal, pathParams) {
|
|
134
|
+
return await this.#transport.requestJson(operation(operationId), {
|
|
135
|
+
pathParams,
|
|
144
136
|
query,
|
|
145
137
|
signal,
|
|
146
|
-
pathParams,
|
|
147
138
|
});
|
|
148
139
|
}
|
|
149
|
-
#post(operationId, body, signal, pathParams) {
|
|
150
|
-
return this.#transport.requestJson(operation(operationId), {
|
|
140
|
+
async #post(operationId, body, signal, pathParams) {
|
|
141
|
+
return await this.#transport.requestJson(operation(operationId), {
|
|
151
142
|
body,
|
|
152
|
-
signal,
|
|
153
143
|
pathParams,
|
|
144
|
+
signal,
|
|
154
145
|
});
|
|
155
146
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
* seed image, colours and a mood, optionally gated by hard specs.
|
|
159
|
-
*
|
|
160
|
-
* Instead use {@link MaterialGraphClient.bySpec} when the spec IS the question
|
|
161
|
-
* (ranking would be noise), {@link MaterialGraphClient.byColour} /
|
|
162
|
-
* `colours.palette()` for visual colour intent (`text` matches WORDS — "sage
|
|
163
|
-
* green" finds materials that SAY sage, not ones that look it),
|
|
164
|
-
* {@link MaterialGraphClient.match} for a photo, {@link MaterialGraphClient.pairings}
|
|
165
|
-
* for what goes WITH something, {@link MaterialGraphClient.suggest} for typeahead.
|
|
166
|
-
*
|
|
167
|
-
* The full POST search primitive. `input.filters` layers typed hard
|
|
168
|
-
* specification gates onto ranked colour/visual/lexical/seed search. Build
|
|
169
|
-
* them with `certificationProgramme`, `specTerm`, or `hasSpec`.
|
|
170
|
-
*/
|
|
171
|
-
search(input, signal) {
|
|
172
|
-
return this.#post("search_materials_post", input, signal);
|
|
147
|
+
async search(input, signal) {
|
|
148
|
+
return await this.#post("search_materials_post", input, signal);
|
|
173
149
|
}
|
|
174
150
|
/** Whole materials ask → inspectable meanings and complete safe search requests. */
|
|
175
|
-
planQuery(query, signal) {
|
|
176
|
-
return this.#post("plan_material_query", { query }, signal);
|
|
151
|
+
async planQuery(query, signal) {
|
|
152
|
+
return await this.#post("plan_material_query", { query }, signal);
|
|
177
153
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
* transport — a cacheable, link-shareable GET for queries that must survive in
|
|
181
|
-
* a URL. `filters`, `preferences`, `verdicts`, image bytes and `weights` have
|
|
182
|
-
* no query-string form, so anything using those must go through `search`.
|
|
183
|
-
*/
|
|
184
|
-
searchGet(params, signal) {
|
|
185
|
-
return this.#get("search_materials_get", { ...params }, signal);
|
|
154
|
+
async searchGet(params, signal) {
|
|
155
|
+
return await this.#get("search_materials_get", { ...params }, signal);
|
|
186
156
|
}
|
|
187
157
|
/**
|
|
188
158
|
* THE QUESTION: "what materials are in this PHOTO?" — Material Match classifies
|
|
@@ -197,8 +167,8 @@ export class MaterialGraphClient extends CatalogueClient {
|
|
|
197
167
|
* `droppedBelowFloor` before reporting an empty result: "nothing was good
|
|
198
168
|
* enough" and "nothing was found" are different answers.
|
|
199
169
|
*/
|
|
200
|
-
match(input, signal) {
|
|
201
|
-
return this.#post("match_material", input, signal);
|
|
170
|
+
async match(input, signal) {
|
|
171
|
+
return await this.#post("match_material", input, signal);
|
|
202
172
|
}
|
|
203
173
|
/**
|
|
204
174
|
* Material Match as a PROGRESSIVE stream — the same POST
|
|
@@ -233,26 +203,27 @@ export class MaterialGraphClient extends CatalogueClient {
|
|
|
233
203
|
* Instead use `colours.palette()` for N colours at stated proportions (a
|
|
234
204
|
* different ranking, not a wrapper), `colours.gradient()` for a transition,
|
|
235
205
|
* {@link MaterialGraphClient.resolveColour} first if you hold a NAME,
|
|
236
|
-
* {@link MaterialGraphClient.
|
|
206
|
+
* {@link MaterialGraphClient.listVariants} to page through a category or a brand, and
|
|
237
207
|
* {@link MaterialGraphClient.search} when colour is one signal among many.
|
|
238
208
|
* Report matches as visual likeness, never a stated colour specification.
|
|
239
209
|
* `family` gates to ONE colorscope family (a gated page can be short); `brand` gates to named brands — one brand's nearest colour to another's.
|
|
240
210
|
*/
|
|
241
|
-
byColour(params, signal) {
|
|
242
|
-
return this.#get("search_by_colour", {
|
|
243
|
-
q: params.q,
|
|
244
|
-
hex: params.hex,
|
|
245
|
-
colour: params.colour,
|
|
246
|
-
l: params.l,
|
|
211
|
+
async byColour(params, signal) {
|
|
212
|
+
return await this.#get("search_by_colour", {
|
|
247
213
|
a: params.a,
|
|
248
214
|
b: params.b,
|
|
249
|
-
category: params.category,
|
|
250
215
|
brand: params.brand,
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
maxColourDistance: params.maxColourDistance,
|
|
216
|
+
category: params.category,
|
|
217
|
+
colour: params.colour,
|
|
254
218
|
corpusScope: params.corpusScope,
|
|
219
|
+
family: params.family,
|
|
220
|
+
hex: params.hex,
|
|
221
|
+
l: params.l,
|
|
255
222
|
limit: params.limit,
|
|
223
|
+
maxColourDistance: params.maxColourDistance,
|
|
224
|
+
order: params.order,
|
|
225
|
+
q: params.q,
|
|
226
|
+
variantId: params.variantId,
|
|
256
227
|
}, signal);
|
|
257
228
|
}
|
|
258
229
|
// ── Materials ──────────────────────────────────────────────────────────────
|
|
@@ -261,195 +232,185 @@ export class MaterialGraphClient extends CatalogueClient {
|
|
|
261
232
|
* `/api/v1/materials/{variantId}`).
|
|
262
233
|
*
|
|
263
234
|
* The hinge of the API: every relationship lens
|
|
264
|
-
* ({@link MaterialGraphClient.
|
|
235
|
+
* ({@link MaterialGraphClient.listVariants}, {@link MaterialGraphClient.pairings},
|
|
265
236
|
* {@link MaterialGraphClient.demand}, `codes.advisory()`) hangs off a
|
|
266
|
-
* `variantId`. Instead use {@link MaterialGraphClient.
|
|
267
|
-
*
|
|
268
|
-
*
|
|
237
|
+
* `variantId`. Instead use {@link MaterialGraphClient.listVariants} for many
|
|
238
|
+
* ids, or for the other colourways of the same product (MG-2222 retired
|
|
239
|
+
* this route's `?include=siblings`; ask `listVariants` with a `product in`
|
|
240
|
+
* filter instead), {@link MaterialGraphClient.materialBlocks} to tell "no
|
|
241
|
+
* value" from "not checked", {@link MaterialGraphClient.search} when you
|
|
242
|
+
* have no id yet.
|
|
269
243
|
*
|
|
270
244
|
* @param variantId Opaque — pass back exactly what you were given.
|
|
271
245
|
*/
|
|
272
|
-
material(variantId,
|
|
273
|
-
return this.#get("get_material",
|
|
246
|
+
async material(variantId, signal) {
|
|
247
|
+
return await this.#get("get_material", undefined, signal, { variantId });
|
|
248
|
+
}
|
|
249
|
+
async materialBlocks(variantId, signal) {
|
|
250
|
+
return await materialBlocksCall(this.#transport, variantId, signal);
|
|
274
251
|
}
|
|
275
252
|
/**
|
|
276
|
-
* THE QUESTION: "
|
|
277
|
-
* — the SAME product, different variants.
|
|
253
|
+
* THE QUESTION: "which product types can composition be answered for yet?"
|
|
278
254
|
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
255
|
+
* Coverage per product type, in Live SKUs as well as tuples. Read the SKU
|
|
256
|
+
* figure: one tuple can carry a hundred thousand SKUs or one.
|
|
281
257
|
*/
|
|
282
|
-
|
|
283
|
-
return this.#
|
|
258
|
+
async compositionReport(signal) {
|
|
259
|
+
return await compositionReportCall(this.#transport, signal);
|
|
284
260
|
}
|
|
285
|
-
|
|
286
|
-
return
|
|
261
|
+
async listVariantAssets(variantId, options, signal) {
|
|
262
|
+
return await listVariantAssetsCall(this.#transport, variantId, options, signal);
|
|
287
263
|
}
|
|
288
|
-
|
|
289
|
-
return
|
|
290
|
-
}
|
|
291
|
-
materialRenderAssets(variantId, signal) {
|
|
292
|
-
return materialRenderAssetsCall(this.#transport, variantId, signal);
|
|
293
|
-
}
|
|
294
|
-
materialDocuments(variantId, options, signal) {
|
|
295
|
-
return materialDocumentsCall(this.#transport, variantId, options, signal);
|
|
264
|
+
async materialDocuments(variantId, options, signal) {
|
|
265
|
+
return await materialDocumentsCall(this.#transport, variantId, options, signal);
|
|
296
266
|
}
|
|
297
267
|
/**
|
|
298
268
|
* THE QUESTION: "what does the schema DEFINE?" — the governed static registry.
|
|
299
269
|
*
|
|
300
270
|
* Definitions, not data: use {@link MaterialGraphClient.specificationFacets} for
|
|
301
|
-
* what the corpus actually holds
|
|
302
|
-
* explain one term.
|
|
271
|
+
* what the corpus actually holds.
|
|
303
272
|
*/
|
|
304
|
-
schema(resource, signal) {
|
|
305
|
-
return this.#get(SCHEMA_RESOURCE_OPERATION_IDS[resource], undefined, signal);
|
|
273
|
+
async schema(resource, signal) {
|
|
274
|
+
return await this.#get(SCHEMA_RESOURCE_OPERATION_IDS[resource], undefined, signal);
|
|
306
275
|
}
|
|
307
276
|
/**
|
|
308
277
|
* THE QUESTION: "what goes WITH this material?" — the companionship rail, hung
|
|
309
278
|
* off one resolved material (GET `/api/v1/materials/{variantId}/pairings`).
|
|
310
279
|
*
|
|
311
280
|
* Instead use {@link MaterialGraphClient.coordinate} for a whole palette of
|
|
312
|
-
* picks, {@link MaterialGraphClient.
|
|
313
|
-
* colour, and `search({ similarTo })` for a LIKE-THIS substitute —
|
|
314
|
-
* complementary are opposite questions.
|
|
281
|
+
* picks, {@link MaterialGraphClient.listVariants} for the same product in
|
|
282
|
+
* another colour, and `search({ similarTo })` for a LIKE-THIS substitute —
|
|
283
|
+
* similar and complementary are opposite questions.
|
|
315
284
|
*
|
|
316
285
|
* READ `item.source` BEFORE PHRASING: the rail mixes three tiers of evidence —
|
|
317
286
|
* `cospec` (real orders), `considered` (board activity), `colour` (palette
|
|
318
287
|
* look-alike). Only `cospec` supports "sampled together". `cospecCount` tells
|
|
319
288
|
* you how much of the rail is real order evidence.
|
|
320
289
|
*/
|
|
321
|
-
pairings(variantId, options, signal) {
|
|
322
|
-
return this.#get("get_material_pairings", { ...options }, signal, {
|
|
290
|
+
async pairings(variantId, options, signal) {
|
|
291
|
+
return await this.#get("get_material_pairings", { ...options }, signal, {
|
|
323
292
|
variantId,
|
|
324
293
|
});
|
|
325
294
|
}
|
|
326
|
-
/** Find bounded, exact-spec substitutes for one opaque variant id. */
|
|
327
|
-
findSubstitutes(variantId, options = {}, signal) {
|
|
328
|
-
return this.#post("find_material_substitutes", options, signal, { variantId });
|
|
329
|
-
}
|
|
330
295
|
/** "What finishes does the manufacturer declare for THIS product?" — {@link declaredFinishes}. */
|
|
331
|
-
associatedFinishes(variantId, options, signal) {
|
|
332
|
-
return assoc.declaredFinishes(this.#transport, variantId, options, signal);
|
|
296
|
+
async associatedFinishes(variantId, options, signal) {
|
|
297
|
+
return await assoc.declaredFinishes(this.#transport, variantId, options, signal);
|
|
333
298
|
}
|
|
334
299
|
/** "What products does the manufacturer declare THIS finish for?" — {@link declaredProducts}. */
|
|
335
|
-
associatedProducts(variantId, options, signal) {
|
|
336
|
-
return assoc.declaredProducts(this.#transport, variantId, options, signal);
|
|
337
|
-
}
|
|
338
|
-
applicability(options, signal) {
|
|
339
|
-
return assoc.applicability(this.#transport, options, signal);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
300
|
+
async associatedProducts(variantId, options, signal) {
|
|
301
|
+
return await assoc.declaredProducts(this.#transport, variantId, options, signal);
|
|
302
|
+
}
|
|
303
|
+
async applicability(options, signal) {
|
|
304
|
+
return await assoc.applicability(this.#transport, options, signal);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* THE QUESTION: "eligible variants matching these hard filters, ranked and
|
|
308
|
+
* cursor-paged" (GET `/api/v1/variants`, MG-2222) — the one read behind
|
|
309
|
+
* `list_variants`, hydrating ids you already hold (`{terms: [{field:
|
|
310
|
+
* "variant", op: "in", values: [...]}]}`, up to 100), the other colourways
|
|
311
|
+
* of a product (`{terms: [{field: "product", op: "in", values:
|
|
312
|
+
* [productId]}, {field: "variant", op: "not_in", values: [variantId]}]}` —
|
|
313
|
+
* `filters` is kind-grouped, `{terms, numbers, presence}`, every condition
|
|
314
|
+
* across all three ANDed), or a category/maker listing. An explicit
|
|
315
|
+
* `variant in` id that does not resolve to an eligible variant is
|
|
316
|
+
* reported in `unresolvedVariantIds`, never silently dropped from the
|
|
317
|
+
* page.
|
|
318
|
+
*
|
|
319
|
+
* `filters`/`optionalFilters`/`orderBy` are sent as URL-encoded JSON;
|
|
320
|
+
* `attributes`/`include` as comma-separated lists — the server validates,
|
|
321
|
+
* this method does not duplicate that check.
|
|
322
|
+
*/
|
|
323
|
+
async listVariants(input, signal) {
|
|
324
|
+
return await this.#get("list_variants", {
|
|
325
|
+
attributes: input.attributes?.length
|
|
326
|
+
? input.attributes.join(",")
|
|
327
|
+
: undefined,
|
|
328
|
+
cursor: input.cursor,
|
|
329
|
+
filters: input.filters ? JSON.stringify(input.filters) : undefined,
|
|
330
|
+
include: input.include?.length ? input.include.join(",") : undefined,
|
|
331
|
+
limit: input.limit,
|
|
332
|
+
name: input.name,
|
|
333
|
+
optionalFilters: input.optionalFilters
|
|
334
|
+
? JSON.stringify(input.optionalFilters)
|
|
335
|
+
: undefined,
|
|
336
|
+
orderBy: input.orderBy?.length
|
|
337
|
+
? JSON.stringify(input.orderBy)
|
|
338
|
+
: undefined,
|
|
359
339
|
}, signal);
|
|
360
340
|
}
|
|
361
|
-
/**
|
|
362
|
-
|
|
363
|
-
|
|
341
|
+
/**
|
|
342
|
+
* THE QUESTION: "which values do the variants matching these filters carry,
|
|
343
|
+
* and how many of each" (POST `/api/v1/variants/facets`, MG-2294) — the
|
|
344
|
+
* options and counts a filter UI shows beside a {@link
|
|
345
|
+
* MaterialGraphClient.listVariants} page. `filters` is the same tree
|
|
346
|
+
* `listVariants()` takes; the server validates both.
|
|
347
|
+
*/
|
|
348
|
+
async listVariantFacets(input, signal) {
|
|
349
|
+
return await this.#post("list_variant_facets", input, signal);
|
|
364
350
|
}
|
|
365
351
|
/** Resolve a colour name to its hex, and the named paint's catalogue variant. */
|
|
366
|
-
resolveColour(name, signal, options) {
|
|
367
|
-
return resolveColourCall(this.#transport, name, signal, options);
|
|
352
|
+
async resolveColour(name, signal, options) {
|
|
353
|
+
return await resolveColourCall(this.#transport, name, signal, options);
|
|
368
354
|
}
|
|
369
355
|
/** Ranked colour-name typeahead (GET `/api/v1/search/colours/suggest`). */
|
|
370
|
-
suggestColour(q, options, signal) {
|
|
371
|
-
return suggestColourCall(this.#transport, q, options, signal);
|
|
356
|
+
async suggestColour(q, options, signal) {
|
|
357
|
+
return await suggestColourCall(this.#transport, q, options, signal);
|
|
372
358
|
}
|
|
373
359
|
/** Entity typeahead. Navigate using the selected `refId`; use `search()` for materials. */
|
|
374
|
-
suggest(q, options, signal) {
|
|
375
|
-
return suggestCall(this.#transport, q, options, signal);
|
|
360
|
+
async suggest(q, options, signal) {
|
|
361
|
+
return await suggestCall(this.#transport, q, options, signal);
|
|
376
362
|
}
|
|
377
363
|
// ── Catalog ──────────────────────────────────────────────────────────────────
|
|
378
|
-
/** Resolve free text to a canonical attribute id. */
|
|
379
|
-
resolveAttribute(q, options, signal) {
|
|
380
|
-
return resolveAttributeCall(this.#transport, q, options, signal);
|
|
381
|
-
}
|
|
382
|
-
/** Resolve a value under a canonical attribute id; inspect `recommendedAction` for ambiguity. */
|
|
383
|
-
resolveAttributeValue(attributeId, query, options, signal) {
|
|
384
|
-
return resolveAttributeValueCall(this.#transport, attributeId, query, options, signal);
|
|
385
|
-
}
|
|
386
|
-
/** "Is this phrase an attribute or a value?" — see {@link searchVocabularyRequest}. */
|
|
387
|
-
searchVocabulary(query, options, signal) {
|
|
388
|
-
return searchVocabularyRequest(this.#transport, query, options, signal);
|
|
389
|
-
}
|
|
390
|
-
/** "I have words — what do they mean, and what stands behind them?" — see {@link resolvePhrases}. */
|
|
391
|
-
resolve(phrases, scope) {
|
|
392
|
-
return resolvePhrases(this.#transport, phrases, scope);
|
|
393
|
-
}
|
|
394
364
|
/**
|
|
395
|
-
* THE QUESTION: "which
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
402
|
-
* and {@link specificationFacets} first if you do not know the canonical
|
|
403
|
-
* tokens. Guessing one no longer returns a silently empty answer: an
|
|
404
|
-
* unresolvable criterion means the query NEVER RAN and the response says so —
|
|
405
|
-
* read {@link BySpecResponse.unresolvedCriteria} before treating an empty
|
|
406
|
-
* `matches` as "nothing qualifies". A PAGE, NOT A CORPUS, unusually so:
|
|
407
|
-
* `totalMatches` is the returned sample's size under `limit`, not a corpus
|
|
408
|
-
* count. Each `spec` is an `attribute:value` criterion built with
|
|
409
|
-
* `specCriterion` / `certificationProgrammeCriterion`; a variant must satisfy
|
|
410
|
-
* ALL of them, and each match carries per-criterion trust (`confidence` +
|
|
411
|
-
* `sourceBasis`). NUMBER-valued specs take BOUNDS, not values — pass
|
|
412
|
-
* `options.ranges` built with `specRangeCriterion("light_reflectance_value",
|
|
413
|
-
* { min: 60 })`; bounds are inclusive, at least one is required, and a
|
|
414
|
-
* non-numeric stored value is excluded rather than read as zero.
|
|
365
|
+
* THE QUESTION: "which attribute means this phrase?" or "what could a
|
|
366
|
+
* <category> be specified by?" (GET `/api/v1/catalog/attributes`). One page of
|
|
367
|
+
* attribute definitions, browsed or found by id, name, misspelling or
|
|
368
|
+
* meaning, scoped by `categoryIds`, `blockIds` and `filterableOnly`. Pass an
|
|
369
|
+
* item's `id` with one of its `filterOps` to
|
|
370
|
+
* {@link MaterialGraphClient.listVariants}; follow `pageInfo.endCursor` for
|
|
371
|
+
* the next page.
|
|
415
372
|
*/
|
|
416
|
-
|
|
417
|
-
return this.#
|
|
418
|
-
spec: Array.isArray(spec) ? spec : [spec],
|
|
419
|
-
...(options?.ranges?.length ? { specRange: options.ranges } : {}),
|
|
420
|
-
limit: options?.limit,
|
|
421
|
-
}, signal);
|
|
373
|
+
async listAttributes(options, signal) {
|
|
374
|
+
return await listAttributesCall(this.#transport, options, signal);
|
|
422
375
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
* The source of every `categoryKey` / product-type id the other lenses accept
|
|
427
|
-
* (`search({ category })`, `colours.profiles()`,
|
|
428
|
-
* {@link MaterialGraphClient.applicableSpecs}). Discover, never hand-write.
|
|
429
|
-
*/
|
|
430
|
-
taxonomy(signal) {
|
|
431
|
-
return this.#get("get_category_taxonomy", undefined, signal);
|
|
376
|
+
/** "Is this phrase an attribute or a value?" — see {@link searchVocabularyRequest}. */
|
|
377
|
+
async searchVocabulary(query, options, signal) {
|
|
378
|
+
return await searchVocabularyRequest(this.#transport, query, options, signal);
|
|
432
379
|
}
|
|
380
|
+
/** "I have words — what do they mean, and what stands behind them?" — see {@link resolvePhrases}. */
|
|
381
|
+
async resolve(phrases, scope) {
|
|
382
|
+
return await resolvePhrases(this.#transport, phrases, scope);
|
|
383
|
+
}
|
|
384
|
+
// Hard-specification search (formerly `bySpec()`, GET
|
|
385
|
+
// `/api/v1/search/specifications`) moved to {@link MaterialGraphClient.listVariants}
|
|
386
|
+
// (MG-2222): each `attribute:value` criterion is one `filters` condition —
|
|
387
|
+
// `{field: attributeId, op: "in", values: [...]}` in `filters.terms` for a
|
|
388
|
+
// term, `{field: attributeId, op: "gte"/"lte"/etc, value}` in
|
|
389
|
+
// `filters.numbers` for a number — and every condition across the
|
|
390
|
+
// kind-grouped `filters` object must match. Use `codes.advisory()` when
|
|
391
|
+
// the real question is what a space demands, and {@link specificationFacets}
|
|
392
|
+
// first if you do not know the canonical tokens.
|
|
393
|
+
// ── Coverage + meta ──────────────────────────────────────────────────────────
|
|
433
394
|
/**
|
|
434
395
|
* Exact current primary-type status counts by retained source category path.
|
|
435
396
|
* `comparisonThreshold` is a reporting cutoff only: it never promotes a
|
|
436
397
|
* proposal into an accepted category.
|
|
437
398
|
*/
|
|
438
|
-
productTypeCoverage(options, signal) {
|
|
439
|
-
return this.#get("get_product_type_status_coverage", options, signal);
|
|
399
|
+
async productTypeCoverage(options, signal) {
|
|
400
|
+
return await this.#get("get_product_type_status_coverage", options, signal);
|
|
440
401
|
}
|
|
441
402
|
/**
|
|
442
403
|
* THE QUESTION: "what is this key allowed to do?" Check `scopes` before
|
|
443
404
|
* offering a capability: the write surfaces need `mg:ingest` / `mg:compose`,
|
|
444
405
|
* and `mg:admin` unlocks extra evidence fields.
|
|
445
406
|
*/
|
|
446
|
-
whoami(signal) {
|
|
447
|
-
return this.#get("whoami", undefined, signal);
|
|
407
|
+
async whoami(signal) {
|
|
408
|
+
return await this.#get("whoami", undefined, signal);
|
|
448
409
|
}
|
|
449
410
|
// ── Pairings / demand ────────────────────────────────────────────────────────
|
|
450
411
|
/** What completes a scheme already part-chosen. See {@link coordinateCall}. */
|
|
451
|
-
coordinate(input, signal) {
|
|
452
|
-
return coordinateCall(this.#transport, input, signal);
|
|
412
|
+
async coordinate(input, signal) {
|
|
413
|
+
return await coordinateCall(this.#transport, input, signal);
|
|
453
414
|
}
|
|
454
415
|
/**
|
|
455
416
|
* THE QUESTION: "how much is this material actually specified, and what gets
|
|
@@ -460,8 +421,8 @@ export class MaterialGraphClient extends CatalogueClient {
|
|
|
460
421
|
* {@link MaterialGraphClient.pairings} for a presentable rail. A null `demand`
|
|
461
422
|
* means UNREAD, never zero. Provide EXACTLY ONE of `variantId` or `material`.
|
|
462
423
|
*/
|
|
463
|
-
demand(params, signal) {
|
|
464
|
-
return this.#get("get_material_demand", {
|
|
424
|
+
async demand(params, signal) {
|
|
425
|
+
return await this.#get("get_material_demand", { material: params.material, variantId: params.variantId }, signal);
|
|
465
426
|
}
|
|
466
427
|
/**
|
|
467
428
|
* THE QUESTION: "for each of these picks I already hold, how much momentum does
|
|
@@ -490,8 +451,8 @@ export class MaterialGraphClient extends CatalogueClient {
|
|
|
490
451
|
* (r) => r.state === "available" && r.momentum.state === "rising",
|
|
491
452
|
* );
|
|
492
453
|
*/
|
|
493
|
-
demandBatch(input, signal) {
|
|
494
|
-
return this.#post("get_demand_batch", input, signal);
|
|
454
|
+
async demandBatch(input, signal) {
|
|
455
|
+
return await this.#post("get_demand_batch", input, signal);
|
|
495
456
|
}
|
|
496
457
|
// ── Codes (advisory building-code compliance) ────────────────────────────────
|
|
497
458
|
/**
|
|
@@ -503,8 +464,8 @@ export class MaterialGraphClient extends CatalogueClient {
|
|
|
503
464
|
* `mg.codes.advisory()` in new code, and start at `mg.codes.context()` to
|
|
504
465
|
* discover every accepted context value. `unverified` is not a pass.
|
|
505
466
|
*/
|
|
506
|
-
codeAdvisory(input, signal) {
|
|
507
|
-
return this.codes.advisory(input, signal);
|
|
467
|
+
async codeAdvisory(input, signal) {
|
|
468
|
+
return await this.codes.advisory(input, signal);
|
|
508
469
|
}
|
|
509
470
|
// ── Colour helpers (extract) ─────────────────────────────────────────────────
|
|
510
471
|
/**
|
|
@@ -514,16 +475,15 @@ export class MaterialGraphClient extends CatalogueClient {
|
|
|
514
475
|
* {@link MaterialGraphClient.byColour}. Instead use
|
|
515
476
|
* {@link MaterialGraphClient.match} for the MATERIALS in the photo.
|
|
516
477
|
*/
|
|
517
|
-
extractPalette(input, signal) {
|
|
518
|
-
return this.#post("extract_image_palette", input, signal);
|
|
478
|
+
async extractPalette(input, signal) {
|
|
479
|
+
return await this.#post("extract_image_palette", input, signal);
|
|
519
480
|
}
|
|
520
|
-
// ── Catalog (facets /
|
|
481
|
+
// ── Catalog (facets / glossary) ─────────────────────────────────────────────
|
|
521
482
|
/**
|
|
522
483
|
* THE QUESTION: "what can I even filter on, and what values does the corpus
|
|
523
484
|
* actually hold?" The start of every spec-driven workflow. Instead use
|
|
524
|
-
* {@link MaterialGraphClient.
|
|
525
|
-
* {@link MaterialGraphClient.
|
|
526
|
-
* carry, {@link MaterialGraphClient.schema} for the definition.
|
|
485
|
+
* {@link MaterialGraphClient.listAttributes} with `categoryIds` for what a
|
|
486
|
+
* product type COULD carry, {@link MaterialGraphClient.schema} for the definition.
|
|
527
487
|
*
|
|
528
488
|
* Discover the live specification vocabulary (GET
|
|
529
489
|
* `/api/v1/catalog/specifications/facets`) — the facetable spec attributes that
|
|
@@ -532,57 +492,18 @@ export class MaterialGraphClient extends CatalogueClient {
|
|
|
532
492
|
* exists: LEED, GREENGUARD, ASTM E84 Class A, FloorScore, EPDs all surface here
|
|
533
493
|
* with counts. Includes the virtual `certification_programme` facet (its values
|
|
534
494
|
* are programme names). Learn an `attribute:value` here, then reuse it as a
|
|
535
|
-
* {@link
|
|
495
|
+
* {@link MaterialGraphClient.listVariants} filter leaf or a {@link search}
|
|
496
|
+
* `filters` entry. NOTE: continuous
|
|
536
497
|
* numeric specs (e.g. `slip_resistance_dcof`, a 0–1 DCOF range) are NOT
|
|
537
498
|
* token-facetable and do not appear here — read those per-attribute.
|
|
538
499
|
*/
|
|
539
|
-
specificationFacets(signal) {
|
|
540
|
-
return this.#get("list_spec_facets", undefined, signal);
|
|
541
|
-
}
|
|
542
|
-
/**
|
|
543
|
-
* List the live value distribution for ONE canonical attribute (GET
|
|
544
|
-
* `/api/v1/catalog/attributes/{attributeId}/values`), ordered by cross-brand
|
|
545
|
-
* reach with variant + brand counts. The drill-in companion to
|
|
546
|
-
* {@link specificationFacets} — e.g. every certification programme on record,
|
|
547
|
-
* or every fire classification and how many variants carry each.
|
|
548
|
-
*/
|
|
549
|
-
attributeValues(attributeId, signal) {
|
|
550
|
-
return this.#get("list_attribute_values", undefined, signal, {
|
|
551
|
-
attributeId,
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
/**
|
|
555
|
-
* THE QUESTION: "what specs COULD a material of this type carry?" — the
|
|
556
|
-
* template, not the data. Use it to know which absences are meaningful; instead
|
|
557
|
-
* use {@link MaterialGraphClient.specificationFacets} for what the corpus holds
|
|
558
|
-
* and {@link MaterialGraphClient.materialBlocks} for one material.
|
|
559
|
-
*
|
|
560
|
-
* @param key A canonical taxonomy key from {@link MaterialGraphClient.taxonomy}.
|
|
561
|
-
*/
|
|
562
|
-
applicableSpecs(key, signal) {
|
|
563
|
-
return this.#get("get_applicable_specs", undefined, signal, { key });
|
|
564
|
-
}
|
|
565
|
-
/**
|
|
566
|
-
* THE QUESTION: "what does 'DCOF' MEAN?" — one term explained, for a human.
|
|
567
|
-
* Explanation, not retrieval: instead use
|
|
568
|
-
* {@link MaterialGraphClient.searchVocabulary} to FIND a token and
|
|
569
|
-
* {@link MaterialGraphClient.attributeValues} for the values it takes.
|
|
570
|
-
*/
|
|
571
|
-
glossary(term, signal) {
|
|
572
|
-
return this.#get("explain_material_term", undefined, signal, { term });
|
|
500
|
+
async specificationFacets(signal) {
|
|
501
|
+
return await this.#get("list_spec_facets", undefined, signal);
|
|
573
502
|
}
|
|
574
503
|
// ── Brands ───────────────────────────────────────────────────────────────────
|
|
575
504
|
/** "Whose catalogs are in here, and how big is each?" — {@link listBrands}. */
|
|
576
|
-
brands(options = {}, signal) {
|
|
577
|
-
return listBrands(this.#transport, options, signal);
|
|
578
|
-
}
|
|
579
|
-
/** "Who is this brand, and what do they claim?" — {@link brandProfile}. */
|
|
580
|
-
brand(brandSlug, options, signal) {
|
|
581
|
-
return brandProfile(this.#transport, brandSlug, options, signal);
|
|
582
|
-
}
|
|
583
|
-
/** "This maker's whole range, the way a fan deck reads" — {@link brandColourDeck}. */
|
|
584
|
-
brandColourDeck(brandSlug, signal) {
|
|
585
|
-
return brandColourDeck(this.#transport, brandSlug, signal);
|
|
505
|
+
async brands(options = {}, signal) {
|
|
506
|
+
return await listBrands(this.#transport, options, signal);
|
|
586
507
|
}
|
|
587
508
|
// ── Runs (the hosted agentic surface) ────────────────────────────────────────
|
|
588
509
|
/**
|
|
@@ -591,8 +512,8 @@ export class MaterialGraphClient extends CatalogueClient {
|
|
|
591
512
|
* text/markdown, and images — the server classifies each) or the legacy
|
|
592
513
|
* `{ brief, references }` shape. Requires the `mg:ingest` scope.
|
|
593
514
|
*/
|
|
594
|
-
uploadSourceMaterial(input, signal) {
|
|
595
|
-
return uploadSourceMaterial(this.#transport, input, signal);
|
|
515
|
+
async uploadSourceMaterial(input, signal) {
|
|
516
|
+
return await uploadSourceMaterial(this.#transport, input, signal);
|
|
596
517
|
}
|
|
597
518
|
/**
|
|
598
519
|
* Read back an uploaded batch (GET `/api/v1/source-material/{batchId}`): every
|
|
@@ -602,90 +523,30 @@ export class MaterialGraphClient extends CatalogueClient {
|
|
|
602
523
|
* immediately. A batch you do not own raises the same 404 as one that does not
|
|
603
524
|
* exist. Requires the `mg:compose` scope.
|
|
604
525
|
*/
|
|
605
|
-
sourceMaterialBatch(batchId, signal) {
|
|
606
|
-
return getSourceMaterialBatchCall(this.#transport, batchId, signal);
|
|
607
|
-
}
|
|
608
|
-
/**
|
|
609
|
-
* THE QUESTION: "what can the hosted agentic surface be asked to DO?" Start
|
|
610
|
-
* here before {@link MaterialGraphClient.createRun}: each capability carries its
|
|
611
|
-
* live input/output schemas, scopes and side-effect class, so nothing about a
|
|
612
|
-
* Run need be hardcoded.
|
|
613
|
-
*/
|
|
614
|
-
capabilities(signal) {
|
|
615
|
-
return capabilitiesRun(this.#transport, signal);
|
|
526
|
+
async sourceMaterialBatch(batchId, signal) {
|
|
527
|
+
return await getSourceMaterialBatchCall(this.#transport, batchId, signal);
|
|
616
528
|
}
|
|
617
529
|
/**
|
|
618
530
|
* THE QUESTION: "do a whole job for me" — the ASYNC lens. Everything else here
|
|
619
531
|
* answers in one round trip; a Run may suspend for human input and finish
|
|
620
532
|
* minutes later. Follow with {@link MaterialGraphClient.streamRunEvents} (live)
|
|
621
|
-
* or {@link MaterialGraphClient.run} (poll)
|
|
622
|
-
* {@link MaterialGraphClient.resumeRun}; pick the capability from
|
|
623
|
-
* {@link MaterialGraphClient.capabilities}. Pass `idempotencyKey` so a retry
|
|
533
|
+
* or {@link MaterialGraphClient.run} (poll). Pass `idempotencyKey` so a retry
|
|
624
534
|
* replays rather than duplicates.
|
|
625
535
|
*/
|
|
626
|
-
createRun(body, signal) {
|
|
627
|
-
return createRun(this.#transport, body, signal);
|
|
536
|
+
async createRun(body, signal) {
|
|
537
|
+
return await createRun(this.#transport, body, signal);
|
|
628
538
|
}
|
|
629
539
|
/**
|
|
630
540
|
* THE QUESTION: "where has this Run got to?" — the caller-owned, redacted
|
|
631
541
|
* ledger record. Polling; prefer {@link MaterialGraphClient.streamRunEvents}
|
|
632
|
-
* when a human is waiting.
|
|
633
|
-
* asking you something (see {@link MaterialGraphClient.resumeRun}).
|
|
542
|
+
* when a human is waiting.
|
|
634
543
|
*/
|
|
635
|
-
run(runId, signal) {
|
|
636
|
-
return getRun(this.#transport, runId, signal);
|
|
637
|
-
}
|
|
638
|
-
/**
|
|
639
|
-
* THE QUESTION: "which Runs are mine?" — your own Runs, newest first, paged
|
|
640
|
-
* (GET `/api/v1/runs`). This is how a client that lost a Run id finds its work
|
|
641
|
-
* again: `{ status: "suspended" }` returns the Runs still waiting on an
|
|
642
|
-
* answer, whose ids you can then feed to {@link MaterialGraphClient.resumeRun}.
|
|
643
|
-
*
|
|
644
|
-
* Only your own Runs are ever returned. Page by following `nextCursor` until
|
|
645
|
-
* it is ABSENT — a full page is not the signal to stop.
|
|
646
|
-
*/
|
|
647
|
-
listRuns(options) {
|
|
648
|
-
return listRuns(this.#transport, options);
|
|
649
|
-
}
|
|
650
|
-
/**
|
|
651
|
-
* Export a completed compose Run's scheme as a finish schedule — one row per
|
|
652
|
-
* slot, every attribute value carrying its source and verification state
|
|
653
|
-
* (GET `/api/v1/runs/{runId}/schedule`). Unknown values are explicit
|
|
654
|
-
* `missing` cells, never blanks. The `.xlsx` form is a direct-URL download:
|
|
655
|
-
* `GET /api/v1/runs/{runId}/schedule.xlsx` with the same bearer key.
|
|
656
|
-
*/
|
|
657
|
-
runSchedule(runId, options) {
|
|
658
|
-
return getRunSchedule(this.#transport, runId, options);
|
|
544
|
+
async run(runId, signal) {
|
|
545
|
+
return await getRun(this.#transport, runId, signal);
|
|
659
546
|
}
|
|
660
547
|
/** Follow a verdict cell's citation handle to its canonical claim source. */
|
|
661
|
-
citation(citationId, signal) {
|
|
662
|
-
return this.#get("get_verdict_citation", undefined, signal, { citationId });
|
|
663
|
-
}
|
|
664
|
-
/**
|
|
665
|
-
* Resume a suspended Run (POST `/api/v1/runs/{runId}/resume`).
|
|
666
|
-
*
|
|
667
|
-
* The third argument accepts either an `AbortSignal` (the published form) or
|
|
668
|
-
* {@link ResumeRunOptions}, whose `stepId` guards against resuming a step the
|
|
669
|
-
* run has already moved past — the API answers 409 on a mismatch (MG-608).
|
|
670
|
-
*/
|
|
671
|
-
resumeRun(runId, resumeData, signalOrOptions) {
|
|
672
|
-
return resumeRun(this.#transport, runId, resumeData, signalOrOptions);
|
|
673
|
-
}
|
|
674
|
-
/**
|
|
675
|
-
* THE QUESTION: "stop this Run." Requests DURABLE cancellation — the Run
|
|
676
|
-
* acknowledges and unwinds; the call returning does not mean it has stopped.
|
|
677
|
-
* Poll {@link MaterialGraphClient.run} for the terminal state.
|
|
678
|
-
*/
|
|
679
|
-
cancelRun(runId, signal) {
|
|
680
|
-
return cancelRun(this.#transport, runId, signal);
|
|
681
|
-
}
|
|
682
|
-
/** Option B from a composed Run, along one axis. See {@link varySchemeCall}. */
|
|
683
|
-
varyScheme(body, signal) {
|
|
684
|
-
return varySchemeCall(this.#transport, body, signal);
|
|
685
|
-
}
|
|
686
|
-
/** Ranked candidate pools for up to 24 slots. See {@link slotPoolsCall}. */
|
|
687
|
-
slotPools(body, signal) {
|
|
688
|
-
return slotPoolsCall(this.#transport, body, signal);
|
|
548
|
+
async citation(citationId, signal) {
|
|
549
|
+
return await this.#get("get_verdict_citation", undefined, signal, { citationId });
|
|
689
550
|
}
|
|
690
551
|
/**
|
|
691
552
|
* Stream ordered Run events as an async iterator (GET
|
|
@@ -695,42 +556,11 @@ export class MaterialGraphClient extends CatalogueClient {
|
|
|
695
556
|
streamRunEvents(runId, options) {
|
|
696
557
|
return streamRunEvents(this.#transport, runId, options);
|
|
697
558
|
}
|
|
698
|
-
// ── Projects (the persistent Material Box entity) ────────────────────────────
|
|
699
|
-
/**
|
|
700
|
-
* Create a persistent project owned by the caller (POST `/api/v1/projects`).
|
|
701
|
-
* Returns the freshly assembled state (an empty event log). Requires the
|
|
702
|
-
* `mg:ingest` scope.
|
|
703
|
-
*/
|
|
704
|
-
createProject(body = {}, signal) {
|
|
705
|
-
return createProjectCall(this.#transport, body, signal);
|
|
706
|
-
}
|
|
707
|
-
/**
|
|
708
|
-
* THE QUESTION: "what has happened on this project?" — the append-only event log
|
|
709
|
-
* FOLDED into a read model, plus the raw `events`. Read the folded collections;
|
|
710
|
-
* the log is there for audit.
|
|
711
|
-
*/
|
|
712
|
-
getProject(projectId, signal) {
|
|
713
|
-
return getProjectCall(this.#transport, projectId, signal);
|
|
714
|
-
}
|
|
715
|
-
/**
|
|
716
|
-
* Append one event to a project's append-only process trail (POST
|
|
717
|
-
* `/api/v1/projects/{projectId}/events`). Requires the `mg:ingest` scope.
|
|
718
|
-
*/
|
|
719
|
-
appendProjectEvent(projectId, body, signal) {
|
|
720
|
-
return appendProjectEventCall(this.#transport, projectId, body, signal);
|
|
721
|
-
}
|
|
722
|
-
/**
|
|
723
|
-
* THE QUESTION: "what Boxes do I have?" Scoped to the authenticated principal —
|
|
724
|
-
* another key's projects are invisible, not forbidden.
|
|
725
|
-
*/
|
|
726
|
-
listProjects(signal) {
|
|
727
|
-
return listProjectsCall(this.#transport, signal);
|
|
728
|
-
}
|
|
729
559
|
/**
|
|
730
560
|
* Collect Run events until a terminal event, the deadline, or the stream ends
|
|
731
561
|
* — the bounded events-log pattern (a single pass over {@link streamRunEvents}).
|
|
732
562
|
*/
|
|
733
|
-
drainRunEvents(runId, options) {
|
|
734
|
-
return drainRunEvents(this.#transport, runId, options);
|
|
563
|
+
async drainRunEvents(runId, options) {
|
|
564
|
+
return await drainRunEvents(this.#transport, runId, options);
|
|
735
565
|
}
|
|
736
566
|
}
|