pctx_type_check_runtime 0.1.2

Isolated TypeScript type checking runtime for PCTX
//! Build script for `pctx_type_check`
//!
//! This script generates a V8 snapshot that includes the TypeScript compiler
//! for full type checking capabilities.

#![allow(long_running_const_eval)]

use std::env;
use std::path::PathBuf;

use deno_core::extension;
use deno_core::snapshot::CreateSnapshotOptions;
use deno_core::snapshot::create_snapshot;

// Include the ignored codes module (we need access to it at build time)
mod ignored_codes {
    include!("src/ignored_codes.rs");
}

// Generate the TypeScript checking runtime JS as a const string
// This includes the ignored diagnostic codes embedded from Rust
const TYPE_CHECK_RUNTIME_JS: &str = include_str!("src/type_check_runtime.js");

fn generate_runtime_js_string() -> String {
    // Generate the codes array
    let codes: Vec<String> = ignored_codes::IGNORED_DIAGNOSTIC_CODES
        .iter()
        .map(std::string::ToString::to_string)
        .collect();
    let codes_js = format!(
        "// AUTO-GENERATED CODE - DO NOT EDIT\n\
         // This code was generated from ignored_codes.rs at build time\n\n\
         const IGNORED_DIAGNOSTIC_CODES = [{}];",
        codes.join(", ")
    );

    // Replace the placeholder
    TYPE_CHECK_RUNTIME_JS.replace("// CODEGEN_IGNORED_CODES_PLACEHOLDER", &codes_js)
}

// Define the extension for snapshot creation
extension!(
    pctx_type_check_snapshot,
    esm_entry_point = "ext:pctx_type_check_snapshot/type_check_runtime_generated.js",
    esm = [
        dir "src",
        "typescript.min.js",
        "type_check_runtime_generated.js"
    ],
);

fn main() {
    // Tell cargo to rerun this build script ONLY if these specific files change
    // IMPORTANT: We do NOT include type_check_runtime_generated.js because it's
    // generated by this build script, which would create a circular dependency
    println!("cargo:rerun-if-changed=src/typescript.min.js");
    println!("cargo:rerun-if-changed=src/type_check_runtime.js");
    println!("cargo:rerun-if-changed=src/ignored_codes.rs");
    println!("cargo:rerun-if-changed=build.rs");

    // Get the output directory
    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
    let snapshot_path = out_dir.join("PCTX_TYPE_CHECK_SNAPSHOT.bin");

    // Generate the runtime JS with embedded codes
    let generated_runtime_js = generate_runtime_js_string();

    // Write to src/ ONLY if the content has changed
    // This prevents unnecessary rebuilds when the generated content is the same
    let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
    let src_runtime_path = manifest_dir.join("src/type_check_runtime_generated.js");

    let should_write = if src_runtime_path.exists() {
        let existing_content = std::fs::read_to_string(&src_runtime_path)
            .expect("Failed to read existing runtime file");
        existing_content != generated_runtime_js
    } else {
        true
    };

    if should_write {
        std::fs::write(&src_runtime_path, &generated_runtime_js)
            .expect("Failed to write generated runtime to src");
        println!("cargo:warning=Updated type_check_runtime_generated.js (content changed)");
    }

    // Also write to OUT_DIR for reference
    let out_runtime_path = out_dir.join("type_check_runtime_generated.js");
    std::fs::write(&out_runtime_path, &generated_runtime_js)
        .expect("Failed to write generated runtime JS to OUT_DIR");

    // Create the snapshot
    let snapshot = create_snapshot(
        CreateSnapshotOptions {
            cargo_manifest_dir: env!("CARGO_MANIFEST_DIR"),
            startup_snapshot: None,
            skip_op_registration: false,
            extensions: vec![pctx_type_check_snapshot::init()],
            extension_transpiler: None,
            with_runtime_cb: None,
        },
        None, // No warmup script
    )
    .expect("Failed to create snapshot");

    // Write the snapshot to disk
    std::fs::write(&snapshot_path, snapshot.output).expect("Failed to write snapshot");

    println!(
        "cargo:rustc-env=PCTX_TYPE_CHECK_SNAPSHOT={}",
        snapshot_path.display()
    );
    println!(
        "Type check snapshot created at: {}",
        snapshot_path.display()
    );
}