@instruments/materialgraph 0.9.1 → 0.11.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/brands-client.d.ts +48 -0
- package/brands-client.js +45 -0
- package/browse-types.d.ts +147 -0
- package/browse-types.js +1 -0
- package/by-colour-types.d.ts +105 -5
- package/client-browse.d.ts +13 -3
- package/client-browse.js +12 -2
- package/client-exploration.d.ts +9 -0
- package/client-exploration.js +7 -0
- package/client-source-material-comments.d.ts +51 -0
- package/client-source-material-comments.js +40 -0
- package/client.d.ts +64 -71
- package/client.js +90 -78
- package/colour-aggregate-types.d.ts +58 -0
- package/colours-client.d.ts +8 -2
- package/colours-client.js +15 -2
- package/composition-client.d.ts +33 -0
- package/composition-client.js +27 -0
- package/composition-types.d.ts +46 -0
- package/coordinate-client.d.ts +23 -0
- package/coordinate-client.js +25 -0
- package/errors.js +24 -8
- package/exploration-types.d.ts +110 -0
- package/exploration-types.js +1 -0
- package/fan-deck-types.d.ts +42 -0
- package/fan-deck-types.js +9 -0
- package/http-transport.js +24 -5
- package/index.d.ts +7 -3
- package/index.js +2 -2
- package/match-stream-types.d.ts +1 -1
- package/match-stream-types.js +16 -3
- package/match-stream.js +14 -4
- package/material-types.d.ts +1 -1
- package/operations.d.ts +1 -1
- package/operations.js +187 -26
- package/package.json +1 -1
- package/palette-search-types.d.ts +31 -0
- package/resolve-client.d.ts +22 -3
- package/resolve-client.js +31 -4
- package/resolve-types.d.ts +70 -1
- package/run-events.d.ts +1 -1
- package/run-events.js +4 -1
- package/run-types.d.ts +132 -0
- package/runs.d.ts +35 -1
- package/runs.js +69 -5
- package/schedule-types.d.ts +128 -0
- package/schema-resource-types.d.ts +1 -1
- package/search-refinement-types.d.ts +39 -4
- package/search-request-types.d.ts +172 -0
- package/search-request-types.js +1 -0
- package/search-result-validation.js +21 -4
- package/slot-pool-types.d.ts +370 -0
- package/slot-pool-types.js +1 -0
- package/source-material-validation.d.ts +5 -1
- package/source-material-validation.js +114 -5
- package/spec-facet-types.d.ts +53 -0
- package/spec-facet-types.js +7 -0
- package/specifications.d.ts +26 -0
- package/specifications.js +32 -0
- package/sse.js +3 -1
- package/suggest-types.js +3 -1
- package/types.d.ts +176 -216
- package/validation.d.ts +12 -0
- package/validation.js +23 -0
package/client.d.ts
CHANGED
|
@@ -1,25 +1,31 @@
|
|
|
1
|
-
import { type RateLimit } from "./errors.js";
|
|
2
1
|
import type { MaterialGraphClientOptions } from "./client-config.js";
|
|
2
|
+
import { type RateLimit } from "./errors.js";
|
|
3
3
|
export * from "./client-config.js";
|
|
4
4
|
import { type BrowseNamespace } from "./client-browse.js";
|
|
5
|
+
import { type ExplorationNamespace } from "./client-exploration.js";
|
|
5
6
|
export type { BrowseNamespace } from "./client-browse.js";
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
import type { AppendProjectEventRequest, CreateProjectRequest, ProjectEventReceipt, ProjectListResponse, ProjectState } from "./project-types.js";
|
|
10
|
-
import type { VarySchemesRequest, VarySchemesResponse } from "./composition-types.js";
|
|
11
|
-
import { CodesClient } from "./codes-client.js";
|
|
12
|
-
import { ColoursClient } from "./colours-client.js";
|
|
13
|
-
import type { CodeAdvisoryInput, CodeAdvisoryResponse } from "./codes-types.js";
|
|
7
|
+
export type { ExplorationNamespace } from "./client-exploration.js";
|
|
8
|
+
import { type SourceMaterialCommentsNamespace } from "./client-source-material-comments.js";
|
|
9
|
+
export type { SourceMaterialCommentsNamespace } from "./client-source-material-comments.js";
|
|
14
10
|
import type { AssociatedOptions } from "./association-types.js";
|
|
15
11
|
import type { BrandCatalogListPage, BrandsOptions } from "./brand-types.js";
|
|
12
|
+
import type { ByColourParams, ByColourResponse } from "./by-colour-types.js";
|
|
13
|
+
import { CodesClient } from "./codes-client.js";
|
|
14
|
+
import type { CodeAdvisoryInput, CodeAdvisoryResponse } from "./codes-types.js";
|
|
15
|
+
import { ColoursClient } from "./colours-client.js";
|
|
16
|
+
import type { VarySchemesRequest, VarySchemesResponse } from "./composition-types.js";
|
|
17
|
+
import type { BatchId, ProjectId, RunId, VariantId } from "./identifiers.js";
|
|
18
|
+
import type { MatchStreamEvent } from "./match-stream-types.js";
|
|
19
|
+
import type { MatchInput, MatchResponse } from "./match-types.js";
|
|
16
20
|
import type { MaterialAssetProjection } from "./material-asset-types.js";
|
|
17
21
|
import type { MaterialBlockProjection } from "./material-block-types.js";
|
|
22
|
+
import type { AppendProjectEventRequest, CreateProjectRequest, ProjectEventReceipt, ProjectListResponse, ProjectState } from "./project-types.js";
|
|
23
|
+
import { resolvePhrasesRequest as resolvePhrases } from "./resolve-client.js";
|
|
24
|
+
import type { CapabilityManifestResponse, CreatePublicRunRequest, CreatePublicRunResponse, DrainRunEventsOptions, ListRunsOptions, PublicRunListResponse, PublicRunResponse, ResumeRunOptions, RunEvent, SourceMaterialBatchDetail, SourceMaterialBatchReceipt, StreamRunEventsOptions, UploadSourceMaterialInput } from "./run-types.js";
|
|
25
|
+
import type { FinishScheduleResponse, GetRunScheduleOptions } from "./schedule-types.js";
|
|
18
26
|
import type { SchemaResource, SchemaResourceResponse } from "./schema-resource-types.js";
|
|
19
|
-
import type {
|
|
20
|
-
import type { ByColourParams, ByColourResponse } from "./by-colour-types.js";
|
|
27
|
+
import type { SlotPoolsRequest, SlotPoolsResponse } from "./slot-pool-types.js";
|
|
21
28
|
import type { ApplicableSpecsResponse, BrandOptions, BrandProfileResponse, BySpecOptions, BySpecResponse, ColourFacetsResponse, CoordinateInput, CoordinateResponse, DemandBatchInput, DemandBatchResponse, DemandParams, DemandResponse, ExtractPaletteInput, ExtractPaletteResponse, GlossaryTermResponse, MaterialResponse, MaterialsBatchDetailResponse, MaterialsBatchGetOptions, MaterialsBatchOptions, MaterialsBatchTileResponse, PairingsOptions, PairingsResponse, ResolveAttributeOptions, ResolveAttributeResponse, ResolveAttributeValueOptions, ResolveAttributeValueResponse, ResolveColourResponse, SearchGetParams, SearchInput, SearchResponse, SiblingsResponse, SpecFacetsDistributionResponse, SpecFacetsListResponse, SuggestColourResponse, SuggestOptions, SuggestResponse, TaxonomyResponse, VocabularySearchOptions, WhoamiResponse } from "./types.js";
|
|
22
|
-
import type { MatchInput, MatchResponse } from "./match-types.js";
|
|
23
29
|
/**
|
|
24
30
|
* The MaterialGraph client — every lens on the graph, on one object.
|
|
25
31
|
*
|
|
@@ -60,14 +66,21 @@ export declare class MaterialGraphClient {
|
|
|
60
66
|
#private;
|
|
61
67
|
readonly baseUrl: string;
|
|
62
68
|
/**
|
|
63
|
-
* THE QUESTION: "show me everything
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
69
|
+
* THE QUESTION: "show me everything in this category / this brand, in a plain
|
|
70
|
+
* order." No query, no relevance, no ranking. `browse(params)` is one page;
|
|
71
|
+
* `browse.pages(params)` walks them all.
|
|
72
|
+
*
|
|
73
|
+
* `sort` is optional (`name` A→Z by default, `recent` for newest first, plus
|
|
74
|
+
* the five colour ramps), `types`/`brands`/`corpusScope` narrow it, and
|
|
75
|
+
* `count: true` returns the total so a listing can say how many things it is
|
|
76
|
+
* listing without walking every page. `results.length` remains a PAGE.
|
|
67
77
|
*
|
|
68
78
|
* Instead use {@link MaterialGraphClient.byColour} for materials NEAR a colour,
|
|
69
79
|
* {@link MaterialGraphClient.search} when there is anything to rank against,
|
|
70
80
|
* and `colours.profiles()` for a category's palette rather than its members.
|
|
81
|
+
*
|
|
82
|
+
* @example A category listing that can state its own size
|
|
83
|
+
* const page = await client.browse({ types: "tile_surfaces", count: true });
|
|
71
84
|
*/
|
|
72
85
|
readonly browse: BrowseNamespace;
|
|
73
86
|
/**
|
|
@@ -93,6 +106,14 @@ export declare class MaterialGraphClient {
|
|
|
93
106
|
* likeness, never a declared colour specification.
|
|
94
107
|
*/
|
|
95
108
|
readonly colours: ColoursClient;
|
|
109
|
+
/** Discover honest graph questions, then traverse one explicit operator. */
|
|
110
|
+
readonly exploration: ExplorationNamespace;
|
|
111
|
+
/**
|
|
112
|
+
* THE QUESTION: "what did people say about this uploaded file, and record what
|
|
113
|
+
* they said." Names on these remarks are REPORTED, never verified — see
|
|
114
|
+
* {@link SourceMaterialCommentsNamespace}.
|
|
115
|
+
*/
|
|
116
|
+
readonly sourceMaterialComments: SourceMaterialCommentsNamespace;
|
|
96
117
|
constructor(options: MaterialGraphClientOptions);
|
|
97
118
|
get lastRateLimit(): RateLimit | null;
|
|
98
119
|
/**
|
|
@@ -172,8 +193,7 @@ export declare class MaterialGraphClient {
|
|
|
172
193
|
* {@link MaterialGraphClient.browse} to walk by lightness/vividness, and
|
|
173
194
|
* {@link MaterialGraphClient.search} when colour is one signal among many.
|
|
174
195
|
* Report matches as visual likeness, never a stated colour specification.
|
|
175
|
-
* `family` gates
|
|
176
|
-
* alone crosses a hue boundary; a gated page can be shorter than `limit`.
|
|
196
|
+
* `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.
|
|
177
197
|
*/
|
|
178
198
|
byColour(params: ByColourParams, signal?: AbortSignal): Promise<ByColourResponse>;
|
|
179
199
|
/**
|
|
@@ -326,33 +346,29 @@ export declare class MaterialGraphClient {
|
|
|
326
346
|
resolveAttributeValue(attributeId: string, query: string, options?: ResolveAttributeValueOptions, signal?: AbortSignal): Promise<ResolveAttributeValueResponse>;
|
|
327
347
|
/** "Is this phrase an attribute or a value?" — see {@link searchVocabularyRequest}. */
|
|
328
348
|
searchVocabulary(query: string, options?: VocabularySearchOptions, signal?: AbortSignal): Promise<import("./catalog-discovery-types.js").VocabularySearchResponse>;
|
|
329
|
-
/** "I have words — what do they mean
|
|
330
|
-
resolve(phrases: string[],
|
|
349
|
+
/** "I have words — what do they mean, and what stands behind them?" — see {@link resolvePhrases}. */
|
|
350
|
+
resolve(phrases: string[], scope?: Parameters<typeof resolvePhrases>[2]): Promise<import("./resolve-types.js").ResolveResponse>;
|
|
331
351
|
/**
|
|
332
352
|
* THE QUESTION: "which materials, from ANYONE, are ASTM E84 Class A AND
|
|
333
|
-
* GREENGUARD-certified?" — hard specifications, no ranking, every brand at
|
|
334
|
-
* whatever each called the value in source.
|
|
353
|
+
* GREENGUARD-certified?" — hard specifications, no ranking, every brand at
|
|
354
|
+
* once whatever each called the value in source. The value-anchored,
|
|
355
|
+
* spec-only primitive (GET `/api/v1/search/specifications`).
|
|
335
356
|
*
|
|
336
357
|
* Instead use `search({ filters })` when the spec merely GATES a ranked
|
|
337
358
|
* question, `codes.advisory()` when the real question is what a space demands,
|
|
338
|
-
* and {@link
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
*
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
* `sourceBasis`). Answers "which materials, from anyone, are ASTM E84 Class A
|
|
352
|
-
* AND GREENGUARD-certified?" Build the strings with `specCriterion` /
|
|
353
|
-
* `certificationProgrammeCriterion` (e.g.
|
|
354
|
-
* `certificationProgrammeCriterion("GREENGUARD Gold")`); discover the queryable
|
|
355
|
-
* vocabulary with {@link specificationFacets} and {@link attributeValues}.
|
|
359
|
+
* and {@link specificationFacets} first if you do not know the canonical
|
|
360
|
+
* tokens. Guessing one no longer returns a silently empty answer: an
|
|
361
|
+
* unresolvable criterion means the query NEVER RAN and the response says so —
|
|
362
|
+
* read {@link BySpecResponse.unresolvedCriteria} before treating an empty
|
|
363
|
+
* `matches` as "nothing qualifies". A PAGE, NOT A CORPUS, unusually so:
|
|
364
|
+
* `totalMatches` is the returned sample's size under `limit`, not a corpus
|
|
365
|
+
* count. Each `spec` is an `attribute:value` criterion built with
|
|
366
|
+
* `specCriterion` / `certificationProgrammeCriterion`; a variant must satisfy
|
|
367
|
+
* ALL of them, and each match carries per-criterion trust (`confidence` +
|
|
368
|
+
* `sourceBasis`). NUMBER-valued specs take BOUNDS, not values — pass
|
|
369
|
+
* `options.ranges` built with `specRangeCriterion("light_reflectance_value",
|
|
370
|
+
* { min: 60 })`; bounds are inclusive, at least one is required, and a
|
|
371
|
+
* non-numeric stored value is excluded rather than read as zero.
|
|
356
372
|
*/
|
|
357
373
|
bySpec(spec: string | string[], options?: BySpecOptions, signal?: AbortSignal): Promise<BySpecResponse>;
|
|
358
374
|
/**
|
|
@@ -368,17 +384,7 @@ export declare class MaterialGraphClient {
|
|
|
368
384
|
* and `mg:admin` unlocks extra evidence fields.
|
|
369
385
|
*/
|
|
370
386
|
whoami(signal?: AbortSignal): Promise<WhoamiResponse>;
|
|
371
|
-
/**
|
|
372
|
-
* THE QUESTION: "here is my whole scheme so far — what completes it?" The
|
|
373
|
-
* multi-seed form of {@link MaterialGraphClient.pairings}: lift is summed across
|
|
374
|
-
* seeds, so a companion suiting one pick ranks below one suiting several.
|
|
375
|
-
* Instead use `pairings` for a single material and `colours.palette()` when the
|
|
376
|
-
* scheme is COLOURS rather than materials. Check `unresolved` before presenting.
|
|
377
|
-
*
|
|
378
|
-
* Coordinate a palette of already-chosen materials (POST
|
|
379
|
-
* `/api/v1/pairings/coordinate`). Returns demand-lift-ranked companions with
|
|
380
|
-
* colour swatches and an annotate-only `colourFit` (never reorders in v1).
|
|
381
|
-
*/
|
|
387
|
+
/** What completes a scheme already part-chosen. See {@link coordinateCall}. */
|
|
382
388
|
coordinate(input: CoordinateInput, signal?: AbortSignal): Promise<CoordinateResponse>;
|
|
383
389
|
/**
|
|
384
390
|
* THE QUESTION: "how much is this material actually specified, and what gets
|
|
@@ -479,21 +485,12 @@ export declare class MaterialGraphClient {
|
|
|
479
485
|
* {@link MaterialGraphClient.attributeValues} for the values it takes.
|
|
480
486
|
*/
|
|
481
487
|
glossary(term: string, signal?: AbortSignal): Promise<GlossaryTermResponse>;
|
|
482
|
-
/**
|
|
483
|
-
* THE QUESTION: "whose catalogs are in here, and how big is each?" The SDK's
|
|
484
|
-
* one OFFSET-paginated surface: read `meta.total` for the collection size and
|
|
485
|
-
* `meta.hasMore` to keep walking. Instead use {@link MaterialGraphClient.brand}
|
|
486
|
-
* for one brand's profile and trade signals.
|
|
487
|
-
*/
|
|
488
|
+
/** "Whose catalogs are in here, and how big is each?" — {@link listBrands}. */
|
|
488
489
|
brands(options?: BrandsOptions, signal?: AbortSignal): Promise<BrandCatalogListPage>;
|
|
489
|
-
/**
|
|
490
|
-
* THE QUESTION: "who is this brand, and what do they claim?" — profile plus the
|
|
491
|
-
* trade/spec signals ON RECORD. `trade` is keyed by attribute id and an ABSENT
|
|
492
|
-
* key means no value is held — never infer `false`. Instead use
|
|
493
|
-
* {@link MaterialGraphClient.search} to find their materials; this describes the
|
|
494
|
-
* company, not the catalog.
|
|
495
|
-
*/
|
|
490
|
+
/** "Who is this brand, and what do they claim?" — {@link brandProfile}. */
|
|
496
491
|
brand(brandSlug: string, options?: BrandOptions, signal?: AbortSignal): Promise<BrandProfileResponse>;
|
|
492
|
+
/** "This maker's whole range, the way a fan deck reads" — {@link brandColourDeck}. */
|
|
493
|
+
brandColourDeck(brandSlug: string, signal?: AbortSignal): Promise<import("./fan-deck-types.js").BrandFanDeck>;
|
|
497
494
|
/**
|
|
498
495
|
* Upload one atomic source-material batch (POST `/api/v1/source-material`,
|
|
499
496
|
* multipart). Pass a heterogeneous pile via `{ files }` (any mix of PDF,
|
|
@@ -566,14 +563,10 @@ export declare class MaterialGraphClient {
|
|
|
566
563
|
* Poll {@link MaterialGraphClient.run} for the terminal state.
|
|
567
564
|
*/
|
|
568
565
|
cancelRun(runId: RunId, signal?: AbortSignal): Promise<PublicRunResponse>;
|
|
569
|
-
/**
|
|
570
|
-
* Derive an "option B" scheme from a succeeded compose Run along one
|
|
571
|
-
* constraint axis (POST `/api/v1/schemes/vary`). Deterministic and
|
|
572
|
-
* synchronous — the response IS the hydrated scheme (no Run envelope), stamped
|
|
573
|
-
* with axis + source provenance whose `notes` are the variation's receipts.
|
|
574
|
-
* Requires the `mg:read` scope.
|
|
575
|
-
*/
|
|
566
|
+
/** Option B from a composed Run, along one axis. See {@link varySchemeCall}. */
|
|
576
567
|
varyScheme(body: VarySchemesRequest, signal?: AbortSignal): Promise<VarySchemesResponse>;
|
|
568
|
+
/** Ranked candidate pools for up to 24 slots. See {@link slotPoolsCall}. */
|
|
569
|
+
slotPools(body: SlotPoolsRequest, signal?: AbortSignal): Promise<SlotPoolsResponse>;
|
|
577
570
|
/**
|
|
578
571
|
* Stream ordered Run events as an async iterator (GET
|
|
579
572
|
* `/api/v1/runs/{runId}/events`, SSE). Iterates until the stream ends or the
|
package/client.js
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
|
+
import { DEFAULT_BASE_URL, MAX_BATCH_IDS } from "./client-config.js";
|
|
1
2
|
import { MaterialGraphError } from "./errors.js";
|
|
2
3
|
import { HttpTransport } from "./http-transport.js";
|
|
3
4
|
// Aliased to `operation` — the local name every call site here already used.
|
|
4
|
-
import { resolveOperation as operation } from "./operations.js";
|
|
5
|
+
import { resolveOperation as operation, } from "./operations.js";
|
|
5
6
|
import { cancelRun, capabilities as capabilitiesRun, createRun, drainRunEvents, getRun, getRunSchedule, getSourceMaterialBatch as getSourceMaterialBatchCall, listRuns, resumeRun, streamRunEvents, uploadSourceMaterial, } from "./runs.js";
|
|
6
|
-
import { DEFAULT_BASE_URL, MAX_BATCH_IDS } from "./client-config.js";
|
|
7
7
|
// Re-exported whole so `index.ts` and every existing importer keep their path.
|
|
8
8
|
export * from "./client-config.js";
|
|
9
|
-
import { browseQuery, createBrowseNamespace } from "./client-browse.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
9
|
+
import { browseQuery, createBrowseNamespace, } from "./client-browse.js";
|
|
10
|
+
import { createExplorationNamespace, } from "./client-exploration.js";
|
|
11
|
+
import { createSourceMaterialCommentsNamespace, } from "./client-source-material-comments.js";
|
|
12
|
+
import { declaredFinishes, declaredProducts } from "./associations-client.js";
|
|
13
|
+
import { brandColourDeck, brandProfile, listBrands } from "./brands-client.js";
|
|
13
14
|
import { CodesClient } from "./codes-client.js";
|
|
14
15
|
import { ColoursClient } from "./colours-client.js";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
16
|
+
import { slotPools as slotPoolsCall, varyScheme as varySchemeCall, } from "./composition-client.js";
|
|
17
|
+
import { coordinate as coordinateCall } from "./coordinate-client.js";
|
|
18
|
+
import { matchStream as matchStreamCall } from "./match-stream.js";
|
|
19
|
+
import { appendProjectEvent as appendProjectEventCall, createProject as createProjectCall, getProject as getProjectCall, listProjects as listProjectsCall, } from "./projects.js";
|
|
20
|
+
import { resolvePhrasesRequest as resolvePhrases, searchVocabularyRequest, } from "./resolve-client.js";
|
|
17
21
|
import { SCHEMA_RESOURCE_OPERATION_IDS } from "./schema-resource-types.js";
|
|
22
|
+
import { suggestQuery } from "./suggest-types.js";
|
|
18
23
|
/**
|
|
19
24
|
* The MaterialGraph client — every lens on the graph, on one object.
|
|
20
25
|
*
|
|
@@ -54,14 +59,21 @@ import { SCHEMA_RESOURCE_OPERATION_IDS } from "./schema-resource-types.js";
|
|
|
54
59
|
export class MaterialGraphClient {
|
|
55
60
|
baseUrl;
|
|
56
61
|
/**
|
|
57
|
-
* THE QUESTION: "show me everything
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
62
|
+
* THE QUESTION: "show me everything in this category / this brand, in a plain
|
|
63
|
+
* order." No query, no relevance, no ranking. `browse(params)` is one page;
|
|
64
|
+
* `browse.pages(params)` walks them all.
|
|
65
|
+
*
|
|
66
|
+
* `sort` is optional (`name` A→Z by default, `recent` for newest first, plus
|
|
67
|
+
* the five colour ramps), `types`/`brands`/`corpusScope` narrow it, and
|
|
68
|
+
* `count: true` returns the total so a listing can say how many things it is
|
|
69
|
+
* listing without walking every page. `results.length` remains a PAGE.
|
|
61
70
|
*
|
|
62
71
|
* Instead use {@link MaterialGraphClient.byColour} for materials NEAR a colour,
|
|
63
72
|
* {@link MaterialGraphClient.search} when there is anything to rank against,
|
|
64
73
|
* and `colours.profiles()` for a category's palette rather than its members.
|
|
74
|
+
*
|
|
75
|
+
* @example A category listing that can state its own size
|
|
76
|
+
* const page = await client.browse({ types: "tile_surfaces", count: true });
|
|
65
77
|
*/
|
|
66
78
|
browse;
|
|
67
79
|
/**
|
|
@@ -87,6 +99,14 @@ export class MaterialGraphClient {
|
|
|
87
99
|
* likeness, never a declared colour specification.
|
|
88
100
|
*/
|
|
89
101
|
colours;
|
|
102
|
+
/** Discover honest graph questions, then traverse one explicit operator. */
|
|
103
|
+
exploration;
|
|
104
|
+
/**
|
|
105
|
+
* THE QUESTION: "what did people say about this uploaded file, and record what
|
|
106
|
+
* they said." Names on these remarks are REPORTED, never verified — see
|
|
107
|
+
* {@link SourceMaterialCommentsNamespace}.
|
|
108
|
+
*/
|
|
109
|
+
sourceMaterialComments;
|
|
90
110
|
#transport;
|
|
91
111
|
constructor(options) {
|
|
92
112
|
if (!options.apiKey) {
|
|
@@ -107,15 +127,24 @@ export class MaterialGraphClient {
|
|
|
107
127
|
get: (operationId, query, signal) => this.#get(operationId, query, signal),
|
|
108
128
|
post: (operationId, body, signal) => this.#post(operationId, body, signal),
|
|
109
129
|
});
|
|
130
|
+
this.exploration = createExplorationNamespace(this.#transport);
|
|
131
|
+
this.sourceMaterialComments = createSourceMaterialCommentsNamespace(this.#transport);
|
|
110
132
|
}
|
|
111
133
|
get lastRateLimit() {
|
|
112
134
|
return this.#transport.lastRateLimit;
|
|
113
135
|
}
|
|
114
136
|
#get(operationId, query, signal, pathParams) {
|
|
115
|
-
return this.#transport.requestJson(operation(operationId), {
|
|
137
|
+
return this.#transport.requestJson(operation(operationId), {
|
|
138
|
+
query,
|
|
139
|
+
signal,
|
|
140
|
+
pathParams,
|
|
141
|
+
});
|
|
116
142
|
}
|
|
117
143
|
#post(operationId, body, signal) {
|
|
118
|
-
return this.#transport.requestJson(operation(operationId), {
|
|
144
|
+
return this.#transport.requestJson(operation(operationId), {
|
|
145
|
+
body,
|
|
146
|
+
signal,
|
|
147
|
+
});
|
|
119
148
|
}
|
|
120
149
|
/**
|
|
121
150
|
* THE QUESTION: "find me materials like this" — a RANKED answer over words, a
|
|
@@ -202,8 +231,7 @@ export class MaterialGraphClient {
|
|
|
202
231
|
* {@link MaterialGraphClient.browse} to walk by lightness/vividness, and
|
|
203
232
|
* {@link MaterialGraphClient.search} when colour is one signal among many.
|
|
204
233
|
* Report matches as visual likeness, never a stated colour specification.
|
|
205
|
-
* `family` gates
|
|
206
|
-
* alone crosses a hue boundary; a gated page can be shorter than `limit`.
|
|
234
|
+
* `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.
|
|
207
235
|
*/
|
|
208
236
|
byColour(params, signal) {
|
|
209
237
|
return this.#get("search_by_colour", {
|
|
@@ -213,6 +241,7 @@ export class MaterialGraphClient {
|
|
|
213
241
|
a: params.a,
|
|
214
242
|
b: params.b,
|
|
215
243
|
category: params.category,
|
|
244
|
+
brand: params.brand,
|
|
216
245
|
family: params.family,
|
|
217
246
|
limit: params.limit,
|
|
218
247
|
}, signal);
|
|
@@ -307,7 +336,11 @@ export class MaterialGraphClient {
|
|
|
307
336
|
if (ids.length > MAX_BATCH_IDS) {
|
|
308
337
|
throw MaterialGraphError.unexpected(`MaterialGraphClient.materials(): at most ${MAX_BATCH_IDS} ids per call, received ${ids.length}. Split into multiple batches.`);
|
|
309
338
|
}
|
|
310
|
-
return this.#post("get_materials_batch_post", {
|
|
339
|
+
return this.#post("get_materials_batch_post", {
|
|
340
|
+
ids,
|
|
341
|
+
view: options?.view ?? "tile",
|
|
342
|
+
idKind: options?.idKind ?? "variantId",
|
|
343
|
+
}, signal);
|
|
311
344
|
}
|
|
312
345
|
materialsCached(ids, options, signal) {
|
|
313
346
|
if (ids.length > MAX_BATCH_IDS) {
|
|
@@ -388,38 +421,38 @@ export class MaterialGraphClient {
|
|
|
388
421
|
searchVocabulary(query, options, signal) {
|
|
389
422
|
return searchVocabularyRequest(this.#transport, query, options, signal);
|
|
390
423
|
}
|
|
391
|
-
/** "I have words — what do they mean
|
|
392
|
-
resolve(phrases,
|
|
393
|
-
return
|
|
424
|
+
/** "I have words — what do they mean, and what stands behind them?" — see {@link resolvePhrases}. */
|
|
425
|
+
resolve(phrases, scope) {
|
|
426
|
+
return resolvePhrases(this.#transport, phrases, scope);
|
|
394
427
|
}
|
|
395
428
|
/**
|
|
396
429
|
* THE QUESTION: "which materials, from ANYONE, are ASTM E84 Class A AND
|
|
397
|
-
* GREENGUARD-certified?" — hard specifications, no ranking, every brand at
|
|
398
|
-
* whatever each called the value in source.
|
|
430
|
+
* GREENGUARD-certified?" — hard specifications, no ranking, every brand at
|
|
431
|
+
* once whatever each called the value in source. The value-anchored,
|
|
432
|
+
* spec-only primitive (GET `/api/v1/search/specifications`).
|
|
399
433
|
*
|
|
400
434
|
* Instead use `search({ filters })` when the spec merely GATES a ranked
|
|
401
435
|
* question, `codes.advisory()` when the real question is what a space demands,
|
|
402
|
-
* and {@link
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
*
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
* `sourceBasis`). Answers "which materials, from anyone, are ASTM E84 Class A
|
|
416
|
-
* AND GREENGUARD-certified?" Build the strings with `specCriterion` /
|
|
417
|
-
* `certificationProgrammeCriterion` (e.g.
|
|
418
|
-
* `certificationProgrammeCriterion("GREENGUARD Gold")`); discover the queryable
|
|
419
|
-
* vocabulary with {@link specificationFacets} and {@link attributeValues}.
|
|
436
|
+
* and {@link specificationFacets} first if you do not know the canonical
|
|
437
|
+
* tokens. Guessing one no longer returns a silently empty answer: an
|
|
438
|
+
* unresolvable criterion means the query NEVER RAN and the response says so —
|
|
439
|
+
* read {@link BySpecResponse.unresolvedCriteria} before treating an empty
|
|
440
|
+
* `matches` as "nothing qualifies". A PAGE, NOT A CORPUS, unusually so:
|
|
441
|
+
* `totalMatches` is the returned sample's size under `limit`, not a corpus
|
|
442
|
+
* count. Each `spec` is an `attribute:value` criterion built with
|
|
443
|
+
* `specCriterion` / `certificationProgrammeCriterion`; a variant must satisfy
|
|
444
|
+
* ALL of them, and each match carries per-criterion trust (`confidence` +
|
|
445
|
+
* `sourceBasis`). NUMBER-valued specs take BOUNDS, not values — pass
|
|
446
|
+
* `options.ranges` built with `specRangeCriterion("light_reflectance_value",
|
|
447
|
+
* { min: 60 })`; bounds are inclusive, at least one is required, and a
|
|
448
|
+
* non-numeric stored value is excluded rather than read as zero.
|
|
420
449
|
*/
|
|
421
450
|
bySpec(spec, options, signal) {
|
|
422
|
-
return this.#get("catalog_by_spec", {
|
|
451
|
+
return this.#get("catalog_by_spec", {
|
|
452
|
+
spec: Array.isArray(spec) ? spec : [spec],
|
|
453
|
+
...(options?.ranges?.length ? { specRange: options.ranges } : {}),
|
|
454
|
+
limit: options?.limit,
|
|
455
|
+
}, signal);
|
|
423
456
|
}
|
|
424
457
|
// ── Taxonomy + meta ──────────────────────────────────────────────────────────
|
|
425
458
|
/**
|
|
@@ -440,19 +473,9 @@ export class MaterialGraphClient {
|
|
|
440
473
|
return this.#get("whoami", undefined, signal);
|
|
441
474
|
}
|
|
442
475
|
// ── Pairings / demand ────────────────────────────────────────────────────────
|
|
443
|
-
/**
|
|
444
|
-
* THE QUESTION: "here is my whole scheme so far — what completes it?" The
|
|
445
|
-
* multi-seed form of {@link MaterialGraphClient.pairings}: lift is summed across
|
|
446
|
-
* seeds, so a companion suiting one pick ranks below one suiting several.
|
|
447
|
-
* Instead use `pairings` for a single material and `colours.palette()` when the
|
|
448
|
-
* scheme is COLOURS rather than materials. Check `unresolved` before presenting.
|
|
449
|
-
*
|
|
450
|
-
* Coordinate a palette of already-chosen materials (POST
|
|
451
|
-
* `/api/v1/pairings/coordinate`). Returns demand-lift-ranked companions with
|
|
452
|
-
* colour swatches and an annotate-only `colourFit` (never reorders in v1).
|
|
453
|
-
*/
|
|
476
|
+
/** What completes a scheme already part-chosen. See {@link coordinateCall}. */
|
|
454
477
|
coordinate(input, signal) {
|
|
455
|
-
return this.#
|
|
478
|
+
return coordinateCall(this.#transport, input, signal);
|
|
456
479
|
}
|
|
457
480
|
/**
|
|
458
481
|
* THE QUESTION: "how much is this material actually specified, and what gets
|
|
@@ -575,26 +598,17 @@ export class MaterialGraphClient {
|
|
|
575
598
|
return this.#get("explain_material_term", undefined, signal, { term });
|
|
576
599
|
}
|
|
577
600
|
// ── Brands ───────────────────────────────────────────────────────────────────
|
|
578
|
-
/**
|
|
579
|
-
* THE QUESTION: "whose catalogs are in here, and how big is each?" The SDK's
|
|
580
|
-
* one OFFSET-paginated surface: read `meta.total` for the collection size and
|
|
581
|
-
* `meta.hasMore` to keep walking. Instead use {@link MaterialGraphClient.brand}
|
|
582
|
-
* for one brand's profile and trade signals.
|
|
583
|
-
*/
|
|
601
|
+
/** "Whose catalogs are in here, and how big is each?" — {@link listBrands}. */
|
|
584
602
|
brands(options = {}, signal) {
|
|
585
|
-
return this.#
|
|
603
|
+
return listBrands(this.#transport, options, signal);
|
|
586
604
|
}
|
|
587
|
-
/**
|
|
588
|
-
* THE QUESTION: "who is this brand, and what do they claim?" — profile plus the
|
|
589
|
-
* trade/spec signals ON RECORD. `trade` is keyed by attribute id and an ABSENT
|
|
590
|
-
* key means no value is held — never infer `false`. Instead use
|
|
591
|
-
* {@link MaterialGraphClient.search} to find their materials; this describes the
|
|
592
|
-
* company, not the catalog.
|
|
593
|
-
*/
|
|
605
|
+
/** "Who is this brand, and what do they claim?" — {@link brandProfile}. */
|
|
594
606
|
brand(brandSlug, options, signal) {
|
|
595
|
-
return this.#
|
|
596
|
-
|
|
597
|
-
|
|
607
|
+
return brandProfile(this.#transport, brandSlug, options, signal);
|
|
608
|
+
}
|
|
609
|
+
/** "This maker's whole range, the way a fan deck reads" — {@link brandColourDeck}. */
|
|
610
|
+
brandColourDeck(brandSlug, signal) {
|
|
611
|
+
return brandColourDeck(this.#transport, brandSlug, signal);
|
|
598
612
|
}
|
|
599
613
|
// ── Runs (the hosted agentic surface) ────────────────────────────────────────
|
|
600
614
|
/**
|
|
@@ -687,15 +701,13 @@ export class MaterialGraphClient {
|
|
|
687
701
|
cancelRun(runId, signal) {
|
|
688
702
|
return cancelRun(this.#transport, runId, signal);
|
|
689
703
|
}
|
|
690
|
-
/**
|
|
691
|
-
* Derive an "option B" scheme from a succeeded compose Run along one
|
|
692
|
-
* constraint axis (POST `/api/v1/schemes/vary`). Deterministic and
|
|
693
|
-
* synchronous — the response IS the hydrated scheme (no Run envelope), stamped
|
|
694
|
-
* with axis + source provenance whose `notes` are the variation's receipts.
|
|
695
|
-
* Requires the `mg:read` scope.
|
|
696
|
-
*/
|
|
704
|
+
/** Option B from a composed Run, along one axis. See {@link varySchemeCall}. */
|
|
697
705
|
varyScheme(body, signal) {
|
|
698
|
-
return this.#
|
|
706
|
+
return varySchemeCall(this.#transport, body, signal);
|
|
707
|
+
}
|
|
708
|
+
/** Ranked candidate pools for up to 24 slots. See {@link slotPoolsCall}. */
|
|
709
|
+
slotPools(body, signal) {
|
|
710
|
+
return slotPoolsCall(this.#transport, body, signal);
|
|
699
711
|
}
|
|
700
712
|
/**
|
|
701
713
|
* Stream ordered Run events as an async iterator (GET
|
|
@@ -88,6 +88,43 @@ export interface ColourStatsGroup {
|
|
|
88
88
|
productTypes: number;
|
|
89
89
|
variants: number;
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* One cell of the brand x category x colour-family matrix — the shape that
|
|
93
|
+
* answers questions no single dimension can, such as "how many whites does
|
|
94
|
+
* Benjamin Moore offer in paint".
|
|
95
|
+
*/
|
|
96
|
+
export interface ColourStatsRow {
|
|
97
|
+
/** Opaque brand id — the join key for brand reads. Never parse it. */
|
|
98
|
+
brandId: string;
|
|
99
|
+
brandSlug: string;
|
|
100
|
+
brandName: string;
|
|
101
|
+
/**
|
|
102
|
+
* Product-type key. NULL means these variants carry NO accepted primary
|
|
103
|
+
* product type — a real population, kept so the matrix sums to the corpus,
|
|
104
|
+
* not an error and not a residual bucket.
|
|
105
|
+
*/
|
|
106
|
+
categoryKey: string | null;
|
|
107
|
+
family: string;
|
|
108
|
+
/**
|
|
109
|
+
* Distinct variants at this (brand, category, family) carrying an ACCEPTED
|
|
110
|
+
* `colour_family`. Not every variant of the brand.
|
|
111
|
+
*/
|
|
112
|
+
variants: number;
|
|
113
|
+
}
|
|
114
|
+
/** How to narrow the matrix. Passing ANY of these asks for `rows`. */
|
|
115
|
+
export interface ColourStatsParams {
|
|
116
|
+
/** `"brand,category"` — ask for the whole matrix, unscoped. */
|
|
117
|
+
groupBy?: string;
|
|
118
|
+
brandId?: string;
|
|
119
|
+
brandSlug?: string;
|
|
120
|
+
/**
|
|
121
|
+
* A product-type key, or the literal `"null"` for the unclassified
|
|
122
|
+
* population. Omitting it means every category — a different question.
|
|
123
|
+
*/
|
|
124
|
+
categoryKey?: string;
|
|
125
|
+
family?: string;
|
|
126
|
+
limit?: number;
|
|
127
|
+
}
|
|
91
128
|
/** Where each section came from, how fresh it is, and what it does NOT answer. */
|
|
92
129
|
export interface ColourStatsBasis {
|
|
93
130
|
corpus: string;
|
|
@@ -95,11 +132,32 @@ export interface ColourStatsBasis {
|
|
|
95
132
|
groups: string;
|
|
96
133
|
groupsRefreshedAt: string | null;
|
|
97
134
|
groupsVariantCount: number;
|
|
135
|
+
/**
|
|
136
|
+
* Where `rows` came from, its freshness, and what it EXCLUDES — present only
|
|
137
|
+
* when `rows` is. Read it: the matrix deliberately omits Samplize, which is a
|
|
138
|
+
* sampling channel printing other manufacturers' colours rather than a maker.
|
|
139
|
+
*/
|
|
140
|
+
rows?: string;
|
|
98
141
|
omissions: string[];
|
|
99
142
|
}
|
|
100
143
|
export interface ColourStatsResponse {
|
|
101
144
|
corpus: ColourStatsCorpus;
|
|
102
145
|
families: ColourStatsFamily[];
|
|
103
146
|
groups: ColourStatsGroup[];
|
|
147
|
+
/**
|
|
148
|
+
* The brand x category x colour-family matrix. Present ONLY when you asked
|
|
149
|
+
* for it; ABSENT means nobody asked, never that the matrix is empty.
|
|
150
|
+
*
|
|
151
|
+
* `families` above is NOT scoped by the same parameters and stays
|
|
152
|
+
* platform-wide under all of them. Scoped counts live here.
|
|
153
|
+
*/
|
|
154
|
+
rows?: ColourStatsRow[];
|
|
155
|
+
/**
|
|
156
|
+
* Rows matching your query BEFORE the response cap — the honest total.
|
|
157
|
+
* A shortfall against `rows.length` means `rows` is a prefix.
|
|
158
|
+
*/
|
|
159
|
+
rowsMatched?: number;
|
|
160
|
+
/** TRUE when the matrix exceeded the cap and `rows` is a prefix. */
|
|
161
|
+
rowsTruncated?: boolean;
|
|
104
162
|
basis: ColourStatsBasis;
|
|
105
163
|
}
|
package/colours-client.d.ts
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
* FROM PRODUCT IMAGERY, not declared by the manufacturer. Report visual
|
|
33
33
|
* likeness, never a stated colour specification.
|
|
34
34
|
*/
|
|
35
|
-
import type { CategoryColourProfilesResponse, ColourProfilesParams, ColourStatsResponse } from "./colour-aggregate-types.js";
|
|
35
|
+
import type { CategoryColourProfilesResponse, ColourProfilesParams, ColourStatsParams, ColourStatsResponse } from "./colour-aggregate-types.js";
|
|
36
36
|
import type { QueryParams } from "./http-transport.js";
|
|
37
37
|
import type { SdkOperationId } from "./operations.js";
|
|
38
38
|
import type { SearchGradientInput, SearchGradientResponse, SearchPaletteInput, SearchPaletteResponse } from "./palette-search-types.js";
|
|
@@ -87,8 +87,14 @@ export declare class ColoursClient {
|
|
|
87
87
|
* coverage per product-type group. `basis` states the source and freshness of
|
|
88
88
|
* each section plus `basis.omissions` — what this call deliberately does not
|
|
89
89
|
* answer, listed rather than silently absent.
|
|
90
|
+
*
|
|
91
|
+
* Pass `{ groupBy: "brand,category" }` for the whole brand x category x
|
|
92
|
+
* family matrix in one call, or a `brandSlug`/`categoryKey` scope for a slice
|
|
93
|
+
* of it — either way it arrives as `rows`, each row carrying `brandId` and
|
|
94
|
+
* `brandSlug` to join on. Without any of those parameters the payload is the
|
|
95
|
+
* platform-wide one and `rows` is absent. `families` is never scoped by them.
|
|
90
96
|
*/
|
|
91
|
-
stats(signal?: AbortSignal): Promise<ColourStatsResponse>;
|
|
97
|
+
stats(params?: ColourStatsParams, signal?: AbortSignal): Promise<ColourStatsResponse>;
|
|
92
98
|
/**
|
|
93
99
|
* THE QUESTION: "what goes with this WHOLE PALETTE?" — N colours at once, at
|
|
94
100
|
* stated proportions, not one colour repeated (POST `/api/v1/search/palettes`).
|
package/colours-client.js
CHANGED
|
@@ -53,9 +53,22 @@ export class ColoursClient {
|
|
|
53
53
|
* coverage per product-type group. `basis` states the source and freshness of
|
|
54
54
|
* each section plus `basis.omissions` — what this call deliberately does not
|
|
55
55
|
* answer, listed rather than silently absent.
|
|
56
|
+
*
|
|
57
|
+
* Pass `{ groupBy: "brand,category" }` for the whole brand x category x
|
|
58
|
+
* family matrix in one call, or a `brandSlug`/`categoryKey` scope for a slice
|
|
59
|
+
* of it — either way it arrives as `rows`, each row carrying `brandId` and
|
|
60
|
+
* `brandSlug` to join on. Without any of those parameters the payload is the
|
|
61
|
+
* platform-wide one and `rows` is absent. `families` is never scoped by them.
|
|
56
62
|
*/
|
|
57
|
-
stats(signal) {
|
|
58
|
-
return this.#transport.get("get_colour_stats",
|
|
63
|
+
stats(params = {}, signal) {
|
|
64
|
+
return this.#transport.get("get_colour_stats", {
|
|
65
|
+
groupBy: params.groupBy,
|
|
66
|
+
brandId: params.brandId,
|
|
67
|
+
brandSlug: params.brandSlug,
|
|
68
|
+
categoryKey: params.categoryKey,
|
|
69
|
+
family: params.family,
|
|
70
|
+
limit: params.limit,
|
|
71
|
+
}, signal);
|
|
59
72
|
}
|
|
60
73
|
/**
|
|
61
74
|
* THE QUESTION: "what goes with this WHOLE PALETTE?" — N colours at once, at
|