chore: bootstrap nana-story M0
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
use std::{
|
||||
env, fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use nana_domain::{
|
||||
AcquisitionMode, ActionSuggestion, AppInfo, BeatKind, CharacterCard, CharacterJudgmentRule,
|
||||
CharacterStyle, CheckDifficulty, CheckRecord, CheckResult, ClockState, DemoPackSummary,
|
||||
HistoryNodeView, ItemAcquisition, ItemInstance, ItemMechanics, ItemPlacement, ItemSpec,
|
||||
KnowledgeCertainty, KnowledgeRecord, Persona, PlayerItemView, PlayerKnowledgeView,
|
||||
PlayerPromiseView, PlayerView, PlotEvent, PlotModule, PlotOutcome, PlotPressure, Promise,
|
||||
PromiseStatus, PromiseWeight, RelationshipAdjustment, RelationshipAxes, RelationshipBand,
|
||||
RelationshipDimension, RelationshipState, RelationshipView, ResourceBundle, ResourceHeader,
|
||||
ResourceId, ResourceKind, ResourceRef, RuntimeState, SkillValue, StateDelta, StateOp, Story,
|
||||
StoryBinding, StoryNode, TurnFailure, TurnFailureCode, TurnIntent, TurnRequest, TurnResult,
|
||||
ValidationCode, ValidationIssue, ValidationReport, VisualDirective, WorldBook, WorldBookEntry,
|
||||
};
|
||||
use schemars::{JsonSchema, schema_for};
|
||||
use serde::Serialize;
|
||||
use sha2::{Digest, Sha256};
|
||||
use ts_rs::TS;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let check = env::args().any(|argument| argument == "--check");
|
||||
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../..");
|
||||
let outputs = generated_outputs(&root)?;
|
||||
|
||||
if check {
|
||||
let mut stale = Vec::new();
|
||||
for (path, expected) in outputs {
|
||||
if fs::read(&path).ok().as_deref() != Some(expected.as_slice()) {
|
||||
stale.push(path);
|
||||
}
|
||||
}
|
||||
if stale.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
for path in stale {
|
||||
eprintln!("stale generated contract: {}", path.display());
|
||||
}
|
||||
return Err("generated contracts are stale".into());
|
||||
}
|
||||
|
||||
for (path, bytes) in outputs {
|
||||
if let Some(parent) = path.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
}
|
||||
fs::write(path, bytes)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generated_outputs(
|
||||
root: &Path,
|
||||
) -> Result<Vec<(PathBuf, Vec<u8>)>, Box<dyn std::error::Error>> {
|
||||
let mut outputs = Vec::new();
|
||||
let schema_dir = root.join("contracts/schema");
|
||||
|
||||
add_schema::<ResourceHeader>(&mut outputs, &schema_dir, "resource-header")?;
|
||||
add_schema::<CharacterCard>(&mut outputs, &schema_dir, "character-card")?;
|
||||
add_schema::<WorldBook>(&mut outputs, &schema_dir, "world-book")?;
|
||||
add_schema::<Persona>(&mut outputs, &schema_dir, "persona")?;
|
||||
add_schema::<PlotModule>(&mut outputs, &schema_dir, "plot-module")?;
|
||||
add_schema::<ItemSpec>(&mut outputs, &schema_dir, "item-spec")?;
|
||||
add_schema::<ResourceBundle>(&mut outputs, &schema_dir, "resource-bundle")?;
|
||||
add_schema::<StoryNode>(&mut outputs, &schema_dir, "story-node")?;
|
||||
add_schema::<RuntimeState>(&mut outputs, &schema_dir, "runtime-state")?;
|
||||
add_schema::<PlayerView>(&mut outputs, &schema_dir, "player-view")?;
|
||||
add_schema::<TurnRequest>(&mut outputs, &schema_dir, "turn-request")?;
|
||||
add_schema::<TurnResult>(&mut outputs, &schema_dir, "turn-result")?;
|
||||
add_schema::<TurnFailure>(&mut outputs, &schema_dir, "turn-failure")?;
|
||||
add_schema::<AppInfo>(&mut outputs, &schema_dir, "app-info")?;
|
||||
add_schema::<DemoPackSummary>(&mut outputs, &schema_dir, "demo-pack-summary")?;
|
||||
|
||||
let declarations = [
|
||||
ResourceId::decl(),
|
||||
ResourceKind::decl(),
|
||||
ResourceRef::decl(),
|
||||
ResourceHeader::decl(),
|
||||
CharacterStyle::decl(),
|
||||
CharacterJudgmentRule::decl(),
|
||||
SkillValue::decl(),
|
||||
CharacterCard::decl(),
|
||||
WorldBookEntry::decl(),
|
||||
WorldBook::decl(),
|
||||
Persona::decl(),
|
||||
PlotPressure::decl(),
|
||||
PlotOutcome::decl(),
|
||||
PlotEvent::decl(),
|
||||
PlotModule::decl(),
|
||||
ItemMechanics::decl(),
|
||||
ItemSpec::decl(),
|
||||
ResourceBundle::decl(),
|
||||
RelationshipAxes::decl(),
|
||||
RelationshipAdjustment::decl(),
|
||||
RelationshipDimension::decl(),
|
||||
RelationshipBand::decl(),
|
||||
RelationshipView::decl(),
|
||||
PromiseStatus::decl(),
|
||||
PromiseWeight::decl(),
|
||||
Promise::decl(),
|
||||
RelationshipState::decl(),
|
||||
KnowledgeCertainty::decl(),
|
||||
KnowledgeRecord::decl(),
|
||||
ItemPlacement::decl(),
|
||||
AcquisitionMode::decl(),
|
||||
ItemAcquisition::decl(),
|
||||
ItemInstance::decl(),
|
||||
CheckDifficulty::decl(),
|
||||
CheckResult::decl(),
|
||||
CheckRecord::decl(),
|
||||
ClockState::decl(),
|
||||
StoryBinding::decl(),
|
||||
Story::decl(),
|
||||
StateDelta::decl(),
|
||||
StateOp::decl(),
|
||||
StoryNode::decl(),
|
||||
RuntimeState::decl(),
|
||||
BeatKind::decl(),
|
||||
VisualDirective::decl(),
|
||||
PresentationBeat::decl(),
|
||||
ActionSuggestion::decl(),
|
||||
PlayerItemView::decl(),
|
||||
PlayerKnowledgeView::decl(),
|
||||
PlayerPromiseView::decl(),
|
||||
HistoryNodeView::decl(),
|
||||
PlayerView::decl(),
|
||||
TurnIntent::decl(),
|
||||
TurnRequest::decl(),
|
||||
TurnResult::decl(),
|
||||
TurnFailureCode::decl(),
|
||||
TurnFailure::decl(),
|
||||
AppInfo::decl(),
|
||||
DemoPackSummary::decl(),
|
||||
ValidationCode::decl(),
|
||||
ValidationIssue::decl(),
|
||||
ValidationReport::decl(),
|
||||
]
|
||||
.join("\n\n");
|
||||
let ts = format!(
|
||||
"// @generated by crates/nana-contracts; do not edit.\n\n{declarations}\n"
|
||||
);
|
||||
outputs.push((
|
||||
root.join("contracts/ts/index.ts"),
|
||||
ts.into_bytes(),
|
||||
));
|
||||
|
||||
let domain_source = fs::read(root.join("crates/nana-domain/src/lib.rs"))?;
|
||||
let source_hash = format!("{:x}\n", Sha256::digest(domain_source));
|
||||
outputs.push((
|
||||
root.join("contracts/.source.sha256"),
|
||||
source_hash.into_bytes(),
|
||||
));
|
||||
|
||||
Ok(outputs)
|
||||
}
|
||||
|
||||
fn add_schema<T: JsonSchema + Serialize>(
|
||||
outputs: &mut Vec<(PathBuf, Vec<u8>)>,
|
||||
schema_dir: &Path,
|
||||
name: &str,
|
||||
) -> Result<(), serde_json::Error> {
|
||||
let mut bytes = serde_json::to_vec_pretty(&schema_for!(T))?;
|
||||
bytes.push(b'\n');
|
||||
outputs.push((schema_dir.join(format!("{name}.schema.json")), bytes));
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user