@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/specifications.d.ts
CHANGED
|
@@ -1,22 +1,12 @@
|
|
|
1
|
+
import type { CertificationProgrammeFilter, SpecExclusionFilter, SpecPresenceFilter, SpecTermFilter } from "./spec-types.js";
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
-
* spec intent into a typed criterion the SDK's two spec operations accept:
|
|
3
|
+
* A hard criterion excluding one canonical value.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - `bySpec(specs)` takes `attribute:value` strings — the value-anchored,
|
|
9
|
-
* spec-only primitive. Build them with {@link specCriterion} and
|
|
10
|
-
* {@link certificationProgrammeCriterion}.
|
|
11
|
-
*
|
|
12
|
-
* The point of these helpers: Desk (and any spec-driven caller) never has to
|
|
13
|
-
* remember that a certification programme lives under a VIRTUAL attribute, nor
|
|
14
|
-
* hand-format the `attribute:value` string the `bySpec` route splits on its
|
|
15
|
-
* first `:`.
|
|
5
|
+
* By default retains only variants with a KNOWN value (unstated does not
|
|
6
|
+
* pass). Pass `whenUnstated: "pass"` to admit unstated variants too — only a
|
|
7
|
+
* variant that STATES the excluded term is dropped.
|
|
16
8
|
*/
|
|
17
|
-
|
|
18
|
-
/** A hard criterion excluding one known canonical value while retaining only variants with known values. */
|
|
19
|
-
export declare function excludeSpec(attributeId: string, excludesTerm: string): SpecExclusionFilter;
|
|
9
|
+
export declare const excludeSpec: (attributeId: string, excludesTerm: string, whenUnstated?: "drop" | "pass") => SpecExclusionFilter;
|
|
20
10
|
/**
|
|
21
11
|
* A term-equality criterion for `search({ filters })` — the attribute must
|
|
22
12
|
* carry this canonical value.
|
|
@@ -25,7 +15,7 @@ export declare function excludeSpec(attributeId: string, excludesTerm: string):
|
|
|
25
15
|
* // "same fire class as the seed"
|
|
26
16
|
* client.search({ similarTo: { variantId }, filters: [specTerm("fire_classifications", "astm_e84_class_a")] });
|
|
27
17
|
*/
|
|
28
|
-
export declare
|
|
18
|
+
export declare const specTerm: (attributeId: string, term: string) => SpecTermFilter;
|
|
29
19
|
/**
|
|
30
20
|
* A presence criterion for `search({ filters })` — the attribute must have ANY
|
|
31
21
|
* accepted value.
|
|
@@ -34,67 +24,19 @@ export declare function specTerm(attributeId: string, term: string): SpecTermFil
|
|
|
34
24
|
* // "…and it must have an EPD on record"
|
|
35
25
|
* client.search({ similarTo: { variantId }, filters: [hasSpec("environmental_product_declaration")] });
|
|
36
26
|
*/
|
|
37
|
-
export declare
|
|
27
|
+
export declare const hasSpec: (attributeId: string) => SpecPresenceFilter;
|
|
38
28
|
/**
|
|
39
29
|
* A certification-programme criterion for `search({ filters })`, pinned to the
|
|
40
30
|
* virtual attribute so a programme matches wherever it landed at ingest
|
|
41
31
|
* (compliance / sustainability / material-health / VOC buckets).
|
|
42
32
|
*
|
|
43
|
-
* The value
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
33
|
+
* The value is a canonical programme token (e.g. `greenguard_certificate`,
|
|
34
|
+
* `has_greenguard_gold_certification`). The one search matches tokens on its
|
|
35
|
+
* index and does not resolve display names, so a name such as
|
|
36
|
+
* "GREENGUARD Gold" is a 400 naming the term.
|
|
47
37
|
*
|
|
48
38
|
* @example
|
|
49
39
|
* // "find a GREENGUARD-certified alternative"
|
|
50
|
-
* client.search({ similarTo: { variantId: seed }, filters: [certificationProgramme("
|
|
51
|
-
*/
|
|
52
|
-
export declare function certificationProgramme(programme: string): CertificationProgrammeFilter;
|
|
53
|
-
/**
|
|
54
|
-
* An `attribute:value` criterion string for `bySpec`. The `bySpec` route splits
|
|
55
|
-
* on the FIRST `:`, so a value may itself contain colons; the attribute id may
|
|
56
|
-
* not.
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* client.bySpec([specCriterion("primary_material", "textile"), specCriterion("fire_classifications", "astm_e84_class_a")]);
|
|
60
|
-
*/
|
|
61
|
-
export declare function specCriterion(attributeId: string, value: string): string;
|
|
62
|
-
/**
|
|
63
|
-
* An `attribute:min..max` RANGE criterion string for `bySpec`, for a
|
|
64
|
-
* NUMBER-valued spec (`light_reflectance_value`, `nrc_rating`,
|
|
65
|
-
* `slip_resistance_dcof`, …). Pass the result in `bySpec`'s `ranges` option.
|
|
66
|
-
*
|
|
67
|
-
* BOTH BOUNDS ARE INCLUSIVE — `{ min: 60 }` matches a value of exactly 60 —
|
|
68
|
-
* because spec language is written that way ("LRV of 60 or more", "DCOF ≥ 0.42")
|
|
69
|
-
* and because inclusive-both-ends means adjacent ranges overlap at the join
|
|
70
|
-
* rather than leaving a gap that hides products.
|
|
71
|
-
*
|
|
72
|
-
* At least one bound is REQUIRED: a range with neither is a presence check, and
|
|
73
|
-
* this throws rather than sending a criterion the server would have to refuse.
|
|
74
|
-
* Discover which attributes take a range — and the span they actually occupy —
|
|
75
|
-
* from `specificationFacets()`: those are the facets with `kind: "numeric"`.
|
|
76
|
-
*
|
|
77
|
-
* @example
|
|
78
|
-
* // light paints, every brand at once
|
|
79
|
-
* client.bySpec([], { ranges: [specRangeCriterion("light_reflectance_value", { min: 60 })] });
|
|
80
|
-
* @example
|
|
81
|
-
* // a mid-tone band
|
|
82
|
-
* specRangeCriterion("light_reflectance_value", { min: 30, max: 45 }); // "light_reflectance_value:30..45"
|
|
83
|
-
*/
|
|
84
|
-
export declare function specRangeCriterion(attributeId: string, bounds: {
|
|
85
|
-
min?: number;
|
|
86
|
-
max?: number;
|
|
87
|
-
}): string;
|
|
88
|
-
/**
|
|
89
|
-
* An `attribute:value` criterion string for `bySpec` that filters by
|
|
90
|
-
* certification PROGRAMME across all four certification buckets.
|
|
91
|
-
*
|
|
92
|
-
* The value may be a display name or alias ("GREENGUARD Gold", "LEED"), resolved
|
|
93
|
-
* server-side to its canonical programme token, or a canonical token directly
|
|
94
|
-
* (e.g. `greenguard_certificate`, `has_greenguard_gold_certification`).
|
|
95
|
-
*
|
|
96
|
-
* @example
|
|
97
|
-
* // every brand's GREENGUARD-Gold materials
|
|
98
|
-
* client.bySpec([certificationProgrammeCriterion("GREENGUARD Gold")]);
|
|
40
|
+
* client.search({ similarTo: { variantId: seed }, filters: [certificationProgramme("has_greenguard_gold_certification")] });
|
|
99
41
|
*/
|
|
100
|
-
export declare
|
|
42
|
+
export declare const certificationProgramme: (programme: string) => CertificationProgrammeFilter;
|
package/specifications.js
CHANGED
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Zero-dependency builders for the specification surface. Turn a
|
|
3
|
-
* spec intent into a typed
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* {@link specTerm}, {@link hasSpec}, and {@link certificationProgramme}.
|
|
8
|
-
* - `bySpec(specs)` takes `attribute:value` strings — the value-anchored,
|
|
9
|
-
* spec-only primitive. Build them with {@link specCriterion} and
|
|
10
|
-
* {@link certificationProgrammeCriterion}.
|
|
2
|
+
* Zero-dependency builders for the specification surface. Turn a
|
|
3
|
+
* plain-language spec intent into a typed {@link SpecFilter} `search({
|
|
4
|
+
* filters })` accepts: hard token sets on the one search's index, run in the
|
|
5
|
+
* same query. Build them with {@link specTerm}, {@link hasSpec}, and
|
|
6
|
+
* {@link certificationProgramme}.
|
|
11
7
|
*
|
|
12
8
|
* The point of these helpers: Desk (and any spec-driven caller) never has to
|
|
13
|
-
* remember that a certification programme lives under a VIRTUAL attribute
|
|
14
|
-
*
|
|
15
|
-
*
|
|
9
|
+
* remember that a certification programme lives under a VIRTUAL attribute.
|
|
10
|
+
*
|
|
11
|
+
* A hard specification across every brand (formerly `bySpec`, built with
|
|
12
|
+
* `specCriterion`/`specRangeCriterion`) is now `list_variants`'s `filters`:
|
|
13
|
+
* `{field: attributeId, op: "in", values: [...]}` for a term,
|
|
14
|
+
* `{field: attributeId, op: "gte"/"lte"/etc, value}` for a number — a plain
|
|
15
|
+
* object literal needs no encoder (MG-2222).
|
|
16
|
+
*/
|
|
17
|
+
import { CERTIFICATION_PROGRAMME_ATTRIBUTE_ID } from "./spec-types.js";
|
|
18
|
+
/**
|
|
19
|
+
* A hard criterion excluding one canonical value.
|
|
20
|
+
*
|
|
21
|
+
* By default retains only variants with a KNOWN value (unstated does not
|
|
22
|
+
* pass). Pass `whenUnstated: "pass"` to admit unstated variants too — only a
|
|
23
|
+
* variant that STATES the excluded term is dropped.
|
|
16
24
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
25
|
+
export const excludeSpec = (attributeId, excludesTerm, whenUnstated) => ({
|
|
26
|
+
attributeId,
|
|
27
|
+
excludesTerm,
|
|
28
|
+
...(whenUnstated === undefined ? {} : { whenUnstated }),
|
|
29
|
+
});
|
|
22
30
|
/**
|
|
23
31
|
* A term-equality criterion for `search({ filters })` — the attribute must
|
|
24
32
|
* carry this canonical value.
|
|
@@ -27,9 +35,7 @@ export function excludeSpec(attributeId, excludesTerm) {
|
|
|
27
35
|
* // "same fire class as the seed"
|
|
28
36
|
* client.search({ similarTo: { variantId }, filters: [specTerm("fire_classifications", "astm_e84_class_a")] });
|
|
29
37
|
*/
|
|
30
|
-
export
|
|
31
|
-
return { attributeId, term };
|
|
32
|
-
}
|
|
38
|
+
export const specTerm = (attributeId, term) => ({ attributeId, term });
|
|
33
39
|
/**
|
|
34
40
|
* A presence criterion for `search({ filters })` — the attribute must have ANY
|
|
35
41
|
* accepted value.
|
|
@@ -38,81 +44,25 @@ export function specTerm(attributeId, term) {
|
|
|
38
44
|
* // "…and it must have an EPD on record"
|
|
39
45
|
* client.search({ similarTo: { variantId }, filters: [hasSpec("environmental_product_declaration")] });
|
|
40
46
|
*/
|
|
41
|
-
export
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
export const hasSpec = (attributeId) => ({
|
|
48
|
+
attributeId,
|
|
49
|
+
hasValue: true,
|
|
50
|
+
});
|
|
44
51
|
/**
|
|
45
52
|
* A certification-programme criterion for `search({ filters })`, pinned to the
|
|
46
53
|
* virtual attribute so a programme matches wherever it landed at ingest
|
|
47
54
|
* (compliance / sustainability / material-health / VOC buckets).
|
|
48
55
|
*
|
|
49
|
-
* The value
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
56
|
+
* The value is a canonical programme token (e.g. `greenguard_certificate`,
|
|
57
|
+
* `has_greenguard_gold_certification`). The one search matches tokens on its
|
|
58
|
+
* index and does not resolve display names, so a name such as
|
|
59
|
+
* "GREENGUARD Gold" is a 400 naming the term.
|
|
53
60
|
*
|
|
54
61
|
* @example
|
|
55
62
|
* // "find a GREENGUARD-certified alternative"
|
|
56
|
-
* client.search({ similarTo: { variantId: seed }, filters: [certificationProgramme("
|
|
57
|
-
*/
|
|
58
|
-
export function certificationProgramme(programme) {
|
|
59
|
-
return { attributeId: CERTIFICATION_PROGRAMME_ATTRIBUTE_ID, term: programme };
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* An `attribute:value` criterion string for `bySpec`. The `bySpec` route splits
|
|
63
|
-
* on the FIRST `:`, so a value may itself contain colons; the attribute id may
|
|
64
|
-
* not.
|
|
65
|
-
*
|
|
66
|
-
* @example
|
|
67
|
-
* client.bySpec([specCriterion("primary_material", "textile"), specCriterion("fire_classifications", "astm_e84_class_a")]);
|
|
68
|
-
*/
|
|
69
|
-
export function specCriterion(attributeId, value) {
|
|
70
|
-
return `${attributeId}:${value}`;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* An `attribute:min..max` RANGE criterion string for `bySpec`, for a
|
|
74
|
-
* NUMBER-valued spec (`light_reflectance_value`, `nrc_rating`,
|
|
75
|
-
* `slip_resistance_dcof`, …). Pass the result in `bySpec`'s `ranges` option.
|
|
76
|
-
*
|
|
77
|
-
* BOTH BOUNDS ARE INCLUSIVE — `{ min: 60 }` matches a value of exactly 60 —
|
|
78
|
-
* because spec language is written that way ("LRV of 60 or more", "DCOF ≥ 0.42")
|
|
79
|
-
* and because inclusive-both-ends means adjacent ranges overlap at the join
|
|
80
|
-
* rather than leaving a gap that hides products.
|
|
81
|
-
*
|
|
82
|
-
* At least one bound is REQUIRED: a range with neither is a presence check, and
|
|
83
|
-
* this throws rather than sending a criterion the server would have to refuse.
|
|
84
|
-
* Discover which attributes take a range — and the span they actually occupy —
|
|
85
|
-
* from `specificationFacets()`: those are the facets with `kind: "numeric"`.
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* // light paints, every brand at once
|
|
89
|
-
* client.bySpec([], { ranges: [specRangeCriterion("light_reflectance_value", { min: 60 })] });
|
|
90
|
-
* @example
|
|
91
|
-
* // a mid-tone band
|
|
92
|
-
* specRangeCriterion("light_reflectance_value", { min: 30, max: 45 }); // "light_reflectance_value:30..45"
|
|
93
|
-
*/
|
|
94
|
-
export function specRangeCriterion(attributeId, bounds) {
|
|
95
|
-
const { min, max } = bounds;
|
|
96
|
-
if (min === undefined && max === undefined) {
|
|
97
|
-
throw new Error(`specRangeCriterion("${attributeId}") needs a min, a max, or both — a range with neither would match every recorded value. Use hasSpec() for a presence check.`);
|
|
98
|
-
}
|
|
99
|
-
if (min !== undefined && max !== undefined && min > max) {
|
|
100
|
-
throw new Error(`specRangeCriterion("${attributeId}") is inverted (min ${min} > max ${max}) and can only ever match nothing.`);
|
|
101
|
-
}
|
|
102
|
-
return `${attributeId}:${min ?? ""}..${max ?? ""}`;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* An `attribute:value` criterion string for `bySpec` that filters by
|
|
106
|
-
* certification PROGRAMME across all four certification buckets.
|
|
107
|
-
*
|
|
108
|
-
* The value may be a display name or alias ("GREENGUARD Gold", "LEED"), resolved
|
|
109
|
-
* server-side to its canonical programme token, or a canonical token directly
|
|
110
|
-
* (e.g. `greenguard_certificate`, `has_greenguard_gold_certification`).
|
|
111
|
-
*
|
|
112
|
-
* @example
|
|
113
|
-
* // every brand's GREENGUARD-Gold materials
|
|
114
|
-
* client.bySpec([certificationProgrammeCriterion("GREENGUARD Gold")]);
|
|
63
|
+
* client.search({ similarTo: { variantId: seed }, filters: [certificationProgramme("has_greenguard_gold_certification")] });
|
|
115
64
|
*/
|
|
116
|
-
export
|
|
117
|
-
|
|
118
|
-
|
|
65
|
+
export const certificationProgramme = (programme) => ({
|
|
66
|
+
attributeId: CERTIFICATION_PROGRAMME_ATTRIBUTE_ID,
|
|
67
|
+
term: programme,
|
|
68
|
+
});
|
package/sse.d.ts
CHANGED
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
* chunks are held in an internal buffer until their terminating blank line.
|
|
12
12
|
*/
|
|
13
13
|
/** One dispatched SSE frame. `data` is the joined data lines (no trailing newline). */
|
|
14
|
-
export
|
|
14
|
+
export type SseFrame = {
|
|
15
15
|
id?: string;
|
|
16
16
|
event?: string;
|
|
17
17
|
data: string;
|
|
18
|
-
}
|
|
18
|
+
};
|
|
19
19
|
/**
|
|
20
20
|
* A push-based SSE line assembler. Feed it decoded text with {@link push}; it
|
|
21
21
|
* returns any frames completed by that text. Call {@link flush} once the stream
|
package/sse.js
CHANGED
|
@@ -26,13 +26,15 @@ export class SseDecoder {
|
|
|
26
26
|
const frames = [];
|
|
27
27
|
for (;;) {
|
|
28
28
|
const lineEnd = this.#nextLineEnd();
|
|
29
|
-
if (lineEnd === null)
|
|
29
|
+
if (lineEnd === null) {
|
|
30
30
|
break;
|
|
31
|
+
}
|
|
31
32
|
const line = this.#buffer.slice(0, lineEnd.index);
|
|
32
33
|
this.#buffer = this.#buffer.slice(lineEnd.nextIndex);
|
|
33
34
|
const frame = this.#consumeLine(line);
|
|
34
|
-
if (frame)
|
|
35
|
+
if (frame) {
|
|
35
36
|
frames.push(frame);
|
|
37
|
+
}
|
|
36
38
|
}
|
|
37
39
|
return frames;
|
|
38
40
|
}
|
|
@@ -45,8 +47,9 @@ export class SseDecoder {
|
|
|
45
47
|
: this.#buffer;
|
|
46
48
|
this.#buffer = "";
|
|
47
49
|
const frame = this.#consumeLine(line);
|
|
48
|
-
if (frame)
|
|
50
|
+
if (frame) {
|
|
49
51
|
return [frame];
|
|
52
|
+
}
|
|
50
53
|
}
|
|
51
54
|
const frame = this.#dispatch();
|
|
52
55
|
return frame ? [frame] : [];
|
|
@@ -55,11 +58,13 @@ export class SseDecoder {
|
|
|
55
58
|
#nextLineEnd() {
|
|
56
59
|
for (let i = 0; i < this.#buffer.length; i += 1) {
|
|
57
60
|
const char = this.#buffer[i];
|
|
58
|
-
if (char === "\n")
|
|
61
|
+
if (char === "\n") {
|
|
59
62
|
return { index: i, nextIndex: i + 1 };
|
|
63
|
+
}
|
|
60
64
|
if (char === "\r") {
|
|
61
|
-
if (i === this.#buffer.length - 1)
|
|
65
|
+
if (i === this.#buffer.length - 1) {
|
|
62
66
|
return null;
|
|
67
|
+
}
|
|
63
68
|
return this.#buffer[i + 1] === "\n"
|
|
64
69
|
? { index: i, nextIndex: i + 2 }
|
|
65
70
|
: { index: i, nextIndex: i + 1 };
|
|
@@ -68,15 +73,18 @@ export class SseDecoder {
|
|
|
68
73
|
return null;
|
|
69
74
|
}
|
|
70
75
|
#consumeLine(line) {
|
|
71
|
-
if (line.length === 0)
|
|
76
|
+
if (line.length === 0) {
|
|
72
77
|
return this.#dispatch();
|
|
73
|
-
|
|
78
|
+
}
|
|
79
|
+
if (line.startsWith(":")) {
|
|
74
80
|
return undefined;
|
|
81
|
+
}
|
|
75
82
|
const colon = line.indexOf(":");
|
|
76
83
|
const field = colon === -1 ? line : line.slice(0, colon);
|
|
77
84
|
let value = colon === -1 ? "" : line.slice(colon + 1);
|
|
78
|
-
if (value.startsWith(" "))
|
|
85
|
+
if (value.startsWith(" ")) {
|
|
79
86
|
value = value.slice(1);
|
|
87
|
+
}
|
|
80
88
|
if (field === "data") {
|
|
81
89
|
this.#dataLines.push(value);
|
|
82
90
|
this.#hasFields = true;
|
|
@@ -92,13 +100,16 @@ export class SseDecoder {
|
|
|
92
100
|
return undefined;
|
|
93
101
|
}
|
|
94
102
|
#dispatch() {
|
|
95
|
-
if (!this.#hasFields)
|
|
103
|
+
if (!this.#hasFields) {
|
|
96
104
|
return undefined;
|
|
105
|
+
}
|
|
97
106
|
const frame = { data: this.#dataLines.join("\n") };
|
|
98
|
-
if (this.#event !== undefined)
|
|
107
|
+
if (this.#event !== undefined) {
|
|
99
108
|
frame.event = this.#event;
|
|
100
|
-
|
|
109
|
+
}
|
|
110
|
+
if (this.#id !== undefined) {
|
|
101
111
|
frame.id = this.#id;
|
|
112
|
+
}
|
|
102
113
|
this.#dataLines = [];
|
|
103
114
|
this.#event = undefined;
|
|
104
115
|
this.#id = undefined;
|
|
@@ -117,28 +128,33 @@ export async function* readSseFrames(body, signal) {
|
|
|
117
128
|
const sse = new SseDecoder();
|
|
118
129
|
try {
|
|
119
130
|
for (;;) {
|
|
120
|
-
if (signal?.aborted)
|
|
131
|
+
if (signal?.aborted) {
|
|
121
132
|
return;
|
|
133
|
+
}
|
|
122
134
|
let result;
|
|
123
135
|
try {
|
|
124
136
|
result = await reader.read();
|
|
125
137
|
}
|
|
126
138
|
catch (error) {
|
|
127
|
-
if (signal?.aborted)
|
|
139
|
+
if (signal?.aborted) {
|
|
128
140
|
return;
|
|
141
|
+
}
|
|
129
142
|
throw error;
|
|
130
143
|
}
|
|
131
144
|
if (result.done) {
|
|
132
|
-
for (const frame of sse.push(decoder.decode()))
|
|
145
|
+
for (const frame of sse.push(decoder.decode())) {
|
|
133
146
|
yield frame;
|
|
134
|
-
|
|
147
|
+
}
|
|
148
|
+
for (const frame of sse.flush()) {
|
|
135
149
|
yield frame;
|
|
150
|
+
}
|
|
136
151
|
return;
|
|
137
152
|
}
|
|
138
153
|
const text = decoder.decode(result.value, { stream: true });
|
|
139
154
|
for (const frame of sse.push(text)) {
|
|
140
|
-
if (signal?.aborted)
|
|
155
|
+
if (signal?.aborted) {
|
|
141
156
|
return;
|
|
157
|
+
}
|
|
142
158
|
yield frame;
|
|
143
159
|
}
|
|
144
160
|
}
|
package/substitute-types.d.ts
CHANGED
|
@@ -2,40 +2,40 @@ import type { BySpecVerdict } from "./by-spec-types.js";
|
|
|
2
2
|
import type { VariantId } from "./identifiers.js";
|
|
3
3
|
import type { MaterialSuccessor } from "./material-types.js";
|
|
4
4
|
export type SubstituteSignatureFamily = "textile" | "tile" | "coating" | "lighting_electrical" | "acoustic" | "surface" | "furniture" | "sanitaryware" | "fittings" | "architectural_hardware";
|
|
5
|
-
export
|
|
5
|
+
export type SubstituteSignatureCriterion = {
|
|
6
6
|
role: "primary_material" | "performance";
|
|
7
7
|
attributeId: string;
|
|
8
8
|
term: string;
|
|
9
|
-
}
|
|
10
|
-
export
|
|
9
|
+
};
|
|
10
|
+
export type AvailableSubstituteSignature = {
|
|
11
11
|
family: SubstituteSignatureFamily;
|
|
12
12
|
form: string;
|
|
13
13
|
criteria: [SubstituteSignatureCriterion, SubstituteSignatureCriterion];
|
|
14
|
-
}
|
|
15
|
-
export
|
|
14
|
+
};
|
|
15
|
+
export type UnsupportedSubstituteSignature = {
|
|
16
16
|
family: SubstituteSignatureFamily;
|
|
17
17
|
form: string;
|
|
18
18
|
reason: string;
|
|
19
|
-
}
|
|
20
|
-
export
|
|
19
|
+
};
|
|
20
|
+
export type InsufficientSubstituteSignature = {
|
|
21
21
|
family: SubstituteSignatureFamily;
|
|
22
22
|
form: string;
|
|
23
23
|
missingRoles: ("primary_material" | "performance")[];
|
|
24
|
-
}
|
|
25
|
-
export
|
|
24
|
+
};
|
|
25
|
+
export type FindSubstitutesOptions = {
|
|
26
26
|
excludeBrands?: string[];
|
|
27
27
|
diversityBoost?: number;
|
|
28
28
|
limit?: number;
|
|
29
29
|
cursor?: string;
|
|
30
30
|
includeSamplingArtifacts?: boolean;
|
|
31
31
|
includeUnavailable?: boolean;
|
|
32
|
-
}
|
|
33
|
-
export
|
|
32
|
+
};
|
|
33
|
+
export type SubstituteMatchedCriterion = {
|
|
34
34
|
attributeId: string;
|
|
35
35
|
confidence: number | null;
|
|
36
36
|
sourceBasis: string | null;
|
|
37
|
-
}
|
|
38
|
-
export
|
|
37
|
+
};
|
|
38
|
+
export type SubstituteResultItem = {
|
|
39
39
|
variantId: VariantId;
|
|
40
40
|
brandSlug: string;
|
|
41
41
|
brand: string;
|
|
@@ -50,8 +50,8 @@ export interface SubstituteResultItem {
|
|
|
50
50
|
diversityAdjustment: number;
|
|
51
51
|
score: number;
|
|
52
52
|
verdict: BySpecVerdict;
|
|
53
|
-
}
|
|
54
|
-
export
|
|
53
|
+
};
|
|
54
|
+
export type AvailableSubstitutesResponse = {
|
|
55
55
|
status: "available";
|
|
56
56
|
signatureUsed: AvailableSubstituteSignature;
|
|
57
57
|
items: SubstituteResultItem[];
|
|
@@ -69,7 +69,7 @@ export interface AvailableSubstitutesResponse {
|
|
|
69
69
|
poolTruncated: boolean;
|
|
70
70
|
supersededBy: MaterialSuccessor | null;
|
|
71
71
|
nextCursor?: string;
|
|
72
|
-
}
|
|
72
|
+
};
|
|
73
73
|
/**
|
|
74
74
|
* MG-1686. The search read a bounded window of the matches and nothing in it
|
|
75
75
|
* reached the page, while more matches existed past the window. It is not an
|
|
@@ -77,7 +77,7 @@ export interface AvailableSubstitutesResponse {
|
|
|
77
77
|
* empty `items`. `reason` names what happened and the next move; follow
|
|
78
78
|
* `nextCursor` when it is present.
|
|
79
79
|
*/
|
|
80
|
-
export
|
|
80
|
+
export type InconclusiveSubstitutesResponse = {
|
|
81
81
|
status: "inconclusive";
|
|
82
82
|
signatureUsed: AvailableSubstituteSignature;
|
|
83
83
|
items: [];
|
|
@@ -86,17 +86,17 @@ export interface InconclusiveSubstitutesResponse {
|
|
|
86
86
|
reason: string;
|
|
87
87
|
supersededBy: MaterialSuccessor | null;
|
|
88
88
|
nextCursor?: string;
|
|
89
|
-
}
|
|
90
|
-
export
|
|
89
|
+
};
|
|
90
|
+
export type UnsupportedSubstitutesResponse = {
|
|
91
91
|
status: "unsupported";
|
|
92
92
|
signature: UnsupportedSubstituteSignature;
|
|
93
93
|
items: [];
|
|
94
94
|
supersededBy: MaterialSuccessor | null;
|
|
95
|
-
}
|
|
96
|
-
export
|
|
95
|
+
};
|
|
96
|
+
export type InsufficientSubstitutesResponse = {
|
|
97
97
|
status: "insufficient_signature";
|
|
98
98
|
signature: InsufficientSubstituteSignature;
|
|
99
99
|
items: [];
|
|
100
100
|
supersededBy: MaterialSuccessor | null;
|
|
101
|
-
}
|
|
101
|
+
};
|
|
102
102
|
export type FindSubstitutesResponse = AvailableSubstitutesResponse | InconclusiveSubstitutesResponse | UnsupportedSubstitutesResponse | InsufficientSubstitutesResponse;
|
package/suggest-types.d.ts
CHANGED
|
@@ -12,13 +12,12 @@
|
|
|
12
12
|
* `mg.searchVocabulary()` covers attribute/value tokens. Suggestions are a page
|
|
13
13
|
* of the best matches, never a census of matching entities.
|
|
14
14
|
*/
|
|
15
|
-
import type { CorpusScope, CorpusScopeReceipt } from "./corpus-scope-types.js";
|
|
16
15
|
/** Which kind of entity a suggestion is — and therefore what `refId` means. */
|
|
17
16
|
export type SuggestKind = "product" | "brand" | "category";
|
|
18
17
|
/** How the query met the suggestion's label. Strongest first. */
|
|
19
|
-
export type SuggestMatch = "prefix" | "word" | "
|
|
18
|
+
export type SuggestMatch = "prefix" | "word" | "fuzzy";
|
|
20
19
|
/** One ranked typeahead suggestion, carrying the identity it resolves to. */
|
|
21
|
-
export
|
|
20
|
+
export type Suggestion = {
|
|
22
21
|
kind: SuggestKind;
|
|
23
22
|
/** The entity's name as written, for display. */
|
|
24
23
|
label: string;
|
|
@@ -36,27 +35,23 @@ export interface Suggestion {
|
|
|
36
35
|
* Opaque, and null when none was picked — not a product without variants.
|
|
37
36
|
*/
|
|
38
37
|
variantId: string | null;
|
|
39
|
-
/**
|
|
38
|
+
/** How many of this entity's variants the search index holds: a coverage figure. */
|
|
40
39
|
variantCount: number;
|
|
41
|
-
}
|
|
40
|
+
};
|
|
42
41
|
/** The suggest response: the query as interpreted, plus the ranked suggestions. */
|
|
43
|
-
export
|
|
44
|
-
/** The
|
|
42
|
+
export type SuggestResponse = {
|
|
43
|
+
/** The typed words the search index was matched against. */
|
|
45
44
|
query: string;
|
|
46
|
-
/** Ranked best-match-first. Empty when nothing came close
|
|
45
|
+
/** Ranked best-match-first. Empty when nothing came close: a miss, not an error. */
|
|
47
46
|
suggestions: Suggestion[];
|
|
48
|
-
|
|
49
|
-
corpusScope?: CorpusScopeReceipt;
|
|
50
|
-
}
|
|
47
|
+
};
|
|
51
48
|
/** Options for {@link MaterialGraphClient.suggest}. */
|
|
52
|
-
export
|
|
49
|
+
export type SuggestOptions = {
|
|
53
50
|
/** How many suggestions to return (1–20, default 8). */
|
|
54
51
|
limit?: number;
|
|
55
52
|
/** Restrict to these kinds. Omit for all of them. */
|
|
56
53
|
kind?: SuggestKind | SuggestKind[];
|
|
57
|
-
|
|
58
|
-
corpusScope?: CorpusScope;
|
|
59
|
-
}
|
|
54
|
+
};
|
|
60
55
|
/**
|
|
61
56
|
* Shape the query string for a suggest call.
|
|
62
57
|
*
|
|
@@ -65,9 +60,8 @@ export interface SuggestOptions {
|
|
|
65
60
|
* here rather than being sent as repeated `?kind=` pairs the route would ignore.
|
|
66
61
|
* Undefined members are dropped by the transport.
|
|
67
62
|
*/
|
|
68
|
-
export declare
|
|
63
|
+
export declare const suggestQuery: (q: string, options?: SuggestOptions) => {
|
|
69
64
|
q: string;
|
|
70
65
|
limit?: number;
|
|
71
66
|
kind?: string;
|
|
72
|
-
corpusScope?: CorpusScope;
|
|
73
67
|
};
|
package/suggest-types.js
CHANGED
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
* here rather than being sent as repeated `?kind=` pairs the route would ignore.
|
|
21
21
|
* Undefined members are dropped by the transport.
|
|
22
22
|
*/
|
|
23
|
-
export
|
|
23
|
+
export const suggestQuery = (q, options) => {
|
|
24
24
|
const kind = Array.isArray(options?.kind)
|
|
25
25
|
? options.kind.join(",")
|
|
26
26
|
: options?.kind;
|
|
27
|
-
return {
|
|
28
|
-
}
|
|
27
|
+
return { kind, limit: options?.limit, q };
|
|
28
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Exact, source-path-grained status coverage for primary product typing. */
|
|
2
|
-
export
|
|
2
|
+
export type ProductTypeStatusCoverageCounts = {
|
|
3
3
|
variants: number;
|
|
4
4
|
accepted: number;
|
|
5
5
|
proposed: number;
|
|
@@ -8,13 +8,13 @@ export interface ProductTypeStatusCoverageCounts {
|
|
|
8
8
|
proposedUnknownConfidence: number;
|
|
9
9
|
otherStatus: number;
|
|
10
10
|
missingPrimary: number;
|
|
11
|
-
}
|
|
12
|
-
export
|
|
11
|
+
};
|
|
12
|
+
export type ProductTypeStatusCoverageSourcePath = {
|
|
13
13
|
/** Complete stored source path; null means the product retained no path. */
|
|
14
14
|
sourcePath: string | null;
|
|
15
|
-
}
|
|
15
|
+
} & ProductTypeStatusCoverageCounts;
|
|
16
16
|
/** Current primary-assignment coverage, never an inferred acceptance decision. */
|
|
17
|
-
export
|
|
17
|
+
export type ProductTypeStatusCoverage = {
|
|
18
18
|
computedAt: string;
|
|
19
19
|
basis: {
|
|
20
20
|
count: "exact";
|
|
@@ -26,9 +26,9 @@ export interface ProductTypeStatusCoverage {
|
|
|
26
26
|
};
|
|
27
27
|
totals: ProductTypeStatusCoverageCounts;
|
|
28
28
|
sourcePaths: ProductTypeStatusCoverageSourcePath[];
|
|
29
|
-
}
|
|
30
|
-
export
|
|
29
|
+
};
|
|
30
|
+
export type ProductTypeCoverageOptions = {
|
|
31
31
|
[key: string]: number | undefined;
|
|
32
32
|
/** Reporting cutoff in [0,1], default 0.85; it never accepts a proposal. */
|
|
33
33
|
comparisonThreshold?: number;
|
|
34
|
-
}
|
|
34
|
+
};
|