Skip to content

Commit 25ffa21

Browse files
Merge pull request #320 from nocodb/scripts-update
2 parents a926ae3 + a0e8f9d commit 25ffa21

File tree

6 files changed

+161
-5
lines changed

6 files changed

+161
-5
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
---
2+
title: 'External Packages'
3+
description: 'Documentation for the external packages in NocoDB Scripts'
4+
icon: 'code'
5+
---
6+
7+
NocoDB Scripts supports importing external JavaScript packages using **dynamic imports**, allowing you to leverage NPM libraries in your scripts.
8+
9+
<Callout type="info">
10+
External packages are only available in browser environment and does not work in Webhook Scripts.
11+
</Callout>
12+
13+
<Callout type="warning">
14+
**Important:** Only dynamic imports using `import()` are supported. Static imports (e.g., `import _ from 'lodash'`) are not supported.
15+
</Callout>
16+
17+
### Which type of imports are supported?
18+
19+
Only dynamic imports using `import()` are supported. Static imports (`import ... from '...'`) will not work.
20+
21+
### Can I import any NPM package?
22+
23+
Not all packages will work.
24+
25+
**Works:** Pure JavaScript/ESM libraries (e.g., lodash, dayjs, uuid, zod, axios).
26+
27+
**Doesn't work:** Packages that require DOM (react-dom, jquery, chart.js) or Node.js APIs (fs, net, crypto Node module, express, sharp).
28+
29+
**Tip:** If it runs inside a Web Worker, it will usually work in NocoDB Scripts.
30+
31+
### Why do some packages fail in NocoDB Scripts?
32+
33+
Scripts run in a Web Worker sandbox. This environment:
34+
- Has no DOM (`document`, `window`, `HTMLElement`).
35+
- Has no Node APIs (`fs`, `process`, `child_process`, native addons).
36+
- Disallows synchronous browser storage (`localStorage`, `document.cookie`).
37+
38+
### How do I import multiple packages?
39+
40+
Use separate dynamic imports:
41+
```javascript
42+
const _ = (await import('lodash')).default;
43+
const dayjs = (await import('dayjs')).default;
44+
```
45+
46+
### Do I need .default after import?
47+
48+
Many CDN-transpiled packages expose the default export at `.default`. If you see `undefined`, try:
49+
```javascript
50+
const dayjs = (await import('dayjs')).default;
51+
```
52+
53+
### How do I pin a specific package version?
54+
55+
Include a version or semver tag in the CDN URL to avoid breaking changes.
56+
```javascript
57+
const _ = (await import('https://esm.sh/lodash@4.17.21')).default;
58+
```
59+
60+
### Common gotchas & troubleshooting
61+
62+
- **Named vs default exports:** Check the package's docs; you might need named imports:
63+
```javascript
64+
const { nanoid } = await import('nanoid');
65+
const { z } = await import('zod');
66+
```
67+
- **Tree-shaking:** Import subpaths when available for smaller bundles (e.g., lodash-es functions).
68+
69+
### Examples that work well
70+
71+
- lodash / lodash-es
72+
- dayjs
73+
- zod
74+
- uuid
75+
- axios (uses fetch in browsers)
76+
77+
### Examples that won't work
78+
79+
- react-dom, jquery, chart.js, leaflet (DOM-bound)
80+
- express, fs-extra, sharp, sqlite3 (Node-only)
81+
- js-cookie (needs document.cookie)
82+
83+
### Security considerations
84+
85+
- Prefer pinned versions.
86+
- Review package reputation; avoid importing untrusted code at runtime.
87+
- Validate and sanitize any data flowing into third‑party libs.
88+
89+
### Example: Full flow
90+
91+
```javascript
92+
// Load external libs
93+
const _ = (await import('https://esm.sh/lodash@4.17.21')).default;
94+
const dayjs = (await import('https://esm.sh/dayjs@1')).default;
95+
96+
// Query data
97+
const customers = base.getTable('Customers');
98+
const recordQueryResult = await customers.selectRecordsAsync();
99+
100+
// Group and format
101+
const groupedByStatus = _.groupBy(recordQueryResult.records, r => r.getCellValue('Status'));
102+
for (const [status, customers] of Object.entries(groupedByStatus)) {
103+
output.text(`${status}: ${recordQueryResult.records.length} customers`);
104+
}
105+
output.text(`Report generated on: ${dayjs().format('MMMM D, YYYY')}`);
106+
```

content/scripts/api-reference/index.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ description: 'Explore the NocoDB Scripts API for advanced automation and integra
2121

2222
### External Integration
2323
- [Remote Fetch](/docs/scripts/api-reference/fetch) - HTTP requests, external APIs, and NocoDB REST API proxy
24-
- [Script Settings](/docs/scripts/api-reference/script-settings) - Configuration and environment variables
24+
- [Script Settings](/docs/scripts/api-reference/script-settings) - Configuration and environment variables
25+
- [External Packages](/docs/scripts/api-reference/external-packages) - Import and use popular NPM packages from CDN

content/scripts/api-reference/input.mdx

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ Prompts the user to enter text.
2525

2626
**Parameters:**
2727
- `label` (`string`): The prompt text to display to the user
28+
- `options` (`object`, optional): Additional options for the text input
29+
- `defaultValue` (`string`, optional): Default value for the text input
2830

2931
**Returns:** `Promise<string>` - A promise that resolves to the text entered by the user
3032

@@ -34,9 +36,13 @@ Prompts the user to enter text.
3436
const name = await input.textAsync('What is your name?');
3537
output.text(`Hello, ${name}!`);
3638

37-
// Ask for an email subject
38-
const subject = await input.textAsync('Enter email subject:');
39+
// Ask for an email subject with a default value
40+
const subject = await input.textAsync('Enter email subject:', {defaultValue: 'Monthly Newsletter'});
3941
output.text(`Email subject: ${subject}`);
42+
43+
// Ask for user's name with a default
44+
const userName = await input.textAsync('What is your name?', {defaultValue: 'Anonymous'});
45+
output.text(`Hello, ${userName}!`);
4046
```
4147

4248
**Output:**
@@ -99,6 +105,7 @@ Presents a dropdown menu of options for the user to choose from.
99105
**Parameters:**
100106
- `label` (`string`): The prompt text to display to the user
101107
- `options` (`Array<string | { label: string, value: any }>`): An array of options, either as strings or objects with label and value properties
108+
- `defaultValue` (any, optional): Default selected value
102109

103110
**Returns:** `Promise<any>` - A promise that resolves to the value of the selected option
104111

@@ -110,6 +117,14 @@ const department = await input.selectAsync(
110117
['Marketing', 'Sales', 'Engineering', 'Customer Support', 'Finance', 'HR']
111118
);
112119
output.text(`Selected department: ${department}`);
120+
121+
// Ask user to select a department with a default value
122+
const dept = await input.selectAsync(
123+
'Select a department:',
124+
['Marketing', 'Sales', 'Engineering', 'Customer Support', 'Finance', 'HR'],
125+
'Engineering' // default value
126+
);
127+
output.text(`Selected department: ${dept}`);
113128
```
114129

115130
**Output:**
@@ -127,6 +142,18 @@ const priority = await input.selectAsync(
127142
]
128143
);
129144
output.text(`Selected priority level: ${priority}`);
145+
146+
// Ask user to select a priority level with a default value
147+
const priorityLevel = await input.selectAsync(
148+
'Select priority level:',
149+
[
150+
{ label: 'High (Urgent)', value: 3 },
151+
{ label: 'Medium (Normal)', value: 2 },
152+
{ label: 'Low (When time permits)', value: 1 }
153+
],
154+
2 // default value (Medium)
155+
);
156+
output.text(`Selected priority level: ${priorityLevel}`);
130157
```
131158

132159
**Output:**

content/scripts/api-reference/meta.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"script-steps",
1616
"input",
1717
"output",
18-
"fetch"
18+
"fetch",
19+
"external-packages"
1920
]
2021
}

content/scripts/changelog.mdx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,26 @@ icon: 'clock'
66

77
This page documents all changes to the NocoDB Scripts API, including new features, improvements, bug fixes, and breaking changes.
88

9+
## October 03, 2025
10+
11+
#### Input Methods Enhancement
12+
- **Default Values for `input.textAsync()`** - Added optional `defaultValue` parameter in options object
13+
- Example: `await input.textAsync('Enter name:', {defaultValue: 'Anonymous'})`
14+
- Pre-fills the input field with a default value that users can accept or modify
15+
- **Default Values for `input.selectAsync()`** - Added optional `defaultValue` parameter
16+
- Example: `await input.selectAsync('Select option:', options, defaultValue)`
17+
- Pre-selects an option in the dropdown menu
18+
19+
#### External Package Imports
20+
- **Dynamic Import Support** - Scripts can now import external JavaScript packages from CDN using dynamic imports
21+
- Use `await import('package-name')` syntax to load external libraries
22+
- Example: `const _ = await import('lodash')` or `const dayjs = await import('dayjs')`
23+
- Supports popular CDNs: esm.sh (default), unpkg, skypack, jsdelivr
24+
- Enables use of libraries like lodash, dayjs, axios, etc.
25+
- **Note:** Only dynamic imports are supported; static imports are not available
26+
27+
---
28+
929
## July 28, 2025
1030

1131

content/scripts/index.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ NocoDB Scripts is a powerful automation engine that allows you to write JavaScri
1616
- **Database Access**: Query tables and views, create, update, and delete records
1717
- **User Interaction**: Collect input from users with interactive prompts
1818
- **External Integration**: Connect to third-party services via HTTP requests
19+
- **External Package Imports**: Import and use NPM packages from CDN (lodash, dayjs, etc.)
1920
- **Visual Output**: Display results in formatted tables, markdown, and more
2021
- **TypeScript Support**: Enjoy code completion and type checking in the script editor
2122

@@ -102,5 +103,5 @@ if (count > 0) {
102103
- **Input**: Collect user input with interactive prompts and file uploads
103104
- **Output**: Display formatted results with text, markdown, tables, and progress indicators
104105
- **API Integration**: Connect to external services and NocoDB's REST APIs
105-
106+
- **External Packages**: Import and use NPM packages
106107

0 commit comments

Comments
 (0)