how to execute nx build before nx serve? - nrwl-nx

Curious what the correct way is to execute a nx build command as a prerequisite of nx serve?
So for example, in this example from my workspace.json:
"foo": {
"root": "apps/foo",
"sourceRoot": "apps/foo/src",
"projectType": "application",
"prefix": "foo",
"schematics": {},
"architect": {
"build": {
"builder": "./tools/builders/foo:build",
"options": {}
},
"serve": {
"builder": "./tools/builders/foo:serve",
"options": {}
}
}
},
when i run nx serve foo I want it to automatically call nx build foo --with-deps
what's the 'nx way' to do this?

To achieve what you want you could define a new target:
"architect": {
"build": {
"builder": "./tools/builders/foo:build",
"options": {}
},
"base-serve": {
"builder": "./tools/builders/foo:serve",
"options": {}
},
"serve": {
"builder": "#nrwl/workspace:run-commands",
"options": {
"commands": [
"nx build foo --with-deps",
"nx base-serve foo"
],
"parallel": false
}
}
}
Run commands allows you to invoke any number of commands or shell scripts, in parallel or in order. You can block on certain output to appear, etc..
In your case, it looks like you have a custom builder. So you could also extend the builder to invoke the build target before starting serving. If you use the same serve builder many times, that might be preferable.
Nx doesn't have an "aspect-oriented" way of decorating targets. The main reason why is that it sort of works for basic scenarios, but doesn't work for anything sophisticated. For instance, in you case, you may want to watch the files and rebuild all deps of the project. Like this: https://github.com/nrwl/nx-incremental-large-repo/blob/master/tools/scripts/watch.js
So may want to have a long running process performing rebuilds.

You should be able to do this with waitUntilTargets and a run command abstracting the build call
"build-foo": {
"executor": "#nrwl/workspace:run-commands",
"options": {
"commands": [
{
"command": "nx build foo --with-deps"
}
],
"readyWhen": "Put text here you will see when build is complete"
}
},
"serve": {
"executor": "#nrwl/node:execute",
"options": {
"buildTarget": "app:build",
"waitUntilTargets": ["app:build-foo"]
}
},
It's unclear to me if this is a new syntax as the setup you have for declaring the targets is not what I'm seeing now. I have these targets set up in the app project.json files.

Related

VS CODE SaveAll from Task

I want to execute SaveAll from a task such as evoking workbench.action.files.saveAll from within Task.
The objective is to make sure all files are saved before triggering series of other Tasks.
Task #1: SaveAll (workbench.action.files.saveAll)
Task #2: Run Grunt that dependsOn Task#1
The tasks.json looks something like this
{
"version": "2.0.0",
"tasks": [
{
"command": "workbench.action.files.saveAll",
"label": "SaveAllFiles",
},
{
"type": "grunt",
"task": "default",
"label": "Execute Grunt",
"dependsOn": [
"SaveAllFiles"
],
"problemMatcher": []
}
]
}
In theory, all I should have to do is execute the task labeled Execute Grunt, and it will call the SaveAllFiles task. To be precise, I don't want to trigger tasks based on Save or SaveAll events; there are times when I want to save files, but not trigger other tasks.
{
"label": "SaveAllFiles",
"command": "${command:workbench.action.files.saveAll}",
"type": "shell",
"problemMatcher": []
},
{
"type": "grunt",
"task": "default",
"label": "Execute Grunt",
"dependsOn": [
"SaveAllFiles"
],
"dependsOrder": "sequence", // need this, "parallel" is the default otherwise
"problemMatcher": []
}
${command:workbench.action.files.saveAll} is the general form for calling a vscode command, you can also call extension or macro commands this way.
The info on this is in https://code.visualstudio.com/docs/editor/variables-reference#_command-variables which makes it a little tricky to find as it isn't in the Tasks documentation.

How to forward command into run-commands using NX CLI?

Given I have entries in angular.json that define various commands using the serverless CLI (as an example)
"serverless-deploy": {
"builder": "#nrwl/workspace:run-commands",
"options": {
"command": "npx serverless deploy",
"cwd": "apps/my-app"
}
},
"serverless-remove": {
"builder": "#nrwl/workspace:run-commands",
"options": {
"command": "npx serverless remove",
"cwd": "apps/my-app"
}
}
How can I improve this by reducing duplication and combining it into one entry so that I can forward the command in?
E.G something like this:
"sls": {
"builder": "#nrwl/workspace:run-commands",
"options": {
"command": "npx serverless",
"cwd": "apps/my-app"
}
}
And then call it with nx run my-app:sls MYCOMMAND (E.G 'deploy' or 'remove')?
Unfortunately the above doesn't work but would love to know if this is possible.
"sls": {
"builder": "#nrwl/workspace:run-commands",
"options": {
"commands": [
"npx sls {args.cmd}"
],
"cwd": "apps/api",
"parallel": false
}
},
nx run api:sls --cmd=deploy

VSCode Tasks, user input for npm script

I am trying to create a task for the npm script configured in package.json. So, here are the files:
package.json
....
scripts : {
"migrate": "node_modules/.bin/migrate-mongo",
"migrate:create": "npm run migrate create" // --> this command needs input (file name)
}
....
Now when I have to run the migrate:create command I have to go to shell and run like this:
$> npm run migrate:craete filename
And it works fine.
Now I want to create a task for the same. For that I did some research and taking the idea from:
https://stackoverflow.com/a/53846572/1227940 created the tasks.json as:
tasks.json
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "Create a db migration script.",
"command": "npm run migrate create ${input:migrationName}",
}
],
"inputs": [
{
"type": "promptString",
"id": "migrationName",
"description": "Name your migration script?",
"default": "create"
}
]
}
But somehow it is not giving me a text box to input anything and directly going inside and firing a command: npm run migrate:create which is failing since filename is missed.
Can anyone please shed some light, what I lacked and what I missed, please let me know?
Thanks in advance,
happy coding :)
So, finally I did some research and found the solution and here it is:
tasks.json
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "Create Migration Script",
"command": "npm run migrate:create ${input:migrationName}",
"problemMatcher": []
}
],
"inputs": [
{
"type": "promptString",
"id": "migrationName",
"description": "Name your migration script (prefix with create-, update-, delete-, insert-)?"
}
]
}
Here the command is the actual script I configured in pacakage.json as:
package.json
....
scripts : {
"migrate": "node_modules/.bin/migrate-mongo",
"migrate:create": "npm run migrate create",
}
....
In the command of tasks.json I mentioned the npm run script which is configured in package.json.
Thanks and happy coding :)

Using a shell command as VSCode task variable value

I am trying to define a VSCode task in tasks.json that would adapt to the specific architecture where VSCode runs. To do this, I want to get the architecture as uname --m (e.g. "aarch64" or "amd64"). My goal is to interpolate the output of uname into an environment variable like so
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "cmake",
"args": [
"-DMYLIB_INCLUDE_DIR=$MYLIB/include",
"-DMYLIB_LIBRARY=$MYLIB/lib"
],
"options": {
"env": {
"MYLIB": "${workspaceFolder}/mylib/${command:get_arch}"
}
},
}
]
In my case, I will have architecture-specific versions of mylib under mylib/aarch64, mylib/amd64, etc.
My attempt so far as been to define a second get_arch task used in the environment definition of MYLIB, that simply runs uname.
{
"label": "get_arch",
"type": "shell",
"command": "uname --m"
}
Of course, this task is not a proper command and so it isn't detected by VSCode and my build task fails. I checked out the documentation on variable substition, but they don't mention if it's possible to substitute a shell command. I guess this would be possible from within an extension, but I want to keep things as simple as possible.
This extension provides a way to launch arbitrary shell commands as a VS Code command:
"tasks": [
{
"label": "test_arch",
"type": "shell",
"command": "echo",
"args": [
"${MYARCH}"
],
"options": {
"env": {
"MYARCH": "${input:get_arch}"
}
},
"problemMatcher": []
},
],
"inputs": [
{
"id": "get_arch",
"type": "command",
"command": "shellCommand.execute",
"args": {
"command": "uname -m"
}
}
]
One disadvantage I discovered is that you have to press Enter once more when the result of the command is prompted in picker. Aside of this, this is the straightest way to implement what you want, and yet it can be utilized in many similar situations.
Alternatively, you can add pickString input with arch picker or create an extension that adds only single command GetArch.
If you don't want to press enter every time, you can add the option useFirstResult: true in the args section.

How to Invoke WebView Extension from File Type

I am creating a VS Code WebView extension that I wish to invoke/trigger when I open a file of a specific file extension name. e.g. MyFile.abc.
Within myExt I added the onFileSystem to the activationEvents within package.json:
{
"name": "myext",
"description": "A Webview API Sample",
"version": "0.0.2",
"publisher": "vscode-myext",
"engines": {
"vscode": "^1.25.0"
},
"categories": [
"Other"
],
"activationEvents": [
"onWebviewPanel:myExt",
"onFileSystem:abc",
"*"
],
"main": "./out/extension.js",
"contributes": {
"commands": [
{
"command": "myExt.start",
"title": "Start myExt ",
"category": "My Ext"
}
]
},
"scripts": {
"vscode:prepublish": "tsc -p ./",
"compile": "tsc -p ./",
"watch": "tsc -w -p ./",
"postinstall": "node ./node_modules/vscode/bin/install"
},
"dependencies": {
"supports-color": "^6.0.0",
"vscode": "^1.1.18"
},
"devDependencies": {
"#types/node": "^10.5.2",
"tslint": "^5.11.0",
"typescript": "^2.9.2"
}
}
When I add "onFileSystem:abc" to activationEvents in myExt I was expecting my webview extension to open anytime I opened a file with the extension .abc however nothing happened.
I then tried the activationEvents setting "*", expecting that my webview extension would open at the start of VSCode but that too did not open my extension.
I am able to open and run my extension through Ctrl+Shift+P as per normal.
I don't think there's any activation event that fires when a file with a specific name or extension is opened. The onFileSystem event you were trying has a different purpose and checks for the scheme of a file.
Normally you would use onLanguage for this, and use the language identifier that your .abc extension is associated with. If it's not a popular file extension, you might need to register it in the contributes.languages section.
I then tried the activationEvents setting "*", expecting that my webview extension would open at the start of VSCode but that too did not open my extension.
The activate() method of your extension should always be called if the activation event is *. I assume by "running it with the command palette" you mean debugging the extension through the extension development host? Unless your extension is in your <User>/.vscode/extensions directory, it wouldn't be included in regular VSCode executions. It should then also be listed in the Extensions panel.
I think that you need to use
"workspaceContains:*.abc" as activationEvents
I think you have to do something for below in package.json
{
"activationEvents": [
"onCommand:"**HERE WILL BE YOUR EXTENSION NAME WHICH YOU REGISTERED**"
],
"contributes": {
"menus": {
"explorer/context": [
{
"when": "resourceLangId == **abc**", // this is the extension of the file where you want to execute your command
"command": "**YOUR COMMAND NAME**",
"title": "Anything relevent title",
"group": "navigation"
}
]
}
}
}
According to custom-editor-sample example by Microsoft, you need to do the following configuration in package.json:
"contributes": {
"customEditors": [
{
"viewType": "catCustoms.catScratch",
"displayName": "Cat Scratch",
"selector": [
{
"filenamePattern": "*.cscratch"
}
]
},