In NestJS useStaticAssets in non-public folder - nestjs

I have this code in main.ts
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.useStaticAssets(join('public'));
Root folders:
|-public
|-uploads
|...
Path for upload in Multer:
const path = `./uploads/MYIMAGES`;
It works and Url I use to get image:
${process.env.REACT_APP_BACKEND_URL}/uploads/MYIMAGES/image.jpeg
So it looks like it pointed to public folder by default.
The question is: How make it works if upload images in
./uploads folder (in root, not /uploads in public)
(Sorry if it is stupid question, I'm pretty new in NestJS)

Related

Understanding how path works in Node

So I have developed a Node Api and on local the path works fine, but I want to move it now to a server online, and don't know how to address the path.
This is the path in local: const path = "/Users/username/Code/projectname/api/invoices"
And what I want to do is make it work also for online, also to make sure that the folder api is what is going to be uploaded, not the one with projectname as it contains the client folder and other folders, so only the api folder.
use __dirname to get the path of the folder.
The __dirname in a node script returns the path of the folder where the current JavaScript file resides.
const path = `${__dirname}/api/invoices`
You can use the __dirname variable.
For this, you first need to import path.
const nodePath = require("path");
Then, to get the path, you need to join the directory name and your custom path together.
const path = nodePath.join(__dirname, "/api/invoices");
This should correctly join the path together.
Note: Naming conventions changed to avoid naming conflicts.
In conclusion, you can use the __dirname variable!

How to access the base package form a node_module

I am looking to access a JSON config file that the user would place next to their package.json from a node_module package that I created. Is there a best approach to do this. I tried a relative import but that didn't really work and I am not sure how best to accomplish dynamic imports if the config file doesn't exist because I want to allow it to not exist as well.
Here is how I tried to handle dynamic imports though:
export const overrides = (function () {
try {
return require('../../../../../../overrides.json');
} catch (_err) {
return null;
}
})();
Also I tried fs but I get a browser config error I am not sure if that is something else. I should research but I didn't understand the docs around that.
using a library
This worked for me: find-package-json
Basically on any js file who needs the base, home or workspace path, do this:
var finder = require('find-package-json');
var path = require('path');
var f = finder(__dirname);
var rootDirectory = path.dirname(f.next().filename);
rootDirectory will be the location of the folder in which the main package.json exist.
If you want to optimize, get the appRootPath variable at the start of your app and store/propagate the variable to the hole nodejs system.
no libraries
Without any library, this worked for me:
console.log("root directory: "+require('path').resolve('./'));
This will get you the root directory of your nodejs app no matter if you are using npm run start or node foo/bar/index.js
More ways to get the root directory here:
Determine project root from a running node.js application
usage
If you achieve to obtain the root directory of your nodejs app and your file is at the package.json level, use this variable like this to locate any file at root level:
rootDirectory+"/overrides.json"

React doesn't display images uploaded with Multer

After uploading an image with Multer to the uploads folder which is located in the root with server folder and client folder, React cannot access the images in the uploads folder, as the api/upload route returns just a string as /uploads/the_image_name.
I thought I should upload the images to the public folder in the React folder but I found that the convention is using an uploads folder in the root.
Server :
app.use('/uploads', express.static(path.join(__dirname, '/uploads')))
This line should probably solve it:
app.use("/uploads", express.static('uploads'))
You need to actually serve the images that reside in your uploads folder. One way to do this is to use the express static middleware. Assuming your uploads folder resides in your app's root, you'd simply add to your express app:
app.use("/uploads", express.static('uploads'))

How to bundle and require non JS dependencies in Firebase Cloud Functions?

I have an http cloud function that returns some dynamic HTML. I want to use Handlebars as the templating engine. The template is sufficiently big that it's not practical to have it in a const variable on top of my function.
I've tried something like:
const template = fs.readFileSync('./template.hbs', 'utf-8');
But when deploying the function I always get an error that the file does not exist:
Error: ENOENT: no such file or directory, open './template.hbs'
The template.hbs is in the same directory as my index.js file so I imagine the problem is that the Firebase CLI is not bundling this file along the rest of files.
According to the docs of Google Cloud Functions it is possible to bundle local modules with "mymodule": "file:mymodule". So I've tried creating a templates folder at the root of the project and added "templates": "file:./templates" to the package.json.
My file structure being something like this:
/my-function
index.js
/templates
something.hbs
index.js //this is the entry point
And then:
const template = fs.readFileSync('../node_modules/templates/something.hbs', 'utf-8');
But I'm getting the same not found error.
What is the proper way of including and requiring a non JS dependencies in a Firebase Cloud Function?
The Firebase CLI will package up all the files in your functions folder, except for node_modules, and send the entire archive to Cloud Functions. It will reconstitue node_modules by running npm install while building the docker image that runs your function.
If your something.hbs is in /templates under your functions folder, you should be able to refer to it as ./templates/something.hbs from the top-level index.js. If your JS is in another folder, you might have to work you way out first with ../templates/something.hbs. The files should all be there - just figure out the path. I wouldn't try to do anything fancy is your package.json. Just take advantage of the fact that the CLI deploys everything but node_modules.
This code works fine for me if I have a file called 'foo' at the root of my functions folder:
import * as fs from 'fs'
export const test = functions.https.onRequest((req, res) => {
const foo = fs.readFileSync('./foo', 'utf-8')
console.log(foo)
res.send(foo)
})
The solution was to use path.join(__dirname,'template.hbs').
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync(path.join(__dirname,'template.hbs'), 'utf-8');
As #doug-stevenson pointed out all files are included in the final bundle but for some reason using the relative path did not work. Forcing an absolute path with __dirname did the trick.

Reading files from a directory inside a meteor app

How can i read the public directory in a meteor application inside my /server path.
I tried using the native 'fs' package but i keep getting a file/directory not found error.
var fs = Npm.require('fs');
var files = fs.readdirSync('/public/soundfiles/');
Has anyone used the filesystem package to read static files inside a meteor application?
I learned that it is best to upload files in your private folder if you are not displaying them outside.
In my case I need to store XML uploads and process them.
At first I wrote the XML into the public folder but that would trigger a reload.
Then I renamed the the upload folder to /public/.#uploads which would stop the reload of Meteor, but then again...it completely ignored that folder during build and the uploaded folder would not exist in the build (throw ENOENT error during read).
So I figured out it is best to put the files in /private/files and then reading goes as follows:
result = fs.readdirSync('assets/app/files')
Everything in the private folder will be moved to the Assets folder where during runtime there is an APP folder available (you do not see that in your build folder structure).
It helps to just simple dump result = fs.readdirSync('.') to see what folder you in and look through the structure.
***UPDATE*****
Locally putting files in private folder still triggered meteor rebuild/update (perhaps not in production..) so I found another solution using the UploadServer just to define the upload directory:
https://github.com/tomitrescak/meteor-uploads
This works for me in Meteor 1.0:
var fs = Npm.require('fs')
var xsd = fs.readFileSync(process.cwd().split('.meteor')[0] + 'server/company.xsd', 'utf8')
Access files without the "/public" part. In a running Meteor app, the public directory becomes your root, and everything that is located at /public/whatever can be accessed at /whatever.
Additionally, if you're playing around with files, you might find these useful:
FileSaver.js
CollectionFS
This is no longer true. For Meteor 0.8, the folder "../client/app" is public. Thus, use fs.readdirSync('../client/app') to get files and folders in public.
Source: personal experience and https://stackoverflow.com/a/18405793
For meteor 1.0.2 public is /web.browser/app/
Checked by entering .meteor dir
Total path in linux /home/user/your_app_name/.meteor/local/build/programs/web.browser/app/
And to get to root is `process.env.PWD or process.cwd().
Im not sure if its work deployed.
_meteor_bootstrap_.serverDir +'/assets/app'
This is path to private folder.
For Meteor 1.4, use server Assets.
See the official docs on Assets
http://docs.meteor.com/api/assets.html
On the server you can use fs to access any part of the meteor directory tree, not just /public, for example
import fs from 'fs';
const rd = process.env.PWD;
const obj = JSON.parse(fs.readFileSync(`${rd}/private/file.json`));
would read and parse a json file located at private/file.json under your meteor app directory root.

Resources