Browse Source

feat: Docker tool directory

Default tool directory is configured as `/usr/app/data/`, so user can mount volume and persist data(meta, uplods, default sqlite meta db, etc..)

re #351

Signed-off-by: Pranav C <61551451+pranavxc@users.noreply.github.com>
pull/359/head
Pranav C 3 years ago
parent
commit
ceb2e11891
  1. 9
      packages/nocodb/Dockerfile
  2. 3
      packages/nocodb/docker/start.sh
  3. 82
      packages/nocodb/src/lib/migrator/SqlMigrator/lib/KnexMigrator.ts
  4. 237
      packages/nocodb/src/lib/migrator/SqlMigrator/lib/NcConfigFactory.ts
  5. 4
      packages/nocodb/src/lib/noco/Noco.ts
  6. 2
      packages/nocodb/src/lib/noco/meta/NcMetaMgr.ts
  7. 6
      packages/nocodb/src/lib/noco/plugins/adapters/storage/Local.ts
  8. 43
      packages/nocodb/src/lib/utils/NcConfigFactory.ts

9
packages/nocodb/Dockerfile

@ -4,11 +4,6 @@
FROM node:12 as builder FROM node:12 as builder
WORKDIR /usr/src/app WORKDIR /usr/src/app
ENV NODE_ENV production
ENV NC_VERSION 0.6
ENV NC_DOCKER 0.6
ENV PORT 8080
# Copy application dependency manifests to the container image. # Copy application dependency manifests to the container image.
# A wildcard is used to ensure both package.json AND package-lock.json are copied. # A wildcard is used to ensure both package.json AND package-lock.json are copied.
# Copying this separately prevents re-running npm ci on every code change. # Copying this separately prevents re-running npm ci on every code change.
@ -31,6 +26,10 @@ RUN npm ci --production --quiet \
FROM alpine:3.12 FROM alpine:3.12
WORKDIR /usr/src/app WORKDIR /usr/src/app
ENV NC_DOCKER 0.6
ENV PORT 8080
ENV NC_TOOL_DIR=/usr/app/data/
RUN apk --update --no-cache add \ RUN apk --update --no-cache add \
nodejs \ nodejs \
tar tar

3
packages/nocodb/docker/start.sh

@ -2,10 +2,11 @@
FILE="/usr/src/app/package.json" FILE="/usr/src/app/package.json"
#sleep 5 #sleep 5
mkdir /usr/src/data
if [ ! -f "$FILE" ] if [ ! -f "$FILE" ]
then then
tar -xzf /usr/src/appEntry/app.tar.gz -C /usr/src/app/ tar -xzf /usr/src/appEntry/app.tar.gz -C /usr/src/app/
fi fi
DEBUG=xc* node docker/main.js node docker/main.js

82
packages/nocodb/src/lib/migrator/SqlMigrator/lib/KnexMigrator.ts

@ -15,8 +15,8 @@ import Emit from "../../util/emit";
import * as fileHelp from "../../util/file.help"; import * as fileHelp from "../../util/file.help";
import NcConfigFactory from './NcConfigFactory';
import SqlMigrator from "./SqlMigrator"; import SqlMigrator from "./SqlMigrator";
import NcConfigFactory from "../../../utils/NcConfigFactory";
const evt = new Emit(); const evt = new Emit();
const log = new Debug("KnexMigrator"); const log = new Debug("KnexMigrator");
@ -33,17 +33,19 @@ export default class KnexMigrator extends SqlMigrator {
// @ts-ignore // @ts-ignore
private project_id: any; private project_id: any;
private metaDb: any; private metaDb: any;
private toolDir: string;
/** /**
* Creates an instance of KnexMigrator. * Creates an instance of KnexMigrator.
* @memberof KnexMigrator * @memberof KnexMigrator
*/ */
constructor(projectObj?:any) { constructor(projectObj?: any) {
super(); super();
this.projectObj = projectObj; this.projectObj = projectObj;
this.project_id = projectObj && projectObj.project_id; this.project_id = projectObj?.project_id;
this.project = projectObj && projectObj.config; this.project = projectObj?.config;
this.metaDb = projectObj && projectObj.metaDb; this.metaDb = projectObj?.metaDb;
this.toolDir = NcConfigFactory.getToolDir();
} }
emit(data, _args?) { emit(data, _args?) {
@ -78,7 +80,7 @@ export default class KnexMigrator extends SqlMigrator {
* @memberof KnexMigrator * @memberof KnexMigrator
*/ */
_getWorkingEnvDir(args) { _getWorkingEnvDir(args) {
return path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, 'migrations'); return path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, 'migrations');
} }
async _initAllEnvOnFilesystem() { async _initAllEnvOnFilesystem() {
@ -113,74 +115,74 @@ export default class KnexMigrator extends SqlMigrator {
async _initDbOnFs(args) { async _initDbOnFs(args) {
this.emit( this.emit(
"Creating folder: ", "Creating folder: ",
path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, 'migrations') path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, 'migrations')
); );
try { try {
await promisify(mkdirp)( await promisify(mkdirp)(
path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, 'migrations') path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, 'migrations')
); );
// @ts-ignore // @ts-ignore
const dirStat = await promisify(fs.stat)( const dirStat = await promisify(fs.stat)(
path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, 'migrations') path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, 'migrations')
); );
await promisify(mkdirp)( await promisify(mkdirp)(
path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, this.project.meta.metaFolder || 'meta') path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, this.project.meta.metaFolder || 'meta')
); );
this.emit( this.emit(
"Creating folder: ", "Creating folder: ",
path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, this.project.meta.seedsFolder) path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, this.project.meta.seedsFolder)
); );
await promisify(mkdirp)( await promisify(mkdirp)(
path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, this.project.meta.seedsFolder) path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, this.project.meta.seedsFolder)
); );
this.emit( this.emit(
"Creating folder: ", "Creating folder: ",
path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, this.project.meta.queriesFolder) path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, this.project.meta.queriesFolder)
); );
await promisify(mkdirp)( await promisify(mkdirp)(
path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, this.project.meta.queriesFolder) path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, this.project.meta.queriesFolder)
); );
this.emit( this.emit(
"Creating folder: ", "Creating folder: ",
path.join(process.cwd(), 'nc', this.project.id, this.project.meta.apisFolder) path.join(this.toolDir, 'nc', this.project.id, this.project.meta.apisFolder)
); );
await promisify(mkdirp)( await promisify(mkdirp)(
path.join(process.cwd(), 'nc', this.project.id, this.project.meta.apisFolder) path.join(this.toolDir, 'nc', this.project.id, this.project.meta.apisFolder)
); );
await promisify(mkdirp)( await promisify(mkdirp)(
path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, this.project.meta.metaFolder || 'meta') path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, this.project.meta.metaFolder || 'meta')
); );
// @ts-ignore // @ts-ignore
const metaStat = await promisify(fs.stat)( const metaStat = await promisify(fs.stat)(
path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, this.project.meta.metaFolder || 'meta') path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, this.project.meta.metaFolder || 'meta')
); );
} catch (e) { } catch (e) {
log.debug( log.debug(
"Error creating folders (migrations, apis, seeds, queries):", "Error creating folders (migrations, apis, seeds, queries):",
path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, 'migrations') path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, 'migrations')
); );
} }
} }
async _cleanFs(args) { async _cleanFs(args) {
this.emit("Removing folder: ", path.join(process.cwd(), 'nc', this.project.id, args.dbAlias)); this.emit("Removing folder: ", path.join(this.toolDir, 'nc', this.project.id, args.dbAlias));
try { try {
await promisify(rmdir)(path.join(process.cwd(), 'nc', this.project.id, args.dbAlias)); await promisify(rmdir)(path.join(this.toolDir, 'nc', this.project.id, args.dbAlias));
} catch (e) { } catch (e) {
log.debug( log.debug(
"Error removing folder:", "Error removing folder:",
path.join(process.cwd(), 'nc', this.project.id, args.dbAlias), path.join(this.toolDir, 'nc', this.project.id, args.dbAlias),
e e
); );
} }
@ -188,7 +190,7 @@ export default class KnexMigrator extends SqlMigrator {
async _readProjectJson(projJsonFilePath = null) { async _readProjectJson(projJsonFilePath = null) {
try { try {
// projJsonFilePath = `${path.join(process.cwd(), "config.xc.json")}`; // projJsonFilePath = `${path.join(this.toolDir, "config.xc.json")}`;
log.debug("_readProjectJson", projJsonFilePath); log.debug("_readProjectJson", projJsonFilePath);
const exists = await promisify(fs.exists)(projJsonFilePath); const exists = await promisify(fs.exists)(projJsonFilePath);
@ -202,7 +204,7 @@ export default class KnexMigrator extends SqlMigrator {
this.project = JSON.parse(this.project, (_key, value) => { this.project = JSON.parse(this.project, (_key, value) => {
return typeof value === 'string' ? Handlebars.compile(value, {noEscape: true})(process.env) : value; return typeof value === 'string' ? Handlebars.compile(value, {noEscape: true})(process.env) : value;
}); });
this.project.folder = process.cwd() || path.dirname(projJsonFilePath) this.project.folder = this.toolDir || path.dirname(projJsonFilePath)
} else { } else {
throw new Error("Project file should have got created"); throw new Error("Project file should have got created");
} }
@ -214,7 +216,7 @@ export default class KnexMigrator extends SqlMigrator {
async _initProjectJsonFile(args) { async _initProjectJsonFile(args) {
try { try {
if (!args.folder) { if (!args.folder) {
args.folder = process.cwd(); args.folder = this.toolDir;
} }
const projJsonFilePath = `${path.join(args.folder, "config.xc.json")}`; const projJsonFilePath = `${path.join(args.folder, "config.xc.json")}`;
@ -450,7 +452,7 @@ export default class KnexMigrator extends SqlMigrator {
} }
} }
async _migrationsUp(args):Promise<any> { async _migrationsUp(args): Promise<any> {
const result = new Result(); const result = new Result();
@ -1087,9 +1089,9 @@ export default class KnexMigrator extends SqlMigrator {
migrationSteps: args.migrationSteps, migrationSteps: args.migrationSteps,
file: args.file, file: args.file,
onlyList: args.onlyList, onlyList: args.onlyList,
upFilesPattern: path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, 'migrations', '*.up.sql'), upFilesPattern: path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, 'migrations', '*.up.sql'),
downFilesPattern: path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, 'migrations', '*.down.sql'), downFilesPattern: path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, 'migrations', '*.down.sql'),
tn: this._getEvolutionsTablename(args),//`${process.cwd()}`, tn: this._getEvolutionsTablename(args),//`${this.toolDir}`,
sqlContentMigrate: args.sqlContentMigrate sqlContentMigrate: args.sqlContentMigrate
}); });
} }
@ -1127,8 +1129,8 @@ export default class KnexMigrator extends SqlMigrator {
migrationSteps: args.migrationSteps, migrationSteps: args.migrationSteps,
onlyList: args.onlyList, onlyList: args.onlyList,
file: args.file, file: args.file,
upFilesPattern: path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, 'migrations', '*.up.sql'), upFilesPattern: path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, 'migrations', '*.up.sql'),
downFilesPattern: path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, 'migrations', '*.down.sql'), downFilesPattern: path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, 'migrations', '*.down.sql'),
tn: this._getEvolutionsTablename(args),//`_evolutions`, tn: this._getEvolutionsTablename(args),//`_evolutions`,
sqlContentMigrate: args.sqlContentMigrate sqlContentMigrate: args.sqlContentMigrate
}); });
@ -1280,8 +1282,8 @@ export default class KnexMigrator extends SqlMigrator {
result.data.object.up = migration.up; result.data.object.up = migration.up;
result.data.object.down = migration.down; result.data.object.down = migration.down;
} else { } else {
const upFilePath = path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, 'migrations', args.title); const upFilePath = path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, 'migrations', args.title);
const downFilePath = path.join(process.cwd(), 'nc', this.project.id, args.dbAlias, 'migrations', args.titleDown); const downFilePath = path.join(this.toolDir, 'nc', this.project.id, args.dbAlias, 'migrations', args.titleDown);
result.data.object.up = await promisify(fs.readFile)(upFilePath, "utf8"); result.data.object.up = await promisify(fs.readFile)(upFilePath, "utf8");
result.data.object.down = await promisify(fs.readFile)( result.data.object.down = await promisify(fs.readFile)(
@ -1348,7 +1350,7 @@ export default class KnexMigrator extends SqlMigrator {
// // if (args.folder) { // // if (args.folder) {
// // await this._readProjectJson(path.join(args.folder, "config.xc.json")); // // await this._readProjectJson(path.join(args.folder, "config.xc.json"));
// // } else { // // } else {
// // await this._readProjectJson(path.join(process.cwd(), "config.xc.json")); // // await this._readProjectJson(path.join(this.toolDir, "config.xc.json"));
// // } // // }
// // } // // }
// // // //
@ -1361,7 +1363,7 @@ export default class KnexMigrator extends SqlMigrator {
/** /**
* *
* @param args * @param args
* @param {String} args.folder - defaults to process.cwd() * @param {String} args.folder - defaults to this.toolDir
* @param {String} args.key * @param {String} args.key
* @param {String} args.value * @param {String} args.value
* @returns {Result} * @returns {Result}
@ -1369,7 +1371,7 @@ export default class KnexMigrator extends SqlMigrator {
async migrationsRenameProjectKey(args) { async migrationsRenameProjectKey(args) {
const func = this.migrationsRenameProjectKey.name; const func = this.migrationsRenameProjectKey.name;
const result:any = new Result(); const result: any = new Result();
log.api(`${func}:args:`, args); log.api(`${func}:args:`, args);
try { try {
@ -1384,7 +1386,7 @@ export default class KnexMigrator extends SqlMigrator {
if (args.key in this.project) { if (args.key in this.project) {
this.project.key = args.value; this.project.key = args.value;
await this._writeProjectJson(process.cwd(), this.project); await this._writeProjectJson(this.toolDir, this.project);
} }
this.emitE(`Project key('${args.key}') is set to value successfully ${args.value}`); this.emitE(`Project key('${args.key}') is set to value successfully ${args.value}`);
@ -1438,7 +1440,7 @@ export default class KnexMigrator extends SqlMigrator {
this.project[args.env] = []; this.project[args.env] = [];
} }
await this._writeProjectJson(process.cwd(), this.project); await this._writeProjectJson(this.toolDir, this.project);
await this._initEnvDbsWithSql(args.env) await this._initEnvDbsWithSql(args.env)
this.emitE(`Environment ' ${args.env} ' created succesfully in project.`); this.emitE(`Environment ' ${args.env} ' created succesfully in project.`);
} }
@ -1486,7 +1488,7 @@ export default class KnexMigrator extends SqlMigrator {
await this._cleanEnvDbsWithSql(args) await this._cleanEnvDbsWithSql(args)
delete this.project.envs[args.env]; delete this.project.envs[args.env];
await this._writeProjectJson(process.cwd(), this.project); await this._writeProjectJson(this.toolDir, this.project);
this.emitE(`${args.env} deleted`); this.emitE(`${args.env} deleted`);
} else { } else {
@ -1572,7 +1574,7 @@ export default class KnexMigrator extends SqlMigrator {
// TODO : init db for this dbAlias // TODO : init db for this dbAlias
await this._writeProjectJson(process.cwd(), this.project); await this._writeProjectJson(this.toolDir, this.project);
} else { } else {

237
packages/nocodb/src/lib/migrator/SqlMigrator/lib/NcConfigFactory.ts

@ -1,237 +0,0 @@
import fs from 'fs';
import path from 'path';
// const {uniqueNamesGenerator, starWars, adjectives, animals} = require('unique-names-generator');
export default class NcConfigFactory {
static make() {
const config: any = new NcConfigFactory();
const dbUrls = Object.keys(process.env).filter(envKey => envKey.startsWith('NC_DB_URL'));
for (const key of dbUrls.sort()) {
const dbConfig = this.urlToDbConfig(process.env[key], key.slice(9), config);
config.envs[process.env.NODE_ENV || 'dev'].db.push(dbConfig);
}
if (process.env.NC_AUTH_ADMIN_SECRET) {
config.auth = {
masterKey: {
secret: process.env.NC_AUTH_ADMIN_SECRET
}
};
} else if (process.env.NC_NO_AUTH) {
config.auth = {
disabled: true
};
} else if (config.envs[process.env.NODE_ENV || 'dev'].db[0]) {
config.auth = {
jwt: {
dbAlias: process.env.NC_AUTH_JWT_DB_ALIAS || config.envs[process.env.NODE_ENV || 'dev'].db[0].meta.dbAlias,
secret: process.env.NC_AUTH_JWT_SECRET || 'sdjhjdhkshdkjhskdkjshk' // uuidv4()
}
};
}
if (process.env.NC_DB) {
config.meta.db = this.metaUrlToDbConfig(process.env.NC_DB)
}
config.port = +(process.env.PORT || 8080);
config.env = process.env.NODE_ENV || 'dev';
config.workingEnv = process.env.NODE_ENV || 'dev';
config.folder = config.toolDir = process.env.NC_TOOL_DIR || process.cwd();
return config;
}
static hasDbUrl() {
return Object.keys(process.env).some(envKey => envKey.startsWith('NC_DB_URL'));
}
static makeFromUrls(urls) {
const config: any = new NcConfigFactory();
config.envs[process.env.NODE_ENV || 'dev'].db = [];
for (const [i, url] of Object.entries(urls)) {
config.envs[process.env.NODE_ENV || 'dev'].db.push(this.urlToDbConfig(url, i));
}
return config;
}
static urlToDbConfig(urlString, key, config?) {
const url = new URL(urlString);
let 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'),
"useNullAsDefault": true
},
};
} else {
dbConfig = {
client: url.protocol.replace(':', ''),
"connection": {
database: url.searchParams.get('d') || url.searchParams.get('database'),
"host": url.hostname,
"password": url.searchParams.get('p') || url.searchParams.get('password'),
"port": +url.port,
'user': url.searchParams.get('u') || url.searchParams.get('user'),
},
pool: {
min: 5,
max: 50
},
acquireConnectionTimeout: 600000,
};
if (url.searchParams.get('keyFilePath') && url.searchParams.get('certFilePath') && url.searchParams.get('caFilePath')) {
dbConfig.connection.ssl = {
keyFilePath: url.searchParams.get('keyFilePath'),
certFilePath: url.searchParams.get('certFilePath'),
caFilePath: url.searchParams.get('caFilePath'),
}
}
}
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: url.searchParams.get('api') || url.searchParams.get('a') || "rest",
},
dbAlias: url.searchParams.get('dbAlias') || `db${key}`,
metaTables: 'db',
migrations: {
disabled: false,
name: "nc_evolutions"
}
}
})
return dbConfig;
}
static generateRandomTitle() {
return 'test'
// return uniqueNamesGenerator({
// dictionaries: [[starWars], [adjectives, animals]][Math.floor(Math.random() * 2)]
// }).toLowerCase().replace(/[ -]/g, '_');
}
static metaUrlToDbConfig(urlString) {
const url = new URL(urlString);
let dbConfig;
if (url.protocol.startsWith('sqlite3')) {
dbConfig = {
"client": "sqlite3",
"connection": {
"filename": url.searchParams.get('d') || url.searchParams.get('database')
}
}
} else {
dbConfig = {
client: url.protocol.replace(':', ''),
"connection": {
database: url.searchParams.get('d') || url.searchParams.get('database'),
"host": url.hostname,
"password": url.searchParams.get('p') || url.searchParams.get('password'),
"port": +url.port,
'user': url.searchParams.get('u') || url.searchParams.get('user'),
},
pool: {
min: 5,
max: 50
},
acquireConnectionTimeout: 600000,
};
}
return dbConfig
}
static metaDbCreateIfNotExist(args) {
const dbPath = path.join(args.toolDir, 'noco.db')
const exists = fs.existsSync(dbPath);
if (!exists) {
const fd = fs.openSync(dbPath, "w");
fs.closeSync(fd);
}
}
// version = '0.6';
// port;
// auth;
// env;
// workingEnv;
// toolDir;
// envs;
// queriesFolder;
// seedsFolder;
// title;
// meta = {
// "db": {
// "client": "sqlite3",
// "connection": {
// "filename": "xc.db"
// }
// }
// }
//@ts-ignore
private envs: any;
constructor() {
this.envs = {dev: {db: []}};
}
}
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

4
packages/nocodb/src/lib/noco/Noco.ts

@ -292,7 +292,7 @@ export default class Noco {
break; break;
case 'projectUpdateByWeb': case 'projectUpdateByWeb':
this.config.toolDir = process.cwd(); this.config.toolDir = this.config.toolDir || process.cwd();
this.config.workingEnv = this.env; this.config.workingEnv = this.env;
this.ncMeta.setConfig(this.config); this.ncMeta.setConfig(this.config);
this.metaMgr.setConfig(this.config); this.metaMgr.setConfig(this.config);
@ -307,7 +307,7 @@ export default class Noco {
case 'projectChangeEnv': case 'projectChangeEnv':
try { try {
this.config = importFresh(path.join(process.cwd(), 'config.xc.json')) as NcConfig; this.config = importFresh(path.join(process.cwd(), 'config.xc.json')) as NcConfig;
this.config.toolDir = process.cwd(); this.config.toolDir = this.config.toolDir || process.cwd();
this.ncMeta.setConfig(this.config); this.ncMeta.setConfig(this.config);
this.metaMgr.setConfig(this.config); this.metaMgr.setConfig(this.config);
Object.assign(process.env, {NODE_ENV: this.env = this.config.workingEnv}); Object.assign(process.env, {NODE_ENV: this.env = this.config.workingEnv});

2
packages/nocodb/src/lib/noco/meta/NcMetaMgr.ts

@ -109,7 +109,7 @@ export default class NcMetaMgr {
})); }));
if (!process.env.NC_SERVERLESS_TYPE && !this.config.try) { if (!process.env.NC_SERVERLESS_TYPE && !this.config.try) {
const upload = multer({dest: 'uploads/'}) const upload = multer({dest: path.join(this.config.toolDir, 'uploads')})
router.post(this.config.dashboardPath, upload.single('file')) router.post(this.config.dashboardPath, upload.single('file'))
} }

6
packages/nocodb/src/lib/noco/plugins/adapters/storage/Local.ts

@ -4,6 +4,7 @@ import path from "path";
import mkdirp from "mkdirp"; import mkdirp from "mkdirp";
import IStorageAdapter, {XcFile} from "../../../../../interface/IStorageAdapter"; import IStorageAdapter, {XcFile} from "../../../../../interface/IStorageAdapter";
import NcConfigFactory from "../../../../utils/NcConfigFactory";
export default class Local implements IStorageAdapter { export default class Local implements IStorageAdapter {
@ -11,7 +12,7 @@ export default class Local implements IStorageAdapter {
} }
public async fileCreate(key: string, file: XcFile): Promise<any> { public async fileCreate(key: string, file: XcFile): Promise<any> {
const destPath = path.join(...key.split('/')); const destPath = path.join(NcConfigFactory.getToolDir(), ...key.split('/'));
try { try {
mkdirp.sync(path.dirname(destPath)); mkdirp.sync(path.dirname(destPath));
await fs.promises.rename(file.path, destPath); await fs.promises.rename(file.path, destPath);
@ -20,13 +21,14 @@ export default class Local implements IStorageAdapter {
} }
} }
// todo: implement
fileDelete(_path: string): Promise<any> { fileDelete(_path: string): Promise<any> {
return Promise.resolve(undefined); return Promise.resolve(undefined);
} }
public async fileRead(filePath: string): Promise<any> { public async fileRead(filePath: string): Promise<any> {
try { try {
const fileData = await fs.promises.readFile(filePath); const fileData = await fs.promises.readFile(path.join(NcConfigFactory.getToolDir(), ...filePath.split('/')));
return fileData; return fileData;
} catch (e) { } catch (e) {
throw e; throw e;

43
packages/nocodb/src/lib/utils/NcConfigFactory.ts

@ -3,6 +3,7 @@ import fs from 'fs';
import parseDbUrl from "parse-database-url"; import parseDbUrl from "parse-database-url";
import {AuthConfig, DbConfig, MailerConfig, NcConfig} from "../../interface/config"; import {AuthConfig, DbConfig, MailerConfig, NcConfig} from "../../interface/config";
import * as path from "path";
const {uniqueNamesGenerator, starWars, adjectives, animals} = require('unique-names-generator'); const {uniqueNamesGenerator, starWars, adjectives, animals} = require('unique-names-generator');
@ -39,6 +40,17 @@ export default class NcConfigFactory implements NcConfig {
}; };
config.port = +(process?.env?.PORT ?? 8080);
config.env = process.env?.NODE_ENV || 'dev';
config.workingEnv = process.env?.NODE_ENV || 'dev';
config.toolDir = this.getToolDir();
config.projectType = config?.envs?.[config.workingEnv]?.db?.[0]?.meta?.api?.type || 'rest';
if (config.meta?.db?.connection?.filename) {
config.meta.db.connection.filename = path.join(config.toolDir, config.meta.db.connection.filename)
}
if (process.env.NC_DB) { if (process.env.NC_DB) {
config.meta.db = this.metaUrlToDbConfig(process.env.NC_DB) config.meta.db = this.metaUrlToDbConfig(process.env.NC_DB)
} }
@ -59,34 +71,11 @@ export default class NcConfigFactory implements NcConfig {
} }
/* if (process.env.NC_MAILER) {
config.mailer = {
from: process.env.NC_MAILER_FROM,
options: {
"host": process.env.NC_MAILER_HOST,
"port": parseInt(process.env.NC_MAILER_PORT, 10),
"secure": process.env.NC_MAILER_SECURE === 'true',
"auth": {
"user": process.env.NC_MAILER_USER,
"pass": process.env.NC_MAILER_PASS
}
}
}
}*/
if (process.env.NC_PUBLIC_URL) { if (process.env.NC_PUBLIC_URL) {
config.envs[process.env.NODE_ENV || 'dev'].publicUrl = process.env.NC_PUBLIC_URL; config.envs[process.env.NODE_ENV || 'dev'].publicUrl = process.env.NC_PUBLIC_URL;
} }
config.port = +(process?.env?.PORT ?? 8080);
config.env = process.env?.NODE_ENV || 'dev';
config.workingEnv = process.env?.NODE_ENV || 'dev';
config.toolDir = process.env.NC_TOOL_DIR || process.cwd();
config.projectType = config?.envs?.[config.workingEnv]?.db?.[0]?.meta?.api?.type || 'rest';
if (process.env.NC_DASHBOARD_URL) { if (process.env.NC_DASHBOARD_URL) {
config.dashboardPath = process.env.NC_DASHBOARD_URL; config.dashboardPath = process.env.NC_DASHBOARD_URL;
} }
@ -173,12 +162,16 @@ export default class NcConfigFactory implements NcConfig {
config.port = +(process?.env?.PORT ?? 8080); config.port = +(process?.env?.PORT ?? 8080);
config.env = process.env?.NODE_ENV || 'dev'; config.env = process.env?.NODE_ENV || 'dev';
config.workingEnv = process.env?.NODE_ENV || 'dev'; config.workingEnv = process.env?.NODE_ENV || 'dev';
config.toolDir = process.env.NC_TOOL_DIR || process.cwd(); config.toolDir = this.getToolDir();
config.projectType = config?.envs?.[config.workingEnv]?.db?.[0]?.meta?.api?.type || 'rest'; config.projectType = config?.envs?.[config.workingEnv]?.db?.[0]?.meta?.api?.type || 'rest';
return config; return config;
} }
public static getToolDir() {
return process.env.NC_TOOL_DIR || process.cwd();
}
public static hasDbUrl(): boolean { public static hasDbUrl(): boolean {
return Object.keys(process.env).some(envKey => envKey.startsWith('NC_DB_URL')); return Object.keys(process.env).some(envKey => envKey.startsWith('NC_DB_URL'));
} }
@ -395,7 +388,7 @@ export default class NcConfigFactory implements NcConfig {
config.port = +(process?.env?.PORT ?? 8080); config.port = +(process?.env?.PORT ?? 8080);
config.env = process.env?.NODE_ENV || 'dev'; config.env = process.env?.NODE_ENV || 'dev';
config.workingEnv = process.env?.NODE_ENV || 'dev'; config.workingEnv = process.env?.NODE_ENV || 'dev';
config.toolDir = process.env.NC_TOOL_DIR || process.cwd(); config.toolDir = this.getToolDir();
config.projectType = type || config?.envs?.[config.workingEnv]?.db?.[0]?.meta?.api?.type || 'rest'; config.projectType = type || config?.envs?.[config.workingEnv]?.db?.[0]?.meta?.api?.type || 'rest';
return config; return config;

Loading…
Cancel
Save