I already deployed my smart contract to my wallet and connected it to my Alchemy account.
Here are my codings (Note that my contract address, PUBLIC_KEY, PRIVATE_KEY, API_URL and alchemy address are edited for security purposes).
mint-nft.js
require('dotenv').config();
const API_URL = process.env.API_URL;
const PUBLIC_KEY = process.env.PUBLIC_KEY;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const { createAlchemyWeb3 } = require("#alch/alchemy-web3");
const web3 = createAlchemyWeb3(API_URL);
const contract = require("../artifacts/contracts/MyNFT.sol/MyNFT.json");
const contractAddress = "My_Contract_Adress";
const nftContract = new web3.eth.Contract(contract.abi, contractAddress);
async function mintNFT(tokenURI) {
const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, 'latest'); //get latest nonce
//the transaction
const tx = {
'from': PUBLIC_KEY,
'to': contractAddress,
'nonce': nonce,
'gas': 500000,
'data': nftContract.methods.mintNFT(PUBLIC_KEY, tokenURI).encodeABI()
};
const signPromise = web3.eth.accounts.signTransaction(tx, PRIVATE_KEY);
signPromise.then((signedTx) => {
web3.eth.sendSignedTransaction(signedTx.rawTransaction, function(err, hash) {
if (!err) {
console.log("The hash of your transaction is: ", hash, "\nCheck Alchemy's Mempool to view the status of your transaction!");
} else {
console.log("Something went wrong when submitting your transaction:", err)
}
});
}).catch((err) => {
console.log(" Promise failed:", err);
});
}
mintNFT("https://gateway.pinata.cloud/ipfs/My_NFT_Picture_Hash");
alchemyContext.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeAlchemyContext = void 0;
var tslib_1 = require("tslib");
var sturdy_websocket_1 = tslib_1.__importDefault(require("sturdy-websocket"));
var websocket_1 = require("websocket");
var jsonRpc_1 = require("../util/jsonRpc");
var version_1 = require("../version");
var alchemySendHttp_1 = require("./alchemySendHttp");
var alchemySendWebSocket_1 = require("./alchemySendWebSocket");
var httpProvider_1 = require("./httpProvider");
var sendPayload_1 = require("./sendPayload");
var webSocketProvider_1 = require("./webSocketProvider");
var NODE_MAX_WS_FRAME_SIZE = 100 * 1024 * 1024; // 100 MB
function makeAlchemyContext(url, config) {
var makePayload = jsonRpc_1.makePayloadFactory();
if (/^https?:\/\//.test(url)) {
var alchemySend = alchemySendHttp_1.makeHttpSender(url);
var _a = sendPayload_1.makePayloadSender(alchemySend, config), sendPayload = _a.sendPayload, setWriteProvider = _a.setWriteProvider;
var senders = jsonRpc_1.makeSenders(sendPayload, makePayload);
var provider = httpProvider_1.makeAlchemyHttpProvider(sendPayload);
return { provider: provider, senders: senders, setWriteProvider: setWriteProvider };
}
else if (/^wss?:\/\//.test(url)) {
var protocol = isAlchemyUrl(url) ? "alchemy-web3-" + version_1.VERSION : undefined;
var ws = new sturdy_websocket_1.default(url, protocol, {
wsConstructor: getWebSocketConstructor(),
});
var alchemySend = alchemySendWebSocket_1.makeWebSocketSender(ws);
var _b = sendPayload_1.makePayloadSender(alchemySend, config), sendPayload = _b.sendPayload, setWriteProvider = _b.setWriteProvider;
var senders = jsonRpc_1.makeSenders(sendPayload, makePayload);
var provider = new webSocketProvider_1.AlchemyWebSocketProvider(ws, sendPayload, senders);
return { provider: provider, senders: senders, setWriteProvider: setWriteProvider };
}
else {
throw new Error("Alchemy URL protocol must be one of http, https, ws, or wss. Recieved: " + url);
}
}
exports.makeAlchemyContext = makeAlchemyContext;
function getWebSocketConstructor() {
return isNodeEnvironment()
? function (url, protocols) {
return new websocket_1.w3cwebsocket(url, protocols, undefined, undefined, undefined, {
maxReceivedMessageSize: NODE_MAX_WS_FRAME_SIZE,
maxReceivedFrameSize: NODE_MAX_WS_FRAME_SIZE,
});
}
: WebSocket;
}
function isNodeEnvironment() {
return (typeof process !== "undefined" &&
process != null &&
process.versions != null &&
process.versions.node != null);
}
function isAlchemyUrl(url) {
return url.indexOf("alchemyapi.io") >= 0;
}
.env
API_URL = "https://eth-rinkeby.alchemyapi.io/v2/KEY"
PRIVATE_KEY = "MY_PRIVATE_KEY"
PUBLIC_KEY = "MY_PUBLIC_KEY"
But then I was trying to deploy my NFT with metadata and nft-mint.js, I got these error.
Can anyone please tell me what was the error about?
Your issue may be with dotenv not reading in the values in your .env.
If you add console.log(API_URL), is it correct or is it undefined?
If it is undefined, I was able to resolve the issue by adding the path to my .env like so:
require('dotenv').config({path:"../.env"});
(In my case my mint-nft.js was in scripts/mint-nft.js
and .env is in the root directory.)
Related
when i run this code it says KustoAuthenticationError: Failed to get cloud
info for cluster https://clusterName.kusto.windows.net
The appId is the Application (client) ID,
appKey is the value of the client secret
and authorityId is the Directory (tenant) ID
I got this code from: https://github.com/Azure/azure-kusto-node/blob/master/packages/azure-kusto-ingest/example.js
code:
const IngestClient = require("azure-kusto-ingest").IngestClient;
const IngestStatusQueues = require("azure-kusto-ingest").IngestStatusQueues;
const IngestionProps = require("azure-kusto-ingest").IngestionProperties;
const KustoConnectionStringBuilder = require("azure-kusto-data").KustoConnectionStringBuilder;
const { DataFormat, JsonColumnMapping, IngestionMappingKind, CompressionType, ReportLevel, ReportMethod } = require("azure-kusto-ingest");
const { BlobDescriptor, StreamDescriptor } = require("azure-kusto-ingest").IngestionDescriptors;
const StreamingIngestClient = require("azure-kusto-ingest").StreamingIngestClient;
// const fs = require("fs");
const clusterName = "clusterName";
const authorityId = "authorityId";
const appId = "appId"
const appKey = "appKey"
var d = new Date();
var dateTimeNow = d.toJSON().slice(0,19).replace('T',':');
var data = {"Id" : "1314444525", "Temperature" : 32, "Battery" : 89, "Humidity" : 94, "Time" : dateTimeNow};
var s = require('stream');
var stream = new s.Readable();
stream.push(JSON.stringify(data));
stream.push(null);
// Streaming ingest client
const props2 = new IngestionProps({
database: "DBname",
table: "Tablename",
format: DataFormat.JSON,
ingestionMappingReference: "Pre-defined mapping name",
});
const streamingIngestClient = new StreamingIngestClient(
KustoConnectionStringBuilder.withAadApplicationKeyAuthentication(`https://${clusterName}.kusto.windows.net`, appId, appKey, authorityId),
props2
);
startStreamingIngestion();
async function startStreamingIngestion() {
try {
await streamingIngestClient.ingestFromStream(stream, props2);
console.log("Ingestion done");
await waitForStatus();
} catch (err) {
console.log(err);
}
}
async function waitForStatus(numberOFIngestions = 1) {
while ((await statusQueues.failure.isEmpty()) && (await statusQueues.success.isEmpty())) {
console.log("Waiting for status...");
await sleep(1000);
}
const failures = await statusQueues.failure.pop(numberOFIngestions);
for (let failure of failures) {
console.log('Failed: ${JSON.stringify(failure)}');
}
const successes = await statusQueues.success.pop(numberOFIngestions);
for (let success of successes) {
console.log('Succeeded: ${JSON.stringify(success)}');
}
}
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
This usually means you don’t have access to your ADX cluster’s endpoint. Verify whether your ADX cluster allows requests over the public network and that your Azure AD App doesn't have any outgoing network restrictions. In addition, make sure to grant 'ingestor' permission on your ADX database to your Azure AD App.
I am trying to integrate with a service (paysera https://developers.paysera.com/) that uses HMAC Authentication. I've manage to integrate every GET endpoint. Nevertheless, when it comes to the POST request it seems the code is not working.
createHMACAuth(data) {
let bodyHash = crypto.createHash('sha256').update(JSON.stringify(data)).digest('base64');
let method = 'POST';
let path = `/rest/v1/transfers`;
let ts = moment().unix();
let nonce = GUID(32);
let port = 443;
let macString = `${ts}\n${nonce}\n${method}\n${path}\n${host}\n${port}\n${bodyHash || ''}\n`;
let my_mac_key = 'my_mac_key';
let my_mac_id = 'my_mac_id';
let mac = crypto.createHmac('sha256', my_mac_key).update(macString).digest('base64');
let headerString = `MAC id="${my_mac_id}", ts="${ts}", nonce="${nonce}", mac="${mac}", ext="body_hash=${bodyHash}"`;
return headerString;
}
let data = {
key: 'value',
otherkey: 'othervalue'
};
let headers = {
Host: 'wallet.paysera.com',
'User-Agent': `Paysera node.js library`,
mac_id: 'my_mac_id',
Authorization: createHMACAuth(data);
};
POST_REQUEST(`${headers.host}/rest/v1/transfers`, data, headers, (err, res) => console.log(res))
The response I get is:
{
error: 'unauthorized',
error_description: 'Given MAC content body hash does not match actual hash of content'
}
Any help will be much appreciated!
I had an error when generating the body_hash
Fix
createHMACAuth(method, path, data) {
let bodyHash, ext;
if (method === 'POST') {
ext = `body_hash=${encodeURIComponent(this.createHash(JSON.stringify(data)))}`;
}
this.method = method;
this.path = `/${path}`;
let nonce = `${U.GUID(32)}`;
let port = 443;
let macString = `${this.ts}\n${nonce}\n${this.method}\n${this.path}\n${this.host}\n${port}\n${ext || ''}\n`;
let mac = this.createHMACHash(macString);
let headerString = `MAC id="${this.mac_id}", ts="${this.ts}", nonce="${nonce}", mac="${mac}"`;
if (method === 'POST') headerString += `, ext="${ext}"`
return headerString;
}
Your answer helped me make it work. Full code for other people that might need this.
import crypto from 'crypto'
import fetch from 'node-fetch'
function createHash(data) {
return crypto.createHash('sha256').update(data).digest('base64');
}
function createHMACHash (macKey, macString) {
return crypto.createHmac('sha256', macKey).update(macString).digest('base64');
}
async function createHMACAuth() {
const macId = 'your-mac-id';
const macKey = 'your-mac-key';
const ts = new Date().getTime();
const nonce = 'nQnNaSNyubfPErjRO55yaaEYo9YZfKYU';
const method = 'POST';
const uri = '/rest/v1/transaction'
const host = 'wallet.paysera.com'
const port = 443;
const data = {
"payments": [
{
"description": "Payment for order No. 1234",
"price": 1299,
"currency": "EUR",
"parameters": {
"orderid": 1234
}
}
],
"redirect_uri": "http://www.example.com/somePage"
}
let ext;
if (method === 'POST') {
ext = `body_hash=${encodeURIComponent(createHash(JSON.stringify(data)))}`;
}
let macString = `${ts}\n${nonce}\n${method}\n${uri}\n${host}\n${port}\n${ext || ''}\n`;
let mac = createHMACHash(macKey, macString);
let headerString = `MAC id="${macId}", ts="${ts}", nonce="${nonce}", mac="${mac}"`;
if (method === 'POST') headerString += `, ext="${ext}"`
const response = await fetch(`https://${host}${uri}`,{
method:method,
headers:{
Authorization: headerString,
'Content-Type':'application/json'
},
body: JSON.stringify(data)
})
return headerString;
}
await createHMACAuth()
I am writing a node JS web crawler class, and I have encountered the following error, this.textInvertedIndex[word].push is not a function. Upon further inspection I realised that for some reason this.textInvertedIndex[word] was written as a native object, function Object({ [native code] }). For the first few iterations, by console logging this.textInvertedIndex everything seemed fine as it was an object of arrays. But then suddenly this error occurred. Is there any part of the code where I am implicitly rewriting textInvertedIndex?
Here is the relevant class:
function Crawler(queue, maxIndexSize) {
this.queue = queue;
this.maxIndexSize = maxIndexSize;
this.findChunks = () => {
let currentChunk;
let minimumDistance = Infinity;
for (i = 1; i <= this.maxIndexSize; i++) {
if (this.maxIndexSize % i === 0) {
const newDistance = Math.abs(i - 30);
if (newDistance < minimumDistance) {
minimumDistance = newDistance;
currentChunk = i;
} else {
return currentChunk
};
};
};
};
this.chunks = this.findChunks();
this.chunkSize = this.maxIndexSize / this.chunks;
this.totalWordOccurances = {};
this.imageInvertedIndex = {};
this.textInvertedIndex = {};
this.images = [];
this.sites = [];
this.seen = {};
this.write = (url, html) => {
const documentId = this.sites.length;
const website = new Website(url, html);
const title = website.title();
const content = website.content(title);
const words = content.filter(item => typeof item !== "object");
const wordsLength = words.length;
const query = new Query(words);
const individualWords = query.individualize(words);
this.seen[url] = true;
this.sites.push({
url,
title,
description: website.description()
});
for (word of individualWords) {
const normalizedTf = query.count(word) / wordsLength;
const textInvertedIndexEntry = {
documentId,
normalizedTf
};
if (this.textInvertedIndex[word]) {
this.textInvertedIndex[word].push(textInvertedIndexEntry);
} else {
this.textInvertedIndex[word] = [textInvertedIndexEntry];
};
if (this.totalWordOccurances[word]) {
this.totalWordOccurances[word] += 1;
} else {
this.totalWordOccurances[word] = 1;
};
};
for (i = 0; i < content.length; i++) {
const item = content[i];
if (typeof item === "object") {
const imageId = this.images.length;
this.images.push(item);
for (word of individualWords) {
const imageScore = getImageScore(i, word, content);
const imageInvertedIndexEntry = {
imageId,
imageScore
};
if (this.imageInvertedIndex[word]) {
this.imageInvertedIndex[word].push(imageInvertedIndexEntry);
} else {
this.imageInvertedIndex[word] = [imageInvertedIndexEntry];
};
};
};
};
};
this.crawl = async () => {
while (this.sites.length !== this.maxIndexSize) {
let nextQueue = [];
const websitesUnfiltered = await Promise.all(this.queue.map((url) => {
const website = new Website(url);
return website.request();
}));
const websitesToAdd = this.maxIndexSize - this.sites.length;
let websites = websitesUnfiltered.filter(message => message !== "Failure")
.slice(0, websitesToAdd);
for (site of websites) {
const url = site.url;
const htmlCode = site.htmlCode;
const website = new Website(url, htmlCode);
this.write(url, htmlCode);
nextQueue = nextQueue.concat(website.urls());
};
nextQueue = new Query(nextQueue.filter(url => !this.seen[url]))
.individualize();
this.queue = nextQueue;
};
};
};
Called like this
const crawler = new Crawler(["https://stanford.edu/"], 25000000);
crawler.crawl();
this.textInvertedIndex = {}; is defining an Object of which push is not a valid function. you can change it to an array by defining it as this.textInvertedIndex = []; otherwise you can add key/value entries to the object as it is defined like this: this.textInvertedIndex[key] = value;
Turns out, my key was accessing this.textInvertedIndex[word]. And word was constructor. constructor is already a built in object property so it can never be rewritten as an array with .push defined. To solve this problem, make all object keys capital, so constructor will become CONSTRUCTOR, thus making sure that already existing object properties are never called.
I'm trying to get a FeatherJS app up and running using two way ssl for authentication over Socket.IO. I've built a simple cert strategy, verifier, etc.. to handle the task of validating that the user presented is a valid user.
However -- at this point everything I try keeps sending me in loops. I swear it doesn't appear that the authentication is running and when I do get it to finally kick out some debugging messages the peerCert is never present.
What am I doing wrong here?
index.js
const server = https.createServer({
key: fs.readFileSync('certificates/my.key'),
cert: fs.readFileSync('certificates/my-cert.pem'),
ca: fs.readFileSync('certificates/ca/my-ca.pem'),
requestCert: true,
rejectUnauthorized: true
}, app).listen(port);
app.setup(server);
Now the first time I hit the site I DO get prompted for a certificate but, I can't see any evidence that that cert gets to my authentication service.
app.js
const feathers = require('feathers');
const configuration = require('feathers-configuration');
const hooks = require('feathers-hooks');
const socketio = require('feathers-socketio');
const handler = require('feathers-errors/handler');
const notFound = require('feathers-errors/not-found');
const middleware = require('./middleware');
const services = require('./services');
const appHooks = require('./app.hooks');
const authentication = require('./authentication');
const app = feathers();
// Load app configuration
app.configure(configuration());
// Enable CORS, security, compression, favicon and body parsing
app.use(cors());
app.use(helmet());
app.use(compress());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(favicon(path.join(app.get('public'), 'favicon.ico')));
// Host the public folder
app.use('/', feathers.static(app.get('public')));
// Set up Plugins and providers
app.configure(hooks());
app.configure(socketio());
// Configure other middleware (see `middleware/index.js`)
app.configure(middleware);
app.configure(authentication);
// Set up our services (see `services/index.js`)
app.configure(services);
// Configure a middleware for 404s and the error handler
app.use(notFound());
app.use(handler());
app.hooks(appHooks);
module.exports = app;
authentication.js
const authentication = require('feathers-authentication');
const jwt = require('feathers-authentication-jwt');
const cert = require('./feathers-authentication-cert.js');
module.exports = function () {
const app = this;
const config = app.get('authentication');
// Set up authentication with the secret
app.configure(authentication(config));
app.configure(jwt());
app.configure(cert());
// The `authentication` service is used to create a JWT.
// The before `create` hook registers strategies that can be used
// to create a new valid JWT (e.g. local or oauth2)
app.service('authentication').hooks({
before: {
create: [authentication.hooks.authenticate(config.strategies)],
remove: [authentication.hooks.authenticate('jwt')]
}
});
};
feathers-authentication-cert.js
const Debug = require('debug');
const merge = require('lodash.merge');
const omit = require('lodash.omit');
const pick = require('lodash.pick');
const DefaultVerifier = require('./cert-verifier.js');
const ClientCertStrategy = require('./cert-strategy.js').Strategy;
const debug = Debug('feathers-authentication-cert');
const defaults = {
name: 'cert'
};
const KEYS = [
'passReqToCallback',
'session'
];
function init(options = {}) {
return function certAuth() {
const app = this;
const _super = app.setup;
if (!app.passport) {
throw new Error(`Can not find app.passport. Did you initialize feathers-authentication before feathers-authentication-cert?`);
}
let name = options.name || defaults.name;
let authOptions = app.get('authentication') || {};
let localOptions = authOptions[name] || {};
const localSettings = merge({}, defaults, pick(authOptions, KEYS), localOptions, omit(options, ['Verifier']));
let Verifier = DefaultVerifier;
if (options.Verifier) {
Verifier = options.Verifier;
}
app.setup = function () {
let result = _super.apply(this, arguments);
let verifier = new Verifier(app, localSettings);
if (!verifier.verify) {
throw new Error(`Your verifier must implement a 'verify' function. It should have the same signature as a local passport verify callback.`)
}
// Register 'cert' strategy with passport
debug('Registering cert authentication strategy with options:', localSettings);
app.passport.use(localSettings.name, new ClientCertStrategy(localSettings, verifier.verify.bind(verifier)));
app.passport.options(localSettings.name, localSettings);
return result;
}
};
}
// Exposed Modules
Object.assign(init, {
defaults,
Verifier: DefaultVerifier
});
module.exports = init;
cert-strategy.js
const util = require('util');
const Strategy = require('passport-strategy');
/*
* passport.js TLS client certificate strategy
*/
function ClientCertStrategy(options, verify) {
if (typeof options == 'function') {
verify = options;
options = {};
}
if (!verify) throw new Error('Client cert authentication strategy requires a verify function');
Strategy.call(this);
this.name = 'client-cert';
this._verify = verify;
this._passReqToCallback = options.passReqToCallback;
}
util.inherits(ClientCertStrategy, Strategy);
ClientCertStrategy.prototype.authenticate = function(req, options) {
var that = this;
console.log('Request', req);
// Requests must be authorized
// (i.e. the certificate must be signed by at least one trusted CA)
if(!req.socket.authorized) {
that.fail();
} else {
var clientCert = req.socket.getPeerCertificate();
// The cert must exist and be non-empty
if(!clientCert || Object.getOwnPropertyNames(clientCert).length === 0) {
that.fail();
} else {
var verified = function verified(err, user) {
if (err) { return that.error(err); }
if (!user) { return that.fail(); }
that.success(user);
};
if (this._passReqToCallback) {
this._verify(req, clientCert, verified);
} else {
this._verify(clientCert, verified);
}
}
}
};
module.exports.Strategy = ClientCertStrategy;
cert-verifier.js
class CertVerifier {
constructor (app, options = {}) {
this.app = app;
this.options = options;
this.verify = this.verify.bind(this);
}
verify(req, cert, done) {
console.log(req.socket);
done= () => {
console.log('done?');
}
var subject = cert.subject;
var msg = 'Attempting PKI authentication';
if(!subject) {
console.log(msg + ' ✘ - no subject'.red);
done(null, false);
} else if(!subject.CN) {
console.log(msg + '✘ - no client CN'.red);
done(null, false);
} else {
var cn = subject.CN;
lookupUser(cn, function(err, user) {
msg = 'Authenticating ' + cn + ' with certificate';
if(!user) {
console.log(msg + ' ✘ - no such user'.red);
done(null, false);
} else {
console.log(msg + ' - ✔'.green);
done(null, user);
}
});
}
}
}
module.exports = CertVerifier;
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