saltcat-dsx-transformer
v0.1.0
Published
A transformer for DSX, an extension to JSX that supports compile-time, server-time, and client-side JavaScript execution phases.
Maintainers
Readme
saltcat-dsx-transformer
A transformer for DSX (Durable Script eXtensions), an innovative extension to JSX that introduces distinct execution phases for JavaScript code, enabling powerful meta-programming and compile-time code generation.
What is DSX?
DSX extends JSX by introducing three distinct execution phases for JavaScript code:
- Phase 1 - Compile Time (Node.js context): Code that runs during the build process
- Phase 2 - Server Time (Node.js context, optional): Code that runs on the server at request time
- Phase 3 - Client Side (Browser context): Code that runs in the user's browser
When server-time execution is disabled, both Phase 1 and Phase 2 run at compile time, effectively creating a two-phase system (compile-time and client-side).
Why DSX?
DSX enables powerful meta-programming patterns that aren't possible with standard JSX:
- Compile-time code generation: Loop through files, configurations, or data structures at build time to generate components
- Static site generation with dynamic logic: Use server-side logic at compile time without runtime overhead
- Flexible deployment models: Choose between static compilation or server-side rendering based on your needs
- Type-safe meta-programming: Generate type-safe components from schemas, APIs, or other sources
- Zero-runtime overhead for static content: Compile-time code never ships to the client
Example Use Cases
// Example 1: Generate components from a configuration file at compile time
<#compile>
const routes = require('./routes.json');
return routes.map(route => (
<Route path={route.path} component={route.component} />
));
</#compile>
// Example 2: Server-time data fetching (if server mode enabled)
<#server>
const userData = await fetchUserData(userId);
</#server>
<UserProfile data={userData} />
// Example 3: Client-side interactivity
<button onClick={() => console.log('Client-side code')}>
Click Me
</button>Key Features
- Multi-phase execution: Clearly separate compile-time, server-time, and client-side code
- Meta-programming support: Generate code dynamically at build time
- Flexible architecture: Enable or disable server-time execution based on deployment needs
- JSX compatible: Works with existing JSX tooling and React/Preact/etc.
- Type-safe: Designed to work with TypeScript for enhanced developer experience
- Zero config: Sensible defaults with optional configuration
Installation
npm install saltcat-dsx-transformerUsage
Basic Transformation
import { transformDSX } from 'saltcat-dsx-transformer';
const dsxCode = `
<#compile>
const items = ['apple', 'banana', 'orange'];
</#compile>
<ul>
{items.map(item => <li key={item}>{item}</li>)}
</ul>
`;
const options = {
serverEnabled: false // Phase 1 and 2 both run at compile time
};
const transformedCode = transformDSX(dsxCode, options);With Build Tools
Webpack
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.dsx$/,
use: {
loader: 'saltcat-dsx-transformer/loader',
options: {
serverEnabled: false
}
}
}
]
}
};Vite
// vite.config.js
import { dsxPlugin } from 'saltcat-dsx-transformer/vite';
export default {
plugins: [
dsxPlugin({
serverEnabled: false
})
]
};API Reference
transformDSX(code, options)
Transforms DSX code into standard JavaScript/JSX.
Parameters:
code(string): The DSX source code to transformoptions(object, optional): Transformation optionsserverEnabled(boolean): Whether server-time execution is enabled (default:true)target(string): Output target -'browser','node', or'universal'(default:'browser')sourceMap(boolean): Generate source maps (default:false)filename(string): Source filename for error reporting and source maps
Returns: string - The transformed code
Throws: DSXSyntaxError - If the DSX syntax is invalid
parseDSX(code)
Parses DSX code into an abstract syntax tree (AST).
Parameters:
code(string): The DSX source code to parse
Returns: DSXNode - The root AST node
generateCode(ast, options)
Generates code from a DSX AST.
Parameters:
ast(DSXNode): The DSX AST to generate code fromoptions(object, optional): Code generation options
Returns: string - The generated code
DSX Syntax
Phase Markers
DSX introduces special syntax for marking different execution phases:
// Compile-time code (Phase 1)
<#compile>
// This code runs during build
const config = require('./config.js');
</#compile>
// Server-time code (Phase 2, optional)
<#server>
// This code runs on the server
const data = await fetchFromDatabase();
</#server>
// Client-side code (Phase 3) - standard JSX
<div onClick={() => handleClick()}>
{data.message}
</div>Phase Block Properties
- Isolated scope: Each phase block has its own scope
- Data flow: Variables from earlier phases can be used in later phases
- Async support: All phases support async/await
- Nested blocks: Phase blocks can be nested (with restrictions)
Expression Syntax
// Inline compile-time expression
<div className={#compile config.theme.className}>
// Inline server-time expression (if server mode enabled)
<UserProfile data={#server await fetchUser(id)} />
// Standard client-side expression
<button onClick={() => console.log('click')}>Click</button>Configuration
Options
Create a dsx.config.js file in your project root:
export default {
// Enable or disable server-time execution
serverEnabled: false,
// Output target
target: 'browser',
// Source map generation
sourceMap: true,
// Custom phase handlers
phases: {
compile: {
// Custom compile-time context
context: {
// Add custom globals available at compile time
}
},
server: {
// Server-time configuration
runtime: 'node',
}
},
// Transform options
jsx: {
pragma: 'React.createElement',
pragmaFrag: 'React.Fragment'
}
};Advanced Usage
Custom Phase Handlers
import { transformDSX, registerPhaseHandler } from 'saltcat-dsx-transformer';
// Register a custom phase handler
registerPhaseHandler('compile', async (code, context) => {
// Custom compile-time logic
const result = await customTransform(code);
return result;
});TypeScript Support
DSX works seamlessly with TypeScript:
interface User {
id: string;
name: string;
}
<#compile>
const users: User[] = await import('./users.json');
</#compile>
<ul>
{users.map((user: User) => (
<li key={user.id}>{user.name}</li>
))}
</ul>Performance Considerations
- Compile-time overhead: DSX adds processing time during builds, but results in optimized runtime code
- Bundle size: Compile-time code never ships to the client, reducing bundle size
- Caching: Transformed code is cached to avoid repeated processing
- Incremental builds: Only changed files are retransformed
Comparison with Alternatives
| Feature | DSX | Standard JSX | Astro | SvelteKit | |---------|-----|--------------|-------|-----------| | Multi-phase execution | ✓ | ✗ | ✓ | ✓ | | Compile-time code generation | ✓ | ✗ | Partial | ✗ | | JSX compatible | ✓ | ✓ | Partial | ✗ | | Optional server-time | ✓ | ✗ | ✗ | ✓ | | Framework agnostic | ✓ | ✓ | ✗ | ✗ |
Examples
See the examples directory for complete working examples:
Development
Building
npm run buildTesting
npm test
npm run test:watch
npm run test:coverageContributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Philosophy
This project aligns with Durable Programming LLC's core values:
- Pragmatic problem-solving: DSX solves real meta-programming challenges
- Sustainability: Built for long-term maintenance and evolution
- Developer experience: Clear syntax and excellent tooling support
- Performance: Zero runtime overhead for compile-time code
- Interoperability: Works with existing JSX ecosystems
Roadmap
- [x] Core DSX syntax and parser
- [ ] Full AST implementation
- [ ] Source map support
- [ ] Webpack loader
- [ ] Vite plugin
- [ ] TypeScript definitions
- [ ] Server-time execution runtime
- [ ] Hot module replacement support
- [ ] VS Code extension with syntax highlighting
- [ ] Comprehensive documentation site
Requirements
- Node.js >= 14.0.0
- npm >= 6.0.0
License
MIT License - see LICENSE for details
Support
- Issues: GitHub Issues
- Documentation: Full documentation
- Commercial Support: [email protected]
Acknowledgments
DSX is inspired by:
- JSX and React's component model
- Astro's multi-phase execution
- Svelte's compile-time optimizations
- PHP's mixed server/client execution model
Built with ❤️ by Durable Programming LLC
