958 lines
31 KiB
Plaintext
958 lines
31 KiB
Plaintext
#!/usr/bin/env nu
|
|
|
|
# Core distribution preparation tool - prepares core files for distribution
|
|
#
|
|
# Prepares:
|
|
# - Nushell core libraries and modules
|
|
# - Configuration templates and schemas
|
|
# - CLI wrapper scripts and entry points
|
|
# - Plugin definitions and extensions
|
|
# - Template system and utilities
|
|
|
|
use std log
|
|
|
|
def main [
|
|
--source-root: string = "" # Source root directory (auto-detected if empty)
|
|
--output-dir: string = "dist/core" # Output directory for core distribution
|
|
--include-dev: bool = false # Include development files and tools
|
|
--minify-scripts: bool = false # Minify Nushell scripts (remove comments/whitespace)
|
|
--validate-syntax: bool = true # Validate all Nushell scripts
|
|
--generate-index: bool = true # Generate module index files
|
|
--bundle-plugins: bool = true # Bundle plugin definitions
|
|
--create-stubs: bool = false # Create type definition stubs
|
|
--verbose: bool = false # Enable verbose logging
|
|
] -> record {
|
|
|
|
let repo_root = if $source_root == "" {
|
|
($env.PWD | path dirname | path dirname | path dirname)
|
|
} else {
|
|
($source_root | path expand)
|
|
}
|
|
|
|
let core_config = {
|
|
source_root: $repo_root
|
|
output_dir: ($output_dir | path expand)
|
|
include_dev: $include_dev
|
|
minify_scripts: $minify_scripts
|
|
validate_syntax: $validate_syntax
|
|
generate_index: $generate_index
|
|
bundle_plugins: $bundle_plugins
|
|
create_stubs: $create_stubs
|
|
verbose: $verbose
|
|
}
|
|
|
|
log info $"Starting core distribution preparation with config: ($core_config)"
|
|
|
|
# Ensure output directory exists
|
|
mkdir ($core_config.output_dir)
|
|
|
|
let preparation_results = []
|
|
|
|
try {
|
|
# Phase 1: Discover and validate core components
|
|
let discovery_result = discover_core_components $core_config
|
|
|
|
let preparation_results = ($preparation_results | append { phase: "discovery", result: $discovery_result })
|
|
|
|
if $discovery_result.status != "success" {
|
|
log error $"Core component discovery failed: ($discovery_result.reason)"
|
|
exit 1
|
|
}
|
|
|
|
# Phase 2: Prepare core libraries
|
|
let libraries_result = prepare_core_libraries $core_config $discovery_result
|
|
|
|
let preparation_results = ($preparation_results | append { phase: "libraries", result: $libraries_result })
|
|
|
|
# Phase 3: Prepare CLI components
|
|
let cli_result = prepare_cli_components $core_config $discovery_result
|
|
|
|
let preparation_results = ($preparation_results | append { phase: "cli", result: $cli_result })
|
|
|
|
# Phase 4: Prepare configuration system
|
|
let config_result = prepare_configuration_system $core_config $discovery_result
|
|
|
|
let preparation_results = ($preparation_results | append { phase: "configuration", result: $config_result })
|
|
|
|
# Phase 5: Bundle plugins and extensions
|
|
let plugins_result = if $core_config.bundle_plugins {
|
|
prepare_plugin_system $core_config $discovery_result
|
|
} else {
|
|
{ status: "skipped", reason: "plugin bundling disabled" }
|
|
}
|
|
|
|
let preparation_results = ($preparation_results | append { phase: "plugins", result: $plugins_result })
|
|
|
|
# Phase 6: Generate indexes and metadata
|
|
let index_result = if $core_config.generate_index {
|
|
generate_core_indexes $core_config $preparation_results
|
|
} else {
|
|
{ status: "skipped", reason: "index generation disabled" }
|
|
}
|
|
|
|
let preparation_results = ($preparation_results | append { phase: "indexes", result: $index_result })
|
|
|
|
# Phase 7: Create distribution metadata
|
|
let metadata_result = create_core_metadata $core_config $preparation_results
|
|
|
|
let preparation_results = ($preparation_results | append { phase: "metadata", result: $metadata_result })
|
|
|
|
let summary = {
|
|
source_root: $core_config.source_root
|
|
output_directory: $core_config.output_dir
|
|
successful_phases: ($preparation_results | where {|r| $r.result.status == "success"} | length)
|
|
total_phases: ($preparation_results | length)
|
|
core_files_prepared: ($preparation_results | get result.files_processed | math sum)
|
|
total_size: (get_directory_size $core_config.output_dir)
|
|
core_config: $core_config
|
|
phases: $preparation_results
|
|
}
|
|
|
|
log info $"Core distribution preparation completed successfully - ($summary.core_files_prepared) files prepared"
|
|
|
|
return $summary
|
|
|
|
} catch {|err|
|
|
log error $"Core distribution preparation failed: ($err.msg)"
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
# Discover core components in the source tree
|
|
def discover_core_components [core_config: record] -> record {
|
|
log info "Discovering core components..."
|
|
|
|
let start_time = (date now)
|
|
|
|
try {
|
|
# Define core component locations
|
|
let core_locations = {
|
|
provisioning_cli: ($core_config.source_root | path join "provisioning" "core" "nulib" "provisioning")
|
|
core_libraries: ($core_config.source_root | path join "provisioning" "core" "nulib" "lib_provisioning")
|
|
workflows: ($core_config.source_root | path join "provisioning" "core" "nulib" "workflows")
|
|
servers: ($core_config.source_root | path join "provisioning" "core" "nulib" "servers")
|
|
extensions: ($core_config.source_root | path join "provisioning" "extensions")
|
|
config_system: ($core_config.source_root | path join "provisioning" "config.defaults.toml")
|
|
}
|
|
|
|
# Discover Nushell files
|
|
let nu_files = []
|
|
for location_name in ($core_locations | columns) {
|
|
let location_path = ($core_locations | get $location_name)
|
|
if ($location_path | path exists) {
|
|
let found_files = (find $location_path -name "*.nu" -type f)
|
|
let nu_files = ($nu_files | append ($found_files | each {|file|
|
|
{
|
|
path: $file
|
|
component: $location_name
|
|
relative_path: ($file | str replace $core_config.source_root "")
|
|
size: (ls $file | get 0.size)
|
|
}
|
|
}))
|
|
}
|
|
}
|
|
|
|
# Discover configuration files
|
|
let config_files = (find ($core_config.source_root | path join "provisioning") -name "*.toml" -type f)
|
|
|
|
# Discover template files
|
|
let template_files = (find ($core_config.source_root | path join "provisioning") -name "*.j2" -o -name "*.template" -type f)
|
|
|
|
# Validate critical components exist
|
|
let missing_components = []
|
|
let critical_components = ["provisioning_cli", "core_libraries"]
|
|
for component in $critical_components {
|
|
let component_path = ($core_locations | get $component)
|
|
if not ($component_path | path exists) {
|
|
let missing_components = ($missing_components | append $component)
|
|
}
|
|
}
|
|
|
|
if ($missing_components | length) > 0 {
|
|
return {
|
|
status: "failed"
|
|
reason: $"Missing critical components: ($missing_components | str join ', ')"
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
|
|
{
|
|
status: "success"
|
|
core_locations: $core_locations
|
|
nu_files: $nu_files
|
|
config_files: $config_files
|
|
template_files: $template_files
|
|
total_nu_files: ($nu_files | length)
|
|
total_config_files: ($config_files | length)
|
|
total_template_files: ($template_files | length)
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
|
|
} catch {|err|
|
|
{
|
|
status: "failed"
|
|
reason: $err.msg
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
}
|
|
|
|
# Prepare core libraries for distribution
|
|
def prepare_core_libraries [
|
|
core_config: record
|
|
discovery_result: record
|
|
] -> record {
|
|
log info "Preparing core libraries..."
|
|
|
|
let start_time = (date now)
|
|
let lib_output_dir = ($core_config.output_dir | path join "lib")
|
|
mkdir $lib_output_dir
|
|
|
|
try {
|
|
let mut prepared_files = []
|
|
let mut validation_errors = []
|
|
|
|
# Process core library files
|
|
let core_lib_files = ($discovery_result.nu_files | where component == "core_libraries")
|
|
|
|
for file_info in $core_lib_files {
|
|
let processing_result = process_nushell_file $file_info $core_config $lib_output_dir
|
|
|
|
if $processing_result.status == "success" {
|
|
$prepared_files = ($prepared_files | append $processing_result)
|
|
} else {
|
|
$validation_errors = ($validation_errors | append $processing_result.errors)
|
|
}
|
|
}
|
|
|
|
# Process workflow files
|
|
let workflow_files = ($discovery_result.nu_files | where component == "workflows")
|
|
|
|
for file_info in $workflow_files {
|
|
let processing_result = process_nushell_file $file_info $core_config ($lib_output_dir | path join "workflows")
|
|
|
|
if $processing_result.status == "success" {
|
|
$prepared_files = ($prepared_files | append $processing_result)
|
|
} else {
|
|
$validation_errors = ($validation_errors | append $processing_result.errors)
|
|
}
|
|
}
|
|
|
|
# Process server management files
|
|
let server_files = ($discovery_result.nu_files | where component == "servers")
|
|
|
|
for file_info in $server_files {
|
|
let processing_result = process_nushell_file $file_info $core_config ($lib_output_dir | path join "servers")
|
|
|
|
if $processing_result.status == "success" {
|
|
$prepared_files = ($prepared_files | append $processing_result)
|
|
} else {
|
|
$validation_errors = ($validation_errors | append $processing_result.errors)
|
|
}
|
|
}
|
|
|
|
let status = if ($validation_errors | length) > 0 { "partial" } else { "success" }
|
|
|
|
{
|
|
status: $status
|
|
files_processed: ($prepared_files | length)
|
|
validation_errors: ($validation_errors | length)
|
|
prepared_files: $prepared_files
|
|
errors: $validation_errors
|
|
lib_output_dir: $lib_output_dir
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
|
|
} catch {|err|
|
|
{
|
|
status: "failed"
|
|
reason: $err.msg
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
}
|
|
|
|
# Prepare CLI components for distribution
|
|
def prepare_cli_components [
|
|
core_config: record
|
|
discovery_result: record
|
|
] -> record {
|
|
log info "Preparing CLI components..."
|
|
|
|
let start_time = (date now)
|
|
let cli_output_dir = ($core_config.output_dir | path join "bin")
|
|
mkdir $cli_output_dir
|
|
|
|
try {
|
|
# Process main provisioning CLI
|
|
let cli_location = ($discovery_result.core_locations.provisioning_cli)
|
|
|
|
if ($cli_location | path exists) {
|
|
let target_cli = ($cli_output_dir | path join "provisioning")
|
|
|
|
# Copy CLI script
|
|
cp $cli_location $target_cli
|
|
|
|
# Make executable on Unix-like systems
|
|
if $nu.os-info.name != "windows" {
|
|
chmod +x $target_cli
|
|
}
|
|
|
|
# Create wrapper scripts for different environments
|
|
create_cli_wrappers $cli_output_dir $core_config
|
|
|
|
{
|
|
status: "success"
|
|
cli_prepared: $target_cli
|
|
wrappers_created: 3 # Unix, Windows, Development
|
|
files_processed: 4
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
} else {
|
|
{
|
|
status: "failed"
|
|
reason: "provisioning CLI not found"
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
|
|
} catch {|err|
|
|
{
|
|
status: "failed"
|
|
reason: $err.msg
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
}
|
|
|
|
# Create CLI wrapper scripts
|
|
def create_cli_wrappers [cli_output_dir: string, core_config: record] {
|
|
# Unix shell wrapper
|
|
let unix_wrapper = $"#!/bin/bash
|
|
# Provisioning System CLI Wrapper
|
|
# This wrapper sets up the environment and executes the main CLI
|
|
|
|
# Set environment variables
|
|
export PROVISIONING_HOME=\"$(dirname \"$(readlink -f \"$0\")\")/../\"
|
|
export PROVISIONING_LIB=\"$PROVISIONING_HOME/lib\"
|
|
export PROVISIONING_CONFIG=\"$PROVISIONING_HOME/../config\"
|
|
|
|
# Execute the main CLI with proper library path
|
|
exec nu \"$PROVISIONING_HOME/bin/provisioning\" \"$@\"
|
|
"
|
|
|
|
$unix_wrapper | save ($cli_output_dir | path join "provisioning.sh")
|
|
chmod +x ($cli_output_dir | path join "provisioning.sh")
|
|
|
|
# Windows batch wrapper
|
|
let windows_wrapper = $"@echo off
|
|
REM Provisioning System CLI Wrapper
|
|
REM This wrapper sets up the environment and executes the main CLI
|
|
|
|
REM Set environment variables
|
|
set \"PROVISIONING_HOME=%~dp0..\\\"
|
|
set \"PROVISIONING_LIB=%PROVISIONING_HOME%lib\"
|
|
set \"PROVISIONING_CONFIG=%PROVISIONING_HOME%..\\config\"
|
|
|
|
REM Execute the main CLI
|
|
nu \"%PROVISIONING_HOME%bin\\provisioning\" %*
|
|
"
|
|
|
|
$windows_wrapper | save ($cli_output_dir | path join "provisioning.bat")
|
|
|
|
# Development wrapper (preserves source paths)
|
|
let dev_wrapper = $"#!/usr/bin/env nu
|
|
# Provisioning Development CLI Wrapper
|
|
# This wrapper is used during development with source paths
|
|
|
|
# Set development paths
|
|
$env.PROVISIONING_HOME = ($env.PWD | path dirname)
|
|
$env.PROVISIONING_LIB = ($env.PROVISIONING_HOME | path join \"lib\")
|
|
$env.PROVISIONING_CONFIG = ($env.PROVISIONING_HOME | path join \"../config\")
|
|
$env.PROVISIONING_DEV = true
|
|
|
|
# Execute the main CLI
|
|
source ($env.PROVISIONING_HOME | path join \"bin\" \"provisioning\")
|
|
"
|
|
|
|
$dev_wrapper | save ($cli_output_dir | path join "provisioning-dev.nu")
|
|
chmod +x ($cli_output_dir | path join "provisioning-dev.nu")
|
|
}
|
|
|
|
# Prepare configuration system for distribution
|
|
def prepare_configuration_system [
|
|
core_config: record
|
|
discovery_result: record
|
|
] -> record {
|
|
log info "Preparing configuration system..."
|
|
|
|
let start_time = (date now)
|
|
let config_output_dir = ($core_config.output_dir | path join "config")
|
|
mkdir $config_output_dir
|
|
|
|
try {
|
|
let mut processed_configs = []
|
|
|
|
# Process configuration files
|
|
for config_file in $discovery_result.config_files {
|
|
let config_name = ($config_file | path basename)
|
|
let target_config = ($config_output_dir | path join $config_name)
|
|
|
|
# Process configuration file (validate and optionally minify)
|
|
let processing_result = process_config_file $config_file $target_config $core_config
|
|
|
|
if $processing_result.status == "success" {
|
|
$processed_configs = ($processed_configs | append $processing_result)
|
|
}
|
|
}
|
|
|
|
# Create configuration templates
|
|
create_config_templates $config_output_dir $core_config
|
|
|
|
{
|
|
status: "success"
|
|
files_processed: ($processed_configs | length)
|
|
config_files: $processed_configs
|
|
templates_created: 3 # user, dev, prod
|
|
config_output_dir: $config_output_dir
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
|
|
} catch {|err|
|
|
{
|
|
status: "failed"
|
|
reason: $err.msg
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
}
|
|
|
|
# Process a single Nushell file
|
|
def process_nushell_file [
|
|
file_info: record
|
|
core_config: record
|
|
output_dir: string
|
|
] -> record {
|
|
let relative_path = ($file_info.relative_path | str trim-left "/")
|
|
let target_file = ($output_dir | path join ($file_info.path | path basename))
|
|
|
|
# Ensure target directory exists
|
|
mkdir ($target_file | path dirname)
|
|
|
|
try {
|
|
let content = (open $file_info.path --raw)
|
|
|
|
# Validate syntax if requested
|
|
if $core_config.validate_syntax {
|
|
let validation_result = validate_nu_syntax $file_info.path $content
|
|
|
|
if $validation_result.status != "success" {
|
|
return {
|
|
status: "failed"
|
|
file: $file_info.path
|
|
target: $target_file
|
|
errors: $validation_result.errors
|
|
}
|
|
}
|
|
}
|
|
|
|
# Process content based on configuration
|
|
let processed_content = if $core_config.minify_scripts {
|
|
minify_nushell_script $content $core_config
|
|
} else {
|
|
$content
|
|
}
|
|
|
|
# Filter development code if not including dev files
|
|
let final_content = if not $core_config.include_dev {
|
|
filter_development_code $processed_content
|
|
} else {
|
|
$processed_content
|
|
}
|
|
|
|
# Save processed file
|
|
$final_content | save $target_file
|
|
|
|
{
|
|
status: "success"
|
|
source: $file_info.path
|
|
target: $target_file
|
|
size: ($final_content | str length)
|
|
component: $file_info.component
|
|
}
|
|
|
|
} catch {|err|
|
|
{
|
|
status: "failed"
|
|
file: $file_info.path
|
|
target: $target_file
|
|
errors: [$err.msg]
|
|
}
|
|
}
|
|
}
|
|
|
|
# Validate Nushell syntax
|
|
def validate_nu_syntax [file_path: string, content: string] -> record {
|
|
try {
|
|
# Use Nushell's built-in syntax checking
|
|
nu --check $file_path
|
|
|
|
{
|
|
status: "success"
|
|
file: $file_path
|
|
}
|
|
|
|
} catch {|err|
|
|
{
|
|
status: "failed"
|
|
file: $file_path
|
|
errors: [$err.msg]
|
|
}
|
|
}
|
|
}
|
|
|
|
# Minify Nushell script by removing comments and extra whitespace
|
|
def minify_nushell_script [content: string, core_config: record] -> string {
|
|
if not $core_config.minify_scripts {
|
|
return $content
|
|
}
|
|
|
|
# Simple minification - remove comment lines and extra whitespace
|
|
let lines = ($content | lines)
|
|
let minified_lines = $lines | each {|line|
|
|
let trimmed = ($line | str trim)
|
|
# Keep non-comment lines and preserve some important comments
|
|
if ($trimmed | str starts-with "#") {
|
|
if ($trimmed | str contains "!/usr/bin") or ($trimmed | str contains "!/bin/") {
|
|
$line # Keep shebang lines
|
|
} else {
|
|
"" # Remove comment lines
|
|
}
|
|
} else {
|
|
$trimmed # Keep code lines, trimmed
|
|
}
|
|
} | where $it != ""
|
|
|
|
return ($minified_lines | str join "\n")
|
|
}
|
|
|
|
# Filter out development-specific code
|
|
def filter_development_code [content: string] -> string {
|
|
let lines = ($content | lines)
|
|
let mut filtered_lines = []
|
|
let mut in_dev_block = false
|
|
|
|
for line in $lines {
|
|
# Check for development block markers
|
|
if ($line | str contains "# DEV_START") or ($line | str contains "# DEBUG_START") {
|
|
$in_dev_block = true
|
|
continue
|
|
}
|
|
|
|
if ($line | str contains "# DEV_END") or ($line | str contains "# DEBUG_END") {
|
|
$in_dev_block = false
|
|
continue
|
|
}
|
|
|
|
# Skip lines in development blocks
|
|
if $in_dev_block {
|
|
continue
|
|
}
|
|
|
|
# Skip individual development lines
|
|
if ($line | str contains "# DEV_ONLY") or ($line | str contains "# DEBUG") {
|
|
continue
|
|
}
|
|
|
|
$filtered_lines = ($filtered_lines | append $line)
|
|
}
|
|
|
|
return ($filtered_lines | str join "\n")
|
|
}
|
|
|
|
# Process configuration file
|
|
def process_config_file [source_file: string, target_file: string, core_config: record] -> record {
|
|
try {
|
|
# Validate TOML syntax
|
|
let config_data = (open $source_file)
|
|
|
|
# Copy file (could add processing here if needed)
|
|
cp $source_file $target_file
|
|
|
|
{
|
|
status: "success"
|
|
source: $source_file
|
|
target: $target_file
|
|
validated: true
|
|
}
|
|
|
|
} catch {|err|
|
|
{
|
|
status: "failed"
|
|
source: $source_file
|
|
target: $target_file
|
|
error: $err.msg
|
|
}
|
|
}
|
|
}
|
|
|
|
# Create configuration templates
|
|
def create_config_templates [config_output_dir: string, core_config: record] {
|
|
# User configuration template
|
|
let user_template = $"# User Configuration Template
|
|
# Copy this file to config.user.toml and customize as needed
|
|
|
|
# User-specific paths and preferences
|
|
[paths]
|
|
# Override default paths if needed
|
|
# home = \"/custom/path\"
|
|
|
|
[user]
|
|
name = \"Your Name\"
|
|
email = \"your.email@example.com\"
|
|
|
|
# Development settings
|
|
[dev]
|
|
debug = false
|
|
verbose = false
|
|
"
|
|
|
|
$user_template | save ($config_output_dir | path join "config.user.toml.template")
|
|
|
|
# Development configuration template
|
|
let dev_template = $"# Development Configuration Template
|
|
# Copy this file to config.dev.toml for development environment
|
|
|
|
[general]
|
|
environment = \"development\"
|
|
debug = true
|
|
log_level = \"debug\"
|
|
|
|
[paths]
|
|
cache_ttl = 60 # Short cache for development
|
|
"
|
|
|
|
$dev_template | save ($config_output_dir | path join "config.dev.toml.template")
|
|
|
|
# Production configuration template
|
|
let prod_template = $"# Production Configuration Template
|
|
# Copy this file to config.prod.toml for production environment
|
|
|
|
[general]
|
|
environment = \"production\"
|
|
debug = false
|
|
log_level = \"info\"
|
|
|
|
[security]
|
|
# Enable security features for production
|
|
strict_mode = true
|
|
"
|
|
|
|
$prod_template | save ($config_output_dir | path join "config.prod.toml.template")
|
|
}
|
|
|
|
# Prepare plugin system for distribution
|
|
def prepare_plugin_system [
|
|
core_config: record
|
|
discovery_result: record
|
|
] -> record {
|
|
log info "Preparing plugin system..."
|
|
|
|
let start_time = (date now)
|
|
let plugins_output_dir = ($core_config.output_dir | path join "plugins")
|
|
mkdir $plugins_output_dir
|
|
|
|
try {
|
|
# Process extension files
|
|
let extension_files = ($discovery_result.nu_files | where component == "extensions")
|
|
let mut processed_extensions = []
|
|
|
|
for file_info in $extension_files {
|
|
let processing_result = process_nushell_file $file_info $core_config $plugins_output_dir
|
|
|
|
if $processing_result.status == "success" {
|
|
$processed_extensions = ($processed_extensions | append $processing_result)
|
|
}
|
|
}
|
|
|
|
# Create plugin registry
|
|
let plugin_registry = create_plugin_registry $processed_extensions $core_config
|
|
|
|
{
|
|
status: "success"
|
|
files_processed: ($processed_extensions | length)
|
|
extensions: $processed_extensions
|
|
plugin_registry: $plugin_registry
|
|
plugins_output_dir: $plugins_output_dir
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
|
|
} catch {|err|
|
|
{
|
|
status: "failed"
|
|
reason: $err.msg
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
}
|
|
|
|
# Create plugin registry
|
|
def create_plugin_registry [processed_extensions: list, core_config: record] -> record {
|
|
let plugin_registry = {
|
|
version: "1.0.0"
|
|
plugins: ($processed_extensions | each {|ext|
|
|
{
|
|
name: ($ext.target | path basename | str replace ".nu" "")
|
|
path: ($ext.target | path basename)
|
|
component: $ext.component
|
|
size: $ext.size
|
|
}
|
|
})
|
|
created_at: (date now)
|
|
}
|
|
|
|
let registry_file = ($core_config.output_dir | path join "plugins" "registry.json")
|
|
$plugin_registry | to json | save $registry_file
|
|
|
|
return $plugin_registry
|
|
}
|
|
|
|
# Generate core indexes and module listings
|
|
def generate_core_indexes [
|
|
core_config: record
|
|
preparation_results: list
|
|
] -> record {
|
|
log info "Generating core indexes..."
|
|
|
|
let start_time = (date now)
|
|
|
|
try {
|
|
# Generate library index
|
|
let lib_result = ($preparation_results | where {|r| $r.phase == "libraries"} | get 0.result)
|
|
let lib_index = generate_library_index $lib_result.prepared_files $core_config
|
|
|
|
# Generate CLI index
|
|
let cli_result = ($preparation_results | where {|r| $r.phase == "cli"} | get 0.result)
|
|
let cli_index = generate_cli_index $cli_result $core_config
|
|
|
|
# Generate main index
|
|
let main_index = generate_main_index $preparation_results $core_config
|
|
|
|
{
|
|
status: "success"
|
|
indexes_generated: ["library", "cli", "main"]
|
|
library_index: $lib_index
|
|
cli_index: $cli_index
|
|
main_index: $main_index
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
|
|
} catch {|err|
|
|
{
|
|
status: "failed"
|
|
reason: $err.msg
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
}
|
|
|
|
# Generate library index
|
|
def generate_library_index [prepared_files: list, core_config: record] -> string {
|
|
let index_content = $"# Core Library Index
|
|
|
|
This file provides an index of all core library modules included in this distribution.
|
|
|
|
## Library Modules
|
|
|
|
"
|
|
|
|
let modules = ($prepared_files | group-by component)
|
|
|
|
let mut full_content = [$index_content]
|
|
|
|
for component in ($modules | columns) {
|
|
let component_files = ($modules | get $component)
|
|
$full_content = ($full_content | append $"### ($component | str title-case)")
|
|
$full_content = ($full_content | append "")
|
|
|
|
for file in $component_files {
|
|
let module_name = ($file.target | path basename | str replace ".nu" "")
|
|
$full_content = ($full_content | append $"- **($module_name)**: ($file.target)")
|
|
}
|
|
|
|
$full_content = ($full_content | append "")
|
|
}
|
|
|
|
let content = ($full_content | str join "\n")
|
|
$content | save ($core_config.output_dir | path join "lib" "INDEX.md")
|
|
|
|
return $content
|
|
}
|
|
|
|
# Generate CLI index
|
|
def generate_cli_index [cli_result: record, core_config: record] -> string {
|
|
let cli_index = $"# CLI Components Index
|
|
|
|
## Main CLI
|
|
- **provisioning**: Main provisioning CLI entry point
|
|
|
|
## Wrapper Scripts
|
|
- **provisioning.sh**: Unix/Linux shell wrapper
|
|
- **provisioning.bat**: Windows batch wrapper
|
|
- **provisioning-dev.nu**: Development wrapper
|
|
|
|
## Usage
|
|
The main CLI provides access to all provisioning functionality:
|
|
```
|
|
./bin/provisioning help
|
|
```
|
|
|
|
Generated: (date now | format date '%Y-%m-%d %H:%M:%S')
|
|
"
|
|
|
|
$cli_index | save ($core_config.output_dir | path join "bin" "INDEX.md")
|
|
return $cli_index
|
|
}
|
|
|
|
# Generate main index
|
|
def generate_main_index [preparation_results: list, core_config: record] -> string {
|
|
let successful_phases = ($preparation_results | where {|r| $r.result.status == "success"})
|
|
let total_files = ($successful_phases | get result.files_processed | math sum)
|
|
|
|
let main_index = $"# Core Distribution Index
|
|
|
|
This distribution contains the core components of the Provisioning System.
|
|
|
|
## Directory Structure
|
|
- **bin/**: CLI executables and wrapper scripts
|
|
- **lib/**: Core Nushell libraries and modules
|
|
- **config/**: Configuration files and templates
|
|
- **plugins/**: Extensions and plugin definitions
|
|
|
|
## Statistics
|
|
- **Total files processed**: ($total_files)
|
|
- **Successful phases**: ($successful_phases | length)
|
|
- **Generated**: (date now | format date '%Y-%m-%d %H:%M:%S')
|
|
|
|
## Usage
|
|
To use this core distribution:
|
|
1. Add bin/ to your PATH
|
|
2. Set PROVISIONING_LIB to point to lib/
|
|
3. Configure PROVISIONING_CONFIG to point to config/
|
|
4. Run `provisioning help` to get started
|
|
|
|
For more information, see the documentation in each subdirectory.
|
|
"
|
|
|
|
$main_index | save ($core_config.output_dir | path join "INDEX.md")
|
|
return $main_index
|
|
}
|
|
|
|
# Create core metadata
|
|
def create_core_metadata [
|
|
core_config: record
|
|
preparation_results: list
|
|
] -> record {
|
|
log info "Creating core metadata..."
|
|
|
|
let start_time = (date now)
|
|
|
|
try {
|
|
let metadata = {
|
|
name: "provisioning-core"
|
|
version: (detect_version $core_config.source_root)
|
|
type: "core-distribution"
|
|
created_at: (date now)
|
|
created_by: "core-distribution-tool"
|
|
source_root: $core_config.source_root
|
|
configuration: $core_config
|
|
preparation_phases: ($preparation_results | each {|r|
|
|
{
|
|
phase: $r.phase
|
|
status: $r.result.status
|
|
files_processed: (if "files_processed" in ($r.result | columns) { $r.result.files_processed } else { 0 })
|
|
duration: (if "duration" in ($r.result | columns) { $r.result.duration } else { 0 })
|
|
}
|
|
})
|
|
statistics: {
|
|
total_phases: ($preparation_results | length)
|
|
successful_phases: ($preparation_results | where {|r| $r.result.status == "success"} | length)
|
|
total_files: ($preparation_results | get result.files_processed | math sum)
|
|
distribution_size: (get_directory_size $core_config.output_dir)
|
|
}
|
|
}
|
|
|
|
let metadata_file = ($core_config.output_dir | path join "core-metadata.json")
|
|
$metadata | to json | save $metadata_file
|
|
|
|
{
|
|
status: "success"
|
|
metadata_file: $metadata_file
|
|
metadata: $metadata
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
|
|
} catch {|err|
|
|
{
|
|
status: "failed"
|
|
reason: $err.msg
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
}
|
|
|
|
# Detect version from git or other sources
|
|
def detect_version [repo_root: string] -> string {
|
|
cd $repo_root
|
|
|
|
try {
|
|
let git_version = (git describe --tags --always --dirty 2>/dev/null | str trim)
|
|
if $git_version != "" {
|
|
return ($git_version | str replace "^v" "")
|
|
}
|
|
|
|
return $"dev-(date now | format date '%Y%m%d')"
|
|
} catch {
|
|
return "unknown"
|
|
}
|
|
}
|
|
|
|
# Get directory size helper
|
|
def get_directory_size [dir: string] -> int {
|
|
if not ($dir | path exists) {
|
|
return 0
|
|
}
|
|
|
|
try {
|
|
find $dir -type f | each {|file| ls $file | get 0.size } | math sum | if $in == null { 0 } else { $in }
|
|
} catch {
|
|
0
|
|
}
|
|
}
|
|
|
|
# Show core distribution status
|
|
def "main status" [] {
|
|
let repo_root = ($env.PWD | path dirname | path dirname | path dirname)
|
|
let version = (detect_version $repo_root)
|
|
|
|
# Check for core components
|
|
let provisioning_cli = ($repo_root | path join "provisioning" "core" "nulib" "provisioning")
|
|
let core_libraries = ($repo_root | path join "provisioning" "core" "nulib" "lib_provisioning")
|
|
|
|
{
|
|
repository: $repo_root
|
|
version: $version
|
|
core_components: {
|
|
provisioning_cli: ($provisioning_cli | path exists)
|
|
core_libraries: ($core_libraries | path exists)
|
|
}
|
|
nu_files_found: (try { find $repo_root -name "*.nu" -type f | length } catch { 0 })
|
|
config_files_found: (try { find ($repo_root | path join "provisioning") -name "*.toml" -type f | length } catch { 0 })
|
|
ready_for_distribution: (($provisioning_cli | path exists) and ($core_libraries | path exists))
|
|
}
|
|
}
|
|
|
|
# Quick core preparation with minimal options
|
|
def "main quick" [output_dir: string = "dist/core"] {
|
|
main --output-dir $output_dir --validate-syntax --generate-index
|
|
} |