Drop Protobuf; move continuum/v1 domain model to JSON Schema
Nothing imported the proto-generated code (zero references to continuum-rust-types or @continuum/ts-types's proto export in any consumer repo), and protobuf's real value - one schema compiled to a compact binary wire format for both languages - never applied: BE<->proxy and FE<->BE are both JSON. Also fixes 8 broken $ref paths in the bambulab schemas and a root tsconfig.json that was sweeping the gitignored examples/ directory into typecheck. - proto/continuum/v1/*.proto -> schemas/continuum/v1/*.schema.json - packages/rust-types: hand-written serde structs instead of prost-build codegen - packages/ts-types: drop the generated/ proto barrel export, keep the hand-written TypeBox schemas as the TS source of truth - root package.json: drop build:ts, protoc, ts-proto
This commit is contained in:
@@ -8,8 +8,5 @@ bun.lock
|
|||||||
Cargo.lock
|
Cargo.lock
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
|
|
||||||
packages/ts-types/src/generated/*
|
|
||||||
!packages/ts-types/src/generated/.gitkeep
|
|
||||||
|
|
||||||
# Personal study files, not part of the real schema build.
|
# Personal study files, not part of the real schema build.
|
||||||
/examples/
|
/examples/
|
||||||
|
|||||||
@@ -1,35 +1,47 @@
|
|||||||
# continuum-schemas
|
# continuum-schemas
|
||||||
|
|
||||||
Single source of truth for the Continuum data model. Protobuf definitions in
|
Single source of truth for the Continuum data model. Everything here is
|
||||||
`proto/` are compiled into two consumer packages:
|
JSON Schema, compiled into two consumer packages:
|
||||||
|
|
||||||
- `packages/ts-types` - TypeScript types generated via `ts-proto`, plus
|
- `packages/ts-types` - hand-written [TypeBox](https://github.com/sinclairzx81/typebox)
|
||||||
hand-written [TypeBox](https://github.com/sinclairzx81/typebox) schemas
|
schemas under `src/schemas/` used for runtime validation in
|
||||||
under `src/schemas/` used for runtime validation in `continuum-backend`'s
|
`continuum-backend`'s ElysiaJS routes.
|
||||||
ElysiaJS routes.
|
- `packages/rust-types` - a Rust crate (`continuum-rust-types`) with
|
||||||
- `packages/rust-types` - a Rust crate (`continuum-rust-types`) that compiles
|
hand-written, `serde`-derived structs for `continuum-proxy` and
|
||||||
the same `.proto` files with `prost-build` (via `build.rs`), producing
|
`continuum-ai-worker`.
|
||||||
`serde`-derived structs for `continuum-proxy` and `continuum-ai-worker`.
|
|
||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
```
|
```
|
||||||
proto/continuum/v1/ canonical .proto message definitions
|
schemas/continuum/v1/ Continuum's own domain model (PrintJob, Template, ...)
|
||||||
packages/ts-types/ TypeBox schemas + generated TS proto types
|
schemas/bambulab/ Bambu Lab MQTT wire schemas (v1/v2, report + request)
|
||||||
packages/rust-types/ prost-generated Rust structs (build.rs codegen)
|
packages/ts-types/ TypeBox schemas (hand-written, mirrors schemas/)
|
||||||
|
packages/rust-types/ serde structs (hand-written, mirrors schemas/)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Build
|
`schemas/continuum/v1/*.schema.json` is the canonical shape for each
|
||||||
|
domain object; `packages/ts-types/src/schemas/` and
|
||||||
|
`packages/rust-types/src/lib.rs` both mirror it by hand. There are only
|
||||||
|
four small, stable DTOs here (`PrintJob`, `MaterialProfile`,
|
||||||
|
`PrintParameters`, `Template`), so keeping two hand-synced copies in sync
|
||||||
|
is less overhead than running a codegen pipeline (`protoc`/`ts-proto`/
|
||||||
|
`prost-build`) nothing actually consumed - see git history for the
|
||||||
|
protobuf version this replaced, and why it was dropped: every service in
|
||||||
|
this system talks JSON (JSON Schema for the wire, TypeBox/serde for
|
||||||
|
runtime validation), so protobuf's actual value - a single schema compiled
|
||||||
|
into a compact **binary** wire format for both languages - never applied.
|
||||||
|
|
||||||
Requires `protoc` on `PATH` and `npm install` run at the repo root first.
|
Whenever a domain schema changes, update all three by hand: the JSON
|
||||||
|
Schema file, the TypeBox schema, and the Rust struct.
|
||||||
|
|
||||||
|
## Build / verify
|
||||||
|
|
||||||
|
Requires `npm install` at the repo root, and a Rust toolchain, first.
|
||||||
|
|
||||||
```
|
```
|
||||||
npm install
|
npm install
|
||||||
npm run build:ts # protoc + ts-proto -> packages/ts-types/src/generated
|
npm run build:rust # cargo build, confirms the Rust structs compile
|
||||||
npm run build:rust # cargo build, runs build.rs -> prost-generated structs
|
npm run typecheck # tsc -b, confirms the TypeBox schemas compile
|
||||||
npm run build # both
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Generated TS output under `packages/ts-types/src/generated` is build-derived
|
There's no `build:ts` step - the TS side is hand-written, not generated.
|
||||||
and gitignored. The Rust crate's generated code lands in `OUT_DIR` per
|
|
||||||
standard `prost-build` conventions and is never committed.
|
|
||||||
|
|||||||
+1
-3
@@ -6,13 +6,11 @@
|
|||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:ts": "protoc --plugin=protoc-gen-ts_proto=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=packages/ts-types/src/generated --ts_proto_opt=esModuleInterop=true,outputServices=false,useOptionals=messages,outputIndex=true -I proto $(find proto -name '*.proto')",
|
|
||||||
"build:rust": "cargo build -p continuum-rust-types --manifest-path packages/rust-types/Cargo.toml",
|
"build:rust": "cargo build -p continuum-rust-types --manifest-path packages/rust-types/Cargo.toml",
|
||||||
"build": "npm run build:ts && npm run build:rust",
|
"build": "npm run build:rust",
|
||||||
"typecheck": "tsc -b"
|
"typecheck": "tsc -b"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ts-proto": "^1.181.0",
|
|
||||||
"typescript": "^5.5.0"
|
"typescript": "^5.5.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,7 @@ name = "continuum_types"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
prost = "0.13"
|
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
prost-build = "0.13"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let proto_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
||||||
.join("../../proto")
|
|
||||||
.canonicalize()
|
|
||||||
.expect("proto root must exist");
|
|
||||||
|
|
||||||
let proto_files = [
|
|
||||||
proto_root.join("continuum/v1/material.proto"),
|
|
||||||
proto_root.join("continuum/v1/print_params.proto"),
|
|
||||||
proto_root.join("continuum/v1/template.proto"),
|
|
||||||
proto_root.join("continuum/v1/print_job.proto"),
|
|
||||||
];
|
|
||||||
|
|
||||||
for file in &proto_files {
|
|
||||||
println!("cargo:rerun-if-changed={}", file.display());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut config = prost_build::Config::new();
|
|
||||||
config.type_attribute(".", "#[derive(serde::Serialize, serde::Deserialize)]");
|
|
||||||
config.type_attribute(".", "#[serde(rename_all = \"camelCase\")]");
|
|
||||||
|
|
||||||
// prost stores proto3 enums as plain `i32` fields (not the generated
|
|
||||||
// enum type), so the blanket type_attribute above never actually runs
|
|
||||||
// for `status` - it'd serialize as a bare number, disagreeing with
|
|
||||||
// TypeBox's full-name string literals in ts-types. Route the field
|
|
||||||
// through PrintJobStatus's own as_str_name()/from_str_name() instead,
|
|
||||||
// matching protobuf's own canonical JSON enum representation.
|
|
||||||
config.field_attribute(
|
|
||||||
".continuum.v1.PrintJob.status",
|
|
||||||
"#[serde(with = \"crate::print_job_status_serde\")]",
|
|
||||||
);
|
|
||||||
|
|
||||||
config
|
|
||||||
.compile_protos(&proto_files, &[proto_root])
|
|
||||||
.expect("failed to compile continuum .proto sources");
|
|
||||||
}
|
|
||||||
@@ -1,46 +1,80 @@
|
|||||||
pub mod continuum {
|
// Hand-written structs mirroring the JSON Schemas in `schemas/continuum/v1/`
|
||||||
pub mod v1 {
|
// and the TypeBox schemas in `ts-types/src/schemas/` - this used to be
|
||||||
include!(concat!(env!("OUT_DIR"), "/continuum.v1.rs"));
|
// prost-generated from `.proto` sources, but nothing here needed protobuf's
|
||||||
}
|
// actual value (cross-language binary codegen): both consumers (this crate
|
||||||
|
// and ts-types) only ever exchange JSON, so a hand-synced struct is less
|
||||||
|
// machinery than a `protoc`/`prost-build` pipeline for the same three
|
||||||
|
// flat DTOs. Keep field names and the `PrintJobStatus` string values in
|
||||||
|
// sync with `ts-types/src/schemas/` by hand when either side changes.
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct MaterialProfile {
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub filament_type: String,
|
||||||
|
pub nozzle_temp_c: f64,
|
||||||
|
pub bed_temp_c: f64,
|
||||||
|
pub density_g_cm3: f64,
|
||||||
|
pub color_hex: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use continuum::v1::{
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
MaterialProfile, PrintJob, PrintJobStatus, PrintParameters, Template,
|
#[serde(rename_all = "camelCase")]
|
||||||
};
|
pub struct PrintParameters {
|
||||||
|
pub layer_height_mm: f64,
|
||||||
// PrintJob.status is generated as a plain i32 (see build.rs's comment) -
|
pub infill_percent: i32,
|
||||||
// (de)serialize it via PrintJobStatus's full proto name strings
|
pub infill_pattern: String,
|
||||||
// (e.g. "PRINT_JOB_STATUS_QUEUED") so Rust's JSON matches ts-types'
|
pub print_speed_mm_s: f64,
|
||||||
// TypeBox schema and protobuf's own canonical JSON enum mapping.
|
pub supports_enabled: bool,
|
||||||
mod print_job_status_serde {
|
pub wall_count: i32,
|
||||||
use super::PrintJobStatus;
|
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|
||||||
|
|
||||||
pub fn serialize<S: Serializer>(value: &i32, serializer: S) -> Result<S::Ok, S::Error> {
|
|
||||||
let status = PrintJobStatus::try_from(*value).unwrap_or(PrintJobStatus::Unspecified);
|
|
||||||
status.as_str_name().serialize(serializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<i32, D::Error> {
|
|
||||||
let name = String::deserialize(deserializer)?;
|
|
||||||
PrintJobStatus::from_str_name(&name)
|
|
||||||
.map(|status| status as i32)
|
|
||||||
.ok_or_else(|| serde::de::Error::custom(format!("unknown PrintJobStatus: {name}")))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bambu's raw MQTT command/report structs are NOT modeled here - they're
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
// plain hand-written Rust + serde in continuum-proxy's
|
#[serde(rename_all = "camelCase")]
|
||||||
// src/printer/bambu_commands/, not proto. That data is JSON-over-MQTT
|
pub struct Template {
|
||||||
// (not binary protobuf), and only continuum-proxy ever needs to parse it
|
pub id: String,
|
||||||
// - none of protobuf's actual value (cross-language codegen, binary wire
|
pub name: String,
|
||||||
// efficiency) applies, and forcing it through prost-build's codegen model
|
pub description: String,
|
||||||
// anyway produced real, avoidable friction (see this crate's git history
|
pub owner_id: String,
|
||||||
// for the specifics: a field/variant attribute-matching collision on
|
pub model_file_key: String,
|
||||||
// `oneof`, needing package-scoped `type_attribute` calls, explicit
|
pub material: MaterialProfile,
|
||||||
// `field_attribute(..., "#[serde(default)]")` for fields that aren't
|
pub print_parameters: PrintParameters,
|
||||||
// always present - every one of these disappears with a hand-written
|
pub created_at_unix: i64,
|
||||||
// struct, where `Option<T>` and `#[serde(flatten)]` just work with zero
|
pub updated_at_unix: i64,
|
||||||
// configuration). Proto stays for continuum.v1 above, which - unlike
|
pub tags: Vec<String>,
|
||||||
// this - is a schema we designed ourselves and that both TS and Rust
|
}
|
||||||
// genuinely need.
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum PrintJobStatus {
|
||||||
|
#[serde(rename = "PRINT_JOB_STATUS_UNSPECIFIED")]
|
||||||
|
Unspecified,
|
||||||
|
#[serde(rename = "PRINT_JOB_STATUS_QUEUED")]
|
||||||
|
Queued,
|
||||||
|
#[serde(rename = "PRINT_JOB_STATUS_PRINTING")]
|
||||||
|
Printing,
|
||||||
|
#[serde(rename = "PRINT_JOB_STATUS_PAUSED")]
|
||||||
|
Paused,
|
||||||
|
#[serde(rename = "PRINT_JOB_STATUS_COMPLETED")]
|
||||||
|
Completed,
|
||||||
|
#[serde(rename = "PRINT_JOB_STATUS_FAILED")]
|
||||||
|
Failed,
|
||||||
|
#[serde(rename = "PRINT_JOB_STATUS_CANCELLED")]
|
||||||
|
Cancelled,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PrintJob {
|
||||||
|
pub id: String,
|
||||||
|
pub farm_id: String,
|
||||||
|
pub printer_id: String,
|
||||||
|
pub template_id: String,
|
||||||
|
pub status: PrintJobStatus,
|
||||||
|
pub progress_percent: f64,
|
||||||
|
pub started_at_unix: i64,
|
||||||
|
pub completed_at_unix: i64,
|
||||||
|
pub gcode_file_key: String,
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ fn sample(status: PrintJobStatus) -> PrintJob {
|
|||||||
farm_id: "farm-1".into(),
|
farm_id: "farm-1".into(),
|
||||||
printer_id: "printer-1".into(),
|
printer_id: "printer-1".into(),
|
||||||
template_id: "template-1".into(),
|
template_id: "template-1".into(),
|
||||||
status: status as i32,
|
status,
|
||||||
progress_percent: 50.0,
|
progress_percent: 50.0,
|
||||||
started_at_unix: 0,
|
started_at_unix: 0,
|
||||||
completed_at_unix: 0,
|
completed_at_unix: 0,
|
||||||
@@ -14,9 +14,8 @@ fn sample(status: PrintJobStatus) -> PrintJob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regression test: PrintJob.status must serialize as the full proto enum
|
// Regression test: PrintJob.status must serialize as the full name string
|
||||||
// name (matching ts-types' TypeBox schema), not the raw i32 prost stores
|
// (matching ts-types' TypeBox schema), not a bare enum discriminant.
|
||||||
// it as internally.
|
|
||||||
#[test]
|
#[test]
|
||||||
fn status_serializes_as_full_proto_enum_name() {
|
fn status_serializes_as_full_proto_enum_name() {
|
||||||
let json = serde_json::to_value(sample(PrintJobStatus::Printing)).unwrap();
|
let json = serde_json::to_value(sample(PrintJobStatus::Printing)).unwrap();
|
||||||
@@ -28,5 +27,5 @@ fn status_round_trips_through_json() {
|
|||||||
let original = sample(PrintJobStatus::Completed);
|
let original = sample(PrintJobStatus::Completed);
|
||||||
let json = serde_json::to_string(&original).unwrap();
|
let json = serde_json::to_string(&original).unwrap();
|
||||||
let restored: PrintJob = serde_json::from_str(&json).unwrap();
|
let restored: PrintJob = serde_json::from_str(&json).unwrap();
|
||||||
assert_eq!(restored.status, PrintJobStatus::Completed as i32);
|
assert_eq!(restored.status, PrintJobStatus::Completed);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,6 @@
|
|||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sinclair/typebox": "^0.32.0",
|
"@sinclair/typebox": "^0.32.0"
|
||||||
"protobufjs": "^7.4.0",
|
|
||||||
"long": "^5.2.3"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
-1
@@ -1,2 +1 @@
|
|||||||
export * from "./schemas";
|
export * from "./schemas";
|
||||||
export * as proto from "./generated";
|
|
||||||
|
|||||||
@@ -1,6 +1 @@
|
|||||||
export * from "./schemas";
|
export * from "./schemas";
|
||||||
// `src/generated/**` is produced by `npm run build:ts` (protoc + ts-proto)
|
|
||||||
// from the .proto sources in /proto and is not committed. Re-export it
|
|
||||||
// here once generated so consumers get both the TypeBox runtime schemas
|
|
||||||
// and the proto-derived TS types from a single package entry point.
|
|
||||||
export * as proto from "./generated";
|
|
||||||
|
|||||||
@@ -1,7 +1 @@
|
|||||||
export * from "./schemas";
|
export * from "./schemas";
|
||||||
|
|
||||||
// `src/generated/**` is produced by `npm run build:ts` (protoc + ts-proto)
|
|
||||||
// from the .proto sources in /proto and is not committed. Re-export it
|
|
||||||
// here once generated so consumers get both the TypeBox runtime schemas
|
|
||||||
// and the proto-derived TS types from a single package entry point.
|
|
||||||
export * as proto from "./generated";
|
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package continuum.v1;
|
|
||||||
|
|
||||||
message MaterialProfile {
|
|
||||||
string id = 1;
|
|
||||||
string name = 2;
|
|
||||||
string filament_type = 3;
|
|
||||||
double nozzle_temp_c = 4;
|
|
||||||
double bed_temp_c = 5;
|
|
||||||
double density_g_cm3 = 6;
|
|
||||||
string color_hex = 7;
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package continuum.v1;
|
|
||||||
|
|
||||||
enum PrintJobStatus {
|
|
||||||
PRINT_JOB_STATUS_UNSPECIFIED = 0;
|
|
||||||
PRINT_JOB_STATUS_QUEUED = 1;
|
|
||||||
PRINT_JOB_STATUS_PRINTING = 2;
|
|
||||||
PRINT_JOB_STATUS_PAUSED = 3;
|
|
||||||
PRINT_JOB_STATUS_COMPLETED = 4;
|
|
||||||
PRINT_JOB_STATUS_FAILED = 5;
|
|
||||||
PRINT_JOB_STATUS_CANCELLED = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
message PrintJob {
|
|
||||||
string id = 1;
|
|
||||||
string farm_id = 2;
|
|
||||||
string printer_id = 3;
|
|
||||||
string template_id = 4;
|
|
||||||
PrintJobStatus status = 5;
|
|
||||||
double progress_percent = 6;
|
|
||||||
int64 started_at_unix = 7;
|
|
||||||
int64 completed_at_unix = 8;
|
|
||||||
string gcode_file_key = 9;
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package continuum.v1;
|
|
||||||
|
|
||||||
message PrintParameters {
|
|
||||||
double layer_height_mm = 1;
|
|
||||||
int32 infill_percent = 2;
|
|
||||||
string infill_pattern = 3;
|
|
||||||
double print_speed_mm_s = 4;
|
|
||||||
bool supports_enabled = 5;
|
|
||||||
int32 wall_count = 6;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package continuum.v1;
|
|
||||||
|
|
||||||
import "continuum/v1/material.proto";
|
|
||||||
import "continuum/v1/print_params.proto";
|
|
||||||
|
|
||||||
message Template {
|
|
||||||
string id = 1;
|
|
||||||
string name = 2;
|
|
||||||
string description = 3;
|
|
||||||
string owner_id = 4;
|
|
||||||
string model_file_key = 5;
|
|
||||||
MaterialProfile material = 6;
|
|
||||||
PrintParameters print_parameters = 7;
|
|
||||||
int64 created_at_unix = 8;
|
|
||||||
int64 updated_at_unix = 9;
|
|
||||||
repeated string tags = 10;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/continuum/v1/material.schema.json",
|
||||||
|
"title": "MaterialProfile",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": { "type": "string", "format": "uuid" },
|
||||||
|
"name": { "type": "string", "minLength": 1 },
|
||||||
|
"filamentType": { "type": "string", "minLength": 1 },
|
||||||
|
"nozzleTempC": { "type": "number" },
|
||||||
|
"bedTempC": { "type": "number" },
|
||||||
|
"densityGCm3": { "type": "number" },
|
||||||
|
"colorHex": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$" }
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"filamentType",
|
||||||
|
"nozzleTempC",
|
||||||
|
"bedTempC",
|
||||||
|
"densityGCm3",
|
||||||
|
"colorHex"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/continuum/v1/print_job.schema.json",
|
||||||
|
"title": "PrintJob",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": { "type": "string", "format": "uuid" },
|
||||||
|
"farmId": { "type": "string", "format": "uuid" },
|
||||||
|
"printerId": { "type": "string", "format": "uuid" },
|
||||||
|
"templateId": { "type": "string", "format": "uuid" },
|
||||||
|
"status": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"PRINT_JOB_STATUS_UNSPECIFIED",
|
||||||
|
"PRINT_JOB_STATUS_QUEUED",
|
||||||
|
"PRINT_JOB_STATUS_PRINTING",
|
||||||
|
"PRINT_JOB_STATUS_PAUSED",
|
||||||
|
"PRINT_JOB_STATUS_COMPLETED",
|
||||||
|
"PRINT_JOB_STATUS_FAILED",
|
||||||
|
"PRINT_JOB_STATUS_CANCELLED"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"progressPercent": { "type": "number", "minimum": 0, "maximum": 100 },
|
||||||
|
"startedAtUnix": { "type": "integer" },
|
||||||
|
"completedAtUnix": { "type": "integer" },
|
||||||
|
"gcodeFileKey": { "type": "string", "minLength": 1 }
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"farmId",
|
||||||
|
"printerId",
|
||||||
|
"templateId",
|
||||||
|
"status",
|
||||||
|
"progressPercent",
|
||||||
|
"startedAtUnix",
|
||||||
|
"completedAtUnix",
|
||||||
|
"gcodeFileKey"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/continuum/v1/print_params.schema.json",
|
||||||
|
"title": "PrintParameters",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"layerHeightMm": { "type": "number", "minimum": 0.04, "maximum": 1.0 },
|
||||||
|
"infillPercent": { "type": "integer", "minimum": 0, "maximum": 100 },
|
||||||
|
"infillPattern": { "type": "string", "minLength": 1 },
|
||||||
|
"printSpeedMmS": { "type": "number", "minimum": 0 },
|
||||||
|
"supportsEnabled": { "type": "boolean" },
|
||||||
|
"wallCount": { "type": "integer", "minimum": 0 }
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"layerHeightMm",
|
||||||
|
"infillPercent",
|
||||||
|
"infillPattern",
|
||||||
|
"printSpeedMmS",
|
||||||
|
"supportsEnabled",
|
||||||
|
"wallCount"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/continuum/v1/template.schema.json",
|
||||||
|
"title": "Template",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": { "type": "string", "format": "uuid" },
|
||||||
|
"name": { "type": "string", "minLength": 1 },
|
||||||
|
"description": { "type": "string" },
|
||||||
|
"ownerId": { "type": "string", "format": "uuid" },
|
||||||
|
"modelFileKey": { "type": "string", "minLength": 1 },
|
||||||
|
"material": { "$ref": "material.schema.json" },
|
||||||
|
"printParameters": { "$ref": "print_params.schema.json" },
|
||||||
|
"createdAtUnix": { "type": "integer" },
|
||||||
|
"updatedAtUnix": { "type": "integer" },
|
||||||
|
"tags": { "type": "array", "items": { "type": "string" } }
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"description",
|
||||||
|
"ownerId",
|
||||||
|
"modelFileKey",
|
||||||
|
"material",
|
||||||
|
"printParameters",
|
||||||
|
"createdAtUnix",
|
||||||
|
"updatedAtUnix",
|
||||||
|
"tags"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user