How to get a mapped Url in Vite? Source map - vite

I have not yet entered the world of plugins, but I have one idea and I want to test it as simple as possible.
Question:
I have a url WITHOUT SOURCE MAP, e.g. instance/$$self.$$.update#http://localhost:5173/src/lib/ContextListItem.svelte:448:15.
And I want to get from it a URL WITH SOURCE MAP, e.g. http://localhost:5173/src/lib/ContextListItem.svelte:19:11.
Theoretically it is a simple function:
const mappedUrl = getMappedUrl(url)
How to get it in Vite?
What do I need it for?
I have such code:
window._log = console.log.bind(console);
console.log = function (...a) {
try {
throw Error("aa");
} catch (err) {
const fileUrl = err.stack.split("\n")[1].split("#")[1].replace(`${location.origin}/`,"").split(":")[0];
window._log(...a, `${location.origin}/__open-in-editor?file=${/* encodeURIComponent */(fileUrl)}`);
}
}
And I want (as you can see) to add a link to the location in the code (thanks to the method from __open-in-editor).
Here I am missing a specific line and column in the file.
In Microsoft Egde any link from the console can direct to VSCode, but unfortunately in other browsers this is not there (e.g. my bug for Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1771862).

This is the answer, But it only works asynchronously, so it's not suitable for replacing console.log. :/
Use on the Web - https://github.com/mozilla/source-map/#use-on-the-web
Consuming a source map - https://github.com/mozilla/source-map/#consuming-a-source-map
<script src="https://unpkg.com/source-map#0.7.3/dist/source-map.js"></script>
<script>
sourceMap.SourceMapConsumer.initialize({
"lib/mappings.wasm": "https://unpkg.com/source-map#0.7.3/lib/mappings.wasm"
});
</script>
<script type="module">
export async function aaa (origin, fileUrl, line, column) {
const res = await fetch(`${origin}/${fileUrl}.map`);
const json = await res.json();
const place = await sourceMap.SourceMapConsumer.with(json, null, consumer => {
const place = consumer.originalPositionFor({
line: Number(line),
column: Number(column)
});
return place;
});
return place;
}
</script>

Related

How can I import a Cypher query to my Node.js logic?

I'm not a very experienced developer but I am looking too structure my project so it is easier to work on.
Lets say I have a function like this:
const x = async (tx, hobby) => {
const result = await tx.run(
"MATCH (a:Person) - [r] -> (b:$hobby) " +
"RETURN properties(a)",
{ hobby }
)
return result
}
Can I put my cypher query scripts in seperate files, and reference it? I have seen a similar pattern for SQL scripts.
This is what I'm thinking:
const CYPHER_SCRIPT = require('./folder/myCypherScript.cyp')
const x = async (tx, hobby) => {
const result = await tx.run(
CYPHER_SCRIPT,
{ hobby }
)
return result
}
..or will i need to stringify the contents of the .cyp file?
Thanks
You can use the #cybersam/require-cypher package (which I just created).
For example, if folder/myCypherScript.cyp contains this:
MATCH (a:Person)-->(:$hobby)
RETURN PROPERTIES(a)
then after the package is installed (npm i #cybersam/require-cypher), this code will output the contents of that file:
// Just require the package. You don't usually need to use the returned module directly.
// Handlers for files with extensions .cyp, .cql, and .cypher will be registered.
require('#cybersam/require-cypher');
// Now require() will return the string content of Cypher files
const CYPHER_SCRIPT = require('./folder/myCypherScript.cyp')
console.log(CYPHER_SCRIPT);

fs.createReadStream getting a different path than what's being passed in

I'm using NodeJS on a VM. One part of it serves up pages, and another part is an API. I've run into a problem, where fs.createReadStream attempts to access a different path than what is being passed into the function. I made a small test server to see if it was something else in the server affecting path usage, for whatever reason, but it's happening on my test server as well. First, here's the code:
const fs = require('fs');
const path = require('path');
const csv = require('csv-parser');
const readCSV = (filename) => {
console.log('READ CSV GOT ' + filename); // show me what you got
return new Promise((resolve, reject) => {
const arr = [];
fs.createReadStream(filename)
.pipe(csv())
.on('data', row => {
arr.push(row);
})
.on('error', err => {
console.log(err);
})
.on('end', () => {
resolve(arr);
});
}
}
// tried this:
// const dir = path.relative(
// path.join('path', 'to', 'this', 'file),
// path.join('path', 'to', 'CONTENT.csv')
// );
// tried a literal relative path:
// const dir = '../data/CONTENT.csv';
// tried a literal absolute path:
// const dir = '/repo/directory/server/data/CONTENT.csv';
// tried an absolute path:
const dir = path.join(__dirname, 'data', 'CONTENT.csv');
const content = readCSV(dir)
.then(result => {console.log(result[0]);})
.catch(err => {console.log(err);});
...but any way I slice it, I get the following output:
READCSV GOT /repo/directory/server/data/CONTENT.csv
throw er; // Unhandled 'error' event
^
Error: ENOENT: no such file or directory, open '/repo/directory/data/CONTENT.csv'
i.e., is fs.createReadStream somehow stripping out the directory of the server, for some reason? I suppose I could hard code the directory into the call to createReadStream, maybe? I just want to know why this is happening.
Some extra: I'm stuck on node v8.11, can't go any higher. On the server itself, I believe I'm using older function(param) {...} instead of arrow functions -- but the behavior is exactly the same.
Please help!!
Code is perfect working.
I think you file CONTENT.csv should be in data folder like "/repo/directory/data/CONTENT.csv".
I'm answering my own question, because I found an answer, I'm not entirely sure why it's working, and at least it's interesting. To the best of my estimation, it's got something to do with the call stack, and where NodeJS identifies as the origin of the function call. I've got my server set up in an MVC pattern so my main app.js is in the root dir, and the function that's being called is in /controllers folder, and I've been trying to do relative paths from that folder -- I'm still not sure why absolute paths didn't work.
The call stack goes:
app.js:
app.use('/somepath', endpointRouter);
...then in endpointRouter.js:
router.get('/request/file', endpointController.getFile);
...then finally in endpointController.js:
const readCSV = filename => {
//the code I shared
}
exports.getFile = (req, res, next) => {
// code that calls readCSV(filename)
}
...and I believe that because Node views the chain as originating from app.js, it then treats all relative paths as relative to app.js, in my root folder. Basically when I switched to the super unintuitive single-dot-relative path: './data/CONTENT.csv', it worked with no issue.

Call function from Dust template

I'm developing a simple web site where I need to retrieve a list of objects from a database. I wanted to try nodejs so, after days of reading and tests, I finally decided to use this configuration:
Server technology: Nodejs + Express
Template engine: Dust
Database/Data source: Parse
I wired all these stuff and it seems working well, but I have now the first problem: I need to call a function from a Dust template, this is the code:
{>layout/}
{<content}
<ul>
{#photos}
<li>{photo.get("name")}{~n}</li>
{/photos}
</ul>
{/content}
but it doesn't work because it prints out {photo.get("name")} (literally) instead of printing the name of each photo. The query with Parse works correctly as I can see the loaded objects via console.log().
I'm new both with nodejs and dust so I'm not sure the problem is related only to dust. Any idea?
I have no any other solution except creation of a helper:
var dust = require('dustjs-linkedin');
dust.helpers.exec = function(chunk, context, bodies, params) {
var args = JSON.parse(params.args.replace(/'/g, '"'));
var object = context.stack.head;
params.func.split('.').some(function(property) {
if (typeof(object[property]) === "function") {
var result = object[property].apply(object, args);
chunk.write(result);
return true;
} else {
object = object[property];
return false;
}
})
return chunk;
};
Suppose we have following data:
app.get('/dust-test', function(req, res) {
function Photo(name) {
var props = {'name': name};
this.get = function(prop) {
return props[prop];
}
}
var photos = ['foo', 'bar', 'nanana'].map(function(name) {
return new Photo(name);
})
res.render("dust-test", {
photo: new Photo('me'),
photos: photos
});
});
Usage:
<li>{#exec func="photo.get" args="['name']" /}</li>
{#photo}
<li>{#exec func="get" args="['name']" /}</li>
{/photo}
<ul>
{#photos}
<li>{#exec func="get" args="['name']" /}{~n}</li>
{/photos}
</ul>
Where args - is an array of arguments in json format (single quotes are used)

Node.JS - fs.exists not working?

I'm a beginner in Node.js, and was having trouble with this piece of code.
var fs = require('fs');
Framework.Router = function() {
this.run = function(req, res) {
fs.exists(global.info.controller_file, function(exists) {
if (exists) {
// Here's the problem
res.writeHead(200, {'Content-Type':'text/html'});
var cname = App.ucfirst(global.info.controller)+'Controller';
var c = require(global.info.controller_file);
var c = new App[cname]();
var action = global.info.action;
c[action].apply(global.info.action, global.info.params);
res.end();
} else {
App.notFound();
return false;
}
});
}
};
The problem lies in the part after checking if the 'global.info.controller_file' exists, I can't seem to get the code to work properly inside the: if (exists) { ... NOT WORKING }
I tried logging out the values for all the variables in that section, and they have their expected values, however the line: c[action].apply(global.info.action, global.info.params);
is not running as expected. It is supposed to call a function in the controller_file and is supposed to do a simple res.write('hello world');. I wasn't having this problem before I started checking for the file using fs.exists. Everything inside the if statement, worked perfectly fine before this check.
Why is the code not running as expected? Why does the request just time out?
Does it have something to do with the whole synchronous vs asynchronous thing? (Sorry, I'm a complete beginner)
Thank you
Like others have commented, I would suggest you rewrite your code to bring it more in-line with the Node.js design patterns, then see if your problem still exists. In the meantime, here's something which may help:
The advice about not using require dynamically at "run time" should be heeded, and calling fs.exists() on every request is tremendously wasteful. However, say you want to load all *.js files in a directory (perhaps a "controllers" directory). This is best accomplished using an index.js file.
For example, save the following as app/controllers/index.js
var fs = require('fs');
var files = fs.readdirSync(__dirname);
var dotJs = /\.js$/;
for (var i in files) {
if (files[i] !== 'index.js' && dotJs.test(files[i]))
exports[files[i].replace(dotJs, '')] = require('./' + files[i]);
}
Then, at the start of app/router.js, add:
var controllers = require('./controllers');
Now you can access the app/controllers/test.js module by using controllers.test. So, instead of:
fs.exists(controllerFile, function (exists) {
if (exists) {
...
}
});
simply:
if (controllers[controllerName]) {
...
}
This way you can retain the dynamic functionality you desire without unnecessary disk IO.

Javascript-emitting template engine for node.js?

Consider e.g. the following scenario: we give some entry point URL (something like https://our.server/customer-name/entry-point.js) to our customer, so that they're able to include our product on their page by simply writing
<script language="Javascript" src="https://our.server/customer-name/entry-point.js"/>
in the place they want to put our product (yes, I know, this is an ugly solution, but it is not something I could change).
So here we face the problem: our entry-point.js should somehow know from where (https://our.server/customer-name/) it should load the other files. So it seems that the answer is to generate entry-point.js dynamically so that it will contain e.g.
var ourcompany_ourproduct_basepath = "https://our.server/customer-name/";
The obvious way to do this is to construct an entry-point.js manually, something like this:
res.write("var ourprefix_basepath = \"" + basepath.escape() + "\";");
res.write("function ourprefix_entryPoint() { /*do something*/ }");
res.write("ourprefix_entryPoint();");
As you can see, it is just too bad.
Is there any template engine that will allow e.g. for the following:
var basepath = "https://our.server/customer-name/";
var export = {
ourprefix_basepath: basepath.escape(),
ourprefix_entrypoint: function() { /* do something */ }
};
templateEngine.render(export);
or
view.vw:
ourprefix_basepath = rewrite("{#basepath}");
function ourprefix_entrypoint() { /* do something */
ourprefix_entrypoint();
App.js:
templateEngine.render("view.vw", { basepath: "https://our.server/customer-name/" });
or something like this (you've got the idea), which will write the following to the response stream:
var ourprefix_basepath = "https://our.server/customer-name/";
function ourprefix_entrypoint() { /* do something */ };
ourprefix_entrypoint();
?
It seems that Node.js supports reflection, though i can't find if it is explicitly stated somewhere.
So, by exploiting the fact JSON is the subset of JS, the following cleaner code without using a template engine is possible:
var entrypoint = function(data) {
/* do something with data.basepath and data.otherparam here... */
}
exports.processRequest = function(request, response) {
var data = {
basepath: computeBasepath(request),
otherparam: "somevalue"
};
response.send("(" + entrypoint.toString() + ")(" + JSON.stringify(data) + ")");
}

Resources