Browse Source

fix: Miscellaneous bugs (#9149)

* feat: support pretty print in webhook json

* fix: on renaming table update default view name as well

* fix: show default view name alias as 'Default view'

* fix:  chunk loading error handling

* fix: global error boundary handling improvements

* fix: typo correction

* chore: sentry integration

* refactor: destroy the toast message after reload

* chore: add missing dependencies

Signed-off-by: Pranav C <pranavxc@gmail.com>

* chore: sentry error reporting

Signed-off-by: Pranav C <pranavxc@gmail.com>

* refactor: improved error toast message

Signed-off-by: Pranav C <pranavxc@gmail.com>

* refactor: timeout correction

Signed-off-by: Pranav C <pranavxc@gmail.com>

---------

Signed-off-by: Pranav C <pranavxc@gmail.com>
Co-authored-by: Raju Udava <86527202+dstala@users.noreply.github.com>
pull/9170/head
Pranav C 4 months ago committed by GitHub
parent
commit
d4f76d348a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      packages/nc-gui/components/dlg/ViewDelete.vue
  2. 5
      packages/nc-gui/components/dlg/share-and-collaborate/View.vue
  3. 201
      packages/nc-gui/components/nc/ErrorBoundary.vue
  4. 3
      packages/nc-gui/components/smartsheet/column/LinkedToAnotherRecordOptions.vue
  5. 1
      packages/nc-gui/composables/useGlobal/state.ts
  6. 1
      packages/nc-gui/composables/useGlobal/types.ts
  7. 1
      packages/nc-gui/lang/en.json
  8. 2
      packages/nc-gui/package.json
  9. 21
      packages/nc-gui/plugins/error-handler.ts
  10. 69
      packages/nc-gui/plugins/sentry.ts
  11. 7
      packages/noco-docs/docs/020.getting-started/050.self-hosted/020.environment-variables.md
  12. 105
      packages/noco-docs/versioned_docs/version-0.109.7/020.getting-started/020.environment-variables.md
  13. 184
      packages/nocodb-sdk/src/lib/Api.ts
  14. 2
      packages/nocodb/package.json
  15. 6
      packages/nocodb/src/helpers/webhookHelpers.ts
  16. 10
      packages/nocodb/src/models/Model.ts
  17. 5
      packages/nocodb/src/schema/swagger-v2.json
  18. 5
      packages/nocodb/src/schema/swagger.json
  19. 1
      packages/nocodb/src/services/utils.service.ts
  20. 1110
      pnpm-lock.yaml

5
packages/nc-gui/components/dlg/ViewDelete.vue

@ -52,7 +52,10 @@ async function onDelete() {
class="capitalize text-ellipsis overflow-hidden select-none w-full pl-3"
:style="{ wordBreak: 'keep-all', whiteSpace: 'nowrap', display: 'inline' }"
>
{{ view.title }}
<span v-if="view.is_default">{{ $t('labels.defaultView') }}</span>
<span v-else>
{{ view.title }}
</span>
</div>
</div>
</template>

5
packages/nc-gui/components/dlg/share-and-collaborate/View.vue

@ -147,7 +147,10 @@ watch(showShareModal, (val) => {
class="max-w-79/100 ml-2 px-2 py-0.5 rounded-md bg-gray-100 capitalize text-ellipsis overflow-hidden"
:style="{ wordBreak: 'keep-all', whiteSpace: 'nowrap' }"
>
{{ activeView.title }}
<span v-if="activeView.is_default">{{ $t('labels.defaultView') }}</span>
<span v-else>
{{ activeView.title }}
</span>
</div>
</div>
<DlgShareAndCollaborateSharePage />

201
packages/nc-gui/components/nc/ErrorBoundary.vue

@ -1,6 +1,9 @@
<script lang="ts">
// modified version of default NuxtErrorBoundary component - https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/components/nuxt-error-boundary.ts
import { message } from 'ant-design-vue'
import * as Sentry from '@sentry/vue'
const MESSAGE_KEY = 'ErrorMessageKey'
export default {
emits: {
@ -14,14 +17,114 @@ export default {
const prevError = ref()
const errModal = computed(() => !!error.value)
const key = ref(0)
const repeated: Record<string, number> = {}
const isErrorExpanded = ref(false)
const { copy } = useCopy()
const reload = () => {
error.value = null
key.value++
// destroy the toast message
message.destroy(MESSAGE_KEY)
}
const navigateToHome = () => {
error.value = null
location.hash = '/'
location.reload()
}
const close = () => {
error.value = null
// destroy the toast message
message.destroy(MESSAGE_KEY)
}
onErrorCaptured((err) => {
if (import.meta.client && (!nuxtApp.isHydrating || !nuxtApp.payload.serverRendered)) {
console.error('UI Error :', err)
emit('error', err)
error.value = err
repeated[err.message] = (repeated[err.message] || 0) + 1
// reset repeated count after 30 seconds
setTimeout(() => {
repeated[err.message] = 0
}, 30000)
try {
Sentry.captureException(err)
} catch {
// ignore
}
// destroy any previous toast message to avoid duplicate messages
message.destroy(MESSAGE_KEY)
message.open({
key: MESSAGE_KEY,
content: h('div', [
h(
'div',
{
class: 'flex gap-3 py-1.5',
},
[
h(resolveComponent('GeneralIcon'), { icon: 'error', class: 'text-2xl text-red-500 -mt-1' }),
h('div', { class: 'text-left flex flex-col gap-1' }, [
h('div', { class: 'font-weight-bold' }, 'Page Loading Error'),
h('div', [h('span', { class: 'text-sm text-gray-500' }, 'Something went wrong while loading page!')]),
]),
h(
'div',
{
class: 'flex gap-1 justify-end',
},
[
repeated[err.message] > 2
? h(
resolveComponent('NcButton'),
{
onClick: navigateToHome,
type: 'text',
size: 'xsmall',
class: '!text-sm !px-2 !text-primary',
},
'Home',
)
: h(
resolveComponent('NcButton'),
{
onClick: reload,
type: 'text',
size: 'xsmall',
class: '!text-sm !px-2 !text-primary',
},
'Reload',
),
h(
resolveComponent('NcButton'),
{
onClick: close,
type: 'text',
size: 'xsmall',
class: 'flex items-center gap-1',
},
[h(resolveComponent('GeneralIcon'), { icon: 'close', class: '' })],
),
],
),
],
),
]),
duration: 5,
style: {
position: 'fixed',
bottom: '20px',
right: '20px',
},
})
return false
}
})
@ -35,19 +138,6 @@ export default {
}
}
const reload = () => {
prevError.value = error.value
error.value = null
key.value++
}
const navigateToHome = () => {
prevError.value = error.value
error.value = null
location.hash = '/'
location.reload()
}
return {
errModal,
error,
@ -64,89 +154,4 @@ export default {
<template>
<slot :key="key"></slot>
<slot name="error">
<NcModal
v-if="error"
v-model:visible="errModal"
:class="{ active: errModal }"
:centered="true"
:closable="false"
:footer="null"
>
<div class="w-full flex flex-col gap-1">
<h2 class="text-xl font-semibold">Oops! Something unexpected happened :/</h2>
<p class="mb-0">
<span
>Please report this error in our
<a href="https://discord.gg/5RgZmkW" target="_blank" rel="noopener noreferrer">Discord channel</a>. You can copy the
error message by clicking the "Copy" button below.</span
>
</p>
<span class="cursor-pointer" @click="isErrorExpanded = !isErrorExpanded"
>{{ isErrorExpanded ? 'Hide' : 'Show' }} details
<GeneralIcon
icon="arrowDown"
class="transition-transform transform duration-300"
:class="{
'rotate-180': isErrorExpanded,
}"
/></span>
<div
class="nc-error"
:class="{
active: isErrorExpanded,
}"
>
<div class="nc-left-vertical-bar"></div>
<div class="nc-error-content">
<span class="font-weight-bold">Message: {{ error.message }}</span>
<br />
<div class="text-gray-500 mt-2">{{ error.stack }}</div>
</div>
</div>
<div class="flex justify-end gap-2">
<NcButton size="small" type="secondary" @click="copyError">
<div class="flex items-center gap-1">
<GeneralIcon icon="copy" />
Copy Error
</div>
</NcButton>
<NcButton v-if="!prevError || error.message !== prevError.message" size="small" @click="reload">
<div class="flex items-center gap-1">
<GeneralIcon icon="reload" />
Reload
</div>
</NcButton>
<NcButton v-else size="small" @click="navigateToHome">
<div class="flex items-center gap-1">
<GeneralIcon icon="link" />
Home
</div>
</NcButton>
</div>
</div>
</NcModal>
</slot>
</template>
<style scoped lang="scss">
.nc-error {
@apply flex gap-2 mb-2 max-h-0;
white-space: pre;
transition: max-height 300ms linear;
&.active {
max-height: 250px;
}
.nc-left-vertical-bar {
@apply w-6px min-w-6px rounded min-h-full bg-gray-300;
}
.nc-error-content {
@apply min-w-0 overflow-auto pl-2 flex-shrink;
}
}
</style>

3
packages/nc-gui/components/smartsheet/column/LinkedToAnotherRecordOptions.vue

@ -346,7 +346,8 @@ const onFilterLabelClick = () => {
<div class="min-w-5 flex items-center justify-center">
<GeneralViewIcon :meta="view" class="text-gray-500" />
</div>
<NcTooltip class="flex-1 truncate" show-on-truncate-only>
<span v-if="view.is_default">{{ $t('labels.defaultView') }}</span>
<NcTooltip v-else class="flex-1 truncate" show-on-truncate-only>
<template #title>{{ view.title }}</template>
<span>{{ view.title }}</span>
</NcTooltip>

1
packages/nc-gui/composables/useGlobal/state.ts

@ -98,6 +98,7 @@ export function useGlobalState(storageKey = 'nocodb-gui-v2'): State {
oneClick: false,
baseHasAdmin: false,
teleEnabled: true,
errorReportingEnabled: false,
auditEnabled: true,
type: 'nocodb',
version: '0.0.0',

1
packages/nc-gui/composables/useGlobal/types.ts

@ -22,6 +22,7 @@ export interface AppInfo {
oneClick: boolean
baseHasAdmin: boolean
teleEnabled: boolean
errorReportingEnabled: boolean
auditEnabled: boolean
type: string
version: string

1
packages/nc-gui/lang/en.json

@ -561,6 +561,7 @@
"directlyInRealTime": "Directly in real time"
},
"labels": {
"defaultView": "Default view",
"recordInsert": "Record Insert",
"recordUpdate": "Record Update",
"recordDelete": "Record Delete",

2
packages/nc-gui/package.json

@ -40,6 +40,8 @@
"@iconify/vue": "^4.1.2",
"@nuxt/image": "^1.3.0",
"@pinia/nuxt": "^0.5.1",
"@sentry/tracing": "^7.72.0",
"@sentry/vue": "^7.72.0",
"@tiptap/extension-link": "^2.4.0",
"@tiptap/extension-placeholder": "^2.4.0",
"@tiptap/extension-task-list": "2.4.0",

21
packages/nc-gui/plugins/error-handler.ts

@ -3,8 +3,7 @@ export default defineNuxtPlugin((nuxtApp) => {
const MAX_RETRIES = 2
const QUERY_PARAM_NAME = 'reload_attempt'
// Handle "Failed to fetch dynamically imported module ..." or similar issues
nuxtApp.hook('app:chunkError', () => {
const reload = () => {
const searchParams = new URLSearchParams(window.location.search)
const currentRetry = Number(searchParams.get(QUERY_PARAM_NAME)) || 0
if (currentRetry < MAX_RETRIES) {
@ -13,5 +12,23 @@ export default defineNuxtPlugin((nuxtApp) => {
// Changing the search also causes a refresh
window.location.search = searchParams.toString()
}
}
// Handle "Failed to fetch dynamically imported module ..." or similar issues
nuxtApp.hook('app:chunkError', () => {
reload()
})
nuxtApp.hook('app:error', (error) => {
const reload_error_list = [
'error loading dynamically imported module',
'Importing a module script failed',
'Failed to fetch dynamically imported module',
]
for (const message of reload_error_list) {
if (error.message.includes(message)) {
reload()
}
}
})
})

69
packages/nc-gui/plugins/sentry.ts

@ -0,0 +1,69 @@
// ref: https://localazy.com/blog/nuxt-3-tailwind-i18n-eslint-starter#add-sentry
// https://docs.sentry.io/platforms/javascript/guides/vue/
import * as Sentry from '@sentry/vue'
import { defineNuxtPlugin } from 'nuxt/app'
export default defineNuxtPlugin((nuxtApp) => {
if (isEeUI) return
const { vueApp } = nuxtApp
const env = process.env.NODE_ENV === 'production' ? 'production' : 'development'
if (process.env.CI || process.env.PLAYWRIGHT) {
return
}
if (env !== 'production' && !process.env.NC_ENABLE_DEV_SENTRY) {
return
}
let initialized = false
const init = () => {
// prevent multiple init
if (initialized) return
initialized = true
Sentry.init({
app: [vueApp],
dsn: 'https://64cb4904bcbec03a1b9a0be02a2d10a9@o4505953073889280.ingest.us.sentry.io/4507725383663616',
environment: env,
integrations: [
new Sentry.BrowserTracing({
tracingOrigins: ['*'],
routingInstrumentation: Sentry.vueRouterInstrumentation(nuxtApp.$router),
}),
],
beforeSend(event) {
if (process.env.NODE_ENV === 'production') {
event.extra = event.extra || {}
try {
// set additional context
const appInfo = (nuxtApp.$state as ReturnType<typeof useGlobal>).appInfo.value
event.extra.version = appInfo?.version
} catch {
// ignore
}
return event
}
return null
},
autoSessionTracking: false,
tracesSampleRate: 0.5,
})
}
// load sentry only if enabled
watch(
() => (nuxtApp.$state as ReturnType<typeof useGlobal>).appInfo?.value?.errorReportingEnabled,
(enabled) => {
try {
if (enabled) init()
} catch (e) {
// ignore
}
},
{ immediate: true },
)
})

7
packages/noco-docs/docs/020.getting-started/050.self-hosted/020.environment-variables.md

@ -92,9 +92,10 @@ For production use cases, it is crucial to set all environment variables marked
| `NC_AUTOMATION_LOG_LEVEL` | No | Configures logging levels for automation features. Possible values: `OFF`, `ERROR`, `ALL`. More details can be found under [Webhooks](/automation/webhook/create-webhook#call-log). | Defaults to `OFF`. |
## Logging & Monitoring
| Variable | Mandatory | Description | If Not Set |
| -------- | --------- | ----------- | ---------- |
| `NC_SENTRY_DSN` | No | Data Source Name (DSN) for integrating with Sentry for monitoring and error tracking. | |
| Variable | Mandatory | Description | If Not Set |
| -------- | --------- |---------------------------------------------------------------------------------------|------------|
| `NC_SENTRY_DSN` | No | Data Source Name (DSN) for integrating with Sentry for monitoring and error tracking. | |
| `NC_DISABLE_ERR_REPORTS` | No | Disable default Sentry error reporting. | TRUE |
## Debugging Only
| Variable | Mandatory | Description | If Not Set |

105
packages/noco-docs/versioned_docs/version-0.109.7/020.getting-started/020.environment-variables.md vendored

@ -10,55 +10,56 @@ For production usecases, it is **recommended** to configure
- `NC_PUBLIC_URL`,
- `NC_REDIS_URL`
| Variable | Comments | If absent |
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---|
| NC_DB | See our database URLs | A local SQLite will be created in root folder if `NC_DB` is not provided |
| NC_DB_JSON | Can be used instead of `NC_DB` and value should be valid knex connection JSON | |
| NC_DB_JSON_FILE | Can be used instead of `NC_DB` and value should be a valid path to knex connection JSON | |
| DATABASE_URL | JDBC URL Format. Can be used instead of NC_DB. | |
| DATABASE_URL_FILE | Can be used instead of DATABASE_URL: path to file containing JDBC URL Format. | |
| NC_AUTH_JWT_SECRET | JWT secret used for auth and storing other secrets | A random secret will be generated |
| PORT | For setting app running port | `8080` |
| DB_QUERY_LIMIT_DEFAULT | Default pagination limit | 25 |
| DB_QUERY_LIMIT_MAX | Maximum allowed pagination limit | 1000 |
| DB_QUERY_LIMIT_MIN | Minimum allowed pagination limit | 1 |
| NC_TOOL_DIR | App directory to keep metadata and app related files | Defaults to current working directory. In docker maps to `/usr/app/data/` for mounting volume. |
| NC_PUBLIC_URL | Used for sending Email invitations | Best guess from http request params |
| NC_JWT_EXPIRES_IN | JWT token expiry time | `10h` |
| NC_CONNECT_TO_EXTERNAL_DB_DISABLED | Disable Project creation with external database | |
| NC_INVITE_ONLY_SIGNUP | Removed since version 0.99.0 and now it's recommended to use [super admin settings menu](/0.109.7/setup-and-usages/account-settings#enable--disable-signup). Allow users to signup only via invite url, value should be any non-empty string. | |
| NUXT_PUBLIC_NC_BACKEND_URL | Custom Backend URL | ``http://localhost:8080`` will be used |
| NC_REQUEST_BODY_SIZE | Request body size [limit](https://expressjs.com/en/resources/middleware/body-parser.html#limit) | `1048576` |
| NC_EXPORT_MAX_TIMEOUT | After NC_EXPORT_MAX_TIMEOUT csv gets downloaded in batches | Default value 5000(in millisecond) will be used |
| NC_DISABLE_TELE | Disable telemetry | |
| NC_DASHBOARD_URL | Custom dashboard url path | `/dashboard` |
| NC_GOOGLE_CLIENT_ID | Google client id to enable google authentication | |
| NC_GOOGLE_CLIENT_SECRET | Google client secret to enable google authentication | |
| NC_MIGRATIONS_DISABLED | Disable NocoDB migration | |
| NC_MIN | If set to any non-empty string the default splash screen(initial welcome animation) and matrix screensaver will disable | |
| NC_SENTRY_DSN | For Sentry monitoring | |
| NC_REDIS_URL | Custom Redis URL. Example: `redis://:authpassword@127.0.0.1:6380/4` | Meta data will be stored in memory |
| NC_DISABLE_ERR_REPORT | Disable error reporting | |
| NC_DISABLE_CACHE | To be used only while debugging. On setting this to `true` - meta data be fetched from db instead of redis/cache. | `false` |
| AWS_ACCESS_KEY_ID | For Litestream - S3 access key id | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 |
| AWS_SECRET_ACCESS_KEY | For Litestream - S3 secret access key | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 |
| AWS_BUCKET | For Litestream - S3 bucket | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 |
| AWS_BUCKET_PATH | For Litestream - S3 bucket path (like folder within S3 bucket) | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 |
| NC_SMTP_FROM | For SMTP plugin - Email sender address | |
| NC_SMTP_HOST | For SMTP plugin - SMTP host value | |
| NC_SMTP_PORT | For SMTP plugin - SMTP port value | |
| NC_SMTP_USERNAME | For SMTP plugin (Optional) - SMTP username value for authentication | |
| NC_SMTP_PASSWORD | For SMTP plugin (Optional) - SMTP password value for authentication | |
| NC_SMTP_SECURE | For SMTP plugin (Optional) - To enable secure set value as `true` any other value treated as false | |
| NC_SMTP_IGNORE_TLS | For SMTP plugin (Optional) - To ignore tls set value as `true` any other value treated as false. For more info visit https://nodemailer.com/smtp/ | |
| NC_S3_BUCKET_NAME | For S3 storage plugin - AWS S3 bucket name | |
| NC_S3_REGION | For S3 storage plugin - AWS S3 region | |
| NC_S3_ACCESS_KEY | For S3 storage plugin - AWS access key credential for accessing resource | |
| NC_S3_ACCESS_SECRET | For S3 storage plugin - AWS access secret credential for accessing resource | |
| NC_ADMIN_EMAIL | For updating/creating super admin with provided email and password | |
| NC_ATTACHMENT_FIELD_SIZE | For setting the attachment field size(in Bytes) | Defaults to 20MB |
| NC_ADMIN_PASSWORD | For updating/creating super admin with provided email and password. Your password should have at least 8 letters with one uppercase, one number and one special letter(Allowed special chars $&+,:;=?@#\|'.^*()%!_-" ) | |
| NODE_OPTIONS | For passing Node.js [options](https://nodejs.org/api/cli.html#node_optionsoptions) to instance | |
| NC_MINIMAL_DBS | Create a new SQLite file for each project. All the db files are stored in `nc_minimal_dbs` folder in current working directory. (This option restricts project creation on external sources) | |
| NC_DISABLE_AUDIT | Disable Audit Log | `false` |
| NC_AUTOMATION_LOG_LEVEL | Possible Values: `OFF`, `ERROR`, `ALL`. See [Webhooks](/0.109.7/developer-resources/webhooks#call-log) for details. | `OFF` |
| Variable | Comments | If absent |
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---|
| NC_DB | See our database URLs | A local SQLite will be created in root folder if `NC_DB` is not provided |
| NC_DB_JSON | Can be used instead of `NC_DB` and value should be valid knex connection JSON | |
| NC_DB_JSON_FILE | Can be used instead of `NC_DB` and value should be a valid path to knex connection JSON | |
| DATABASE_URL | JDBC URL Format. Can be used instead of NC_DB. | |
| DATABASE_URL_FILE | Can be used instead of DATABASE_URL: path to file containing JDBC URL Format. | |
| NC_AUTH_JWT_SECRET | JWT secret used for auth and storing other secrets | A random secret will be generated |
| PORT | For setting app running port | `8080` |
| DB_QUERY_LIMIT_DEFAULT | Default pagination limit | 25 |
| DB_QUERY_LIMIT_MAX | Maximum allowed pagination limit | 1000 |
| DB_QUERY_LIMIT_MIN | Minimum allowed pagination limit | 1 |
| NC_TOOL_DIR | App directory to keep metadata and app related files | Defaults to current working directory. In docker maps to `/usr/app/data/` for mounting volume. |
| NC_PUBLIC_URL | Used for sending Email invitations | Best guess from http request params |
| NC_JWT_EXPIRES_IN | JWT token expiry time | `10h` |
| NC_CONNECT_TO_EXTERNAL_DB_DISABLED | Disable Project creation with external database | |
| NC_INVITE_ONLY_SIGNUP | Removed since version 0.99.0 and now it's recommended to use [super admin settings menu](/0.109.7/setup-and-usages/account-settings#enable--disable-signup). Allow users to signup only via invite url, value should be any non-empty string. | |
| NUXT_PUBLIC_NC_BACKEND_URL | Custom Backend URL | ``http://localhost:8080`` will be used |
| NC_REQUEST_BODY_SIZE | Request body size [limit](https://expressjs.com/en/resources/middleware/body-parser.html#limit) | `1048576` |
| NC_EXPORT_MAX_TIMEOUT | After NC_EXPORT_MAX_TIMEOUT csv gets downloaded in batches | Default value 5000(in millisecond) will be used |
| NC_DISABLE_TELE | Disable telemetry | |
| NC_DISABLE_ERR_REPORTS | Disable default sentry error reporting | |
| NC_DASHBOARD_URL | Custom dashboard url path | `/dashboard` |
| NC_GOOGLE_CLIENT_ID | Google client id to enable google authentication | |
| NC_GOOGLE_CLIENT_SECRET | Google client secret to enable google authentication | |
| NC_MIGRATIONS_DISABLED | Disable NocoDB migration | |
| NC_MIN | If set to any non-empty string the default splash screen(initial welcome animation) and matrix screensaver will disable | |
| NC_SENTRY_DSN | For Sentry monitoring | |
| NC_REDIS_URL | Custom Redis URL. Example: `redis://:authpassword@127.0.0.1:6380/4` | Meta data will be stored in memory |
| NC_DISABLE_ERR_REPORT | Disable error reporting | |
| NC_DISABLE_CACHE | To be used only while debugging. On setting this to `true` - meta data be fetched from db instead of redis/cache. | `false` |
| AWS_ACCESS_KEY_ID | For Litestream - S3 access key id | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 |
| AWS_SECRET_ACCESS_KEY | For Litestream - S3 secret access key | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 |
| AWS_BUCKET | For Litestream - S3 bucket | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 |
| AWS_BUCKET_PATH | For Litestream - S3 bucket path (like folder within S3 bucket) | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 |
| NC_SMTP_FROM | For SMTP plugin - Email sender address | |
| NC_SMTP_HOST | For SMTP plugin - SMTP host value | |
| NC_SMTP_PORT | For SMTP plugin - SMTP port value | |
| NC_SMTP_USERNAME | For SMTP plugin (Optional) - SMTP username value for authentication | |
| NC_SMTP_PASSWORD | For SMTP plugin (Optional) - SMTP password value for authentication | |
| NC_SMTP_SECURE | For SMTP plugin (Optional) - To enable secure set value as `true` any other value treated as false | |
| NC_SMTP_IGNORE_TLS | For SMTP plugin (Optional) - To ignore tls set value as `true` any other value treated as false. For more info visit https://nodemailer.com/smtp/ | |
| NC_S3_BUCKET_NAME | For S3 storage plugin - AWS S3 bucket name | |
| NC_S3_REGION | For S3 storage plugin - AWS S3 region | |
| NC_S3_ACCESS_KEY | For S3 storage plugin - AWS access key credential for accessing resource | |
| NC_S3_ACCESS_SECRET | For S3 storage plugin - AWS access secret credential for accessing resource | |
| NC_ADMIN_EMAIL | For updating/creating super admin with provided email and password | |
| NC_ATTACHMENT_FIELD_SIZE | For setting the attachment field size(in Bytes) | Defaults to 20MB |
| NC_ADMIN_PASSWORD | For updating/creating super admin with provided email and password. Your password should have at least 8 letters with one uppercase, one number and one special letter(Allowed special chars $&+,:;=?@#\|'.^*()%!_-" ) | |
| NODE_OPTIONS | For passing Node.js [options](https://nodejs.org/api/cli.html#node_optionsoptions) to instance | |
| NC_MINIMAL_DBS | Create a new SQLite file for each project. All the db files are stored in `nc_minimal_dbs` folder in current working directory. (This option restricts project creation on external sources) | |
| NC_DISABLE_AUDIT | Disable Audit Log | `false` |
| NC_AUTOMATION_LOG_LEVEL | Possible Values: `OFF`, `ERROR`, `ALL`. See [Webhooks](/0.109.7/developer-resources/webhooks#call-log) for details. | `OFF` |

184
packages/nocodb-sdk/src/lib/Api.ts

@ -256,8 +256,12 @@ export interface AuditRowUpdateReqType {
* Model for Source
*/
export interface SourceType {
/** Source Name - Default BASE will be null by default */
/** Source Name */
alias?: StringOrNullType;
/** Integration Name */
integration_title?: StringOrNullType;
/** Integration Id */
fk_integration_id?: StringOrNullType;
/** Source Configuration */
config?: any;
/** Is this source enabled */
@ -304,6 +308,43 @@ export interface SourceType {
| 'databricks';
}
/**
* Model for Integration
*/
export interface IntegrationType {
/** Source Name - Default BASE will be null by default */
title?: StringOrNullType;
/** Source Configuration */
config?: any;
/** Is this Intgration enabled */
enabled?: BoolType;
/** Unique Integration ID */
id?: string;
/** Unique Workspace ID */
fk_workspace_id?: string;
/**
* The order of the list of sources
* @example 1
*/
order?: number;
/** The base ID that this source belongs to */
base_id?: string;
/** Model for Bool */
is_private?: BoolType;
/** Integration Type */
type?: IntegrationsType;
/**
* DB Type
* @example mysql2
*/
sub_type?: string;
/**
* DB Type
* @example mysql2
*/
created_by?: string;
}
/**
* Model for Source List
*/
@ -353,6 +394,35 @@ export interface BaseReqType {
| 'snowflake'
| 'sqlite3'
| 'databricks';
fk_integration_id?: string;
}
/**
* Integration Type
*/
export enum IntegrationsType {
Database = 'database',
}
/**
* Model for Integration Request
*/
export interface IntegrationReqType {
/**
* Integration Name - Default BASE will be null by default
* @example Integration
*/
title: string;
/** Source Configuration */
config: any;
/** Integration metas */
meta?: any;
/** Integration Type */
type: IntegrationsType;
/** Sub Type */
sub_type?: string;
/** ID of integration to be copied from. Used in Copy Integration. */
copy_from_id?: StringOrNullType;
}
/**
@ -12279,4 +12349,116 @@ export class Api<
...params,
}),
};
integration = {
/**
* @description List integrations
*
* @tags Integration
* @name List
* @summary List integrations
* @request GET:/api/v2/meta/integrations
* @response `200` `any` OK
*/
list: (
query?: {
/** Integration Type */
type?: IntegrationsType;
includeDatabaseInfo?: boolean;
limit?: number;
offset?: number;
baseId?: string;
query?: string;
},
params: RequestParams = {}
) =>
this.request<any, any>({
path: `/api/v2/meta/integrations`,
method: 'GET',
query: query,
format: 'json',
...params,
}),
/**
* @description Create integration
*
* @tags Integration
* @name Create
* @summary Create integration
* @request POST:/api/v2/meta/integrations
* @response `200` `IntegrationType` OK
*/
create: (data: IntegrationReqType, params: RequestParams = {}) =>
this.request<IntegrationType, any>({
path: `/api/v2/meta/integrations`,
method: 'POST',
body: data,
type: ContentType.Json,
format: 'json',
...params,
}),
/**
* @description Read integration
*
* @tags Integration
* @name Read
* @summary Read integration
* @request GET:/api/v2/meta/integrations/{integrationId}
* @response `200` `IntegrationType` OK
*/
read: (
integrationId: string,
query?: {
includeConfig?: boolean;
includeSources?: boolean;
},
params: RequestParams = {}
) =>
this.request<IntegrationType, any>({
path: `/api/v2/meta/integrations/${integrationId}`,
method: 'GET',
query: query,
format: 'json',
...params,
}),
/**
* @description Update integration
*
* @tags Integration
* @name Update
* @summary Update integration
* @request PATCH:/api/v2/meta/integrations/{integrationId}
* @response `200` `void` OK
*/
update: (
integrationId: string,
data: IntegrationReqType,
params: RequestParams = {}
) =>
this.request<void, any>({
path: `/api/v2/meta/integrations/${integrationId}`,
method: 'PATCH',
body: data,
type: ContentType.Json,
...params,
}),
/**
* @description Delete integration
*
* @tags Integration
* @name Delete
* @summary Delete integration
* @request DELETE:/api/v2/meta/integrations/{integrationId}
* @response `200` `void` OK
*/
delete: (integrationId: string, params: RequestParams = {}) =>
this.request<void, any>({
path: `/api/v2/meta/integrations/${integrationId}`,
method: 'DELETE',
...params,
}),
};
}

2
packages/nocodb/package.json

@ -122,7 +122,7 @@
"multer": "^1.4.5-lts.1",
"mysql2": "^3.9.7",
"nanoid": "^3.3.7",
"nc-help": "0.3.1",
"nc-help": "0.3.4",
"nc-lib-gui": "0.251.3",
"nc-plugin": "^0.1.6",
"nestjs-throttler-storage-redis": "^0.4.4",

6
packages/nocodb/src/helpers/webhookHelpers.ts

@ -18,7 +18,11 @@ dayjs.extend(isBetween);
dayjs.extend(isSameOrBefore);
dayjs.extend(isSameOrAfter);
Handlebars.registerHelper('json', function (context) {
Handlebars.registerHelper('json', function (context, pretty = false) {
if (pretty === true || pretty === 'true') {
// Pretty print with 2-space indentation
return JSON.stringify(context, null, 2);
}
return JSON.stringify(context);
});

10
packages/nocodb/src/models/Model.ts

@ -749,6 +749,16 @@ export default class Model implements TableType {
tableId,
);
// get default view and update alias
{
const defaultView = await View.getDefaultView(context, tableId, ncMeta);
if (defaultView) {
await View.update(context, defaultView.id, {
title,
});
}
}
await NocoCache.update(`${CacheScope.MODEL}:${tableId}`, {
title,
table_name,

5
packages/nocodb/src/schema/swagger-v2.json

@ -10286,6 +10286,7 @@
"defaultLimit": 25,
"ncMin": false,
"teleEnabled": false,
"errorReportingEnabled": true,
"auditEnabled": true,
"ncSiteUrl": "http://localhost:8080",
"ee": false,
@ -10330,6 +10331,9 @@
"teleEnabled": {
"type": "boolean"
},
"errorReportingEnabled": {
"type": "boolean"
},
"auditEnabled": {
"type": "boolean"
},
@ -10380,6 +10384,7 @@
"defaultLimit": 25,
"ncMin": false,
"teleEnabled": false,
"errorReportingEnabled": true,
"auditEnabled": true,
"ncSiteUrl": "http://localhost:8080",
"ee": false,

5
packages/nocodb/src/schema/swagger.json

@ -15787,6 +15787,7 @@
"defaultLimit": 25,
"ncMin": false,
"teleEnabled": false,
"errorReportingEnabled": true,
"auditEnabled": true,
"ncSiteUrl": "http://localhost:8080",
"ee": false,
@ -15831,6 +15832,9 @@
"teleEnabled": {
"type": "boolean"
},
"errorReportingEnabled": {
"type": "boolean"
},
"auditEnabled": {
"type": "boolean"
},
@ -15881,6 +15885,7 @@
"defaultLimit": 25,
"ncMin": false,
"teleEnabled": false,
"errorReportingEnabled": true,
"auditEnabled": true,
"ncSiteUrl": "http://localhost:8080",
"ee": false,

1
packages/nocodb/src/services/utils.service.ts

@ -437,6 +437,7 @@ export class UtilsService {
timezone: defaultConnectionConfig.timezone,
ncMin: !!process.env.NC_MIN,
teleEnabled: process.env.NC_DISABLE_TELE !== 'true',
errorReportingEnabled: process.env.NC_DISABLE_ERR_REPORTS !== 'true',
auditEnabled: process.env.NC_DISABLE_AUDIT !== 'true',
ncSiteUrl: (param.req as any).ncSiteUrl,
ee: Noco.isEE(),

1110
pnpm-lock.yaml

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save