@instruments/materialgraph 0.1.0 → 0.3.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/by-spec-types.d.ts +73 -0
- package/by-spec-types.js +7 -0
- package/client.d.ts +186 -7
- package/client.js +242 -125
- package/codes-client.d.ts +82 -0
- package/codes-client.js +73 -0
- package/codes-types.d.ts +238 -0
- package/codes-types.js +1 -0
- package/colour-aggregate-types.d.ts +93 -0
- package/colour-aggregate-types.js +1 -0
- package/colours-client.d.ts +52 -0
- package/colours-client.js +39 -0
- package/composition-types.d.ts +343 -0
- package/composition-types.js +10 -0
- package/http-transport.d.ts +74 -0
- package/http-transport.js +201 -0
- package/index.d.ts +19 -0
- package/index.js +9 -0
- package/match-stream-types.d.ts +150 -0
- package/match-stream-types.js +28 -0
- package/match-stream.d.ts +22 -0
- package/match-stream.js +280 -0
- package/material-block-types.d.ts +23 -2
- package/material-types.d.ts +92 -0
- package/material-types.js +1 -0
- package/ndjson.d.ts +46 -0
- package/ndjson.js +103 -0
- package/operations.d.ts +6 -2
- package/operations.js +30 -2
- package/package.json +1 -1
- package/project-types.d.ts +67 -0
- package/project-types.js +16 -0
- package/projects.d.ts +13 -0
- package/projects.js +46 -0
- package/run-events.d.ts +82 -0
- package/run-events.js +29 -0
- package/run-types.d.ts +266 -0
- package/run-types.js +6 -0
- package/runs.d.ts +84 -0
- package/runs.js +253 -0
- package/schedule-types.d.ts +88 -0
- package/schedule-types.js +12 -0
- package/search-refinement-types.d.ts +26 -1
- package/search-result-validation.d.ts +27 -0
- package/search-result-validation.js +174 -0
- package/source-material-validation.d.ts +3 -0
- package/source-material-validation.js +109 -0
- package/spec-types.d.ts +82 -0
- package/spec-types.js +44 -0
- package/specifications.d.ts +72 -0
- package/specifications.js +82 -0
- package/sse.d.ts +35 -0
- package/sse.js +147 -0
- package/types.d.ts +204 -77
- package/validation.d.ts +119 -0
- package/validation.js +241 -0
package/ndjson.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal, dependency-free NDJSON (newline-delimited JSON) line reader — the
|
|
3
|
+
* primitive behind {@link MaterialGraphClient.matchStream}. Hand-rolled so the
|
|
4
|
+
* SDK stays zero-runtime-dep and works unchanged inside Node route handlers,
|
|
5
|
+
* where `fetch` yields a byte `ReadableStream`.
|
|
6
|
+
*
|
|
7
|
+
* Deliberately a SIBLING of `sse.ts`, not a reuse of it. NDJSON and SSE agree on
|
|
8
|
+
* nothing but "text arrives in chunks": SSE frames are `field: value` lines
|
|
9
|
+
* terminated by a BLANK line, with comment lines and multi-line `data:`
|
|
10
|
+
* accumulation, whereas an NDJSON frame is exactly one line of JSON. Feeding
|
|
11
|
+
* NDJSON through the SSE tokenizer would read `{"type":"step",…}` as a field
|
|
12
|
+
* named `{"type"` and silently discard every frame. The two also want OPPOSITE
|
|
13
|
+
* end-of-stream policies: SSE dispatches a trailing partial frame as valid,
|
|
14
|
+
* while a truncated NDJSON line must surface as an error (enforced by the
|
|
15
|
+
* caller, which parses whatever `flush` returns rather than dropping it).
|
|
16
|
+
*
|
|
17
|
+
* Line endings: the reader splits on `\n` only, per the NDJSON contract. A `\r`
|
|
18
|
+
* left by a CRLF-normalising proxy stays as trailing whitespace on the line,
|
|
19
|
+
* which `JSON.parse` ignores.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* A push-based NDJSON line assembler. Feed it decoded text with {@link push};
|
|
23
|
+
* it returns the lines that text COMPLETED, terminators removed. Any partial
|
|
24
|
+
* trailing line is held in an internal buffer until a later chunk terminates it,
|
|
25
|
+
* or until {@link flush} surrenders it at end of stream.
|
|
26
|
+
*/
|
|
27
|
+
export class NdjsonDecoder {
|
|
28
|
+
#buffer = "";
|
|
29
|
+
/** Absorb one decoded chunk and return the lines it completed, in order. */
|
|
30
|
+
push(text) {
|
|
31
|
+
this.#buffer += text;
|
|
32
|
+
const lines = [];
|
|
33
|
+
for (;;) {
|
|
34
|
+
const index = this.#buffer.indexOf("\n");
|
|
35
|
+
if (index === -1)
|
|
36
|
+
break;
|
|
37
|
+
lines.push(this.#buffer.slice(0, index));
|
|
38
|
+
this.#buffer = this.#buffer.slice(index + 1);
|
|
39
|
+
}
|
|
40
|
+
return lines;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Surrender the unterminated remainder at end of stream — a well-formed
|
|
44
|
+
* NDJSON stream's final line need not carry a trailing newline. The remainder
|
|
45
|
+
* is RETURNED, never dropped: a truncated frame is the caller's error to
|
|
46
|
+
* raise, not this decoder's fragment to discard.
|
|
47
|
+
*/
|
|
48
|
+
flush() {
|
|
49
|
+
if (this.#buffer.length === 0)
|
|
50
|
+
return [];
|
|
51
|
+
const remainder = this.#buffer;
|
|
52
|
+
this.#buffer = "";
|
|
53
|
+
return [remainder];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Iterate the NDJSON lines of a byte stream. Only lines with non-whitespace
|
|
58
|
+
* content are yielded — a blank separator line carries no frame and must never
|
|
59
|
+
* reach `JSON.parse`, where it would become an empty object. Stops cleanly when
|
|
60
|
+
* the stream ends or `signal` aborts (mid-read abort rejections are swallowed
|
|
61
|
+
* once the signal is set).
|
|
62
|
+
*/
|
|
63
|
+
export async function* readNdjsonLines(body, signal) {
|
|
64
|
+
const reader = body.getReader();
|
|
65
|
+
const decoder = new TextDecoder();
|
|
66
|
+
const ndjson = new NdjsonDecoder();
|
|
67
|
+
try {
|
|
68
|
+
for (;;) {
|
|
69
|
+
if (signal?.aborted)
|
|
70
|
+
return;
|
|
71
|
+
let result;
|
|
72
|
+
try {
|
|
73
|
+
result = await reader.read();
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (signal?.aborted)
|
|
77
|
+
return;
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
if (result.done) {
|
|
81
|
+
// `decode()` with no argument flushes any dangling multi-byte sequence.
|
|
82
|
+
for (const line of ndjson.push(decoder.decode())) {
|
|
83
|
+
if (line.trim().length > 0)
|
|
84
|
+
yield line;
|
|
85
|
+
}
|
|
86
|
+
for (const line of ndjson.flush()) {
|
|
87
|
+
if (line.trim().length > 0)
|
|
88
|
+
yield line;
|
|
89
|
+
}
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
for (const line of ndjson.push(decoder.decode(result.value, { stream: true }))) {
|
|
93
|
+
if (signal?.aborted)
|
|
94
|
+
return;
|
|
95
|
+
if (line.trim().length > 0)
|
|
96
|
+
yield line;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
reader.releaseLock();
|
|
102
|
+
}
|
|
103
|
+
}
|
package/operations.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export declare const MATERIALGRAPH_API_VERSION = "0.
|
|
2
|
-
declare const OPERATION_DEFINITIONS: readonly [readonly ["search", "POST", "/api/v1/search", "search_materials_post"], readonly ["searchGet", "GET", "/api/v1/search", "search_materials_get"], readonly ["match", "POST", "/api/v1/search/match", "match_material"], readonly ["byColour", "GET", "/api/v1/search/colours", "search_by_colour"], readonly ["material", "GET", "/api/v1/materials/{variantId}", "get_material"], readonly ["siblings", "GET", "/api/v1/materials/{variantId}/siblings", "get_material_siblings"], readonly ["materialBlocks", "GET", "/api/v1/materials/{variantId}/blocks", "list_material_blocks"], readonly ["materialAssets", "GET", "/api/v1/materials/{variantId}/assets", "list_material_assets"], readonly ["schema", "GET", "/api/v1/schema/blocks", "list_schema_blocks"], readonly ["schema", "GET", "/api/v1/schema/attributes", "list_schema_attributes"], readonly ["schema", "GET", "/api/v1/schema/verticals", "list_schema_verticals"], readonly ["schema", "GET", "/api/v1/schema/product-types", "list_schema_product_types"], readonly ["schema", "GET", "/api/v1/schema/units", "list_schema_units"], readonly ["schema", "GET", "/api/v1/schema/value-dictionaries", "list_schema_value_dictionaries"], readonly ["schema", "GET", "/api/v1/schema/source-requirements", "list_schema_source_requirements"], readonly ["schema", "GET", "/api/v1/schema/product-type-templates", "list_schema_product_type_templates"], readonly ["schema", "GET", "/api/v1/schema/mappings", "list_schema_mappings"], readonly ["pairings", "GET", "/api/v1/materials/{variantId}/pairings", "get_material_pairings"], readonly ["materials", "POST", "/api/v1/materials/batch", "get_materials_batch_post"], readonly ["materialsCached", "GET", "/api/v1/materials/batch", "get_materials_batch_get"], readonly ["browse", "GET", "/api/v1/search/browse", "search_browse_by_colour"], readonly ["colourFacets", "GET", "/api/v1/colours/facets", "get_colour_facets"], readonly ["resolveColour", "GET", "/api/v1/search/colours/resolve", "resolve_colour_name"], readonly ["suggestColour", "GET", "/api/v1/search/colours/suggest", "suggest_colour_names"], readonly ["resolveAttribute", "GET", "/api/v1/catalog/attributes/resolve", "catalog_resolve_attribute"], readonly ["resolveAttributeValue", "GET", "/api/v1/catalog/attributes/{attributeId}/values/resolve", "catalog_resolve_value"], readonly ["searchVocabulary", "GET", "/api/v1/catalog/vocabulary/search", "catalog_vocabulary_search"], readonly ["bySpec", "GET", "/api/v1/search/specifications", "catalog_by_spec"], readonly ["taxonomy", "GET", "/api/v1/taxonomy/categories", "get_category_taxonomy"], readonly ["whoami", "GET", "/api/v1/whoami", "whoami"], readonly ["coordinate", "POST", "/api/v1/pairings/coordinate", "coordinate_materials"], readonly ["demand", "GET", "/api/v1/demand", "get_material_demand"], readonly ["extractPalette", "POST", "/api/v1/search/palettes/extract", "extract_image_palette"], readonly ["specificationFacets", "GET", "/api/v1/catalog/specifications/facets", "list_spec_facets"], readonly ["attributeValues", "GET", "/api/v1/catalog/attributes/{attributeId}/values", "list_attribute_values"], readonly ["applicableSpecs", "GET", "/api/v1/taxonomy/categories/{key}/specs", "get_applicable_specs"], readonly ["glossary", "GET", "/api/v1/glossary/{term}", "explain_material_term"], readonly ["brands", "GET", "/api/v1/brands", "list_brands"], readonly ["brand", "GET", "/api/v1/brands/{
|
|
1
|
+
export declare const MATERIALGRAPH_API_VERSION = "0.7.0";
|
|
2
|
+
declare const OPERATION_DEFINITIONS: readonly [readonly ["search", "POST", "/api/v1/search", "search_materials_post"], readonly ["searchGet", "GET", "/api/v1/search", "search_materials_get"], readonly ["match", "POST", "/api/v1/search/match", "match_material"], readonly ["byColour", "GET", "/api/v1/search/colours", "search_by_colour"], readonly ["material", "GET", "/api/v1/materials/{variantId}", "get_material"], readonly ["siblings", "GET", "/api/v1/materials/{variantId}/siblings", "get_material_siblings"], readonly ["materialBlocks", "GET", "/api/v1/materials/{variantId}/blocks", "list_material_blocks"], readonly ["materialAssets", "GET", "/api/v1/materials/{variantId}/assets", "list_material_assets"], readonly ["schema", "GET", "/api/v1/schema/blocks", "list_schema_blocks"], readonly ["schema", "GET", "/api/v1/schema/attributes", "list_schema_attributes"], readonly ["schema", "GET", "/api/v1/schema/verticals", "list_schema_verticals"], readonly ["schema", "GET", "/api/v1/schema/product-types", "list_schema_product_types"], readonly ["schema", "GET", "/api/v1/schema/units", "list_schema_units"], readonly ["schema", "GET", "/api/v1/schema/value-dictionaries", "list_schema_value_dictionaries"], readonly ["schema", "GET", "/api/v1/schema/source-requirements", "list_schema_source_requirements"], readonly ["schema", "GET", "/api/v1/schema/product-type-templates", "list_schema_product_type_templates"], readonly ["schema", "GET", "/api/v1/schema/mappings", "list_schema_mappings"], readonly ["pairings", "GET", "/api/v1/materials/{variantId}/pairings", "get_material_pairings"], readonly ["materials", "POST", "/api/v1/materials/batch", "get_materials_batch_post"], readonly ["materialsCached", "GET", "/api/v1/materials/batch", "get_materials_batch_get"], readonly ["browse", "GET", "/api/v1/search/browse", "search_browse_by_colour"], readonly ["colourFacets", "GET", "/api/v1/colours/facets", "get_colour_facets"], readonly ["colours.profiles", "GET", "/api/v1/colours/profiles", "get_category_colour_profiles"], readonly ["colours.stats", "GET", "/api/v1/colours/stats", "get_colour_stats"], readonly ["resolveColour", "GET", "/api/v1/search/colours/resolve", "resolve_colour_name"], readonly ["suggestColour", "GET", "/api/v1/search/colours/suggest", "suggest_colour_names"], readonly ["resolveAttribute", "GET", "/api/v1/catalog/attributes/resolve", "catalog_resolve_attribute"], readonly ["resolveAttributeValue", "GET", "/api/v1/catalog/attributes/{attributeId}/values/resolve", "catalog_resolve_value"], readonly ["searchVocabulary", "GET", "/api/v1/catalog/vocabulary/search", "catalog_vocabulary_search"], readonly ["bySpec", "GET", "/api/v1/search/specifications", "catalog_by_spec"], readonly ["taxonomy", "GET", "/api/v1/taxonomy/categories", "get_category_taxonomy"], readonly ["whoami", "GET", "/api/v1/whoami", "whoami"], readonly ["coordinate", "POST", "/api/v1/pairings/coordinate", "coordinate_materials"], readonly ["demand", "GET", "/api/v1/demand", "get_material_demand"], readonly ["extractPalette", "POST", "/api/v1/search/palettes/extract", "extract_image_palette"], readonly ["specificationFacets", "GET", "/api/v1/catalog/specifications/facets", "list_spec_facets"], readonly ["attributeValues", "GET", "/api/v1/catalog/attributes/{attributeId}/values", "list_attribute_values"], readonly ["applicableSpecs", "GET", "/api/v1/taxonomy/categories/{key}/specs", "get_applicable_specs"], readonly ["glossary", "GET", "/api/v1/glossary/{term}", "explain_material_term"], readonly ["brands", "GET", "/api/v1/brands", "list_brands"], readonly ["brand", "GET", "/api/v1/brands/{brandSlug}", "get_brand_profile"], readonly ["uploadSourceMaterial", "POST", "/api/v1/source-material", "upload_source_material"], readonly ["sourceMaterialBatch", "GET", "/api/v1/source-material/{batchId}", "get_source_material_batch"], readonly ["capabilities", "GET", "/api/v1/capabilities", "list_public_capabilities"], readonly ["createRun", "POST", "/api/v1/runs", "create_public_run"], readonly ["run", "GET", "/api/v1/runs/{runId}", "get_public_run"], readonly ["runSchedule", "GET", "/api/v1/runs/{runId}/schedule", "get_run_finish_schedule"], readonly ["streamRunEvents", "GET", "/api/v1/runs/{runId}/events", "list_public_run_events"], readonly ["resumeRun", "POST", "/api/v1/runs/{runId}/resume", "resume_public_run"], readonly ["cancelRun", "POST", "/api/v1/runs/{runId}/cancel", "cancel_public_run"], readonly ["varyScheme", "POST", "/api/v1/schemes/vary", "vary_schemes"], readonly ["createProject", "POST", "/api/v1/projects", "create_box_project"], readonly ["listProjects", "GET", "/api/v1/projects", "list_box_projects"], readonly ["getProject", "GET", "/api/v1/projects/{projectId}", "get_box_project"], readonly ["appendProjectEvent", "POST", "/api/v1/projects/{projectId}/events", "append_box_project_event"], readonly ["demandBatch", "POST", "/api/v1/demand/batch", "get_demand_batch"], readonly ["codeAdvisory", "POST", "/api/v1/codes/advisory", "resolveCodeAdvisory"], readonly ["codes.context", "GET", "/api/v1/codes/context", "list_code_context"], readonly ["codes.requirements", "GET", "/api/v1/codes/requirements", "list_code_requirements"]];
|
|
3
3
|
export type SdkOperationId = (typeof OPERATION_DEFINITIONS)[number][3];
|
|
4
4
|
export type SdkOperation = Readonly<{
|
|
5
5
|
clientMethod: (typeof OPERATION_DEFINITIONS)[number][0];
|
|
@@ -8,4 +8,8 @@ export type SdkOperation = Readonly<{
|
|
|
8
8
|
operationId: SdkOperationId;
|
|
9
9
|
}>;
|
|
10
10
|
export declare const SDK_OPERATIONS: readonly SdkOperation[];
|
|
11
|
+
/** Look up a registered operation by its OpenAPI `operationId`. */
|
|
12
|
+
export declare function findSdkOperation(operationId: SdkOperationId): SdkOperation | undefined;
|
|
13
|
+
/** Substitute `{param}` path placeholders with percent-encoded values. */
|
|
14
|
+
export declare function operationPath(sdkOperation: SdkOperation, pathParams?: Readonly<Record<string, string>>): string;
|
|
11
15
|
export {};
|
package/operations.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const MATERIALGRAPH_API_VERSION = "0.
|
|
1
|
+
export const MATERIALGRAPH_API_VERSION = "0.7.0";
|
|
2
2
|
const OPERATION_DEFINITIONS = [
|
|
3
3
|
["search", "POST", "/api/v1/search", "search_materials_post"],
|
|
4
4
|
["searchGet", "GET", "/api/v1/search", "search_materials_get"],
|
|
@@ -22,6 +22,8 @@ const OPERATION_DEFINITIONS = [
|
|
|
22
22
|
["materialsCached", "GET", "/api/v1/materials/batch", "get_materials_batch_get"],
|
|
23
23
|
["browse", "GET", "/api/v1/search/browse", "search_browse_by_colour"],
|
|
24
24
|
["colourFacets", "GET", "/api/v1/colours/facets", "get_colour_facets"],
|
|
25
|
+
["colours.profiles", "GET", "/api/v1/colours/profiles", "get_category_colour_profiles"],
|
|
26
|
+
["colours.stats", "GET", "/api/v1/colours/stats", "get_colour_stats"],
|
|
25
27
|
["resolveColour", "GET", "/api/v1/search/colours/resolve", "resolve_colour_name"],
|
|
26
28
|
["suggestColour", "GET", "/api/v1/search/colours/suggest", "suggest_colour_names"],
|
|
27
29
|
["resolveAttribute", "GET", "/api/v1/catalog/attributes/resolve", "catalog_resolve_attribute"],
|
|
@@ -48,6 +50,32 @@ const OPERATION_DEFINITIONS = [
|
|
|
48
50
|
["applicableSpecs", "GET", "/api/v1/taxonomy/categories/{key}/specs", "get_applicable_specs"],
|
|
49
51
|
["glossary", "GET", "/api/v1/glossary/{term}", "explain_material_term"],
|
|
50
52
|
["brands", "GET", "/api/v1/brands", "list_brands"],
|
|
51
|
-
["brand", "GET", "/api/v1/brands/{
|
|
53
|
+
["brand", "GET", "/api/v1/brands/{brandSlug}", "get_brand_profile"],
|
|
54
|
+
["uploadSourceMaterial", "POST", "/api/v1/source-material", "upload_source_material"],
|
|
55
|
+
["sourceMaterialBatch", "GET", "/api/v1/source-material/{batchId}", "get_source_material_batch"],
|
|
56
|
+
["capabilities", "GET", "/api/v1/capabilities", "list_public_capabilities"],
|
|
57
|
+
["createRun", "POST", "/api/v1/runs", "create_public_run"],
|
|
58
|
+
["run", "GET", "/api/v1/runs/{runId}", "get_public_run"],
|
|
59
|
+
["runSchedule", "GET", "/api/v1/runs/{runId}/schedule", "get_run_finish_schedule"],
|
|
60
|
+
["streamRunEvents", "GET", "/api/v1/runs/{runId}/events", "list_public_run_events"],
|
|
61
|
+
["resumeRun", "POST", "/api/v1/runs/{runId}/resume", "resume_public_run"],
|
|
62
|
+
["cancelRun", "POST", "/api/v1/runs/{runId}/cancel", "cancel_public_run"],
|
|
63
|
+
["varyScheme", "POST", "/api/v1/schemes/vary", "vary_schemes"],
|
|
64
|
+
["createProject", "POST", "/api/v1/projects", "create_box_project"],
|
|
65
|
+
["listProjects", "GET", "/api/v1/projects", "list_box_projects"],
|
|
66
|
+
["getProject", "GET", "/api/v1/projects/{projectId}", "get_box_project"],
|
|
67
|
+
["appendProjectEvent", "POST", "/api/v1/projects/{projectId}/events", "append_box_project_event"],
|
|
68
|
+
["demandBatch", "POST", "/api/v1/demand/batch", "get_demand_batch"],
|
|
69
|
+
["codeAdvisory", "POST", "/api/v1/codes/advisory", "resolveCodeAdvisory"],
|
|
70
|
+
["codes.context", "GET", "/api/v1/codes/context", "list_code_context"],
|
|
71
|
+
["codes.requirements", "GET", "/api/v1/codes/requirements", "list_code_requirements"],
|
|
52
72
|
];
|
|
53
73
|
export const SDK_OPERATIONS = Object.freeze(OPERATION_DEFINITIONS.map(([clientMethod, method, path, operationId]) => Object.freeze({ clientMethod, method, path, operationId })));
|
|
74
|
+
/** Look up a registered operation by its OpenAPI `operationId`. */
|
|
75
|
+
export function findSdkOperation(operationId) {
|
|
76
|
+
return SDK_OPERATIONS.find((candidate) => candidate.operationId === operationId);
|
|
77
|
+
}
|
|
78
|
+
/** Substitute `{param}` path placeholders with percent-encoded values. */
|
|
79
|
+
export function operationPath(sdkOperation, pathParams = {}) {
|
|
80
|
+
return Object.entries(pathParams).reduce((path, [name, value]) => path.replace(`{${name}}`, encodeURIComponent(value)), sdkOperation.path);
|
|
81
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire types for the persistent Material Box project surface (`/api/v1/projects`).
|
|
3
|
+
* Hand-mirrored from `@materialgraph/products/projects`' Zod contract — the SDK
|
|
4
|
+
* has zero runtime dependency on `@materialgraph/*`. Kept shape-identical to the
|
|
5
|
+
* server contract; the OpenAPI parity test gates method/path/operationId, and the
|
|
6
|
+
* server route schemas gate the body shapes.
|
|
7
|
+
*/
|
|
8
|
+
/** The six governed project-event kinds. */
|
|
9
|
+
export type ProjectEventKind = "batch-attached" | "run-started" | "clarifying-answer" | "pairwise-preference" | "reference-chosen" | "scheme-adopted";
|
|
10
|
+
/** The frozen tuple of every project-event kind, for enumeration. */
|
|
11
|
+
export declare const PROJECT_EVENT_KINDS: readonly ProjectEventKind[];
|
|
12
|
+
/** One clarifying question and the designer's answer. */
|
|
13
|
+
export interface ClarifyingAnswer {
|
|
14
|
+
question: string;
|
|
15
|
+
answer: string;
|
|
16
|
+
}
|
|
17
|
+
/** One pairwise preference; `chosenId` is `leftId` or `rightId`. */
|
|
18
|
+
export interface PairwisePreference {
|
|
19
|
+
leftId: string;
|
|
20
|
+
rightId: string;
|
|
21
|
+
chosenId: string;
|
|
22
|
+
}
|
|
23
|
+
/** One stored event; `payload` is validated to the shape of `kind`. */
|
|
24
|
+
export interface ProjectEvent {
|
|
25
|
+
eventId: string;
|
|
26
|
+
kind: ProjectEventKind;
|
|
27
|
+
payload: Record<string, unknown>;
|
|
28
|
+
createdAt: string;
|
|
29
|
+
}
|
|
30
|
+
/** A lightweight project row for list views (no event fold). */
|
|
31
|
+
export interface ProjectSummary {
|
|
32
|
+
projectId: string;
|
|
33
|
+
principalId: string;
|
|
34
|
+
name: string;
|
|
35
|
+
createdAt: string;
|
|
36
|
+
updatedAt: string;
|
|
37
|
+
}
|
|
38
|
+
/** A project's assembled read model — identity plus the folded event collections. */
|
|
39
|
+
export interface ProjectState extends ProjectSummary {
|
|
40
|
+
batchIds: string[];
|
|
41
|
+
runIds: string[];
|
|
42
|
+
answers: ClarifyingAnswer[];
|
|
43
|
+
preferences: PairwisePreference[];
|
|
44
|
+
chosenReferences: string[];
|
|
45
|
+
adoptedSchemes: string[];
|
|
46
|
+
events: ProjectEvent[];
|
|
47
|
+
}
|
|
48
|
+
/** `GET /api/v1/projects` — the caller's projects, newest first. */
|
|
49
|
+
export interface ProjectListResponse {
|
|
50
|
+
projects: ProjectSummary[];
|
|
51
|
+
}
|
|
52
|
+
/** `POST /api/v1/projects` request body. */
|
|
53
|
+
export interface CreateProjectRequest {
|
|
54
|
+
name?: string;
|
|
55
|
+
}
|
|
56
|
+
/** `POST /api/v1/projects/{projectId}/events` request body. */
|
|
57
|
+
export interface AppendProjectEventRequest {
|
|
58
|
+
kind: ProjectEventKind;
|
|
59
|
+
payload: Record<string, unknown>;
|
|
60
|
+
}
|
|
61
|
+
/** `POST /api/v1/projects/{projectId}/events` response — the appended event receipt. */
|
|
62
|
+
export interface ProjectEventReceipt {
|
|
63
|
+
eventId: string;
|
|
64
|
+
projectId: string;
|
|
65
|
+
kind: ProjectEventKind;
|
|
66
|
+
createdAt: string;
|
|
67
|
+
}
|
package/project-types.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire types for the persistent Material Box project surface (`/api/v1/projects`).
|
|
3
|
+
* Hand-mirrored from `@materialgraph/products/projects`' Zod contract — the SDK
|
|
4
|
+
* has zero runtime dependency on `@materialgraph/*`. Kept shape-identical to the
|
|
5
|
+
* server contract; the OpenAPI parity test gates method/path/operationId, and the
|
|
6
|
+
* server route schemas gate the body shapes.
|
|
7
|
+
*/
|
|
8
|
+
/** The frozen tuple of every project-event kind, for enumeration. */
|
|
9
|
+
export const PROJECT_EVENT_KINDS = Object.freeze([
|
|
10
|
+
"batch-attached",
|
|
11
|
+
"run-started",
|
|
12
|
+
"clarifying-answer",
|
|
13
|
+
"pairwise-preference",
|
|
14
|
+
"reference-chosen",
|
|
15
|
+
"scheme-adopted",
|
|
16
|
+
]);
|
package/projects.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { HttpTransport } from "./http-transport.js";
|
|
2
|
+
import type { AppendProjectEventRequest, CreateProjectRequest, ProjectEventReceipt, ProjectListResponse, ProjectState } from "./project-types.js";
|
|
3
|
+
/** Create a project (`POST /api/v1/projects`). Requires the `mg:ingest` scope. */
|
|
4
|
+
export declare function createProject(transport: HttpTransport, body?: CreateProjectRequest, signal?: AbortSignal): Promise<ProjectState>;
|
|
5
|
+
/** Read a project's assembled state (`GET /api/v1/projects/{projectId}`). */
|
|
6
|
+
export declare function getProject(transport: HttpTransport, projectId: string, signal?: AbortSignal): Promise<ProjectState>;
|
|
7
|
+
/**
|
|
8
|
+
* Append one event to a project's process trail
|
|
9
|
+
* (`POST /api/v1/projects/{projectId}/events`). Requires the `mg:ingest` scope.
|
|
10
|
+
*/
|
|
11
|
+
export declare function appendProjectEvent(transport: HttpTransport, projectId: string, body: AppendProjectEventRequest, signal?: AbortSignal): Promise<ProjectEventReceipt>;
|
|
12
|
+
/** List your own projects, newest first (`GET /api/v1/projects`). */
|
|
13
|
+
export declare function listProjects(transport: HttpTransport, signal?: AbortSignal): Promise<ProjectListResponse>;
|
package/projects.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The persistent-project namespace of the SDK. Thin wrappers over the shared
|
|
3
|
+
* {@link HttpTransport} for the `/api/v1/projects` surface: create a project,
|
|
4
|
+
* read its assembled state, append process-trail events, and list your own.
|
|
5
|
+
* Box's proxy routes are thin wrappers over exactly these calls.
|
|
6
|
+
*/
|
|
7
|
+
import { MaterialGraphError } from "./errors.js";
|
|
8
|
+
import { HttpTransport } from "./http-transport.js";
|
|
9
|
+
import { findSdkOperation } from "./operations.js";
|
|
10
|
+
function projectOperation(operationId) {
|
|
11
|
+
const match = findSdkOperation(operationId);
|
|
12
|
+
if (!match)
|
|
13
|
+
throw MaterialGraphError.unexpected(`Unknown SDK operation: ${operationId}`);
|
|
14
|
+
return match;
|
|
15
|
+
}
|
|
16
|
+
/** Create a project (`POST /api/v1/projects`). Requires the `mg:ingest` scope. */
|
|
17
|
+
export function createProject(transport, body = {}, signal) {
|
|
18
|
+
return transport.requestJson(projectOperation("create_box_project"), {
|
|
19
|
+
body,
|
|
20
|
+
signal,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/** Read a project's assembled state (`GET /api/v1/projects/{projectId}`). */
|
|
24
|
+
export function getProject(transport, projectId, signal) {
|
|
25
|
+
return transport.requestJson(projectOperation("get_box_project"), {
|
|
26
|
+
pathParams: { projectId },
|
|
27
|
+
signal,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Append one event to a project's process trail
|
|
32
|
+
* (`POST /api/v1/projects/{projectId}/events`). Requires the `mg:ingest` scope.
|
|
33
|
+
*/
|
|
34
|
+
export function appendProjectEvent(transport, projectId, body, signal) {
|
|
35
|
+
return transport.requestJson(projectOperation("append_box_project_event"), {
|
|
36
|
+
body,
|
|
37
|
+
pathParams: { projectId },
|
|
38
|
+
signal,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/** List your own projects, newest first (`GET /api/v1/projects`). */
|
|
42
|
+
export function listProjects(transport, signal) {
|
|
43
|
+
return transport.requestJson(projectOperation("list_box_projects"), {
|
|
44
|
+
signal,
|
|
45
|
+
});
|
|
46
|
+
}
|
package/run-events.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed payloads for the composition Run event family — the friction fix flagged
|
|
3
|
+
* by the MG-443 walk. These narrow the loose {@link RunEvent.payloadJson} so
|
|
4
|
+
* consumers (the Box console) can render phase progress, the parsed programme,
|
|
5
|
+
* and the criteria-correction UI without re-typing each payload at the call
|
|
6
|
+
* site.
|
|
7
|
+
*
|
|
8
|
+
* Both wire generations are covered: the CURRENT `composition.*` strings the
|
|
9
|
+
* server emits today, and the LEGACY `material-box.*` strings kept for read-side
|
|
10
|
+
* dual-read compatibility. Shapes mirror
|
|
11
|
+
* `packages/mastra/src/workflow/composition/events.ts` and the
|
|
12
|
+
* `reviewCriteriaSuspendPayloadSchema` in `@materialgraph/products` — expressed
|
|
13
|
+
* as standalone TS types (no cross-package import; the SDK is publishable).
|
|
14
|
+
*/
|
|
15
|
+
import type { OpenEnum } from "./types.js";
|
|
16
|
+
import type { RunEvent } from "./run-types.js";
|
|
17
|
+
export declare const COMPOSITION_PHASE_EVENT_TYPES: readonly ["composition.phase", "material-box.phase"];
|
|
18
|
+
export declare const COMPOSITION_PROGRAMME_EVENT_TYPES: readonly ["composition.programme", "material-box.brief"];
|
|
19
|
+
export declare const COMPOSITION_REVIEW_CRITERIA_EVENT_TYPES: readonly ["composition.review-criteria", "material-box.review-criteria"];
|
|
20
|
+
export type CompositionPhaseEventType = (typeof COMPOSITION_PHASE_EVENT_TYPES)[number];
|
|
21
|
+
export type CompositionProgrammeEventType = (typeof COMPOSITION_PROGRAMME_EVENT_TYPES)[number];
|
|
22
|
+
export type CompositionReviewCriteriaEventType = (typeof COMPOSITION_REVIEW_CRITERIA_EVENT_TYPES)[number];
|
|
23
|
+
/** Payload of a `composition.phase` / `material-box.phase` progress event. */
|
|
24
|
+
export interface CompositionPhasePayload {
|
|
25
|
+
workflow: OpenEnum<"parse-material-brief" | "compose-material-schemes">;
|
|
26
|
+
phase: string;
|
|
27
|
+
label: string;
|
|
28
|
+
state: OpenEnum<"started" | "completed" | "failed">;
|
|
29
|
+
/** Additive narration (file names, error messages); absent on older events. */
|
|
30
|
+
detail?: string;
|
|
31
|
+
/** Additive tallies (slot/candidate/scheme counts); absent on older events. */
|
|
32
|
+
counts?: Record<string, number>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Payload of a `composition.programme` / `material-box.brief` event. The current
|
|
36
|
+
* generation carries `programme`; the legacy generation carried `brief`. Both
|
|
37
|
+
* are read structurally (the parsed programme document).
|
|
38
|
+
*/
|
|
39
|
+
export interface CompositionProgrammePayload {
|
|
40
|
+
programme?: unknown;
|
|
41
|
+
brief?: unknown;
|
|
42
|
+
}
|
|
43
|
+
/** One unresolved brief phrase offered for human correction at the review step. */
|
|
44
|
+
export interface CompositionReviewCriteriaSuggestion {
|
|
45
|
+
attributeId: string;
|
|
46
|
+
name: string;
|
|
47
|
+
term?: string;
|
|
48
|
+
score: number;
|
|
49
|
+
}
|
|
50
|
+
export interface CompositionReviewCriteriaUnresolved {
|
|
51
|
+
slotId: string;
|
|
52
|
+
raw: string;
|
|
53
|
+
suggestions: CompositionReviewCriteriaSuggestion[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Payload of a `composition.review-criteria` / `material-box.review-criteria`
|
|
57
|
+
* suspend event — the correction grammar the Box review step renders.
|
|
58
|
+
*/
|
|
59
|
+
export interface CompositionReviewCriteriaPayload {
|
|
60
|
+
unresolved: CompositionReviewCriteriaUnresolved[];
|
|
61
|
+
}
|
|
62
|
+
export interface CompositionPhaseEvent extends RunEvent {
|
|
63
|
+
type: CompositionPhaseEventType;
|
|
64
|
+
payloadJson: CompositionPhasePayload;
|
|
65
|
+
}
|
|
66
|
+
export interface CompositionProgrammeEvent extends RunEvent {
|
|
67
|
+
type: CompositionProgrammeEventType;
|
|
68
|
+
payloadJson: CompositionProgrammePayload;
|
|
69
|
+
}
|
|
70
|
+
export interface CompositionReviewCriteriaEvent extends RunEvent {
|
|
71
|
+
type: CompositionReviewCriteriaEventType;
|
|
72
|
+
payloadJson: CompositionReviewCriteriaPayload;
|
|
73
|
+
}
|
|
74
|
+
/** The discriminated union of all composition Run events. */
|
|
75
|
+
export type CompositionEvent = CompositionPhaseEvent | CompositionProgrammeEvent | CompositionReviewCriteriaEvent;
|
|
76
|
+
/**
|
|
77
|
+
* Narrow a {@link RunEvent} to the composition family by its `type`, returning
|
|
78
|
+
* `null` for lifecycle events (`queued`, `running`, `succeeded`, …) and any
|
|
79
|
+
* unknown type. Narrowing is by the discriminating `type` only — payloads are
|
|
80
|
+
* trusted structurally per the tolerant-parsing contract, never re-validated.
|
|
81
|
+
*/
|
|
82
|
+
export declare function parseRunEvent(event: RunEvent): CompositionEvent | null;
|
package/run-events.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// ── Wire event-type strings (both generations) ───────────────────────────────
|
|
2
|
+
export const COMPOSITION_PHASE_EVENT_TYPES = ["composition.phase", "material-box.phase"];
|
|
3
|
+
export const COMPOSITION_PROGRAMME_EVENT_TYPES = [
|
|
4
|
+
"composition.programme",
|
|
5
|
+
"material-box.brief",
|
|
6
|
+
];
|
|
7
|
+
export const COMPOSITION_REVIEW_CRITERIA_EVENT_TYPES = [
|
|
8
|
+
"composition.review-criteria",
|
|
9
|
+
"material-box.review-criteria",
|
|
10
|
+
];
|
|
11
|
+
const includesType = (types, type) => types.includes(type);
|
|
12
|
+
/**
|
|
13
|
+
* Narrow a {@link RunEvent} to the composition family by its `type`, returning
|
|
14
|
+
* `null` for lifecycle events (`queued`, `running`, `succeeded`, …) and any
|
|
15
|
+
* unknown type. Narrowing is by the discriminating `type` only — payloads are
|
|
16
|
+
* trusted structurally per the tolerant-parsing contract, never re-validated.
|
|
17
|
+
*/
|
|
18
|
+
export function parseRunEvent(event) {
|
|
19
|
+
if (includesType(COMPOSITION_PHASE_EVENT_TYPES, event.type)) {
|
|
20
|
+
return event;
|
|
21
|
+
}
|
|
22
|
+
if (includesType(COMPOSITION_PROGRAMME_EVENT_TYPES, event.type)) {
|
|
23
|
+
return event;
|
|
24
|
+
}
|
|
25
|
+
if (includesType(COMPOSITION_REVIEW_CRITERIA_EVENT_TYPES, event.type)) {
|
|
26
|
+
return event;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|