feat: integrating app with the bru lang

This commit is contained in:
Anoop M D 2023-01-17 02:00:58 +05:30
parent 23076b41c6
commit b6c3205474
9 changed files with 131 additions and 44 deletions

View File

@ -1,5 +1,5 @@
module.exports = { module.exports = {
reactStrictMode: true, reactStrictMode: false,
publicRuntimeConfig: { publicRuntimeConfig: {
CI: process.env.CI, CI: process.env.CI,
PLAYWRIGHT: process.env.PLAYWRIGHT PLAYWRIGHT: process.env.PLAYWRIGHT

View File

@ -30,7 +30,7 @@ const Collections = ({ searchText }) => {
? collectionToDisplay.map((c) => { ? collectionToDisplay.map((c) => {
return ( return (
<DndProvider backend={HTML5Backend} key={c.uid}> <DndProvider backend={HTML5Backend} key={c.uid}>
<Collection searchText={searchText} collection={c} />; <Collection searchText={searchText} collection={c} />
</DndProvider> </DndProvider>
); );
}) })

View File

@ -1,3 +1,4 @@
import reckon from 'reckonjs';
import get from 'lodash/get'; import get from 'lodash/get';
import each from 'lodash/each'; import each from 'lodash/each';
import find from 'lodash/find'; import find from 'lodash/find';
@ -413,7 +414,6 @@ export const interpolateEnvironmentVars = (item, variables) => {
}; };
request.url = interpolate(request.url); request.url = interpolate(request.url);
console.log(request.url);
each(request.headers, (header) => { each(request.headers, (header) => {
header.value = interpolate(header.value); header.value = interpolate(header.value);

View File

@ -14,7 +14,7 @@ export const isLocalCollection = (collection) => {
}; };
export const resolveRequestFilename = (name) => { export const resolveRequestFilename = (name) => {
return `${trim(name)}.json`; return `${trim(name)}.bru`;
}; };
export const getSubdirectoriesFromRoot = (rootPath, pathname) => { export const getSubdirectoriesFromRoot = (rootPath, pathname) => {

View File

@ -13,6 +13,8 @@
"pack-app": "electron-builder --dir" "pack-app": "electron-builder --dir"
}, },
"dependencies": { "dependencies": {
"@usebruno/bruno-lang": "0.1.0",
"@usebruno/schema": "0.1.0",
"axios": "^0.26.0", "axios": "^0.26.0",
"chokidar": "^3.5.3", "chokidar": "^3.5.3",
"electron-is-dev": "^2.0.0", "electron-is-dev": "^2.0.0",

View File

@ -1,7 +1,14 @@
const _ = require('lodash');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const chokidar = require('chokidar'); const chokidar = require('chokidar');
const { hasJsonExtension } = require('../utils/filesystem'); const { hasJsonExtension, hasBruExtension, writeFile } = require('../utils/filesystem');
const {
bruToJson,
jsonToBru
} = require('@usebruno/bruno-lang');
const { itemSchema } = require('@usebruno/schema');
const { generateUidBasedOnHash, uuid } = require('../utils/common');
const isEnvironmentConfig = (pathname, collectionPath) => { const isEnvironmentConfig = (pathname, collectionPath) => {
const dirname = path.dirname(pathname); const dirname = path.dirname(pathname);
@ -10,6 +17,22 @@ const isEnvironmentConfig = (pathname, collectionPath) => {
return dirname === collectionPath && basename === 'environments.json'; return dirname === collectionPath && basename === 'environments.json';
} }
const hydrateRequestWithUuid = (request, pathname) => {
request.uid = generateUidBasedOnHash(pathname);
const params = _.get(request, 'request.params', []);
const headers = _.get(request, 'request.headers', []);
const bodyFormUrlEncoded = _.get(request, 'request.body.formUrlEncoded', []);
const bodyMultipartForm = _.get(request, 'request.body.multipartForm', []);
params.forEach((param) => param.uid = uuid());
headers.forEach((header) => header.uid = uuid());
bodyFormUrlEncoded.forEach((param) => param.uid = uuid());
bodyMultipartForm.forEach((param) => param.uid = uuid());
return request;
}
const addEnvironmentFile = async (win, pathname, collectionUid) => { const addEnvironmentFile = async (win, pathname, collectionUid) => {
try { try {
const file = { const file = {
@ -71,7 +94,30 @@ const add = async (win, pathname, collectionUid, collectionPath) => {
if(isEnvironmentConfig(pathname, collectionPath)) { if(isEnvironmentConfig(pathname, collectionPath)) {
return addEnvironmentFile(win, pathname, collectionUid); return addEnvironmentFile(win, pathname, collectionUid);
} }
}
// migrate old json files to bru
if(hasJsonExtension(pathname)) {
try {
const json = fs.readFileSync(pathname, 'utf8');
const jsonData = JSON.parse(json);
await itemSchema.validate(jsonData);
const content = jsonToBru(jsonData);
const re = /(.*)\.json$/;
const subst = `$1.bru`;
const bruFilename = pathname.replace(re, subst);
await writeFile(bruFilename, content);
await fs.unlinkSync(pathname);
} catch (err) {
// do nothing
}
}
if(hasBruExtension(pathname)) {
const file = { const file = {
meta: { meta: {
collectionUid, collectionUid,
@ -81,8 +127,9 @@ const add = async (win, pathname, collectionUid, collectionPath) => {
} }
try { try {
const jsonData = fs.readFileSync(pathname, 'utf8'); const bru = fs.readFileSync(pathname, 'utf8');
file.data = JSON.parse(jsonData); file.data = bruToJson(bru);
hydrateRequestWithUuid(file.data, pathname);
win.webContents.send('main:collection-tree-updated', 'addFile', file); win.webContents.send('main:collection-tree-updated', 'addFile', file);
} catch (err) { } catch (err) {
console.error(err) console.error(err)
@ -104,25 +151,30 @@ const addDirectory = (win, pathname, collectionUid) => {
const change = async (win, pathname, collectionUid, collectionPath) => { const change = async (win, pathname, collectionUid, collectionPath) => {
console.log(`watcher change: ${pathname}`); console.log(`watcher change: ${pathname}`);
try {
if(isEnvironmentConfig(pathname, collectionPath)) {
return changeEnvironmentFile(win, pathname, collectionUid);
}
const file = { if(isEnvironmentConfig(pathname, collectionPath)) {
meta: { return changeEnvironmentFile(win, pathname, collectionUid);
collectionUid,
pathname,
name: path.basename(pathname),
}
};
const jsonData = fs.readFileSync(pathname, 'utf8');
file.data = await JSON.parse(jsonData);
win.webContents.send('main:collection-tree-updated', 'change', file);
} catch (err) {
console.error(err)
} }
if(hasBruExtension(pathname)) {
try {
const file = {
meta: {
collectionUid,
pathname,
name: path.basename(pathname),
}
};
const bru = fs.readFileSync(pathname, 'utf8');
file.data = bruToJson(bru);
hydrateRequestWithUuid(file.data, pathname);
win.webContents.send('main:collection-tree-updated', 'change', file);
} catch (err) {
console.error(err)
}
}
}; };
const unlink = (win, pathname, collectionUid, collectionPath) => { const unlink = (win, pathname, collectionUid, collectionPath) => {
@ -130,19 +182,19 @@ const unlink = (win, pathname, collectionUid, collectionPath) => {
return unlinkEnvironmentFile(win, pathname, collectionUid); return unlinkEnvironmentFile(win, pathname, collectionUid);
} }
console.log(`watcher unlink: ${pathname}`); if(hasBruExtension(pathname)) {
const file = { const file = {
meta: { meta: {
collectionUid, collectionUid,
pathname, pathname,
name: path.basename(pathname) name: path.basename(pathname)
} }
}; };
win.webContents.send('main:collection-tree-updated', 'unlink', file); win.webContents.send('main:collection-tree-updated', 'unlink', file);
}
} }
const unlinkDir = (win, pathname, collectionUid) => { const unlinkDir = (win, pathname, collectionUid) => {
console.log(`watcher unlinkDir: ${pathname}`);
const directory = { const directory = {
meta: { meta: {
collectionUid, collectionUid,
@ -163,6 +215,11 @@ class Watcher {
this.watchers[watchPath].close(); this.watchers[watchPath].close();
} }
// todo
// enable this in a future release
// once we can confirm all older json based files have been auto migrated to .bru format
// watchPath = path.join(watchPath, '**/*.bru');
const self = this; const self = this;
setTimeout(() => { setTimeout(() => {
const watcher = chokidar.watch(watchPath, { const watcher = chokidar.watch(watchPath, {

View File

@ -2,15 +2,19 @@ const _ = require('lodash');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const { ipcMain } = require('electron'); const { ipcMain } = require('electron');
const {
jsonToBru,
bruToJson,
} = require('@usebruno/bruno-lang');
const { const {
isValidPathname, isValidPathname,
writeFile, writeFile,
hasJsonExtension, hasBruExtension,
isDirectory, isDirectory,
browseDirectory, browseDirectory,
createDirectory createDirectory
} = require('../utils/filesystem'); } = require('../utils/filesystem');
const { uuid, stringifyJson, parseJson } = require('../utils/common'); const { uuid, stringifyJson } = require('../utils/common');
const { openCollectionDialog, openCollection } = require('../app/collections'); const { openCollectionDialog, openCollection } = require('../app/collections');
const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollections) => { const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollections) => {
@ -64,7 +68,7 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection
throw new Error(`path: ${pathname} already exists`); throw new Error(`path: ${pathname} already exists`);
} }
const content = await stringifyJson(request); const content = jsonToBru(request);
await writeFile(pathname, content); await writeFile(pathname, content);
} catch (error) { } catch (error) {
return Promise.reject(error); return Promise.reject(error);
@ -78,7 +82,7 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection
throw new Error(`path: ${pathname} does not exist`); throw new Error(`path: ${pathname} does not exist`);
} }
const content = await stringifyJson(request); const content = jsonToBru(request);
await writeFile(pathname, content); await writeFile(pathname, content);
} catch (error) { } catch (error) {
return Promise.reject(error); return Promise.reject(error);
@ -112,18 +116,18 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection
return fs.renameSync(oldPath, newPath); return fs.renameSync(oldPath, newPath);
} }
const isJson = hasJsonExtension(oldPath); const isBru = hasBruExtension(oldPath);
if(!isJson) { if(!isBru) {
throw new Error(`path: ${oldPath} is not a json file`); throw new Error(`path: ${oldPath} is not a bru file`);
} }
// update name in file and save new copy, then delete old copy // update name in file and save new copy, then delete old copy
const data = fs.readFileSync(oldPath, 'utf8'); const data = fs.readFileSync(oldPath, 'utf8');
const jsonData = await parseJson(data); const jsonData = bruToJson(data);
jsonData.name = newName; jsonData.name = newName;
const content = await stringifyJson(jsonData); const content = jsonToBru(jsonData);
await writeFile(newPath, content); await writeFile(newPath, content);
await fs.unlinkSync(oldPath); await fs.unlinkSync(oldPath);
} catch (error) { } catch (error) {

View File

@ -25,8 +25,26 @@ const parseJson = async (obj) => {
} }
} }
const simpleHash = (str) => {
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash &= hash; // Convert to 32bit integer
}
return new Uint32Array([hash])[0].toString(36);
};
const generateUidBasedOnHash = (str) => {
const hash = simpleHash(str);
return `${hash}`.padEnd(21, '0');
}
module.exports = { module.exports = {
uuid, uuid,
stringifyJson, stringifyJson,
parseJson parseJson,
simpleHash,
generateUidBasedOnHash
}; };

View File

@ -65,6 +65,11 @@ const hasJsonExtension = filename => {
return ['json'].some(ext => filename.toLowerCase().endsWith(`.${ext}`)) return ['json'].some(ext => filename.toLowerCase().endsWith(`.${ext}`))
} }
const hasBruExtension = filename => {
if (!filename || typeof filename !== 'string') return false
return ['bru'].some(ext => filename.toLowerCase().endsWith(`.${ext}`))
}
const createDirectory = async (dir) => { const createDirectory = async (dir) => {
if(!dir) { if(!dir) {
throw new Error(`directory: path is null`); throw new Error(`directory: path is null`);
@ -99,6 +104,7 @@ module.exports = {
normalizeAndResolvePath, normalizeAndResolvePath,
writeFile, writeFile,
hasJsonExtension, hasJsonExtension,
hasBruExtension,
createDirectory, createDirectory,
browseDirectory browseDirectory
}; };