Skip to content

Commit

Permalink
Load stock data if found absent, download and initialize stock templa…
Browse files Browse the repository at this point in the history
…te database (resolves #38)
  • Loading branch information
paramsiddharth committed Jul 16, 2021
1 parent dab2f20 commit c6047e0
Show file tree
Hide file tree
Showing 6 changed files with 368 additions and 42 deletions.
5 changes: 4 additions & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ const BASE_ROUTE = process.env.BASE_ROUTE ?
)
: '/';

const STOCK_DATA_URL = `https://github.com/paramsiddharth/rema/releases/download/stock-data-v1.0/static.zip`;

module.exports = {
INTERNAL_STATIC_DIR,
MAX_CAIRO_DIMENSION,
SINGLE_WHITE_PIXEL,
PORT,
DB,
BASE_ROUTE
BASE_ROUTE,
STOCK_DATA_URL
};
21 changes: 12 additions & 9 deletions src/helpers/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,19 @@ const {
SINGLE_WHITE_PIXEL
} = require('../constants');

const RESOURCES = path.join(INTERNAL_STATIC_DIR, 'fonts.json');
if (fs.existsSync(RESOURCES)) {
const fonts = fs.readJSONSync(RESOURCES).filter(i => i.type === 'font');
for (const font of fonts) {
const {
path: fontPath,
family
} = font;
registerFont(path.join(INTERNAL_STATIC_DIR, fontPath), { family });
if (!process.env.FONTS_LOADED) {
const RESOURCES = path.join(INTERNAL_STATIC_DIR, 'items.json');
if (fs.existsSync(RESOURCES)) {
const fonts = fs.readJSONSync(RESOURCES).filter(i => i.type === 'font');
for (const font of fonts) {
const {
path: fontPath,
family
} = font;
registerFont(path.join(INTERNAL_STATIC_DIR, fontPath), { family });
}
}
process.env.FONTS_LOADED = 1;
}

// Render a preview of a template or a certificate
Expand Down
16 changes: 8 additions & 8 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const exitHandler = function(sig, err) {
if (fs.existsSync(tempDirectory.name))
fs.emptyDirSync(tempDirectory.name);
tempDirectory.removeCallback();
console.log(`\rExitting Rema... 🌸`);
console.log(`Exitting Rema... 🌸`);
process.exit(exitCode);
};

Expand All @@ -54,25 +54,25 @@ const certificateRouter = require('./routes/certificate');
// For global await support
(async () => {

// Perform some initial checks
const initResults = await require('./initCheck')();
console.log(initResults.msg);
if (!initResults.success)
process.exit(1);

// Connect to database
try {
await mongoose.connect(DB, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
});
console.log(`Connected to database. 🔐`);
console.log(`Connected to the database. 🔐`);
} catch(e) {
console.error(`Failed to connect to database: "${e.message}"`);
process.exit(1);
}

// Perform some initial checks
const initResults = await require('./initCheck')();
console.log(initResults.msg);
if (!initResults.success)
process.exit(1);

const app = express();

// Show debug output to console
Expand Down
121 changes: 100 additions & 21 deletions src/initCheck.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
const fs = require('fs-extra');
const path = require('path');
const { check: portInUse } = require('tcp-port-used');
const axios = require('axios').default;
const unzip = require('unzipper');
const { registerFont } = require('canvas');

const Template = require('./models/template');
const {
INTERNAL_STATIC_DIR,
PORT
PORT,
STOCK_DATA_URL
} = require('./constants');

const checks = {
Expand All @@ -12,25 +18,10 @@ const checks = {
action: async () => {
const port = PORT;

// Creating a new server just to check for a free port has some caveats
/* const inUse = p => new Promise(resolve => {
const server = net.createServer();
server.once('error', err => {
if (err.code === 'EADDRINUSE')
resolve(true);
});
server.once('listening', () => {
server.close();
resolve(false);
});
server.listen(p);
}); */

if (await portInUse(port))
throw new Error(`Port ${port} already in use!`);

return `Port available for use!`;
},
critical: true
},
Expand All @@ -41,11 +32,98 @@ const checks = {
if (!fullInternalStaticDir.endsWith(path.sep))
fullInternalStaticDir += path.sep;

if (!fs.existsSync(fullInternalStaticDir))
throw new Error(`Internal static directory '${fullInternalStaticDir}' doesn't exist!`);
if (!fs.existsSync(fullInternalStaticDir)) {
try {
fs.ensureDirSync(fullInternalStaticDir);
} catch(e) {
throw new Error(`Failed to ensure internal static directory '${fullInternalStaticDir}' (${e.message})!`);
}
}

return `Internal static directory ensured!`;
},
critical: true
},
stockMaterial: {
msg: `Checking if stock material exists...`,
action: async () => {
if (!fs.existsSync(INTERNAL_STATIC_DIR))
throw new Error(`Missing internal static directory '${INTERNAL_STATIC_DIR}'!`);

const stockDir = path.resolve(INTERNAL_STATIC_DIR, 'stock') + path.sep;
const templates = await Template.find({ name: /^stock-/ });

if (!fs.existsSync(stockDir) || (templates.length < 1 && !fs.existsSync(path.join(INTERNAL_STATIC_DIR, 'items.json')))) {
console.log(`Stock material not found! Downloading...`);

try {
fs.ensureDirSync(stockDir);
fs.emptyDirSync(stockDir);

const stockZip = path.join(process.env.TMP_DIR, 'stock.zip');

const done = await new Promise(async resolve => {
const resp = await axios.get(STOCK_DATA_URL, { responseType: 'stream' });
const downloadStream = fs.createWriteStream(stockZip);
resp.data.pipe(downloadStream);

downloadStream.on('close', () => {
console.log(`Download finished! Extracting...`);
const extractStream = fs.createReadStream(stockZip);
const extractionStream = unzip.Extract({ path: INTERNAL_STATIC_DIR });
extractStream.pipe(extractionStream);
extractionStream.on('close', () => resolve('OK'));
});
});

if (done !== 'OK')
throw new Error();

console.log(`Extracted! Loading material into database...`);
} catch(e) {
throw new Error(`Couldn't ensure stock material in Rema (${e.message})!`);
}
}

try {
const items = fs.readJSONSync(path.join(INTERNAL_STATIC_DIR, 'items.json'));

const temps = items.filter(i => i.type === 'template');
if (templates.length < 1) {
console.log(`Found ${temps.length} stock templates.`);

let i = 0;
for (const t of temps) {
const {
name,
path: templatePath
} = t;
if ((await Template.findOne({ name })) == null) {
try {
process.stdout.write(`Loading template '${name}' to database...`);
const fullPath = path.join(INTERNAL_STATIC_DIR, templatePath);
const obj = fs.readJSONSync(fullPath);
const te = new Template(obj);
await te.save()
process.stdout.write(`\r` + ' '.repeat(60));
console.log(`\r'${name}' added to database.`);
i++;
} catch(e) {
process.stdout.write(`\r` + ' '.repeat(60));
console.log(`\rFailed to load tempalte '${name}' into database.`);
}
} else
console.log(`'${name}' already in database. Skipping...`);
}
}
} catch(e) {
throw new Error(`Failed to load stock templates into database (${e.message})!`);
}

return `Stock material loaded!`;
},
critical: false
}
};

module.exports = async () => {
Expand All @@ -65,7 +143,8 @@ module.exports = async () => {

console.log(`${i}. ${msg}`);
try {
await action();
const ret = await action();
console.log(ret);
successCount++;
} catch(e) {
console.log(e.message);
Expand Down
Loading

0 comments on commit c6047e0

Please sign in to comment.