How to get node asset_builder working with current express? - javascript

I've been trying to use the asset_builder node module with express 3.1, but can't seem to make it very far in the setup before receiving an error like this upon starting the server:
var parsed_url = url.parse(request.url);
TypeError: Cannot read property 'url' of undefined
This is being thrown from within the middleware.js file of the asset_builder module itself. I'm guessing this is due to the fact that Express apps no longer extend server, and so the setup in the base (app.js) file is a bit different than it once was.
Ideally I'm just trying to use asset_builder to grab all my javascript and serve it as a single file rather than the many I currently have (Ember app).
The base project I'm working off of uses ejs as the express view engine (instead of the default Jade).

Related

Fetch local files with Node.js

In a browser environment fetching a local file is quite trivial: one just need to start a server (using MAMP, XAMP, Mac's Python server, etc...), and then doing:
fetch("./foo.txt").then(etc...)
However, in Node.js this simple task has been a challenge. I've tried the same snippet using Node 18 (which comes with an experimental fetch API), but I'm always getting an invalid URL error:
TypeError: Failed to parse URL from foo.bar
[cause]: TypeError [ERR_INVALID_URL]: Invalid URL
I've tried installing node-fetch, but I'm getting the same error. I could start a local server for node like http-server, but it tells me to go to http://localhost:8080 to see the server, that is, using the browser, but the issue is that I can do that without node, using only a node build is the whole point.
My question is: is it possible to fetch a local file in a node build (Sublime Text, VS Code etc...), without using a browser? (note: I can do it with fs, but in my question I'd like to discuss fetch only)
My question is: is it possible to fetch a local file in a node build (Sublime Text, VS Code etc...), without using a browser? (note: I can do it with fs, but in my question I'd like to discuss fetch only)
The Node.js implementation of fetch does not currently support file: scheme URLs…
fetch("file:///tmp/123").then(r => r.text()).then(d => console.log(d));
reports:
Error: not implemented... yet...
…nor (it appears) does it resolve a relative path to a file: scheme URI.
You should use the fs module.

How to find full path when sending a file over a post request from Next JS functions (server)?

In the Next JS server-side pages/api, I have a function that makes a post request to a service requiring two files.
I am trying to read these files using the following code:
var fullPhotoPath = process.cwd() + '/public/photos/photo.png'
var photoStream = fs.createReadStream(fullPhotoPath)
This works when I run the app locally, but it fails with file not found error when deployed.
I assume the pathing in server changes because of webpack, though I am not familiar with NextJS.
Things I have tried:
Use relative path
Move photo files to different locations either public or private folders
Deploy in different environments: same error in both Firebase or Vercel hosting.
Workaround with getStaticProps/getServerSideProps: can't send file to API functions since they aren't JSON-able.
Thanks for suggestions.

Access a local directory to retrieve files from localhost and write back

I currently have an Angular app (MEAN Stack) that I am running locally on my Windows machine. Being new to Node/Express, I would like to be able to access a local directory from http://localhost:3006 that I have setup within my main app directory, called /myfiles which I am unsure how to do.
What I am unsure is, how do I create an endpoint to access and read these files from localhost within the /myfiles directory and display them within an Angular Material dialog?
Just not sure what I need to do as part of Express side (setting up the route) and then the Angular side (using HttpClient) to display.
Further to the above, I will also need to write back to the /myfiles directory, where I will need to perform a copy command based on a file selection within Angular.
You'll want to create an endpoint in Express that your Angular app can call to be served the files.
I'll assume the files you want to read and send are JSON files. Here's a really simple example of an endpoint that you can visit that will return the file to your frontend.
In your Angular code you will make a get call to /myfile
var fs = require("fs");
app.get('/myFile', (req, res) => {
var filepath = __dirname + '/myfiles/thefile.json';
var file = fs.readFileSync(filepath, encoding);
res.json(JSON.parse(file));
});
Then in Angular, you'll have something like
http.get('/myfile').subscribe( (data) => { console.log("The data is: ", data) });
ADDED
The example I provided above was just the basics to answer your question. Ideally, in production for file paths, you should the Node path library which 'knows' how to behave in different environments and file systems.

Issue with routing in react app

I have a web app. Back end with node and front end with React. Setup (simplified) goes like this:
index.js (the server)
client
package.json
The client
Now, the client folder contains a front end web application, its contents are basically same as what you get when you type create-react-app.
Inside client there is a build folder which I created by running npm run build from within the client folder.
Server
Now, the index.js from my main folder acts as the node server, inside it I have a line like:
app.use(express.static(__dirname + "/client/build"));
Using this approach I have merged my node server and a client front end application (located inside client folder). You can see I told the server to serve files from the client/build.
All was working fine, till I encountered this.
If I click a react button in my client app which manually calls my router using say:
this.props.router.push('/listmovies');
it correctly shows the page.
But if I type same page in URL address bar and hit ENTER I get error:
Cannot GET /listmovies
The latter error I am pretty sure comes from node server. Because there is no listener for listmovies in index.js (and there should not be). You see basically I think node is intercepting the call and giving me an error. Whereas in my former case where I called router.push I get a correct page.
I hope I managed to explain my problem. Can someone help how to solve this issue?
You have to make the express application redirect all requests to the main React file so react-router can take over. Something like this below the app.use.
app.get('*', function(req, res) {
res.sendFile(__dirname + '/client/build/index.html')
})
This basically handles all wildcards and points it to the index.html. Mind you if you are also implementing API routes on the express app have them above this wildcard statement because otherwise it will intercept them and treat them as client side react-router routes instead of server-side API routes.

Do RouteControllers need to be defined in server code for iron-router#1.0.0-pre3

While attempting to migrate from Meteor 0.8.3 & IR 0.8.2 to Meteor 0.9.3.1 & IR 1.0.0-pre3 I'm running into a problem with RouteControllers.
I have the following js in the '/both' folder of the project:
Router.route('scene.index', {
path: '/',
controller: 'SceneController'
});
And the SceneController js in the '/client' tree:
SceneController = RouteController.extend({
template: 'SceneView'
...
});
When attempting to access the route from the client, I get the following error:
Error: RouteController 'SceneController' is not defined.
at resolve (packages/iron:router/lib/route.js:94)
at Function.Route.findControllerConstructor (packages/iron:router/lib/route.js:116)
at Function.Route.createController (packages/iron:router/lib/route.js:134)
at Function.Router.createController (packages/iron:router/lib/router.js:181)
at Function.Router.dispatch (packages/iron:router/lib/router_server.js:66)
at Object.router (packages/iron:router/lib/router.js:15)
at next (/Users/pward/.meteor/packages/webapp/.1.1.2.1m8ln9s++os+web.browser+web.cordova/npm/node_modules/connect/lib/proto.js:190:15)
at Function.app.handle (/Users/pward/.meteor/packages/webapp/.1.1.2.1m8ln9s++os+web.browser+web.cordova/npm/node_modules/connect/lib/proto.js:198:3)
at Object.fn [as handle] (/Users/pward/.meteor/packages/webapp/.1.1.2.1m8ln9s++os+web.browser+web.cordova/npm/node_modules/connect/lib/proto.js:74:14)
at next (/Users/pward/.meteor/packages/webapp/.1.1.2.1m8ln9s++os+web.browser+web.cordova/npm/node_modules/connect/lib/proto.js:190:15)
After a little quality time with node-inspector, I've come to the conclusion that IR needs client-side RouteControllers to be visible on the server.
My route controllers currently set session variables and I'd prefer not to sprinkle Meteor.isClient around. Is this an IR bug or a known breaking change?
My route controllers currently set session variables and I'd prefer
not to sprinkle Meteor.isClient around. Is this an IR bug or a known
breaking change?
You don't need to guard your controller code with Meteor.isClient because it's going to be executed only in the client side even if it's declared in the shared folder.
Your route definition is better written like this in iron:router#1.0.0-pre3 :
Router.route('/', {
name: 'scene.index',
controller: 'SceneController'
});
name/path have switched their position.
EDIT :
As far as iron:router concepts are concerned, please read this :
http://eventedmind.github.io/iron-router/#client-and-server
Having routes defined on both the client and the server is mandatory to determine what needs to be done.
Client-side, if a link to a client route is detected then we can navigate to it using the HTML5 pushState API, if a server route is detected then standard HTTP communication takes place (for example I use server routes to provide downloadable resources in my app), if the link corresponds to no known path to the router, then an error is triggered.
Server side, it's important to know about client routes to send 404 on unknown paths instead of serving the Meteor app, here is a quote about this from the official guide :
It also means that on the server, if there is no client route defined,
we can send a 404 response to the client instead of loading up the
Meteor application.
Yes, I've always placed my router.js in the shared common code, which is any folder not named server/ or client/.

Categories