@itssky/nx-sonar 1.0.0

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.
Files changed (46) hide show
  1. package/README.md +156 -0
  2. package/executors.json +9 -0
  3. package/generators.json +14 -0
  4. package/package.json +40 -0
  5. package/src/executors/scan/executor.d.ts +5 -0
  6. package/src/executors/scan/executor.js +48 -0
  7. package/src/executors/scan/executor.js.map +1 -0
  8. package/src/executors/scan/schema.d.ts +1 -0
  9. package/src/executors/scan/schema.json +41 -0
  10. package/src/generators/configuration/generator.d.ts +4 -0
  11. package/src/generators/configuration/generator.js +44 -0
  12. package/src/generators/configuration/generator.js.map +1 -0
  13. package/src/generators/configuration/schema.d.ts +5 -0
  14. package/src/generators/configuration/schema.json +27 -0
  15. package/src/generators/init/generator.d.ts +4 -0
  16. package/src/generators/init/generator.js +64 -0
  17. package/src/generators/init/generator.js.map +1 -0
  18. package/src/generators/init/schema.d.ts +5 -0
  19. package/src/generators/init/schema.json +14 -0
  20. package/src/index.d.ts +0 -0
  21. package/src/index.js +1 -0
  22. package/src/index.js.map +1 -0
  23. package/src/utils/build-scanner-properties.d.ts +9 -0
  24. package/src/utils/build-scanner-properties.js +42 -0
  25. package/src/utils/build-scanner-properties.js.map +1 -0
  26. package/src/utils/detect-ci-context.d.ts +4 -0
  27. package/src/utils/detect-ci-context.js +87 -0
  28. package/src/utils/detect-ci-context.js.map +1 -0
  29. package/src/utils/detect-test-runner.d.ts +3 -0
  30. package/src/utils/detect-test-runner.js +15 -0
  31. package/src/utils/detect-test-runner.js.map +1 -0
  32. package/src/utils/errors.d.ts +14 -0
  33. package/src/utils/errors.js +43 -0
  34. package/src/utils/errors.js.map +1 -0
  35. package/src/utils/resolve-options.d.ts +7 -0
  36. package/src/utils/resolve-options.js +52 -0
  37. package/src/utils/resolve-options.js.map +1 -0
  38. package/src/utils/resolve-project-paths.d.ts +13 -0
  39. package/src/utils/resolve-project-paths.js +26 -0
  40. package/src/utils/resolve-project-paths.js.map +1 -0
  41. package/src/utils/run-scanner.d.ts +5 -0
  42. package/src/utils/run-scanner.js +36 -0
  43. package/src/utils/run-scanner.js.map +1 -0
  44. package/src/utils/types.d.ts +52 -0
  45. package/src/utils/types.js +13 -0
  46. package/src/utils/types.js.map +1 -0
package/README.md ADDED
@@ -0,0 +1,156 @@
1
+ # @itssky/nx-sonar
2
+
3
+ > Turnkey nx plugin for SonarQube and SonarCloud scans.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@itssky/nx-sonar.svg)](https://www.npmjs.com/package/@itssky/nx-sonar)
6
+ [![CI](https://github.com/xItsSky/nx-sonar/actions/workflows/ci.yml/badge.svg)](https://github.com/xItsSky/nx-sonar/actions/workflows/ci.yml)
7
+ [![codecov](https://codecov.io/gh/xItsSky/nx-sonar/branch/main/graph/badge.svg)](https://codecov.io/gh/xItsSky/nx-sonar)
8
+ [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](../../LICENSE)
9
+
10
+ ## What it does
11
+
12
+ `@itssky/nx-sonar` adds a `sonar` target to any nx project. The target runs
13
+ your tests with coverage (via `dependsOn: ["test"]`), then invokes the official
14
+ Sonar scanner — the binary is downloaded on first use, no separate install.
15
+
16
+ Works with **SonarQube** and **SonarCloud**, and with any test runner that
17
+ emits LCOV (jest, vitest, …).
18
+
19
+ ## Install
20
+
21
+ ```bash
22
+ npm install --save-dev @itssky/nx-sonar
23
+ ```
24
+
25
+ ## Quickstart
26
+
27
+ ```bash
28
+ # 1. Configure the workspace
29
+ npx nx g @itssky/nx-sonar:init --hostUrl=https://sonarcloud.io --organization=my-org
30
+
31
+ # 2. Add a sonar target to a project
32
+ npx nx g @itssky/nx-sonar:configuration --project=my-app --projectKey=org_my-app
33
+
34
+ # 3. Run a scan (tests run first via dependsOn)
35
+ export SONAR_TOKEN=<your-token>
36
+ npx nx run my-app:sonar
37
+
38
+ # Or scan everything that's affected by your last change:
39
+ npx nx affected -t sonar
40
+ ```
41
+
42
+ ## Configuration
43
+
44
+ Options can live in three places (each later layer overrides the previous):
45
+
46
+ ```
47
+ project.json target options > nx.json -> nxSonar > environment variables > built-in default
48
+ ```
49
+
50
+ The `token` is **always** read from `SONAR_TOKEN` — never from `nx.json` or
51
+ `project.json`. The plugin refuses to start if a token is found in a
52
+ committed file.
53
+
54
+ ### Executor options
55
+
56
+ | Option | Type | Default | Description |
57
+ |---|---|---|---|
58
+ | `projectKey` | string | required | Sonar project key |
59
+ | `projectName` | string | nx project name | Display name in Sonar |
60
+ | `projectVersion` | string | from `package.json` | |
61
+ | `hostUrl` | string | `https://sonarcloud.io` | Sonar server URL |
62
+ | `organization` | string | — | SonarCloud organization |
63
+ | `sources` | string \| string[] | project root | |
64
+ | `tests` | string \| string[] | unset | Optional `sonar.tests` value |
65
+ | `exclusions` | string[] | sensible defaults | Merged with workspace defaults |
66
+ | `coverageLcovPath` | string | `coverage/<projectRoot>/lcov.info` | LCOV report path |
67
+ | `testExecutionReportPath` | string | unset | JUnit XML test report (existence checked) |
68
+ | `qualityGateWait` | boolean | `true` | Fail the build if the Quality Gate fails |
69
+ | `branchDetection` | boolean | `true` | Auto-detect branch/PR from CI env vars |
70
+ | `extraProperties` | `Record<string,string>` | `{}` | Raw `sonar.*` properties (overrides built-ins) |
71
+ | `verbose` | boolean | `false` | Pass `-X` to the scanner |
72
+
73
+ ### Environment variables
74
+
75
+ | Env var | Purpose |
76
+ |---|---|
77
+ | `SONAR_TOKEN` | **Required.** Authentication token. |
78
+ | `SONAR_HOST_URL` | Default `hostUrl` if not set in config. |
79
+ | `SONAR_ORGANIZATION` | Default `organization` if not set in config. |
80
+ | `SONAR_PROJECT_KEY` | Default `projectKey` if not set in config. |
81
+
82
+ ### Workspace defaults
83
+
84
+ The `init` generator writes defaults under `nx.json` → `nxSonar`:
85
+
86
+ ```json
87
+ {
88
+ "nxSonar": {
89
+ "hostUrl": "https://sonarcloud.io",
90
+ "organization": "my-org",
91
+ "exclusions": ["**/legacy/**"]
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## CI recipes
97
+
98
+ ### GitHub Actions
99
+
100
+ ```yaml
101
+ - uses: actions/checkout@v4
102
+ with:
103
+ fetch-depth: 0 # required for Sonar branch analysis
104
+ - uses: actions/setup-node@v4
105
+ with:
106
+ node-version: 20
107
+ - run: npm ci
108
+ - run: npx nx affected -t sonar
109
+ env:
110
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
111
+ ```
112
+
113
+ ### GitLab CI
114
+
115
+ ```yaml
116
+ sonar:
117
+ image: node:20
118
+ script:
119
+ - npm ci
120
+ - npx nx affected -t sonar
121
+ variables:
122
+ SONAR_TOKEN: $SONAR_TOKEN
123
+ ```
124
+
125
+ Branch and merge-request context are auto-detected on GitHub Actions, GitLab
126
+ CI, CircleCI, and Bitbucket Pipelines.
127
+
128
+ ## Troubleshooting
129
+
130
+ **`SONAR_TOKEN is not set`** — generate a token in your Sonar server and export
131
+ it before running. In CI, configure it as a secret.
132
+
133
+ **`Coverage report not found at coverage/<...>/lcov.info`** — enable LCOV in
134
+ your test runner:
135
+ - jest: `"coverageReporters": ["lcov"]` in `jest.config.ts`
136
+ - vitest: `"test.coverage.reporter": ["lcov"]` in `vite.config.ts`
137
+
138
+ **`A "token" was found in nx.json`** — remove it. Tokens belong in
139
+ `SONAR_TOKEN` only.
140
+
141
+ **Quality Gate failed but I don't want to block the build** — set
142
+ `qualityGateWait: false` in the target options.
143
+
144
+ ## Migrating from `@koliveira15/nx-sonarqube`
145
+
146
+ | Old | New |
147
+ |---|---|
148
+ | executor name `@koliveira15/nx-sonarqube:scan` | `@itssky/nx-sonar:scan` |
149
+ | `hostUrl` (option) | same, also reads from `SONAR_HOST_URL` |
150
+ | `qualityGate` (option) | renamed to `qualityGateWait` |
151
+ | Token in options | refused — use `SONAR_TOKEN` env |
152
+ | Manual coverage merge step | not needed (per-project LCOV) |
153
+
154
+ ## License
155
+
156
+ [MIT](../../LICENSE) © Quentin (xItsSky)
package/executors.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "executors": {
3
+ "scan": {
4
+ "implementation": "./src/executors/scan/executor",
5
+ "schema": "./src/executors/scan/schema.json",
6
+ "description": "Run a SonarQube/SonarCloud scan on the project."
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "generators": {
3
+ "init": {
4
+ "factory": "./src/generators/init/generator",
5
+ "schema": "./src/generators/init/schema.json",
6
+ "description": "Configure @itssky/nx-sonar in the workspace."
7
+ },
8
+ "configuration": {
9
+ "factory": "./src/generators/configuration/generator",
10
+ "schema": "./src/generators/configuration/schema.json",
11
+ "description": "Add a sonar target to a project."
12
+ }
13
+ }
14
+ }
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@itssky/nx-sonar",
3
+ "version": "1.0.0",
4
+ "description": "Turnkey nx plugin that runs SonarQube/SonarCloud scans on nx projects.",
5
+ "keywords": [
6
+ "nx",
7
+ "nx-plugin",
8
+ "sonar",
9
+ "sonarqube",
10
+ "sonarcloud",
11
+ "code-quality"
12
+ ],
13
+ "homepage": "https://github.com/xItsSky/nx-sonar#readme",
14
+ "bugs": "https://github.com/xItsSky/nx-sonar/issues",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/xItsSky/nx-sonar.git",
18
+ "directory": "nx-sonar"
19
+ },
20
+ "license": "MIT",
21
+ "author": "Quentin (xItsSky)",
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "type": "commonjs",
26
+ "main": "./src/index.js",
27
+ "types": "./src/index.d.ts",
28
+ "engines": {
29
+ "node": ">=20.0.0"
30
+ },
31
+ "peerDependencies": {
32
+ "@nx/devkit": ">=22.0.0"
33
+ },
34
+ "dependencies": {
35
+ "sonarqube-scanner": "^4.3.6",
36
+ "tslib": "^2.3.0"
37
+ },
38
+ "executors": "./executors.json",
39
+ "generators": "./generators.json"
40
+ }
@@ -0,0 +1,5 @@
1
+ import type { ExecutorContext } from '@nx/devkit';
2
+ import type { ScanExecutorOptions } from '../../utils/types';
3
+ export default function scanExecutor(options: ScanExecutorOptions, context: ExecutorContext): Promise<{
4
+ success: boolean;
5
+ }>;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = scanExecutor;
4
+ const tslib_1 = require("tslib");
5
+ const build_scanner_properties_1 = require("../../utils/build-scanner-properties");
6
+ const detect_ci_context_1 = require("../../utils/detect-ci-context");
7
+ const errors_1 = require("../../utils/errors");
8
+ const resolve_options_1 = require("../../utils/resolve-options");
9
+ const resolve_project_paths_1 = require("../../utils/resolve-project-paths");
10
+ const run_scanner_1 = require("../../utils/run-scanner");
11
+ function scanExecutor(options, context) {
12
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
13
+ var _a, _b, _c, _d, _e;
14
+ try {
15
+ const projectConfig = (_b = (_a = context.projectsConfigurations) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b[(_c = context.projectName) !== null && _c !== void 0 ? _c : ''];
16
+ if (!projectConfig) {
17
+ throw new errors_1.NxSonarError(`Cannot resolve project config for "${context.projectName}".`);
18
+ }
19
+ const nxJsonConfig = ((_e = (_d = context.nxJsonConfiguration) === null || _d === void 0 ? void 0 : _d.nxSonar) !== null && _e !== void 0 ? _e : {});
20
+ const resolved = (0, resolve_options_1.resolveOptions)({
21
+ projectOptions: options,
22
+ nxJsonConfig,
23
+ env: process.env,
24
+ });
25
+ const paths = (0, resolve_project_paths_1.resolveProjectPaths)({
26
+ workspaceRoot: context.root,
27
+ projectRoot: projectConfig.root,
28
+ options,
29
+ });
30
+ const ciContext = (0, detect_ci_context_1.detectCiContext)(process.env);
31
+ const properties = (0, build_scanner_properties_1.buildScannerProperties)({
32
+ options: resolved,
33
+ paths,
34
+ ciContext,
35
+ });
36
+ const result = yield (0, run_scanner_1.runScanner)(properties);
37
+ return { success: result.success };
38
+ }
39
+ catch (err) {
40
+ if (err instanceof errors_1.NxSonarError) {
41
+ console.error(`[@itssky/nx-sonar] ${err.message}`);
42
+ return { success: false };
43
+ }
44
+ throw err;
45
+ }
46
+ });
47
+ }
48
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../nx-sonar/src/executors/scan/executor.ts"],"names":[],"mappings":";;AAYA,+BA8CC;;AAzDD,mFAA8E;AAC9E,qEAAgE;AAChE,+CAAkD;AAClD,iEAA6D;AAC7D,6EAAwE;AACxE,yDAAqD;AAMrD,SAA8B,YAAY,CACxC,OAA4B,EAC5B,OAAwB;;;QAExB,IAAI,CAAC;YACH,MAAM,aAAa,GACjB,MAAA,MAAA,OAAO,CAAC,sBAAsB,0CAAE,QAAQ,0CAAG,MAAA,OAAO,CAAC,WAAW,mCAAI,EAAE,CAAC,CAAC;YACxE,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,MAAM,IAAI,qBAAY,CACpB,sCAAsC,OAAO,CAAC,WAAW,IAAI,CAC9D,CAAC;YACJ,CAAC;YAED,MAAM,YAAY,GAChB,CAAC,MAAA,MAAC,OAAO,CAAC,mBAAuD,0CAC7D,OAAO,mCAAI,EAAE,CAAsB,CAAC;YAE1C,MAAM,QAAQ,GAAG,IAAA,gCAAc,EAAC;gBAC9B,cAAc,EAAE,OAAO;gBACvB,YAAY;gBACZ,GAAG,EAAE,OAAO,CAAC,GAAG;aACjB,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG,IAAA,2CAAmB,EAAC;gBAChC,aAAa,EAAE,OAAO,CAAC,IAAI;gBAC3B,WAAW,EAAE,aAAa,CAAC,IAAI;gBAC/B,OAAO;aACR,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,IAAA,mCAAe,EAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAE/C,MAAM,UAAU,GAAG,IAAA,iDAAsB,EAAC;gBACxC,OAAO,EAAE,QAAQ;gBACjB,KAAK;gBACL,SAAS;aACV,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,IAAA,wBAAU,EAAC,UAAU,CAAC,CAAC;YAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,qBAAY,EAAE,CAAC;gBAChC,OAAO,CAAC,KAAK,CAAC,sBAAsB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBACnD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAC5B,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;CAAA"}
@@ -0,0 +1 @@
1
+ export type { ScanExecutorOptions as Schema } from '../../utils/types';
@@ -0,0 +1,41 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "$id": "NxSonarScanExecutor",
4
+ "title": "@itssky/nx-sonar:scan",
5
+ "description": "Run a SonarQube/SonarCloud scan against the project.",
6
+ "type": "object",
7
+ "properties": {
8
+ "projectKey": { "type": "string", "description": "Sonar project key." },
9
+ "projectName": { "type": "string", "description": "Display name in Sonar." },
10
+ "projectVersion": { "type": "string" },
11
+ "hostUrl": { "type": "string", "format": "uri" },
12
+ "organization": { "type": "string", "description": "SonarCloud organization." },
13
+ "sources": {
14
+ "oneOf": [
15
+ { "type": "string" },
16
+ { "type": "array", "items": { "type": "string" } }
17
+ ]
18
+ },
19
+ "tests": {
20
+ "oneOf": [
21
+ { "type": "string" },
22
+ { "type": "array", "items": { "type": "string" } }
23
+ ]
24
+ },
25
+ "exclusions": {
26
+ "type": "array",
27
+ "items": { "type": "string" }
28
+ },
29
+ "coverageLcovPath": { "type": "string" },
30
+ "testExecutionReportPath": { "type": "string" },
31
+ "qualityGateWait": { "type": "boolean", "default": true },
32
+ "branchDetection": { "type": "boolean", "default": true },
33
+ "extraProperties": {
34
+ "type": "object",
35
+ "additionalProperties": { "type": "string" }
36
+ },
37
+ "verbose": { "type": "boolean", "default": false }
38
+ },
39
+ "required": [],
40
+ "additionalProperties": false
41
+ }
@@ -0,0 +1,4 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ import { ConfigurationGeneratorSchema } from './schema';
3
+ export declare function configurationGenerator(tree: Tree, options: ConfigurationGeneratorSchema): Promise<void>;
4
+ export default configurationGenerator;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configurationGenerator = configurationGenerator;
4
+ const tslib_1 = require("tslib");
5
+ const devkit_1 = require("@nx/devkit");
6
+ const detect_test_runner_1 = require("../../utils/detect-test-runner");
7
+ const EXECUTOR = '@itssky/nx-sonar:scan';
8
+ function configurationGenerator(tree, options) {
9
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
10
+ var _a, _b;
11
+ const project = (0, devkit_1.readProjectConfiguration)(tree, options.project);
12
+ if (((_a = project.targets) === null || _a === void 0 ? void 0 : _a.sonar) && !options.force) {
13
+ throw new Error(`Project "${options.project}" already exists with a sonar target. Re-run with --force to overwrite.`);
14
+ }
15
+ const runner = (0, detect_test_runner_1.detectTestRunner)(project);
16
+ if (runner === 'none') {
17
+ console.warn(`[@itssky/nx-sonar] Project "${options.project}" has no \`test\` target. The sonar target will still be added with dependsOn:["test"], but it will fail until you configure tests with coverage.`);
18
+ }
19
+ else {
20
+ warnIfCoverageNotConfigured(runner, project);
21
+ }
22
+ const sonarTarget = {
23
+ executor: EXECUTOR,
24
+ dependsOn: ['test'],
25
+ options: Object.assign(Object.assign({}, (options.projectKey ? { projectKey: options.projectKey } : {})), { projectName: options.project }),
26
+ };
27
+ project.targets = Object.assign(Object.assign({}, ((_b = project.targets) !== null && _b !== void 0 ? _b : {})), { sonar: sonarTarget });
28
+ (0, devkit_1.updateProjectConfiguration)(tree, options.project, project);
29
+ yield (0, devkit_1.formatFiles)(tree);
30
+ });
31
+ }
32
+ function warnIfCoverageNotConfigured(runner, project) {
33
+ var _a, _b, _c;
34
+ const opts = (_c = (_b = (_a = project.targets) === null || _a === void 0 ? void 0 : _a.test) === null || _b === void 0 ? void 0 : _b.options) !== null && _c !== void 0 ? _c : {};
35
+ const hasCoverage = 'coverage' in opts ||
36
+ 'codeCoverage' in opts ||
37
+ 'collectCoverage' in opts;
38
+ if (!hasCoverage) {
39
+ console.warn(`[@itssky/nx-sonar] The "test" target does not appear to enable coverage. ` +
40
+ `For ${runner}, enable coverage so an lcov.info file is produced at coverage/<projectRoot>/lcov.info.`);
41
+ }
42
+ }
43
+ exports.default = configurationGenerator;
44
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../nx-sonar/src/generators/configuration/generator.ts"],"names":[],"mappings":";;AAWA,wDAoCC;;AA/CD,uCAKoB;AACpB,uEAAkE;AAGlE,MAAM,QAAQ,GAAG,uBAAuB,CAAC;AAEzC,SAAsB,sBAAsB,CAC1C,IAAU,EACV,OAAqC;;;QAErC,MAAM,OAAO,GAAG,IAAA,iCAAwB,EAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAEhE,IAAI,CAAA,MAAA,OAAO,CAAC,OAAO,0CAAE,KAAK,KAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC7C,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,CAAC,OAAO,yEAAyE,CACrG,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,IAAA,qCAAgB,EAAC,OAAO,CAAC,CAAC;QACzC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CACV,+BAA+B,OAAO,CAAC,OAAO,mJAAmJ,CAClM,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,2BAA2B,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,WAAW,GAAG;YAClB,QAAQ,EAAE,QAAQ;YAClB,SAAS,EAAE,CAAC,MAAM,CAAC;YACnB,OAAO,kCACF,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KACjE,WAAW,EAAE,OAAO,CAAC,OAAO,GAC7B;SACF,CAAC;QAEF,OAAO,CAAC,OAAO,mCACV,CAAC,MAAA,OAAO,CAAC,OAAO,mCAAI,EAAE,CAAC,KAC1B,KAAK,EAAE,WAAW,GACnB,CAAC;QACF,IAAA,mCAA0B,EAAC,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3D,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CAAA;AAED,SAAS,2BAA2B,CAClC,MAAmC,EACnC,OAA4E;;IAE5E,MAAM,IAAI,GAAG,MAAA,MAAA,MAAA,OAAO,CAAC,OAAO,0CAAE,IAAI,0CAAE,OAAO,mCAAI,EAAE,CAAC;IAClD,MAAM,WAAW,GACf,UAAU,IAAI,IAAI;QAClB,cAAc,IAAI,IAAI;QACtB,iBAAiB,IAAI,IAAI,CAAC;IAC5B,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CACV,2EAA2E;YACzE,OAAO,MAAM,yFAAyF,CACzG,CAAC;IACJ,CAAC;AACH,CAAC;AAED,kBAAe,sBAAsB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export interface ConfigurationGeneratorSchema {
2
+ project: string;
3
+ projectKey?: string;
4
+ force?: boolean;
5
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "$id": "NxSonarConfigurationGenerator",
4
+ "title": "@itssky/nx-sonar:configuration",
5
+ "description": "Add a sonar target to a project.",
6
+ "type": "object",
7
+ "properties": {
8
+ "project": {
9
+ "type": "string",
10
+ "description": "Project to configure.",
11
+ "$default": { "$source": "projectName" },
12
+ "x-prompt": "Which project should be configured for Sonar?"
13
+ },
14
+ "projectKey": {
15
+ "type": "string",
16
+ "description": "Sonar project key.",
17
+ "x-prompt": "Sonar projectKey (leave blank to set later in project.json):"
18
+ },
19
+ "force": {
20
+ "type": "boolean",
21
+ "default": false,
22
+ "description": "Overwrite an existing sonar target."
23
+ }
24
+ },
25
+ "required": ["project"],
26
+ "additionalProperties": false
27
+ }
@@ -0,0 +1,4 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ import { InitGeneratorSchema } from './schema';
3
+ export declare function initGenerator(tree: Tree, options: InitGeneratorSchema): Promise<void>;
4
+ export default initGenerator;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initGenerator = initGenerator;
4
+ const tslib_1 = require("tslib");
5
+ const devkit_1 = require("@nx/devkit");
6
+ const PLUGIN_NAME = '@itssky/nx-sonar';
7
+ const ENV_LINES = [
8
+ '# @itssky/nx-sonar — required for `nx run <project>:sonar`',
9
+ 'SONAR_TOKEN=',
10
+ 'SONAR_HOST_URL=',
11
+ 'SONAR_ORGANIZATION=',
12
+ ];
13
+ function initGenerator(tree, options) {
14
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
15
+ registerPluginInNxJson(tree, options);
16
+ ensureGitignoreCoverage(tree);
17
+ appendEnvExampleIfPresent(tree);
18
+ yield (0, devkit_1.formatFiles)(tree);
19
+ });
20
+ }
21
+ function registerPluginInNxJson(tree, options) {
22
+ var _a, _b, _c;
23
+ const nxJson = ((_a = (0, devkit_1.readNxJson)(tree)) !== null && _a !== void 0 ? _a : {});
24
+ const plugins = (_b = nxJson.plugins) !== null && _b !== void 0 ? _b : [];
25
+ const alreadyHasPlugin = plugins.some((p) => typeof p === 'string' ? p === PLUGIN_NAME : (p === null || p === void 0 ? void 0 : p.plugin) === PLUGIN_NAME);
26
+ if (!alreadyHasPlugin) {
27
+ plugins.push({ plugin: PLUGIN_NAME });
28
+ }
29
+ nxJson.plugins = plugins;
30
+ const sonarDefaults = Object.assign({}, ((_c = nxJson.nxSonar) !== null && _c !== void 0 ? _c : {}));
31
+ if (options.hostUrl)
32
+ sonarDefaults.hostUrl = options.hostUrl;
33
+ if (options.organization)
34
+ sonarDefaults.organization = options.organization;
35
+ if (Object.keys(sonarDefaults).length > 0) {
36
+ nxJson.nxSonar = sonarDefaults;
37
+ }
38
+ (0, devkit_1.updateNxJson)(tree, nxJson);
39
+ }
40
+ function ensureGitignoreCoverage(tree) {
41
+ var _a;
42
+ const path = '.gitignore';
43
+ const existing = tree.exists(path) ? (_a = tree.read(path, 'utf-8')) !== null && _a !== void 0 ? _a : '' : '';
44
+ const lines = existing.split('\n');
45
+ if (!lines.some((l) => l.trim() === 'coverage/')) {
46
+ const updated = existing.length === 0 || existing.endsWith('\n')
47
+ ? `${existing}coverage/\n`
48
+ : `${existing}\ncoverage/\n`;
49
+ tree.write(path, updated);
50
+ }
51
+ }
52
+ function appendEnvExampleIfPresent(tree) {
53
+ var _a;
54
+ const path = '.env.example';
55
+ if (!tree.exists(path))
56
+ return;
57
+ const existing = (_a = tree.read(path, 'utf-8')) !== null && _a !== void 0 ? _a : '';
58
+ if (existing.includes('SONAR_TOKEN='))
59
+ return;
60
+ const sep = existing.endsWith('\n') ? '' : '\n';
61
+ tree.write(path, `${existing}${sep}${ENV_LINES.join('\n')}\n`);
62
+ }
63
+ exports.default = initGenerator;
64
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../nx-sonar/src/generators/init/generator.ts"],"names":[],"mappings":";;AAgBA,sCAQC;;AAxBD,uCAKoB;AAGpB,MAAM,WAAW,GAAG,kBAAkB,CAAC;AACvC,MAAM,SAAS,GAAG;IAChB,4DAA4D;IAC5D,cAAc;IACd,iBAAiB;IACjB,qBAAqB;CACtB,CAAC;AAEF,SAAsB,aAAa,CACjC,IAAU,EACV,OAA4B;;QAE5B,sBAAsB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACtC,uBAAuB,CAAC,IAAI,CAAC,CAAC;QAC9B,yBAAyB,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CAAA;AAED,SAAS,sBAAsB,CAC7B,IAAU,EACV,OAA4B;;IAE5B,MAAM,MAAM,GAAG,CAAC,MAAA,IAAA,mBAAU,EAAC,IAAI,CAAC,mCAAI,EAAE,CAGrC,CAAC;IAEF,MAAM,OAAO,GAAG,MAAA,MAAM,CAAC,OAAO,mCAAI,EAAE,CAAC;IACrC,MAAM,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC1C,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAA,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,MAAM,MAAK,WAAW,CACtE,CAAC;IACF,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACxC,CAAC;IACD,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IAEzB,MAAM,aAAa,qBACd,CAAC,MAAA,MAAM,CAAC,OAAO,mCAAI,EAAE,CAAC,CAC1B,CAAC;IACF,IAAI,OAAO,CAAC,OAAO;QAAE,aAAa,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAC7D,IAAI,OAAO,CAAC,YAAY;QAAE,aAAa,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAC5E,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,CAAC,OAAO,GAAG,aAAa,CAAC;IACjC,CAAC;IAED,IAAA,qBAAY,EAAC,IAAI,EAAE,MAAe,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAU;;IACzC,MAAM,IAAI,GAAG,YAAY,CAAC;IAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,mCAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACzE,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,WAAW,CAAC,EAAE,CAAC;QACjD,MAAM,OAAO,GACX,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;YAC9C,CAAC,CAAC,GAAG,QAAQ,aAAa;YAC1B,CAAC,CAAC,GAAG,QAAQ,eAAe,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,SAAS,yBAAyB,CAAC,IAAU;;IAC3C,MAAM,IAAI,GAAG,cAAc,CAAC;IAC5B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;QAAE,OAAO;IAC/B,MAAM,QAAQ,GAAG,MAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,mCAAI,EAAE,CAAC;IAChD,IAAI,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC;QAAE,OAAO;IAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,QAAQ,GAAG,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjE,CAAC;AAED,kBAAe,aAAa,CAAC"}
@@ -0,0 +1,5 @@
1
+ export interface InitGeneratorSchema {
2
+ hostUrl?: string;
3
+ organization?: string;
4
+ skipPrompts?: boolean;
5
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "$id": "NxSonarInitGenerator",
4
+ "title": "@itssky/nx-sonar:init",
5
+ "description": "Configure @itssky/nx-sonar in the workspace.",
6
+ "type": "object",
7
+ "properties": {
8
+ "hostUrl": { "type": "string", "format": "uri" },
9
+ "organization": { "type": "string" },
10
+ "skipPrompts": { "type": "boolean", "default": false }
11
+ },
12
+ "required": [],
13
+ "additionalProperties": false
14
+ }
package/src/index.d.ts ADDED
File without changes
package/src/index.js ADDED
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../nx-sonar/src/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import { CiContext, ResolvedOptions } from './types';
2
+ import { ResolvedPaths } from './resolve-project-paths';
3
+ export interface BuildPropsInput {
4
+ options: ResolvedOptions;
5
+ paths: ResolvedPaths;
6
+ ciContext: CiContext;
7
+ }
8
+ export type ScannerProperties = Record<string, string>;
9
+ export declare function buildScannerProperties({ options, paths, ciContext, }: BuildPropsInput): ScannerProperties;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildScannerProperties = buildScannerProperties;
4
+ function buildScannerProperties({ options, paths, ciContext, }) {
5
+ const props = {};
6
+ props['sonar.projectKey'] = options.projectKey;
7
+ if (options.projectName)
8
+ props['sonar.projectName'] = options.projectName;
9
+ if (options.projectVersion)
10
+ props['sonar.projectVersion'] = options.projectVersion;
11
+ props['sonar.host.url'] = options.hostUrl;
12
+ if (options.organization)
13
+ props['sonar.organization'] = options.organization;
14
+ props['sonar.token'] = options.token;
15
+ props['sonar.sources'] = joinList(paths.sources);
16
+ if (paths.tests)
17
+ props['sonar.tests'] = joinList(paths.tests);
18
+ props['sonar.javascript.lcov.reportPaths'] = paths.coveragePath;
19
+ props['sonar.typescript.lcov.reportPaths'] = paths.coveragePath;
20
+ if (paths.testExecutionReportPath)
21
+ props['sonar.testExecutionReportPaths'] = paths.testExecutionReportPath;
22
+ props['sonar.exclusions'] = options.exclusions.join(',');
23
+ props['sonar.qualitygate.wait'] = String(options.qualityGateWait);
24
+ if (options.verbose)
25
+ props['sonar.verbose'] = 'true';
26
+ if (options.branchDetection && ciContext) {
27
+ if (ciContext.kind === 'branch') {
28
+ props['sonar.branch.name'] = ciContext.name;
29
+ }
30
+ else {
31
+ props['sonar.pullrequest.key'] = ciContext.key;
32
+ props['sonar.pullrequest.branch'] = ciContext.branch;
33
+ props['sonar.pullrequest.base'] = ciContext.base;
34
+ }
35
+ }
36
+ // extraProperties last so users can override anything above.
37
+ return Object.assign(Object.assign({}, props), options.extraProperties);
38
+ }
39
+ function joinList(value) {
40
+ return Array.isArray(value) ? value.join(',') : value;
41
+ }
42
+ //# sourceMappingURL=build-scanner-properties.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-scanner-properties.js","sourceRoot":"","sources":["../../../../nx-sonar/src/utils/build-scanner-properties.ts"],"names":[],"mappings":";;AAWA,wDAwCC;AAxCD,SAAgB,sBAAsB,CAAC,EACrC,OAAO,EACP,KAAK,EACL,SAAS,GACO;IAChB,MAAM,KAAK,GAAsB,EAAE,CAAC;IAEpC,KAAK,CAAC,kBAAkB,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IAC/C,IAAI,OAAO,CAAC,WAAW;QAAE,KAAK,CAAC,mBAAmB,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAC1E,IAAI,OAAO,CAAC,cAAc;QACxB,KAAK,CAAC,sBAAsB,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC;IAEzD,KAAK,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAC1C,IAAI,OAAO,CAAC,YAAY;QAAE,KAAK,CAAC,oBAAoB,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;IAC7E,KAAK,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;IAErC,KAAK,CAAC,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,KAAK,CAAC,KAAK;QAAE,KAAK,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAE9D,KAAK,CAAC,mCAAmC,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC;IAChE,KAAK,CAAC,mCAAmC,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC;IAChE,IAAI,KAAK,CAAC,uBAAuB;QAC/B,KAAK,CAAC,gCAAgC,CAAC,GAAG,KAAK,CAAC,uBAAuB,CAAC;IAE1E,KAAK,CAAC,kBAAkB,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzD,KAAK,CAAC,wBAAwB,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAClE,IAAI,OAAO,CAAC,OAAO;QAAE,KAAK,CAAC,eAAe,CAAC,GAAG,MAAM,CAAC;IAErD,IAAI,OAAO,CAAC,eAAe,IAAI,SAAS,EAAE,CAAC;QACzC,IAAI,SAAS,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAChC,KAAK,CAAC,mBAAmB,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,uBAAuB,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC;YAC/C,KAAK,CAAC,0BAA0B,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC;YACrD,KAAK,CAAC,wBAAwB,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC;QACnD,CAAC;IACH,CAAC;IAED,6DAA6D;IAC7D,uCAAY,KAAK,GAAK,OAAO,CAAC,eAAe,EAAG;AAClD,CAAC;AAED,SAAS,QAAQ,CAAC,KAAwB;IACxC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACxD,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { CiContext } from './types';
2
+ type Env = Record<string, string | undefined>;
3
+ export declare function detectCiContext(env: Env): CiContext;
4
+ export {};
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectCiContext = detectCiContext;
4
+ function detectCiContext(env) {
5
+ var _a, _b, _c, _d;
6
+ return ((_d = (_c = (_b = (_a = detectGitHubActions(env)) !== null && _a !== void 0 ? _a : detectGitLab(env)) !== null && _b !== void 0 ? _b : detectCircleCi(env)) !== null && _c !== void 0 ? _c : detectBitbucket(env)) !== null && _d !== void 0 ? _d : null);
7
+ }
8
+ function detectGitHubActions(env) {
9
+ var _a, _b, _c;
10
+ if (env.GITHUB_ACTIONS !== 'true')
11
+ return null;
12
+ if (env.GITHUB_EVENT_NAME === 'pull_request' ||
13
+ env.GITHUB_EVENT_NAME === 'pull_request_target') {
14
+ const key = parsePrFromRef(env.GITHUB_REF);
15
+ return key
16
+ ? {
17
+ kind: 'pullRequest',
18
+ key,
19
+ branch: (_a = env.GITHUB_HEAD_REF) !== null && _a !== void 0 ? _a : '',
20
+ base: (_b = env.GITHUB_BASE_REF) !== null && _b !== void 0 ? _b : 'main',
21
+ }
22
+ : null;
23
+ }
24
+ if ((_c = env.GITHUB_REF) === null || _c === void 0 ? void 0 : _c.startsWith('refs/heads/')) {
25
+ return { kind: 'branch', name: env.GITHUB_REF.slice('refs/heads/'.length) };
26
+ }
27
+ return null;
28
+ }
29
+ function detectGitLab(env) {
30
+ var _a, _b;
31
+ if (env.GITLAB_CI !== 'true')
32
+ return null;
33
+ if (env.CI_MERGE_REQUEST_IID) {
34
+ return {
35
+ kind: 'pullRequest',
36
+ key: env.CI_MERGE_REQUEST_IID,
37
+ branch: (_a = env.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME) !== null && _a !== void 0 ? _a : '',
38
+ base: (_b = env.CI_MERGE_REQUEST_TARGET_BRANCH_NAME) !== null && _b !== void 0 ? _b : 'main',
39
+ };
40
+ }
41
+ if (env.CI_COMMIT_BRANCH) {
42
+ return { kind: 'branch', name: env.CI_COMMIT_BRANCH };
43
+ }
44
+ return null;
45
+ }
46
+ function detectCircleCi(env) {
47
+ var _a;
48
+ if (env.CIRCLECI !== 'true')
49
+ return null;
50
+ if (env.CIRCLE_PULL_REQUEST) {
51
+ const key = env.CIRCLE_PULL_REQUEST.split('/').pop();
52
+ if (key) {
53
+ return {
54
+ kind: 'pullRequest',
55
+ key,
56
+ branch: (_a = env.CIRCLE_BRANCH) !== null && _a !== void 0 ? _a : '',
57
+ base: 'main',
58
+ };
59
+ }
60
+ }
61
+ if (env.CIRCLE_BRANCH) {
62
+ return { kind: 'branch', name: env.CIRCLE_BRANCH };
63
+ }
64
+ return null;
65
+ }
66
+ function detectBitbucket(env) {
67
+ var _a, _b;
68
+ if (!env.BITBUCKET_BUILD_NUMBER)
69
+ return null;
70
+ if (env.BITBUCKET_PR_ID) {
71
+ return {
72
+ kind: 'pullRequest',
73
+ key: env.BITBUCKET_PR_ID,
74
+ branch: (_a = env.BITBUCKET_BRANCH) !== null && _a !== void 0 ? _a : '',
75
+ base: (_b = env.BITBUCKET_PR_DESTINATION_BRANCH) !== null && _b !== void 0 ? _b : 'main',
76
+ };
77
+ }
78
+ if (env.BITBUCKET_BRANCH) {
79
+ return { kind: 'branch', name: env.BITBUCKET_BRANCH };
80
+ }
81
+ return null;
82
+ }
83
+ function parsePrFromRef(ref) {
84
+ const m = ref === null || ref === void 0 ? void 0 : ref.match(/^refs\/pull\/(\d+)\//);
85
+ return m ? m[1] : null;
86
+ }
87
+ //# sourceMappingURL=detect-ci-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-ci-context.js","sourceRoot":"","sources":["../../../../nx-sonar/src/utils/detect-ci-context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ProjectConfiguration } from '@nx/devkit';
2
+ export type TestRunner = 'jest' | 'vitest' | 'other' | 'none';
3
+ export declare function detectTestRunner(project: ProjectConfiguration): TestRunner;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectTestRunner = detectTestRunner;
4
+ function detectTestRunner(project) {
5
+ var _a, _b;
6
+ const executor = (_b = (_a = project.targets) === null || _a === void 0 ? void 0 : _a.test) === null || _b === void 0 ? void 0 : _b.executor;
7
+ if (!executor)
8
+ return 'none';
9
+ if (executor.includes('jest'))
10
+ return 'jest';
11
+ if (executor.includes('vite'))
12
+ return 'vitest';
13
+ return 'other';
14
+ }
15
+ //# sourceMappingURL=detect-test-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-test-runner.js","sourceRoot":"","sources":["../../../../nx-sonar/src/utils/detect-test-runner.ts"],"names":[],"mappings":";;AAIA,4CAMC;AAND,SAAgB,gBAAgB,CAAC,OAA6B;;IAC5D,MAAM,QAAQ,GAAG,MAAA,MAAA,OAAO,CAAC,OAAO,0CAAE,IAAI,0CAAE,QAAQ,CAAC;IACjD,IAAI,CAAC,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC7B,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAC7C,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC/C,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,14 @@
1
+ export declare class NxSonarError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export declare class MissingTokenError extends NxSonarError {
5
+ constructor();
6
+ }
7
+ export declare class MissingCoverageError extends NxSonarError {
8
+ constructor(path: string);
9
+ }
10
+ export declare class TokenInDiskConfigError extends NxSonarError {
11
+ constructor(source: string);
12
+ }
13
+ export declare class InvalidConfigError extends NxSonarError {
14
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InvalidConfigError = exports.TokenInDiskConfigError = exports.MissingCoverageError = exports.MissingTokenError = exports.NxSonarError = void 0;
4
+ class NxSonarError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = new.target.name;
8
+ Object.setPrototypeOf(this, new.target.prototype);
9
+ }
10
+ }
11
+ exports.NxSonarError = NxSonarError;
12
+ class MissingTokenError extends NxSonarError {
13
+ constructor() {
14
+ super('SONAR_TOKEN environment variable is not set. ' +
15
+ 'Generate a token in your Sonar server and export it before running the scan, e.g. ' +
16
+ '`export SONAR_TOKEN=...` locally or as a secret in CI.');
17
+ }
18
+ }
19
+ exports.MissingTokenError = MissingTokenError;
20
+ class MissingCoverageError extends NxSonarError {
21
+ constructor(path) {
22
+ super(`Coverage report not found at "${path}".\n` +
23
+ 'Make sure the test target emits LCOV:\n' +
24
+ ' - jest: add "coverageReporters": ["lcov"] in jest.config.ts\n' +
25
+ ' - vitest: add "test.coverage.reporter": ["lcov"] in vite.config.ts\n' +
26
+ 'Or pass `coverageLcovPath` in the sonar target options if your file lives elsewhere.');
27
+ }
28
+ }
29
+ exports.MissingCoverageError = MissingCoverageError;
30
+ class TokenInDiskConfigError extends NxSonarError {
31
+ constructor(source) {
32
+ super(`A "token" was found in ${source}. ` +
33
+ 'Tokens are secrets and must not be committed. ' +
34
+ 'Remove it from ' +
35
+ source +
36
+ ' and provide it via the SONAR_TOKEN environment variable instead.');
37
+ }
38
+ }
39
+ exports.TokenInDiskConfigError = TokenInDiskConfigError;
40
+ class InvalidConfigError extends NxSonarError {
41
+ }
42
+ exports.InvalidConfigError = InvalidConfigError;
43
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../../nx-sonar/src/utils/errors.ts"],"names":[],"mappings":";;;AAAA,MAAa,YAAa,SAAQ,KAAK;IACrC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAC5B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAND,oCAMC;AAED,MAAa,iBAAkB,SAAQ,YAAY;IACjD;QACE,KAAK,CACH,+CAA+C;YAC7C,oFAAoF;YACpF,wDAAwD,CAC3D,CAAC;IACJ,CAAC;CACF;AARD,8CAQC;AAED,MAAa,oBAAqB,SAAQ,YAAY;IACpD,YAAY,IAAY;QACtB,KAAK,CACH,iCAAiC,IAAI,MAAM;YACzC,yCAAyC;YACzC,iEAAiE;YACjE,wEAAwE;YACxE,sFAAsF,CACzF,CAAC;IACJ,CAAC;CACF;AAVD,oDAUC;AAED,MAAa,sBAAuB,SAAQ,YAAY;IACtD,YAAY,MAAc;QACxB,KAAK,CACH,0BAA0B,MAAM,IAAI;YAClC,gDAAgD;YAChD,iBAAiB;YACjB,MAAM;YACN,mEAAmE,CACtE,CAAC;IACJ,CAAC;CACF;AAVD,wDAUC;AAED,MAAa,kBAAmB,SAAQ,YAAY;CAAG;AAAvD,gDAAuD"}
@@ -0,0 +1,7 @@
1
+ import { NxJsonSonarConfig, ResolvedOptions, ScanExecutorOptions } from './types';
2
+ export interface ResolveInput {
3
+ projectOptions: ScanExecutorOptions;
4
+ nxJsonConfig: NxJsonSonarConfig;
5
+ env: NodeJS.ProcessEnv | Record<string, string | undefined>;
6
+ }
7
+ export declare function resolveOptions({ projectOptions, nxJsonConfig, env, }: ResolveInput): ResolvedOptions;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveOptions = resolveOptions;
4
+ const errors_1 = require("./errors");
5
+ const types_1 = require("./types");
6
+ function resolveOptions({ projectOptions, nxJsonConfig, env, }) {
7
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
8
+ refuseTokenInDiskConfig(projectOptions, 'project.json');
9
+ refuseTokenInDiskConfig(nxJsonConfig, 'nx.json');
10
+ const token = env.SONAR_TOKEN;
11
+ if (!token || token.trim() === '') {
12
+ throw new errors_1.MissingTokenError();
13
+ }
14
+ const projectKey = (_b = (_a = projectOptions.projectKey) !== null && _a !== void 0 ? _a : nxJsonConfig.projectKey) !== null && _b !== void 0 ? _b : env.SONAR_PROJECT_KEY;
15
+ if (!projectKey) {
16
+ throw new errors_1.InvalidConfigError('projectKey is required. Set it in the sonar target options, in nx.json under nxSonar, or via the SONAR_PROJECT_KEY env var.');
17
+ }
18
+ const hostUrl = (_e = (_d = (_c = projectOptions.hostUrl) !== null && _c !== void 0 ? _c : nxJsonConfig.hostUrl) !== null && _d !== void 0 ? _d : env.SONAR_HOST_URL) !== null && _e !== void 0 ? _e : types_1.DEFAULT_HOST_URL;
19
+ const organization = (_g = (_f = projectOptions.organization) !== null && _f !== void 0 ? _f : nxJsonConfig.organization) !== null && _g !== void 0 ? _g : env.SONAR_ORGANIZATION;
20
+ const exclusions = uniq([
21
+ ...types_1.DEFAULT_EXCLUSIONS,
22
+ ...((_h = nxJsonConfig.exclusions) !== null && _h !== void 0 ? _h : []),
23
+ ...((_j = projectOptions.exclusions) !== null && _j !== void 0 ? _j : []),
24
+ ]);
25
+ const extraProperties = Object.assign(Object.assign({}, ((_k = nxJsonConfig.extraProperties) !== null && _k !== void 0 ? _k : {})), ((_l = projectOptions.extraProperties) !== null && _l !== void 0 ? _l : {}));
26
+ return {
27
+ projectKey,
28
+ projectName: projectOptions.projectName,
29
+ projectVersion: projectOptions.projectVersion,
30
+ hostUrl,
31
+ organization,
32
+ sources: projectOptions.sources,
33
+ tests: projectOptions.tests,
34
+ exclusions,
35
+ coverageLcovPath: projectOptions.coverageLcovPath,
36
+ testExecutionReportPath: projectOptions.testExecutionReportPath,
37
+ qualityGateWait: (_o = (_m = projectOptions.qualityGateWait) !== null && _m !== void 0 ? _m : nxJsonConfig.qualityGateWait) !== null && _o !== void 0 ? _o : true,
38
+ branchDetection: (_q = (_p = projectOptions.branchDetection) !== null && _p !== void 0 ? _p : nxJsonConfig.branchDetection) !== null && _q !== void 0 ? _q : true,
39
+ extraProperties,
40
+ verbose: (_r = projectOptions.verbose) !== null && _r !== void 0 ? _r : false,
41
+ token,
42
+ };
43
+ }
44
+ function refuseTokenInDiskConfig(config, source) {
45
+ if (config && typeof config === 'object' && 'token' in config) {
46
+ throw new errors_1.TokenInDiskConfigError(source);
47
+ }
48
+ }
49
+ function uniq(values) {
50
+ return Array.from(new Set(values));
51
+ }
52
+ //# sourceMappingURL=resolve-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-options.js","sourceRoot":"","sources":["../../../../nx-sonar/src/utils/resolve-options.ts"],"names":[],"mappings":";;AAmBA,wCAgEC;AAnFD,qCAIkB;AAClB,mCAMiB;AAQjB,SAAgB,cAAc,CAAC,EAC7B,cAAc,EACd,YAAY,EACZ,GAAG,GACU;;IACb,uBAAuB,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;IACxD,uBAAuB,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IAEjD,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC;IAC9B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAClC,MAAM,IAAI,0BAAiB,EAAE,CAAC;IAChC,CAAC;IAED,MAAM,UAAU,GACd,MAAA,MAAA,cAAc,CAAC,UAAU,mCACxB,YAAoC,CAAC,UAAU,mCAChD,GAAG,CAAC,iBAAiB,CAAC;IACxB,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,2BAAkB,CAC1B,6HAA6H,CAC9H,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GACX,MAAA,MAAA,MAAA,cAAc,CAAC,OAAO,mCACtB,YAAY,CAAC,OAAO,mCACpB,GAAG,CAAC,cAAc,mCAClB,wBAAgB,CAAC;IAEnB,MAAM,YAAY,GAChB,MAAA,MAAA,cAAc,CAAC,YAAY,mCAC3B,YAAY,CAAC,YAAY,mCACzB,GAAG,CAAC,kBAAkB,CAAC;IAEzB,MAAM,UAAU,GAAG,IAAI,CAAC;QACtB,GAAG,0BAAkB;QACrB,GAAG,CAAC,MAAA,YAAY,CAAC,UAAU,mCAAI,EAAE,CAAC;QAClC,GAAG,CAAC,MAAA,cAAc,CAAC,UAAU,mCAAI,EAAE,CAAC;KACrC,CAAC,CAAC;IAEH,MAAM,eAAe,mCAChB,CAAC,MAAA,YAAY,CAAC,eAAe,mCAAI,EAAE,CAAC,GACpC,CAAC,MAAA,cAAc,CAAC,eAAe,mCAAI,EAAE,CAAC,CAC1C,CAAC;IAEF,OAAO;QACL,UAAU;QACV,WAAW,EAAE,cAAc,CAAC,WAAW;QACvC,cAAc,EAAE,cAAc,CAAC,cAAc;QAC7C,OAAO;QACP,YAAY;QACZ,OAAO,EAAE,cAAc,CAAC,OAAO;QAC/B,KAAK,EAAE,cAAc,CAAC,KAAK;QAC3B,UAAU;QACV,gBAAgB,EAAE,cAAc,CAAC,gBAAgB;QACjD,uBAAuB,EAAE,cAAc,CAAC,uBAAuB;QAC/D,eAAe,EACb,MAAA,MAAA,cAAc,CAAC,eAAe,mCAAI,YAAY,CAAC,eAAe,mCAAI,IAAI;QACxE,eAAe,EACb,MAAA,MAAA,cAAc,CAAC,eAAe,mCAAI,YAAY,CAAC,eAAe,mCAAI,IAAI;QACxE,eAAe;QACf,OAAO,EAAE,MAAA,cAAc,CAAC,OAAO,mCAAI,KAAK;QACxC,KAAK;KACN,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAC9B,MAAc,EACd,MAAc;IAEd,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;QAC9D,MAAM,IAAI,+BAAsB,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC;AAED,SAAS,IAAI,CAAI,MAAoB;IACnC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { ScanExecutorOptions } from './types';
2
+ export interface ResolvedPaths {
3
+ sources: string | string[];
4
+ tests?: string | string[];
5
+ coveragePath: string;
6
+ testExecutionReportPath?: string;
7
+ }
8
+ export interface ResolvePathsInput {
9
+ workspaceRoot: string;
10
+ projectRoot: string;
11
+ options: ScanExecutorOptions;
12
+ }
13
+ export declare function resolveProjectPaths({ workspaceRoot, projectRoot, options, }: ResolvePathsInput): ResolvedPaths;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveProjectPaths = resolveProjectPaths;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const errors_1 = require("./errors");
7
+ function resolveProjectPaths({ workspaceRoot, projectRoot, options, }) {
8
+ var _a, _b;
9
+ const sources = (_a = options.sources) !== null && _a !== void 0 ? _a : projectRoot;
10
+ const tests = options.tests;
11
+ const coveragePath = (_b = options.coverageLcovPath) !== null && _b !== void 0 ? _b : `coverage/${projectRoot}/lcov.info`;
12
+ if (!(0, fs_1.existsSync)((0, path_1.join)(workspaceRoot, coveragePath))) {
13
+ throw new errors_1.MissingCoverageError(coveragePath);
14
+ }
15
+ let testExecutionReportPath;
16
+ if (options.testExecutionReportPath) {
17
+ if ((0, fs_1.existsSync)((0, path_1.join)(workspaceRoot, options.testExecutionReportPath))) {
18
+ testExecutionReportPath = options.testExecutionReportPath;
19
+ }
20
+ else {
21
+ console.warn(`[@itssky/nx-sonar] testExecutionReportPath "${options.testExecutionReportPath}" not found — omitting from scanner properties.`);
22
+ }
23
+ }
24
+ return { sources, tests, coveragePath, testExecutionReportPath };
25
+ }
26
+ //# sourceMappingURL=resolve-project-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-project-paths.js","sourceRoot":"","sources":["../../../../nx-sonar/src/utils/resolve-project-paths.ts"],"names":[],"mappings":";;AAkBA,kDA2BC;AA7CD,2BAAgC;AAChC,+BAA4B;AAC5B,qCAAgD;AAgBhD,SAAgB,mBAAmB,CAAC,EAClC,aAAa,EACb,WAAW,EACX,OAAO,GACW;;IAClB,MAAM,OAAO,GAAG,MAAA,OAAO,CAAC,OAAO,mCAAI,WAAW,CAAC;IAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAE5B,MAAM,YAAY,GAChB,MAAA,OAAO,CAAC,gBAAgB,mCAAI,YAAY,WAAW,YAAY,CAAC;IAElE,IAAI,CAAC,IAAA,eAAU,EAAC,IAAA,WAAI,EAAC,aAAa,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,6BAAoB,CAAC,YAAY,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,uBAA2C,CAAC;IAChD,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;QACpC,IAAI,IAAA,eAAU,EAAC,IAAA,WAAI,EAAC,aAAa,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC,EAAE,CAAC;YACrE,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CACV,+CAA+C,OAAO,CAAC,uBAAuB,iDAAiD,CAChI,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,uBAAuB,EAAE,CAAC;AACnE,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { ScannerProperties } from './build-scanner-properties';
2
+ export interface ScanResult {
3
+ success: boolean;
4
+ }
5
+ export declare function runScanner(properties: ScannerProperties): Promise<ScanResult>;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runScanner = runScanner;
4
+ const tslib_1 = require("tslib");
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ const sonarqube_scanner_1 = require("sonarqube-scanner");
8
+ function runScanner(properties) {
9
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
10
+ if (process.env.NX_SONAR_DRY_RUN === '1') {
11
+ const out = process.env.NX_SONAR_DRY_RUN_OUT;
12
+ if (!out) {
13
+ throw new Error('NX_SONAR_DRY_RUN=1 requires NX_SONAR_DRY_RUN_OUT to be set to a file path.');
14
+ }
15
+ (0, fs_1.mkdirSync)((0, path_1.dirname)(out), { recursive: true });
16
+ (0, fs_1.writeFileSync)(out, JSON.stringify(properties, null, 2));
17
+ return { success: true };
18
+ }
19
+ const serverUrl = properties['sonar.host.url'];
20
+ return yield new Promise((resolve) => {
21
+ (0, sonarqube_scanner_1.default)({
22
+ serverUrl,
23
+ options: properties,
24
+ }, (error) => {
25
+ if (error) {
26
+ console.error('[@itssky/nx-sonar] scanner failed:', error);
27
+ resolve({ success: false });
28
+ }
29
+ else {
30
+ resolve({ success: true });
31
+ }
32
+ });
33
+ });
34
+ });
35
+ }
36
+ //# sourceMappingURL=run-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-scanner.js","sourceRoot":"","sources":["../../../../nx-sonar/src/utils/run-scanner.ts"],"names":[],"mappings":";;AASA,gCAgCC;;AAzCD,2BAA8C;AAC9C,+BAA+B;AAC/B,yDAAwC;AAOxC,SAAsB,UAAU,CAC9B,UAA6B;;QAE7B,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,GAAG,EAAE,CAAC;YACzC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;YAC7C,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,IAAI,KAAK,CACb,4EAA4E,CAC7E,CAAC;YACJ,CAAC;YACD,IAAA,cAAS,EAAC,IAAA,cAAO,EAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7C,IAAA,kBAAa,EAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACxD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAED,MAAM,SAAS,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC;QAC/C,OAAO,MAAM,IAAI,OAAO,CAAa,CAAC,OAAO,EAAE,EAAE;YAC/C,IAAA,2BAAO,EACL;gBACE,SAAS;gBACT,OAAO,EAAE,UAAU;aACpB,EACD,CAAC,KAAe,EAAE,EAAE;gBAClB,IAAI,KAAK,EAAE,CAAC;oBACV,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC;oBAC3D,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC9B,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC7B,CAAC;YACH,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CAAA"}
@@ -0,0 +1,52 @@
1
+ export interface ScanExecutorOptions {
2
+ projectKey?: string;
3
+ projectName?: string;
4
+ projectVersion?: string;
5
+ hostUrl?: string;
6
+ organization?: string;
7
+ sources?: string | string[];
8
+ tests?: string | string[];
9
+ exclusions?: string[];
10
+ coverageLcovPath?: string;
11
+ testExecutionReportPath?: string;
12
+ qualityGateWait?: boolean;
13
+ branchDetection?: boolean;
14
+ extraProperties?: Record<string, string>;
15
+ verbose?: boolean;
16
+ }
17
+ export interface NxJsonSonarConfig {
18
+ hostUrl?: string;
19
+ organization?: string;
20
+ exclusions?: string[];
21
+ qualityGateWait?: boolean;
22
+ branchDetection?: boolean;
23
+ extraProperties?: Record<string, string>;
24
+ }
25
+ export interface ResolvedOptions {
26
+ projectKey: string;
27
+ projectName?: string;
28
+ projectVersion?: string;
29
+ hostUrl: string;
30
+ organization?: string;
31
+ sources?: string | string[];
32
+ tests?: string | string[];
33
+ exclusions: string[];
34
+ coverageLcovPath?: string;
35
+ testExecutionReportPath?: string;
36
+ qualityGateWait: boolean;
37
+ branchDetection: boolean;
38
+ extraProperties: Record<string, string>;
39
+ verbose: boolean;
40
+ token: string;
41
+ }
42
+ export declare const DEFAULT_EXCLUSIONS: readonly ["**/node_modules/**", "**/dist/**", "**/*.spec.ts", "**/*.test.ts", "**/*.spec.tsx", "**/*.test.tsx"];
43
+ export declare const DEFAULT_HOST_URL = "https://sonarcloud.io";
44
+ export type CiContext = {
45
+ kind: 'branch';
46
+ name: string;
47
+ } | {
48
+ kind: 'pullRequest';
49
+ key: string;
50
+ branch: string;
51
+ base: string;
52
+ } | null;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_HOST_URL = exports.DEFAULT_EXCLUSIONS = void 0;
4
+ exports.DEFAULT_EXCLUSIONS = [
5
+ '**/node_modules/**',
6
+ '**/dist/**',
7
+ '**/*.spec.ts',
8
+ '**/*.test.ts',
9
+ '**/*.spec.tsx',
10
+ '**/*.test.tsx',
11
+ ];
12
+ exports.DEFAULT_HOST_URL = 'https://sonarcloud.io';
13
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../nx-sonar/src/utils/types.ts"],"names":[],"mappings":";;;AA4Ca,QAAA,kBAAkB,GAAG;IAChC,oBAAoB;IACpB,YAAY;IACZ,cAAc;IACd,cAAc;IACd,eAAe;IACf,eAAe;CACP,CAAC;AAEE,QAAA,gBAAgB,GAAG,uBAAuB,CAAC"}