How to copy asset files before deploying cloud functions to Firebase - node.js

I have a firebase project where I write typescript functions to be deployed into Google Node Cloud functions.
When I run the firebase deploy --only functions command, it transpiles my code into javascript and put the js output into a folder called lib next to src folder where my typescript functions are.
However, some of my functions need access to local files such as .ttf files or some other file types. Those don't get copied over to the lib folder and therefore, I get errors in runtime Error: ENOENT: no such file or directory, open path/to/file
Question 1 : How do I get the deploy command to copy assets files to the output folder ?
Question 2 : Given that all my functions live in separate files, in separate folders, and so do my assets, how should I reference my assets so that they can be found ? Should I give the path to the asset file relative to the lib folder or relative to where the function lives ?
EDIT -1
See the project structure here :
the code that need the font lives in the some-function.ts file. And it uses the pdfmake library that needs fonts to work.
Here is how I do it in the some-function.ts file :
const fonts: TFontDictionary = {
Poppins: {
normal: './fonts/Poppins/Poppins-Regular.ttf',
bold: './fonts/Poppins/Poppins-Bold.ttf',
italics: './fonts/Poppins/Poppins-Medium.ttf',
bolditalics: './fonts/Poppins/Poppins-Thin.ttf',
}
};
const pdfmake = require('pdfmake');
const printer = new pdfmake(fonts);
So how do I reference such fonts given that they are located in the fonts folder. or event if I put them in a separate folder at the root or src ?

After some digging I came to a solution that I would like to share here.
1- First thing, as suggested by #Dharmaraj, I added a script that removes the lib folder, before building the project, and copy my assets files before deploying.
So in the package.json under functions folder, I updated the build command as follow
"remove-lib":"rm -rf lib",
"copy-assets":"cp -rf src/path/to/your-folder/fonts lib/path/to/your-folder",
"do-build":"tsc",
"build": "npm run remove-lib && npm run do-build && npm run copy-assets",
Actually, adding the remove lib command solved another issue I had with deploying functions. I think this should be the default behaviour because when you rename function files, old ones stick in lib folder causing all sort of issues.
Anyway, now in order to correctly reference your asset, just construct the path as ${__dirname}/fonts/some-font.ttf provided that the fonts folder lives in the same folder as the file your are editing.

Related

How to copy files/folders from src folder during a bin execution with Node js?

I would like to copy the content of my 'three-experience' folder into the current "bin execution environment".
I'm using Typescript, but there is no issue with it at the moment (and I'm mapping on the .js dist files).
I have the following root:
My package.json is mapping in the dist folder like so :
"bin": {
"ts-cli": "dist/main.js",
"vite-config": "dist/bin/vite-config.js"
},
During the execution I'm calling the "vite-config" bin (using shelljs):
shell.exec('vite-config');
It may not be clear but the purpose is to do a npm package that would install a template on your local machine.
I can do it with git. But that's not what I want to do.
I thought about filling a process.env.FOLDER global variable, but I am quite sure that's a bad idea.
Any clue would be appreciated !

__dirname in typescript for nodejs

This is the first time I'm using typescript in my node project.
my directory structure looks like this
root
src // typescript files
index.ts
build // compiled js files
src
index.js
storage // storage for media
I'm outputting my compiled javascript into ./build
now, In my index.ts file, I have
fs.existsSync(resolve(__dirname, '../storage'))
This works when i'm running nodemon with ts-node and of course fails when I run javascript output from build.
I believe there's a way to tell typescript to process these files according to tsconfig.compilerOptions.outDir
or compile as srcNew/index.js instead of build/src/index.js but I'm not able to find it.
I figured it out,
Turns out this is a behaviour of typescript compiler.
And you should only set tsconfig.compilerOptions.rootDir when you want your current directory structure to be a part of the tsconfig.compilerOptions.outDir directory. Otherwise it would copy your current directory struture into outDir as it is.
You can read more about it here.

readFileSync - no such file or directory on packaged app

I am working on an Electron app.
I have several JSON files from my src folder that need to be copied over to a user-folder during app initialization (settings, config, etc).
It works well when on dev mode and when I do import the JSON files.
But based on how I need it, readFileSync is the best way to implement this.
var srcPath = path.resolve(__dirname, '../config/settings.json')
fs.readFileSync(srcPath)
I am getting an error though when running the packaged exe app (in asar).
Getting error messages like this:
Error: ENOENT: no such file or directory, open
'C:\Users\username\Desktop\NodeJS\branches\Electron
\myApp\dist\electron\My-App-win32-x64\resources\config\settings.json'
readdirSync() also does not work for the same reason.
I understand that my relative path is different in the packaged version
I checked the asar file and I can't seem to find my JSON files. Not sure if I am checking correctly though since it is bundled up by Webpack.
My file in this example is located in:
C:\Users\username\Desktop\NodeJS\branches\Electron\myApp\src\config\settings.json
How can I make this work?
Is there a way to force electron (I am using Electron-Packager with Quasar framework) to include my JSON files in the packaged app?
Does Webpack not bundle up the JSON files??
Thoughts? Help please!
As a workaround, I just created a folder that will contain 'post-packaging' scripts. One of which does a copy from my src folder to my dist\electron\appName\resources folder (using robocopy).

How can i download file inside app folder ?[ after packaging ]

This is my current folder structurebefore packaging
WRM_80.. is my downloaded folder.
I have these two lines of code inside index.js to download and show html in my electron window
fs.createReadStream('./Report.zip').pipe(unzip.Extract({ path: './'+folderName }));
LoginWindow.loadURL(`file://${__dirname}./`+folderName+`/t01s01q01.html`);
in development mode its working fine, file downloaded inside the same folder where my index.js exists. But after packaging the app file is downloading outside app folder. Packaged folder structure is given below WRM_80.. is my downloaded folder.
after packaging
That's why I can not load that downloaded file into window. How can I download file inside app folder? If that is not possible, how can I load external file from resources\app location ?
By referencing the directory as ./folder_name you are essentially telling the application to download to the working directory. In this case, the working directory is the folder that the program is contained in. While developing and using the electron command, the working directory is the root of your application. However once installed and running as a .exe, the working directory changes to the location of the executable.
To solve this problem, do not use the current working directory. Instead use the user / application data folder to store this information. It is not only a consistent location across development and deployment, but it is also the semantically correct place to store application data.
In Electron you can get the path to the application data folder for your app with:
const {app} = require('electron');
app.getPath('userData')
So your code should look something like this:
var userData = app.getPath('userData');
fs.createReadStream(`${userData}/Report.zip`).pipe(unzip.Extract({ path: `${userData}/${folderName}` }));
LoginWindow.loadURL(`file://${userData}/${folderName}/t01s01q01.html`);

require.context for node modules does not work with linked package

I created kind of a plug-in web site. Each plug-in follows a certain name standard and a contract. Inside my main.js I load all packages "dynamically" following the name standard:
const context = require.context("../../node_modules", true, /plugin\-\w+\/dist\/(index\.js|styles\.css)$/)
This requires a context throughout node_modules folder and loads all modules named "plugin-X". From within those modules it looks for "dist/index.js" and "dist/styles.css". Those later get imported:
context.keys().forEach(path => {/* do stuff */ })
This works super nice as long as the packages are installed using npm install path/to/tgz. However this does not give a pleasant developing experience. So in my plugin-X folder I use "npm link" and in my web site I use "npm link plugin-X".
when I start webpack now the whole thing explodes after creating 15K file handles. If I remove the node_modules folder inside "plugin-X" it works. However I need node_modules for building with babel and other stuff to recognize changes in src folder to rebuild and put new scripts into dist folder.
Is there any way I could do this? Or maybe another option I missed during my research on how this could be done?
Regards

Resources