infaira-canvas
v0.1.10
Published
InfAIra Canvas CLI — Widget development toolkit for InfAIra Canvas
Maintainers
Readme
infaira-canvas
CLI toolkit for building and publishing widgets for the InfAIra Canvas (ICan).
What is this?
infaira-canvas is a command-line tool that helps widget developers:
- Scaffold a new widget project with all required files
- Upload a built widget bundle to an ICan portal
Installation
No installation needed. Use npx to always get the latest version:
npx infaira-canvas <command>Or install globally:
npm install -g infaira-canvas
infaira-canvas <command>Commands
init — Scaffold a new widget
npx infaira-canvas init <widget-name>Example:
npx infaira-canvas init my-sales-widgetWhat it does:
- Creates a new folder
my-sales-widget/ - Fetches the latest
ican.d.tstype definitions fromhttps://infaira.ai/dist/client/ican.d.ts - Generates all files needed to build and run a widget
Files generated:
| File | Purpose |
|------|---------|
| bundle.json | Widget identity — unique ID, name, version |
| src/index.tsx | Main widget React component |
| src/ican.ts | ICan bridge — registerWidget() and other registration functions |
| src/styles.scss | Widget styles |
| ican.d.ts | TypeScript type definitions for ICan components |
| designer.d.ts | TypeScript type definitions for the widget designer |
| webpack.config.js | Build config — ensures React and ICan are NOT bundled |
| tsconfig.json | TypeScript config |
| package.json | npm dependencies |
| index.html | Dev harness to preview the widget locally |
| ui.html | UI harness for testing UIs |
| localization.json | Localization strings |
| .gitignore | Ignores node_modules/, dist/ |
upload — Upload a built widget to the portal
infaira-canvas upload \
--url <portal-url> \
--token <auth-token> \
--bundle <path-to-bundle.json> \
--script <path-to-main.js>Example:
infaira-canvas upload \
--url https://infaira.ai \
--token eyJhbGciOiJIUzI1NiJ9... \
--bundle ./bundle.json \
--script ./dist/main.jsOptions:
| Flag | Required | Description |
|------|----------|-------------|
| --url | Yes | Base URL of the ICan portal |
| --token | Yes | Your JWT auth token from the portal |
| --bundle | Yes | Path to bundle.json |
| --script | Yes | Path to compiled main.js (from npm run build) |
What it does:
- Sends
bundle.jsonandmain.jsto the portal's/api/bundles/uploadendpoint - The portal stores widget metadata in the database
- The widget becomes available in the portal's widget library
- Admins can then add it to any dashboard
Full Developer Workflow
# 1. Scaffold a new widget
npx infaira-canvas init my-widget
# 2. Install dependencies
cd my-widget
npm install
# 3. Start dev server (preview at http://localhost:8080)
npm run dev
# 4. Build for production
npm run build
# 5. Upload to the ICan portal
infaira-canvas upload \
--url https://infaira.ai \
--token <your-token> \
--bundle ./bundle.json \
--script ./dist/main.jsWidget Structure
Every widget scaffolded by infaira-canvas init follows this structure:
my-widget/
├── bundle.json ← Widget metadata (edit this to configure your widget)
├── localization.json ← Localization strings
├── src/
│ ├── index.tsx ← Your widget component (main file to edit)
│ ├── ican.ts ← ICan bridge (do not edit)
│ └── styles.scss ← Widget styles
├── resources/
│ ├── ican-components.js ← ICan component library (for dev mode)
│ ├── infaira-logo.png
│ └── infaira-icon.png
├── ican.d.ts ← ICan type definitions
├── designer.d.ts ← Designer type definitions
├── index.html ← Dev harness
├── ui.html ← UI harness
├── webpack.config.js ← Build config
├── tsconfig.json
└── package.jsonHow Widgets Work
Developer builds → main.js + bundle.json
↓
Upload via infaira-canvas upload
↓
Portal stores main.js + metadata in DB
↓
Portal loads main.js as <script> tag at runtime
↓
Script calls window.registerWidget() → widget appears in grid
↓
Widget receives icanContext → calls executeAction() → renders databundle.json Reference
{
"id": "your-bundle-uuid",
"name": "My Widget",
"version": "1.0.0",
"author": "Your Name",
"widgets": [
{
"id": "my-widget",
"name": "My Widget",
"description": "What this widget does",
"icon": "",
"tags": [],
"category": "",
"isTemplate": false
}
],
"sidebarLinks": [],
"uis": [],
"menuItems": []
}Using icanContext in your widget
The portal passes an icanContext prop to every widget. Use it to fetch data from Orch:
const MyWidget: React.FC<IWidgetProps> = ({ icanContext }) => {
const [data, setData] = React.useState(null);
React.useEffect(() => {
if (!icanContext) return;
icanContext
.executeAction('MyModel', 'GetAll', {}, { json: true })
.then((result) => setData(result));
}, [icanContext]);
return <div>{JSON.stringify(data)}</div>;
};Important Rules
- Never bundle React — it comes from the portal at runtime. The
webpack.config.jsexternals handle this automatically. - Always call
registerWidget()at the bottom ofsrc/index.tsx— this is how the portal discovers your widget. - Widget ID must match
bundle.json— the ID you pass toregisterWidget()must exist in thewidgetsarray inbundle.json. - Grid is 30 columns — design your widget layout accordingly.
Updating ican.d.ts
The type definitions are served from https://infaira.ai/dist/client/ican.d.ts. When you run npx infaira-canvas init, it always fetches the latest version. If the server is unreachable, it falls back to the version bundled inside the npm package.
Publishing a New CLI Version (Maintainers Only)
# Make your changes in src/ or templates/
# then bump version and publish:
npm version patch # bug fix → 0.1.1
npm version minor # new feature → 0.2.0
npm version major # breaking change → 1.0.0
npm publish --access publicRequirements
- Node.js >= 18
- npm >= 7
