diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 02d321f178..25793d026f 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -49,7 +49,6 @@ jobs: uses: cypress-io/github-action@v2 with: start: | - npm run build:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/cypress/docker-compose-pg.yml up -d @@ -94,7 +93,6 @@ jobs: uses: cypress-io/github-action@v2 with: start: | - npm run build:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/cypress/docker-compose-pg.yml up -d @@ -139,7 +137,6 @@ jobs: uses: cypress-io/github-action@v2 with: start: | - npm run build:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/cypress/docker-compose-pg.yml up -d @@ -184,7 +181,6 @@ jobs: uses: cypress-io/github-action@v2 with: start: | - npm run build:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/cypress/docker-compose-pg.yml up -d @@ -229,7 +225,6 @@ jobs: uses: cypress-io/github-action@v2 with: start: | - npm run build:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -274,7 +269,6 @@ jobs: uses: cypress-io/github-action@v2 with: start: | - npm run build:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -319,7 +313,6 @@ jobs: uses: cypress-io/github-action@v2 with: start: | - npm run build:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -364,7 +357,6 @@ jobs: uses: cypress-io/github-action@v2 with: start: | - npm run build:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -409,7 +401,6 @@ jobs: uses: cypress-io/github-action@v2 with: start: | - npm run build:common npm run start:xcdb-api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -454,7 +445,6 @@ jobs: uses: cypress-io/github-action@v2 with: start: | - npm run build:common npm run start:xcdb-api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -499,7 +489,6 @@ jobs: uses: cypress-io/github-action@v2 with: start: | - npm run build:common npm run start:xcdb-api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -544,7 +533,6 @@ jobs: uses: cypress-io/github-action@v2 with: start: | - npm run build:common npm run start:xcdb-api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d diff --git a/package.json b/package.json index 579c3db173..602192d780 100644 --- a/package.json +++ b/package.json @@ -15,12 +15,12 @@ "scripts": { "build:common": "cd ./packages/nocodb-sdk; npm install; npm run build", "install:common": "cd ./packages/nocodb; npm install ../nocodb-sdk; cd ../nc-gui; npm install ../nocodb-sdk", - "start:api": "cd ./packages/nocodb; npm install; NC_DISABLE_CACHE=true NC_DISABLE_TELE=true npm run watch:run:cypress", - "start:xcdb-api": "cd ./packages/nocodb; npm install; NC_DISABLE_CACHE=true NC_DISABLE_TELE=true NC_INFLECTION=camelize DATABASE_URL=sqlite:../../../scripts/cypress/fixtures/sqlite-sakila/sakila.db npm run watch:run:cypress", - "start:api:cache": "cd ./packages/nocodb; npm install; NC_DISABLE_TELE=true npm run watch:run:cypress", - "start:api:cache:pg": "cd ./packages/nocodb; npm install; NC_DISABLE_TELE=true npm run watch:run:cypress:pg", - "start:xcdb-api:cache": "cd ./packages/nocodb; npm install; NC_DISABLE_TELE=true NC_INFLECTION=camelize DATABASE_URL=sqlite:../../../scripts/cypress/fixtures/sqlite-sakila/sakila.db npm run watch:run:cypress", - "start:web": "cd ./packages/nc-gui; npm install; npm run dev", + "start:api": "npm run build:common ; cd ./packages/nocodb; npm install ../nocodb-sdk; npm install; NC_DISABLE_CACHE=true NC_DISABLE_TELE=true npm run watch:run:cypress", + "start:xcdb-api": "npm run build:common ; cd ./packages/nocodb; npm install ../nocodb-sdk;npm install; NC_DISABLE_CACHE=true NC_DISABLE_TELE=true NC_INFLECTION=camelize DATABASE_URL=sqlite:../../../scripts/cypress/fixtures/sqlite-sakila/sakila.db npm run watch:run:cypress", + "start:api:cache": "npm run build:common ; cd ./packages/nocodb; npm install ../nocodb-sdk;npm install; NC_DISABLE_TELE=true npm run watch:run:cypress", + "start:api:cache:pg": "npm run build:common ; cd ./packages/nocodb; npm install ../nocodb-sdk; npm install; NC_DISABLE_TELE=true npm run watch:run:cypress:pg", + "start:xcdb-api:cache": "npm run build:common ; cd ./packages/nocodb; npm install ../nocodb-sdk; npm install; NC_DISABLE_TELE=true NC_INFLECTION=camelize DATABASE_URL=sqlite:../../../scripts/cypress/fixtures/sqlite-sakila/sakila.db npm run watch:run:cypress", + "start:web": "npm run build:common ; cd ./packages/nc-gui; npm install ../nocodb-sdk; npm install; npm run dev", "cypress:run": "cypress run --config-file ./scripts/cypress/cypress.json", "cypress:open": "cypress open --config-file ./scripts/cypress/cypress.json", "cypress:clear": "cypress cache clear", diff --git a/packages/nc-gui/components/ProjectTabs.vue b/packages/nc-gui/components/ProjectTabs.vue index a3fd6392ec..0a69cd3360 100644 --- a/packages/nc-gui/components/ProjectTabs.vue +++ b/packages/nc-gui/components/ProjectTabs.vue @@ -315,6 +315,21 @@ + + + + mdi-code-json + + + + JSON file + + + + + + @@ -404,9 +426,11 @@ import GlobalAcl from '~/components/GlobalAcl' import AuditTab from '~/components/project/AuditTab' import QuickImport from '~/components/import/QuickImport' import ImportFromAirtable from '~/components/import/ImportFromAirtable' +import JsonImport from '~/components/import/JSONImport' export default { components: { + JsonImport, ImportFromAirtable, SwaggerClient, // Screensaver, @@ -447,7 +471,8 @@ export default { showScreensaver: false, quickImportModal: false, quickImportType: '', - airtableImportModal: false + airtableImportModal: false, + jsonImportModal: false } }, methods: { diff --git a/packages/nc-gui/components/import/ImportFromAirtable.vue b/packages/nc-gui/components/import/ImportFromAirtable.vue index d22031d35f..a3264182a3 100644 --- a/packages/nc-gui/components/import/ImportFromAirtable.vue +++ b/packages/nc-gui/components/import/ImportFromAirtable.vue @@ -8,7 +8,6 @@
🚀
@@ -86,6 +85,13 @@ hide-details dense /> + +
+ + + + + + mdi-file-upload-outline + + Upload + + + + + + mdi-link-variant + + String + + + +
+
+ + mdi-file-plus-outline + +

+ + {{ $t('msg.info.upload') }} +

+

+ + {{ $t('msg.info.upload_sub') }} +

+ +

+ + {{ $t('msg.info.excelSupport') }} +

+
+
+
+ + +
+
+ +
+ + Format + + + + +
+ + + {{ $t('general.load') }} + +
+
+
+
+
+
+
+ +
+
+ + + {{ showMore ? $t('general.hideAll') : $t('general.showMore') }} + mdi-menu-{{ showMore ? 'up' : 'down' }} + +
+
+

+ + + + + + + + + +

+
+
+
+ + + + Create template from JSON + + + + + + + + + +
+ + + + + diff --git a/packages/nc-gui/components/import/templateParsers/CSVTemplateAdapter.js b/packages/nc-gui/components/import/templateParsers/CSVTemplateAdapter.js index 9a3be0d4de..c608a79f85 100644 --- a/packages/nc-gui/components/import/templateParsers/CSVTemplateAdapter.js +++ b/packages/nc-gui/components/import/templateParsers/CSVTemplateAdapter.js @@ -1,6 +1,5 @@ import Papaparse from 'papaparse' import TemplateGenerator from '~/components/import/templateParsers/TemplateGenerator' - export default class CSVTemplateAdapter extends TemplateGenerator { constructor(name, data) { super() diff --git a/packages/nc-gui/components/import/templateParsers/JSONTemplateAdapter.js b/packages/nc-gui/components/import/templateParsers/JSONTemplateAdapter.js new file mode 100644 index 0000000000..b53230b789 --- /dev/null +++ b/packages/nc-gui/components/import/templateParsers/JSONTemplateAdapter.js @@ -0,0 +1,150 @@ +import { TemplateGenerator, UITypes } from 'nocodb-sdk' +import { + extractMultiOrSingleSelectProps, + getCheckboxValue, + isCheckboxType, isDecimalType, isEmailType, + isMultiLineTextType, isUrlType +} from '~/components/import/templateParsers/parserHelpers' + +const jsonTypeToUidt = { + number: UITypes.Number, + string: UITypes.SingleLineText, + date: UITypes.DateTime, + boolean: UITypes.Checkbox, + object: UITypes.JSON +} + +const extractNestedData = (obj, path) => path.reduce((val, key) => val && val[key], obj) + +export default class JSONTemplateAdapter extends TemplateGenerator { + constructor(name = 'test', data, parserConfig = {}) { + super() + this.config = { + maxRowsToParse: 500, + ...parserConfig + } + this.name = name + this._jsonData = typeof data === 'string' ? JSON.parse(data) : data + this.project = { + title: this.name, + tables: [] + } + this.data = {} + } + + async init() { + } + + parseData() { + this.columns = this.csv.meta.fields + this.data = this.csv.data + } + + getColumns() { + return this.columns + } + + getData() { + return this.data + } + + get jsonData() { + return Array.isArray(this._jsonData) ? this._jsonData : [this._jsonData] + } + + parse() { + const jsonData = this.jsonData + const tn = 'table' + const table = { table_name: tn, ref_table_name: tn, columns: [] } + + this.data[tn] = [] + + for (const col of Object.keys(jsonData[0])) { + const columns = this._parseColumn([col], jsonData) + table.columns.push(...columns) + } + + if (this.config.importData) { this._parseTableData(table) } + + this.project.tables.push(table) + } + + getTemplate() { + return this.project + } + + _parseColumn(path = [], jsonData = this.jsonData, firstRowVal = path.reduce((val, k) => val && val[k], this.jsonData[0])) { + const columns = [] + // parse nested + if (firstRowVal && typeof firstRowVal === 'object' && !Array.isArray(firstRowVal) && this.config.normalizeNested) { + for (const key of Object.keys(firstRowVal)) { + const normalizedNestedColumns = this._parseColumn([...path, key], this.jsonData, firstRowVal[key]) + columns.push(...normalizedNestedColumns) + } + } else { + const cn = path.join('_').replace(/\W/g, '_').trim() + + const column = { + column_name: cn, + ref_column_name: cn, + path + } + + column.uidt = jsonTypeToUidt[typeof firstRowVal] || UITypes.SingleLineText + + const colData = jsonData.map(r => extractNestedData(r, path)) + Object.assign(column, this._getColumnUIDTAndMetas(colData, column.uidt)) + columns.push(column) + } + + return columns + } + + _getColumnUIDTAndMetas(colData, defaultType) { + const colProps = { uidt: defaultType } + // todo: optimize + if (colProps.uidt === UITypes.SingleLineText) { + // check for long text + if (isMultiLineTextType(colData)) { + colProps.uidt = UITypes.LongText + } if (isEmailType(colData)) { + colProps.uidt = UITypes.Email + } if (isUrlType(colData)) { + colProps.uidt = UITypes.URL + } else { + const checkboxType = isCheckboxType(colData) + if (checkboxType.length === 1) { + colProps.uidt = UITypes.Checkbox + } else { + Object.assign(colProps, extractMultiOrSingleSelectProps(colData)) + } + } + } else if (colProps.uidt === UITypes.Number) { + if (isDecimalType(colData)) { + colProps.uidt = UITypes.Decimal + } + } + return colProps + } + + _parseTableData(tableMeta) { + for (const row of this.jsonData) { + const rowData = {} + for (let i = 0; i < tableMeta.columns.length; i++) { + const value = extractNestedData(row, tableMeta.columns[i].path || []) + if (tableMeta.columns[i].uidt === UITypes.Checkbox) { + rowData[tableMeta.columns[i].ref_column_name] = getCheckboxValue(value) + } else if (tableMeta.columns[i].uidt === UITypes.SingleSelect || tableMeta.columns[i].uidt === UITypes.MultiSelect) { + rowData[tableMeta.columns[i].ref_column_name] = (value || '').toString().trim() || null + } else if (tableMeta.columns[i].uidt === UITypes.JSON) { + rowData[tableMeta.columns[i].ref_column_name] = JSON.stringify(value) + } else { + // toto: do parsing if necessary based on type + rowData[tableMeta.columns[i].column_name] = value + } + } + this.data[tableMeta.ref_table_name].push(rowData) + // rowIndex++ + } + } +} diff --git a/packages/nc-gui/components/import/templateParsers/JSONUrlTemplateAdapter.js b/packages/nc-gui/components/import/templateParsers/JSONUrlTemplateAdapter.js new file mode 100644 index 0000000000..34494e00fc --- /dev/null +++ b/packages/nc-gui/components/import/templateParsers/JSONUrlTemplateAdapter.js @@ -0,0 +1,21 @@ +import JSONTemplateAdapter from '~/components/import/templateParsers/JSONTemplateAdapter' + +export default class JSONUrlTemplateAdapter extends JSONTemplateAdapter { + constructor(url, $store, parserConfig, $api) { + const name = url.split('/').pop() + super(name, null, parserConfig) + this.url = url + this.$api = $api + this.$store = $store + } + + async init() { + const data = await this.$api.utils.axiosRequestMake({ + apiMeta: { + url: this.url + } + }) + this._jsonData = data + await super.init() + } +} diff --git a/packages/nc-gui/components/import/templateParsers/parserHelpers.js b/packages/nc-gui/components/import/templateParsers/parserHelpers.js index 75fd80ead7..43156d3bea 100644 --- a/packages/nc-gui/components/import/templateParsers/parserHelpers.js +++ b/packages/nc-gui/components/import/templateParsers/parserHelpers.js @@ -1,3 +1,6 @@ +import { UITypes } from 'nocodb-sdk' +import { isEmail, isValidURL } from '~/helpers' + const booleanOptions = [ { checked: true, unchecked: false }, { x: true, '': false }, @@ -11,14 +14,24 @@ const booleanOptions = [ { '✔': true, '': false }, { enabled: true, disabled: false }, { on: true, off: false }, - { done: true, '': false } + { done: true, '': false }, + { true: true, false: false } ] const aggBooleanOptions = booleanOptions.reduce((obj, o) => ({ ...obj, ...o }), {}) -export const isCheckboxType = (values, col = '') => { + +const getColVal = (row, col = null) => { + return row && col ? row[col] : row +} + +export const isCheckboxType = (values, col = null) => { let options = booleanOptions for (let i = 0; i < values.length; i++) { - let val = col ? values[i][col] : values[i] - val = val === null || val === undefined ? '' : val + const val = getColVal(values[i], col) + + if (val === null || val === undefined || val.toString().trim() === '') { + continue + } + options = options.filter(v => val in v) if (!options.length) { return false @@ -29,3 +42,40 @@ export const isCheckboxType = (values, col = '') => { export const getCheckboxValue = (value) => { return value && aggBooleanOptions[value] } + +export const isMultiLineTextType = (values, col = null) => { + return values.some(r => + (getColVal(r, col) || '').toString().match(/[\r\n]/) || + (getColVal(r, col) || '').toString().length > 255) +} + +export const extractMultiOrSingleSelectProps = (colData) => { + const colProps = {} + if (colData.some(v => v && (v || '').toString().includes(','))) { + let flattenedVals = colData.flatMap(v => v ? v.toString().trim().split(/\s*,\s*/) : []) + const uniqueVals = flattenedVals = flattenedVals + .filter((v, i, arr) => i === arr.findIndex(v1 => v.toLowerCase() === v1.toLowerCase())) + if (flattenedVals.length > uniqueVals.length && uniqueVals.length <= Math.ceil(flattenedVals.length / 2)) { + colProps.uidt = UITypes.MultiSelect + colProps.dtxp = `'${uniqueVals.join("','")}'` + } + } else { + const uniqueVals = colData.map(v => (v || '').toString().trim()).filter((v, i, arr) => i === arr.findIndex(v1 => v.toLowerCase() === v1.toLowerCase())) + if (colData.length > uniqueVals.length && uniqueVals.length <= Math.ceil(colData.length / 2)) { + colProps.uidt = UITypes.SingleSelect + colProps.dtxp = `'${uniqueVals.join("','")}'` + } + } + return colProps +} + +export const isDecimalType = colData => colData.some((v) => { + return v && parseInt(+v) !== +v +}) + +export const isEmailType = colData => !colData.some((v) => { + return v && !isEmail(v) +}) +export const isUrlType = colData => !colData.some((v) => { + return v && !isValidURL(v) +}) diff --git a/packages/nc-gui/components/monaco/MonacoJsonEditor.js b/packages/nc-gui/components/monaco/MonacoJsonEditor.js index 1362ac4f1c..aa05a99738 100644 --- a/packages/nc-gui/components/monaco/MonacoJsonEditor.js +++ b/packages/nc-gui/components/monaco/MonacoJsonEditor.js @@ -83,6 +83,9 @@ export default { }, methods: { + format() { + this.editor.getAction('editor.action.formatDocument').run() + }, resizeLayout() { this.editor.layout(); }, diff --git a/packages/nc-plugin/package-lock.json b/packages/nc-plugin/package-lock.json index dfecb2107a..2fba7f3aba 100644 --- a/packages/nc-plugin/package-lock.json +++ b/packages/nc-plugin/package-lock.json @@ -1,12 +1,12 @@ { "name": "nc-plugin", - "version": "0.1.1", + "version": "0.1.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nc-plugin", - "version": "0.1.1", + "version": "0.1.3", "license": "MIT", "dependencies": { "@bitauth/libauth": "^1.17.1", @@ -10298,9 +10298,9 @@ } }, "node_modules/shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", "dev": true }, "node_modules/shelljs": { @@ -19881,9 +19881,9 @@ "dev": true }, "shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", "dev": true }, "shelljs": { diff --git a/packages/noco-blog/package-lock.json b/packages/noco-blog/package-lock.json index 05a95ff26b..ef5c75c2ed 100644 --- a/packages/noco-blog/package-lock.json +++ b/packages/noco-blog/package-lock.json @@ -5836,16 +5836,16 @@ } }, "got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "version": "11.8.5", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", + "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", "requires": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", "@types/cacheable-request": "^6.0.1", "@types/responselike": "^1.0.0", "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.1", + "cacheable-request": "^7.0.2", "decompress-response": "^6.0.0", "http2-wrapper": "^1.0.0-beta.5.2", "lowercase-keys": "^2.0.0", @@ -10797,9 +10797,9 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" }, "side-channel": { "version": "1.0.4", diff --git a/packages/noco-docs-prev/package-lock.json b/packages/noco-docs-prev/package-lock.json index 0b4965758b..72f1beb650 100644 --- a/packages/noco-docs-prev/package-lock.json +++ b/packages/noco-docs-prev/package-lock.json @@ -7390,16 +7390,16 @@ } }, "node_modules/got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "version": "11.8.5", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", + "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", "@types/cacheable-request": "^6.0.1", "@types/responselike": "^1.0.0", "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.1", + "cacheable-request": "^7.0.2", "decompress-response": "^6.0.0", "http2-wrapper": "^1.0.0-beta.5.2", "lowercase-keys": "^2.0.0", @@ -13804,9 +13804,9 @@ } }, "node_modules/shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" }, "node_modules/side-channel": { "version": "1.0.4", @@ -22650,16 +22650,16 @@ } }, "got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "version": "11.8.5", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", + "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", "requires": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", "@types/cacheable-request": "^6.0.1", "@types/responselike": "^1.0.0", "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.1", + "cacheable-request": "^7.0.2", "decompress-response": "^6.0.0", "http2-wrapper": "^1.0.0-beta.5.2", "lowercase-keys": "^2.0.0", @@ -27611,9 +27611,9 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" }, "side-channel": { "version": "1.0.4", diff --git a/packages/noco-docs/content/en/developer-resources/rest-apis.md b/packages/noco-docs/content/en/developer-resources/rest-apis.md index 22cd7fe419..72bdeb470c 100644 --- a/packages/noco-docs/content/en/developer-resources/rest-apis.md +++ b/packages/noco-docs/content/en/developer-resources/rest-apis.md @@ -166,7 +166,8 @@ Currently, the default value for {orgs} is noco. Users will be able to ch | Meta | Delete| utils | cacheDelete | /api/v1/db/meta/cache | | Meta | Post | utils | testConnection | /api/v1/db/meta/projects/connection/test | | Meta | Get | utils | appInfo | /api/v1/db/meta/nocodb/info | -| Meta | Get | utils | appVersion | /api/v1/db/meta/nocodb/version | +| Meta | Get | utils | appVersion | /api/v1/version | +| Meta | Get | utils | appHealth | /api/v1/health | ## Query params diff --git a/packages/noco-docs/package-lock.json b/packages/noco-docs/package-lock.json index 6647d34ac9..b30ce6478d 100644 --- a/packages/noco-docs/package-lock.json +++ b/packages/noco-docs/package-lock.json @@ -7390,16 +7390,16 @@ } }, "node_modules/got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "version": "11.8.5", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", + "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", "@types/cacheable-request": "^6.0.1", "@types/responselike": "^1.0.0", "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.1", + "cacheable-request": "^7.0.2", "decompress-response": "^6.0.0", "http2-wrapper": "^1.0.0-beta.5.2", "lowercase-keys": "^2.0.0", @@ -13804,9 +13804,9 @@ } }, "node_modules/shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" }, "node_modules/side-channel": { "version": "1.0.4", @@ -22650,16 +22650,16 @@ } }, "got": { - "version": "11.8.2", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", - "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "version": "11.8.5", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", + "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", "requires": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", "@types/cacheable-request": "^6.0.1", "@types/responselike": "^1.0.0", "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.1", + "cacheable-request": "^7.0.2", "decompress-response": "^6.0.0", "http2-wrapper": "^1.0.0-beta.5.2", "lowercase-keys": "^2.0.0", @@ -27611,9 +27611,9 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" }, "side-channel": { "version": "1.0.4", diff --git a/packages/noco-i18n/package-lock.json b/packages/noco-i18n/package-lock.json index 0534c88b81..db60a0be16 100644 --- a/packages/noco-i18n/package-lock.json +++ b/packages/noco-i18n/package-lock.json @@ -9793,9 +9793,9 @@ "dev": true }, "shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", "dev": true }, "side-channel": { diff --git a/packages/nocodb-sdk/src/index.ts b/packages/nocodb-sdk/src/index.ts index 805152d812..561b841c36 100644 --- a/packages/nocodb-sdk/src/index.ts +++ b/packages/nocodb-sdk/src/index.ts @@ -5,6 +5,7 @@ export * from './lib/sqlUi'; export * from './lib/globals'; export * from './lib/helperFunctions'; export * from './lib/formulaHelpers'; -export * from './lib/passwordHelpers'; export { default as UITypes, isVirtualCol } from './lib/UITypes'; export { default as CustomAPI } from './lib/CustomAPI'; +export { default as TemplateGenerator } from './lib/TemplateGenerator'; +export * from './lib/passwordHelpers'; diff --git a/packages/nocodb-sdk/src/lib/Api.ts b/packages/nocodb-sdk/src/lib/Api.ts index b9ab9d3e20..950123a8ad 100644 --- a/packages/nocodb-sdk/src/lib/Api.ts +++ b/packages/nocodb-sdk/src/lib/Api.ts @@ -3197,12 +3197,28 @@ export class Api< * * @tags Utils * @name AppVersion - * @request GET:/api/v1/db/meta/nocodb/version + * @request GET:/api/v1/version * @response `200` `any` OK */ appVersion: (params: RequestParams = {}) => this.request({ - path: `/api/v1/db/meta/nocodb/version`, + path: `/api/v1/version`, + method: 'GET', + format: 'json', + ...params, + }), + + /** + * No description + * + * @tags Utils + * @name AppHealth + * @request GET:/api/v1/health + * @response `200` `any` OK + */ + appHealth: (params: RequestParams = {}) => + this.request({ + path: `/api/v1/health`, method: 'GET', format: 'json', ...params, diff --git a/packages/nocodb-sdk/src/lib/TemplateGenerator.ts b/packages/nocodb-sdk/src/lib/TemplateGenerator.ts new file mode 100644 index 0000000000..ad74741b65 --- /dev/null +++ b/packages/nocodb-sdk/src/lib/TemplateGenerator.ts @@ -0,0 +1,30 @@ +import UITypes from './UITypes'; + +export interface Column { + column_name: string; + ref_column_name: string; + uidt?: UITypes; + dtxp?: any; + dt?: any; +} +export interface Table { + table_name: string; + ref_table_name: string; + columns: Array; +} +export interface Template { + title: string; + tables: Array; +} + +export default abstract class TemplateGenerator { + abstract parse(): Promise; + abstract parseTemplate(): Promise