@instruments/materialgraph 0.29.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 +2 -2
- 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
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The runtime validator for `GET /api/v1/source-material/{batchId}` — the
|
|
3
|
-
* hand-rolled, zero-runtime-dependency mirror of
|
|
4
|
-
* `sourceMaterialBatchDetailSchema` and its transitive closure
|
|
5
|
-
* (`sourceMaterialBatchDetailFileSchema`, `sourceImageAnalysisSchema`,
|
|
6
|
-
* `sourceImageAnalysisResultSchema`) in
|
|
7
|
-
* `packages/sources/src/source-material/contract.ts`.
|
|
8
|
-
*
|
|
9
|
-
* WHY IT EXISTS. `contract-parity.test.ts` proves the SDK's STATIC types match
|
|
10
|
-
* the canonical schemas; that is a compile-time proof about shapes and validates
|
|
11
|
-
* nothing at run time. This is the run-time half, and it must ACCEPT and REJECT
|
|
12
|
-
* exactly what the schema does — pinned by `source-material-parity.test.ts`.
|
|
13
|
-
*
|
|
14
|
-
* THREE CONTRACT PROPERTIES IT ENFORCES, each easy to lose in a refactor:
|
|
15
|
-
* 1. `analyses` is REQUIRED and an array on every file. `[]` means "nothing
|
|
16
|
-
* computed yet"; an absent field is a broken response, not an empty one.
|
|
17
|
-
* Preprocessing is manual today and automatic later — only the trigger
|
|
18
|
-
* changes, never this contract.
|
|
19
|
-
* 2. `comments` is REQUIRED and an array on every file, and every root comment
|
|
20
|
-
* carries a REQUIRED `replies` array. Same distinction: "nobody said
|
|
21
|
-
* anything about this file" is a state the client draws, and an absent
|
|
22
|
-
* field is a malformed response.
|
|
23
|
-
* 3. `result` is a JSON record all the way down (`z.json()`), not `unknown`.
|
|
24
|
-
* See `requireJsonValue` for why the schema is that strict and why this
|
|
25
|
-
* mirror cannot actually fire over the wire.
|
|
26
|
-
*
|
|
27
|
-
* ENUMS ARE CLOSED here, matching the canonical `z.enum(…)` members, while the
|
|
28
|
-
* published types are `OpenEnum` so a newer server value keeps type-checking.
|
|
29
|
-
* The validator follows the SCHEMA: the type stays wider than what is proven,
|
|
30
|
-
* which is imprecise but never a lie — the same choice
|
|
31
|
-
* `search-result-validation.ts` makes for `basis`.
|
|
32
|
-
*
|
|
33
|
-
* Package-internal (not re-exported from `index.ts`): a published symbol is a
|
|
34
|
-
* permanent contract, and promoting it later is additive.
|
|
35
|
-
*/
|
|
36
|
-
import { MaterialGraphError } from "./errors.js";
|
|
37
|
-
import { requireArray, requireBoolean, requireEnum, requireSafeInteger, requireJsonRecord, requireNonEmptyString, requireNullableTrimmedBoundedString, requireRecord, requireString, requireTrimmedBoundedString, } from "./validation.js";
|
|
38
|
-
/** `sourceImageAnalysisKindSchema` members, verbatim. */
|
|
39
|
-
const ANALYSIS_KINDS = ["scene_match"];
|
|
40
|
-
/** `sourceImageAnalysisStatusSchema` members, verbatim. */
|
|
41
|
-
const ANALYSIS_STATUSES = ["ok", "failed"];
|
|
42
|
-
/** `sourceMaterialRoleSchema` members, verbatim. */
|
|
43
|
-
const SOURCE_ROLES = [
|
|
44
|
-
"brief",
|
|
45
|
-
"reference_image",
|
|
46
|
-
"document",
|
|
47
|
-
"document_image",
|
|
48
|
-
"inspiration_image",
|
|
49
|
-
"unclassified",
|
|
50
|
-
];
|
|
51
|
-
const detailFailure = (batchId) => (reason) => MaterialGraphError.unexpected(`GET /api/v1/source-material/${batchId} returned a malformed body: ${reason}`);
|
|
52
|
-
const checkAnalysis = (value, what, fail) => {
|
|
53
|
-
const record = requireRecord(value, what, fail);
|
|
54
|
-
// `model` and `analysedAt` ARE `.min(1)` canonically — fields this endpoint
|
|
55
|
-
// introduces, where an empty value is meaningless and `model` already cannot
|
|
56
|
-
// be written empty. Parity here is achieved by the schema being strict, never
|
|
57
|
-
// by this mirror freelancing past it.
|
|
58
|
-
return {
|
|
59
|
-
analysedAt: requireNonEmptyString(record.analysedAt, `${what}.analysedAt`, fail),
|
|
60
|
-
kind: requireEnum(record.kind, ANALYSIS_KINDS, `${what}.kind`, fail),
|
|
61
|
-
model: requireNonEmptyString(record.model, `${what}.model`, fail),
|
|
62
|
-
result: requireJsonRecord(record.result, `${what}.result`, fail),
|
|
63
|
-
status: requireEnum(record.status, ANALYSIS_STATUSES, `${what}.status`, fail),
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
/** `sourceMaterialCommentAuthorSchema`'s `attribution` members, verbatim. */
|
|
67
|
-
const COMMENT_ATTRIBUTIONS = ["reported"];
|
|
68
|
-
/** The canonical cap on both author fields: `.trim().min(1).max(160)`. */
|
|
69
|
-
const AUTHOR_FIELD_MAX = 160;
|
|
70
|
-
/**
|
|
71
|
-
* A reply, and the shared half of a root comment.
|
|
72
|
-
*
|
|
73
|
-
* `body`, `commentId` and `createdAt` are `.min(1)` canonically — fields this
|
|
74
|
-
* endpoint introduces, where an empty value carries nothing a client could
|
|
75
|
-
* render. `author.organisation` is nullable, NOT optional: `null` is the answer
|
|
76
|
-
* for a note with no organisation, and an absent key is a malformed body.
|
|
77
|
-
*
|
|
78
|
-
* The author fields are `.trim().min(1).max(160)` canonically and are mirrored
|
|
79
|
-
* as exactly that. A plain non-empty check — which is what this used to do —
|
|
80
|
-
* disagreed with the schema in both directions: it accepted `" "`, which the
|
|
81
|
-
* schema rejects once trimmed, and accepted a name of any length, which the
|
|
82
|
-
* schema caps. A validator that is looser than the contract is a validator that
|
|
83
|
-
* lets the two drift without anything failing.
|
|
84
|
-
*/
|
|
85
|
-
const checkCommentBase = (record, what, fail) => {
|
|
86
|
-
const author = requireRecord(record.author, `${what}.author`, fail);
|
|
87
|
-
const recordedBy = requireRecord(record.recordedBy, `${what}.recordedBy`, fail);
|
|
88
|
-
return {
|
|
89
|
-
author: {
|
|
90
|
-
// Closed here, matching the canonical `z.literal("reported")`, while the
|
|
91
|
-
// published type is `OpenEnum` so a newer server value keeps
|
|
92
|
-
// type-checking — the same split the analysis enums make.
|
|
93
|
-
attribution: requireEnum(author.attribution, COMMENT_ATTRIBUTIONS, `${what}.author.attribution`, fail),
|
|
94
|
-
name: requireTrimmedBoundedString(author.name, `${what}.author.name`, AUTHOR_FIELD_MAX, fail),
|
|
95
|
-
organisation: requireNullableTrimmedBoundedString(author.organisation, `${what}.author.organisation`, AUTHOR_FIELD_MAX, fail),
|
|
96
|
-
},
|
|
97
|
-
body: requireNonEmptyString(record.body, `${what}.body`, fail),
|
|
98
|
-
commentId: requireNonEmptyString(record.commentId, `${what}.commentId`, fail),
|
|
99
|
-
createdAt: requireNonEmptyString(record.createdAt, `${what}.createdAt`, fail),
|
|
100
|
-
recordedBy: {
|
|
101
|
-
principalId: requireNonEmptyString(recordedBy.principalId, `${what}.recordedBy.principalId`, fail),
|
|
102
|
-
},
|
|
103
|
-
};
|
|
104
|
-
};
|
|
105
|
-
const checkComment = (value, what, fail) => {
|
|
106
|
-
const record = requireRecord(value, what, fail);
|
|
107
|
-
// Same reasoning as `analyses`: no `.default([])` canonically, so an absent
|
|
108
|
-
// `replies` is malformed rather than empty.
|
|
109
|
-
const replies = requireArray(record.replies, `${what}.replies`, fail);
|
|
110
|
-
return {
|
|
111
|
-
...checkCommentBase(record, what, fail),
|
|
112
|
-
replies: replies.map((reply, index) => checkCommentBase(requireRecord(reply, `${what}.replies[${index}]`, fail), `${what}.replies[${index}]`, fail)),
|
|
113
|
-
};
|
|
114
|
-
};
|
|
115
|
-
const checkFile = (value, what, fail) => {
|
|
116
|
-
const record = requireRecord(value, what, fail);
|
|
117
|
-
// NOT `requireDefaultedArray`: the schema has no `.default([])`, so an absent
|
|
118
|
-
// `analyses` is a malformed body rather than an empty one. Keeping that
|
|
119
|
-
// distinction is the whole point of the always-an-array contract. `comments`
|
|
120
|
-
// is required for the same reason: "nobody has said anything" and "the server
|
|
121
|
-
// forgot to tell you" are different answers.
|
|
122
|
-
const analyses = requireArray(record.analyses, `${what}.analyses`, fail);
|
|
123
|
-
const comments = requireArray(record.comments, `${what}.comments`, fail);
|
|
124
|
-
// Required, not defaulted: "you are seeing the whole thread" is a claim the
|
|
125
|
-
// server makes or does not, never one a client should infer from a length.
|
|
126
|
-
const commentsTruncated = requireBoolean(record.commentsTruncated, `${what}.commentsTruncated`, fail);
|
|
127
|
-
// `requireString`, NOT `requireNonEmptyString`, for the fields this endpoint
|
|
128
|
-
// INHERITS from the shared source-material contract (`sourceId`, `sha256`,
|
|
129
|
-
// `url` — plus `batchId`/`createdAt` below). Those are plain `z.string()`
|
|
130
|
-
// there and shared with the upload path; a client that rejected `""` would
|
|
131
|
-
// refuse a response the server can legitimately produce, and tightening them
|
|
132
|
-
// is a change to a contract this endpoint does not own.
|
|
133
|
-
return {
|
|
134
|
-
analyses: analyses.map((analysis, index) => checkAnalysis(analysis, `${what}.analyses[${index}]`, fail)),
|
|
135
|
-
// `requireSafeInteger`, NOT `requireIntegerAtLeast(…, 0)`. Canonically these
|
|
136
|
-
// are a bare `z.number().int()` on the INHERITED
|
|
137
|
-
// `sourceMaterialFileReceiptSchema`, which carries no lower bound — so a
|
|
138
|
-
// negative is accepted there and must be accepted here.
|
|
139
|
-
//
|
|
140
|
-
// A negative `bytes` is nonsense and a negative `pages` more so, and this is
|
|
141
|
-
// still not the place to say so: a client validator holding an opinion the
|
|
142
|
-
// contract does not is how the two drift, and how a response the server may
|
|
143
|
-
// legitimately produce starts throwing at the boundary. Tightening those
|
|
144
|
-
// fields is a canonical change to a schema shared with the upload path, and
|
|
145
|
-
// belongs in its own ticket with this mirror following after.
|
|
146
|
-
bytes: requireSafeInteger(record.bytes, `${what}.bytes`, fail),
|
|
147
|
-
comments: comments.map((comment, index) => checkComment(comment, `${what}.comments[${index}]`, fail)),
|
|
148
|
-
commentsTruncated,
|
|
149
|
-
filename: requireString(record.filename, `${what}.filename`, fail),
|
|
150
|
-
mediaType: requireString(record.mediaType, `${what}.mediaType`, fail),
|
|
151
|
-
pages: record.pages === null
|
|
152
|
-
? null
|
|
153
|
-
: requireSafeInteger(record.pages, `${what}.pages`, fail),
|
|
154
|
-
role: requireEnum(record.role, SOURCE_ROLES, `${what}.role`, fail),
|
|
155
|
-
sha256: requireString(record.sha256, `${what}.sha256`, fail),
|
|
156
|
-
sourceId: requireString(record.sourceId, `${what}.sourceId`, fail),
|
|
157
|
-
url: requireString(record.url, `${what}.url`, fail),
|
|
158
|
-
};
|
|
159
|
-
};
|
|
160
|
-
/** Validate a batch-detail body, returning it typed, or throw explaining why. */
|
|
161
|
-
export const checkSourceMaterialBatchDetail = (value, batchId) => {
|
|
162
|
-
const fail = detailFailure(batchId);
|
|
163
|
-
const record = requireRecord(value, "body", fail);
|
|
164
|
-
const sources = requireArray(record.sources, "body.sources", fail);
|
|
165
|
-
return {
|
|
166
|
-
batchId: requireString(record.batchId, "body.batchId", fail),
|
|
167
|
-
createdAt: requireString(record.createdAt, "body.createdAt", fail),
|
|
168
|
-
sources: sources.map((file, index) => checkFile(file, `body.sources[${index}]`, fail)),
|
|
169
|
-
};
|
|
170
|
-
};
|
|
171
|
-
const commentsFailure = (verb, sourceId) => (reason) => MaterialGraphError.unexpected(`${verb} .../sources/${sourceId}/comments returned a malformed body: ${reason}`);
|
|
172
|
-
/** Validate a comment-thread body, returning it typed, or throw explaining why. */
|
|
173
|
-
export const checkSourceMaterialCommentThread = (value, sourceId) => {
|
|
174
|
-
const fail = commentsFailure("GET", sourceId);
|
|
175
|
-
const record = requireRecord(value, "body", fail);
|
|
176
|
-
const comments = requireArray(record.comments, "body.comments", fail);
|
|
177
|
-
return {
|
|
178
|
-
comments: comments.map((comment, index) => checkComment(comment, `body.comments[${index}]`, fail)),
|
|
179
|
-
sourceId: requireString(record.sourceId, "body.sourceId", fail),
|
|
180
|
-
truncated: requireBoolean(record.truncated, "body.truncated", fail),
|
|
181
|
-
};
|
|
182
|
-
};
|
|
183
|
-
/** `storedSourceMaterialCommentSchema`'s discriminator members, verbatim. */
|
|
184
|
-
const STORED_COMMENT_KINDS = ["root", "reply"];
|
|
185
|
-
/**
|
|
186
|
-
* Validate a stored comment, following its `kind` discriminator.
|
|
187
|
-
*
|
|
188
|
-
* The two branches are checked as the two DIFFERENT shapes they are: a root must
|
|
189
|
-
* carry `replies`, a reply must carry `parentCommentId` and must not be assumed
|
|
190
|
-
* to carry `replies` at all. Validating both as the root shape is exactly the
|
|
191
|
-
* defect this discriminated union was added to fix, and a mirror that did it
|
|
192
|
-
* would put the lie back on the client side.
|
|
193
|
-
*/
|
|
194
|
-
const checkStoredComment = (value, what, fail) => {
|
|
195
|
-
const record = requireRecord(value, what, fail);
|
|
196
|
-
const kind = requireEnum(record.kind, STORED_COMMENT_KINDS, `${what}.kind`, fail);
|
|
197
|
-
if (kind === "reply") {
|
|
198
|
-
return {
|
|
199
|
-
kind: "reply",
|
|
200
|
-
...checkCommentBase(record, what, fail),
|
|
201
|
-
parentCommentId: requireNonEmptyString(record.parentCommentId, `${what}.parentCommentId`, fail),
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
return { kind: "root", ...checkComment(record, what, fail) };
|
|
205
|
-
};
|
|
206
|
-
/** Validate a posted-comment body, returning it typed, or throw explaining why. */
|
|
207
|
-
export const checkPostSourceMaterialCommentResult = (value, sourceId) => {
|
|
208
|
-
const fail = commentsFailure("POST", sourceId);
|
|
209
|
-
const record = requireRecord(value, "body", fail);
|
|
210
|
-
return {
|
|
211
|
-
comment: checkStoredComment(record.comment, "body.comment", fail),
|
|
212
|
-
sourceId: requireString(record.sourceId, "body.sourceId", fail),
|
|
213
|
-
};
|
|
214
|
-
};
|
package/spec-facet-types.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
export type SpecFacetValue = {
|
|
2
|
-
value: string;
|
|
3
|
-
variants: number;
|
|
4
|
-
brands: number;
|
|
5
|
-
label?: string;
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
* A NUMERIC facet's observed span and the coverage behind it.
|
|
9
|
-
*
|
|
10
|
-
* A range, not buckets — no bucketing scheme has been decided, and one invented
|
|
11
|
-
* on the wire would be treated as canonical by everyone who read it. Both bounds
|
|
12
|
-
* are INCLUSIVE, matching `specRange`.
|
|
13
|
-
*
|
|
14
|
-
* READ `variants` BEFORE TRUSTING A FILTER. It is how many variants carry a
|
|
15
|
-
* value that parses as a number, i.e. how much of the corpus a range can reach;
|
|
16
|
-
* a facet that exists says the attribute is queryable, not that it is populated.
|
|
17
|
-
* `unparseableVariants` is the honesty companion: values recorded here that are
|
|
18
|
-
* not numbers, which a range EXCLUDES rather than reading as zero.
|
|
19
|
-
*/
|
|
20
|
-
export type SpecFacetRange = {
|
|
21
|
-
min: number;
|
|
22
|
-
max: number;
|
|
23
|
-
variants: number;
|
|
24
|
-
unparseableVariants: number;
|
|
25
|
-
};
|
|
26
|
-
export type SpecFacet = {
|
|
27
|
-
attributeId: string;
|
|
28
|
-
name: string;
|
|
29
|
-
isArray: boolean;
|
|
30
|
-
/**
|
|
31
|
-
* How this facet is queried. `token` — pick a value from `values` and send it
|
|
32
|
-
* as a `{field: attributeId, op: "in", values: [...]}` filter leaf.
|
|
33
|
-
* `numeric` — `values` is EMPTY and `range` carries the span; send inclusive
|
|
34
|
-
* bounds as `{field: attributeId, op: "gte"/"lte", value}` leaves instead.
|
|
35
|
-
*/
|
|
36
|
-
kind: "token" | "numeric" | (string & {});
|
|
37
|
-
brands: number;
|
|
38
|
-
/** EMPTY for a `numeric` facet, which has no token vocabulary. */
|
|
39
|
-
values: SpecFacetValue[];
|
|
40
|
-
/** Present ONLY on a `numeric` facet. */
|
|
41
|
-
range?: SpecFacetRange;
|
|
42
|
-
description?: string;
|
|
43
|
-
};
|
|
44
|
-
export type SpecFacetsListResponse = {
|
|
45
|
-
mode: "facets";
|
|
46
|
-
count: number;
|
|
47
|
-
facets: SpecFacet[];
|
|
48
|
-
};
|
package/spec-facet-types.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
// ── Specification facets + attribute values ─────────────────────────────────
|
|
2
|
-
//
|
|
3
|
-
// Hand-maintained mirror of the `SpecificationFacet` OpenAPI schema (the source
|
|
4
|
-
// of truth on the wire); the `sdk-openapi-parity` test gates this against the
|
|
5
|
-
// generated spec. Split out of `types.ts` to keep that file under its growth
|
|
6
|
-
// baseline; re-exported from `types.ts` so importers see no change.
|
|
7
|
-
export {};
|
package/substitute-types.d.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import type { BySpecVerdict } from "./by-spec-types.js";
|
|
2
|
-
import type { VariantId } from "./identifiers.js";
|
|
3
|
-
import type { MaterialSuccessor } from "./material-types.js";
|
|
4
|
-
export type SubstituteSignatureFamily = "textile" | "tile" | "coating" | "lighting_electrical" | "acoustic" | "surface" | "furniture" | "sanitaryware" | "fittings" | "architectural_hardware";
|
|
5
|
-
export type SubstituteSignatureCriterion = {
|
|
6
|
-
role: "primary_material" | "performance";
|
|
7
|
-
attributeId: string;
|
|
8
|
-
term: string;
|
|
9
|
-
};
|
|
10
|
-
export type AvailableSubstituteSignature = {
|
|
11
|
-
family: SubstituteSignatureFamily;
|
|
12
|
-
form: string;
|
|
13
|
-
criteria: [SubstituteSignatureCriterion, SubstituteSignatureCriterion];
|
|
14
|
-
};
|
|
15
|
-
export type UnsupportedSubstituteSignature = {
|
|
16
|
-
family: SubstituteSignatureFamily;
|
|
17
|
-
form: string;
|
|
18
|
-
reason: string;
|
|
19
|
-
};
|
|
20
|
-
export type InsufficientSubstituteSignature = {
|
|
21
|
-
family: SubstituteSignatureFamily;
|
|
22
|
-
form: string;
|
|
23
|
-
missingRoles: ("primary_material" | "performance")[];
|
|
24
|
-
};
|
|
25
|
-
export type FindSubstitutesOptions = {
|
|
26
|
-
excludeBrands?: string[];
|
|
27
|
-
diversityBoost?: number;
|
|
28
|
-
limit?: number;
|
|
29
|
-
cursor?: string;
|
|
30
|
-
includeSamplingArtifacts?: boolean;
|
|
31
|
-
includeUnavailable?: boolean;
|
|
32
|
-
};
|
|
33
|
-
export type SubstituteMatchedCriterion = {
|
|
34
|
-
attributeId: string;
|
|
35
|
-
confidence: number | null;
|
|
36
|
-
sourceBasis: string | null;
|
|
37
|
-
};
|
|
38
|
-
export type SubstituteResultItem = {
|
|
39
|
-
variantId: VariantId;
|
|
40
|
-
brandSlug: string;
|
|
41
|
-
brand: string;
|
|
42
|
-
product: string;
|
|
43
|
-
variant: string;
|
|
44
|
-
color: string | null;
|
|
45
|
-
imageUrl: string | null;
|
|
46
|
-
hex: string | null;
|
|
47
|
-
matched: SubstituteMatchedCriterion[];
|
|
48
|
-
minConfidence: number | null;
|
|
49
|
-
baseScore: number;
|
|
50
|
-
diversityAdjustment: number;
|
|
51
|
-
score: number;
|
|
52
|
-
verdict: BySpecVerdict;
|
|
53
|
-
};
|
|
54
|
-
export type AvailableSubstitutesResponse = {
|
|
55
|
-
status: "available";
|
|
56
|
-
signatureUsed: AvailableSubstituteSignature;
|
|
57
|
-
items: SubstituteResultItem[];
|
|
58
|
-
candidatePoolSize: number;
|
|
59
|
-
droppedUnavailable: number;
|
|
60
|
-
/**
|
|
61
|
-
* MG-1686, MG-1783. True when the candidate read hit the bounded pool ceiling,
|
|
62
|
-
* so more materials match the signature than were ranked. A cut pool is an
|
|
63
|
-
* even SAMPLE across the id keyspace rather than its lowest window, so the
|
|
64
|
-
* ranked set is representative of the match set without being all of it —
|
|
65
|
-
* treat the items as the best of a sample, never as the best that exist. A cut
|
|
66
|
-
* pool that produced NO items answers `inconclusive` instead, so `available`
|
|
67
|
-
* with an empty `items` always means a complete search that found nothing.
|
|
68
|
-
*/
|
|
69
|
-
poolTruncated: boolean;
|
|
70
|
-
supersededBy: MaterialSuccessor | null;
|
|
71
|
-
nextCursor?: string;
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* MG-1686. The search read a bounded window of the matches and nothing in it
|
|
75
|
-
* reached the page, while more matches existed past the window. It is not an
|
|
76
|
-
* answer of "nothing can replace this" — that answer is `available` with an
|
|
77
|
-
* empty `items`. `reason` names what happened and the next move; follow
|
|
78
|
-
* `nextCursor` when it is present.
|
|
79
|
-
*/
|
|
80
|
-
export type InconclusiveSubstitutesResponse = {
|
|
81
|
-
status: "inconclusive";
|
|
82
|
-
signatureUsed: AvailableSubstituteSignature;
|
|
83
|
-
items: [];
|
|
84
|
-
candidatePoolSize: number;
|
|
85
|
-
droppedUnavailable: number;
|
|
86
|
-
reason: string;
|
|
87
|
-
supersededBy: MaterialSuccessor | null;
|
|
88
|
-
nextCursor?: string;
|
|
89
|
-
};
|
|
90
|
-
export type UnsupportedSubstitutesResponse = {
|
|
91
|
-
status: "unsupported";
|
|
92
|
-
signature: UnsupportedSubstituteSignature;
|
|
93
|
-
items: [];
|
|
94
|
-
supersededBy: MaterialSuccessor | null;
|
|
95
|
-
};
|
|
96
|
-
export type InsufficientSubstitutesResponse = {
|
|
97
|
-
status: "insufficient_signature";
|
|
98
|
-
signature: InsufficientSubstituteSignature;
|
|
99
|
-
items: [];
|
|
100
|
-
supersededBy: MaterialSuccessor | null;
|
|
101
|
-
};
|
|
102
|
-
export type FindSubstitutesResponse = AvailableSubstitutesResponse | InconclusiveSubstitutesResponse | UnsupportedSubstitutesResponse | InsufficientSubstitutesResponse;
|
package/substitute-types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/suggest-types.d.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Entity typeahead (MG-654) — the hand-mirrored wire types for
|
|
3
|
-
* `GET /api/v1/search/suggest`, plus the one query-shaping rule the endpoint
|
|
4
|
-
* imposes.
|
|
5
|
-
*
|
|
6
|
-
* Split out of `types.ts` for the repository's source-file size budget, the same
|
|
7
|
-
* reason `catalog-discovery-types.ts` sits beside it; both are re-exported from
|
|
8
|
-
* `types.ts`, so importers see no difference.
|
|
9
|
-
*
|
|
10
|
-
* THE LENS: entity typeahead — it ranks NAMES, not materials. `mg.search()` is
|
|
11
|
-
* what answers a committed query; `mg.suggestColour()` covers colour names and
|
|
12
|
-
* `mg.listAttributes({ query })` covers attributes. Suggestions are a page
|
|
13
|
-
* of the best matches, never a census of matching entities.
|
|
14
|
-
*/
|
|
15
|
-
/** Which kind of entity a suggestion is — and therefore what `refId` means. */
|
|
16
|
-
export type SuggestKind = "product" | "brand" | "category";
|
|
17
|
-
/** How the query met the suggestion's label. Strongest first. */
|
|
18
|
-
export type SuggestMatch = "prefix" | "word" | "fuzzy";
|
|
19
|
-
/** One ranked typeahead suggestion, carrying the identity it resolves to. */
|
|
20
|
-
export type Suggestion = {
|
|
21
|
-
kind: SuggestKind;
|
|
22
|
-
/** The entity's name as written, for display. */
|
|
23
|
-
label: string;
|
|
24
|
-
/**
|
|
25
|
-
* The resolvable identity: a product id, a brand slug, or a product-type key.
|
|
26
|
-
* Selecting a suggestion should navigate to this, not re-search `label`.
|
|
27
|
-
*/
|
|
28
|
-
refId: string;
|
|
29
|
-
match: SuggestMatch;
|
|
30
|
-
brandSlug: string | null;
|
|
31
|
-
brandName: string | null;
|
|
32
|
-
categoryKey: string | null;
|
|
33
|
-
/**
|
|
34
|
-
* A representative variant, so a client can open a material record directly.
|
|
35
|
-
* Opaque, and null when none was picked — not a product without variants.
|
|
36
|
-
*/
|
|
37
|
-
variantId: string | null;
|
|
38
|
-
/** How many of this entity's variants the search index holds: a coverage figure. */
|
|
39
|
-
variantCount: number;
|
|
40
|
-
};
|
|
41
|
-
/** The suggest response: the query as interpreted, plus the ranked suggestions. */
|
|
42
|
-
export type SuggestResponse = {
|
|
43
|
-
/** The typed words the search index was matched against. */
|
|
44
|
-
query: string;
|
|
45
|
-
/** Ranked best-match-first. Empty when nothing came close: a miss, not an error. */
|
|
46
|
-
suggestions: Suggestion[];
|
|
47
|
-
};
|
|
48
|
-
/** Options for {@link MaterialGraphClient.suggest}. */
|
|
49
|
-
export type SuggestOptions = {
|
|
50
|
-
/** How many suggestions to return (1–20, default 8). */
|
|
51
|
-
limit?: number;
|
|
52
|
-
/** Restrict to these kinds. Omit for all of them. */
|
|
53
|
-
kind?: SuggestKind | SuggestKind[];
|
|
54
|
-
};
|
|
55
|
-
/**
|
|
56
|
-
* Shape the query string for a suggest call.
|
|
57
|
-
*
|
|
58
|
-
* The only non-obvious rule: `kind` is a COMMA LIST on the wire (`product,brand`),
|
|
59
|
-
* which is the house convention for multi-value v1 params, so an array is joined
|
|
60
|
-
* here rather than being sent as repeated `?kind=` pairs the route would ignore.
|
|
61
|
-
* Undefined members are dropped by the transport.
|
|
62
|
-
*/
|
|
63
|
-
export declare const suggestQuery: (q: string, options?: SuggestOptions) => {
|
|
64
|
-
q: string;
|
|
65
|
-
limit?: number;
|
|
66
|
-
kind?: string;
|
|
67
|
-
};
|
package/suggest-types.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Entity typeahead (MG-654) — the hand-mirrored wire types for
|
|
3
|
-
* `GET /api/v1/search/suggest`, plus the one query-shaping rule the endpoint
|
|
4
|
-
* imposes.
|
|
5
|
-
*
|
|
6
|
-
* Split out of `types.ts` for the repository's source-file size budget, the same
|
|
7
|
-
* reason `catalog-discovery-types.ts` sits beside it; both are re-exported from
|
|
8
|
-
* `types.ts`, so importers see no difference.
|
|
9
|
-
*
|
|
10
|
-
* THE LENS: entity typeahead — it ranks NAMES, not materials. `mg.search()` is
|
|
11
|
-
* what answers a committed query; `mg.suggestColour()` covers colour names and
|
|
12
|
-
* `mg.listAttributes({ query })` covers attributes. Suggestions are a page
|
|
13
|
-
* of the best matches, never a census of matching entities.
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
* Shape the query string for a suggest call.
|
|
17
|
-
*
|
|
18
|
-
* The only non-obvious rule: `kind` is a COMMA LIST on the wire (`product,brand`),
|
|
19
|
-
* which is the house convention for multi-value v1 params, so an array is joined
|
|
20
|
-
* here rather than being sent as repeated `?kind=` pairs the route would ignore.
|
|
21
|
-
* Undefined members are dropped by the transport.
|
|
22
|
-
*/
|
|
23
|
-
export const suggestQuery = (q, options) => {
|
|
24
|
-
const kind = Array.isArray(options?.kind)
|
|
25
|
-
? options.kind.join(",")
|
|
26
|
-
: options?.kind;
|
|
27
|
-
return { kind, limit: options?.limit, q };
|
|
28
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/** Exact, source-path-grained status coverage for primary product typing. */
|
|
2
|
-
export type ProductTypeStatusCoverageCounts = {
|
|
3
|
-
variants: number;
|
|
4
|
-
accepted: number;
|
|
5
|
-
proposed: number;
|
|
6
|
-
proposedBelowThreshold: number;
|
|
7
|
-
/** Proposed rows with no confidence remain explicit rather than thresholded. */
|
|
8
|
-
proposedUnknownConfidence: number;
|
|
9
|
-
otherStatus: number;
|
|
10
|
-
missingPrimary: number;
|
|
11
|
-
};
|
|
12
|
-
export type ProductTypeStatusCoverageSourcePath = {
|
|
13
|
-
/** Complete stored source path; null means the product retained no path. */
|
|
14
|
-
sourcePath: string | null;
|
|
15
|
-
} & ProductTypeStatusCoverageCounts;
|
|
16
|
-
/** Current primary-assignment coverage, never an inferred acceptance decision. */
|
|
17
|
-
export type ProductTypeStatusCoverage = {
|
|
18
|
-
computedAt: string;
|
|
19
|
-
basis: {
|
|
20
|
-
count: "exact";
|
|
21
|
-
universe: "non_superseded_variants";
|
|
22
|
-
assignment: "variant_primary_only";
|
|
23
|
-
sourcePath: "products.source_category_path";
|
|
24
|
-
/** Reporting cutoff only: higher-confidence proposals remain proposed. */
|
|
25
|
-
comparisonThreshold: number;
|
|
26
|
-
};
|
|
27
|
-
totals: ProductTypeStatusCoverageCounts;
|
|
28
|
-
sourcePaths: ProductTypeStatusCoverageSourcePath[];
|
|
29
|
-
};
|
|
30
|
-
export type ProductTypeCoverageOptions = {
|
|
31
|
-
[key: string]: number | undefined;
|
|
32
|
-
/** Reporting cutoff in [0,1], default 0.85; it never accepts a proposal. */
|
|
33
|
-
comparisonThreshold?: number;
|
|
34
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|