flaglint 0.7.0 → 0.8.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.
- package/CHANGELOG.md +28 -2
- package/README.md +13 -11
- package/dist/bin/flaglint.js +14 -14
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,15 +5,41 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.8.0] - 2026-06-13
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **`--cost-estimate` renamed to `--effort-estimate`** (breaking) — the flag outputs
|
|
13
|
+
hours, not dollars; "effort" is more accurate. Update any scripts or CI pipelines
|
|
14
|
+
that use `--cost-estimate`.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Homepage email-capture / Loops signup section removed.
|
|
19
|
+
- Version displayed on homepage now read from `package.json` at build time — can no
|
|
20
|
+
longer drift from the published npm version.
|
|
21
|
+
- `robots.txt` sitemap URL updated to `/sitemap-index.xml` (was `/sitemap.xml`, which 404'd).
|
|
22
|
+
- Audit sample numbers corrected to real fixture output: 13 unique flags across 19 call
|
|
23
|
+
sites, readiness 53/100, estimate 20.8h–40h.
|
|
24
|
+
|
|
25
|
+
### Infrastructure
|
|
26
|
+
|
|
27
|
+
- Vitest `testTimeout`/`hookTimeout` raised to 30 s to fix flaky Windows/Node 22 CI timeouts.
|
|
28
|
+
- `npm publish --provenance` re-enabled in release workflow.
|
|
29
|
+
- `scripts/metrics/collect.mjs` added: fetches npm downloads + GitHub stars/forks/issues
|
|
30
|
+
and appends a JSON line to `.agent-output/metrics/history.jsonl`.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
8
34
|
## [0.7.0] - 2026-06-07
|
|
9
35
|
|
|
10
36
|
### Added
|
|
11
37
|
|
|
12
|
-
- `flaglint audit --
|
|
38
|
+
- `flaglint audit --effort-estimate` — adds a directional migration-effort estimate to
|
|
13
39
|
audit output. Computes low/high hour ranges from automatable and manual-review call
|
|
14
40
|
counts using configurable planning heuristics.
|
|
15
41
|
- `flaglint audit --hourly-rate <rate>` — adds engineering cost projection
|
|
16
|
-
(`costLow`/`costHigh`) to the estimate. Requires `--
|
|
42
|
+
(`costLow`/`costHigh`) to the estimate. Requires `--effort-estimate`.
|
|
17
43
|
- Migration readiness score displayed in `flaglint audit` terminal output: 0–100 ratio
|
|
18
44
|
of safely automatable calls to total detected LaunchDarkly calls, with grade
|
|
19
45
|
(`ready` | `moderate` | `complex` | `not-applicable`) and progress bar.
|
package/README.md
CHANGED
|
@@ -30,27 +30,27 @@ npx flaglint audit ./src
|
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
```
|
|
33
|
-
✓ Audit complete: 13 flags — 3 high risk, 10 medium risk
|
|
33
|
+
✓ Audit complete: 13 unique flags across 19 call sites — 3 high risk, 10 medium risk
|
|
34
34
|
|
|
35
|
-
Migration readiness:
|
|
36
|
-
[█████████████░░░░░░░░░░░░]
|
|
37
|
-
10 safely automatable ·
|
|
35
|
+
Migration readiness: 53/100 · moderate
|
|
36
|
+
[█████████████░░░░░░░░░░░░] 53%
|
|
37
|
+
10 of 19 call sites safely automatable · 9 require manual review
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
Add `--
|
|
40
|
+
Add `--effort-estimate` to include a directional planning estimate:
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
npx flaglint audit ./src --
|
|
43
|
+
npx flaglint audit ./src --effort-estimate
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
```
|
|
47
|
-
✓ Audit complete: 13 flags — 3 high risk, 10 medium risk
|
|
47
|
+
✓ Audit complete: 13 unique flags across 19 call sites — 3 high risk, 10 medium risk
|
|
48
48
|
|
|
49
|
-
Migration readiness:
|
|
50
|
-
[█████████████░░░░░░░░░░░░]
|
|
51
|
-
10 safely automatable ·
|
|
49
|
+
Migration readiness: 53/100 · moderate
|
|
50
|
+
[█████████████░░░░░░░░░░░░] 53%
|
|
51
|
+
10 of 19 call sites safely automatable · 9 require manual review
|
|
52
52
|
|
|
53
|
-
Estimated migration effort:
|
|
53
|
+
Estimated migration effort: 20.8h – 40h
|
|
54
54
|
Estimates are directional. See the report for assumptions.
|
|
55
55
|
```
|
|
56
56
|
|
|
@@ -58,6 +58,8 @@ For the full report see `--format html`. [Documentation](https://flaglint.dev/do
|
|
|
58
58
|
|
|
59
59
|
No API key. No source upload. LaunchDarkly stays your provider — OpenFeature becomes the evaluation API your application calls.
|
|
60
60
|
|
|
61
|
+
Migrating an existing Node.js service? Read the [complete LaunchDarkly-to-OpenFeature migration guide](https://flaglint.dev/guides/launchdarkly-to-openfeature-nodejs/).
|
|
62
|
+
|
|
61
63
|
---
|
|
62
64
|
|
|
63
65
|
## The problem FlagLint solves
|
package/dist/bin/flaglint.js
CHANGED
|
@@ -789,7 +789,7 @@ function formatHTML(result, options) {
|
|
|
789
789
|
<div class="card"><div class="card-num orange">${manualCount}</div><div class="card-label">Manual Review (${manualPct}%)</div></div>
|
|
790
790
|
<div class="card"><div class="card-num blue">${detailBulkCount}</div><div class="card-label">Detail/Bulk Calls</div></div>` : "";
|
|
791
791
|
const title = options.title ? esc(options.title) : "FlagLint Scan Report";
|
|
792
|
-
const version = true ? "0.
|
|
792
|
+
const version = true ? "0.8.0" : "0.1.0";
|
|
793
793
|
return `<!DOCTYPE html>
|
|
794
794
|
<html lang="en">
|
|
795
795
|
<head>
|
|
@@ -1322,7 +1322,7 @@ function formatMigrationReport(analysis) {
|
|
|
1322
1322
|
unsupportedUnknownCount
|
|
1323
1323
|
} = analysis;
|
|
1324
1324
|
const date = (/* @__PURE__ */ new Date()).toLocaleDateString();
|
|
1325
|
-
const version = true ? "0.
|
|
1325
|
+
const version = true ? "0.8.0" : "0.1.0";
|
|
1326
1326
|
const lines = [];
|
|
1327
1327
|
lines.push("# OpenFeature Migration Inventory");
|
|
1328
1328
|
lines.push(`Generated by FlagLint v${version} on ${date}`);
|
|
@@ -2329,7 +2329,7 @@ function formatAuditMarkdown(report, options) {
|
|
|
2329
2329
|
}
|
|
2330
2330
|
function formatAuditHtml(report, options) {
|
|
2331
2331
|
const { summary, flags, readiness } = report;
|
|
2332
|
-
const version = true ? "0.
|
|
2332
|
+
const version = true ? "0.8.0" : "0.1.0";
|
|
2333
2333
|
const date = new Date(summary.scannedAt).toLocaleString();
|
|
2334
2334
|
const riskBadge = (level) => {
|
|
2335
2335
|
if (level === "high")
|
|
@@ -2593,15 +2593,15 @@ function computeEstimate(readiness, overrides, hourlyRate) {
|
|
|
2593
2593
|
// src/commands/audit.ts
|
|
2594
2594
|
var VALID_AUDIT_FORMATS = ["json", "markdown", "html"];
|
|
2595
2595
|
function registerAuditCommand(program2) {
|
|
2596
|
-
program2.command("audit").description("Generate a flag debt audit report").argument("[dir]", "directory to audit", process.cwd()).option("-f, --format <format>", "output format: json | markdown | html", "markdown").option("-o, --output <file>", "write report to file").option("-c, --config <path>", "path to .flaglintrc config file").option("--exclude-tests", "exclude test files (*.test.*, *.spec.*, __tests__/, tests/)").option("--
|
|
2596
|
+
program2.command("audit").description("Generate a flag debt audit report").argument("[dir]", "directory to audit", process.cwd()).option("-f, --format <format>", "output format: json | markdown | html", "markdown").option("-o, --output <file>", "write report to file").option("-c, --config <path>", "path to .flaglintrc config file").option("--exclude-tests", "exclude test files (*.test.*, *.spec.*, __tests__/, tests/)").option("--effort-estimate", "include a migration effort estimate in the report. The default assumptions are configurable planning heuristics, not observed industry benchmarks.").option("--hourly-rate <rate>", "hourly rate for cost projection (requires --effort-estimate)").addHelpText(
|
|
2597
2597
|
"after",
|
|
2598
2598
|
`
|
|
2599
2599
|
Examples:
|
|
2600
2600
|
$ flaglint audit generate flag debt audit report
|
|
2601
2601
|
$ flaglint audit --format html shareable HTML report
|
|
2602
2602
|
$ flaglint audit --output audit.md save to file
|
|
2603
|
-
$ flaglint audit --
|
|
2604
|
-
$ flaglint audit --
|
|
2603
|
+
$ flaglint audit --effort-estimate include migration effort estimate
|
|
2604
|
+
$ flaglint audit --effort-estimate --hourly-rate 125 include cost projection`
|
|
2605
2605
|
).action(
|
|
2606
2606
|
async (dir, options) => {
|
|
2607
2607
|
if (!VALID_AUDIT_FORMATS.includes(options.format)) {
|
|
@@ -2615,9 +2615,9 @@ Examples:
|
|
|
2615
2615
|
}
|
|
2616
2616
|
let hourlyRate;
|
|
2617
2617
|
if (options.hourlyRate !== void 0) {
|
|
2618
|
-
if (!options.
|
|
2618
|
+
if (!options.effortEstimate) {
|
|
2619
2619
|
process.stderr.write(
|
|
2620
|
-
chalk4.yellow("warn: --hourly-rate has no effect without --
|
|
2620
|
+
chalk4.yellow("warn: --hourly-rate has no effect without --effort-estimate\n")
|
|
2621
2621
|
);
|
|
2622
2622
|
} else {
|
|
2623
2623
|
const parsed = Number(options.hourlyRate);
|
|
@@ -2710,11 +2710,11 @@ Examples:
|
|
|
2710
2710
|
`
|
|
2711
2711
|
)
|
|
2712
2712
|
);
|
|
2713
|
-
if (format === "json" && options.
|
|
2713
|
+
if (format === "json" && options.effortEstimate) {
|
|
2714
2714
|
const emptyReport = buildAuditReport(scanResult, []);
|
|
2715
2715
|
process.stdout.write(formatAuditJson(emptyReport, { estimate: null }) + "\n");
|
|
2716
2716
|
process.stderr.write(chalk4.dim("Migration estimate: N/A\n"));
|
|
2717
|
-
} else if (options.
|
|
2717
|
+
} else if (options.effortEstimate) {
|
|
2718
2718
|
process.stderr.write(chalk4.dim("Migration estimate: N/A\n"));
|
|
2719
2719
|
}
|
|
2720
2720
|
process.exit(0);
|
|
@@ -2723,7 +2723,7 @@ Examples:
|
|
|
2723
2723
|
scanResult,
|
|
2724
2724
|
scanResult.migrationInventory ?? []
|
|
2725
2725
|
);
|
|
2726
|
-
const renderOptions = options.
|
|
2726
|
+
const renderOptions = options.effortEstimate ? { estimate: computeEstimate(auditReport.readiness, void 0, hourlyRate) } : void 0;
|
|
2727
2727
|
let output;
|
|
2728
2728
|
if (format === "json") {
|
|
2729
2729
|
output = formatAuditJson(auditReport, renderOptions);
|
|
@@ -2762,7 +2762,7 @@ Examples:
|
|
|
2762
2762
|
process.stderr.write("\n");
|
|
2763
2763
|
if (readiness.grade === "not-applicable") {
|
|
2764
2764
|
process.stderr.write(chalk4.dim("Migration readiness: N/A \u2014 no direct LaunchDarkly calls detected.\n"));
|
|
2765
|
-
if (options.
|
|
2765
|
+
if (options.effortEstimate) {
|
|
2766
2766
|
process.stderr.write(chalk4.dim("Migration estimate: N/A\n"));
|
|
2767
2767
|
}
|
|
2768
2768
|
} else {
|
|
@@ -2777,7 +2777,7 @@ Examples:
|
|
|
2777
2777
|
`
|
|
2778
2778
|
)
|
|
2779
2779
|
);
|
|
2780
|
-
if (options.
|
|
2780
|
+
if (options.effortEstimate && renderOptions?.estimate) {
|
|
2781
2781
|
const est = renderOptions.estimate;
|
|
2782
2782
|
process.stderr.write("\n");
|
|
2783
2783
|
process.stderr.write(
|
|
@@ -2800,7 +2800,7 @@ Examples:
|
|
|
2800
2800
|
// src/cli.ts
|
|
2801
2801
|
function createCLI() {
|
|
2802
2802
|
const program2 = new Command();
|
|
2803
|
-
program2.name("flaglint").description("Scan LaunchDarkly Node.js SDK usage, generate safe OpenFeature migration diffs, and enforce the vendor boundary in CI.").version("0.
|
|
2803
|
+
program2.name("flaglint").description("Scan LaunchDarkly Node.js SDK usage, generate safe OpenFeature migration diffs, and enforce the vendor boundary in CI.").version("0.8.0", "-v, --version", "output the current version").addHelpText(
|
|
2804
2804
|
"after",
|
|
2805
2805
|
`
|
|
2806
2806
|
Examples:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flaglint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Scan LaunchDarkly Node.js SDK usage, generate safe OpenFeature migration diffs, and enforce the vendor boundary in CI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"preview:docs": "ASTRO_TELEMETRY_DISABLED=1 astro preview --port 4321",
|
|
52
52
|
"test:package": "tsx scripts/test-package.ts",
|
|
53
53
|
"test:smoke": "playwright test",
|
|
54
|
+
"metrics": "node scripts/metrics/collect.mjs",
|
|
54
55
|
"new-branch": "tsx scripts/new-branch.ts",
|
|
55
56
|
"release:patch": "tsx scripts/release.ts patch",
|
|
56
57
|
"release:minor": "tsx scripts/release.ts minor",
|