Define variable global not local - node.js

I have some issues to use a global variable in my node.js app.
I use:
app.locals.isTestCafeRunning = false;
I think the problem here is locals, I think this variable is only valid inside the browser session, not inside the global app.
I want to use this variable in the main route:
app.get('/', function(req, res) {
async function getListData(){
var myListOptions = "";
var myListText = "";
arrayTestcaseData = await getMongojson();
/*code cut*/
var inPlaceButton = "";
if(req.app.locals.isTestCafeRunning===false){
inPlaceButton = "<button id=\"myButton\">Testrun starten</button>";
}else{
inPlaceButton = "<strong>Clipcafe in Benutzung!</strong>";
}
myHtmlCode = myHtmlCode.replace("%%BUTTON%%",inPlaceButton);
res.send(myHtmlCode);
}
getListData();
});
I want to fill the variable in
app.post('/clicked', (req, res) => {
//Function start Testcafe?
createTestCafe('localhost', 1337, 1338)
.then(tc => {
testcafe = tc;
const runner = testcafe.createRunner();
req.app.locals.isTestCafeRunning = true;
inputStore.clLogin = req.body.name;
inputStore.clPassword = req.body.pass;
inputStore.metaFolder = '19233456';
inputStore.metaUrl = req.body.channel;
return runner
.src(['tests/temp.js'])
.browsers(myBrowser)
//.browsers('browserstack:Chrome')
.screenshots('allure/screenshots/', true)
.reporter('allure')
.run();
})
.then(failedCount => {
req.app.locals.isTestCafeRunning = false;
console.log('Tests failed: ' + failedCount);
testcafe.close();
startReportGenerator();
res.sendStatus(201);
});
});
But I want to have this global not local vor all users, so if user 1 starts TestCafe, user 2 will only see "In use".

Related

connection.queryRaw is not a function error in NodeJs WebAPI call

I am new to Nodejs. I am developing WebAPI by using NodeJs and MSSQl as database.My api is giving proper response in case of POST endpoint If it is called while server is listening through Dev environment command [npm run start]. But, If I Deploy my API on Windows IIS , it is giving the mentioned error. My reference API endpoint code is as below :
router.post('/',async (req,res,next)=>{
// console.log('Enter products creation')
const Product = Array.from(req.body) // req.body
// console.log('New Product details passed on',Product)
const createProd = require('../CreateProduct')
const response = await createProd(Product)
res.status(404).json({
message : response.retStatus
})
})
CreateProduct function called in above code is as below :
const sql = require("mssql/msnodesqlv8");
const dataAccess = require("../DataAccess");
const fn_CreateProd = async function (product) {
let errmsg = "";
let objBlankTableStru = {};
let connPool = null;
// console.log('Going to connect with Connstr:',global.config)
await sql
.connect(global.config)
.then((pool) => {
global.connPool = pool;
productsStru = pool.request().query("DECLARE #tblProds tvp_products select * from #tblProds");
return productsStru;
})
.then(productsStru=>{
objBlankTableStru.products = productsStru
productsOhStru = global.connPool.request().query("DECLARE #tblprodsOh tvp_product_oh select * from #tblprodsOh");
return productsOhStru
})
.then((productsOhStru) => {
objBlankTableStru.products_oh = productsOhStru
let objTvpArr = [
{
uploadTableStru: objBlankTableStru,
},
{
tableName : "products",
tvpName: "tvp_products",
tvpPara: "tblProds"
},
{
tableName : "products_oh",
tvpName: "tvp_product_oh",
tvpPara: "tblProdsOh",
}
];
newResult = dataAccess.getPostResult(
objTvpArr,
"sp3s_ins_products_tvp",
product
);
console.log("New Result of Execute Final procedure", newResult);
return newResult;
})
.then((result) => {
// console.log("Result of proc", result);
if (!result.recordset[0].errmsg)
errmsg = "New Products Inserted successfully";
else errmsg = result.recordset[0].errmsg;
})
.catch((err) => {
console.log("Enter catch of Posting prod", err.message);
errmsg = err.message;
if (errmsg == "") {
errmsg = "Unknown error from Server... ";
}
})
.finally((resp) => {
sql.close();
});
return { retStatus: errmsg };
};
module.exports = fn_CreateProd;
GetPost() function is as below :
const getPostResult = (
tvpNamesArr,
procName,
sourceData,
sourceDataFormat,
singleTableData
) => {
let arrtvpNamesPara = [];
let prdTable = null;
let newSrcData = [];
// console.log("Source Data :", sourceData);
let uploadTable = tvpNamesArr[0];
for (i = 1; i <= tvpNamesArr.length - 1; i++) {
let tvpName = tvpNamesArr[i].tvpName;
let tvpNamePara = tvpNamesArr[i].tvpPara;
let TableName = tvpNamesArr[i].tableName;
let srcTable = uploadTable.uploadTableStru[TableName];
srcTable = srcTable.recordset.toTable(tvpName);
let newsrcTable = Array.from(srcTable.columns);
newsrcTable = newsrcTable.map((i) => {
i.name = i.name.toUpperCase();
return i;
});
if (!singleTableData) {
switch (sourceDataFormat) {
case 1:
newSrcData = sourceData.filter((obj) => {
return obj.tablename.toUpperCase() === TableName.toUpperCase();
});
break;
case 2:
newSrcData = getObjectDatabyKey(sourceData, TableName);
break;
default:
newSrcData = getTableDatabyKey(sourceData, TableName);
break;
}
} else {
newSrcData = sourceData;
}
// console.log(`Filtered Source data for Table:${TableName}`, newSrcData);
prdTable = generateTable(
newsrcTable,
newSrcData,
tvpName,
sourceDataFormat
);
arrtvpNamesPara.push({ name: tvpNamePara, value: prdTable });
}
const newResult = execute(procName, arrtvpNamesPara);
return newResult;
};
Finally, I have found the solution to this.. it is very strange and shocking and surprising that If I using Morgan Middleware in app.js and have used it by syntax : app.use(morgan('dev')) , then it is the culprit command..I just removed dev from this command after which problem got resolved..But I found no help regarding this issue over Google anywhere..I really fear that what type of challenges I am going to face in future development if these kind of silly error come without giving any hint..I would be highly obliged If anyone could make me understand this kind of silly errors..

Using classes in firebase functions?

I am writing code for a firebase function, the problem is that I need to use a class but when I call the class method the firebase function log shows this error:
ERROR:
ReferenceError: Proverbi is not defined
at exports.getProverbio.functions.https.onRequest (/srv/index.js:48:26)
at cloudFunction (/srv/node_modules/firebase-functions/lib/providers/https.js:49:16)
at /worker/worker.js:783:7
at /worker/worker.js:766:11
at _combinedTickCallback (internal/process/next_tick.js:132:7)
at process._tickDomainCallback (internal/process/next_tick.js:219:9)
Here's the "index.js" code:
//firebase deploy --only functions
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();
// Take the text parameter passed to this HTTP endpoint and insert it into the
// Realtime Database under the path /messages/:pushId/original
exports.addStanza = functions.https.onRequest(async (req, res) => {
// Grab the text parameter.
const nome = req.query.text;
// Push the new message into the Realtime Database using the Firebase Admin SDK.
const snapshot = await admin.database().ref('/stanze').push({giocatori: {giocatore:{nome:nome,punteggio:0}}});
// Redirect with 303 SEE OTHER to the URL of the pushed object in the Firebase console.
//res.redirect(200, nome.toString());
var link = snapshot.toString().split('/');
res.json({idStanza:link[4]});
});
// Listens for new messages added to /messages/:pushId/original and creates an
// uppercase version of the message to /messages/:pushId/uppercase
exports.addFirstPlayer = functions.database.ref('/stanze/{pushId}/giocatori/giocatore/nome')
.onCreate((snapshot, context) => {
// Grab the current value of what was written to the Realtime Database.
const nome = snapshot.val();
// const snapshot3 = snapshot.ref('/stanza/{pushId}/giocatori/giocatore').remove();
const snapshot2 = snapshot.ref.parent.parent.remove();
return snapshot.ref.parent.parent.push({nome:nome,punteggio:0});
});
exports.addPlayer = functions.https.onRequest(async (req, res) => {
// Grab the text parameter.
const nome = req.query.text;
const idStanza = req.query.id;
// Push the new message into the Realtime Database using the Firebase Admin SDK.
const snapshot = await admin.database().ref('/stanz/'+idStanza+"/giocatori").push({nome:nome,punteggio:0 });
// Redirect with 303 SEE OTHER to the URL of the pushed object in the Firebase console.
//res.redirect(200, nome.toString());
res.json({success:{id:idStanza}});
});
exports.getProverbio = functions.https.onRequest(async (req, res) => {
const difficolta = req.query.difficolta;
var proverbioClass = new Proverbi(2);
var p = proverbioClass.getProverbio();
var proverbio = p.split('-');
var inizio = proverbio[0];
var fine = proverbio[1];
res.json({proverbio:{inizio:inizio,fine:fine,difficolta:difficolta}});
});
Here's the code that's causing the problem:
exports.getProverbio = functions.https.onRequest(async (req, res) => {
const difficolta = req.query.difficolta;
var proverbioClass = new Proverbi(2);
var p = proverbioClass.getProverbio();
var proverbio = p.split('-');
var inizio = proverbio[0];
var fine = proverbio[1];
res.json({proverbio:{inizio:inizio,fine:fine,difficolta:difficolta}});
});
Here's the "Proverbi.class" code:
class Proverbi{
constructor(n) {
this.magicNumber = n;
}
getProverbio() {
var text = "";
switch (magicNumber) {
case 1:
text += ("Chip");
text += ("-Chop");
break;
}
return text;
}
}
How can I use the "Proverbi" class inside the "index.js"?
You need to add the definition of your Proverbi Class to the index.js file.
If you are just going to use this Class in the getProverbio Cloud Function, do as follows:
exports.getProverbio = functions.https.onRequest(async (req, res) => {
class Proverbi {
constructor(n) {
this.magicNumber = n;
}
getProverbio() {
var text = "";
switch (this.magicNumber) {
case 1:
text += ("Chip");
text += ("-Chop");
break;
}
return text;
}
}
const difficolta = req.query.difficolta;
var proverbioClass = new Proverbi(2);
var p = proverbioClass.getProverbio();
var proverbio = p.split('-');
var inizio = proverbio[0];
var fine = proverbio[1];
res.json({ proverbio: { inizio: inizio, fine: fine, difficolta: difficolta } });
});
If you want to use the Class in other functions, just declare it as follows:
class Proverbi {
constructor(n) {
console.log(n);
}
getProverbio() {
console.log(this.magicNumber);
console.log(this.magicNumber);
var text = "";
switch (this.magicNumber) {
case 1:
text += ("Chip");
text += ("-Chop");
break;
}
return text;
}
}
exports.getProverbio = functions.https.onRequest(async (req, res) => {
const difficolta = req.query.difficolta;
var proverbioClass = new Proverbi(2);
var p = proverbioClass.getProverbio();
var proverbio = p.split('-');
var inizio = proverbio[0];
var fine = proverbio[1];
res.json({ proverbio: { inizio: inizio, fine: fine, difficolta: difficolta } });
});

Algolia in Azure

I am using firebase for my android application and am performing full text search using Algolia which is suggested by all the blogs. I have successfully developed the script and its functioning properly. Now I want to host the script to run 24* 7. As I have an azure account , how do I go about uploading the script ? I have tried uploading the following as a function , web app but have been unsuccessful .
PS:- I have tried Heroku but wasn't satisfied.
The Script.
var http = require('http');
var port = process.env.port || 1337;
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}).listen(port);
var dotenv = require('dotenv');
var firebaseAdmin = require("firebase-admin");
var algoliasearch = require('algoliasearch');
var algoliasearchHelper = require('algoliasearch-helper');
// load values from the .env file in this directory into process.env
dotenv.load();
// configure firebase
var serviceAccount = require("./serviceAccountKey.json");
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(serviceAccount),
databaseURL: process.env.FIREBASE_DATABASE_URL
});
var database = firebaseAdmin.database();
// configure algolia
var algolia = algoliasearch(process.env.ALGOLIA_APP_ID, process.env.ALGOLIA_API_KEY);
var index = algolia.initIndex('books');
var contactsRef = database.ref("/BookFair");
contactsRef.on('child_added', addOrUpdateIndexRecord);
contactsRef.on('child_changed', addOrUpdateIndexRecord);
contactsRef.on('child_removed', deleteIndexRecord);
function addOrUpdateIndexRecord(dataSnapshot) {
// Get Firebase object
var firebaseObject = dataSnapshot.val();
// Specify Algolia's objectID using the Firebase object key
firebaseObject.objectID = dataSnapshot.key;
// Add or update object
index.saveObject(firebaseObject, function(err, content) {
if (err) {
throw err;
}
console.log('Firebase object indexed in Algolia', firebaseObject.objectID);
});
}
function deleteIndexRecord(dataSnapshot) {
// Get Algolia's objectID from the Firebase object key
var objectID = dataSnapshot.key;
// Remove the object from Algolia
index.deleteObject(objectID, function(err, content) {
if (err) {
throw err;
}
console.log('Firebase object deleted from Algolia', objectID);
});
}
var queries = database.ref("/queries");
queries.on('child_added', addOrUpdateIndexRecordN);
function addOrUpdateIndexRecordN(dataSnapshot) {
// Get Firebase object
var firebaseObject = dataSnapshot.val();
// Specify Algolia's objectID using the Firebase object key
firebaseObject.objectID = dataSnapshot.key;
// Add or update object
var collegeName = "";
var query_ID_LOLWA= "";
var year="";
var query = "";
var counter = 0;
for(var i in firebaseObject){
var c = firebaseObject.charAt(i);
if(c=='/'){
counter = counter + 1;
continue;
}
else{
if(counter==2)
collegeName = collegeName + c;
else if(counter == 3)
year = year+c;
else if(counter == 1)
query_ID_LOLWA = query_ID_LOLWA + c;
else
query = query +c;
}
}
console.log(collegeName);
console.log(year);
console.log(query_ID_LOLWA);
console.log(query);
const query_final = query_ID_LOLWA;
var helper = algoliasearchHelper(algoliasearch("****", "****"), 'books', {
facets: ['collegeName', 'year','priority']});
helper.on('result', function(data,query_ID_LOLWA){
data.getFacetValues('priority',{sortBy: ['count:desc']});
console.log(data.hits);
var path_query = "/queries_answers/"+query_final;
path_query = path_query.toString();
console.log(path_query);
if(data.hits.length==0){
console.log("No results");
database.ref(path_query).push(-1);
}
else if(data.hits.length>1){
var ID = 1;
var counter = -1;
var length = data.hits.length-1;
for(var h in data.hits){
counter = counter + 1;
if( (counter%5 == 0) && (counter != 0)){
ID = ID + 1;
}
database.ref(path_query+"/"+ID).push(data.hits[h].uuid);
}
database.ref(path_query+"/totalResults").push(data.hits.length);
}
else{
database.ref(path_query+"/totalResults").push(data.hits.length);
for(var h in data.hits)
database.ref(path_query+"/1").push(data.hits[h].uuid);
}
});
helper.addFacetRefinement('collegeName', collegeName);
helper.addFacetRefinement('year',year);
helper.setQuery(query);
helper.search();
/*index.search(firebaseObject, function(err, content) {
if (err) {
console.error(err);
return;
}
console.log(content.hits);
for (var h in content.hits) {
console.log('Hit(' + content.hits[h].objectID + '): ' + content.hits[h].uuid);
}
database.ref("/query_result").push(content.hits);
});*/
}
Without more details than but have been unsuccessful, the only advice one could give you is to follow the usual steps to get a time-based Azure function deployed.
The simplest way is to use the Azure Portal:
Login to your Microsoft Azure account
Create a Function App to host your function
Add a Timer-triggered Function
Select the TimerTrigger-Javascript template to get started
At this point, you'll have a function that runs every minute. You can check the logs to confirm it is working.
You now want to configure its frequency:
Update the function's Timer Schedule (in the Integrate tab) to set how frequently the function should run
Finally, replace the template's code with your own.
You can find a detailed tutorial here with explanations on how to achieve each of these steps.

mocha test sends `test` as variable to node app

When writing the tests for my entry file, index.js I run into the problem that the command mocha test passes test as an argument to index.js as it uses process.argv to receive parameters to run on a development environment. I had thought that by using something like minimist to name the parameters would fix this, however this problem still remains when running the tests. In this way my tests do not use the object provided in my test suits, as shown in the following code.
How do I get around this, so that when running my tests, it uses the event object I provide in my test set-up and not the command mocha test?
index.js
'use strict';
var _ = require("underscore");
var async = require('async');
var argv = require("minimist")(process.argv.slice(2));
var getprotocol = require("./getProtocol");
var _getprotocol = getprotocol.getProtocol;
var S3rs = require("./S3resizer");
var s3resizer = S3rs.rs;
var objCr = require("./objectCreator");
var createObj = objCr.creator;
var fileRs = require("./fileResizer");
var fileResizer = fileRs.rs;
var configs = require("./configs.json");
var mkDir = require("./makeDir");
var makeDir = mkDir.handler;
exports.imageRs = function (event, context) {
var _path = argv.x || event.path; //argv.x used to be process.argv[2]
console.log("Path, %s", _path);
var _dir = argv.y; // used to be process.argv[3]
console.log(_dir);
var parts = _getprotocol(_path);
var imgName = parts.pathname.split("/").pop();
console.log("imgName: %s", imgName);
var s3Bucket = parts.hostname;
var s3Key = imgName;
var _protocol = parts.protocol;
console.log(_protocol);
// RegExp to check for image type
var imageTypeRegExp = /(?:(jpg)|(png)|(jpeg))$/;
var sizesConfigs = configs.sizes;
var obj = createObj(_path);
// Check if file has a supported image extension
var imgExt = imageTypeRegExp.exec(s3Key);
if (imgExt === null) {
console.error('unable to infer the image type for key %s', s3Key);
context.done(new Error('unable to infer the image type for key %s' + s3Key));
return;
}
var imageType = imgExt[1] || imgExt[2];
// Do more stuff here
};
if (!process.env.LAMBDA_TASK_ROOT) {
exports.imageRs();
}
test.js
describe("imgeRs", function () {
var getprotocol = require("../getProtocol");
var S3rs = require("../S3resizer");
var objCr = require("../objectCreator");
var mkDir = require("../makeDir");
var fileResizer = require("../fileResizer");
describe("Calling S3", function () {
describe("Success call", function () {
var testedModule, eventObj, contextDoneSpy, S3resizerStub, objCreatorStub, getProtocolStub, fakeResults, mkDirStub, fileResizerStub;
before(function (done) {
contextDoneSpy = sinon.spy();
S3resizerStub = sinon.stub(S3rs, "rs");
objCreatorStub = sinon.stub(objCr, 'creator');
getProtocolStub = sinon.stub(getprotocol, "getProtocol");
mkDirStub = sinon.stub(mkDir, "handler");
fileResizerStub = sinon.stub(fileResizer, "rs");
eventObj = {"path": "s3://theBucket/image.jpeg"};
fakeResults = ["resized"];
testedModule = proxyquire("../index", {
'./getProtocol': {
'getProtocol': getProtocolStub
},
'./S3resizer': {
'rs': S3resizerStub
},
'./objectCreator': {
'creator': objCreatorStub
},
'./makeDir': {
'handler': mkDirStub
},
'./fileResizer': {
'rs': fileResizerStub
}
});
S3resizerStub.callsArgWith(5, null, fakeResults);
testedModule.imageRs(eventObj, {done: function (error) {
contextDoneSpy.apply(null, arguments);
done();
}});
});
after(function () {
S3rs.rs.restore();
objCr.creator.restore();
getprotocol.getProtocol.restore();
mkDir.handler.restore();
fileResizer.rs.restore();
});
it("calls context.done with no error", function () {
expect(contextDoneSpy).has.been.called;
});
});
});
});

Ember blueprint that injects environment config?

I'm relatively new to Ember and was wondering if there is a way to create a blueprint/generator that would inject a new value into the environment config while maintaining all existing configuration. Is there some Ember magic that allows an existing file to act as the blueprint template? My ideal implementation would look something like this:
ember g platform foo
// config/environment.js
module.exports = function(environment) {
var ENV = {
// Existing config values here...
APP: {
platforms: {
foo: 'abc123' // Generator injects the 'foo' platform and a GUID
}
};
// Existing environment-specific settings here...
return ENV;
};
Is this something that would be more easily accomplished using Node's fs.readFile() and fs.writeFile()? If so, how could I parse environment.js?
No there's no existing magic in Ember to my knowledge sorry. When you generate a route, something very similar to what you are talking about happens but the code is rather complex. The ember generate route new_route function has a call to this function
function addRouteToRouter(name, options) {
var routerPath = path.join(options.root, 'app', 'router.js');
var source = fs.readFileSync(routerPath, 'utf-8');
var routes = new EmberRouterGenerator(source);
var newRoutes = routes.add(name, options);
fs.writeFileSync(routerPath, newRoutes.code());
}
which then exectutes interpreter level like code to add the router and revert it back to code:
module.exports = EmberRouterGenerator;
var recast = require('recast');
var traverse = require('es-simpler-traverser');
var Scope = require('./scope');
var DefineCallExpression = require('./visitors/define-call-expression.js');
var findFunctionExpression = require('./helpers/find-function-expression');
var hasRoute = require('./helpers/has-route');
var newFunctionExpression = require('./helpers/new-function-expression');
var resourceNode = require('./helpers/resource-node');
var routeNode = require('./helpers/route-node');
function EmberRouterGenerator(source, ast) {
this.source = source;
this.ast = ast;
this.mapNode = null;
this.scope = new Scope();
this.visitors = {
CallExpression: new DefineCallExpression(this.scope, this)
};
this._ast();
this._walk();
}
EmberRouterGenerator.prototype.clone = function() {
var route = new EmberRouterGenerator(this.source);
return route;
};
EmberRouterGenerator.prototype._ast = function() {
this.ast = this.ast || recast.parse(this.source);
};
EmberRouterGenerator.prototype._walk = function() {
var scope = this.scope;
var visitors = this.visitors;
traverse(this.ast, {
exit: function(node) {
var visitor = visitors[node.type];
if (visitor && typeof visitor.exit === 'function') {
visitor.exit(node);
}
},
enter: function(node) {
var visitor = visitors[node.type];
if (visitor && typeof visitor.enter === 'function') {
visitor.enter(node);
}
}
});
};
EmberRouterGenerator.prototype.add = function(routeName, options) {
if (typeof this.mapNode === 'undefined') {
throw new Error('Source doesn\'t include Ember.map');
}
var route = this.clone();
var routes = route.mapNode.arguments[0].body.body;
route._add.call(
route,
routeName.split('/'),
routes,
options
);
return route;
};
EmberRouterGenerator.prototype._add = function(nameParts, routes, options) {
options = options || {};
var parent = nameParts[0];
var name = parent;
var children = nameParts.slice(1);
var route = hasRoute(parent, routes);
if (!route) {
if (options.type === 'resource') {
route = resourceNode(name, options);
routes.push(route);
} else {
route = routeNode(name, options);
routes.push(route);
}
}
if (children.length > 0) {
var routesFunction = findFunctionExpression(route.expression.arguments);
if (!routesFunction) {
routesFunction = newFunctionExpression();
route.expression.arguments.push(routesFunction);
}
this._add(children, routesFunction.body.body, options);
}
};
EmberRouterGenerator.prototype.remove = function(routeName) {
if (typeof this.mapNode === 'undefined') {
throw new Error('Source doesn\'t include Ember.map');
}
var route = this.clone();
var routes = route.mapNode.arguments[0].body.body;
var newRoutes = route._remove.call(
route,
routeName.split('/'),
routes
);
if (newRoutes) {
route.mapNode.arguments[0].body.body = newRoutes;
}
return route;
};
EmberRouterGenerator.prototype._remove = function(nameParts, routes) {
var parent = nameParts[0];
var name = parent;
var children = nameParts.slice(1);
var route = hasRoute(parent, routes);
var newRoutes;
if (children.length > 0) {
var routesFunction = route.expression && findFunctionExpression(route.expression.arguments);
if (routesFunction) {
newRoutes = this._remove(children, routesFunction.body.body);
if (newRoutes) {
routesFunction.body.body = newRoutes;
}
return routes;
}
} else {
if (route) {
routes = routes.filter(function(node) {
return node !== route;
});
return routes;
} else {
return false;
}
}
};
EmberRouterGenerator.prototype.code = function(options) {
options = options || { tabWidth: 2, quote: 'single' };
return recast.print(this.ast, options).code;
};
So then there's the alternative, which involves reading the file, adding in your new environment in the correct place after parsing the file correctly, and then writing the stream back. The complexity of what you are wanting to do probably outweighs the time it would take to do this manually IMO. If this is something you are doing often, maybe consider writing a script in another language that's better(read as more people use it for this) at textual file manipulation

Resources