@joshmossas/nx-cargo 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +3 -0
- package/.eslintrc.json +34 -0
- package/README.md +39 -0
- package/build.config.ts +10 -0
- package/dist/index.cjs +100 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.mjs +79 -0
- package/executors.json +25 -0
- package/generators.json +25 -0
- package/jest.config.ts +17 -0
- package/package.json +30 -0
- package/project.json +53 -0
- package/src/common/index.spec.ts +183 -0
- package/src/common/index.ts +358 -0
- package/src/common/schema.d.ts +111 -0
- package/src/executors/build/executor.ts +21 -0
- package/src/executors/build/schema.d.ts +39 -0
- package/src/executors/build/schema.json +77 -0
- package/src/executors/clippy/executor.ts +18 -0
- package/src/executors/clippy/schema.d.ts +34 -0
- package/src/executors/clippy/schema.json +29 -0
- package/src/executors/run/executor.ts +19 -0
- package/src/executors/run/schema.d.ts +32 -0
- package/src/executors/run/schema.json +77 -0
- package/src/executors/test/executor.ts +19 -0
- package/src/executors/test/schema.d.ts +22 -0
- package/src/executors/test/schema.json +73 -0
- package/src/generators/binary/files/Cargo.toml__template__ +8 -0
- package/src/generators/binary/files/src/main.rs__template__ +3 -0
- package/src/generators/binary/generator.spec.ts +75 -0
- package/src/generators/binary/generator.ts +76 -0
- package/src/generators/binary/schema.d.ts +6 -0
- package/src/generators/binary/schema.json +35 -0
- package/src/generators/init/files/Cargo.toml +2 -0
- package/src/generators/init/files/rust-toolchain.toml__template__ +2 -0
- package/src/generators/init/files/rustfmt.toml +0 -0
- package/src/generators/init/generator.spec.ts +49 -0
- package/src/generators/init/generator.ts +55 -0
- package/src/generators/init/schema.d.ts +7 -0
- package/src/generators/init/schema.json +14 -0
- package/src/generators/library/files/Cargo.toml__template__ +8 -0
- package/src/generators/library/files/src/lib.rs__template__ +13 -0
- package/src/generators/library/generator.spec.ts +96 -0
- package/src/generators/library/generator.ts +78 -0
- package/src/generators/library/schema.d.ts +6 -0
- package/src/generators/library/schema.json +35 -0
- package/src/graph/index.ts +189 -0
- package/src/index.ts +1 -0
- package/tsconfig.json +13 -0
- package/tsconfig.lib.json +12 -0
- package/tsconfig.spec.json +20 -0
package/.babelrc
ADDED
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": ["../../.eslintrc.json"],
|
|
3
|
+
"ignorePatterns": ["!**/*"],
|
|
4
|
+
"overrides": [
|
|
5
|
+
{
|
|
6
|
+
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
|
7
|
+
"rules": {
|
|
8
|
+
"@typescript-eslint/no-explicit-any": "off"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"files": ["*.ts", "*.tsx"],
|
|
13
|
+
"rules": {}
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"files": ["*.js", "*.jsx"],
|
|
17
|
+
"rules": {}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"files": ["*.json"],
|
|
21
|
+
"parser": "jsonc-eslint-parser",
|
|
22
|
+
"rules": {
|
|
23
|
+
"@nx/dependency-checks": "error"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"files": ["./package.json", "./executors.json"],
|
|
28
|
+
"parser": "jsonc-eslint-parser",
|
|
29
|
+
"rules": {
|
|
30
|
+
"@nx/nx-plugin-checks": "error"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# @nxrs/cargo
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/%40nxrs%2Fcargo)
|
|
4
|
+
|
|
5
|
+
This is a WIP plugin for `@nrwl/nx` adding support for Rust applications and libraries.
|
|
6
|
+
|
|
7
|
+
## Generators
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
# @nxrs/cargo:bin also works
|
|
11
|
+
> nx generate @nxrs/cargo:app my-rust-app
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
> nx generate @nxrs/cargo:lib my-rust-lib
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Executors
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
# Build a library or binary
|
|
22
|
+
> nx build my-rust-app
|
|
23
|
+
|
|
24
|
+
# Run unit tests in a library
|
|
25
|
+
> nx test my-rust-lib
|
|
26
|
+
|
|
27
|
+
# Check a Rust project with `clippy`
|
|
28
|
+
> nx lint my-rust-app
|
|
29
|
+
# Don't fail on warnings:
|
|
30
|
+
> nx lint my-rust-app --fail-on-warnings false
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Options
|
|
34
|
+
|
|
35
|
+
The executors accept most of the same CLI args as the corresponding `cargo` commands. When in doubt, run with the `--help` flag to see all options with descriptions:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
> nx build my-rust-app --help
|
|
39
|
+
```
|
package/build.config.ts
ADDED
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const devkit = require('@nx/devkit');
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const cp = require('node:child_process');
|
|
6
|
+
const os = require('node:os');
|
|
7
|
+
const path = require('node:path');
|
|
8
|
+
|
|
9
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
10
|
+
|
|
11
|
+
function _interopNamespaceCompat(e) {
|
|
12
|
+
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
13
|
+
const n = Object.create(null);
|
|
14
|
+
if (e) {
|
|
15
|
+
for (const k in e) {
|
|
16
|
+
n[k] = e[k];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
n.default = e;
|
|
20
|
+
return n;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
24
|
+
const cp__namespace = /*#__PURE__*/_interopNamespaceCompat(cp);
|
|
25
|
+
const os__namespace = /*#__PURE__*/_interopNamespaceCompat(os);
|
|
26
|
+
const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
|
|
27
|
+
|
|
28
|
+
function createDependencies(_, ctx) {
|
|
29
|
+
const allDependencies = [];
|
|
30
|
+
const processedWorkspaceRoots = /* @__PURE__ */ new Set();
|
|
31
|
+
const cargoConfigPaths = Object.values(ctx.projects).map((p) => path__namespace.join(ctx.workspaceRoot, p.root, "Cargo.toml")).filter((p) => fs__default.existsSync(p));
|
|
32
|
+
for (const configPath of cargoConfigPaths) {
|
|
33
|
+
const configDir = path__namespace.dirname(configPath);
|
|
34
|
+
const metadata = getCargoMetadata(configDir);
|
|
35
|
+
if (processedWorkspaceRoots.has(metadata.workspace_root)) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
processedWorkspaceRoots.add(metadata.workspace_root);
|
|
39
|
+
const workspaceDeps = processWorkspaceMetadata(ctx, metadata);
|
|
40
|
+
allDependencies.push(...workspaceDeps);
|
|
41
|
+
}
|
|
42
|
+
return allDependencies;
|
|
43
|
+
}
|
|
44
|
+
function processWorkspaceMetadata(ctx, metadata) {
|
|
45
|
+
const {
|
|
46
|
+
packages,
|
|
47
|
+
workspace_members: cargoWsMembers,
|
|
48
|
+
resolve: cargoResolve
|
|
49
|
+
} = metadata;
|
|
50
|
+
const workspacePackages = /* @__PURE__ */ new Map();
|
|
51
|
+
for (const id of cargoWsMembers) {
|
|
52
|
+
const pkg = packages.find((p) => p.id === id);
|
|
53
|
+
if (pkg) workspacePackages.set(id, pkg);
|
|
54
|
+
}
|
|
55
|
+
const nxData = mapCargoProjects(ctx, workspacePackages);
|
|
56
|
+
return cargoResolve.nodes.filter(({ id }) => nxData.has(id)).flatMap(({ id: sourceId, dependencies }) => {
|
|
57
|
+
const sourceProject = nxData.get(sourceId);
|
|
58
|
+
const cargoPackage = workspacePackages.get(sourceId);
|
|
59
|
+
const sourceManifest = path__namespace.relative(ctx.workspaceRoot, cargoPackage.manifest_path).replace(/\\/g, "/");
|
|
60
|
+
return dependencies.filter((depId) => nxData.has(depId)).map((depId) => ({
|
|
61
|
+
source: sourceProject.name,
|
|
62
|
+
target: nxData.get(depId).name,
|
|
63
|
+
type: devkit.DependencyType.static,
|
|
64
|
+
sourceFile: sourceManifest
|
|
65
|
+
}));
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function getCargoMetadata(cwd) {
|
|
69
|
+
const availableMemory = os__namespace.freemem();
|
|
70
|
+
const metadata = cp__namespace.execSync("cargo metadata --format-version=1", {
|
|
71
|
+
encoding: "utf8",
|
|
72
|
+
maxBuffer: availableMemory,
|
|
73
|
+
cwd
|
|
74
|
+
// Crucial: run in the workspace directory
|
|
75
|
+
});
|
|
76
|
+
return JSON.parse(metadata);
|
|
77
|
+
}
|
|
78
|
+
function mapCargoProjects(ctx, packages) {
|
|
79
|
+
let result = /* @__PURE__ */ new Map();
|
|
80
|
+
for (let [cargoId, cargoPackage] of packages) {
|
|
81
|
+
if (!cargoPackage.manifest_path) {
|
|
82
|
+
throw new Error("Expected cargo package's `manifest_path` to exist");
|
|
83
|
+
}
|
|
84
|
+
let manifestDir = path__namespace.dirname(cargoPackage.manifest_path);
|
|
85
|
+
let projectDir = path__namespace.relative(ctx.workspaceRoot, manifestDir).replace(/\\/g, "/");
|
|
86
|
+
let found = Object.entries(ctx.projects).find(
|
|
87
|
+
([, config]) => config.root === projectDir
|
|
88
|
+
);
|
|
89
|
+
if (found) {
|
|
90
|
+
let [projectName, projectConfig] = found;
|
|
91
|
+
result.set(cargoId, {
|
|
92
|
+
...projectConfig,
|
|
93
|
+
name: projectName
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
exports.createDependencies = createDependencies;
|
package/dist/index.d.cts
ADDED
package/dist/index.d.mts
ADDED
package/dist/index.d.ts
ADDED
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { DependencyType } from '@nx/devkit';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import * as cp from 'node:child_process';
|
|
4
|
+
import * as os from 'node:os';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
|
|
7
|
+
function createDependencies(_, ctx) {
|
|
8
|
+
const allDependencies = [];
|
|
9
|
+
const processedWorkspaceRoots = /* @__PURE__ */ new Set();
|
|
10
|
+
const cargoConfigPaths = Object.values(ctx.projects).map((p) => path.join(ctx.workspaceRoot, p.root, "Cargo.toml")).filter((p) => fs.existsSync(p));
|
|
11
|
+
for (const configPath of cargoConfigPaths) {
|
|
12
|
+
const configDir = path.dirname(configPath);
|
|
13
|
+
const metadata = getCargoMetadata(configDir);
|
|
14
|
+
if (processedWorkspaceRoots.has(metadata.workspace_root)) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
processedWorkspaceRoots.add(metadata.workspace_root);
|
|
18
|
+
const workspaceDeps = processWorkspaceMetadata(ctx, metadata);
|
|
19
|
+
allDependencies.push(...workspaceDeps);
|
|
20
|
+
}
|
|
21
|
+
return allDependencies;
|
|
22
|
+
}
|
|
23
|
+
function processWorkspaceMetadata(ctx, metadata) {
|
|
24
|
+
const {
|
|
25
|
+
packages,
|
|
26
|
+
workspace_members: cargoWsMembers,
|
|
27
|
+
resolve: cargoResolve
|
|
28
|
+
} = metadata;
|
|
29
|
+
const workspacePackages = /* @__PURE__ */ new Map();
|
|
30
|
+
for (const id of cargoWsMembers) {
|
|
31
|
+
const pkg = packages.find((p) => p.id === id);
|
|
32
|
+
if (pkg) workspacePackages.set(id, pkg);
|
|
33
|
+
}
|
|
34
|
+
const nxData = mapCargoProjects(ctx, workspacePackages);
|
|
35
|
+
return cargoResolve.nodes.filter(({ id }) => nxData.has(id)).flatMap(({ id: sourceId, dependencies }) => {
|
|
36
|
+
const sourceProject = nxData.get(sourceId);
|
|
37
|
+
const cargoPackage = workspacePackages.get(sourceId);
|
|
38
|
+
const sourceManifest = path.relative(ctx.workspaceRoot, cargoPackage.manifest_path).replace(/\\/g, "/");
|
|
39
|
+
return dependencies.filter((depId) => nxData.has(depId)).map((depId) => ({
|
|
40
|
+
source: sourceProject.name,
|
|
41
|
+
target: nxData.get(depId).name,
|
|
42
|
+
type: DependencyType.static,
|
|
43
|
+
sourceFile: sourceManifest
|
|
44
|
+
}));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function getCargoMetadata(cwd) {
|
|
48
|
+
const availableMemory = os.freemem();
|
|
49
|
+
const metadata = cp.execSync("cargo metadata --format-version=1", {
|
|
50
|
+
encoding: "utf8",
|
|
51
|
+
maxBuffer: availableMemory,
|
|
52
|
+
cwd
|
|
53
|
+
// Crucial: run in the workspace directory
|
|
54
|
+
});
|
|
55
|
+
return JSON.parse(metadata);
|
|
56
|
+
}
|
|
57
|
+
function mapCargoProjects(ctx, packages) {
|
|
58
|
+
let result = /* @__PURE__ */ new Map();
|
|
59
|
+
for (let [cargoId, cargoPackage] of packages) {
|
|
60
|
+
if (!cargoPackage.manifest_path) {
|
|
61
|
+
throw new Error("Expected cargo package's `manifest_path` to exist");
|
|
62
|
+
}
|
|
63
|
+
let manifestDir = path.dirname(cargoPackage.manifest_path);
|
|
64
|
+
let projectDir = path.relative(ctx.workspaceRoot, manifestDir).replace(/\\/g, "/");
|
|
65
|
+
let found = Object.entries(ctx.projects).find(
|
|
66
|
+
([, config]) => config.root === projectDir
|
|
67
|
+
);
|
|
68
|
+
if (found) {
|
|
69
|
+
let [projectName, projectConfig] = found;
|
|
70
|
+
result.set(cargoId, {
|
|
71
|
+
...projectConfig,
|
|
72
|
+
name: projectName
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { createDependencies };
|
package/executors.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"executors": {
|
|
4
|
+
"build": {
|
|
5
|
+
"implementation": "./src/executors/build/executor",
|
|
6
|
+
"schema": "./src/executors/build/schema.json",
|
|
7
|
+
"description": "Build a Cargo project"
|
|
8
|
+
},
|
|
9
|
+
"run": {
|
|
10
|
+
"implementation": "./src/executors/run/executor",
|
|
11
|
+
"schema": "./src/executors/run/schema.json",
|
|
12
|
+
"description": "Run a Cargo executable"
|
|
13
|
+
},
|
|
14
|
+
"test": {
|
|
15
|
+
"implementation": "./src/executors/test/executor",
|
|
16
|
+
"schema": "./src/executors/test/schema.json",
|
|
17
|
+
"description": "Run unit tests"
|
|
18
|
+
},
|
|
19
|
+
"clippy": {
|
|
20
|
+
"implementation": "./src/executors/clippy/executor",
|
|
21
|
+
"schema": "./src/executors/clippy/schema.json",
|
|
22
|
+
"description": "Linter for Rust code"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
package/generators.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"name": "cargo",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"generators": {
|
|
6
|
+
"init": {
|
|
7
|
+
"factory": "./src/generators/init/generator",
|
|
8
|
+
"schema": "./src/generators/init/schema.json",
|
|
9
|
+
"description": "Initialize the @nxrs/cargo plugin",
|
|
10
|
+
"hidden": true
|
|
11
|
+
},
|
|
12
|
+
"binary": {
|
|
13
|
+
"factory": "./src/generators/binary/generator",
|
|
14
|
+
"schema": "./src/generators/binary/schema.json",
|
|
15
|
+
"description": "Create a Rust binary",
|
|
16
|
+
"aliases": ["bin", "app", "application"]
|
|
17
|
+
},
|
|
18
|
+
"library": {
|
|
19
|
+
"factory": "./src/generators/library/generator",
|
|
20
|
+
"schema": "./src/generators/library/schema.json",
|
|
21
|
+
"description": "Create a Rust library",
|
|
22
|
+
"aliases": ["lib"]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
package/jest.config.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
export default {
|
|
3
|
+
displayName: "cargo",
|
|
4
|
+
preset: "../../jest.preset.js",
|
|
5
|
+
globals: {},
|
|
6
|
+
testEnvironment: "node",
|
|
7
|
+
transform: {
|
|
8
|
+
"^.+\\.[tj]sx?$": [
|
|
9
|
+
"ts-jest",
|
|
10
|
+
{
|
|
11
|
+
tsconfig: "<rootDir>/tsconfig.spec.json",
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
moduleFileExtensions: ["ts", "tsx", "js", "jsx"],
|
|
16
|
+
coverageDirectory: "../../coverage/packages/cargo",
|
|
17
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@joshmossas/nx-cargo",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.6.2",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "dist/index.mjs",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/nxrs/cargo.git"
|
|
10
|
+
},
|
|
11
|
+
"author": {
|
|
12
|
+
"name": "Danny McGee",
|
|
13
|
+
"email": "dannymcgee@gmail.com",
|
|
14
|
+
"url": "https://github.com/dannymcgee"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"chalk": "^4.1.2",
|
|
18
|
+
"lodash": "^4.17.21",
|
|
19
|
+
"tslib": "^2.0.0"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@nx/devkit": ">= 17"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"unbuild": "^3.6.1"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "unbuild"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/project.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
3
|
+
"name": "cargo",
|
|
4
|
+
"projectType": "library",
|
|
5
|
+
"sourceRoot": "packages/cargo/src",
|
|
6
|
+
"tags": [],
|
|
7
|
+
"targets": {
|
|
8
|
+
"lint": {
|
|
9
|
+
"executor": "@nx/eslint:lint",
|
|
10
|
+
"outputs": ["{options.outputFile}"]
|
|
11
|
+
},
|
|
12
|
+
"test": {
|
|
13
|
+
"executor": "@nx/jest:jest",
|
|
14
|
+
"outputs": ["{workspaceRoot}/coverage/packages/cargo"],
|
|
15
|
+
"options": {
|
|
16
|
+
"jestConfig": "packages/cargo/jest.config.ts"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"build": {
|
|
20
|
+
"executor": "@nx/js:tsc",
|
|
21
|
+
"outputs": ["{options.outputPath}"],
|
|
22
|
+
"options": {
|
|
23
|
+
"outputPath": "dist/packages/cargo",
|
|
24
|
+
"tsConfig": "packages/cargo/tsconfig.lib.json",
|
|
25
|
+
"packageJson": "packages/cargo/package.json",
|
|
26
|
+
"main": "packages/cargo/src/index.ts",
|
|
27
|
+
"assets": [
|
|
28
|
+
"packages/cargo/*.md",
|
|
29
|
+
{
|
|
30
|
+
"input": "./packages/cargo/src",
|
|
31
|
+
"glob": "**/!(*.ts)",
|
|
32
|
+
"output": "./src"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"input": "./packages/cargo/src",
|
|
36
|
+
"glob": "**/*.d.ts",
|
|
37
|
+
"output": "./src"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"input": "./packages/cargo",
|
|
41
|
+
"glob": "generators.json",
|
|
42
|
+
"output": "."
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"input": "./packages/cargo",
|
|
46
|
+
"glob": "executors.json",
|
|
47
|
+
"output": "."
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { ExecutorContext, Tree } from "@nx/devkit";
|
|
2
|
+
import { createTreeWithEmptyWorkspace } from "@nx/devkit/testing";
|
|
3
|
+
|
|
4
|
+
import ClippyCliOptions from "../executors/clippy/schema";
|
|
5
|
+
import {
|
|
6
|
+
CargoOptions,
|
|
7
|
+
normalizeGeneratorOptions,
|
|
8
|
+
parseCargoArgs,
|
|
9
|
+
Target,
|
|
10
|
+
} from "./index";
|
|
11
|
+
|
|
12
|
+
describe("common utils", () => {
|
|
13
|
+
describe("parseCargoArgs", () => {
|
|
14
|
+
it("should support --target argument", () => {
|
|
15
|
+
let ctx = mockExecutorContext("test-app:build");
|
|
16
|
+
let opts: CargoOptions = {
|
|
17
|
+
target: "86_64-pc-windows-gnu",
|
|
18
|
+
};
|
|
19
|
+
let [args] = parseCargoArgs(Target.Build, opts, ctx);
|
|
20
|
+
args.unshift("cargo");
|
|
21
|
+
|
|
22
|
+
expect(args.join(" ")).toEqual(
|
|
23
|
+
"cargo build --bin test-app --target 86_64-pc-windows-gnu"
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should support --package argument", () => {
|
|
28
|
+
let ctx = mockExecutorContext("test-app:build");
|
|
29
|
+
let opts: CargoOptions = {
|
|
30
|
+
package: "foo",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
let args = ["cargo", ...parseCargoArgs(Target.Build, opts, ctx)[0]];
|
|
34
|
+
expect(args.join(" ")).toEqual("cargo build --bin foo");
|
|
35
|
+
|
|
36
|
+
args = ["cargo", ...parseCargoArgs(Target.Test, opts, ctx)[0]];
|
|
37
|
+
expect(args.join(" ")).toEqual("cargo test -p foo");
|
|
38
|
+
|
|
39
|
+
args = ["cargo", ...parseCargoArgs(Target.Run, opts, ctx)[0]];
|
|
40
|
+
expect(args.join(" ")).toEqual("cargo run -p foo");
|
|
41
|
+
|
|
42
|
+
args = ["cargo", ...parseCargoArgs(Target.Clippy, opts, ctx)[0]];
|
|
43
|
+
expect(args.join(" ")).toEqual(
|
|
44
|
+
"cargo clippy -p foo -- -D warnings --no-deps"
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("should ignore the Nx-config-specified target name", () => {
|
|
49
|
+
let ctx = mockExecutorContext("test-app:flooptydoopty");
|
|
50
|
+
let opts: CargoOptions = {};
|
|
51
|
+
let args = ["cargo", ...parseCargoArgs(Target.Build, opts, ctx)[0]];
|
|
52
|
+
|
|
53
|
+
expect(args.join(" ")).toEqual("cargo build --bin test-app");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should correctly handle `release` option", () => {
|
|
57
|
+
let ctx = mockExecutorContext("test-app:build");
|
|
58
|
+
|
|
59
|
+
let args = ["cargo", ...parseCargoArgs(Target.Build, { release: false }, ctx)[0]];
|
|
60
|
+
expect(args.join(" ")).toEqual("cargo build --bin test-app");
|
|
61
|
+
|
|
62
|
+
args = ["cargo", ...parseCargoArgs(Target.Build, { release: true }, ctx)[0]];
|
|
63
|
+
expect(args.join(" ")).toEqual("cargo build --bin test-app --profile release");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should pass through unknown arguments to cargo", () => {
|
|
67
|
+
let ctx = mockExecutorContext("test-app:build");
|
|
68
|
+
|
|
69
|
+
let opts: CargoOptions & { [key: string]: string } = {
|
|
70
|
+
profile: "dev-custom",
|
|
71
|
+
};
|
|
72
|
+
let args = ["cargo", ...parseCargoArgs(Target.Build, opts, ctx)[0]];
|
|
73
|
+
|
|
74
|
+
expect(args.join(" ")).toEqual(
|
|
75
|
+
"cargo build --bin test-app --profile dev-custom",
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
opts = { unknownArg: "lorem-ipsum" };
|
|
79
|
+
args = ["cargo", ...parseCargoArgs(Target.Build, opts, ctx)[0]];
|
|
80
|
+
|
|
81
|
+
expect(args.join(" ")).toEqual(
|
|
82
|
+
"cargo build --bin test-app --unknown-arg lorem-ipsum",
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("allows specifying a custom binary target", () => {
|
|
87
|
+
let ctx = mockExecutorContext("test-app:build");
|
|
88
|
+
|
|
89
|
+
let opts: CargoOptions = {
|
|
90
|
+
bin: "custom-bin-name",
|
|
91
|
+
};
|
|
92
|
+
let args = ["cargo", ...parseCargoArgs(Target.Build, opts, ctx)[0]];
|
|
93
|
+
|
|
94
|
+
expect(args.join(" ")).toEqual(
|
|
95
|
+
"cargo build -p test-app --bin custom-bin-name",
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("correctly handles pass-through arguments for clippy", () => {
|
|
100
|
+
let ctx = mockExecutorContext("test-app:lint");
|
|
101
|
+
let opts: ClippyCliOptions = {
|
|
102
|
+
package: "test-app-pkg",
|
|
103
|
+
target: "wasm32-unknown-unknown",
|
|
104
|
+
fix: false,
|
|
105
|
+
failOnWarnings: true,
|
|
106
|
+
noDeps: true,
|
|
107
|
+
};
|
|
108
|
+
let args = ["cargo", ...parseCargoArgs(Target.Clippy, opts, ctx)[0]];
|
|
109
|
+
|
|
110
|
+
expect(args.join(" ")).toEqual(
|
|
111
|
+
"cargo clippy -p test-app-pkg --target wasm32-unknown-unknown "
|
|
112
|
+
+ "-- -D warnings --no-deps",
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("correctly handles the `env` option", () => {
|
|
117
|
+
let ctx = mockExecutorContext("test-app:run");
|
|
118
|
+
let opts: CargoOptions = {
|
|
119
|
+
package: "foo",
|
|
120
|
+
env: {
|
|
121
|
+
RUST_BACKTRACE: "FULL",
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
let [args, env] = parseCargoArgs(Target.Run, opts, ctx);
|
|
125
|
+
|
|
126
|
+
expect(["cargo", ...args].join(" ")).toEqual("cargo run -p foo");
|
|
127
|
+
expect(env).toHaveProperty("RUST_BACKTRACE", "FULL");
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe("normalizeGeneratorOptions", () => {
|
|
132
|
+
let appTree: Tree;
|
|
133
|
+
|
|
134
|
+
beforeAll(() => {
|
|
135
|
+
appTree = createTreeWithEmptyWorkspace();
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("should respect kebab-case project names", () => {
|
|
139
|
+
let opts = normalizeGeneratorOptions("application", appTree, { name: "my-app" });
|
|
140
|
+
expect(opts.projectName).toBe("my-app");
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("should respect snake_case project names", () => {
|
|
144
|
+
let opts = normalizeGeneratorOptions("application", appTree, { name: "my_app" });
|
|
145
|
+
expect(opts.projectName).toBe("my_app");
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("should respect PascalCase project names", () => {
|
|
149
|
+
let opts = normalizeGeneratorOptions("application", appTree, { name: "MyApp" });
|
|
150
|
+
expect(opts.projectName).toBe("MyApp");
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("should respect camelCase project names (you monster)", () => {
|
|
154
|
+
let opts = normalizeGeneratorOptions("application", appTree, { name: "myApp" });
|
|
155
|
+
expect(opts.projectName).toBe("myApp");
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
function mockExecutorContext(command: string): ExecutorContext {
|
|
161
|
+
let [projectName, targetName] = command.split(":");
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
cwd: "C:/test",
|
|
165
|
+
root: "C:/test",
|
|
166
|
+
isVerbose: false,
|
|
167
|
+
workspace: {
|
|
168
|
+
projects: {
|
|
169
|
+
"test-app": {
|
|
170
|
+
root: "apps/test-app",
|
|
171
|
+
projectType: "application",
|
|
172
|
+
},
|
|
173
|
+
"test-lib": {
|
|
174
|
+
root: "libs/test-lib",
|
|
175
|
+
projectType: "library",
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
version: 2,
|
|
179
|
+
},
|
|
180
|
+
projectName,
|
|
181
|
+
targetName,
|
|
182
|
+
};
|
|
183
|
+
}
|