@enerlence/suntropy-cli 0.11.2 → 0.11.4
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/README.md +22 -1
- package/dist/bin/suntropy.js +28 -4
- package/dist/bin/suntropy.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,6 +35,27 @@ suntropy auth status
|
|
|
35
35
|
> root command (e.g. `suntropy --profile dev auth status`). They apply to every
|
|
36
36
|
> subcommand, including `auth`.
|
|
37
37
|
|
|
38
|
+
### Token resolution order
|
|
39
|
+
|
|
40
|
+
The auth token is resolved in this order (first non-empty wins):
|
|
41
|
+
|
|
42
|
+
1. `--token <jwt>` global flag
|
|
43
|
+
2. `SUNTROPY_API_KEY` environment variable
|
|
44
|
+
3. `token` stored in the active profile (`~/.suntropy/config.json`, written by
|
|
45
|
+
`auth set-key` / `auth login`)
|
|
46
|
+
|
|
47
|
+
The `SUNTROPY_API_KEY` fallback (available since `0.11.3`) lets a host runtime
|
|
48
|
+
inject a just-in-time credential without a prior `auth login` / `auth set-key`:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
SUNTROPY_API_KEY=<jwt> suntropy studies list
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
> ⚠️ The value must be a **JWT** (the one you'd pass to `auth set-key --key`),
|
|
55
|
+
> since the CLI sends it as `Authorization: Bearer <token>`. Despite the name, it
|
|
56
|
+
> is not a `shp_`/`devic-`-style API key — an invalid format yields a 401 from
|
|
57
|
+
> the backend.
|
|
58
|
+
|
|
38
59
|
## Global Options
|
|
39
60
|
|
|
40
61
|
| Option | Default | Description |
|
|
@@ -42,7 +63,7 @@ suntropy auth status
|
|
|
42
63
|
| `--format json\|human\|csv` | `json` | Output format |
|
|
43
64
|
| `--fields f1,f2,...` | all | Select specific fields |
|
|
44
65
|
| `--server <url>` | config | Override API server URL |
|
|
45
|
-
| `--token <jwt>` | config | Override auth token |
|
|
66
|
+
| `--token <jwt>` | `SUNTROPY_API_KEY` env / config | Override auth token (see "Token resolution order") |
|
|
46
67
|
| `--profile <name>` | default | Config profile |
|
|
47
68
|
| `--verbose` | false | Show HTTP details on stderr |
|
|
48
69
|
| `--quiet` | false | Suppress non-data output |
|
package/dist/bin/suntropy.js
CHANGED
|
@@ -92,9 +92,9 @@ function resolveAuth(opts) {
|
|
|
92
92
|
const config = loadConfig();
|
|
93
93
|
const profile = getActiveProfile(config, opts.profile);
|
|
94
94
|
const server = opts.server || profile.server;
|
|
95
|
-
const token = opts.token || profile.token;
|
|
95
|
+
const token = opts.token || process.env.SUNTROPY_API_KEY || profile.token;
|
|
96
96
|
if (!token) {
|
|
97
|
-
throw new Error("Not authenticated. Run: suntropy auth set-key --key <jwt> or suntropy auth login");
|
|
97
|
+
throw new Error("Not authenticated. Run: suntropy auth set-key --key <jwt> or suntropy auth login, or set the SUNTROPY_API_KEY env var.");
|
|
98
98
|
}
|
|
99
99
|
return { server, token };
|
|
100
100
|
}
|
|
@@ -2635,7 +2635,7 @@ Examples:
|
|
|
2635
2635
|
});
|
|
2636
2636
|
set.command("economics").description(
|
|
2637
2637
|
"Set economic parameters for the study.\nExample: suntropy studies set economics --file study.json --margin 15 --total-cost 6500 --lifetime 25"
|
|
2638
|
-
).option("--file <path>", "Study file path").option("--margin <n>", "Margin percentage").option("--total-cost <n>", "Total installation cost (\u20AC)").option("--lifetime <n>", "Installation lifetime in years").option("--inflation <n>", "Inflation rate percentage").option("--taxes-pct <n>", "Tax percentage").option("--include-taxes", "Include taxes in pricing").option("--commercial-fee <n>", "Commercial fee percentage").option("--excesses-mode <mode>", "Excesses compensation: gridSelling, PPA, noInjection, virtualBattery").option("--excesses-buy-price <n>", "Excesses buy price (\u20AC/MWh)").option("--excesses-selling-price <n>", "Excesses selling price (\u20AC/MWh)").option("--peak-power-cost <n>", "Cost per
|
|
2638
|
+
).option("--file <path>", "Study file path").option("--margin <n>", "Margin percentage").option("--total-cost <n>", "Total installation cost (\u20AC)").option("--lifetime <n>", "Installation lifetime in years").option("--inflation <n>", "Inflation rate percentage").option("--taxes-pct <n>", "Tax percentage").option("--include-taxes", "Include taxes in pricing").option("--commercial-fee <n>", "Commercial fee percentage").option("--excesses-mode <mode>", "Excesses compensation: gridSelling, PPA, noInjection, virtualBattery").option("--excesses-buy-price <n>", "Excesses buy price (\u20AC/MWh)").option("--excesses-selling-price <n>", "Excesses selling price (\u20AC/MWh)").option("--peak-power-cost <n>", "Cost per Wp (\u20AC/Wp). If --total-cost is omitted, totalCost is derived as cost \xD7 installed peak power (W)").option("--guarantee-production <n>", "Guarantee production percentage").action(async (opts) => {
|
|
2639
2639
|
try {
|
|
2640
2640
|
const result = updateStudy(resolveFile(opts), (study) => {
|
|
2641
2641
|
const er = study.economicResults || {};
|
|
@@ -2651,6 +2651,30 @@ Examples:
|
|
|
2651
2651
|
if (opts.excessesSellingPrice !== void 0) er.excessesSellingPrice = parseFloat(opts.excessesSellingPrice);
|
|
2652
2652
|
if (opts.peakPowerCost !== void 0) er.peakPowerCost = parseFloat(opts.peakPowerCost);
|
|
2653
2653
|
if (opts.guaranteeProduction !== void 0) er.guaranteeProductionPercentage = parseFloat(opts.guaranteeProduction);
|
|
2654
|
+
if (opts.peakPowerCost !== void 0 && opts.totalCost === void 0) {
|
|
2655
|
+
const surfaces = study.surfaces || [];
|
|
2656
|
+
let totalWatts = 0;
|
|
2657
|
+
let resolvedCount = 0;
|
|
2658
|
+
let anyDefault = false;
|
|
2659
|
+
for (const surface of surfaces) {
|
|
2660
|
+
const { installedPower, isDefault } = resolveSurfaceInstalledPower(surface, study);
|
|
2661
|
+
if (isDefault) {
|
|
2662
|
+
anyDefault = true;
|
|
2663
|
+
continue;
|
|
2664
|
+
}
|
|
2665
|
+
totalWatts += installedPower;
|
|
2666
|
+
resolvedCount += 1;
|
|
2667
|
+
}
|
|
2668
|
+
if (resolvedCount > 0 && !anyDefault) {
|
|
2669
|
+
er.totalCost = Math.round(parseFloat(opts.peakPowerCost) * totalWatts * 100) / 100;
|
|
2670
|
+
} else {
|
|
2671
|
+
process.stderr.write(
|
|
2672
|
+
JSON.stringify({
|
|
2673
|
+
warning: "Set --peak-power-cost but could not derive totalCost: " + (surfaces.length === 0 ? "the study has no surfaces." : "some surfaces have no resolvable installed power (set panels + kit/panel first).") + " Pass --total-cost explicitly to set it."
|
|
2674
|
+
}) + "\n"
|
|
2675
|
+
);
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2654
2678
|
study.economicResults = er;
|
|
2655
2679
|
return void 0;
|
|
2656
2680
|
});
|
|
@@ -4598,7 +4622,7 @@ function registerCommandProfileCommand(program2) {
|
|
|
4598
4622
|
}
|
|
4599
4623
|
|
|
4600
4624
|
// src/index.ts
|
|
4601
|
-
var CLI_VERSION = true ? "0.11.
|
|
4625
|
+
var CLI_VERSION = true ? "0.11.4" : "0.0.0-dev";
|
|
4602
4626
|
function createProgram() {
|
|
4603
4627
|
const program2 = new Command3();
|
|
4604
4628
|
program2.name("suntropy").description("Agent-first CLI for Suntropy solar platform. Optimized for programmatic data manipulation and progressive exploration.").version(CLI_VERSION).option("--format <format>", "Output format: json (default), human, csv", "json").option("--fields <fields>", "Comma-separated fields to include in output").option("--server <url>", "Override API server URL").option("--token <jwt>", "Override authentication token").option("--profile <name>", "Use a specific config profile").option("--verbose", "Show HTTP request/response details on stderr").option("--quiet", "Suppress non-data output").option("--save <file>", "Save output to file (also writes to stdout)");
|