type-bridge-schema-codegen 2.2.1

Deterministic projection-only schema emitters for type-bridge
Documentation
use type_bridge_contract::fingerprint::SemanticProfileId;
use type_bridge_contract::projection::{
    BindingTarget, CodeResourceDigest, ProjectionConfig, ProjectionHandler, RuntimeProjection,
};
use type_bridge_contract::schema::DocumentId;
use type_bridge_schema::{SchemaDocumentSet, normalize_documents, project, resolve};
use type_bridge_schema_codegen::{PythonEmitter, RustEmitter, TypeScriptEmitter};

mod support;

const DOCUMENTED_SCHEMA: &str = r#"format: typebridge.schema/v2
attributes:
  display-name: {value: string}
entities:
  actor: {}
  person:
    doc: Type */ documentation.
    sub: {type: actor, doc: Sub */ documentation.}
    owns:
      display-name: {doc: Owns */ documentation.}
relations:
  employment:
    relates:
      employee: {doc: Relates */ documentation.}
plays:
  person:
    employment:
      employee: {doc: Plays */ documentation.}
functions:
  documented:
    doc: Function */ documentation.
    parameters:
      - {name: person, type: person}
    returns:
      stream: [person]
    body:
      typeql: |-
        match
          $person isa person;
        return { $person };
"#;

fn projected(
    target: BindingTarget,
    config: ProjectionConfig,
    handlers: &[ProjectionHandler],
    resources: &[CodeResourceDigest],
) -> RuntimeProjection {
    let documents = SchemaDocumentSet::parse([(
        DocumentId::new("documentation.yaml").unwrap(),
        DOCUMENTED_SCHEMA,
    )])
    .unwrap();
    let declared = normalize_documents(&documents).unwrap();
    let resolved = resolve(
        &declared,
        &SemanticProfileId::new("typedb-3.12.1/v1").unwrap(),
    )
    .unwrap();
    project(&resolved, target, &config, handlers, resources).unwrap()
}

#[test]
fn every_annotatable_doc_subject_reaches_safe_cross_target_documentation() {
    let authority = support::authority(DOCUMENTED_SCHEMA);
    let python_emitter = PythonEmitter::new();
    let python_resources = python_emitter.code_resources().unwrap();
    let python_projection = projected(
        BindingTarget::Python,
        ProjectionConfig::python(),
        &python_emitter.generator_handlers(),
        &python_resources,
    );
    let python = python_emitter.emit(&python_projection, &authority).unwrap();
    let python_models = std::str::from_utf8(python.get("_models.pyi").unwrap()).unwrap();
    let python_schema = std::str::from_utf8(python.get("_schema.py").unwrap()).unwrap();
    assert!(python_models.contains(
        "\"Type */ documentation.\\n\\nDirect subtype of `actor`:\\nSub */ documentation.\""
    ));
    assert!(
        python_models
            .contains("    #: Owns */ documentation.\n    display_name: _FieldDescriptor["),
        "{python_models}"
    );
    assert!(
        python_models.contains("    #: Relates */ documentation.\n    employee: _RoleDescriptor[")
    );
    assert!(
        python_models.contains("#: Function */ documentation.\ndocumented: Final[FunctionRef[")
    );
    assert!(python_schema.contains("    #: Plays */ documentation.\n"));

    let typescript_emitter = TypeScriptEmitter::new();
    let typescript_resources = typescript_emitter.code_resources().unwrap();
    let typescript_projection = projected(
        BindingTarget::TypeScript,
        ProjectionConfig::typescript(),
        &typescript_emitter.generator_handlers(),
        &typescript_resources,
    );
    let typescript = typescript_emitter
        .emit(&typescript_projection, &authority)
        .unwrap();
    let typescript_models = std::str::from_utf8(typescript.get("src/models.ts").unwrap()).unwrap();
    let typescript_schema = std::str::from_utf8(typescript.get("src/schema.ts").unwrap()).unwrap();
    let typescript_functions =
        std::str::from_utf8(typescript.get("src/functions.ts").unwrap()).unwrap();
    assert!(typescript_models.contains(
        " * Type *\\/ documentation.\n * \n * Direct subtype of `actor`:\n * Sub *\\/ documentation."
    ));
    assert!(
        typescript_models
            .contains("  /**\n   * Owns *\\/ documentation.\n   */\n  readonly displayName:")
    );
    assert!(
        typescript_models
            .contains("  /**\n   * Relates *\\/ documentation.\n   */\n  readonly employee:")
    );
    assert!(typescript_schema.contains(
        "/**\n * Plays *\\/ documentation.\n */\nexport const playsPersonEmploymentEmployee"
    ));
    assert!(
        typescript_functions
            .contains("/**\n * Function *\\/ documentation.\n */\nexport const documented:")
    );
    let rust_emitter = RustEmitter::new();
    let rust_resources = rust_emitter.code_resources().unwrap();
    let rust_projection = projected(
        BindingTarget::Rust,
        ProjectionConfig::rust(),
        &rust_emitter.generator_handlers(),
        &rust_resources,
    );
    let rust = rust_emitter.emit(&rust_projection, &authority).unwrap();
    let rust_read = std::str::from_utf8(rust.get("src/read.rs").unwrap()).unwrap();
    let rust_tokens = std::str::from_utf8(rust.get("src/tokens.rs").unwrap()).unwrap();
    let rust_functions = std::str::from_utf8(rust.get("src/functions.rs").unwrap()).unwrap();
    let rust_manifest = std::str::from_utf8(rust.get("Cargo.toml").unwrap()).unwrap();
    assert!(rust_read.contains(
        "/// Type */ documentation.\n/// \n/// Direct subtype of `actor`:\n/// Sub */ documentation."
    ));
    assert!(
        rust_tokens.contains("  /// Owns */ documentation.\n  pub const display_name: FieldToken<")
    );
    assert!(
        rust_tokens.contains("  /// Relates */ documentation.\n  pub const employee: RoleToken<")
    );
    assert!(rust_tokens.contains(
        "/// Plays */ documentation.\n#[allow(non_upper_case_globals)]\npub const plays_person_employment_employee:"
    ));
    assert!(rust_functions.contains(
        "/// Function */ documentation.\n#[allow(non_upper_case_globals)]\npub const documented:"
    ));
    assert!(rust_manifest.contains("doctest = false"));
}