@neuroequality/neuroadapt-cli
Version:
CLI tool for creating accessible quantum and VR applications
1,348 lines (1,259 loc) ⢠64.1 kB
JavaScript
#!/usr/bin/env node
import { Command } from "commander";
import chalk from "chalk";
import { c as createApp } from "./create-app-Bhc4KAlH.js";
import inquirer from "inquirer";
import ora from "ora";
import fs from "fs-extra";
import * as path from "path";
import path__default from "path";
async function createQuantumApp(name, options = { template: "basic" }) {
console.log(chalk.blue("āļø Creating NeuroAdapt Quantum Application\n"));
let appName = name;
if (!appName) {
const { selectedName } = await inquirer.prompt([
{
type: "input",
name: "selectedName",
message: "Application name:",
validate: (input) => {
if (!input) return "Please provide an application name";
if (!/^[a-z0-9-_]+$/i.test(input)) return "Name can only contain letters, numbers, hyphens, and underscores";
return true;
}
}
]);
appName = selectedName;
}
const spinner = ora("Creating quantum application...").start();
try {
const projectRoot = path.join(process.cwd(), appName);
if (await fs.pathExists(projectRoot)) {
spinner.fail(`Directory '${appName}' already exists`);
return;
}
spinner.text = "Setting up project structure...";
await fs.ensureDir(projectRoot);
spinner.stop();
const answers = await inquirer.prompt([
{
type: "list",
name: "template",
message: "Choose a quantum template:",
choices: [
{ name: "Basic Quantum Circuits", value: "basic" },
{ name: "Bloch Sphere Visualization", value: "bloch" },
{ name: "Quantum Algorithm Demo", value: "algorithm" },
{ name: "Educational Quantum Simulator", value: "educational" }
],
when: !options.template
},
{
type: "confirm",
name: "typescript",
message: "Use TypeScript?",
default: true,
when: options.typescript === void 0
},
{
type: "checkbox",
name: "accessibility",
message: "Select accessibility features:",
choices: [
{ name: "Screen Reader Support", value: "screenreader", checked: true },
{ name: "Keyboard Navigation", value: "keyboard", checked: true },
{ name: "High Contrast Mode", value: "contrast", checked: true },
{ name: "Motion Reduction", value: "motion", checked: true },
{ name: "Audio Descriptions", value: "audio", checked: false }
]
}
]);
const template = options.template || answers.template;
const useTypeScript = options.typescript ?? answers.typescript;
const accessibilityFeatures = answers.accessibility;
const creationSpinner = ora("Generating quantum application...").start();
const packageJson = {
name: appName,
version: "1.0.0",
description: `Accessible quantum computing application - ${template} template`,
main: useTypeScript ? "dist/index.js" : "src/index.js",
scripts: {
dev: useTypeScript ? "tsc && node dist/index.js" : "node src/index.js",
build: useTypeScript ? "tsc" : 'echo "No build step needed"',
start: useTypeScript ? "node dist/index.js" : "node src/index.js",
test: "npm run test:unit && npm run test:accessibility",
"test:unit": "jest",
"test:accessibility": "playwright test tests/accessibility"
},
dependencies: {
"@neuroadapt/core": "^1.1.0",
"@neuroadapt/quantum": "^1.1.0",
"@neuroadapt/testing": "^1.1.0"
},
devDependencies: useTypeScript ? {
"typescript": "^5.0.0",
"@types/node": "^20.0.0",
"jest": "^29.0.0",
"@playwright/test": "^1.40.0"
} : {
"jest": "^29.0.0",
"@playwright/test": "^1.40.0"
}
};
await fs.writeJson(path.join(projectRoot, "package.json"), packageJson, { spaces: 2 });
if (useTypeScript) {
const tsConfig = {
compilerOptions: {
target: "ES2020",
module: "commonjs",
outDir: "./dist",
rootDir: "./src",
strict: true,
esModuleInterop: true,
skipLibCheck: true,
forceConsistentCasingInFileNames: true,
declaration: true,
declarationMap: true,
sourceMap: true
},
include: ["src/**/*"],
exclude: ["node_modules", "dist", "tests"]
};
await fs.writeJson(path.join(projectRoot, "tsconfig.json"), tsConfig, { spaces: 2 });
}
const srcDir = path.join(projectRoot, "src");
await fs.ensureDir(srcDir);
const mainContent = generateMainApp(template, accessibilityFeatures, useTypeScript);
await fs.writeFile(
path.join(srcDir, `index.${useTypeScript ? "ts" : "js"}`),
mainContent
);
switch (template) {
case "bloch":
const blochContent = generateBlochSphereInit(useTypeScript);
await fs.writeFile(
path.join(srcDir, `bloch-sphere.${useTypeScript ? "ts" : "js"}`),
blochContent
);
break;
case "algorithm":
const algorithmContent = generateQuantumAlgorithm(useTypeScript);
await fs.writeFile(
path.join(srcDir, `quantum-algorithm.${useTypeScript ? "ts" : "js"}`),
algorithmContent
);
break;
case "educational":
const educationalContent = generateEducationalSimulator(useTypeScript);
await fs.writeFile(
path.join(srcDir, `quantum-simulator.${useTypeScript ? "ts" : "js"}`),
educationalContent
);
break;
default:
const circuitContent = generateCircuitBuilderInit(useTypeScript);
await fs.writeFile(
path.join(srcDir, `quantum-circuit.${useTypeScript ? "ts" : "js"}`),
circuitContent
);
}
const accessibilityConfig = {
quantum: {
visualizations: {
colorBlindFriendly: accessibilityFeatures.includes("contrast"),
highContrast: accessibilityFeatures.includes("contrast"),
reduceMotion: accessibilityFeatures.includes("motion"),
audioDescriptions: accessibilityFeatures.includes("audio")
},
interactions: {
keyboardNavigation: accessibilityFeatures.includes("keyboard"),
screenReaderSupport: accessibilityFeatures.includes("screenreader"),
alternativeInputs: true
}
}
};
await fs.writeJson(
path.join(projectRoot, "accessibility.config.json"),
accessibilityConfig,
{ spaces: 2 }
);
const readmeContent = generateReadme(appName, template, useTypeScript, accessibilityFeatures);
await fs.writeFile(path.join(projectRoot, "README.md"), readmeContent);
creationSpinner.succeed("Quantum application created successfully!");
console.log(chalk.green("\nā
Success! Your accessible quantum app is ready:"));
console.log(chalk.gray(`š Directory: ${appName}`));
console.log(chalk.gray(`āļø Template: ${template}`));
console.log(chalk.gray(`š Language: ${useTypeScript ? "TypeScript" : "JavaScript"}`));
console.log(chalk.gray(`āæ Accessibility: ${accessibilityFeatures.join(", ")}`));
console.log(chalk.blue("\nš” Next steps:"));
console.log(chalk.gray(`1. cd ${appName}`));
console.log(chalk.gray("2. npm install"));
console.log(chalk.gray("3. npm run dev"));
} catch (error) {
spinner.fail("Failed to create quantum application");
console.error(chalk.red(error instanceof Error ? error.message : "Unknown error"));
process.exit(1);
}
}
function generateBlochSphereInit(isTS) {
const typeAnnotation = isTS ? ": void" : "";
return `/**
* Bloch Sphere Visualization - Accessible quantum state visualization
*/
import { BlochSphere } from '@neuroadapt/quantum';
import { PreferenceStore } from '@neuroadapt/core';
const preferences = new PreferenceStore({ key: 'quantum-prefs' });
export async function initializeBlochSphere()${typeAnnotation} {
const userPrefs = await preferences.load();
const sphere = new BlochSphere({
container: '#bloch-container',
accessibility: {
colorBlindFriendly: userPrefs?.sensory?.colorVisionFilter !== 'none',
highContrast: userPrefs?.sensory?.highContrast || false,
screenReaderDescriptions: true,
keyboardControls: userPrefs?.motor?.keyboardNavigation || false
}
});
// Add quantum state
sphere.setState([0.6, 0.8]); // |0ā© + |1ā© superposition
// Enable accessibility features
sphere.enableKeyboardNavigation();
sphere.addScreenReaderDescriptions();
return sphere;
}
`;
}
function generateCircuitBuilderInit(isTS) {
const typeAnnotation = isTS ? ": void" : "";
return `/**
* Quantum Circuit Builder - Accessible quantum circuit construction
*/
import { QuantumCircuit } from '@neuroadapt/quantum';
import { PreferenceStore } from '@neuroadapt/core';
const preferences = new PreferenceStore({ key: 'quantum-prefs' });
export async function initializeCircuitBuilder()${typeAnnotation} {
const userPrefs = await preferences.load();
const circuit = new QuantumCircuit(3); // 3-qubit circuit
// Configure accessibility
circuit.setAccessibilityOptions({
keyboardNavigation: userPrefs?.motor?.keyboardNavigation || false,
screenReaderSupport: true,
highContrast: userPrefs?.sensory?.highContrast || false,
reduceAnimations: userPrefs?.sensory?.motionReduction || false
});
// Add some basic gates
circuit.addGate('H', 0); // Hadamard gate on qubit 0
circuit.addGate('CNOT', [0, 1]); // CNOT gate between qubits 0 and 1
circuit.addGate('H', 2); // Hadamard gate on qubit 2
// Render circuit with accessibility features
circuit.render('#circuit-container');
return circuit;
}
`;
}
function generateMainApp(template, features, isTS) {
return `/**
* ${template.charAt(0).toUpperCase() + template.slice(1)} Quantum Application
* Accessible quantum computing with NeuroAdapt SDK
*/
import { PreferenceStore } from '@neuroadapt/core';
${template === "bloch" ? "import { initializeBlochSphere } from './bloch-sphere';" : ""}
${template === "basic" ? "import { initializeCircuitBuilder } from './quantum-circuit';" : ""}
const preferences = new PreferenceStore({ key: 'quantum-app-prefs' });
async function main()${isTS ? ": Promise<void>" : ""} {
console.log('š Starting Accessible Quantum Application');
try {
// Load user preferences
const userPrefs = await preferences.load();
console.log('š User preferences loaded');
// Apply accessibility settings
applyAccessibilitySettings(userPrefs);
// Initialize quantum components
${template === "bloch" ? "await initializeBlochSphere();" : ""}
${template === "basic" ? "await initializeCircuitBuilder();" : ""}
console.log('ā
Quantum application ready!');
} catch (error) {
console.error('ā Failed to initialize application:', error);
}
}
function applyAccessibilitySettings(prefs${isTS ? ": any" : ""}) {
if (prefs?.sensory?.highContrast) {
document.body.classList.add('high-contrast');
}
if (prefs?.sensory?.motionReduction) {
document.body.classList.add('reduce-motion');
}
if (prefs?.motor?.keyboardNavigation) {
document.body.classList.add('keyboard-navigation');
}
}
// Start the application
main().catch(console.error);
`;
}
function generateQuantumAlgorithm(isTS) {
return `/**
* Quantum Algorithm Implementation - Accessible quantum algorithms
*/
import { QuantumCircuit } from '@neuroadapt/quantum';
export class AccessibleQuantumAlgorithm {
private circuit${isTS ? ": QuantumCircuit" : ""};
constructor(qubits${isTS ? ": number" : ""}) {
this.circuit = new QuantumCircuit(qubits);
}
// Implement Deutsch-Jozsa algorithm with accessibility
deutschJozsa()${isTS ? ": void" : ""} {
console.log('š¬ Running Deutsch-Jozsa Algorithm');
// Step 1: Initialize qubits
this.circuit.addGate('H', 0); // Hadamard on first qubit
this.circuit.addGate('X', 1); // X gate on second qubit
this.circuit.addGate('H', 1); // Hadamard on second qubit
// Step 2: Apply oracle (placeholder)
this.circuit.addGate('CNOT', [0, 1]);
// Step 3: Final Hadamard
this.circuit.addGate('H', 0);
// Measure and describe result
const result = this.circuit.measure();
this.announceResult(result);
}
private announceResult(result${isTS ? ": any" : ""})${isTS ? ": void" : ""} {
const description = result === 0 ?
'Function is constant - all inputs produce the same output' :
'Function is balanced - inputs produce different outputs';
console.log(\`š Result: \${description}\`);
// Add screen reader announcement
if (typeof window !== 'undefined') {
const announcement = document.createElement('div');
announcement.setAttribute('aria-live', 'polite');
announcement.textContent = description;
document.body.appendChild(announcement);
}
}
}
`;
}
function generateEducationalSimulator(isTS) {
return `/**
* Educational Quantum Simulator - Learning-focused quantum computing
*/
import { QuantumCircuit } from '@neuroadapt/quantum';
export class EducationalQuantumSimulator {
private circuit${isTS ? ": QuantumCircuit" : ""};
private stepCount${isTS ? ": number" : ""} = 0;
constructor() {
this.circuit = new QuantumCircuit(2);
}
// Interactive quantum gate exploration
exploreGates()${isTS ? ": void" : ""} {
console.log('š Welcome to Quantum Gate Explorer');
console.log('Press keys to add gates: H (Hadamard), X (Pauli-X), C (CNOT)');
if (typeof window !== 'undefined') {
document.addEventListener('keydown', this.handleKeyPress.bind(this));
}
}
private handleKeyPress(event${isTS ? ": KeyboardEvent" : ""})${isTS ? ": void" : ""} {
switch (event.key.toLowerCase()) {
case 'h':
this.addHadamardGate();
break;
case 'x':
this.addPauliXGate();
break;
case 'c':
this.addCNOTGate();
break;
case 'r':
this.resetCircuit();
break;
}
}
private addHadamardGate()${isTS ? ": void" : ""} {
this.circuit.addGate('H', 0);
this.announceStep('Added Hadamard gate - creates superposition');
}
private addPauliXGate()${isTS ? ": void" : ""} {
this.circuit.addGate('X', 0);
this.announceStep('Added Pauli-X gate - flips qubit state');
}
private addCNOTGate()${isTS ? ": void" : ""} {
this.circuit.addGate('CNOT', [0, 1]);
this.announceStep('Added CNOT gate - creates entanglement');
}
private resetCircuit()${isTS ? ": void" : ""} {
this.circuit = new QuantumCircuit(2);
this.stepCount = 0;
this.announceStep('Circuit reset');
}
private announceStep(description${isTS ? ": string" : ""})${isTS ? ": void" : ""} {
this.stepCount++;
console.log(\`Step \${this.stepCount}: \${description}\`);
// Screen reader announcement
if (typeof window !== 'undefined') {
const announcement = document.createElement('div');
announcement.setAttribute('aria-live', 'polite');
announcement.textContent = \`Step \${this.stepCount}: \${description}\`;
document.body.appendChild(announcement);
// Clean up old announcements
setTimeout(() => announcement.remove(), 3000);
}
}
}
`;
}
function generateReadme(appName, template, isTS, features) {
return `# ${appName}
An accessible quantum computing application built with NeuroAdapt SDK.
## Features
- **Template**: ${template}
- **Language**: ${isTS ? "TypeScript" : "JavaScript"}
- **Accessibility**: ${features.join(", ")}
- **Quantum Computing**: Circuit simulation, visualization, and algorithms
## Quick Start
\`\`\`bash
npm install
npm run dev
\`\`\`
## Accessibility Features
This application includes comprehensive accessibility support:
${features.includes("screenreader") ? "- **Screen Reader Support**: All quantum states and operations are announced\n" : ""}
${features.includes("keyboard") ? "- **Keyboard Navigation**: Full keyboard control of quantum circuits\n" : ""}
${features.includes("contrast") ? "- **High Contrast Mode**: Enhanced visibility for quantum visualizations\n" : ""}
${features.includes("motion") ? "- **Motion Reduction**: Reduced animations for motion sensitivity\n" : ""}
${features.includes("audio") ? "- **Audio Descriptions**: Spoken descriptions of quantum operations\n" : ""}
## Usage
### Basic Quantum Circuit
\`\`\`${isTS ? "typescript" : "javascript"}
import { QuantumCircuit } from '@neuroadapt/quantum';
const circuit = new QuantumCircuit(2);
circuit.addGate('H', 0); // Hadamard gate
circuit.addGate('CNOT', [0, 1]); // CNOT gate
circuit.render('#circuit-container');
\`\`\`
### Accessibility Configuration
\`\`\`${isTS ? "typescript" : "javascript"}
circuit.setAccessibilityOptions({
keyboardNavigation: true,
screenReaderSupport: true,
highContrast: false,
reduceAnimations: false
});
\`\`\`
## Keyboard Shortcuts
- **H**: Add Hadamard gate
- **X**: Add Pauli-X gate
- **C**: Add CNOT gate
- **R**: Reset circuit
- **Tab**: Navigate between elements
- **Enter/Space**: Activate controls
## Learn More
- [NeuroAdapt SDK Documentation](https://neuroadapt.dev)
- [Quantum Computing Basics](https://neuroadapt.dev/quantum)
- [Accessibility Guidelines](https://neuroadapt.dev/accessibility)
## Support
For accessibility support or quantum computing questions, visit our [documentation](https://neuroadapt.dev) or open an issue.
`;
}
async function createVRApp(name, options = { template: "basic" }) {
console.log(chalk.blue("š„½ Creating NeuroAdapt VR Application\n"));
let appName = name;
if (!appName) {
const { selectedName } = await inquirer.prompt([
{
type: "input",
name: "selectedName",
message: "VR Application name:",
validate: (input) => {
if (!input) return "Please provide an application name";
if (!/^[a-z0-9-_]+$/i.test(input)) return "Name can only contain letters, numbers, hyphens, and underscores";
return true;
}
}
]);
appName = selectedName;
}
const spinner = ora("Creating VR application...").start();
try {
const projectRoot = path.join(process.cwd(), appName);
if (await fs.pathExists(projectRoot)) {
spinner.fail(`Directory '${appName}' already exists`);
return;
}
spinner.text = "Setting up VR project structure...";
await fs.ensureDir(projectRoot);
spinner.stop();
const answers = await inquirer.prompt([
{
type: "list",
name: "template",
message: "Choose a VR template:",
choices: [
{ name: "Basic VR Experience", value: "basic" },
{ name: "Safe Zone Demo", value: "safezone" },
{ name: "Proximity Detection", value: "proximity" },
{ name: "Educational VR Environment", value: "educational" },
{ name: "Therapy/Meditation VR", value: "therapy" }
],
when: !options.template
},
{
type: "list",
name: "platform",
message: "Target VR platform:",
choices: [
{ name: "WebXR (Browser)", value: "webxr" },
{ name: "Unity", value: "unity" },
{ name: "Unreal Engine", value: "unreal" },
{ name: "A-Frame", value: "aframe" }
],
when: !options.platform
},
{
type: "confirm",
name: "typescript",
message: "Use TypeScript?",
default: true,
when: options.typescript === void 0
},
{
type: "checkbox",
name: "safetyFeatures",
message: "Select safety and accessibility features:",
choices: [
{ name: "Safe Zone Management", value: "safezone", checked: true },
{ name: "Proximity Detection", value: "proximity", checked: true },
{ name: "Motion Sickness Prevention", value: "motion", checked: true },
{ name: "Emergency Panic Mode", value: "panic", checked: true },
{ name: "Audio Spatial Warnings", value: "audio", checked: true },
{ name: "Haptic Feedback Alerts", value: "haptic", checked: false }
]
}
]);
const template = options.template || answers.template;
const platform = options.platform || answers.platform;
const useTypeScript = options.typescript ?? answers.typescript;
const safetyFeatures = answers.safetyFeatures;
const creationSpinner = ora("Generating VR application...").start();
const packageJson = {
name: appName,
version: "1.0.0",
description: `Accessible VR application - ${template} template for ${platform}`,
main: useTypeScript ? "dist/index.js" : "src/index.js",
scripts: {
dev: platform === "webxr" ? "vite dev" : useTypeScript ? "tsc && node dist/index.js" : "node src/index.js",
build: platform === "webxr" ? "vite build" : useTypeScript ? "tsc" : 'echo "No build step needed"',
start: useTypeScript ? "node dist/index.js" : "node src/index.js",
preview: platform === "webxr" ? "vite preview" : "npm start",
test: "npm run test:unit && npm run test:accessibility",
"test:unit": "jest",
"test:accessibility": "playwright test tests/accessibility"
},
dependencies: {
"@neuroadapt/core": "^1.1.0",
"@neuroadapt/vr": "^1.1.0",
"@neuroadapt/testing": "^1.1.0"
},
devDependencies: {}
};
if (platform === "webxr") {
packageJson.dependencies["three"] = "^0.160.0";
packageJson.dependencies["aframe"] = "^1.4.0";
packageJson.devDependencies["vite"] = "^5.0.0";
}
if (useTypeScript) {
packageJson.devDependencies["typescript"] = "^5.0.0";
packageJson.devDependencies["@types/node"] = "^20.0.0";
if (platform === "webxr") {
packageJson.devDependencies["@types/three"] = "^0.160.0";
packageJson.devDependencies["@types/aframe"] = "^1.2.0";
}
}
packageJson.devDependencies["jest"] = "^29.0.0";
packageJson.devDependencies["@playwright/test"] = "^1.40.0";
await fs.writeJson(path.join(projectRoot, "package.json"), packageJson, { spaces: 2 });
if (useTypeScript) {
const tsConfig = {
compilerOptions: {
target: "ES2020",
module: platform === "webxr" ? "ESNext" : "commonjs",
moduleResolution: "bundler",
outDir: "./dist",
rootDir: "./src",
strict: true,
esModuleInterop: true,
skipLibCheck: true,
forceConsistentCasingInFileNames: true,
declaration: true,
declarationMap: true,
sourceMap: true,
types: platform === "webxr" ? ["vite/client"] : ["node"]
},
include: ["src/**/*"],
exclude: ["node_modules", "dist", "tests"]
};
await fs.writeJson(path.join(projectRoot, "tsconfig.json"), tsConfig, { spaces: 2 });
}
if (platform === "webxr") {
const viteConfig = `import { defineConfig } from 'vite';
export default defineConfig({
server: {
https: true, // Required for WebXR
port: 3000
},
build: {
target: 'esnext'
}
});`;
await fs.writeFile(path.join(projectRoot, "vite.config.js"), viteConfig);
}
const srcDir = path.join(projectRoot, "src");
await fs.ensureDir(srcDir);
const mainContent = this.generateMainVRApp(template, platform, safetyFeatures, useTypeScript);
await fs.writeFile(
path.join(srcDir, `index.${useTypeScript ? "ts" : "js"}`),
mainContent
);
switch (template) {
case "safezone":
const safeZoneContent = this.generateSafeZoneSetup(useTypeScript);
await fs.writeFile(
path.join(srcDir, `safe-zone-manager.${useTypeScript ? "ts" : "js"}`),
safeZoneContent
);
break;
case "proximity":
const proximityContent = this.generateProximitySetup(useTypeScript);
await fs.writeFile(
path.join(srcDir, `proximity-detector.${useTypeScript ? "ts" : "js"}`),
proximityContent
);
break;
case "therapy":
const therapyContent = this.generateTherapyEnvironment(useTypeScript);
await fs.writeFile(
path.join(srcDir, `therapy-environment.${useTypeScript ? "ts" : "js"}`),
therapyContent
);
break;
case "educational":
const educationalContent = this.generateEducationalVR(useTypeScript);
await fs.writeFile(
path.join(srcDir, `educational-vr.${useTypeScript ? "ts" : "js"}`),
educationalContent
);
break;
}
if (platform === "webxr") {
const htmlContent = this.generateWebXRHTML(appName, template);
await fs.writeFile(path.join(projectRoot, "index.html"), htmlContent);
}
const safetyConfig = {
vr: {
safety: {
safeZoneEnabled: safetyFeatures.includes("safezone"),
proximityDetection: safetyFeatures.includes("proximity"),
motionSicknessReduction: safetyFeatures.includes("motion"),
panicMode: safetyFeatures.includes("panic"),
spatialAudio: safetyFeatures.includes("audio"),
hapticFeedback: safetyFeatures.includes("haptic")
},
boundaries: {
width: 2,
// meters
height: 2,
depth: 2
},
comfort: {
locomotionType: "teleport",
turnType: "snap",
vignettingEnabled: true
}
}
};
await fs.writeJson(
path.join(projectRoot, "vr-safety.config.json"),
safetyConfig,
{ spaces: 2 }
);
const readmeContent = this.generateVRReadme(appName, template, platform, useTypeScript, safetyFeatures);
await fs.writeFile(path.join(projectRoot, "README.md"), readmeContent);
creationSpinner.succeed("VR application created successfully!");
console.log(chalk.green("\nā
Success! Your accessible VR app is ready:"));
console.log(chalk.gray(`š Directory: ${appName}`));
console.log(chalk.gray(`š„½ Template: ${template}`));
console.log(chalk.gray(`š® Platform: ${platform}`));
console.log(chalk.gray(`š Language: ${useTypeScript ? "TypeScript" : "JavaScript"}`));
console.log(chalk.gray(`š”ļø Safety: ${safetyFeatures.join(", ")}`));
console.log(chalk.blue("\nš” Next steps:"));
console.log(chalk.gray(`1. cd ${appName}`));
console.log(chalk.gray("2. npm install"));
console.log(chalk.gray("3. npm run dev"));
if (platform === "webxr") {
console.log(chalk.yellow("\nā ļø WebXR Notes:"));
console.log(chalk.gray("⢠Requires HTTPS for VR features"));
console.log(chalk.gray("⢠Test on VR-capable devices"));
console.log(chalk.gray("⢠Configure safe zone before use"));
}
} catch (error) {
spinner.fail("Failed to create VR application");
console.error(chalk.red(error instanceof Error ? error.message : "Unknown error"));
process.exit(1);
}
}
async function addAdapter(adapterType, options = {}) {
console.log(chalk.blue("š§ Adding NeuroAdapt Accessibility Adapter\n"));
let adapter = adapterType;
if (!adapter) {
const { selectedAdapter } = await inquirer.prompt([
{
type: "list",
name: "selectedAdapter",
message: "Which adapter would you like to add?",
choices: [
{ name: "OpenAI Adapter", value: "openai" },
{ name: "Claude Adapter", value: "claude" },
{ name: "Ollama Adapter", value: "ollama" },
{ name: "All Adapters", value: "all" }
]
}
]);
adapter = selectedAdapter;
}
const spinner = ora("Adding adapter configuration...").start();
try {
const projectRoot = process.cwd();
const packageJsonPath = path__default.join(projectRoot, "package.json");
if (!await fs.pathExists(packageJsonPath)) {
spinner.fail("No package.json found. Please run this command in a project directory.");
return;
}
const packageJson = await fs.readJson(packageJsonPath);
const dependencies = packageJson.dependencies || {};
const devDependencies = packageJson.devDependencies || {};
dependencies["@neuroadapt/ai"] = "^1.1.0";
if (adapter === "openai" || adapter === "all") {
dependencies["openai"] = "^4.0.0";
}
if (adapter === "claude" || adapter === "all") {
dependencies["@anthropic-ai/sdk"] = "^0.20.0";
}
if (adapter === "ollama" || adapter === "all") {
dependencies["ollama"] = "^0.5.0";
}
packageJson.dependencies = dependencies;
packageJson.devDependencies = devDependencies;
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
const configPath = path__default.join(projectRoot, "neuroadapt.config.js");
if (!await fs.pathExists(configPath) || options.force) {
const configContent = generateAdapterConfig(adapter);
await fs.writeFile(configPath, configContent);
}
const examplePath = path__default.join(projectRoot, "src", "neuroadapt-example.ts");
await fs.ensureDir(path__default.dirname(examplePath));
if (!await fs.pathExists(examplePath) || options.force) {
const exampleContent = generateExampleUsage(adapter);
await fs.writeFile(examplePath, exampleContent);
}
spinner.succeed("Adapter configuration added successfully!");
console.log(chalk.green("\nā
Success! Next steps:"));
console.log(chalk.gray("1. Run `npm install` or `pnpm install` to install dependencies"));
console.log(chalk.gray("2. Configure your API keys in environment variables"));
console.log(chalk.gray("3. Check `src/neuroadapt-example.ts` for usage examples"));
} catch (error) {
spinner.fail("Failed to add adapter configuration");
console.error(chalk.red(error instanceof Error ? error.message : "Unknown error"));
process.exit(1);
}
}
function generateAdapterConfig(adapter) {
return `/**
* NeuroAdapt Configuration
* Configure accessibility adapters for your application
*/
export default {
adapters: {
${adapter === "openai" || adapter === "all" ? `
openai: {
apiKey: process.env.OPENAI_API_KEY,
model: 'gpt-4',
features: ['cognitive-assistance', 'content-adaptation']
},` : ""}
${adapter === "claude" || adapter === "all" ? `
claude: {
apiKey: process.env.ANTHROPIC_API_KEY,
model: 'claude-3-sonnet-20240229',
features: ['cognitive-assistance', 'content-simplification']
},` : ""}
${adapter === "ollama" || adapter === "all" ? `
ollama: {
baseUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',
model: 'llama2',
features: ['local-processing', 'privacy-focused']
},` : ""}
},
accessibility: {
cognitive: {
enabled: true,
adaptationLevel: 'medium',
processingPace: 'normal'
},
sensory: {
enabled: true,
highContrast: false,
motionReduction: false,
fontSize: 16
},
motor: {
enabled: true,
keyboardNavigation: true,
largerTargets: false
}
}
};
`;
}
function generateExampleUsage(adapter) {
return `/**
* NeuroAdapt Usage Example
* Example implementation of accessibility adapters
*/
import { createAdapter } from '@neuroadapt/ai';
import { PreferenceStore } from '@neuroadapt/core';
import config from '../neuroadapt.config.js';
// Initialize preference store
const preferences = new PreferenceStore({ key: 'neuroadapt-prefs' });
// Create adapter based on configuration
${adapter === "openai" || adapter === "all" ? `
// OpenAI Adapter Example
const openaiAdapter = createAdapter('openai', {
apiKey: config.adapters.openai?.apiKey,
model: config.adapters.openai?.model
});
` : ""}
${adapter === "claude" || adapter === "all" ? `
// Claude Adapter Example
const claudeAdapter = createAdapter('claude', {
apiKey: config.adapters.claude?.apiKey,
model: config.adapters.claude?.model
});
` : ""}
${adapter === "ollama" || adapter === "all" ? `
// Ollama Adapter Example
const ollamaAdapter = createAdapter('ollama', {
baseUrl: config.adapters.ollama?.baseUrl,
model: config.adapters.ollama?.model
});
` : ""}
// Example: Adapt content for cognitive accessibility
export async function adaptContentForUser(content: string) {
try {
const userPrefs = await preferences.load();
if (userPrefs?.cognitive.explanationLevel === 'simple') {
${adapter === "openai" ? "const result = await openaiAdapter.simplifyContent(content);" : adapter === "claude" ? "const result = await claudeAdapter.simplifyContent(content);" : adapter === "ollama" ? "const result = await ollamaAdapter.simplifyContent(content);" : "const result = await openaiAdapter.simplifyContent(content);"}
return result.adaptedContent;
}
return content;
} catch (error) {
console.error('Content adaptation failed:', error);
return content; // Fallback to original content
}
}
// Example: Get personalized accessibility recommendations
export async function getAccessibilityRecommendations() {
try {
const userPrefs = await preferences.load();
${adapter === "openai" ? "const recommendations = await openaiAdapter.getRecommendations(userPrefs);" : adapter === "claude" ? "const recommendations = await claudeAdapter.getRecommendations(userPrefs);" : adapter === "ollama" ? "const recommendations = await ollamaAdapter.getRecommendations(userPrefs);" : "const recommendations = await openaiAdapter.getRecommendations(userPrefs);"}
return recommendations;
} catch (error) {
console.error('Failed to get recommendations:', error);
return [];
}
}
`;
}
async function exportProfile(profileName, options = {}) {
console.log(chalk.blue("š¤ Exporting NeuroAdapt Accessibility Profile\n"));
const spinner = ora("Scanning for accessibility profiles...").start();
try {
const projectRoot = process.cwd();
const preferencesPath = path__default.join(projectRoot, ".neuroadapt", "preferences.json");
const configPath = path__default.join(projectRoot, "neuroadapt.config.js");
if (!await fs.pathExists(preferencesPath)) {
spinner.fail("No accessibility preferences found in this project.");
console.log(chalk.gray("Run your application first to generate preferences, or use `neuroadapt create-app` to start fresh."));
return;
}
spinner.text = "Loading preferences...";
const preferences = await fs.readJson(preferencesPath);
let config = {};
if (await fs.pathExists(configPath)) {
const configModule = await import(path__default.resolve(configPath));
config = configModule.default || configModule;
}
spinner.stop();
let format = options.format;
let outputPath = options.output;
let includePersonalData = options.includePersonalData;
if (!format || !outputPath) {
const answers = await inquirer.prompt([
{
type: "list",
name: "format",
message: "Export format:",
choices: [
{ name: "JSON (recommended)", value: "json" },
{ name: "JavaScript/ES Module", value: "js" },
{ name: "YAML", value: "yaml" }
],
when: !format
},
{
type: "input",
name: "outputPath",
message: "Output file path:",
default: `accessibility-profile.${format || "json"}`,
when: !outputPath
},
{
type: "confirm",
name: "includePersonalData",
message: "Include personal data (usage analytics, session data)?",
default: false,
when: includePersonalData === void 0
}
]);
format = format || answers.format;
outputPath = outputPath || answers.outputPath;
includePersonalData = includePersonalData ?? answers.includePersonalData;
}
const exportSpinner = ora("Generating profile export...").start();
const profile = createExportableProfile(preferences, config, includePersonalData);
let content;
const resolvedOutputPath = path__default.resolve(outputPath);
switch (format) {
case "json":
content = JSON.stringify(profile, null, 2);
break;
case "js":
content = generateJSExport(profile);
break;
case "yaml":
content = generateYAMLExport(profile);
break;
default:
throw new Error(`Unsupported format: ${format}`);
}
await fs.ensureDir(path__default.dirname(resolvedOutputPath));
await fs.writeFile(resolvedOutputPath, content, "utf8");
exportSpinner.succeed("Profile exported successfully!");
console.log(chalk.green("\nā
Export completed:"));
console.log(chalk.gray(`š File: ${resolvedOutputPath}`));
console.log(chalk.gray(`š Format: ${format?.toUpperCase()}`));
console.log(chalk.gray(`š Personal data: ${includePersonalData ? "Included" : "Excluded"}`));
console.log(chalk.blue("\nš” Usage:"));
console.log(chalk.gray("⢠Share this profile with other developers"));
console.log(chalk.gray("⢠Import it using `neuroadapt import-profile`"));
console.log(chalk.gray("⢠Use it as a template for new projects"));
} catch (error) {
spinner.fail("Failed to export profile");
console.error(chalk.red(error instanceof Error ? error.message : "Unknown error"));
process.exit(1);
}
}
function createExportableProfile(preferences, config, includePersonalData) {
const profile = {
name: preferences.name || "Accessibility Profile",
version: "1.1.0",
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
accessibility: {
cognitive: {
readingSpeed: preferences.cognitive?.readingSpeed || "normal",
processingPace: preferences.cognitive?.processingPace || "normal",
explanationLevel: preferences.cognitive?.explanationLevel || "standard",
allowInterruptions: preferences.cognitive?.allowInterruptions ?? true
},
sensory: {
highContrast: preferences.sensory?.highContrast || false,
darkMode: preferences.sensory?.darkMode || false,
motionReduction: preferences.sensory?.motionReduction || false,
fontSize: preferences.sensory?.fontSize || 16,
colorVisionFilter: preferences.sensory?.colorVisionFilter || "none"
},
motor: {
keyboardNavigation: preferences.motor?.keyboardNavigation || false,
mouseAlternatives: preferences.motor?.mouseAlternatives || false,
targetSizeIncrease: preferences.motor?.targetSizeIncrease || 0,
dwellTime: preferences.motor?.dwellTime || 500
},
audio: {
enableAudio: preferences.audio?.enableAudio || false,
enableCaptions: preferences.audio?.enableCaptions || false,
volume: preferences.audio?.volume || 0.7,
audioDescription: preferences.audio?.audioDescription || false
}
},
configuration: {
adapters: config.adapters || {},
features: config.features || {}
}
};
if (includePersonalData && preferences.analytics) {
profile.analytics = {
usagePatterns: preferences.analytics.usagePatterns,
adaptationHistory: preferences.analytics.adaptationHistory,
performanceMetrics: preferences.analytics.performanceMetrics
};
}
return profile;
}
function generateJSExport(profile) {
return `/**
* NeuroAdapt Accessibility Profile
* Generated on ${(/* @__PURE__ */ new Date()).toISOString()}
*/
export default ${JSON.stringify(profile, null, 2)};
export const accessibilityPreferences = ${JSON.stringify(profile.accessibility, null, 2)};
export const adapterConfiguration = ${JSON.stringify(profile.configuration, null, 2)};
`;
}
function generateYAMLExport(profile) {
const yamlContent = Object.entries(profile).map(([key, value]) => `${key}: ${JSON.stringify(value, null, 2)}`).join("\n");
return `# NeuroAdapt Accessibility Profile
# Generated on ${(/* @__PURE__ */ new Date()).toISOString()}
${yamlContent}
`;
}
async function importProfile(profilePath, options = {}) {
console.log(chalk.blue("š„ Importing NeuroAdapt Accessibility Profile\n"));
let inputPath = profilePath;
if (!inputPath) {
const { selectedPath } = await inquirer.prompt([
{
type: "input",
name: "selectedPath",
message: "Path to accessibility profile file:",
validate: async (input) => {
if (!input) return "Please provide a file path";
if (!await fs.pathExists(input)) return "File does not exist";
return true;
}
}
]);
inputPath = selectedPath;
}
const spinner = ora("Loading profile...").start();
try {
const projectRoot = process.cwd();
const preferencesPath = path__default.join(projectRoot, ".neuroadapt", "preferences.json");
const configPath = path__default.join(projectRoot, "neuroadapt.config.js");
if (!await fs.pathExists(inputPath)) {
spinner.fail(`Profile file not found: ${inputPath}`);
return;
}
spinner.text = "Parsing profile data...";
const ext = path__default.extname(inputPath).toLowerCase();
let profile;
if (ext === ".json") {
profile = await fs.readJson(inputPath);
} else if (ext === ".js" || ext === ".mjs") {
const profileModule = await import(path__default.resolve(inputPath));
profile = profileModule.default || profileModule;
} else {
throw new Error(`Unsupported file format: ${ext}. Supported formats: .json, .js, .mjs`);
}
validateProfileStructure(profile);
spinner.text = "Checking existing configuration...";
const hasExistingPrefs = await fs.pathExists(preferencesPath);
const hasExistingConfig = await fs.pathExists(configPath);
let shouldProceed = true;
let mergeMode = options.merge;
let createBackup = options.backup;
if ((hasExistingPrefs || hasExistingConfig) && !options.force) {
spinner.stop();
const answers = await inquirer.prompt([
{
type: "list",
name: "action",
message: "Existing accessibility configuration found. What would you like to do?",
choices: [
{ name: "Merge with existing settings", value: "merge" },
{ name: "Replace existing settings", value: "replace" },
{ name: "Cancel import", value: "cancel" }
]
},
{
type: "confirm",
name: "backup",
message: "Create backup of existing configuration?",
default: true,
when: (answers2) => answers2.action !== "cancel"
}
]);
if (answers.action === "cancel") {
console.log(chalk.yellow("Import cancelled by user."));
return;
}
mergeMode = answers.action === "merge";
createBackup = answers.backup;
shouldProceed = true;
}
if (!shouldProceed) return;
const importSpinner = ora("Importing profile...").start();
if (createBackup && (hasExistingPrefs || hasExistingConfig)) {
const backupDir = path__default.join(projectRoot, ".neuroadapt", "backups");
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
await fs.ensureDir(backupDir);
if (hasExistingPrefs) {
await fs.copy(preferencesPath, path__default.join(backupDir, `preferences-${timestamp}.json`));
}
if (hasExistingConfig) {
await fs.copy(configPath, path__default.join(backupDir, `config-${timestamp}.js`));
}
importSpinner.text = "Backup created, applying new settings...";
}
await applyProfileSettings(profile, projectRoot, mergeMode, hasExistingPrefs, hasExistingConfig);
importSpinner.succeed("Profile imported successfully!");
console.log(chalk.green("\nā
Import completed:"));
console.log(chalk.gray(`š Source: ${inputPath}`));
console.log(chalk.gray(`š Mode: ${mergeMode ? "Merged" : "Replaced"}`));
console.log(chalk.gray(`š¾ Backup: ${createBackup ? "Created" : "Skipped"}`));
console.log(chalk.blue("\nš” Next steps:"));
console.log(chalk.gray("⢠Restart your application to apply new settings"));
console.log(chalk.gray("⢠Verify accessibility features are working as expected"));
console.log(chalk.gray("⢠Customize settings further if needed"));
} catch (error) {
spinner.fail("Failed to import profile");
console.error(chalk.red(error instanceof Error ? error.message : "Unknown error"));
process.exit(1);
}
}
function validateProfileStructure(profile) {
if (!profile || typeof profile !== "object") {
throw new Error("Invalid profile: must be an object");
}
if (!profile.accessibility) {
throw new Error("Invalid profile: missing accessibility configuration");
}
const required = ["cognitive", "sensory", "motor", "audio"];
for (const section of required) {
if (!profile.accessibility[section]) {
throw new Error(`Invalid profile: missing accessibility.${section} configuration`);
}
}
}
async function applyProfileSettings(profile, projectRoot, mergeMode, hasExistingPrefs, hasExistingConfig) {
const preferencesPath = path__default.join(projectRoot, ".neuroadapt", "preferences.json");
const configPath = path__default.join(projectRoot, "neuroadapt.config.js");
let preferences = profile.accessibility;
if (mergeMode && hasExistingPrefs) {
const existing = await fs.readJson(preferencesPath);
preferences = mergeDeep(existing, preferences);
}
preferences.importedAt = (/* @__PURE__ */ new Date()).toISOString();
preferences.importedFrom = profile.name || "Unknown Profile";
preferences.version = profile.version || "1.1.0";
await fs.ensureDir(path__default.dirname(preferencesPath));
await fs.writeJson(preferencesPath, preferences, { spaces: 2 });
if (profile.configuration) {
let config = profile.configuration;
if (mergeMode && hasExistingConfig) {
const existingModule = await import(path__default.resolve(configPath));
const existing = existingModule.default || existingModule;
config = mergeDeep(existing, config);
}
const configContent = generateConfigFile(config);
await fs.writeFile(configPath, configContent);
}
}
function mergeDeep(target, source) {
const result = { ...target };
for (const key in source) {
if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
result[key] = mergeDeep(result[key] || {}, source[key]);
} else {
result[key] = source[key];
}
}
return result;
}
function generateConfigFile(config) {
return `/**
* NeuroAdapt Configuration
* Imported on ${(/* @__PURE__ */ new Date()).toISOString()}
*/
export default ${JSON.stringify(config, null, 2)};
`;
}
async function initProject(options = {}) {
console.log(chalk.blue("š Initializing NeuroAdapt SDK in existing project\n"));
const spinner = ora("Analyzing project structure...").start();
try {
const projectRoot = process.cwd();
const packageJsonPath = path__default.join(projectRoot, "package.json");
if (!await fs.pathExists(packageJsonPath)) {
spinner.fail("No package.json found. Please run this command in a project directory.");
return;
}
const packageJson = await fs.readJson(packageJsonPath);
const isTypeScript = options.typescript ?? (await fs.pathExists(path__default.join(projectRoot, "tsconfig.json")) || packageJson.devDependencies?.typescript || packageJson.dependencies?.typescript);
spinner.stop();
const answers = await inquirer.prompt([
{
type: "input",
name: "projectName",
message: "Project name:",
default: packageJson.name || path__default.basename(projectRoot)
},
{
type: "checkbox",
name: "features",
message: "Select accessibility features to enable:",
choices: [
{ name: "Cognitive Load Management", value: "cognitive", checked: true },
{ name: "Sensory Adaptations (contrast, motion)", value: "sensory", checked: true },
{ name: "Motor Accessibility (keyboard nav)", value: "motor", checked: true },
{ name: "Audio Support (captions, descriptions)", value: "audio", checked: true },
{ name: "AI-Powered Personalization", value: "ai", checked: false },
{ name: "Quantum Computing Support", value: "quantum", checked: false },
{ name: "VR/AR Safety Features", value: "vr", checked: false }
],
when: !options.features
},
{
type: "list",
name: "framework",
message: "What framework are you using?",
choices: [
{ name: "React", value: "react" },
{ name: "Vue.js", value: "vue" },
{ name: "Angular", value: "angular" },
{ name: "Svelte", value: "svelte" },
{ name: "Vanilla JavaScript/TypeScript", value: "vanilla" },
{ name: "Node.js (Backend)", value: "node" }
]
},
{
type: "confirm",
name: "setupTesting",
message: "Set up accessibility testing?",
default: true
}
]);
const features = options.features || answers.features;
const setupSpinner = ora("Setting up NeuroAdapt SDK...").start();
const dependencies = packageJson.dependencies || {};
const devDependencies = packageJson.devDependencies || {};
dependencies["@neuroadapt/core"] = "^1.1.0";
if (features.includes("ai")) {
dependencies["@neuroadapt/ai"] = "^1.1.0";
}
if (features.includes("quantum")) {
dependencies["@neuroadapt/quantum"] = "^1.1.0";
}
if (features.includes("vr")) {
dependencies["@neuroadapt/vr"] = "^1.1.0";
}
if (answers.framework === "react") {
dependencies["react"] = dependencies["react"] || "^18.0.0";
dependencies["react-dom"] = dependencies["react-dom"] || "^18.0.0";
}
if (answers.setupTesting