Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 59 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ It may be useful for standalone scripts that do not require a `package.json`. Al
- **Dynamic package loading**: In `node.js`, `use-m` loads and imports npm packages on-demand with **global installation** (using `npm i -g` with separate alias for each version), making them available across projects and reusable without needing to reinstall each time. In case of a browser `use-m` loads npm packages directly from CDNs (by default `esm.sh` is used).
- **Version-safe imports**: Allows multiple versions of the same library to coexist without conflicts, so you can specify any version for each import (usage) without affecting other scripts or other usages (imports) in the same script.
- **No more `require`, `import`, or `package.json`**: With `use-m`, traditional module loading approaches like `require()`, `import` statements, and `package.json` dependencies become effectively obsolete. You can dynamically load any module at runtime without pre-declaring dependencies in separate file. This enables truly self-contained `.mjs` files that can effectively replace shell scripts.
- **Built-in modules emulation**: Provides emulation for Node.js built-in modules across all environments (browser, Node.js, Bun, Deno), ensuring consistent behavior regardless of the runtime.
- **Built-in modules emulation**: Provides emulation for Node.js built-in modules across all environments (browser, Node.js, Bun, Deno), ensuring consistent behavior regardless of the runtime. Also includes support for popular frameworks like React.js and ink (CLI apps).
- **Relative path resolution**: Supports `./ ` and `../` paths for loading local JavaScript and JSON files relative to the executing file, working seamlessly even in browser environments.

## Usage
Expand Down Expand Up @@ -367,6 +367,64 @@ const _ = await use('[email protected]');
console.log(`_.add(1, 2) = ${_.add(1, 2)}`);
```

### React.js and ink Support

`use-m` includes built-in support for React.js and ink (React for CLI apps) with automatic environment detection and CDN fallbacks.

#### React.js in Browser

```javascript
const { use } = eval(await (await fetch('https://unpkg.com/use-m/use.js')).text());

// Load React and ReactDOM with automatic CDN fallback
const React = await use('react');
const ReactDOM = await use('react-dom');

// Create and render a React component
const App = React.createElement('h1', null, 'Hello from React with use-m!');
ReactDOM.render(App, document.getElementById('root'));
```

#### React.js in Node.js

```javascript
import { use } from 'use-m';

// Load React for server-side rendering
const React = await use('react');
const ReactDOMServer = await use('react-dom/server');

// Create a React component
const App = React.createElement('div', null,
React.createElement('h1', null, 'Hello from React with use-m!')
);

// Render to HTML string
const html = ReactDOMServer.renderToString(App);
console.log(html);
```

#### ink CLI Apps

```javascript
#!/usr/bin/env node
import { use } from 'use-m';

// Load React and ink for CLI apps
const React = await use('react');
const { render, Text, Box } = await use('ink');

// Create a CLI component
const CliApp = () => React.createElement(Box, { padding: 1 },
React.createElement(Text, { color: 'green' }, '🚀 Hello from ink with use-m!')
);

// Render to terminal
render(React.createElement(CliApp));
```

**Note**: React.js and ink modules require the corresponding packages to be installed (`npm install react react-dom` for React.js, `npm install react ink` for ink). In browser environments, React.js will automatically fall back to CDN loading.

## Examples

You can check out [usage examples source code](https://github.com/link-foundation/use-m/tree/main/examples). You can also explore our [tests](https://github.com/link-foundation/use-m/tree/main/tests) to get even more examples.
Expand Down
67 changes: 67 additions & 0 deletions examples/ink/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# ink CLI Examples with use-m

This directory contains examples showing how to use ink (React for CLI) with use-m's built-in module support.

## Examples

### Simple CLI Example (`cli-example.mjs`)

Demonstrates basic ink CLI application with use-m:

```bash
# Install dependencies first
npm install react ink

# Run the example
node cli-example.mjs
```

This example shows:
- Loading React and ink using use-m's built-in modules
- Creating CLI components with ink
- Text rendering and styling in terminal

### Interactive CLI Example (`interactive-example.mjs`)

Demonstrates interactive ink CLI application with use-m:

```bash
# Install dependencies first
npm install react ink

# Run the interactive example
node interactive-example.mjs
```

This example shows:
- Interactive CLI with user input handling
- State management with React hooks
- Real-time updates in terminal interface
- Keyboard event handling

## Controls for Interactive Example

- `+` : Increment counter
- `-` : Decrement counter
- `q` : Quit application
- `Ctrl+C` : Force quit

## Features Demonstrated

- **Built-in Module Support**: Use `await use('ink')` and `await use('react')` without package.json
- **CLI Components**: React components that render to terminal instead of DOM
- **Interactive UIs**: Handle keyboard input and update UI in real-time
- **Hooks Support**: useState, useInput, useApp and other React/ink hooks
- **Terminal Styling**: Colors, formatting, and layout in terminal

## Use Cases

- Command-line tools and utilities
- Interactive terminal applications
- Developer tools and build scripts
- System administration interfaces
- Educational CLI applications

## Requirements

ink requires Node.js environment and will not work in browser. The built-in module support automatically handles this by returning `null` for browser environments.
46 changes: 46 additions & 0 deletions examples/ink/cli-example.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env node

// ink CLI example using use-m
// This example shows how to use ink built-in modules with use-m
import { use } from '../../use.mjs';

async function main() {
try {
// Import ink and React using built-in module support
const React = await use('react');
const { render, Text, Box } = await use('ink');

// Create a simple CLI component using React and ink
const CliApp = () => React.createElement(Box,
{ flexDirection: 'column', padding: 1 },
React.createElement(Text,
{ color: 'green', bold: true },
'🚀 Hello from ink with use-m!'
),
React.createElement(Text, null, 'This CLI app was built using:'),
React.createElement(Box, { marginLeft: 2, flexDirection: 'column' },
React.createElement(Text, { color: 'blue' }, '• React for component logic'),
React.createElement(Text, { color: 'blue' }, '• ink for CLI rendering'),
React.createElement(Text, { color: 'blue' }, '• use-m for dynamic imports')
),
React.createElement(Text, null, ''),
React.createElement(Text,
{ color: 'yellow' },
`React version: ${React.version}`
)
);

// Render the CLI app
const { waitUntilExit } = render(React.createElement(CliApp));

// Wait for the app to finish (though this simple example will exit immediately)
await waitUntilExit();

} catch (error) {
console.error('Error:', error.message);
console.log('\nTo run this example, install the required dependencies:');
console.log('npm install react ink');
}
}

main().catch(console.error);
74 changes: 74 additions & 0 deletions examples/ink/interactive-example.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env node

// Interactive ink CLI example using use-m
// This example shows a more complex ink application with state and user input
import { use } from '../../use.mjs';

async function main() {
try {
// Import React, ink, and other utilities using built-in module support
const React = await use('react');
const { render, Text, Box, useInput, useApp } = await use('ink');

// Create an interactive CLI component
const InteractiveApp = () => {
const { exit } = useApp();
const [counter, setCounter] = React.useState(0);
const [lastKey, setLastKey] = React.useState('');

// Handle user input
useInput((input, key) => {
setLastKey(input || key.name || 'unknown');

if (input === '+') {
setCounter(prev => prev + 1);
} else if (input === '-') {
setCounter(prev => prev - 1);
} else if (input === 'q' || key.ctrl && input === 'c') {
exit();
}
});

return React.createElement(Box,
{ flexDirection: 'column', padding: 1 },
React.createElement(Text,
{ color: 'green', bold: true },
'🎮 Interactive ink App with use-m'
),
React.createElement(Text, null, ''),
React.createElement(Box, { flexDirection: 'column' },
React.createElement(Text,
{ color: 'cyan' },
`Counter: ${counter}`
),
React.createElement(Text,
{ color: 'gray' },
`Last key pressed: ${lastKey}`
)
),
React.createElement(Text, null, ''),
React.createElement(Box, { flexDirection: 'column' },
React.createElement(Text, { color: 'yellow' }, 'Controls:'),
React.createElement(Text, null, ' + : Increment counter'),
React.createElement(Text, null, ' - : Decrement counter'),
React.createElement(Text, null, ' q : Quit application')
),
React.createElement(Text, null, ''),
React.createElement(Text,
{ color: 'dim' },
'Built with React, ink, and use-m'
)
);
};

// Render the interactive CLI app
render(React.createElement(InteractiveApp));

} catch (error) {
console.error('Error:', error.message);
console.log('\nTo run this example, install the required dependencies:');
console.log('npm install react ink');
}
}

main().catch(console.error);
54 changes: 54 additions & 0 deletions examples/react/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# React.js Examples with use-m

This directory contains examples showing how to use React.js with use-m's built-in module support.

## Examples

### Node.js Example (`node-example.mjs`)

Demonstrates server-side React.js usage with use-m:

```bash
# Install dependencies first
npm install react react-dom

# Run the example
node node-example.mjs
```

This example shows:
- Loading React using use-m's built-in `react` module
- Server-side rendering with ReactDOMServer
- Error handling for missing dependencies

### Browser Example (`browser-example.html`)

Demonstrates client-side React.js usage with use-m:

```bash
# Open in browser
open browser-example.html
# or serve with a local server
python -m http.server 8000
```

This example shows:
- Loading React in the browser using use-m's built-in modules
- Creating and rendering React components
- Fallback to CDN if React globals aren't available
- Interactive React components with event handlers

## Features Demonstrated

- **Built-in Module Support**: Use `await use('react')` instead of installing dependencies
- **Environment Detection**: Automatically works in both Node.js and browser
- **Version Management**: Uses consistent React versions across environments
- **Error Handling**: Graceful fallbacks when dependencies are missing
- **CDN Fallback**: Browser examples automatically load from CDN

## Use Cases

- Rapid prototyping without setting up package.json
- Educational examples and tutorials
- Self-contained scripts that don't require dependency management
- Cross-environment React applications
Loading
Loading