@instruments/materialgraph 0.4.0 → 0.6.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/client.js +1 -0
- package/colour-aggregate-types.d.ts +16 -4
- package/colours-client.d.ts +62 -12
- package/colours-client.js +49 -0
- package/index.d.ts +1 -0
- package/operations.d.ts +1 -1
- package/operations.js +2 -0
- package/package.json +1 -1
- package/palette-search-types.d.ts +122 -0
- package/palette-search-types.js +1 -0
package/client.js
CHANGED
|
@@ -60,6 +60,7 @@ export class MaterialGraphClient {
|
|
|
60
60
|
});
|
|
61
61
|
this.colours = new ColoursClient({
|
|
62
62
|
get: (operationId, query, signal) => this.#get(operationId, query, signal),
|
|
63
|
+
post: (operationId, body, signal) => this.#post(operationId, body, signal),
|
|
63
64
|
});
|
|
64
65
|
}
|
|
65
66
|
get lastRateLimit() {
|
|
@@ -8,8 +8,12 @@
|
|
|
8
8
|
* widened so a new server value still type-checks.
|
|
9
9
|
*/
|
|
10
10
|
import type { OpenEnum } from "./types.js";
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Which taxonomy tier a colour profile's `categoryKey` names — or `"merged"`,
|
|
13
|
+
* where the key is a composite over a caller-defined key set rather than a
|
|
14
|
+
* taxonomy node.
|
|
15
|
+
*/
|
|
16
|
+
export type CategoryTier = OpenEnum<"group" | "type" | "merged">;
|
|
13
17
|
/** How the endpoint picks which colours to keep. */
|
|
14
18
|
export type ColourProfileSelect = OpenEnum<"frequency" | "diverse">;
|
|
15
19
|
/** One representative colour bucket of a category. */
|
|
@@ -29,6 +33,11 @@ export interface CategoryColourProfile {
|
|
|
29
33
|
level: CategoryTier;
|
|
30
34
|
name: string;
|
|
31
35
|
path: string;
|
|
36
|
+
/**
|
|
37
|
+
* Under `groupBy: "merged"`, the requested keys in composite-key order, so
|
|
38
|
+
* `categoryKey` never has to be split. Absent on a single-category profile.
|
|
39
|
+
*/
|
|
40
|
+
members?: string[];
|
|
32
41
|
variantCount: number;
|
|
33
42
|
avgLightness: number;
|
|
34
43
|
avgChroma: number;
|
|
@@ -51,8 +60,11 @@ export interface CategoryColourProfilesResponse {
|
|
|
51
60
|
export interface ColourProfilesParams {
|
|
52
61
|
/** 1–8 category keys, at the tier named by `groupBy`. */
|
|
53
62
|
productTypeIds: readonly string[];
|
|
54
|
-
/**
|
|
55
|
-
|
|
63
|
+
/**
|
|
64
|
+
* `"group"` merges each group's leaf product types into one palette;
|
|
65
|
+
* `"merged"` merges EVERY key's leaves into a single combined palette.
|
|
66
|
+
*/
|
|
67
|
+
groupBy?: "group" | "type" | "merged";
|
|
56
68
|
/** Representative colours per category, 1–64. */
|
|
57
69
|
topN?: number;
|
|
58
70
|
/** `"diverse"` maximises visual distinctness instead of frequency. */
|
package/colours-client.d.ts
CHANGED
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The colour
|
|
2
|
+
* The colour surface, namespaced as `mg.colours` — the aggregate reads
|
|
3
|
+
* (`stats`, `profiles`) plus MULTI-COLOUR search (`palette`, `gradient`).
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
* does the graph hold at all" (`stats`)
|
|
6
|
-
* come in" (`profiles`)
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* single verb.
|
|
5
|
+
* One colour family rather than four more flat methods on an already-large
|
|
6
|
+
* client facade: "how much colour does the graph hold at all" (`stats`), "what
|
|
7
|
+
* colours does this category come in" (`profiles`), "what goes with these
|
|
8
|
+
* colours" (`palette`), and "what moves from this colour to that one"
|
|
9
|
+
* (`gradient`). `mg.codes` and `mg.browse` set the precedent for a namespace
|
|
10
|
+
* when a capability is a family rather than a single verb.
|
|
10
11
|
*
|
|
11
12
|
* The namespace holds no transport of its own: the client hands it a bound
|
|
12
|
-
* `get`, so auth, rate-limit accounting and error shaping stay in one
|
|
13
|
+
* `get`/`post`, so auth, rate-limit accounting and error shaping stay in one
|
|
14
|
+
* place.
|
|
13
15
|
*
|
|
14
|
-
*
|
|
15
|
-
* refreshed on a schedule, not on write, so a caller can and
|
|
16
|
-
* much of the corpus the answer actually covers before
|
|
16
|
+
* The two AGGREGATE responses carry a `basis`. Those are reads of a
|
|
17
|
+
* materialized view refreshed on a schedule, not on write, so a caller can and
|
|
18
|
+
* should check how much of the corpus the answer actually covers before
|
|
19
|
+
* treating it as complete. The two SEARCH responses are live and uncached.
|
|
17
20
|
*/
|
|
18
21
|
import type { CategoryColourProfilesResponse, ColourProfilesParams, ColourStatsResponse } from "./colour-aggregate-types.js";
|
|
19
22
|
import type { QueryParams } from "./http-transport.js";
|
|
20
23
|
import type { SdkOperationId } from "./operations.js";
|
|
21
|
-
|
|
24
|
+
import type { SearchGradientInput, SearchGradientResponse, SearchPaletteInput, SearchPaletteResponse } from "./palette-search-types.js";
|
|
25
|
+
/** The client's own request primitives, handed down so this file owns no transport. */
|
|
22
26
|
export interface ColoursTransport {
|
|
23
27
|
get<T>(operationId: SdkOperationId, query?: QueryParams, signal?: AbortSignal): Promise<T>;
|
|
28
|
+
post<T>(operationId: SdkOperationId, body: unknown, signal?: AbortSignal): Promise<T>;
|
|
24
29
|
}
|
|
25
30
|
export declare class ColoursClient {
|
|
26
31
|
#private;
|
|
@@ -37,6 +42,13 @@ export declare class ColoursClient {
|
|
|
37
42
|
* cannot recover that spread from a truncated frequency list, which is why it
|
|
38
43
|
* is a server mode rather than a local sort.
|
|
39
44
|
*
|
|
45
|
+
* `groupBy: "merged"` merges across the KEYS as well and returns ONE profile
|
|
46
|
+
* over the union of their leaves — the palette of a caller-defined facet such
|
|
47
|
+
* as "Wood" (`wood_surface` + `wood_flooring`) that the taxonomy holds no
|
|
48
|
+
* single node for, and that no combination of per-key responses reconstructs.
|
|
49
|
+
* Its keys may sit at either tier, `categoryKey` is those keys sorted and
|
|
50
|
+
* joined with `+`, and `members` hands them back so nothing has to split it.
|
|
51
|
+
*
|
|
40
52
|
* A selected category with no colour data comes back as a zero-count profile,
|
|
41
53
|
* not a missing key.
|
|
42
54
|
*/
|
|
@@ -49,4 +61,42 @@ export declare class ColoursClient {
|
|
|
49
61
|
* answer, listed rather than silently absent.
|
|
50
62
|
*/
|
|
51
63
|
stats(signal?: AbortSignal): Promise<ColourStatsResponse>;
|
|
64
|
+
/**
|
|
65
|
+
* Find materials that go with a WHOLE PALETTE — N colours at once, not one
|
|
66
|
+
* colour repeated (POST `/api/v1/search/palettes`).
|
|
67
|
+
*
|
|
68
|
+
* Each colour scores `sim × prop`: `sim` is OKLab closeness on the same
|
|
69
|
+
* mapping `byColour` ranks with, and `prop` rewards a candidate whose own
|
|
70
|
+
* swatch SHARE sits near the `proportion` you asked for. So the same colours
|
|
71
|
+
* at different proportions come back in a different order — a colour at 60%
|
|
72
|
+
* of the surface is a different query from one at 5%. `logic: "all"` (the
|
|
73
|
+
* default) applies a per-colour eligibility floor and returns the weighted
|
|
74
|
+
* geometric mean, so a candidate missing one colour is rejected rather than
|
|
75
|
+
* merely ranked low; `logic: "any"` is a noisy-OR that accepts partial
|
|
76
|
+
* answers but saturates once several colours score well, so prefer `all`
|
|
77
|
+
* when the ORDER is what matters.
|
|
78
|
+
*
|
|
79
|
+
* Every match carries the candidate's full `palette` plus a per-colour
|
|
80
|
+
* receipt naming the swatch that answered each queried colour.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* const { matches } = await mg.colours.palette({
|
|
84
|
+
* colours: [
|
|
85
|
+
* { hex: "F5EFE0", proportion: 0.6 },
|
|
86
|
+
* { hex: "9CAF88", proportion: 0.2 },
|
|
87
|
+
* { hex: "3E3B36", proportion: 0.2 },
|
|
88
|
+
* ],
|
|
89
|
+
* });
|
|
90
|
+
*/
|
|
91
|
+
palette(input: SearchPaletteInput, signal?: AbortSignal): Promise<SearchPaletteResponse>;
|
|
92
|
+
/**
|
|
93
|
+
* Find materials that move ALONG a colour transition — "cream to rust", in
|
|
94
|
+
* order (POST `/api/v1/search/gradients`).
|
|
95
|
+
*
|
|
96
|
+
* Not a palette: the score is multiplied by `coverage`, the share of the path
|
|
97
|
+
* the candidate actually spans, so a material owning only one end ranks below
|
|
98
|
+
* one that travels the whole way, and a flat single-colour material is
|
|
99
|
+
* rejected outright however close its hue sits to the path.
|
|
100
|
+
*/
|
|
101
|
+
gradient(input: SearchGradientInput, signal?: AbortSignal): Promise<SearchGradientResponse>;
|
|
52
102
|
}
|
package/colours-client.js
CHANGED
|
@@ -15,6 +15,13 @@ export class ColoursClient {
|
|
|
15
15
|
* cannot recover that spread from a truncated frequency list, which is why it
|
|
16
16
|
* is a server mode rather than a local sort.
|
|
17
17
|
*
|
|
18
|
+
* `groupBy: "merged"` merges across the KEYS as well and returns ONE profile
|
|
19
|
+
* over the union of their leaves — the palette of a caller-defined facet such
|
|
20
|
+
* as "Wood" (`wood_surface` + `wood_flooring`) that the taxonomy holds no
|
|
21
|
+
* single node for, and that no combination of per-key responses reconstructs.
|
|
22
|
+
* Its keys may sit at either tier, `categoryKey` is those keys sorted and
|
|
23
|
+
* joined with `+`, and `members` hands them back so nothing has to split it.
|
|
24
|
+
*
|
|
18
25
|
* A selected category with no colour data comes back as a zero-count profile,
|
|
19
26
|
* not a missing key.
|
|
20
27
|
*/
|
|
@@ -36,4 +43,46 @@ export class ColoursClient {
|
|
|
36
43
|
stats(signal) {
|
|
37
44
|
return this.#transport.get("get_colour_stats", undefined, signal);
|
|
38
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Find materials that go with a WHOLE PALETTE — N colours at once, not one
|
|
48
|
+
* colour repeated (POST `/api/v1/search/palettes`).
|
|
49
|
+
*
|
|
50
|
+
* Each colour scores `sim × prop`: `sim` is OKLab closeness on the same
|
|
51
|
+
* mapping `byColour` ranks with, and `prop` rewards a candidate whose own
|
|
52
|
+
* swatch SHARE sits near the `proportion` you asked for. So the same colours
|
|
53
|
+
* at different proportions come back in a different order — a colour at 60%
|
|
54
|
+
* of the surface is a different query from one at 5%. `logic: "all"` (the
|
|
55
|
+
* default) applies a per-colour eligibility floor and returns the weighted
|
|
56
|
+
* geometric mean, so a candidate missing one colour is rejected rather than
|
|
57
|
+
* merely ranked low; `logic: "any"` is a noisy-OR that accepts partial
|
|
58
|
+
* answers but saturates once several colours score well, so prefer `all`
|
|
59
|
+
* when the ORDER is what matters.
|
|
60
|
+
*
|
|
61
|
+
* Every match carries the candidate's full `palette` plus a per-colour
|
|
62
|
+
* receipt naming the swatch that answered each queried colour.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* const { matches } = await mg.colours.palette({
|
|
66
|
+
* colours: [
|
|
67
|
+
* { hex: "F5EFE0", proportion: 0.6 },
|
|
68
|
+
* { hex: "9CAF88", proportion: 0.2 },
|
|
69
|
+
* { hex: "3E3B36", proportion: 0.2 },
|
|
70
|
+
* ],
|
|
71
|
+
* });
|
|
72
|
+
*/
|
|
73
|
+
palette(input, signal) {
|
|
74
|
+
return this.#transport.post("search_by_palette", input, signal);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Find materials that move ALONG a colour transition — "cream to rust", in
|
|
78
|
+
* order (POST `/api/v1/search/gradients`).
|
|
79
|
+
*
|
|
80
|
+
* Not a palette: the score is multiplied by `coverage`, the share of the path
|
|
81
|
+
* the candidate actually spans, so a material owning only one end ranks below
|
|
82
|
+
* one that travels the whole way, and a flat single-colour material is
|
|
83
|
+
* rejected outright however close its hue sits to the path.
|
|
84
|
+
*/
|
|
85
|
+
gradient(input, signal) {
|
|
86
|
+
return this.#transport.post("search_by_gradient", input, signal);
|
|
87
|
+
}
|
|
39
88
|
}
|
package/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export type * from "./codes-types.js";
|
|
|
21
21
|
export { ColoursClient } from "./colours-client.js";
|
|
22
22
|
export type { ColoursTransport } from "./colours-client.js";
|
|
23
23
|
export type * from "./colour-aggregate-types.js";
|
|
24
|
+
export type * from "./palette-search-types.js";
|
|
24
25
|
export type * from "./brand-types.js";
|
|
25
26
|
export type * from "./material-asset-types.js";
|
|
26
27
|
export type * from "./material-block-types.js";
|
package/operations.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const MATERIALGRAPH_API_VERSION = "0.7.0";
|
|
2
|
-
declare const OPERATION_DEFINITIONS: readonly [readonly ["search", "POST", "/api/v1/search", "search_materials_post"], readonly ["searchGet", "GET", "/api/v1/search", "search_materials_get"], readonly ["match", "POST", "/api/v1/search/match", "match_material"], readonly ["byColour", "GET", "/api/v1/search/colours", "search_by_colour"], readonly ["material", "GET", "/api/v1/materials/{variantId}", "get_material"], readonly ["siblings", "GET", "/api/v1/materials/{variantId}/siblings", "get_material_siblings"], readonly ["materialBlocks", "GET", "/api/v1/materials/{variantId}/blocks", "list_material_blocks"], readonly ["materialAssets", "GET", "/api/v1/materials/{variantId}/assets", "list_material_assets"], readonly ["schema", "GET", "/api/v1/schema/blocks", "list_schema_blocks"], readonly ["schema", "GET", "/api/v1/schema/attributes", "list_schema_attributes"], readonly ["schema", "GET", "/api/v1/schema/verticals", "list_schema_verticals"], readonly ["schema", "GET", "/api/v1/schema/product-types", "list_schema_product_types"], readonly ["schema", "GET", "/api/v1/schema/units", "list_schema_units"], readonly ["schema", "GET", "/api/v1/schema/value-dictionaries", "list_schema_value_dictionaries"], readonly ["schema", "GET", "/api/v1/schema/source-requirements", "list_schema_source_requirements"], readonly ["schema", "GET", "/api/v1/schema/product-type-templates", "list_schema_product_type_templates"], readonly ["schema", "GET", "/api/v1/schema/mappings", "list_schema_mappings"], readonly ["pairings", "GET", "/api/v1/materials/{variantId}/pairings", "get_material_pairings"], readonly ["materials", "POST", "/api/v1/materials/batch", "get_materials_batch_post"], readonly ["materialsCached", "GET", "/api/v1/materials/batch", "get_materials_batch_get"], readonly ["browse", "GET", "/api/v1/search/browse", "search_browse_by_colour"], readonly ["colourFacets", "GET", "/api/v1/colours/facets", "get_colour_facets"], readonly ["colours.profiles", "GET", "/api/v1/colours/profiles", "get_category_colour_profiles"], readonly ["colours.stats", "GET", "/api/v1/colours/stats", "get_colour_stats"], readonly ["resolveColour", "GET", "/api/v1/search/colours/resolve", "resolve_colour_name"], readonly ["suggestColour", "GET", "/api/v1/search/colours/suggest", "suggest_colour_names"], readonly ["suggest", "GET", "/api/v1/search/suggest", "search_suggest"], readonly ["resolveAttribute", "GET", "/api/v1/catalog/attributes/resolve", "catalog_resolve_attribute"], readonly ["resolveAttributeValue", "GET", "/api/v1/catalog/attributes/{attributeId}/values/resolve", "catalog_resolve_value"], readonly ["searchVocabulary", "GET", "/api/v1/catalog/vocabulary/search", "catalog_vocabulary_search"], readonly ["bySpec", "GET", "/api/v1/search/specifications", "catalog_by_spec"], readonly ["taxonomy", "GET", "/api/v1/taxonomy/categories", "get_category_taxonomy"], readonly ["whoami", "GET", "/api/v1/whoami", "whoami"], readonly ["coordinate", "POST", "/api/v1/pairings/coordinate", "coordinate_materials"], readonly ["demand", "GET", "/api/v1/demand", "get_material_demand"], readonly ["extractPalette", "POST", "/api/v1/search/palettes/extract", "extract_image_palette"], readonly ["specificationFacets", "GET", "/api/v1/catalog/specifications/facets", "list_spec_facets"], readonly ["attributeValues", "GET", "/api/v1/catalog/attributes/{attributeId}/values", "list_attribute_values"], readonly ["applicableSpecs", "GET", "/api/v1/taxonomy/categories/{key}/specs", "get_applicable_specs"], readonly ["glossary", "GET", "/api/v1/glossary/{term}", "explain_material_term"], readonly ["brands", "GET", "/api/v1/brands", "list_brands"], readonly ["brand", "GET", "/api/v1/brands/{brandSlug}", "get_brand_profile"], readonly ["uploadSourceMaterial", "POST", "/api/v1/source-material", "upload_source_material"], readonly ["sourceMaterialBatch", "GET", "/api/v1/source-material/{batchId}", "get_source_material_batch"], readonly ["capabilities", "GET", "/api/v1/capabilities", "list_public_capabilities"], readonly ["createRun", "POST", "/api/v1/runs", "create_public_run"], readonly ["run", "GET", "/api/v1/runs/{runId}", "get_public_run"], readonly ["runSchedule", "GET", "/api/v1/runs/{runId}/schedule", "get_run_finish_schedule"], readonly ["streamRunEvents", "GET", "/api/v1/runs/{runId}/events", "list_public_run_events"], readonly ["resumeRun", "POST", "/api/v1/runs/{runId}/resume", "resume_public_run"], readonly ["cancelRun", "POST", "/api/v1/runs/{runId}/cancel", "cancel_public_run"], readonly ["varyScheme", "POST", "/api/v1/schemes/vary", "vary_schemes"], readonly ["createProject", "POST", "/api/v1/projects", "create_box_project"], readonly ["listProjects", "GET", "/api/v1/projects", "list_box_projects"], readonly ["getProject", "GET", "/api/v1/projects/{projectId}", "get_box_project"], readonly ["appendProjectEvent", "POST", "/api/v1/projects/{projectId}/events", "append_box_project_event"], readonly ["demandBatch", "POST", "/api/v1/demand/batch", "get_demand_batch"], readonly ["codeAdvisory", "POST", "/api/v1/codes/advisory", "resolveCodeAdvisory"], readonly ["codes.context", "GET", "/api/v1/codes/context", "list_code_context"], readonly ["codes.requirements", "GET", "/api/v1/codes/requirements", "list_code_requirements"]];
|
|
2
|
+
declare const OPERATION_DEFINITIONS: readonly [readonly ["search", "POST", "/api/v1/search", "search_materials_post"], readonly ["searchGet", "GET", "/api/v1/search", "search_materials_get"], readonly ["match", "POST", "/api/v1/search/match", "match_material"], readonly ["byColour", "GET", "/api/v1/search/colours", "search_by_colour"], readonly ["material", "GET", "/api/v1/materials/{variantId}", "get_material"], readonly ["siblings", "GET", "/api/v1/materials/{variantId}/siblings", "get_material_siblings"], readonly ["materialBlocks", "GET", "/api/v1/materials/{variantId}/blocks", "list_material_blocks"], readonly ["materialAssets", "GET", "/api/v1/materials/{variantId}/assets", "list_material_assets"], readonly ["schema", "GET", "/api/v1/schema/blocks", "list_schema_blocks"], readonly ["schema", "GET", "/api/v1/schema/attributes", "list_schema_attributes"], readonly ["schema", "GET", "/api/v1/schema/verticals", "list_schema_verticals"], readonly ["schema", "GET", "/api/v1/schema/product-types", "list_schema_product_types"], readonly ["schema", "GET", "/api/v1/schema/units", "list_schema_units"], readonly ["schema", "GET", "/api/v1/schema/value-dictionaries", "list_schema_value_dictionaries"], readonly ["schema", "GET", "/api/v1/schema/source-requirements", "list_schema_source_requirements"], readonly ["schema", "GET", "/api/v1/schema/product-type-templates", "list_schema_product_type_templates"], readonly ["schema", "GET", "/api/v1/schema/mappings", "list_schema_mappings"], readonly ["pairings", "GET", "/api/v1/materials/{variantId}/pairings", "get_material_pairings"], readonly ["materials", "POST", "/api/v1/materials/batch", "get_materials_batch_post"], readonly ["materialsCached", "GET", "/api/v1/materials/batch", "get_materials_batch_get"], readonly ["browse", "GET", "/api/v1/search/browse", "search_browse_by_colour"], readonly ["colourFacets", "GET", "/api/v1/colours/facets", "get_colour_facets"], readonly ["colours.profiles", "GET", "/api/v1/colours/profiles", "get_category_colour_profiles"], readonly ["colours.stats", "GET", "/api/v1/colours/stats", "get_colour_stats"], readonly ["resolveColour", "GET", "/api/v1/search/colours/resolve", "resolve_colour_name"], readonly ["suggestColour", "GET", "/api/v1/search/colours/suggest", "suggest_colour_names"], readonly ["suggest", "GET", "/api/v1/search/suggest", "search_suggest"], readonly ["resolveAttribute", "GET", "/api/v1/catalog/attributes/resolve", "catalog_resolve_attribute"], readonly ["resolveAttributeValue", "GET", "/api/v1/catalog/attributes/{attributeId}/values/resolve", "catalog_resolve_value"], readonly ["searchVocabulary", "GET", "/api/v1/catalog/vocabulary/search", "catalog_vocabulary_search"], readonly ["bySpec", "GET", "/api/v1/search/specifications", "catalog_by_spec"], readonly ["taxonomy", "GET", "/api/v1/taxonomy/categories", "get_category_taxonomy"], readonly ["whoami", "GET", "/api/v1/whoami", "whoami"], readonly ["coordinate", "POST", "/api/v1/pairings/coordinate", "coordinate_materials"], readonly ["demand", "GET", "/api/v1/demand", "get_material_demand"], readonly ["colours.palette", "POST", "/api/v1/search/palettes", "search_by_palette"], readonly ["extractPalette", "POST", "/api/v1/search/palettes/extract", "extract_image_palette"], readonly ["colours.gradient", "POST", "/api/v1/search/gradients", "search_by_gradient"], readonly ["specificationFacets", "GET", "/api/v1/catalog/specifications/facets", "list_spec_facets"], readonly ["attributeValues", "GET", "/api/v1/catalog/attributes/{attributeId}/values", "list_attribute_values"], readonly ["applicableSpecs", "GET", "/api/v1/taxonomy/categories/{key}/specs", "get_applicable_specs"], readonly ["glossary", "GET", "/api/v1/glossary/{term}", "explain_material_term"], readonly ["brands", "GET", "/api/v1/brands", "list_brands"], readonly ["brand", "GET", "/api/v1/brands/{brandSlug}", "get_brand_profile"], readonly ["uploadSourceMaterial", "POST", "/api/v1/source-material", "upload_source_material"], readonly ["sourceMaterialBatch", "GET", "/api/v1/source-material/{batchId}", "get_source_material_batch"], readonly ["capabilities", "GET", "/api/v1/capabilities", "list_public_capabilities"], readonly ["createRun", "POST", "/api/v1/runs", "create_public_run"], readonly ["run", "GET", "/api/v1/runs/{runId}", "get_public_run"], readonly ["runSchedule", "GET", "/api/v1/runs/{runId}/schedule", "get_run_finish_schedule"], readonly ["streamRunEvents", "GET", "/api/v1/runs/{runId}/events", "list_public_run_events"], readonly ["resumeRun", "POST", "/api/v1/runs/{runId}/resume", "resume_public_run"], readonly ["cancelRun", "POST", "/api/v1/runs/{runId}/cancel", "cancel_public_run"], readonly ["varyScheme", "POST", "/api/v1/schemes/vary", "vary_schemes"], readonly ["createProject", "POST", "/api/v1/projects", "create_box_project"], readonly ["listProjects", "GET", "/api/v1/projects", "list_box_projects"], readonly ["getProject", "GET", "/api/v1/projects/{projectId}", "get_box_project"], readonly ["appendProjectEvent", "POST", "/api/v1/projects/{projectId}/events", "append_box_project_event"], readonly ["demandBatch", "POST", "/api/v1/demand/batch", "get_demand_batch"], readonly ["codeAdvisory", "POST", "/api/v1/codes/advisory", "resolveCodeAdvisory"], readonly ["codes.context", "GET", "/api/v1/codes/context", "list_code_context"], readonly ["codes.requirements", "GET", "/api/v1/codes/requirements", "list_code_requirements"]];
|
|
3
3
|
export type SdkOperationId = (typeof OPERATION_DEFINITIONS)[number][3];
|
|
4
4
|
export type SdkOperation = Readonly<{
|
|
5
5
|
clientMethod: (typeof OPERATION_DEFINITIONS)[number][0];
|
package/operations.js
CHANGED
|
@@ -40,7 +40,9 @@ const OPERATION_DEFINITIONS = [
|
|
|
40
40
|
["whoami", "GET", "/api/v1/whoami", "whoami"],
|
|
41
41
|
["coordinate", "POST", "/api/v1/pairings/coordinate", "coordinate_materials"],
|
|
42
42
|
["demand", "GET", "/api/v1/demand", "get_material_demand"],
|
|
43
|
+
["colours.palette", "POST", "/api/v1/search/palettes", "search_by_palette"],
|
|
43
44
|
["extractPalette", "POST", "/api/v1/search/palettes/extract", "extract_image_palette"],
|
|
45
|
+
["colours.gradient", "POST", "/api/v1/search/gradients", "search_by_gradient"],
|
|
44
46
|
["specificationFacets", "GET", "/api/v1/catalog/specifications/facets", "list_spec_facets"],
|
|
45
47
|
[
|
|
46
48
|
"attributeValues",
|
package/package.json
CHANGED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire types for MULTI-COLOUR search — `POST /api/v1/search/palettes` and
|
|
3
|
+
* `POST /api/v1/search/gradients`.
|
|
4
|
+
*
|
|
5
|
+
* Kept out of `types.ts` for the same reason `colour-aggregate-types.ts` and
|
|
6
|
+
* `codes-types.ts` are: the shared mirror is at its source-size budget. Same
|
|
7
|
+
* tolerant-parsing contract as the rest of the mirror — response enums are
|
|
8
|
+
* widened so a new server value still type-checks.
|
|
9
|
+
*
|
|
10
|
+
* The MATCH SEMANTICS these types carry are the server's, stated on
|
|
11
|
+
* {@link SearchPaletteInput.logic} and {@link GradientMatch.coverage} rather
|
|
12
|
+
* than left to the endpoint docs.
|
|
13
|
+
*/
|
|
14
|
+
import type { OklabTriple, OpenEnum } from "./types.js";
|
|
15
|
+
/** How the per-colour scores are combined across a palette. */
|
|
16
|
+
export type PaletteLogic = OpenEnum<"all" | "any">;
|
|
17
|
+
/** One queried palette colour — exactly one of `hex` or `oklab`. */
|
|
18
|
+
export interface PaletteQueryColour {
|
|
19
|
+
hex?: string;
|
|
20
|
+
oklab?: OklabTriple;
|
|
21
|
+
/**
|
|
22
|
+
* Share of the surface this colour should occupy, in (0,1]. Stating it
|
|
23
|
+
* CHANGES the ranking: a colour asked for at 0.6 rewards candidates whose own
|
|
24
|
+
* swatch sits near 0.6, not merely candidates that contain the colour.
|
|
25
|
+
*/
|
|
26
|
+
proportion?: number;
|
|
27
|
+
/** Relative importance; defaults to 1 and is normalised across the query. */
|
|
28
|
+
weight?: number;
|
|
29
|
+
}
|
|
30
|
+
/** One gradient stop — exactly one of `hex` or `oklab`. Order is meaningful. */
|
|
31
|
+
export interface GradientStop {
|
|
32
|
+
hex?: string;
|
|
33
|
+
oklab?: OklabTriple;
|
|
34
|
+
}
|
|
35
|
+
export interface SearchPaletteInput {
|
|
36
|
+
/** The palette to match, 1–8 colours. */
|
|
37
|
+
colours: PaletteQueryColour[];
|
|
38
|
+
/**
|
|
39
|
+
* `all` (the default) requires every queried colour to clear a per-colour
|
|
40
|
+
* eligibility floor and scores the weighted geometric mean; `any` is a
|
|
41
|
+
* noisy-OR and never rejects a candidate for missing one colour.
|
|
42
|
+
*/
|
|
43
|
+
logic?: PaletteLogic;
|
|
44
|
+
/** Results to return; defaults to 24, capped at 48. */
|
|
45
|
+
limit?: number;
|
|
46
|
+
}
|
|
47
|
+
export interface SearchGradientInput {
|
|
48
|
+
/** The ordered colour transition, 2–6 stops. */
|
|
49
|
+
stops: GradientStop[];
|
|
50
|
+
/** Results to return; defaults to 24, capped at 48. */
|
|
51
|
+
limit?: number;
|
|
52
|
+
}
|
|
53
|
+
/** One swatch of a candidate's colorscope-extracted palette. */
|
|
54
|
+
export interface CandidateSwatch {
|
|
55
|
+
hex: string;
|
|
56
|
+
proportion: number;
|
|
57
|
+
name: string | null;
|
|
58
|
+
}
|
|
59
|
+
/** Why a queried colour (or gradient sample) scored what it scored. */
|
|
60
|
+
export interface ColourMatchReceipt {
|
|
61
|
+
queryHex: string;
|
|
62
|
+
/** `colourScore × proportionScore` for the best-matching swatch. */
|
|
63
|
+
score: number;
|
|
64
|
+
/** OKLab closeness alone, in [0,1]. */
|
|
65
|
+
colourScore: number;
|
|
66
|
+
/** Proportion agreement alone, in [0,1]. */
|
|
67
|
+
proportionScore: number;
|
|
68
|
+
/** The swatch that produced the score, or null when nothing matched. */
|
|
69
|
+
matched: CandidateSwatch | null;
|
|
70
|
+
}
|
|
71
|
+
/** Identity and evidence shared by both multi-colour match shapes. */
|
|
72
|
+
export interface MultiColourMatchBase {
|
|
73
|
+
variantId: string;
|
|
74
|
+
brand: string;
|
|
75
|
+
product: string;
|
|
76
|
+
brandSlug: string | null;
|
|
77
|
+
productId: string | null;
|
|
78
|
+
color: string | null;
|
|
79
|
+
variantName: string | null;
|
|
80
|
+
imageUrl: string | null;
|
|
81
|
+
/** MB has retired or hidden this SKU. */
|
|
82
|
+
retired: boolean;
|
|
83
|
+
/** The candidate's full extracted palette — the evidence scored against. */
|
|
84
|
+
palette: CandidateSwatch[];
|
|
85
|
+
/** The aggregate match score in [0,1]; higher is closer. */
|
|
86
|
+
score: number;
|
|
87
|
+
}
|
|
88
|
+
export interface PaletteMatch extends MultiColourMatchBase {
|
|
89
|
+
/** One receipt per queried colour, in query order. */
|
|
90
|
+
colours: ColourMatchReceipt[];
|
|
91
|
+
}
|
|
92
|
+
export interface GradientMatch extends MultiColourMatchBase {
|
|
93
|
+
/**
|
|
94
|
+
* Distinct matched thirds of the path over 3. A material owning only one end
|
|
95
|
+
* of the transition caps out around 0.33 — coverage is what separates a real
|
|
96
|
+
* gradient match from a good match on a single stop.
|
|
97
|
+
*/
|
|
98
|
+
coverage: number;
|
|
99
|
+
/** One receipt per sampled point along the path, in path order. */
|
|
100
|
+
samples: ColourMatchReceipt[];
|
|
101
|
+
}
|
|
102
|
+
export interface SearchPaletteResponse {
|
|
103
|
+
query: {
|
|
104
|
+
colours: Array<{
|
|
105
|
+
hex: string;
|
|
106
|
+
proportion?: number;
|
|
107
|
+
weight?: number;
|
|
108
|
+
}>;
|
|
109
|
+
logic: PaletteLogic;
|
|
110
|
+
};
|
|
111
|
+
count: number;
|
|
112
|
+
matches: PaletteMatch[];
|
|
113
|
+
}
|
|
114
|
+
export interface SearchGradientResponse {
|
|
115
|
+
query: {
|
|
116
|
+
stops: string[];
|
|
117
|
+
/** The sampled path points the search actually ran against. */
|
|
118
|
+
samples: string[];
|
|
119
|
+
};
|
|
120
|
+
count: number;
|
|
121
|
+
matches: GradientMatch[];
|
|
122
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|