I have tried importing my Kafka library inside page.svelte, and it has thrown an error saying it is not allowed to import Kafka inside the script.
<script>
import Table from "$lib/Table.svelte";
import {Kafka, logLevel} from 'kafkajs';
</script>
Later I found we can export the kafka producer by setting the kafka import in hooks.server.js. I imported the kafka library in hooks.server.js and added the producer in event.locals. Later exported it to my script tag of page.svelte.
export let producer;
Still, the value of producer is undefined. Any leads on how to expose the imports from hooks.server.js to svelte.page could be much appreciated.
You can't do that at all, as the library is not meant for the browser and data transferred to the page has to be serialized which is impossible here.
From the FAQ:
Can KafkaJS be used in a browser?
No - KafkaJS is a library for NodeJS
and will not work in a browser context.
Communication with Kafka happens over a TCP socket. The NodeJS API
used to create that socket is net.connect/tls.connect. There is no
equivalent API in browsers as of yet, which means that even if you run
KafkaJS through a transpilation tool like Browserify, it cannot
polyfill those modules.
You could expose the functionality via custom API endpoints instead of trying to use it directly.
How one would transfer locals otherwise:
Locals are not exposed automatically, they are only available in server functions. One can pass locals from the server to the page e.g. in the top +layout.server.js load function:
export const load = ({ locals }) => {
return { value: locals.value };
};
Data returned from this function is available to all pages using the layout via the data property.
Related
Let's say you have a standalone server that acts as your data layer and then a Next.js app that's sole purpose is to server-side render the React and occasionally prefetch data from getServerSideProps. Beyond that, most interactions happen between the browser-side client and the standalone server directly (trying to avoid an unnecessary Next.js middleman / cold starts). Now if I'm trying to set an auth token via cookies, is there an elegant way to effectively share that cookie between Next.js and the client, so that the client is authenticated on requests, but also the Next.js getServerSideProps functions?
I'm wondering if I need to have a singular /api/login Next.js serverless function that just acts as a "I'll take the cookie for myself and also pass it right along to you (the client)"
Does this all make sense? In my case the standalone server is built on NestJS. I could use a tool like react-ssr to server side render everything, and that might be a good solution since almost every page has blocking data requirements, but I'm trying to understand my options, and it seems like this is probably a commonly faced issue with frameworks like Next.js.
You can use js-cookie to set cookies directly from the renderer.
Then all you need to do is get your cookie from req.headers.cookie.
import Cookie from "js-cookie";
function Index() {
function setCookie() {
Cookie.set("yourCookieName", "yourCookieValue");
}
return (
<div>
<button onClick={setCookie}>set cookie</button>
</div>
);
};
export async function getServerSideProps({ req }) {
console.log(req.headers.cookie)
return { props: {} }
}
export default Index;
I am using Quasar v2 for my Electron app development.
In this version, native node modules will no longer work on the renderer processes.
To get around this, there is electron-preload.js where we can access these node methods and expose them to the other parts of the app.
So I did this to expose fs:
import { contextBridge } from 'electron'
contextBridge.exposeInMainWorld('electronFs', require('fs'))
Then on my Vue/js files:
const fs = window.electronFs || require('fs')
fs.lstatSync(somePath).isFile()
But then I am getting fs.lstatSync(...).isFile is not a function. Any thoughts how can I make this work?
This is just for a local application (no web connectivity).
Thanks!
By default, Main process doesn't share the same context as Renderer's. And Preload runs in a context of Renderer's but isolated. Instead of exposing native Nodejs APIs to Renderer insecurely, even though you're building a local app, you may still use IPC to expose limited interfaces to Preload of Renderer process, then use contextBridge to expose APIs to Renderer. Here are some demo snippets.
/* Main.js */
const fs = require('fs');
const {ipcMain} = require('electron');
ipcMain.handle('isFile', (path) =>
fs.lstatSync(path).isFile()
)
/* Preload.js */
import {ipcRenderer, contextBridge} from "electron";
contextBridge.exposeInMainWorld('myAPIs', {
isFile: (path) => ipcRenderer.invoke('isFile')
}
/* index.vue */
myAPIs.isFile('path-to-file');
That happens because, in Electron, the backend and the UI don't share the same process (they run in different threads) because if you allow exposing native node APIs into the user context (the UI that runs finally in Chromium), it means that any time external javascript is loaded, they can access all those native APIs in the user computer.
So, those variables get transported to one thread to the other using IPC (Inter-process Communication), is just data, need to be primitives, if not they get serialized to primitives in the end (types of variables with no methods or objects like string, numbers, dates, or objects as string or binary), so probably to send those object from the parent context to the UI context Electron probably removes all non-serializable properties (so no functions).
Don't do that, is extremely insecure, just move data from one side to the other, which is very similar to using WebSockets.
I'm trying to develop a desktop app which would need to make a few private API calls, authenticated using some secret keys.
The keys are created for me by external IT service providers outside of my organisation - they are responsible for the security so there are a few constraints:
They said even though they have already taken steps on their end to secure the API and there are mitigation strategies in place even if a breach happens, but still they would like to make sure that I treat the keys with a security-conscious mindset and take whatever steps possible on my end as well to make sure they remain secured.
I'm not allowed to just create random middleware / gateway on a private server or serverless platform to perform the API calls on my app's behalf as these calls may contain business data.
I have done some research and from what I can find, the general recommendation is to set up a ".env" file in the project folder and use environment variables in that file to store the API keys.
But upon reading the Vue CLI documentation I found the following:
WARNING
Do not store any secrets (such as private API keys) in your app!
Environment variables are embedded into the build, meaning anyone can
view them by inspecting your app's files.
So, given the constraints, is there a way to store these keys securely in a Vue CLI 4 + Electron Desktop app project?
Thanks.
In general, especially if you have a lot of environment variables, it would be better practice to store environment variables in a dot env file (.env), however, it's possible that this file could be leaked when you package your electron app. So, in this case it would be better to store your environment variables from the terminal/command line. To do so follow this guide (https://www.electronjs.org/docs/api/environment-variables).
Keep in mind anything that requires the API key/private information try to keep it on the backend, i.e., the electron process and send the results to the Vue front end.
Here's an example of how you could implement this:
On windows from CMD:
set SOME_SECRET="a cool secret"
On POSIX:
$ export SOME_SECRET="a cool secret"
Main process:
// Other electron logic
const { ipcMain } = require("electron");
// Listen for an event sent from the client to do something with the secret
ipcMain.on("doSomethingOnTheBackend", (event, data) => {
API.post("https://example.com/some/api/endpoint", {token: process.env.SOME_SECRET, data});
});
Client side:
const { ipcRenderer } = require("electron");
ipcRenderer.send("doSomethingOnTheBackend", {username: "test", password: "some password"});
Also note, to use the ipcRenderer on the client side nodeIntegration needs to be enabled.
Here are some more resources to help you get started:
https://www.electronjs.org/docs/api/ipc-renderer
https://www.electronjs.org/docs/api/ipc-main
I have a file called utils.js which has some constants and I'm building a socket app which uses Node for backend work and regular Javascript for frontend. The names of the socket events are identical in both frontend and backend so I want to use the constants both in backend and frontend. But the syntax for exporting/importing is different in ecmascript6 as opposed to Node so how do I pull this off?
This is the contents of utils.js:
const EVENTS = {
CONNECTION: 'connection',
MESSAGE: 'message'
};
Object.freeze(EVENTS);
module.exports = EVENTS;
You can put the objects in JSON file, like events.json, or even event.js is you want plain JS objects. Both the Node and JS have access to this. Then you require/import this file in utils.js and you can do the same on the front end. Front and back ends can handle these however they want.
I wrote a very simple service using sails.js. It uses Basic Authentication for access to its services.
I also have a separate front end written in Angular, using the #angular/cli.
I have two sets of environment variables to set for prod and dev. For example:
// dev
ADMIN=admin
ADMIN_PASS=mypassword123
API_ENDPOINT=http://localhost:1337/endpoint
This would obviously be different for prod. My issue is that I am deploying this using Heroku. You can easily set the env vars in heroku, but I don't know how to access them. I know you can set things in src/environments but this would then put my variables in code control.
I have also tried process.env but I learned this is a node.js thing not and angular thing.
How do I access system environment variables from angular2?
example of how I'd us it:
#Injectable()
export class HeroService {
private heroesUrl = 'api/heroes'; // <- this should be grabbed from environment
private adminUser = 'admin'; // this line too...
private adminPass = 'myPassword'; // same with this line...
constructor (private http: Http) {}
getHeroes(): Observable<Hero[]> { ...}
}
Programing Point of View
Use process.env then server side(nodejs) can put them into a structure. Since you are using sails.js, setup a post route or an api call that will send this structure in json format.
Front end(browser) app can make a http.post call to pick it up at run time.
This way the set of parameters are not bundled/hardcoded in your front end app code base.
Security Point of View
If password credential is required for 3rd party service, such call is better handled from the server side like following:
(browser) -- api call --> (your server) -- api call --> (3rd-party)
This way credential to 3rd party is not exposed. And api call to your server should be protected by some authentication mechanism.