Browse Source

feat: cli - unit test, npmp package and executable build

pull/9499/head
Pranav C 2 months ago
parent
commit
511b929ffa
  1. 7
      packages/nc-secret-cli/src/core/NcConfig.ts
  2. 3
      packages/nc-secret-cli/src/core/NcError.ts
  3. 27
      packages/nc-secret-cli/src/core/NcLogger.ts
  4. 30
      packages/nc-secret-cli/src/core/SecretManager.ts
  5. 4
      packages/nc-secret-cli/src/core/index.ts
  6. 17
      packages/nc-secret-cli/src/index.spec.ts
  7. 68
      packages/nc-secret-cli/src/index.ts
  8. 86
      packages/nc-secret-cli/src/nc-config/constants.ts
  9. 326
      packages/nc-secret-cli/src/nc-config/helpers.ts
  10. 4
      packages/nc-secret-cli/src/nc-config/index.ts
  11. 39
      packages/nc-secret-cli/src/nc-config/interfaces.ts
  12. 24
      packages/nc-secret-cli/src/nocodb/cli.js
  13. 6
      packages/nc-secret-cli/tsconfig.json
  14. 46
      packages/nc-secret-cli/webpack.config.js
  15. 5
      packages/nocodb/src/cli.ts
  16. 3
      packages/nocodb/src/index.ts
  17. 10
      packages/nocodb/src/utils/encryptDecrypt.ts
  18. 2
      packages/nocodb/src/utils/globals.ts
  19. 61
      packages/nocodb/webpack.cli.config.js
  20. BIN
      scripts/pkg-secret-cli-executable/binaries/binding/napi-v3-darwin-arm64/node_sqlite3.node
  21. BIN
      scripts/pkg-secret-cli-executable/binaries/binding/napi-v3-darwin-x64/node_sqlite3.node
  22. BIN
      scripts/pkg-secret-cli-executable/binaries/binding/napi-v3-linux-x64/node_sqlite3.node
  23. BIN
      scripts/pkg-secret-cli-executable/binaries/binding/napi-v3-win32-ia32/node_sqlite3.node
  24. BIN
      scripts/pkg-secret-cli-executable/binaries/binding/napi-v3-win32-x64/node_sqlite3.node
  25. 13
      scripts/pkg-secret-cli-executable/index.js

7
packages/nc-secret-cli/src/nc-config/NcConfig.ts → packages/nc-secret-cli/src/core/NcConfig.ts

@ -1,14 +1,11 @@
import * as path from 'path'; import * as path from 'path';
import fs from 'fs'; import fs from 'fs';
import { promisify } from 'util'; import { promisify } from 'util';
import { getToolDir, metaUrlToDbConfig } from './helpers'; const { DriverClient, getToolDir, metaUrlToDbConfig } = require( '../nocodb/cli');
import { DriverClient } from './interfaces';
import type { DbConfig } from './interfaces';
import { SqlClientFactory } from 'nocodb';
export class NcConfig { export class NcConfig {
meta: { meta: {
db: DbConfig; db: any;
} = { } = {
db: { db: {
client: DriverClient.SQLITE, client: DriverClient.SQLITE,

3
packages/nc-secret-cli/src/core/NcError.ts

@ -0,0 +1,3 @@
export class NcError extends Error {
}

27
packages/nc-secret-cli/src/core/NcLogger.ts

@ -0,0 +1,27 @@
// a class to log messages to the console with colors and styles
export class NcLogger {
static log(message: string) {
console.log(message);
}
static error(message: string) {
console.error('\x1b[31m%s\x1b[0m', 'Error: ' + message);
}
static warn(message: string) {
console.warn('\x1b[33m%s\x1b[0m', 'Warning: ' + message);
}
static info(message: string) {
console.info('\x1b[32m%s\x1b[0m', 'Info: ' + message);
}
static success(message: string) {
console.log('\x1b[32m%s\x1b[0m', 'Success: ' + message);
}
static debug(message: string) {
console.debug('\x1b[34m%s\x1b[0m', 'Debug: ' + message);
}
}

30
packages/nc-secret-cli/src/core/SecretManager.ts

@ -1,4 +1,6 @@
import { SqlClientFactory, MetaTable, decryptPropIfRequired, encryptPropIfRequired } from 'nocodb'; import {NcError} from "./NcError";
const { SqlClientFactory, MetaTable, decryptPropIfRequired, encryptPropIfRequired } = require('../nocodb/cli')
export class SecretManager { export class SecretManager {
@ -14,19 +16,34 @@ export class SecretManager {
// use the sqlClientFactory to create a new sql client and then use testConnection to test the connection // use the sqlClientFactory to create a new sql client and then use testConnection to test the connection
const isValid = await this.sqlClient.testConnection(); const isValid = await this.sqlClient.testConnection();
if (!isValid) { if (!isValid) {
throw new Error('Invalid database configuration'); throw new NcError('Invalid database configuration');
} }
} }
async validateAndExtract() { async validateAndExtract() {
// check if tables are present in the database
if (!(await this.sqlClient.knex.schema.hasTable(MetaTable.SOURCES))) {
throw new NcError('Sources table not found');
}
if (!(await this.sqlClient.knex.schema.hasTable(MetaTable.INTEGRATIONS))) {
throw new NcError('Integrations table not found');
}
// if is_encrypted column is not present in the sources table then throw an error
if(
!(await this.sqlClient.knex.schema.hasColumn(MetaTable.SOURCES, 'is_encrypted')) ||
!(await this.sqlClient.knex.schema.hasColumn(MetaTable.INTEGRATIONS, 'is_encrypted'))){
throw new NcError('Looks like you are using an older version of NocoDB. Please upgrade to the latest version and try again.');
}
const sources = await this.sqlClient.knex(MetaTable.SOURCES).where(qb => { const sources = await this.sqlClient.knex(MetaTable.SOURCES).where(qb => {
qb.where('is_meta', false).orWhere('is_meta', null) qb.where('is_meta', false).orWhere('is_meta', null)
}); });
const integrations = await this.sqlClient.knex(MetaTable.INTEGRATIONS).where(qb => { const integrations = await this.sqlClient.knex(MetaTable.INTEGRATIONS);
qb.where('is_meta', false).orWhere('is_meta', null)
});
const sourcesToUpdate: Record<string, any>[] = []; const sourcesToUpdate: Record<string, any>[] = [];
const integrationsToUpdate: Record<string, any>[] = []; const integrationsToUpdate: Record<string, any>[] = [];
@ -63,10 +80,11 @@ export class SecretManager {
// if all of the decyptions are failed then throw an error // if all of the decyptions are failed then throw an error
if (!isValid) { if (!isValid) {
throw new Error('Invalid old secret or no sources/integrations found'); throw new NcError('Invalid old secret or no sources/integrations found');
} }
return { sourcesToUpdate, integrationsToUpdate }; return { sourcesToUpdate, integrationsToUpdate };
} }

4
packages/nc-secret-cli/src/core/index.ts

@ -0,0 +1,4 @@
export * from './NcConfig';
export * from './NcError';
export * from './NcLogger';
export * from './SecretManager';

17
packages/nc-secret-cli/src/index.spec.ts

@ -0,0 +1,17 @@
import { describe, it } from 'mocha';
import { expect } from 'chai';
import { program } from 'commander';
describe('Index', () => {
describe('index.ts', () => {
it('should parse the arguments and options correctly', () => {
const argv = ['node', 'index.ts', 'oldSecret', 'newSecret', '--nc-db','test_db_url', '--database-url', 'test_db_url', '-o', 'oldSecret', '-n', 'newSecret'];
program.parse(argv);
expect(program.opts().oldSecret).to.equal('oldSecret');
expect(program.opts().newSecret).to.equal('newSecret');
expect(program.opts().ncDb).to.equal('test_db_url');
expect(program.opts().databaseUrl).to.equal('test_db_url');
});
});
});

68
packages/nc-secret-cli/src/index.ts

@ -1,39 +1,58 @@
import figlet from "figlet"; import figlet from "figlet";
console.log(figlet.textSync("Nocodb Secret CLI"));
import { Command } from 'commander'; import { Command } from 'commander';
import { getNocoConfig } from "./nc-config"; import { getNocoConfig } from "./core/NcConfig";
import { SecretManager } from "./core/SecretManager"; import { SecretManager } from "./core/SecretManager";
import { NcError } from "./core/NcError";
import { NcLogger } from "./core/NcLogger";
console.log(figlet.textSync("NocoDB Secret CLI"));
const program = new Command(); const program = new Command();
program program
.version('1.0.0') .version('1.0.0')
.description('NocoDB Secret CLI') .description('NocoDB Secret CLI')
.arguments('<oldSecret> <newSecret>') .arguments('<oldSecret> <newSecret>')
.action(async (key, value) => { .option('--nc-db <nc-db>', 'NocoDB connection database url, equivalent to NC_DB env variable')
.option('--nc-db-json <nc-db-json>', 'NocoDB connection database json, equivalent to NC_DB_JSON env variable')
.option('--nc-db-json-file <nc-db-json-file>', 'NocoDB connection database json file path, equivalent to NC_DB_JSON_FILE env variable')
.option('--database-url <database-url>', 'JDBC database url, equivalent to DATABASE_URL env variable')
.option('--database-url-file <database-url-file>', 'JDBC database url file path, equivalent to DATABASE_URL_FILE env variable')
.option('-o, --old-secret <old-secret>', 'old secret string to decrypt sources and integrations')
.option('-n, --new-secret <new-secret>', 'new secret string to encrypt sources and integrations')
.action(async (key, value, ...rest) => {
try {
const config = await getNocoConfig();
const config = await getNocoConfig(); if (!key || !value) {
console.error('Error: Both key and value are required.');
program.help();
} else {
const secretManager = new SecretManager(key, value, config);
if (!key || !value) { // validate meta db config which is resolved from env variables
console.error('Error: Both key and value are required.'); await secretManager.validateConfig();
program.help();
} else {
const secretManager = new SecretManager(key, value, config);
// validate meta db config which is resolved from env variables // validate old secret
await secretManager.validateConfig(); const { sourcesToUpdate, integrationsToUpdate } = await secretManager.validateAndExtract();
// validate old secret
const { sourcesToUpdate, integrationsToUpdate } = await secretManager.validateAndExtract();
// update sources and integrations
await secretManager.updateSecret(sourcesToUpdate, integrationsToUpdate);
// update sources and integrations }
await secretManager.updateSecret(sourcesToUpdate, integrationsToUpdate); } catch (e) {
if (e instanceof NcError) {
// print error message in a better way
NcLogger.error(e.message);
} process.exit(1);
}); }
console.error(e);
}
});
@ -41,3 +60,8 @@ program
program.exitOverride(); program.exitOverride();
program.parse(process.argv); program.parse(process.argv);

86
packages/nc-secret-cli/src/nc-config/constants.ts

@ -1,86 +0,0 @@
export const driverClientMapping = {
mysql: 'mysql2',
mariadb: 'mysql2',
postgres: 'pg',
postgresql: 'pg',
sqlite: 'sqlite3',
mssql: 'mssql',
};
export const defaultClientPortMapping = {
mysql: 3306,
mysql2: 3306,
postgres: 5432,
pg: 5432,
mssql: 1433,
};
export const defaultConnectionConfig: any = {
// https://github.com/knex/knex/issues/97
// timezone: process.env.NC_TIMEZONE || 'UTC',
dateStrings: true,
};
// default knex options
export const defaultConnectionOptions = {
pool: {
min: 0,
max: 10,
},
};
export const avoidSSL = [
'localhost',
'127.0.0.1',
'host.docker.internal',
'172.17.0.1',
];
export const knownQueryParams = [
{
parameter: 'database',
aliases: ['d', 'db'],
},
{
parameter: 'password',
aliases: ['p'],
},
{
parameter: 'user',
aliases: ['u'],
},
{
parameter: 'title',
aliases: ['t'],
},
{
parameter: 'keyFilePath',
aliases: [],
},
{
parameter: 'certFilePath',
aliases: [],
},
{
parameter: 'caFilePath',
aliases: [],
},
{
parameter: 'ssl',
aliases: [],
},
{
parameter: 'options',
aliases: ['opt', 'opts'],
},
];
export enum DriverClient {
MYSQL = 'mysql2',
MYSQL_LEGACY = 'mysql',
MSSQL = 'mssql',
PG = 'pg',
SQLITE = 'sqlite3',
SNOWFLAKE = 'snowflake',
DATABRICKS = 'databricks',
}

326
packages/nc-secret-cli/src/nc-config/helpers.ts

@ -1,326 +0,0 @@
import fs from 'fs';
import { URL } from 'url';
import { promisify } from 'util';
import parseDbUrl from 'parse-database-url';
import {
avoidSSL,
defaultClientPortMapping,
defaultConnectionConfig,
defaultConnectionOptions,
driverClientMapping,
knownQueryParams,
} from './constants';
import { DriverClient } from './interfaces';
import type { Connection, DbConfig } from './interfaces';
export async function prepareEnv() {
if (process.env.NC_DATABASE_URL_FILE || process.env.DATABASE_URL_FILE) {
const database_url = await promisify(fs.readFile)(
(process.env.NC_DATABASE_URL_FILE || process.env.DATABASE_URL_FILE) as string,
'utf-8',
);
process.env.NC_DB = jdbcToXcUrl(database_url);
} else if (process.env.NC_DATABASE_URL || process.env.DATABASE_URL) {
process.env.NC_DB = jdbcToXcUrl(
(process.env.NC_DATABASE_URL || process.env.DATABASE_URL) as string,
);
}
}
export function getToolDir() {
return process.env.NC_TOOL_DIR || process.cwd();
}
export function jdbcToXcConfig(url: string): DbConfig {
// drop the jdbc prefix
url.replace(/^jdbc:/, '');
const config = parseDbUrl(url);
const parsedConfig: Connection = {};
for (const [key, value] of Object.entries(config)) {
const fnd = knownQueryParams.find(
(param) => param.parameter === key || param.aliases.includes(key),
);
if (fnd) {
parsedConfig[fnd.parameter] = value;
} else {
parsedConfig[key] = value;
}
}
if (!parsedConfig?.port) {
parsedConfig.port =
defaultClientPortMapping[
driverClientMapping[parsedConfig.driver as DriverClient] || parsedConfig.driver
];
}
const { driver, ...connectionConfig } = parsedConfig;
const client = driverClientMapping[driver as DriverClient] || driver;
if (
client === 'pg' &&
!connectionConfig?.ssl &&
!avoidSSL.includes(connectionConfig.host as string)
) {
connectionConfig.ssl = true;
}
return {
client: client,
connection: {
...connectionConfig,
},
} as DbConfig;
}
export function jdbcToXcUrl(url: string): string {
// drop the jdbc prefix
url.replace(/^jdbc:/, '');
const config = parseDbUrl(url);
const parsedConfig: Connection = {};
for (const [key, value] of Object.entries(config)) {
const fnd = knownQueryParams.find(
(param) => param.parameter === key || param.aliases.includes(key),
);
if (fnd) {
parsedConfig[fnd.parameter] = value;
} else {
parsedConfig[key] = value;
}
}
if (!parsedConfig?.port) {
parsedConfig.port =
defaultClientPortMapping[
driverClientMapping[parsedConfig.driver as DriverClient] || parsedConfig.driver
];
}
const { driver, host, port, database, user, password, ...extra } =
parsedConfig;
const extraParams: string[] = [];
for (const [key, value] of Object.entries(extra)) {
extraParams.push(`${key}=${encodeURIComponent(String(value))}`);
}
const res = `${driverClientMapping[driver as DriverClient] || driver}://${host}${
port ? `:${port}` : ''
}?${user ? `u=${encodeURIComponent(user)}&` : ''}${
password ? `p=${encodeURIComponent(password)}&` : ''
}${database ? `d=${encodeURIComponent(database)}&` : ''}${extraParams.join(
'&',
)}`;
return res;
}
export function xcUrlToDbConfig(
urlString: string,
key = '',
type?: string,
): DbConfig {
const url = new URL(urlString);
let dbConfig: DbConfig;
if (url.protocol.startsWith('sqlite3')) {
dbConfig = {
client: 'sqlite3',
connection: {
client: 'sqlite3',
connection: {
filename:
url.searchParams.get('d') || url.searchParams.get('database'),
},
database: url.searchParams.get('d') || url.searchParams.get('database'),
},
} as any;
} else {
const parsedQuery = {};
for (const [key, value] of url.searchParams.entries()) {
const fnd = knownQueryParams.find(
(param) => param.parameter === key || param.aliases.includes(key),
);
if (fnd) {
parsedQuery[fnd.parameter] = value;
} else {
parsedQuery[key] = value;
}
}
dbConfig = {
client: url.protocol.replace(':', '') as DriverClient,
connection: {
...parsedQuery,
host: url.hostname,
port: +url.port,
},
acquireConnectionTimeout: 600000,
};
if (process.env.NODE_TLS_REJECT_UNAUTHORIZED) {
dbConfig.connection.ssl = true;
}
if (
url.searchParams.get('keyFilePath') &&
url.searchParams.get('certFilePath') &&
url.searchParams.get('caFilePath')
) {
dbConfig.connection.ssl = {
keyFilePath: url.searchParams.get('keyFilePath') as string,
certFilePath: url.searchParams.get('certFilePath') as string,
caFilePath: url.searchParams.get('caFilePath') as string,
};
}
}
/* TODO check if this is needed
if (config && !config.title) {
config.title =
url.searchParams.get('t') ||
url.searchParams.get('title') ||
this.generateRandomTitle();
}
*/
Object.assign(dbConfig, {
meta: {
tn: 'nc_evolutions',
allSchemas:
!!url.searchParams.get('allSchemas') ||
!(url.searchParams.get('d') || url.searchParams.get('database')),
api: {
prefix: url.searchParams.get('apiPrefix') || '',
swagger: true,
type:
type ||
((url.searchParams.get('api') || url.searchParams.get('a')) as any) ||
'rest',
},
dbAlias: url.searchParams.get('dbAlias') || `db${key}`,
metaTables: 'db',
migrations: {
disabled: false,
name: 'nc_evolutions',
},
},
});
return dbConfig;
}
export async function metaUrlToDbConfig(urlString): Promise<DbConfig> {
const url = new URL(urlString);
let dbConfig: DbConfig;
if (url.protocol.startsWith('sqlite3')) {
const db = url.searchParams.get('d') || url.searchParams.get('database');
dbConfig = {
client: DriverClient.SQLITE,
connection: {
filename: db as string,
},
...(db === ':memory:'
? {
pool: {
min: 1,
max: 1,
// disposeTimeout: 360000*1000,
idleTimeoutMillis: 360000 * 1000,
},
}
: {}),
};
} else {
const parsedQuery = {};
for (const [key, value] of url.searchParams.entries()) {
const fnd = knownQueryParams.find(
(param) => param.parameter === key || param.aliases.includes(key),
);
if (fnd) {
parsedQuery[fnd.parameter] = value;
} else {
parsedQuery[key] = value;
}
}
dbConfig = {
client: url.protocol.replace(':', '') as DriverClient,
connection: {
...defaultConnectionConfig,
...parsedQuery,
host: url.hostname,
port: +url.port,
},
acquireConnectionTimeout: 600000,
...defaultConnectionOptions,
...(url.searchParams.has('search_path')
? {
searchPath: url.searchParams.get('search_path')?.split(','),
}
: {}),
};
if (process.env.NODE_TLS_REJECT_UNAUTHORIZED) {
dbConfig.connection.ssl = true;
}
}
url.searchParams.forEach((_value, key) => {
let value: any = _value;
if (value === 'true') {
value = true;
} else if (value === 'false') {
value = false;
} else if (/^\d+$/.test(value)) {
value = +value;
}
// todo: implement config read from JSON file or JSON env val read
if (
!['password', 'p', 'database', 'd', 'user', 'u', 'search_path'].includes(
key,
)
) {
key.split('.').reduce((obj, k, i, arr) => {
return (obj[k] = i === arr.length - 1 ? value : obj[k] || {});
}, dbConfig);
}
});
if (
dbConfig?.connection?.ssl &&
typeof dbConfig?.connection?.ssl === 'object'
) {
if (dbConfig.connection.ssl.caFilePath && !dbConfig.connection.ssl.ca) {
dbConfig.connection.ssl.ca = (
await promisify(fs.readFile)(dbConfig.connection.ssl.caFilePath)
).toString();
delete dbConfig.connection.ssl.caFilePath;
}
if (dbConfig.connection.ssl.keyFilePath && !dbConfig.connection.ssl.key) {
dbConfig.connection.ssl.key = (
await promisify(fs.readFile)(dbConfig.connection.ssl.keyFilePath)
).toString();
delete dbConfig.connection.ssl.keyFilePath;
}
if (dbConfig.connection.ssl.certFilePath && !dbConfig.connection.ssl.cert) {
dbConfig.connection.ssl.cert = (
await promisify(fs.readFile)(dbConfig.connection.ssl.certFilePath)
).toString();
delete dbConfig.connection.ssl.certFilePath;
}
}
return dbConfig;
}

4
packages/nc-secret-cli/src/nc-config/index.ts

@ -1,4 +0,0 @@
export * from './helpers';
export * from './interfaces';
export * from './constants';
export * from './NcConfig';

39
packages/nc-secret-cli/src/nc-config/interfaces.ts

@ -1,39 +0,0 @@
import { DriverClient } from './constants';
interface Connection {
driver?: DriverClient;
host?: string;
port?: number;
database?: string;
user?: string;
password?: string;
ssl?:
| boolean
| {
ca?: string;
cert?: string;
key?: string;
caFilePath?: string;
certFilePath?: string;
keyFilePath?: string;
};
filename?: string;
}
interface DbConfig {
client: DriverClient;
connection: Connection;
acquireConnectionTimeout?: number;
useNullAsDefault?: boolean;
pool?: {
min?: number;
max?: number;
idleTimeoutMillis?: number;
};
migrations?: {
directory?: string;
tableName?: string;
};
}
export { DriverClient, Connection, DbConfig };

24
packages/nc-secret-cli/src/nocodb/cli.js

File diff suppressed because one or more lines are too long

6
packages/nc-secret-cli/tsconfig.json

@ -9,6 +9,8 @@
"esModuleInterop": true, "esModuleInterop": true,
"moduleResolution": "node", "moduleResolution": "node",
"skipLibCheck": true, "skipLibCheck": true,
"noImplicitAny": false "noImplicitAny": false,
"allowJs": true,
"experimentalDecorators": true
} }
} }

46
packages/nc-secret-cli/webpack.config.js

@ -0,0 +1,46 @@
const nodeExternals = require('webpack-node-externals');
const TerserPlugin = require('terser-webpack-plugin');
const webpack = require('webpack');
const path = require('path');
module.exports = {
entry: './src/index.ts',
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: {
loader: 'ts-loader',
options: {
transpileOnly: true
}
},
},
],
},
optimization: {
minimize: true, //Update this to true or false
minimizer: [new TerserPlugin()],
nodeEnv: false
},
externals: [nodeExternals()],
resolve: {
extensions: ['.tsx', '.ts', '.js', '.json'],
},
output: {
filename: 'cli.js',
path: path.resolve(__dirname, 'dist'),
library: 'libs',
libraryTarget: 'umd',
globalObject: "typeof self !== 'undefined' ? self : this",
},
// node: {
// fs: 'empty'
// },
plugins: [
new webpack.BannerPlugin({banner: "#! /usr/bin/env node", raw: true}),
],
target: 'node',
};

5
packages/nocodb/src/cli.ts

@ -0,0 +1,5 @@
export { SqlClientFactory } from '~/db/sql-client/lib/SqlClientFactory';
export { MetaTable } from '~/utils/globals';
export * from '~/utils/encryptDecrypt';
export { getToolDir, metaUrlToDbConfig } from '~/utils/nc-config/helpers';
export { DriverClient } from '~/utils/nc-config/constants';

3
packages/nocodb/src/index.ts

@ -3,6 +3,3 @@ import Noco from './Noco';
export default Noco; export default Noco;
export { Noco }; export { Noco };
export { SqlClientFactory } from './db/sql-client/lib/SqlClientFactory';
export { MetaTable } from '~/utils/globals'
export * from '~/utils/encryptDecrypt'

10
packages/nocodb/src/utils/encryptDecrypt.ts

@ -1,10 +1,12 @@
import CryptoJS from 'crypto-js'; import CryptoJS from 'crypto-js';
import Noco from '~/Noco';
export const credentialEncyptSecret = process.env.NC_KEY_CREDENTIAL_ENCRYPT;
export const encryptPropIfRequired = ({ export const encryptPropIfRequired = ({
data, data,
prop = 'config', prop = 'config',
secret = Noco.getConfig()?.credentialSecret, secret = credentialEncyptSecret,
}: { }: {
data: Record<string, any>; data: Record<string, any>;
prop?: string; prop?: string;
@ -20,14 +22,14 @@ export const encryptPropIfRequired = ({
return CryptoJS.AES.encrypt( return CryptoJS.AES.encrypt(
JSON.stringify(data[prop]), JSON.stringify(data[prop]),
Noco.getConfig()?.credentialSecret, secret,
).toString(); ).toString();
}; };
export const decryptPropIfRequired = ({ export const decryptPropIfRequired = ({
data, data,
prop = 'config', prop = 'config',
secret = Noco.getConfig()?.credentialSecret, secret = credentialEncyptSecret,
}: { }: {
data: Record<string, any>; data: Record<string, any>;
prop?: string; prop?: string;

2
packages/nocodb/src/utils/globals.ts

@ -1,6 +1,6 @@
export enum MetaTable { export enum MetaTable {
PROJECT = 'nc_bases_v2', PROJECT = 'nc_bases_v2',
SOURCES = 'nc_sources_v2', SOURCES = 'nc_source_v2',
MODELS = 'nc_models_v2', MODELS = 'nc_models_v2',
COLUMNS = 'nc_columns_v2', COLUMNS = 'nc_columns_v2',
COLUMN_VALIDATIONS = 'nc_columns_validations_v2', COLUMN_VALIDATIONS = 'nc_columns_validations_v2',

61
packages/nocodb/webpack.cli.config.js

@ -0,0 +1,61 @@
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const webpack = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
const { resolveTsAliases } = require('./build-utils/resolveTsAliases');
module.exports = {
entry: './src/cli.ts',
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: {
loader: 'ts-loader',
options: {
transpileOnly: true,
},
},
},
],
},
optimization: {
minimize: true, //Update this to true or false
minimizer: [
new TerserPlugin({
extractComments: false,
}),
],
nodeEnv: false,
},
externals: [
nodeExternals({
allowlist: ['nocodb-sdk'],
}),
],
resolve: {
extensions: ['.tsx', '.ts', '.js', '.json'],
alias: resolveTsAliases(path.resolve('tsconfig.json')),
},
mode: 'production',
output: {
filename: 'cli.js',
path: path.resolve(__dirname, '..', 'nc-secret-cli', 'src/nocodb'),
library: 'libs',
libraryTarget: 'umd',
globalObject: "typeof self !== 'undefined' ? self : this",
},
node: {
__dirname: false,
},
plugins: [
new webpack.EnvironmentPlugin(['EE']),
new webpack.BannerPlugin({
banner: 'This is a generated file. Do not edit',
entryOnly:true
}),
],
target: 'node',
};

BIN
scripts/pkg-secret-cli-executable/binaries/binding/napi-v3-darwin-arm64/node_sqlite3.node

Binary file not shown.

BIN
scripts/pkg-secret-cli-executable/binaries/binding/napi-v3-darwin-x64/node_sqlite3.node

Binary file not shown.

BIN
scripts/pkg-secret-cli-executable/binaries/binding/napi-v3-linux-x64/node_sqlite3.node

Binary file not shown.

BIN
scripts/pkg-secret-cli-executable/binaries/binding/napi-v3-win32-ia32/node_sqlite3.node

Binary file not shown.

BIN
scripts/pkg-secret-cli-executable/binaries/binding/napi-v3-win32-x64/node_sqlite3.node

Binary file not shown.

13
scripts/pkg-secret-cli-executable/index.js

@ -0,0 +1,13 @@
process.env.NC_BINARY_BUILD = 'true';
(async () => {
try {
const app = require('express')();
const {Noco} = require("nocodb");
const port = process.env.PORT || 8080;
const httpServer = app.listen(port);
app.use(await Noco.init({}, httpServer, app));
console.log(`Visit : localhost:${port}/dashboard`)
} catch(e) {
console.log(e)
}
})()
Loading…
Cancel
Save