Electron write file when packaged - electron

In electron, how can I write a file when the app is packaged using electron packager.
The following will create and update the file in development. But once I package the app using electron-packager, the file will no longer be created. What do I need to change?
// imports
const path = require('path');
const fs = require('fs');
// create stream for appending to the log file
stream = fs.createWriteStream(
path.join(__dirname, 'logfile.log'),
{
flags:'a'
}
);
// append content to the log file
stream.write('test');
Here's how I package it:
"scripts": {
"start": "electron .",
"pack:win64": "electron-packager . my-app --out=dist/win64 --platform=win32 --arch=x64 --icon=assets/icon.png --prune=true --overwrite --asar"
},

I haven't tried this but perhaps you could use the afterCopy hook to call the function you need?
afterCopy
Array of Functions
An array of functions to be called after your app directory has been
copied to a temporary directory. Each function is called with five
parameters:
buildPath (String): The path to the temporary folder where your app has been copied to
electronVersion (String): The version of electron you are packaging for
platform (String): The target platform you are packaging for
arch (String): The target architecture you are packaging for
callback (Function): Must be called once you have completed your actions
const packager = require('electron-packager')
const { serialHooks } = require('electron-packager/hooks')
packager({
// ...
afterCopy: [serialHooks([
(buildPath, electronVersion, platform, arch) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('first function')
resolve()
}, 1000)
})
},
(buildPath, electronVersion, platform, arch) => {
console.log('second function')
}
])],
// ...
})

Related

remoteEntry.js not found on Jenkins

We are deploying a remote app written in NextJS and Typescript; The host app is in React only.
Currently the host app gets a 404 not found error as the remote app runs into this error in the Build Snapshot on Jenkins
+ ls ./dist/static/chunks/remoteEntry.js
ls: cannot access './dist/static/chunks/remoteEntry.js': No such file or directory
script returned exit code 2
However, the file is generated locally and both apps are able to spin up in local environment.
Here is our next.config.js:
const NextFederationPlugin = require('#module-federation/nextjs-mf');
const { exposedModules } = require('./lib/routes');
const version = process.env.VERSION_OVERRIDE || require('./package.json').version;
const deps = require('./package.json').dependencies;
// Note: This path needs to match with what's specified in CIRRUS_FRONTEND_ENTRYPOINT for www.
const assetBasePath = process.env.CDN_PATH ? `${process.env.CDN_PATH}${version}` : process.env.ASSET_BASE_PATH;
// Note: Heavily references module federation example meant for omnidirectional federation between Next apps.
// Changes mostly around path resolution due to our current resolution pattern via cdn
// https://github.com/module-federation/module-federation-examples/blob/master/nextjs/home/next.config.js
module.exports = {
webpack(config, options) {
Object.assign(config.experiments, { topLevelAwait: true });
// Integrated mode calls `next build` which has minimization by default. For local development, this is unnecessary.
if (process.env.NEXT_PUBLIC_ENVIRONMENT === 'INTEGRATED') {
config.optimization.minimize = false;
}
if (!options.isServer) {
console.log("Not Server");
config.output.publicPath = 'auto';
config.plugins.push(
new NextFederationPlugin({
name: 'cirrus',
filename: 'static/chunks/remoteEntry.js',
exposes: {
'./FederatedRouter': './lib/FederatedRouter',
...exposedModules
},
remoteType: 'var',
remotes: {},
shared: {
'#transcriptic/amino': {
requiredVersion: deps['#transcriptic/amino'],
singleton: true
},
react: {
requiredVersion: deps.react,
singleton: true
},
'react-dom': {
requiredVersion: deps['react-dom'],
singleton: true
},
'#strateos/micro-apps-utils': {
requiredVersion: deps['#strateos/micro-apps-utils'],
singleton: true
}
},
extraOptions: {
// We need to override the default module sharing behavior of this plugin as that assumes a nextjs host
// and thus next modules will be provided by the parent application.
// However, web is currently NOT a nextjs application so this child application so that assumption is
// invalid. Note that this means we need to ensure we explicitly specify common modules such as `react`
// in the `shared` key above.
skipSharingNextInternals: true
}
})
);
} else {
console.log("Is Server");
}
return config;
},
// Note: Annoyingly, NextJS automatically automatically appends a `_next` directory for assetPrefix
// but NOT public path so we'll have to manually include it here.
publicPath: `${assetBasePath}/_next/`,
// Note: If serving assets via CDN, assetPrefix is required to help resolve static assets.
// Also, NextJS automatically appends and expects a `_next` directory to the assetPrefix path.
// See https://nextjs.org/docs/api-reference/next.config.js/cdn-support-with-asset-prefix
assetPrefix: process.env.CDN_PATH ? assetBasePath : undefined,
distDir: 'dist',
// Use index react-router as fallback for resolving any pages that are not directly specified
async rewrites() {
return {
fallback: [
{
source: '/:path*',
destination: '/'
}
]
};
}
};
Tried upgrade NextJS from 12.1.6 to 12.2.2
Tried upgrade Webpack from 5.74.0 to 5.75.0
Cleaned cache by sh 'yarn cache clean'
Tried clear env by sh 'env -i PATH=$PATH make build-snapshot'
Hash of node modules by tar -cf - node_modules | md5sum
Downgraded "#module-federation/nextjs-mf" from 5.12.9 to 5.10.5
Verified file writing permission

launching Theia based electron app (artifact/package) isn't working

Almost new in using playwright. Exploring the things and checking what we can do with this tool.
I am trying to launch our Theia based electon app in Ubuntu 18.04 with below source.
const { _electron: electron } = require('playwright');
//const { _electron } = require('playwright');
//import { test, expect, Page } from '#playwright/test';
(async () => {
// Launch Electron app.
const electronApp = await electron.launch('./my_executable_file_path');
//this executable is an artifact/packgae
})();
test.describe('New Todo', () => {
test('should allow me to add todo items', async ({ page }) => {
//let's not do anything before the app launch.
});
});
In my package.json file, i have this already
"devDependencies": {
"#playwright/test": "^1.20.2",
I can successfully run test cases based on the browser but not able to launch the electron app.
electron.launch: Cannot find module 'electron/index.js'
We don't have this index.js in our jenkins generated artifact.
This is how I launched electron successfully
const electronApp = await _electron.launch({
args: ['theia-electron-main.js'],
cwd: 'cube-electron/apps/studio/electron/scripts'
});

When not bundling, is there any way to filter the libraries copied with copyWorkboxLibraries?

I'm building my project with npm scripts and node so I'm using workbox-build and calling copyWorkboxLibraries in a script and then in my SW I'm calling importScripts with the path set in setConfig. Is there any way to copy fewer than all of the workbox libraries or is it up to the developer to remove what isn't needed?
You could do something like this in the build script:
const pkgs = [
'workbox-core',
'workbox-sw',
];
copyWorkboxLibraries('./docs')
.then(s => {
console.log(`Workbox libraries available in ${s}.`);
return s;
})
.then(async d => {
const dir = await fs.opendir(path.resolve('./docs/' + d));
for await (const dirent of dir) {
if (!pkgs.some(pk => dirent.name.includes(pk))) {
fs.unlink(path.resolve('./docs/' + d + '/' + dirent.name));
}
}
});
This will remove every file whose name doesn't start with workbox-core or workbox-sw from the workbox-v[version] folder that you will be deploying along with your SW.

is anyone integrated videojs-record with angular 7?

I am trying to record video with audio using videojs-record and my application is in angular 7. I have followed their wiki. Here is the link below
https://github.com/collab-project/videojs-record/wiki/Angular
but this does not work for me.
here is the error what I am getting
ERROR in ./node_modules/videojs-record/dist/videojs.record.js
Module not found: Error: Can't resolve 'RecordRTC' in '/path/to/project/root/node_modules/videojs-record/dist'
ERROR in ./node_modules/videojs-record/dist/videojs.record.js
Module not found: Error: Can't resolve 'videojs' in '/path/to/project/root/node_modules/videojs-record/dist'
Here is my code and my configuration for videojs in video-recorder.component.ts
import { Component, OnInit, OnDestroy, ElementRef, Input } from '#angular/core';
import videojs from 'video.js';
import * as adapter from 'webrtc-adapter/out/adapter_no_global.js';
import * as RecordRTC from 'recordrtc';
// register videojs-record plugin with this import
import * as Record from 'videojs-record/dist/videojs.record.js';
#Component({
selector: 'app-video-recorder',
templateUrl: './video-recorder.component.html',
styleUrls: ['./video-recorder.component.scss']
})
export class VideoRecorderComponent implements OnInit, OnDestroy {
// reference to the element itself: used to access events and methods
private _elementRef: ElementRef;
// index to create unique ID for component
#Input() idx: string;
private config: any;
private player: any;
private plugin: any;
// constructor initializes our declared vars
constructor(elementRef: ElementRef) {
this.player = false;
// save reference to plugin (so it initializes)
this.plugin = Record;
// video.js configuration
this.config = {
controls: true,
autoplay: false,
fluid: false,
loop: false,
width: 320,
height: 240,
controlBar: {
volumePanel: false
},
plugins: {
// configure videojs-record plugin
record: {
audio: false,
video: true,
debug: true
}
}
};
}
ngOnInit() {}
// use ngAfterViewInit to make sure we initialize the videojs element
// after the component template itself has been rendered
ngAfterViewInit() {
// ID with which to access the template's video element
let el = 'video_' + this.idx;
// setup the player via the unique element ID
this.player = videojs(document.getElementById(el), this.config, () => {
console.log('player ready! id:', el);
// print version information at startup
var msg = 'Using video.js ' + videojs.VERSION +
' with videojs-record ' + videojs.getPluginVersion('record') +
' and recordrtc ' + RecordRTC.version;
videojs.log(msg);
});
// device is ready
this.player.on('deviceReady', () => {
console.log('device is ready!');
});
// user clicked the record button and started recording
this.player.on('startRecord', () => {
console.log('started recording!');
});
// user completed recording and stream is available
this.player.on('finishRecord', () => {
// recordedData is a blob object containing the recorded data that
// can be downloaded by the user, stored on server etc.
console.log('finished recording: ', this.player.recordedData);
});
// error handling
this.player.on('error', (element, error) => {
console.warn(error);
});
this.player.on('deviceError', () => {
console.error('device error:', this.player.deviceErrorCode);
});
}
// use ngOnDestroy to detach event handlers and remove the player
ngOnDestroy() {
if (this.player) {
this.player.dispose();
this.player = false;
}
}
}
and here is my video-recorder.component.html
<video id="video_{{idx}}" class="video-js vjs-default-skin" playsinline></video>
Below information may help to figure it out the issue.
Angular CLI: 7.2.3
Node: 10.15.1
OS: linux x64
Angular: 7.2.2
... common, compiler, core, forms, language-service
... platform-browser, platform-browser-dynamic, router
Package Version
-----------------------------------------------------------
#angular-devkit/architect 0.12.3
#angular-devkit/build-angular 0.12.3
#angular-devkit/build-optimizer 0.12.3
#angular-devkit/build-webpack 0.12.3
#angular-devkit/core 7.2.3
#angular-devkit/schematics 7.2.3
#angular/animations 7.2.7
#angular/cdk 7.3.0
#angular/cli 7.2.3
#angular/compiler-cli 7.2.7
#ngtools/webpack 7.2.3
#schematics/angular 7.2.3
#schematics/update 0.12.3
rxjs 6.3.3
typescript 3.2.4
I am new to angular. So any help on this will be appreciated. Thanks in advance.
No worries guys, I have fixed it by myself. After doing some research I came to know that as I was using angular cli to serve and build so I have used ngx-build-plus (as ng eject is deprecated in angular 7 and will be removed from angular 8) to execute webpack config using angular cli. This webpack config was missing before. This may help someone that's why just shared. Thank you.
you can't use in that way. if you are using angular cli to serve or build then you have to create a partial webpack config file and serve or build it through angular cli. You should follow below things.
Please visit below link and install the package and follow the instruction to configure your stuffs.
https://www.npmjs.com/package/ngx-build-plus
Your webpack.partial.js should look like
const webpack = require('webpack');
module.exports = {
resolve: {
alias: {
// place your config
}
},
plugins: [
// place your config
],
}
and scripts in package.json file should look like
"scripts": {
"ng": "ng",
"start": "ng serve --extra-webpack-config webpack.partial.js",
"build": "ng build --extra-webpack-config webpack.partial.js",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"build:prod": "ng build --prod --extra-webpack-config webpack.partial.js",
"build:stage": "ng build --prod -c staging --extra-webpack-config webpack.partial.js",
"build:dev": "ng build -c development --extra-webpack-config webpack.partial.js"
},
Then you can serve your app using npm start
To build you use npm run build:dev || npm run build:stage || npm run build:prod
based on the environment.

Jest and Bower Module loading in jest tests

Lets say I have a project that uses bower, grunt, bowerify(with shim) and since I love Jest so much I want to test with that. How in the world do I get jest to see my browserify shim modules when it runs tests. I use grunt, to kick off the npm test command.
Here is my package.json file.
"browser": {
"jquery": "./bower_components/jquery/dist/jquery.js",
"foundation": "./bower_components/foundation/js/foundation/foundation.js",
"fastclick": "./bower_components/fastclick/lib/fastclick.js",
"greensock-tm": "./bower_components/gsap/src/uncompressed/TweenMax.js",
"greensock-css": "./bower_components/gsap/src/uncompressed/plugins/CSSPlugin.js",
"greensock-time": "./bower_components/gsap/src/uncompressed/TimelineMax.js",
"scrollmagic": "./bower_components/ScrollMagic/js/jquery.scrollmagic.js",
"handlebars": "./bower_components/handlebars/handlebars.runtime.js"
},
"browserify-shim": {
"jquery": "$",
"greensock-css": "CSSPlugin",
"fastclick": "FastClick",
"greensock-tm": "TweenMax",
"greensock-time": "TimelineMax",
"scrollmagic": "ScrollMagic",
"foundation": "foundation",
"handlebars": "Handlebars"
},
"browserify": {
"transform": [
"browserify-shim"
]
},
Right now I almost have this worked out by doing this in my grunt file before I run the test.
grunt.registerTask("shimBowerForTests",function(){
var readJson = require('read-package-json');
var fs = require('fs');
var remapify = require('remapify');
readJson('./package.json', console.error, false, function (er, data) {
if (er) {
throw "There was an error reading the file";
}
var packages = data.browser;
var browserify = require('browserify');
for (var key in packages){
var b = browserify();
var wstream = fs.createWriteStream("devjs/test/modules/"+key+'.js');
b.add(packages[key]);
b.bundle().pipe(wstream);
}
});
});
and.
exec: {
jestTest: {
command: 'cp -r devjs/modules devjs/test/modules && npm test'
}
}
The problem is that using browserify so combine everything for the browser works great with my setup and I can require my shimmed modules like this.
require('jquery') //example but in the jest cli the test fail because they can find the module unless I somehow prefix it with ./, like so require('./jquery')
I'm guessing that the problem is that you've only installed your shimmed modules with bower. If you want them to work in node/jest, you'll have to install them with npm as well. Then just make sure Jest isn't mocking anything in the node_modules directory, and it should find all the required modules in there as long as the names match up.
Your Jest config in package.json should look like:
"jest": {
"unmockedModulePathPatterns": [
"./node_modules"
]
}
And then just download all the dependencies.
npm install jquery --save-dev
UPDATE
Instead of using my below solution you should opt for using Karma,karma browserify. I have converted the below solution into using karma and it is working much much better.
----------------------OLD ANSWER
What I actually did to solve this was, used the Jest source preprocessor to rewrite the require statement to look for a module in a certain directory in my /tests/ folder that I have created using grunt. The Folder contains the files listed in my browserify-shim, browser section of the package.json file.
EDIT: Here is how I shim bower, I made this script in the Gruntfile.js that puts all the bower modules and any commonjs modules that I need into an accessible directory.
grunt.registerTask("shimBowerForTests", function() {
var readJson = require('read-package-json');
var fs = require('fs');
readJson('./package.json', console.error, false, function(er, data) {
if (er) {
throw "There was an error reading the file";
}
var packages = data.browser;
var shim = data['browserify-shim'];
var browserify = require('browserify');
var exclude = ["jquery.maskedinput", "jquery"];
for (var key in packages) {
var b = browserify();
var wstream = fs.createWriteStream("devjs/test/modules/" + key + '.js');
if (shim[key] !== undefined && exclude.indexOf(key) === -1) {
b.add(packages[key]);
b.bundle().pipe(wstream);
} else {
var rstream = fs.createReadStream(packages[key]);
rstream.pipe(wstream);
}
}
});
});
Then in the Jest pre processor file I do this.
module.exports = {
process: function(src, path) {
var src2= src.replace(/require\([\"\']([^\.\'\"]+)[\"\']\)/g, "require(\'../modules/$1\')");
src2= src2.replace(/jest\.dontMock\([\"\']([^\.\'\"]+)[\"\']\)/g, "jest.dontMock(\'../modules/$1\')");
return src2;
}
};

Resources