#!/usr/bin/env node
/**
* JQHTML SSR Reference Example CLI
*
* This is the canonical reference implementation for integrating with the
* JQHTML SSR server. Use this as a source of truth for external integrations.
*
* Usage:
* jqhtml-ssr-example --vendor --app --component [options]
*
* Example:
* jqhtml-ssr-example \
* --vendor ./bundles/vendor.js \
* --app ./bundles/app.js \
* --component Dashboard_Index_Action \
* --base-url http://localhost:3000
*/
const net = require('net');
const fs = require('fs');
const path = require('path');
// ANSI colors for output
const colors = {
reset: '\x1b[0m',
bold: '\x1b[1m',
dim: '\x1b[2m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
cyan: '\x1b[36m'
};
function color(text, c) {
return `${colors[c]}${text}${colors.reset}`;
}
/**
* Parse command line arguments
*/
function parseArgs() {
const args = process.argv.slice(2);
const config = {
vendor: null,
app: null,
component: null,
componentArgs: {},
baseUrl: 'http://localhost:3000',
timeout: 30000,
port: 9876,
socket: null,
outputFormat: 'pretty', // 'pretty', 'json', 'html-only'
showHelp: false
};
for (let i = 0; i < args.length; i++) {
switch (args[i]) {
case '--vendor':
case '-v':
config.vendor = args[++i];
break;
case '--app':
case '-a':
config.app = args[++i];
break;
case '--component':
case '-c':
config.component = args[++i];
break;
case '--args':
// Parse JSON args
try {
config.componentArgs = JSON.parse(args[++i]);
} catch (e) {
console.error(color('Error: --args must be valid JSON', 'red'));
process.exit(1);
}
break;
case '--base-url':
case '-b':
config.baseUrl = args[++i];
break;
case '--timeout':
case '-t':
config.timeout = parseInt(args[++i], 10);
break;
case '--port':
case '-p':
config.port = parseInt(args[++i], 10);
break;
case '--socket':
case '-s':
config.socket = args[++i];
break;
case '--format':
case '-f':
config.outputFormat = args[++i];
break;
case '--help':
case '-h':
config.showHelp = true;
break;
}
}
return config;
}
/**
* Show help message
*/
function showHelp() {
console.log(`
${color('JQHTML SSR Reference Example', 'bold')}
This CLI demonstrates the complete SSR workflow and serves as the
canonical reference for external integrations.
${color('USAGE:', 'yellow')}
jqhtml-ssr-example --vendor --app --component [options]
${color('REQUIRED:', 'yellow')}
--vendor, -v Path to vendor bundle (contains @jqhtml/core)
--app, -a Path to app bundle (contains components)
--component, -c Component name to render
${color('OPTIONS:', 'yellow')}
--args Component arguments as JSON (default: {})
--base-url, -b Base URL for fetch requests (default: http://localhost:3000)
--timeout, -t Render timeout in milliseconds (default: 30000)
--port, -p SSR server port (default: 9876)
--socket, -s Use Unix socket instead of TCP
--format, -f Output format: pretty, json, html-only (default: pretty)
--help, -h Show this help message
${color('EXAMPLES:', 'yellow')}
# Basic render
jqhtml-ssr-example -v ./vendor.js -a ./app.js -c Dashboard_Index_Action
# With component arguments
jqhtml-ssr-example -v ./vendor.js -a ./app.js -c User_Profile \\
--args '{"user_id": 123}'
# JSON output for piping
jqhtml-ssr-example -v ./vendor.js -a ./app.js -c Dashboard_Index_Action \\
--format json > result.json
# HTML only output
jqhtml-ssr-example -v ./vendor.js -a ./app.js -c Dashboard_Index_Action \\
--format html-only > output.html
${color('OUTPUT:', 'yellow')}
The 'pretty' format shows:
- Rendered HTML (formatted)
- localStorage cache entries
- sessionStorage cache entries
- Timing information
The 'json' format outputs the raw server response.
The 'html-only' format outputs just the HTML.
${color('INTEGRATION NOTES:', 'yellow')}
This example demonstrates the exact protocol used by the SSR server.
See the source code for implementation details that can be adapted
to any language (PHP, Python, Ruby, Go, etc.).
Key integration points:
1. Connect to TCP port or Unix socket
2. Send newline-delimited JSON request
3. Read newline-delimited JSON response
4. Parse response and extract HTML + cache
${color('SEE ALSO:', 'yellow')}
README.md - Full documentation
SPECIFICATION.md - Protocol specification
`);
}
/**
* Connect to SSR server
* @param {object} config - Connection configuration
* @returns {Promise}
*/
function connect(config) {
return new Promise((resolve, reject) => {
const options = config.socket
? { path: config.socket }
: { port: config.port, host: 'localhost' };
const client = net.createConnection(options, () => {
resolve(client);
});
client.on('error', (err) => {
if (err.code === 'ECONNREFUSED') {
reject(new Error(
`Cannot connect to SSR server at ${config.socket || `localhost:${config.port}`}\n` +
`Start the server with: node src/server.js --tcp ${config.port}`
));
} else {
reject(err);
}
});
});
}
/**
* Send request and receive response
* @param {net.Socket} client - Connected socket
* @param {object} request - Request object
* @param {number} timeout - Timeout in ms
* @returns {Promise