@netpad/mcp-server 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +745 -15
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -14105,6 +14105,59 @@ var FIELD_TYPES = [
|
|
|
14105
14105
|
included: true,
|
|
14106
14106
|
layout: { type: "image", imageUrl: "https://example.com/logo.png", alignment: "center" }
|
|
14107
14107
|
}
|
|
14108
|
+
},
|
|
14109
|
+
// File upload fields
|
|
14110
|
+
{
|
|
14111
|
+
type: "file",
|
|
14112
|
+
category: "file",
|
|
14113
|
+
description: "File upload field for images and documents",
|
|
14114
|
+
muiComponent: "FileUpload (custom)",
|
|
14115
|
+
example: {
|
|
14116
|
+
path: "attachment",
|
|
14117
|
+
label: "Upload File",
|
|
14118
|
+
type: "file",
|
|
14119
|
+
included: true,
|
|
14120
|
+
validation: { maxSize: 10485760 }
|
|
14121
|
+
// 10MB
|
|
14122
|
+
}
|
|
14123
|
+
},
|
|
14124
|
+
{
|
|
14125
|
+
type: "file_upload",
|
|
14126
|
+
category: "file",
|
|
14127
|
+
description: "File upload field (alias for file)",
|
|
14128
|
+
muiComponent: "FileUpload (custom)",
|
|
14129
|
+
example: {
|
|
14130
|
+
path: "document",
|
|
14131
|
+
label: "Upload Document",
|
|
14132
|
+
type: "file_upload",
|
|
14133
|
+
included: true
|
|
14134
|
+
}
|
|
14135
|
+
},
|
|
14136
|
+
{
|
|
14137
|
+
type: "image_upload",
|
|
14138
|
+
category: "file",
|
|
14139
|
+
description: "Image-specific upload field with preview",
|
|
14140
|
+
muiComponent: "ImageUpload (custom)",
|
|
14141
|
+
example: {
|
|
14142
|
+
path: "profilePhoto",
|
|
14143
|
+
label: "Profile Photo",
|
|
14144
|
+
type: "image_upload",
|
|
14145
|
+
included: true,
|
|
14146
|
+
validation: { accept: "image/*" }
|
|
14147
|
+
}
|
|
14148
|
+
},
|
|
14149
|
+
{
|
|
14150
|
+
type: "document_upload",
|
|
14151
|
+
category: "file",
|
|
14152
|
+
description: "Document upload field (PDF, Word, Excel)",
|
|
14153
|
+
muiComponent: "DocumentUpload (custom)",
|
|
14154
|
+
example: {
|
|
14155
|
+
path: "resume",
|
|
14156
|
+
label: "Resume",
|
|
14157
|
+
type: "document_upload",
|
|
14158
|
+
included: true,
|
|
14159
|
+
validation: { accept: ".pdf,.doc,.docx" }
|
|
14160
|
+
}
|
|
14108
14161
|
}
|
|
14109
14162
|
];
|
|
14110
14163
|
var OPERATORS = [
|
|
@@ -14441,7 +14494,10 @@ var FIELD_TYPE_KEYWORDS = {
|
|
|
14441
14494
|
rating: ["rating", "stars", "rate", "review"],
|
|
14442
14495
|
nps: ["nps", "recommend", "likelihood", "net promoter"],
|
|
14443
14496
|
autocomplete: ["search", "autocomplete", "typeahead"],
|
|
14444
|
-
tags: ["tags", "keywords", "labels"]
|
|
14497
|
+
tags: ["tags", "keywords", "labels"],
|
|
14498
|
+
file: ["file", "upload", "attachment", "attach"],
|
|
14499
|
+
image_upload: ["photo", "picture", "image upload", "profile photo", "avatar", "thumbnail"],
|
|
14500
|
+
document_upload: ["document", "resume", "cv", "pdf", "contract", "agreement"]
|
|
14445
14501
|
};
|
|
14446
14502
|
function inferFieldType(label, description) {
|
|
14447
14503
|
const text = `${label} ${description || ""}`.toLowerCase();
|
|
@@ -14988,6 +15044,342 @@ try {
|
|
|
14988
15044
|
}
|
|
14989
15045
|
}
|
|
14990
15046
|
\`\`\`
|
|
15047
|
+
`,
|
|
15048
|
+
extensions: `# NetPad Extensions
|
|
15049
|
+
|
|
15050
|
+
NetPad's extension system allows you to add custom functionality to your NetPad installation through modular, independently deployable packages. Extensions can provide API routes, UI components, services, middleware, and more.
|
|
15051
|
+
|
|
15052
|
+
## What Are Extensions?
|
|
15053
|
+
|
|
15054
|
+
Extensions are npm packages that follow the \`NetPadExtension\` interface. They integrate seamlessly with NetPad's core functionality while remaining isolated and independently maintainable.
|
|
15055
|
+
|
|
15056
|
+
\`\`\`
|
|
15057
|
+
\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
|
|
15058
|
+
\u2502 NetPad Core \u2502
|
|
15059
|
+
\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524
|
|
15060
|
+
\u2502 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502
|
|
15061
|
+
\u2502 \u2502 Extension \u2502 \u2502 Extension \u2502 \u2502 Extension \u2502 ... \u2502
|
|
15062
|
+
\u2502 \u2502 (Cloud) \u2502 \u2502(Collaborate)\u2502 \u2502 (Custom) \u2502 \u2502
|
|
15063
|
+
\u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502
|
|
15064
|
+
\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
|
|
15065
|
+
\`\`\`
|
|
15066
|
+
|
|
15067
|
+
## Extension Capabilities
|
|
15068
|
+
|
|
15069
|
+
Extensions can provide:
|
|
15070
|
+
|
|
15071
|
+
| Capability | Description |
|
|
15072
|
+
| ------------------- | --------------------------------------------------------- |
|
|
15073
|
+
| **Routes** | Custom API endpoints under /api/ext/{extension-name}/ |
|
|
15074
|
+
| **Services** | Shared business logic accessible throughout the extension |
|
|
15075
|
+
| **Middleware** | Request/response processing with priority ordering |
|
|
15076
|
+
| **Components** | React UI components for use in pages |
|
|
15077
|
+
| **Features** | Feature flags that enable/disable functionality |
|
|
15078
|
+
| **Lifecycle Hooks** | Initialize and cleanup logic |
|
|
15079
|
+
| **Workflow Nodes** | Custom workflow node types for automation |
|
|
15080
|
+
|
|
15081
|
+
## Built-in Extensions
|
|
15082
|
+
|
|
15083
|
+
NetPad includes several built-in extensions:
|
|
15084
|
+
|
|
15085
|
+
### @netpad/cloud-features
|
|
15086
|
+
|
|
15087
|
+
The cloud features extension provides premium functionality for NetPad Cloud:
|
|
15088
|
+
|
|
15089
|
+
* **Billing & Subscriptions** - Stripe integration for payments
|
|
15090
|
+
* **Atlas Provisioning** - Automatic MongoDB cluster creation
|
|
15091
|
+
* **Premium AI Features** - Advanced RAG and AI capabilities
|
|
15092
|
+
* **Usage Analytics** - Detailed usage tracking and reporting
|
|
15093
|
+
|
|
15094
|
+
### @netpad/collaborate
|
|
15095
|
+
|
|
15096
|
+
Community collaboration features:
|
|
15097
|
+
|
|
15098
|
+
* **Gallery** - Community showcase of forms, workflows, and integrations
|
|
15099
|
+
* **Contributors** - Leaderboard and contributor profiles
|
|
15100
|
+
* **Submissions** - Collaboration application system
|
|
15101
|
+
* **UI Components** - Pre-built React components
|
|
15102
|
+
|
|
15103
|
+
### @netpad/demo-node
|
|
15104
|
+
|
|
15105
|
+
A simple demonstration extension that shows how to create custom workflow nodes:
|
|
15106
|
+
|
|
15107
|
+
* **Log Message Node** - A custom workflow node that logs messages with configurable levels
|
|
15108
|
+
* **Template for Extension Development** - Use as a starting point for your own extensions
|
|
15109
|
+
* **Complete Example** - Shows node definition, handler implementation, and extension structure
|
|
15110
|
+
|
|
15111
|
+
**Node Details:**
|
|
15112
|
+
- Type: demo:log-message
|
|
15113
|
+
- Category: Custom
|
|
15114
|
+
- Config Fields: message (textarea), level (select: info/warn/error), label (text), passthrough (boolean)
|
|
15115
|
+
- Outputs: Success output with log data and optional passthrough of input data
|
|
15116
|
+
|
|
15117
|
+
This extension serves as the canonical example for creating workflow node extensions. See the package README for detailed instructions on using it as a template.
|
|
15118
|
+
|
|
15119
|
+
## Extension Architecture
|
|
15120
|
+
|
|
15121
|
+
Extensions follow a clear architectural pattern:
|
|
15122
|
+
|
|
15123
|
+
\`\`\`typescript
|
|
15124
|
+
// Extension structure
|
|
15125
|
+
const myExtension: NetPadExtension = {
|
|
15126
|
+
metadata: {
|
|
15127
|
+
id: 'my-extension',
|
|
15128
|
+
name: 'My Extension',
|
|
15129
|
+
version: '1.0.0',
|
|
15130
|
+
description: 'Description of what this extension does',
|
|
15131
|
+
},
|
|
15132
|
+
|
|
15133
|
+
// Features this extension provides
|
|
15134
|
+
features: ['custom:my_feature'],
|
|
15135
|
+
|
|
15136
|
+
// API routes
|
|
15137
|
+
routes: [
|
|
15138
|
+
{ path: '/api/ext/my-extension/data', method: 'GET', handler: handleGet },
|
|
15139
|
+
{ path: '/api/ext/my-extension/data', method: 'POST', handler: handlePost },
|
|
15140
|
+
],
|
|
15141
|
+
|
|
15142
|
+
// Request middleware
|
|
15143
|
+
middleware: [
|
|
15144
|
+
{ path: '/api/ext/my-extension/*', handler: authMiddleware, priority: 10 },
|
|
15145
|
+
],
|
|
15146
|
+
|
|
15147
|
+
// Shared services
|
|
15148
|
+
services: {
|
|
15149
|
+
myService: myServiceInstance,
|
|
15150
|
+
},
|
|
15151
|
+
|
|
15152
|
+
// Custom workflow nodes
|
|
15153
|
+
workflowNodes: [
|
|
15154
|
+
{
|
|
15155
|
+
definition: {
|
|
15156
|
+
type: 'my-custom-node',
|
|
15157
|
+
name: 'My Custom Node',
|
|
15158
|
+
category: 'custom',
|
|
15159
|
+
description: 'Does something custom',
|
|
15160
|
+
configSchema: { /* ... */ },
|
|
15161
|
+
},
|
|
15162
|
+
handler: async (config, context) => { /* ... */ },
|
|
15163
|
+
},
|
|
15164
|
+
],
|
|
15165
|
+
|
|
15166
|
+
// Lifecycle hooks
|
|
15167
|
+
initialize: async () => { /* Setup logic */ },
|
|
15168
|
+
cleanup: async () => { /* Cleanup logic */ },
|
|
15169
|
+
};
|
|
15170
|
+
\`\`\`
|
|
15171
|
+
|
|
15172
|
+
## Quick Start
|
|
15173
|
+
|
|
15174
|
+
### 1. Enable an Extension
|
|
15175
|
+
|
|
15176
|
+
Add the extension package name to your \`.env.local\`:
|
|
15177
|
+
|
|
15178
|
+
\`\`\`
|
|
15179
|
+
# Enable single extension
|
|
15180
|
+
NETPAD_EXTENSIONS=@netpad/collaborate
|
|
15181
|
+
|
|
15182
|
+
# Enable multiple extensions
|
|
15183
|
+
NETPAD_EXTENSIONS=@netpad/collaborate,@myorg/custom-extension
|
|
15184
|
+
\`\`\`
|
|
15185
|
+
|
|
15186
|
+
### 2. Install the Package
|
|
15187
|
+
|
|
15188
|
+
\`\`\`bash
|
|
15189
|
+
npm install @netpad/collaborate
|
|
15190
|
+
\`\`\`
|
|
15191
|
+
|
|
15192
|
+
### 3. Restart NetPad
|
|
15193
|
+
|
|
15194
|
+
Extensions are loaded during application startup.
|
|
15195
|
+
|
|
15196
|
+
## Creating Custom Extensions
|
|
15197
|
+
|
|
15198
|
+
To create your own extension, use **@netpad/demo-node** as a template:
|
|
15199
|
+
|
|
15200
|
+
1. **Copy the demo-node package** to a new directory
|
|
15201
|
+
2. **Update package.json** with your extension name and metadata
|
|
15202
|
+
3. **Modify src/index.ts**:
|
|
15203
|
+
- Update extension metadata (id, name, version, description)
|
|
15204
|
+
- Define your workflow nodes (type, label, category, config fields)
|
|
15205
|
+
- Implement your node handlers (business logic)
|
|
15206
|
+
- Export the extension as default
|
|
15207
|
+
4. **Install and enable**:
|
|
15208
|
+
- Run: npm install @myorg/my-extension
|
|
15209
|
+
- Add to .env.local: NETPAD_EXTENSIONS=@myorg/my-extension
|
|
15210
|
+
5. **Restart NetPad** - Your extension will be loaded automatically
|
|
15211
|
+
|
|
15212
|
+
### Example: Creating a Custom Workflow Node
|
|
15213
|
+
|
|
15214
|
+
Based on the demo-node structure:
|
|
15215
|
+
|
|
15216
|
+
\`\`\`typescript
|
|
15217
|
+
// 1. Define your node configuration interface
|
|
15218
|
+
interface MyNodeConfig {
|
|
15219
|
+
action: string;
|
|
15220
|
+
target: string;
|
|
15221
|
+
}
|
|
15222
|
+
|
|
15223
|
+
// 2. Implement the node handler
|
|
15224
|
+
const myNodeHandler: NodeHandler = async (context) => {
|
|
15225
|
+
const config = context.resolvedConfig as MyNodeConfig;
|
|
15226
|
+
const inputs = context.inputs;
|
|
15227
|
+
|
|
15228
|
+
// Your business logic here
|
|
15229
|
+
const result = await performAction(config.action, config.target);
|
|
15230
|
+
|
|
15231
|
+
return {
|
|
15232
|
+
success: true,
|
|
15233
|
+
data: { result },
|
|
15234
|
+
metadata: { durationMs: Date.now() - startTime },
|
|
15235
|
+
};
|
|
15236
|
+
};
|
|
15237
|
+
|
|
15238
|
+
// 3. Define the node appearance
|
|
15239
|
+
const myNodeDefinition = {
|
|
15240
|
+
type: 'myext:my-node', // Unique type (convention: extid:nodename)
|
|
15241
|
+
label: 'My Custom Node',
|
|
15242
|
+
description: 'Does something custom',
|
|
15243
|
+
category: 'custom' as const,
|
|
15244
|
+
color: '#FF6B35',
|
|
15245
|
+
icon: 'Extension', // MUI icon name
|
|
15246
|
+
version: '1.0.0',
|
|
15247
|
+
configFields: [
|
|
15248
|
+
{
|
|
15249
|
+
name: 'action',
|
|
15250
|
+
label: 'Action',
|
|
15251
|
+
type: 'select' as const,
|
|
15252
|
+
options: [
|
|
15253
|
+
{ label: 'Create', value: 'create' },
|
|
15254
|
+
{ label: 'Update', value: 'update' },
|
|
15255
|
+
],
|
|
15256
|
+
},
|
|
15257
|
+
{
|
|
15258
|
+
name: 'target',
|
|
15259
|
+
label: 'Target',
|
|
15260
|
+
type: 'text' as const,
|
|
15261
|
+
required: true,
|
|
15262
|
+
},
|
|
15263
|
+
],
|
|
15264
|
+
outputs: [{ id: 'output', label: 'Success', primary: true }],
|
|
15265
|
+
};
|
|
15266
|
+
|
|
15267
|
+
// 4. Export the extension
|
|
15268
|
+
export const myExtension: NetPadExtension = {
|
|
15269
|
+
metadata: {
|
|
15270
|
+
id: 'my-extension',
|
|
15271
|
+
name: 'My Extension',
|
|
15272
|
+
version: '1.0.0',
|
|
15273
|
+
},
|
|
15274
|
+
workflowNodes: [
|
|
15275
|
+
{
|
|
15276
|
+
definition: myNodeDefinition,
|
|
15277
|
+
handler: myNodeHandler,
|
|
15278
|
+
},
|
|
15279
|
+
],
|
|
15280
|
+
initialize: async () => {
|
|
15281
|
+
console.log('[My Extension] Initialized!');
|
|
15282
|
+
},
|
|
15283
|
+
};
|
|
15284
|
+
|
|
15285
|
+
export default myExtension;
|
|
15286
|
+
\`\`\`
|
|
15287
|
+
|
|
15288
|
+
### Node Handler Context
|
|
15289
|
+
|
|
15290
|
+
The handler receives a \`NodeExecutionContext\` with:
|
|
15291
|
+
|
|
15292
|
+
- **config**: Raw configuration from the editor
|
|
15293
|
+
- **resolvedConfig**: Configuration with variables like \`{{formData.email}}\` already resolved
|
|
15294
|
+
- **inputs**: Data from previous nodes in the workflow
|
|
15295
|
+
- **trigger**: Information about what triggered the workflow
|
|
15296
|
+
- **getConnection()**: Helper to get MongoDB connection details
|
|
15297
|
+
- **getEmailCredentials()**: Helper to get email service credentials
|
|
15298
|
+
|
|
15299
|
+
### Node Categories
|
|
15300
|
+
|
|
15301
|
+
When defining your node, choose an appropriate category:
|
|
15302
|
+
|
|
15303
|
+
- **triggers**: Workflow entry points (form submission, webhook, schedule)
|
|
15304
|
+
- **logic**: Control flow (condition, switch, loop, delay)
|
|
15305
|
+
- **integrations**: External services (Slack, email, HTTP)
|
|
15306
|
+
- **actions**: Data operations (MongoDB queries, transforms)
|
|
15307
|
+
- **data**: Data manipulation (set variable, code execution)
|
|
15308
|
+
- **ai**: AI-powered operations (generate, classify, extract)
|
|
15309
|
+
- **forms**: Form-specific operations
|
|
15310
|
+
- **custom**: Custom extensions (use this for your own nodes)
|
|
15311
|
+
- **annotations**: Non-executable nodes (notes, labels)
|
|
15312
|
+
|
|
15313
|
+
## Extension Loading
|
|
15314
|
+
|
|
15315
|
+
Extensions are loaded in this order:
|
|
15316
|
+
|
|
15317
|
+
1. **Cloud Extension** - \`@netpad/cloud-features\` (if \`NETPAD_CLOUD=true\`)
|
|
15318
|
+
2. **Plugin Extensions** - Packages listed in \`NETPAD_EXTENSIONS\`
|
|
15319
|
+
3. **Programmatic Extensions** - Registered via \`registerExtensionManually()\`
|
|
15320
|
+
|
|
15321
|
+
Each extension goes through:
|
|
15322
|
+
|
|
15323
|
+
1. Package resolution and import
|
|
15324
|
+
2. Registration in the extension registry
|
|
15325
|
+
3. Initialization via the \`initialize()\` hook
|
|
15326
|
+
|
|
15327
|
+
## Feature Checking
|
|
15328
|
+
|
|
15329
|
+
Extensions can declare features that other parts of the application can check:
|
|
15330
|
+
|
|
15331
|
+
\`\`\`typescript
|
|
15332
|
+
import { isFeatureAvailable } from '@/lib/extensions/registry';
|
|
15333
|
+
|
|
15334
|
+
// Check if a feature is available
|
|
15335
|
+
if (isFeatureAvailable('billing')) {
|
|
15336
|
+
// Show billing UI
|
|
15337
|
+
}
|
|
15338
|
+
|
|
15339
|
+
// Custom extension features use the custom: prefix
|
|
15340
|
+
if (isFeatureAvailable('custom:collaborate')) {
|
|
15341
|
+
// Show collaborate features
|
|
15342
|
+
}
|
|
15343
|
+
\`\`\`
|
|
15344
|
+
|
|
15345
|
+
## Best Practices
|
|
15346
|
+
|
|
15347
|
+
1. **Use descriptive metadata** - Clear names and descriptions help users understand your extension
|
|
15348
|
+
2. **Namespace your routes** - Always use \`/api/ext/{your-extension}/\` for routes
|
|
15349
|
+
3. **Handle errors gracefully** - Extensions should not crash the main application
|
|
15350
|
+
4. **Clean up resources** - Implement the \`cleanup()\` hook for proper teardown
|
|
15351
|
+
5. **Document your extension** - Provide clear usage instructions and API documentation
|
|
15352
|
+
6. **Test thoroughly** - Extensions run in production, so ensure they're well-tested
|
|
15353
|
+
|
|
15354
|
+
## Extension Types
|
|
15355
|
+
|
|
15356
|
+
### Service Extensions
|
|
15357
|
+
|
|
15358
|
+
Provide business logic services:
|
|
15359
|
+
- Billing service (Stripe integration)
|
|
15360
|
+
- Atlas provisioning service
|
|
15361
|
+
- Usage tracking service
|
|
15362
|
+
- Admin service
|
|
15363
|
+
|
|
15364
|
+
### Feature Extensions
|
|
15365
|
+
|
|
15366
|
+
Add new capabilities:
|
|
15367
|
+
- Custom workflow nodes
|
|
15368
|
+
- Additional form field types
|
|
15369
|
+
- UI components
|
|
15370
|
+
- Integration connectors
|
|
15371
|
+
|
|
15372
|
+
### Middleware Extensions
|
|
15373
|
+
|
|
15374
|
+
Intercept and modify requests:
|
|
15375
|
+
- Authentication middleware
|
|
15376
|
+
- Rate limiting
|
|
15377
|
+
- Request logging
|
|
15378
|
+
- Data transformation
|
|
15379
|
+
|
|
15380
|
+
## API Reference
|
|
15381
|
+
|
|
15382
|
+
See the full extension API documentation at: https://docs.netpad.io/docs/extensions/api-reference
|
|
14991
15383
|
`
|
|
14992
15384
|
};
|
|
14993
15385
|
var QUICK_START_GUIDE = `# Quick Start Guide
|
|
@@ -17537,6 +17929,53 @@ var WORKFLOW_NODE_TYPES = {
|
|
|
17537
17929
|
{ key: "timeout", label: "Timeout (ms)", type: "number", default: 5e3 }
|
|
17538
17930
|
]
|
|
17539
17931
|
}
|
|
17932
|
+
],
|
|
17933
|
+
// Forms (Form Reactions)
|
|
17934
|
+
forms: [
|
|
17935
|
+
{
|
|
17936
|
+
type: "field-event-trigger",
|
|
17937
|
+
name: "Field Event Trigger",
|
|
17938
|
+
description: "Trigger workflow when a form field event occurs (blur, change, focus). Entry point for form reaction workflows.",
|
|
17939
|
+
icon: "bolt",
|
|
17940
|
+
color: "#00BCD4",
|
|
17941
|
+
category: "forms",
|
|
17942
|
+
stage: "trigger",
|
|
17943
|
+
inputs: [],
|
|
17944
|
+
outputs: [
|
|
17945
|
+
{ id: "triggerField", label: "Trigger Field", type: "string" },
|
|
17946
|
+
{ id: "triggerEvent", label: "Event Type", type: "string" },
|
|
17947
|
+
{ id: "fieldValue", label: "Field Value", type: "any" },
|
|
17948
|
+
{ id: "formData", label: "Form Data", type: "object" },
|
|
17949
|
+
{ id: "formId", label: "Form ID", type: "string" },
|
|
17950
|
+
{ id: "reactionId", label: "Reaction ID", type: "string" }
|
|
17951
|
+
],
|
|
17952
|
+
configFields: [
|
|
17953
|
+
{ key: "formId", label: "Form ID", type: "string", required: false },
|
|
17954
|
+
{ key: "triggerMode", label: "Trigger Mode", type: "select", options: ["any", "all"], default: "any" },
|
|
17955
|
+
{ key: "debounceMs", label: "Debounce (ms)", type: "number", default: 0 }
|
|
17956
|
+
]
|
|
17957
|
+
},
|
|
17958
|
+
{
|
|
17959
|
+
type: "form-field-update",
|
|
17960
|
+
name: "Form Field Update",
|
|
17961
|
+
description: "Update form fields with workflow data. Maps workflow outputs to form fields for real-time updates.",
|
|
17962
|
+
icon: "edit_note",
|
|
17963
|
+
color: "#00BCD4",
|
|
17964
|
+
category: "forms",
|
|
17965
|
+
stage: "action",
|
|
17966
|
+
inputs: [{ id: "data", label: "Input Data", type: "object" }],
|
|
17967
|
+
outputs: [
|
|
17968
|
+
{ id: "success", label: "Success", type: "boolean" },
|
|
17969
|
+
{ id: "updates", label: "Updates", type: "object" },
|
|
17970
|
+
{ id: "updatedFields", label: "Updated Fields", type: "array" },
|
|
17971
|
+
{ id: "skippedFields", label: "Skipped Fields", type: "array" }
|
|
17972
|
+
],
|
|
17973
|
+
configFields: [
|
|
17974
|
+
{ key: "feedbackMode", label: "Feedback Mode", type: "select", options: ["silent", "subtle", "toast"], default: "silent" },
|
|
17975
|
+
{ key: "validateAfterUpdate", label: "Validate After Update", type: "boolean", default: false },
|
|
17976
|
+
{ key: "updates", label: "Field Mappings", type: "array", itemType: "object", required: true }
|
|
17977
|
+
]
|
|
17978
|
+
}
|
|
17540
17979
|
]
|
|
17541
17980
|
};
|
|
17542
17981
|
var WORKFLOW_TEMPLATES = {
|
|
@@ -17798,6 +18237,126 @@ var WORKFLOW_TEMPLATES = {
|
|
|
17798
18237
|
targetHandle: "data"
|
|
17799
18238
|
}
|
|
17800
18239
|
]
|
|
18240
|
+
},
|
|
18241
|
+
"company-lookup-reaction": {
|
|
18242
|
+
id: "company-lookup-reaction",
|
|
18243
|
+
name: "Company Domain Lookup Reaction",
|
|
18244
|
+
description: "Form reaction that fetches company data when user enters a domain and auto-fills related fields",
|
|
18245
|
+
category: "forms",
|
|
18246
|
+
tags: ["reaction", "forms", "auto-fill", "api"],
|
|
18247
|
+
nodes: [
|
|
18248
|
+
{
|
|
18249
|
+
id: "trigger_1",
|
|
18250
|
+
type: "field-event-trigger",
|
|
18251
|
+
label: "Domain Field Event",
|
|
18252
|
+
position: { x: 100, y: 200 },
|
|
18253
|
+
config: { triggerMode: "any", debounceMs: 500 },
|
|
18254
|
+
enabled: true
|
|
18255
|
+
},
|
|
18256
|
+
{
|
|
18257
|
+
id: "http_1",
|
|
18258
|
+
type: "http-request",
|
|
18259
|
+
label: "Fetch Company Data",
|
|
18260
|
+
position: { x: 350, y: 200 },
|
|
18261
|
+
config: {
|
|
18262
|
+
url: "https://api.example.com/company?domain={{nodes.trigger_1.fieldValue}}",
|
|
18263
|
+
method: "GET",
|
|
18264
|
+
headers: { "Accept": "application/json" }
|
|
18265
|
+
},
|
|
18266
|
+
enabled: true
|
|
18267
|
+
},
|
|
18268
|
+
{
|
|
18269
|
+
id: "update_1",
|
|
18270
|
+
type: "form-field-update",
|
|
18271
|
+
label: "Update Form Fields",
|
|
18272
|
+
position: { x: 600, y: 200 },
|
|
18273
|
+
config: {
|
|
18274
|
+
feedbackMode: "subtle",
|
|
18275
|
+
validateAfterUpdate: false,
|
|
18276
|
+
updates: [
|
|
18277
|
+
{ fieldPath: "companyName", sourcePath: "http_1.response.name", nullBehavior: "skip" },
|
|
18278
|
+
{ fieldPath: "industry", sourcePath: "http_1.response.industry", nullBehavior: "skip" },
|
|
18279
|
+
{ fieldPath: "employeeCount", sourcePath: "http_1.response.size", nullBehavior: "skip" }
|
|
18280
|
+
]
|
|
18281
|
+
},
|
|
18282
|
+
enabled: true
|
|
18283
|
+
}
|
|
18284
|
+
],
|
|
18285
|
+
edges: [
|
|
18286
|
+
{
|
|
18287
|
+
id: "edge_1",
|
|
18288
|
+
source: "trigger_1",
|
|
18289
|
+
sourceHandle: "fieldValue",
|
|
18290
|
+
target: "http_1",
|
|
18291
|
+
targetHandle: "body"
|
|
18292
|
+
},
|
|
18293
|
+
{
|
|
18294
|
+
id: "edge_2",
|
|
18295
|
+
source: "http_1",
|
|
18296
|
+
sourceHandle: "response",
|
|
18297
|
+
target: "update_1",
|
|
18298
|
+
targetHandle: "data"
|
|
18299
|
+
}
|
|
18300
|
+
]
|
|
18301
|
+
},
|
|
18302
|
+
"ai-categorization-reaction": {
|
|
18303
|
+
id: "ai-categorization-reaction",
|
|
18304
|
+
name: "AI Field Categorization Reaction",
|
|
18305
|
+
description: "Form reaction that uses AI to categorize text input and auto-fills category field",
|
|
18306
|
+
category: "forms",
|
|
18307
|
+
tags: ["reaction", "forms", "ai", "classification"],
|
|
18308
|
+
nodes: [
|
|
18309
|
+
{
|
|
18310
|
+
id: "trigger_1",
|
|
18311
|
+
type: "field-event-trigger",
|
|
18312
|
+
label: "Description Field Event",
|
|
18313
|
+
position: { x: 100, y: 200 },
|
|
18314
|
+
config: { triggerMode: "any", debounceMs: 1e3 },
|
|
18315
|
+
enabled: true
|
|
18316
|
+
},
|
|
18317
|
+
{
|
|
18318
|
+
id: "classify_1",
|
|
18319
|
+
type: "ai-classify",
|
|
18320
|
+
label: "Classify Content",
|
|
18321
|
+
position: { x: 350, y: 200 },
|
|
18322
|
+
config: {
|
|
18323
|
+
categories: ["Technical Support", "Billing", "Feature Request", "Bug Report", "General Inquiry"],
|
|
18324
|
+
instructions: "Classify the support ticket based on its description."
|
|
18325
|
+
},
|
|
18326
|
+
enabled: true
|
|
18327
|
+
},
|
|
18328
|
+
{
|
|
18329
|
+
id: "update_1",
|
|
18330
|
+
type: "form-field-update",
|
|
18331
|
+
label: "Update Category",
|
|
18332
|
+
position: { x: 600, y: 200 },
|
|
18333
|
+
config: {
|
|
18334
|
+
feedbackMode: "subtle",
|
|
18335
|
+
validateAfterUpdate: false,
|
|
18336
|
+
updates: [
|
|
18337
|
+
{ fieldPath: "category", sourcePath: "classify_1.category", nullBehavior: "skip" },
|
|
18338
|
+
{ fieldPath: "aiConfidence", sourcePath: "classify_1.confidence", nullBehavior: "skip" }
|
|
18339
|
+
]
|
|
18340
|
+
},
|
|
18341
|
+
enabled: true
|
|
18342
|
+
}
|
|
18343
|
+
],
|
|
18344
|
+
edges: [
|
|
18345
|
+
{
|
|
18346
|
+
id: "edge_1",
|
|
18347
|
+
source: "trigger_1",
|
|
18348
|
+
sourceHandle: "fieldValue",
|
|
18349
|
+
target: "classify_1",
|
|
18350
|
+
targetHandle: "text"
|
|
18351
|
+
},
|
|
18352
|
+
{
|
|
18353
|
+
id: "edge_2",
|
|
18354
|
+
source: "classify_1",
|
|
18355
|
+
sourceHandle: "category",
|
|
18356
|
+
target: "update_1",
|
|
18357
|
+
targetHandle: "data"
|
|
18358
|
+
}
|
|
18359
|
+
]
|
|
17801
18360
|
}
|
|
17802
18361
|
};
|
|
17803
18362
|
function generateAddNodeCode(workflowId, node) {
|
|
@@ -20651,6 +21210,135 @@ server.resource(
|
|
|
20651
21210
|
]
|
|
20652
21211
|
})
|
|
20653
21212
|
);
|
|
21213
|
+
server.resource(
|
|
21214
|
+
"netpad-extensions",
|
|
21215
|
+
"netpad://docs/extensions",
|
|
21216
|
+
async () => ({
|
|
21217
|
+
contents: [
|
|
21218
|
+
{
|
|
21219
|
+
uri: "netpad://docs/extensions",
|
|
21220
|
+
mimeType: "text/markdown",
|
|
21221
|
+
text: DOCUMENTATION.extensions
|
|
21222
|
+
}
|
|
21223
|
+
]
|
|
21224
|
+
})
|
|
21225
|
+
);
|
|
21226
|
+
server.resource(
|
|
21227
|
+
"netpad-demo-node",
|
|
21228
|
+
"netpad://examples/demo-node",
|
|
21229
|
+
async () => ({
|
|
21230
|
+
contents: [
|
|
21231
|
+
{
|
|
21232
|
+
uri: "netpad://examples/demo-node",
|
|
21233
|
+
mimeType: "text/markdown",
|
|
21234
|
+
text: `# @netpad/demo-node Extension Example
|
|
21235
|
+
|
|
21236
|
+
The demo-node extension is a complete, working example of how to create NetPad workflow node extensions. Use it as a template for your own extensions.
|
|
21237
|
+
|
|
21238
|
+
## What It Provides
|
|
21239
|
+
|
|
21240
|
+
A single workflow node called **"Log Message"** that:
|
|
21241
|
+
- Logs configurable messages to the console
|
|
21242
|
+
- Supports different log levels (info, warn, error)
|
|
21243
|
+
- Can pass through input data to downstream nodes
|
|
21244
|
+
- Demonstrates all key extension concepts
|
|
21245
|
+
|
|
21246
|
+
## Node Details
|
|
21247
|
+
|
|
21248
|
+
**Type:** \`demo:log-message\`
|
|
21249
|
+
**Category:** Custom
|
|
21250
|
+
**Icon:** Terminal (MUI icon)
|
|
21251
|
+
**Color:** #FF6B35 (orange)
|
|
21252
|
+
|
|
21253
|
+
### Configuration Fields
|
|
21254
|
+
|
|
21255
|
+
| Field | Type | Description |
|
|
21256
|
+
|-------|------|-------------|
|
|
21257
|
+
| Message | textarea | The message to log. Supports \`{{variable}}\` syntax for dynamic values |
|
|
21258
|
+
| Log Level | select | info, warn, or error |
|
|
21259
|
+
| Label | text | Custom label for the log entry |
|
|
21260
|
+
| Pass Through | boolean | Include input data in output (default: true) |
|
|
21261
|
+
|
|
21262
|
+
### Example Usage
|
|
21263
|
+
|
|
21264
|
+
1. Drag the "Log Message" node onto the workflow canvas
|
|
21265
|
+
2. Connect it after a form trigger or other node
|
|
21266
|
+
3. Configure the message: \`New submission from {{formData.email}}\`
|
|
21267
|
+
4. The node will log the message and pass data to the next node
|
|
21268
|
+
|
|
21269
|
+
## Using as a Template
|
|
21270
|
+
|
|
21271
|
+
1. **Copy the package** to a new directory
|
|
21272
|
+
2. **Update package.json** with your extension name
|
|
21273
|
+
3. **Modify src/index.ts**:
|
|
21274
|
+
- Change extension metadata (id, name, version)
|
|
21275
|
+
- Update node definition (type, label, icon, color, config fields)
|
|
21276
|
+
- Implement your business logic in the handler
|
|
21277
|
+
4. **Export the extension** as default export
|
|
21278
|
+
|
|
21279
|
+
## Key Concepts Demonstrated
|
|
21280
|
+
|
|
21281
|
+
- **Extension Metadata**: Identifies your extension in the system
|
|
21282
|
+
- **Workflow Nodes**: Custom nodes that appear in the workflow editor palette
|
|
21283
|
+
- **Node Definition**: Describes the node's appearance and configuration UI
|
|
21284
|
+
- **Node Handler**: The function that executes when the node runs
|
|
21285
|
+
- **Configuration Fields**: UI fields for node configuration
|
|
21286
|
+
- **Output Handles**: Connection points for downstream nodes
|
|
21287
|
+
- **Lifecycle Hooks**: initialize() and cleanup() functions
|
|
21288
|
+
|
|
21289
|
+
## File Structure
|
|
21290
|
+
|
|
21291
|
+
\`\`\`
|
|
21292
|
+
packages/demo-node/
|
|
21293
|
+
\u251C\u2500\u2500 package.json # Package metadata
|
|
21294
|
+
\u251C\u2500\u2500 README.md # Documentation
|
|
21295
|
+
\u2514\u2500\u2500 src/
|
|
21296
|
+
\u2514\u2500\u2500 index.ts # Extension + node definition + handler
|
|
21297
|
+
\`\`\`
|
|
21298
|
+
|
|
21299
|
+
## Extension Structure
|
|
21300
|
+
|
|
21301
|
+
\`\`\`typescript
|
|
21302
|
+
export const demoNodeExtension: NetPadExtension = {
|
|
21303
|
+
metadata: {
|
|
21304
|
+
id: 'netpad-demo-node',
|
|
21305
|
+
name: 'Demo Node Extension',
|
|
21306
|
+
version: '1.0.0',
|
|
21307
|
+
},
|
|
21308
|
+
features: ['custom:demo-node'],
|
|
21309
|
+
workflowNodes: [
|
|
21310
|
+
{
|
|
21311
|
+
definition: {
|
|
21312
|
+
type: 'demo:log-message',
|
|
21313
|
+
label: 'Log Message',
|
|
21314
|
+
category: 'custom',
|
|
21315
|
+
// ... node appearance config
|
|
21316
|
+
},
|
|
21317
|
+
handler: async (context) => {
|
|
21318
|
+
// ... execution logic
|
|
21319
|
+
return { success: true, data: {...} };
|
|
21320
|
+
},
|
|
21321
|
+
},
|
|
21322
|
+
],
|
|
21323
|
+
initialize: async () => { /* setup */ },
|
|
21324
|
+
cleanup: async () => { /* teardown */ },
|
|
21325
|
+
};
|
|
21326
|
+
\`\`\`
|
|
21327
|
+
|
|
21328
|
+
## Handler Implementation
|
|
21329
|
+
|
|
21330
|
+
The handler receives a \`NodeExecutionContext\` with:
|
|
21331
|
+
- \`resolvedConfig\`: Configuration with variables resolved
|
|
21332
|
+
- \`inputs\`: Data from previous nodes
|
|
21333
|
+
- \`trigger\`: Workflow trigger information
|
|
21334
|
+
- Helper functions for connections and credentials
|
|
21335
|
+
|
|
21336
|
+
See the full source code in \`packages/demo-node/src/index.ts\` for complete implementation details.
|
|
21337
|
+
`
|
|
21338
|
+
}
|
|
21339
|
+
]
|
|
21340
|
+
})
|
|
21341
|
+
);
|
|
20654
21342
|
server.tool(
|
|
20655
21343
|
"generate_form",
|
|
20656
21344
|
"Generate a complete NetPad form configuration from a description. Returns validated TypeScript code by default (can optionally return JSON). The TypeScript output includes inline types, form config, and API functions - ready to run with `npx tsx`.",
|
|
@@ -21200,7 +21888,18 @@ server.tool(
|
|
|
21200
21888
|
}]
|
|
21201
21889
|
};
|
|
21202
21890
|
}
|
|
21203
|
-
|
|
21891
|
+
const workflowForUI = {
|
|
21892
|
+
id: template.id,
|
|
21893
|
+
name: template.name,
|
|
21894
|
+
description: template.description,
|
|
21895
|
+
category: template.category,
|
|
21896
|
+
tags: template.tags,
|
|
21897
|
+
canvas: {
|
|
21898
|
+
nodes: template.nodes,
|
|
21899
|
+
edges: template.edges
|
|
21900
|
+
}
|
|
21901
|
+
};
|
|
21902
|
+
return { content: [{ type: "text", text: JSON.stringify(workflowForUI, null, 2) }] };
|
|
21204
21903
|
}
|
|
21205
21904
|
let templates = Object.values(WORKFLOW_TEMPLATES);
|
|
21206
21905
|
if (category) {
|
|
@@ -23202,10 +23901,21 @@ server.tool(
|
|
|
23202
23901
|
}]
|
|
23203
23902
|
};
|
|
23204
23903
|
}
|
|
23904
|
+
const workflowForUI = {
|
|
23905
|
+
id: template.id,
|
|
23906
|
+
name: template.name,
|
|
23907
|
+
description: template.description,
|
|
23908
|
+
category: template.category,
|
|
23909
|
+
tags: template.tags,
|
|
23910
|
+
canvas: {
|
|
23911
|
+
nodes: template.nodes,
|
|
23912
|
+
edges: template.edges
|
|
23913
|
+
}
|
|
23914
|
+
};
|
|
23205
23915
|
return {
|
|
23206
23916
|
content: [{
|
|
23207
23917
|
type: "text",
|
|
23208
|
-
text: JSON.stringify(
|
|
23918
|
+
text: JSON.stringify(workflowForUI, null, 2)
|
|
23209
23919
|
}]
|
|
23210
23920
|
};
|
|
23211
23921
|
}
|
|
@@ -23308,8 +24018,10 @@ const WORKFLOW_CONFIG: WorkflowConfig = {
|
|
|
23308
24018
|
name: ${JSON.stringify(name)},
|
|
23309
24019
|
description: ${JSON.stringify(description || template?.description || "Custom workflow")},
|
|
23310
24020
|
tags: ${JSON.stringify(tags || template?.tags || [])},
|
|
23311
|
-
|
|
23312
|
-
|
|
24021
|
+
canvas: {
|
|
24022
|
+
nodes: ${JSON.stringify(updatedNodes, null, 2)},
|
|
24023
|
+
edges: ${JSON.stringify(workflowEdges, null, 2)},
|
|
24024
|
+
},
|
|
23313
24025
|
settings: {
|
|
23314
24026
|
executionMode: 'auto',
|
|
23315
24027
|
maxExecutionTime: 300000,
|
|
@@ -23646,15 +24358,33 @@ ${code}
|
|
|
23646
24358
|
server.resource(
|
|
23647
24359
|
"netpad-workflow-templates",
|
|
23648
24360
|
"netpad://reference/workflow-templates",
|
|
23649
|
-
async () =>
|
|
23650
|
-
|
|
23651
|
-
|
|
23652
|
-
|
|
23653
|
-
|
|
23654
|
-
|
|
23655
|
-
|
|
23656
|
-
|
|
23657
|
-
|
|
24361
|
+
async () => {
|
|
24362
|
+
const templatesForUI = Object.fromEntries(
|
|
24363
|
+
Object.entries(WORKFLOW_TEMPLATES).map(([key, template]) => [
|
|
24364
|
+
key,
|
|
24365
|
+
{
|
|
24366
|
+
id: template.id,
|
|
24367
|
+
name: template.name,
|
|
24368
|
+
description: template.description,
|
|
24369
|
+
category: template.category,
|
|
24370
|
+
tags: template.tags,
|
|
24371
|
+
canvas: {
|
|
24372
|
+
nodes: template.nodes,
|
|
24373
|
+
edges: template.edges
|
|
24374
|
+
}
|
|
24375
|
+
}
|
|
24376
|
+
])
|
|
24377
|
+
);
|
|
24378
|
+
return {
|
|
24379
|
+
contents: [
|
|
24380
|
+
{
|
|
24381
|
+
uri: "netpad://reference/workflow-templates",
|
|
24382
|
+
mimeType: "application/json",
|
|
24383
|
+
text: JSON.stringify(templatesForUI, null, 2)
|
|
24384
|
+
}
|
|
24385
|
+
]
|
|
24386
|
+
};
|
|
24387
|
+
}
|
|
23658
24388
|
);
|
|
23659
24389
|
server.resource(
|
|
23660
24390
|
"netpad-workflow-nodes",
|
|
@@ -23750,7 +24480,7 @@ server.tool(
|
|
|
23750
24480
|
})).describe("Topics to cover in conversation"),
|
|
23751
24481
|
extractionSchema: external_exports.array(external_exports.object({
|
|
23752
24482
|
field: external_exports.string().describe("Field name"),
|
|
23753
|
-
type: external_exports.enum(["string", "number", "boolean", "enum", "array", "object"]).describe("Field type"),
|
|
24483
|
+
type: external_exports.enum(["string", "number", "boolean", "enum", "array", "object", "file"]).describe("Field type"),
|
|
23754
24484
|
required: external_exports.boolean().describe("Whether required"),
|
|
23755
24485
|
description: external_exports.string().describe("Field description"),
|
|
23756
24486
|
options: external_exports.array(external_exports.string()).optional().describe("Options for enum type"),
|