@instruments/materialgraph 0.28.0 → 0.30.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 +1 -1
- package/by-colour-types.d.ts +4 -4
- package/catalogue-client.d.ts +3 -3
- package/catalogue-client.js +3 -3
- package/catalogue-types.d.ts +1 -1
- package/client-vocabulary.d.ts +3 -5
- package/client-vocabulary.js +9 -6
- package/client.d.ts +73 -174
- package/client.js +85 -211
- package/colour-region-types.d.ts +18 -0
- package/colours-client.d.ts +10 -83
- package/colours-client.js +1 -85
- package/find-variants-by-colour-types.d.ts +197 -0
- package/find-variants-by-vector-types.d.ts +67 -0
- package/find-variants-by-vector-types.js +5 -0
- package/get-variant-types.d.ts +50 -0
- package/get-variant-types.js +10 -0
- package/identifiers.d.ts +1 -1
- package/identifiers.js +1 -1
- package/image-reference-types.d.ts +18 -0
- package/index.d.ts +8 -7
- package/index.js +1 -1
- package/list-enum-values-types.d.ts +58 -0
- package/list-variants-types.d.ts +6 -2
- package/material-asset-types.d.ts +4 -3
- package/material-types.d.ts +11 -150
- package/operations.d.ts +1 -1
- package/operations.js +26 -88
- package/package.json +1 -1
- package/palette-search-types.d.ts +3 -49
- package/resolve-colour-types.d.ts +5 -5
- package/resolve-variant-types.d.ts +75 -0
- package/{identify-types.js → resolve-variant-types.js} +2 -2
- package/response-schemas.generated.d.ts +1 -1
- package/response-schemas.generated.js +45 -84
- package/run-types.d.ts +23 -216
- package/runs.d.ts +10 -58
- package/runs.js +19 -106
- package/schema-resource-types.d.ts +2 -139
- package/schema-resource-types.js +0 -8
- package/search-card-types.d.ts +1 -1
- package/search-index-plan-types.d.ts +4 -1
- package/search-request-types.d.ts +10 -2
- package/spec-types.d.ts +4 -4
- package/spec-types.js +2 -2
- package/sse.d.ts +2 -2
- package/sse.js +2 -2
- package/types.d.ts +4 -38
- package/webmcp.generated.js +3 -3
- package/workflows-client.d.ts +54 -0
- package/workflows-client.js +41 -0
- package/client-source-material-comments.d.ts +0 -51
- package/client-source-material-comments.js +0 -6
- package/codes-client.d.ts +0 -118
- package/codes-client.js +0 -99
- package/codes-types.d.ts +0 -325
- package/colour-aggregate-types.d.ts +0 -163
- package/coordinate-client.d.ts +0 -23
- package/coordinate-client.js +0 -13
- package/demand-batch-types.d.ts +0 -118
- package/demand-types.d.ts +0 -154
- package/identify-types.d.ts +0 -82
- package/material-composition-client.d.ts +0 -21
- package/material-composition-client.js +0 -13
- package/material-composition-types.d.ts +0 -403
- package/material-composition-types.js +0 -1
- package/source-material-validation.d.ts +0 -7
- package/source-material-validation.js +0 -214
- package/spec-facet-types.d.ts +0 -48
- package/spec-facet-types.js +0 -7
- package/substitute-types.d.ts +0 -102
- package/substitute-types.js +0 -1
- package/suggest-types.d.ts +0 -67
- package/suggest-types.js +0 -28
- package/taxonomy-coverage-types.d.ts +0 -34
- package/taxonomy-coverage-types.js +0 -1
- /package/{codes-types.js → colour-region-types.js} +0 -0
- /package/{colour-aggregate-types.js → find-variants-by-colour-types.js} +0 -0
- /package/{demand-batch-types.js → image-reference-types.js} +0 -0
- /package/{demand-types.js → list-enum-values-types.js} +0 -0
package/demand-types.d.ts
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Wire types for the SINGLE-SEED demand reads — `GET /api/v1/demand` and
|
|
3
|
-
* `POST /api/v1/pairings/coordinate`.
|
|
4
|
-
*
|
|
5
|
-
* Split out of `types.ts` for the repository's source-file size budget, the same
|
|
6
|
-
* reason `material-types.ts` and `demand-batch-types.ts` sit beside it; both are
|
|
7
|
-
* re-exported from `types.ts`, so importers see no difference.
|
|
8
|
-
*
|
|
9
|
-
* THE LENS: demand answers "how much is this specified, and what travels with
|
|
10
|
-
* it?" from real order behaviour. It is not a search and not a recommendation
|
|
11
|
-
* engine — every number is bounded by the `trailing_36mo` window and by the
|
|
12
|
-
* {@link DemandSignal} it was read under, and a missing number means UNREAD, not
|
|
13
|
-
* zero.
|
|
14
|
-
*/
|
|
15
|
-
import type { ProductId, VariantId } from "./identifiers.js";
|
|
16
|
-
import type { CompanionDemand, DemandMomentum, DemandQuarter, OpenEnum } from "./types.js";
|
|
17
|
-
/** A resolved seed material (identity block shared by the demand reads). */
|
|
18
|
-
export type DemandSeed = {
|
|
19
|
-
/** Opaque — round-trip verbatim. */
|
|
20
|
-
variantId: VariantId;
|
|
21
|
-
brand: string;
|
|
22
|
-
product: string;
|
|
23
|
-
color: string | null;
|
|
24
|
-
variantName: string | null;
|
|
25
|
-
imageUrl: string | null;
|
|
26
|
-
brandSlug: string;
|
|
27
|
-
productId: ProductId;
|
|
28
|
-
};
|
|
29
|
-
/** Headline demand stats for a seed: counts, quarterly series, momentum. */
|
|
30
|
-
export type MaterialDemandStats = {
|
|
31
|
-
specCount: number;
|
|
32
|
-
projectCount: number;
|
|
33
|
-
customerCount: number;
|
|
34
|
-
/** Sparse — a quarter with no activity is ABSENT, not a zero row. */
|
|
35
|
-
byQuarter: DemandQuarter[];
|
|
36
|
-
momentum: DemandMomentum;
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* `getMaterialDemand` result, passed through verbatim by the `/demand` route.
|
|
40
|
-
*
|
|
41
|
-
* `demand: null` means NO READING — the seed did not resolve, or nothing cleared
|
|
42
|
-
* the publication floor. It is never a reading of zero, and never licenses
|
|
43
|
-
* "nobody specifies this".
|
|
44
|
-
*/
|
|
45
|
-
export type MaterialDemandResult = {
|
|
46
|
-
found: boolean;
|
|
47
|
-
query: string;
|
|
48
|
-
seed: DemandSeed | null;
|
|
49
|
-
/** The only window v1 serves. Activity outside it is unread, not absent. */
|
|
50
|
-
window: "trailing_36mo";
|
|
51
|
-
demand: MaterialDemandStats | null;
|
|
52
|
-
};
|
|
53
|
-
/**
|
|
54
|
-
* `getCoSpecifiedMaterials` result, passed through verbatim. The `companions`
|
|
55
|
-
* list (materials specified alongside the seed) is included but left loosely
|
|
56
|
-
* typed — there is no captured fixture to pin its full shape.
|
|
57
|
-
*
|
|
58
|
-
* `resolution` is the honest report on the free-text seed: `ambiguous` means the
|
|
59
|
-
* phrase matched several materials and `seedAlternatives` holds them — pick one
|
|
60
|
-
* and re-ask by `variantId` rather than treating the first as the answer.
|
|
61
|
-
*/
|
|
62
|
-
export type CoSpecifiedResult = {
|
|
63
|
-
found: boolean;
|
|
64
|
-
resolution: OpenEnum<"resolved" | "ambiguous" | "not_found">;
|
|
65
|
-
query: string;
|
|
66
|
-
seed: DemandSeed | null;
|
|
67
|
-
seedCategory: string | null;
|
|
68
|
-
seedAlternatives: DemandSeed[];
|
|
69
|
-
companions?: unknown[];
|
|
70
|
-
};
|
|
71
|
-
/** The `/api/v1/demand` envelope — both domain reads side by side, verbatim. */
|
|
72
|
-
export type DemandResponse = {
|
|
73
|
-
query: string;
|
|
74
|
-
demand: MaterialDemandResult;
|
|
75
|
-
cospec: CoSpecifiedResult;
|
|
76
|
-
};
|
|
77
|
-
/** Seed a demand read by EXACTLY ONE of `variantId` or `material`. */
|
|
78
|
-
export type DemandParams = {
|
|
79
|
-
/** An exact variant id. Opaque — pass through verbatim. */
|
|
80
|
-
variantId?: VariantId;
|
|
81
|
-
/** Free text ("Brand Product Colour"), resolved server-side. May be ambiguous. */
|
|
82
|
-
material?: string;
|
|
83
|
-
};
|
|
84
|
-
export type CoordinateSeed = {
|
|
85
|
-
/** The input reference this seed resolved from. */
|
|
86
|
-
resolvedFrom: string;
|
|
87
|
-
} & DemandSeed;
|
|
88
|
-
export type CoordinateCompanion = {
|
|
89
|
-
/** Opaque — round-trip verbatim. */
|
|
90
|
-
variantId: VariantId;
|
|
91
|
-
brand: string;
|
|
92
|
-
product: string;
|
|
93
|
-
color: string | null;
|
|
94
|
-
variantName: string | null;
|
|
95
|
-
imageUrl: string | null;
|
|
96
|
-
brandSlug: string;
|
|
97
|
-
productId: ProductId;
|
|
98
|
-
/**
|
|
99
|
-
* How this companion relates to the SEED SET — the closest relation that
|
|
100
|
-
* applies to any seed.
|
|
101
|
-
*
|
|
102
|
-
* `companion` is foreign to every seed: a maker the caller did not pick.
|
|
103
|
-
* `brand_sibling` shares a brand with some seed. `colourway` is a seed's own
|
|
104
|
-
* product restyled, and completes nothing.
|
|
105
|
-
*
|
|
106
|
-
* READ IT BEFORE CLAIMING BREADTH. Measured across the live edges (MG-1007),
|
|
107
|
-
* 70.6% are same-brand and 24.3% are the seed's own product in another
|
|
108
|
-
* colourway; on a two-seed rail, 27 of 40 companions came from the seeds' own
|
|
109
|
-
* two brands. A surface headed "makers you haven't picked" that does not
|
|
110
|
-
* filter on this is making a claim the evidence does not support — the
|
|
111
|
-
* measured case showed two distinct makers under a heading promising seven.
|
|
112
|
-
*
|
|
113
|
-
* The server has always sent this field; it was absent from this interface
|
|
114
|
-
* until 2026-08-23, so consumers could not see it and hand-rolled the same
|
|
115
|
-
* comparison against `brandSlug` themselves.
|
|
116
|
-
*/
|
|
117
|
-
relation: "companion" | "brand_sibling" | "colourway";
|
|
118
|
-
totalLift: number;
|
|
119
|
-
liftLabel: string;
|
|
120
|
-
seedMatchCount: number;
|
|
121
|
-
seedContributions: {
|
|
122
|
-
seedVariantId: VariantId;
|
|
123
|
-
lift: number;
|
|
124
|
-
}[];
|
|
125
|
-
demand: CompanionDemand | null;
|
|
126
|
-
swatches: {
|
|
127
|
-
hex: string;
|
|
128
|
-
proportion: number;
|
|
129
|
-
}[];
|
|
130
|
-
/** Annotate-only appearance similarity — never reorders companions in v1. */
|
|
131
|
-
colourFit: number | null;
|
|
132
|
-
};
|
|
133
|
-
/**
|
|
134
|
-
* The `POST /api/v1/pairings/coordinate` envelope. `unresolved` lists the input
|
|
135
|
-
* references that matched nothing — read it before presenting `companions` as
|
|
136
|
-
* "what goes with your palette", because a companion set derived from two of
|
|
137
|
-
* four seeds is a different claim.
|
|
138
|
-
*/
|
|
139
|
-
export type CoordinateResponse = {
|
|
140
|
-
seeds: CoordinateSeed[];
|
|
141
|
-
/** Input references that resolved to no material. Never silently dropped. */
|
|
142
|
-
unresolved: string[];
|
|
143
|
-
window: "trailing_36mo";
|
|
144
|
-
companions: CoordinateCompanion[];
|
|
145
|
-
};
|
|
146
|
-
/** Body for `POST /api/v1/pairings/coordinate`. */
|
|
147
|
-
export type CoordinateInput = {
|
|
148
|
-
/** Free-text material references, resolved server-side; misses land in `unresolved`. */
|
|
149
|
-
materials?: string[];
|
|
150
|
-
/** Exact variant ids. Opaque — pass through verbatim. */
|
|
151
|
-
variantIds?: VariantId[];
|
|
152
|
-
projectType?: string;
|
|
153
|
-
limit?: number;
|
|
154
|
-
};
|
package/identify-types.d.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Public wire types for `POST /api/v1/identify` (MG-1672's `resolve_variant`
|
|
3
|
-
* contract).
|
|
4
|
-
*
|
|
5
|
-
* These intentionally mirror the domain-owned Zod contract
|
|
6
|
-
* (`@materialgraph/products/identify-contract`) rather than importing it: the
|
|
7
|
-
* published SDK must carry no workspace package dependency.
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* What `mg.identify()` accepts. Give `url` alone, or `code` with `brandId`
|
|
11
|
-
* (from `mg.brands()`) when there is no page to read. `labels` are product
|
|
12
|
-
* names visible on the page, sent only to tell several URL candidates apart -
|
|
13
|
-
* they never widen a search or invent an identity on their own.
|
|
14
|
-
*/
|
|
15
|
-
export type IdentifyVariantInput = {
|
|
16
|
-
url?: string;
|
|
17
|
-
code?: string;
|
|
18
|
-
brandId?: string;
|
|
19
|
-
labels?: string[];
|
|
20
|
-
};
|
|
21
|
-
/** One identified, placed or bounded-candidate subject. */
|
|
22
|
-
export type IdentifySubject = {
|
|
23
|
-
kind: "variant" | "brand";
|
|
24
|
-
id: string;
|
|
25
|
-
name: string;
|
|
26
|
-
code?: string;
|
|
27
|
-
brand?: {
|
|
28
|
-
id: string;
|
|
29
|
-
name: string;
|
|
30
|
-
};
|
|
31
|
-
};
|
|
32
|
-
/** What stood behind an outcome. Exact and scoreless: never a similarity guess. */
|
|
33
|
-
export type IdentifyEvidence = {
|
|
34
|
-
kind: "manufacturer-url" | "brand-homepage" | "manufacturer-code" | "visible-label";
|
|
35
|
-
url?: string;
|
|
36
|
-
detail: string;
|
|
37
|
-
};
|
|
38
|
-
/** The submitted URL, normalised, and the steps that normalisation took. Absent for a code-only call. */
|
|
39
|
-
export type IdentifyReceipt = {
|
|
40
|
-
submittedUrl: string;
|
|
41
|
-
normalizedUrl: string;
|
|
42
|
-
normalizationSteps: string[];
|
|
43
|
-
};
|
|
44
|
-
type IdentifyResultBase = {
|
|
45
|
-
evidence: IdentifyEvidence[];
|
|
46
|
-
receipt?: IdentifyReceipt;
|
|
47
|
-
};
|
|
48
|
-
/**
|
|
49
|
-
* Why nothing was identified. Absent and empty differ: this names what was
|
|
50
|
-
* looked for and not found, never a similarity guess.
|
|
51
|
-
*/
|
|
52
|
-
export type IdentifyUnresolvedReason = "no-stored-url" | "no-code-match";
|
|
53
|
-
/** Exact identities only - no rung carries a similarity score. */
|
|
54
|
-
export type IdentifyResult = (IdentifyResultBase & {
|
|
55
|
-
outcome: "identified";
|
|
56
|
-
subject: IdentifySubject & {
|
|
57
|
-
kind: "variant";
|
|
58
|
-
};
|
|
59
|
-
}) | (IdentifyResultBase & {
|
|
60
|
-
outcome: "placed";
|
|
61
|
-
subject: IdentifySubject & {
|
|
62
|
-
kind: "brand";
|
|
63
|
-
};
|
|
64
|
-
}) | (IdentifyResultBase & {
|
|
65
|
-
outcome: "ambiguous";
|
|
66
|
-
candidates: IdentifySubject[];
|
|
67
|
-
truncated: boolean;
|
|
68
|
-
}) | (IdentifyResultBase & {
|
|
69
|
-
outcome: "unresolved";
|
|
70
|
-
reason: IdentifyUnresolvedReason;
|
|
71
|
-
});
|
|
72
|
-
/** The canonical callable-operation envelope returned by `identify()`. */
|
|
73
|
-
export type IdentifyResponse = {
|
|
74
|
-
data: IdentifyResult;
|
|
75
|
-
meta: {
|
|
76
|
-
operationId: "retrieval.identify";
|
|
77
|
-
requestId: string;
|
|
78
|
-
};
|
|
79
|
-
links: Record<string, never>;
|
|
80
|
-
warnings: [];
|
|
81
|
-
};
|
|
82
|
-
export {};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The MATERIAL COMPOSITION lens: what a product is made of, and how far the
|
|
3
|
-
* corpus that answers that question has got (MG-1969).
|
|
4
|
-
*
|
|
5
|
-
* Not `./composition-client.ts`, which wraps the slot pools a scheme composer
|
|
6
|
-
* outside MaterialGraph reads.
|
|
7
|
-
*/
|
|
8
|
-
import type { HttpTransport } from "./http-transport.js";
|
|
9
|
-
import type { CompositionCorpusSummary } from "./material-composition-types.js";
|
|
10
|
-
/**
|
|
11
|
-
* THE QUESTION: "which product types can we answer that question for yet?"
|
|
12
|
-
*
|
|
13
|
-
* Coverage per product type, counted in Live SKUs as well as in tuples. Read
|
|
14
|
-
* the SKU figure: one tuple can carry a hundred thousand SKUs or one, so a
|
|
15
|
-
* corpus that resolved every rare tuple and none of the common ones reads as
|
|
16
|
-
* good coverage counted by tuple.
|
|
17
|
-
*
|
|
18
|
-
* A type in `completeness.authoringQueue` has no bar set, which is never the
|
|
19
|
-
* same as a bar it missed. Requires the `mg:read` scope.
|
|
20
|
-
*/
|
|
21
|
-
export declare const compositionReport: (transport: HttpTransport, signal?: AbortSignal) => Promise<CompositionCorpusSummary>;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { resolveOperation } from "./operations.js";
|
|
2
|
-
/**
|
|
3
|
-
* THE QUESTION: "which product types can we answer that question for yet?"
|
|
4
|
-
*
|
|
5
|
-
* Coverage per product type, counted in Live SKUs as well as in tuples. Read
|
|
6
|
-
* the SKU figure: one tuple can carry a hundred thousand SKUs or one, so a
|
|
7
|
-
* corpus that resolved every rare tuple and none of the common ones reads as
|
|
8
|
-
* good coverage counted by tuple.
|
|
9
|
-
*
|
|
10
|
-
* A type in `completeness.authoringQueue` has no bar set, which is never the
|
|
11
|
-
* same as a bar it missed. Requires the `mg:read` scope.
|
|
12
|
-
*/
|
|
13
|
-
export const compositionReport = async (transport, signal) => await transport.requestJson(resolveOperation("get_composition_report"), { signal });
|
|
@@ -1,403 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hand-mirrored wire types for MATERIAL composition — what a product is made
|
|
3
|
-
* of (`GET /api/v1/materials/{variantId}/composition`, operation
|
|
4
|
-
* `get_material_composition`, and `GET /api/v1/composition/report`, operation
|
|
5
|
-
* `get_composition_report`; MG-1969).
|
|
6
|
-
*
|
|
7
|
-
* Composition means only this. It is unrelated to `./slot-pool-types.ts`,
|
|
8
|
-
* the candidate pools a scheme composer outside MaterialGraph reads.
|
|
9
|
-
*
|
|
10
|
-
* Like the rest of the SDK these interfaces carry NO runtime dependency on any
|
|
11
|
-
* `@materialgraph/*` package; they mirror the `VariantComposition` and
|
|
12
|
-
* `CompositionCorpusSummary` shapes in `apps/web/public/openapi.yaml`.
|
|
13
|
-
*
|
|
14
|
-
* TOLERANT-PARSING CONTRACT: response enums are widened with {@link OpenEnum}
|
|
15
|
-
* so a new server value still type-checks; objects are read structurally. The
|
|
16
|
-
* one exception is {@link VariantCompositionAbsence}, which is closed —
|
|
17
|
-
* see below.
|
|
18
|
-
*/
|
|
19
|
-
import type { VariantId } from "./identifiers.js";
|
|
20
|
-
import type { OpenEnum } from "./types.js";
|
|
21
|
-
/**
|
|
22
|
-
* Why no parse stands behind a material. CLOSED on purpose: a consumer must
|
|
23
|
-
* branch on every arm, and widening it would let a new reason fall through a
|
|
24
|
-
* branch that reads "one of these two, so it must be the other".
|
|
25
|
-
*
|
|
26
|
-
* - `no_material_bank_sku` — the variant was never a Material Bank SKU, so
|
|
27
|
-
* there is no catalogue row anyone could have parsed.
|
|
28
|
-
* - `not_linked` — it has a SKU and the corpus has not reached it. A statement
|
|
29
|
-
* about MaterialGraph's coverage, never about the material.
|
|
30
|
-
*
|
|
31
|
-
* Neither is the same as a present parse whose `status` is `empty`: that is the
|
|
32
|
-
* catalogue row saying it declared nothing, which is knowledge.
|
|
33
|
-
*/
|
|
34
|
-
export type VariantCompositionAbsence = "no_material_bank_sku" | "not_linked";
|
|
35
|
-
/** `failed_closed` means the parser refused rather than guessed. */
|
|
36
|
-
export type CompositionParseStatus = OpenEnum<"parsed" | "empty" | "failed_closed">;
|
|
37
|
-
/** One document or catalogue column the record's facts are taken from. */
|
|
38
|
-
export type CompositionSource = {
|
|
39
|
-
id: string;
|
|
40
|
-
kind: OpenEnum<"epd" | "hpd" | "technical_document" | "manufacturer" | "reseller" | "test_report" | "catalogue_field" | "inference" | "other">;
|
|
41
|
-
/** A URL, a document name, or the catalogue column name. */
|
|
42
|
-
locator: string;
|
|
43
|
-
retrievedAt?: string;
|
|
44
|
-
/** The source's wording, verbatim. Never corrected or completed. */
|
|
45
|
-
statement?: string;
|
|
46
|
-
title?: string;
|
|
47
|
-
};
|
|
48
|
-
/**
|
|
49
|
-
* A percentage as the source gives it, or one of the four ways a source can
|
|
50
|
-
* name a node and still withhold the number. `undisclosed` holds its place in
|
|
51
|
-
* the sum; `alternate` sits outside it.
|
|
52
|
-
*/
|
|
53
|
-
export type CompositionAmount = {
|
|
54
|
-
kind: "exact";
|
|
55
|
-
value: number;
|
|
56
|
-
} | {
|
|
57
|
-
kind: "range";
|
|
58
|
-
max: number;
|
|
59
|
-
min: number;
|
|
60
|
-
} | {
|
|
61
|
-
kind: "bound";
|
|
62
|
-
operator: OpenEnum<"at_most" | "at_least" | "less_than" | "greater_than">;
|
|
63
|
-
value: number;
|
|
64
|
-
} | {
|
|
65
|
-
kind: "unknown";
|
|
66
|
-
} | {
|
|
67
|
-
kind: "undisclosed";
|
|
68
|
-
reason: OpenEnum<"trade_secret" | "not_provided">;
|
|
69
|
-
} | {
|
|
70
|
-
kind: "conditionally_present";
|
|
71
|
-
max: number;
|
|
72
|
-
} | {
|
|
73
|
-
kind: "band";
|
|
74
|
-
band: string;
|
|
75
|
-
version: string;
|
|
76
|
-
vocabulary: string;
|
|
77
|
-
} | {
|
|
78
|
-
kind: "alternate";
|
|
79
|
-
} | {
|
|
80
|
-
kind: string;
|
|
81
|
-
};
|
|
82
|
-
/** How much of its parent, or of the whole product, a node is. */
|
|
83
|
-
export type CompositionShare = {
|
|
84
|
-
amount: CompositionAmount;
|
|
85
|
-
/** What the percentage measures, only as the source says it. Never converted. */
|
|
86
|
-
basis: OpenEnum<"mass" | "volume" | "fibre_mass" | "area" | "count" | "thickness" | "unspecified">;
|
|
87
|
-
of: OpenEnum<"parent" | "product">;
|
|
88
|
-
source: string;
|
|
89
|
-
};
|
|
90
|
-
/** An absolute figure the source states, in its own unit. Never in the sum. */
|
|
91
|
-
export type CompositionQuantity = {
|
|
92
|
-
amount: {
|
|
93
|
-
kind: "exact";
|
|
94
|
-
value: number;
|
|
95
|
-
} | {
|
|
96
|
-
kind: "range";
|
|
97
|
-
max: number;
|
|
98
|
-
min: number;
|
|
99
|
-
} | {
|
|
100
|
-
kind: "bound";
|
|
101
|
-
operator: OpenEnum<"at_most" | "at_least" | "less_than" | "greater_than">;
|
|
102
|
-
value: number;
|
|
103
|
-
} | {
|
|
104
|
-
kind: string;
|
|
105
|
-
};
|
|
106
|
-
/** The figure and unit as the source writes them. */
|
|
107
|
-
raw: string;
|
|
108
|
-
unit: OpenEnum<"mm" | "in" | "mil" | "gauge" | "oz_yd2" | "g_m2" | "kg" | "kg_m3" | "pcf" | "dtex" | "denier" | "ply">;
|
|
109
|
-
};
|
|
110
|
-
/**
|
|
111
|
-
* Which substance a component is. `resolution` is the field to read before
|
|
112
|
-
* trusting `term`: `identified` is the only arm carrying a dictionary id that
|
|
113
|
-
* means what the source said.
|
|
114
|
-
*/
|
|
115
|
-
export type CompositionTermRef = {
|
|
116
|
-
/** The source's own words, verbatim. */
|
|
117
|
-
raw: string;
|
|
118
|
-
resolution: OpenEnum<"identified" | "proprietary" | "withheld" | "unresolved">;
|
|
119
|
-
source?: string;
|
|
120
|
-
term?: string;
|
|
121
|
-
};
|
|
122
|
-
/** Dictionary ids qualifying a term without changing it. */
|
|
123
|
-
export type CompositionModifiers = {
|
|
124
|
-
brand?: string;
|
|
125
|
-
cut?: string;
|
|
126
|
-
grade?: string;
|
|
127
|
-
origin?: string;
|
|
128
|
-
process?: string[];
|
|
129
|
-
provenance?: string;
|
|
130
|
-
treatment?: string[];
|
|
131
|
-
};
|
|
132
|
-
/** A statement about a node that is not a share. Claims never enter the sum. */
|
|
133
|
-
export type CompositionClaim = {
|
|
134
|
-
amount?: CompositionAmount;
|
|
135
|
-
kind: OpenEnum<"free_of" | "contains" | "recyclable" | "renewable" | "bio_based" | "biodegradable" | "compostable" | "certified" | "other">;
|
|
136
|
-
/** The claim's wording, verbatim. */
|
|
137
|
-
raw: string;
|
|
138
|
-
source: string;
|
|
139
|
-
term?: string;
|
|
140
|
-
};
|
|
141
|
-
/** The level above which the source says every substance is listed. */
|
|
142
|
-
export type CompositionThreshold = {
|
|
143
|
-
raw: string;
|
|
144
|
-
regime: OpenEnum<"100_ppm" | "1000_ppm" | "ghs_sds" | "other">;
|
|
145
|
-
scope: OpenEnum<"product" | "material">;
|
|
146
|
-
source: string;
|
|
147
|
-
};
|
|
148
|
-
/**
|
|
149
|
-
* Whether the source presents a node's children as exhaustive. `partial` and
|
|
150
|
-
* `unspecified` are both statements about the SOURCE; neither licenses adding
|
|
151
|
-
* a child to make a list add up.
|
|
152
|
-
*/
|
|
153
|
-
export type CompositionCoverage = {
|
|
154
|
-
claim: OpenEnum<"complete" | "partial" | "unspecified">;
|
|
155
|
-
source?: string;
|
|
156
|
-
threshold?: CompositionThreshold;
|
|
157
|
-
};
|
|
158
|
-
/** Why the unstated part of a composition is unstated. */
|
|
159
|
-
export type CompositionRemainder = {
|
|
160
|
-
kind: "legally_omitted";
|
|
161
|
-
regime: OpenEnum<"eu_1007_2011" | "us_16_cfr_303">;
|
|
162
|
-
rule: string;
|
|
163
|
-
source: string;
|
|
164
|
-
} | {
|
|
165
|
-
kind: "undisclosed";
|
|
166
|
-
reason: OpenEnum<"trade_secret" | "not_provided">;
|
|
167
|
-
source: string;
|
|
168
|
-
} | {
|
|
169
|
-
kind: string;
|
|
170
|
-
};
|
|
171
|
-
/** One named substance with its share. Never an unstated remainder. */
|
|
172
|
-
export type CompositionComponent = {
|
|
173
|
-
claims: CompositionClaim[];
|
|
174
|
-
/** "Of which" subsets of this component; their shares are of it. */
|
|
175
|
-
components?: CompositionComponent[];
|
|
176
|
-
id: string;
|
|
177
|
-
identity: CompositionTermRef;
|
|
178
|
-
modifiers: CompositionModifiers;
|
|
179
|
-
quantity?: CompositionQuantity;
|
|
180
|
-
/** What the substance does inside its part, only where the source says. */
|
|
181
|
-
role?: string;
|
|
182
|
-
share: CompositionShare;
|
|
183
|
-
source: string;
|
|
184
|
-
};
|
|
185
|
-
/** A layer or piece of the product. Sibling parts are co-present and sum. */
|
|
186
|
-
export type CompositionPart = {
|
|
187
|
-
claims: CompositionClaim[];
|
|
188
|
-
components: CompositionComponent[];
|
|
189
|
-
construction: string[];
|
|
190
|
-
coverage: CompositionCoverage;
|
|
191
|
-
id: string;
|
|
192
|
-
/** The part's name as the source writes it. */
|
|
193
|
-
label?: string;
|
|
194
|
-
/** Alternatives the buyer chooses between; options never sum with siblings. */
|
|
195
|
-
options?: CompositionPart[];
|
|
196
|
-
parts?: CompositionPart[];
|
|
197
|
-
/** Stacking order among siblings: 0 is the top or outer face. */
|
|
198
|
-
position: number;
|
|
199
|
-
quantity?: CompositionQuantity;
|
|
200
|
-
remainder?: CompositionRemainder;
|
|
201
|
-
role?: string;
|
|
202
|
-
share: CompositionShare;
|
|
203
|
-
source: string;
|
|
204
|
-
};
|
|
205
|
-
/** The composition of one product, as the cited sources state it. */
|
|
206
|
-
export type CompositionRecord = {
|
|
207
|
-
claims: CompositionClaim[];
|
|
208
|
-
/** The whole product's own inventory; never summed with `parts`. */
|
|
209
|
-
components: CompositionComponent[];
|
|
210
|
-
construction: string[];
|
|
211
|
-
coverage: CompositionCoverage;
|
|
212
|
-
id: string;
|
|
213
|
-
name: string;
|
|
214
|
-
/** Alternatives the buyer chooses between, each a full record. */
|
|
215
|
-
options?: CompositionRecord[];
|
|
216
|
-
parts: CompositionPart[];
|
|
217
|
-
primarySource?: string;
|
|
218
|
-
remainder?: CompositionRemainder;
|
|
219
|
-
sources: CompositionSource[];
|
|
220
|
-
};
|
|
221
|
-
/**
|
|
222
|
-
* The record flattened to the `composition_weighted` attribute value.
|
|
223
|
-
*
|
|
224
|
-
* `basis: "tokens_only"` says the PROPORTIONS are unknown, never that the
|
|
225
|
-
* components are, and every entry then carries a component with no `fraction`.
|
|
226
|
-
* An absent `fraction` is an unknown share; `0` is a declared none.
|
|
227
|
-
*/
|
|
228
|
-
export type CompositionWeightedValue = {
|
|
229
|
-
basis: OpenEnum<"declared_percent" | "single_material" | "tokens_only">;
|
|
230
|
-
components: {
|
|
231
|
-
/** A `composition_component` dictionary term id. */
|
|
232
|
-
component: string;
|
|
233
|
-
/** 0 to 1, never a percentage. */
|
|
234
|
-
fraction?: number;
|
|
235
|
-
tolerance?: number;
|
|
236
|
-
}[];
|
|
237
|
-
[key: string]: unknown;
|
|
238
|
-
};
|
|
239
|
-
/** What meeting a need lets a reader do with the record. */
|
|
240
|
-
export type CompositionUnlock = OpenEnum<"specify" | "substitute" | "compare">;
|
|
241
|
-
/**
|
|
242
|
-
* Why a record was not measured against a bar. Null exactly when
|
|
243
|
-
* `completeness` is present. CLOSED, like {@link VariantCompositionAbsence}:
|
|
244
|
-
* a consumer must branch on every arm.
|
|
245
|
-
*
|
|
246
|
-
* - `no_record` — nothing was parsed, so there is nothing to measure.
|
|
247
|
-
* - `no_product_type` — a record exists, but the tuple resolved to no product
|
|
248
|
-
* type, so there is no bar to pick.
|
|
249
|
-
* - `no_bar_set` — both exist and MaterialGraph has authored no requirement
|
|
250
|
-
* for that product type. A gap in OUR registry. Rendering it as an unscored
|
|
251
|
-
* record reads as a fault in the maker's data.
|
|
252
|
-
*/
|
|
253
|
-
export type CompositionCompletenessAbsence = "no_record" | "no_product_type" | "no_bar_set";
|
|
254
|
-
/**
|
|
255
|
-
* A record measured against its product type's authored bar, AT READ TIME.
|
|
256
|
-
* Absent (rather than zeroed) when it could not be measured; read
|
|
257
|
-
* `completenessAbsent` for which of the three reasons applies.
|
|
258
|
-
*/
|
|
259
|
-
export type CompositionCompleteness = {
|
|
260
|
-
met: number;
|
|
261
|
-
needs: {
|
|
262
|
-
id: string;
|
|
263
|
-
label: string;
|
|
264
|
-
met: boolean;
|
|
265
|
-
unlocks: CompositionUnlock[];
|
|
266
|
-
}[];
|
|
267
|
-
productTypeId: string;
|
|
268
|
-
/** met / total, 0 to 1, to three decimal places. */
|
|
269
|
-
share: number;
|
|
270
|
-
total: number;
|
|
271
|
-
/** Open when every need tagged with it is met. */
|
|
272
|
-
unlocks: {
|
|
273
|
-
compare: boolean;
|
|
274
|
-
specify: boolean;
|
|
275
|
-
substitute: boolean;
|
|
276
|
-
};
|
|
277
|
-
};
|
|
278
|
-
/** The stored parse, with the contract it was written under. */
|
|
279
|
-
export type VariantCompositionParse = {
|
|
280
|
-
parseKey: string;
|
|
281
|
-
status: CompositionParseStatus;
|
|
282
|
-
/** Null when the parse stored none; `empty` and `failed_closed` always do. */
|
|
283
|
-
record: CompositionRecord | null;
|
|
284
|
-
projection: CompositionWeightedValue | null;
|
|
285
|
-
/** Unresolved wording, or the error text when the parse failed closed. */
|
|
286
|
-
unresolved: {
|
|
287
|
-
raw: string;
|
|
288
|
-
source: string;
|
|
289
|
-
}[];
|
|
290
|
-
modelId: string;
|
|
291
|
-
schemaVersion: string;
|
|
292
|
-
dictionaryVersion: string;
|
|
293
|
-
parsedAt: string;
|
|
294
|
-
};
|
|
295
|
-
/**
|
|
296
|
-
* What a material is made of, traced to the catalogue columns it came from.
|
|
297
|
-
*
|
|
298
|
-
* READ `absent` FIRST. When it is set there is no parse, and its value says
|
|
299
|
-
* why. When it is null there is a parse, and `parse.status` may still be
|
|
300
|
-
* `empty` — the catalogue row was read and declared nothing.
|
|
301
|
-
*
|
|
302
|
-
* `productType` is inferred for the TUPLE, which many products share, so it is
|
|
303
|
-
* never a statement about this variant's own category.
|
|
304
|
-
*/
|
|
305
|
-
export type VariantComposition = {
|
|
306
|
-
variantId: VariantId;
|
|
307
|
-
materialBankSku: string | null;
|
|
308
|
-
/** The verbatim catalogue cells, keyed by column name. */
|
|
309
|
-
catalogue: {
|
|
310
|
-
tuple: Record<string, string>;
|
|
311
|
-
} | null;
|
|
312
|
-
parse: VariantCompositionParse | null;
|
|
313
|
-
productType: {
|
|
314
|
-
id: string;
|
|
315
|
-
share: number | null;
|
|
316
|
-
} | null;
|
|
317
|
-
completeness: CompositionCompleteness | null;
|
|
318
|
-
/** Null exactly when `completeness` is present. */
|
|
319
|
-
completenessAbsent: CompositionCompletenessAbsence | null;
|
|
320
|
-
absent: VariantCompositionAbsence | null;
|
|
321
|
-
};
|
|
322
|
-
/** A count in both currencies. The Live SKU figure is the answer. */
|
|
323
|
-
export type CompositionCorpusWeight = {
|
|
324
|
-
tuples: number;
|
|
325
|
-
liveSkus: number;
|
|
326
|
-
};
|
|
327
|
-
export type CompositionCorpusShare = CompositionCorpusWeight & {
|
|
328
|
-
liveSkuShare: number | null;
|
|
329
|
-
tupleShare: number | null;
|
|
330
|
-
};
|
|
331
|
-
export type CompositionCorpusNeedCoverage = {
|
|
332
|
-
id: string;
|
|
333
|
-
label: string;
|
|
334
|
-
unlocks: CompositionUnlock[];
|
|
335
|
-
/** Share of the type's measured Live SKUs whose record meets this need. */
|
|
336
|
-
liveSkuShare: number | null;
|
|
337
|
-
tupleShare: number | null;
|
|
338
|
-
};
|
|
339
|
-
export type CompositionCorpusTypeCoverage = {
|
|
340
|
-
productTypeId: string;
|
|
341
|
-
measured: CompositionCorpusWeight;
|
|
342
|
-
failedClosed: CompositionCorpusWeight;
|
|
343
|
-
empty: CompositionCorpusWeight;
|
|
344
|
-
needs: CompositionCorpusNeedCoverage[];
|
|
345
|
-
/**
|
|
346
|
-
* Share of the type's measured rows meeting EVERY need — the whole bar.
|
|
347
|
-
* Not the same as an unlock being open, which only requires the needs
|
|
348
|
-
* tagged with that unlock. Draw a completeness bar from this.
|
|
349
|
-
*/
|
|
350
|
-
complete: {
|
|
351
|
-
liveSkuShare: number | null;
|
|
352
|
-
tupleShare: number | null;
|
|
353
|
-
};
|
|
354
|
-
unlocks: {
|
|
355
|
-
compare: number | null;
|
|
356
|
-
specify: number | null;
|
|
357
|
-
substitute: number | null;
|
|
358
|
-
};
|
|
359
|
-
/** The need the most Live SKUs are missing, or null when every need is met. */
|
|
360
|
-
mostMissedNeed: {
|
|
361
|
-
id: string;
|
|
362
|
-
label: string;
|
|
363
|
-
liveSkus: number;
|
|
364
|
-
} | null;
|
|
365
|
-
};
|
|
366
|
-
/**
|
|
367
|
-
* How far the material composition corpus has got.
|
|
368
|
-
*
|
|
369
|
-
* `authoringQueue` lists product types SKUs were assigned to but no
|
|
370
|
-
* requirement has been written for. They have NO BAR SET, which is why they
|
|
371
|
-
* are listed apart rather than scored zero.
|
|
372
|
-
*/
|
|
373
|
-
export type CompositionCorpusSummary = {
|
|
374
|
-
completeness: {
|
|
375
|
-
authoringQueue: (CompositionCorpusWeight & {
|
|
376
|
-
productTypeId: string;
|
|
377
|
-
})[];
|
|
378
|
-
byProductType: CompositionCorpusTypeCoverage[];
|
|
379
|
-
unknownProductType: CompositionCorpusWeight;
|
|
380
|
-
};
|
|
381
|
-
coverage: {
|
|
382
|
-
failedClosed: CompositionCorpusWeight;
|
|
383
|
-
/** Tuples with no text to parse at all; not a parser failure. */
|
|
384
|
-
noValue: CompositionCorpusWeight;
|
|
385
|
-
resolvable: CompositionCorpusShare;
|
|
386
|
-
validity: CompositionCorpusShare;
|
|
387
|
-
withValue: CompositionCorpusWeight;
|
|
388
|
-
};
|
|
389
|
-
dictionaryVersion: string;
|
|
390
|
-
/** The corpus's own list-price spend, never a per-request figure. */
|
|
391
|
-
tokens: {
|
|
392
|
-
costUsd: {
|
|
393
|
-
input: number;
|
|
394
|
-
output: number;
|
|
395
|
-
total: number;
|
|
396
|
-
};
|
|
397
|
-
inputTokens: number;
|
|
398
|
-
outputTokens: number;
|
|
399
|
-
};
|
|
400
|
-
parses: number;
|
|
401
|
-
linkedSkus: number;
|
|
402
|
-
generatedAt: string;
|
|
403
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { PostSourceMaterialCommentResult, SourceMaterialBatchDetail, SourceMaterialCommentThread } from "./run-types.js";
|
|
2
|
-
/** Validate a batch-detail body, returning it typed, or throw explaining why. */
|
|
3
|
-
export declare const checkSourceMaterialBatchDetail: (value: unknown, batchId: string) => SourceMaterialBatchDetail;
|
|
4
|
-
/** Validate a comment-thread body, returning it typed, or throw explaining why. */
|
|
5
|
-
export declare const checkSourceMaterialCommentThread: (value: unknown, sourceId: string) => SourceMaterialCommentThread;
|
|
6
|
-
/** Validate a posted-comment body, returning it typed, or throw explaining why. */
|
|
7
|
-
export declare const checkPostSourceMaterialCommentResult: (value: unknown, sourceId: string) => PostSourceMaterialCommentResult;
|