@flagshark/core 2.0.0 → 2.1.1
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 +2 -0
- package/dist/config/schema.d.ts +112 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +63 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/detection/detectors/typescript.d.ts.map +1 -1
- package/dist/detection/detectors/typescript.js +41 -0
- package/dist/detection/detectors/typescript.js.map +1 -1
- package/dist/detection/feature-flag.d.ts +28 -0
- package/dist/detection/feature-flag.d.ts.map +1 -1
- package/dist/detection/helpers.d.ts +16 -0
- package/dist/detection/helpers.d.ts.map +1 -1
- package/dist/detection/helpers.js +117 -6
- package/dist/detection/helpers.js.map +1 -1
- package/dist/detection/import-graph.d.ts +234 -0
- package/dist/detection/import-graph.d.ts.map +1 -0
- package/dist/detection/import-graph.js +641 -0
- package/dist/detection/import-graph.js.map +1 -0
- package/dist/detection/interface.d.ts +57 -0
- package/dist/detection/interface.d.ts.map +1 -1
- package/dist/detection/interface.js.map +1 -1
- package/dist/detection/polyglot-analyzer.d.ts +8 -0
- package/dist/detection/polyglot-analyzer.d.ts.map +1 -1
- package/dist/detection/polyglot-analyzer.js +2 -0
- package/dist/detection/polyglot-analyzer.js.map +1 -1
- package/dist/detection/tree-sitter/engine.d.ts.map +1 -1
- package/dist/detection/tree-sitter/engine.js +62 -15
- package/dist/detection/tree-sitter/engine.js.map +1 -1
- package/dist/detection/tree-sitter/parser-cache.d.ts +20 -0
- package/dist/detection/tree-sitter/parser-cache.d.ts.map +1 -1
- package/dist/detection/tree-sitter/parser-cache.js +32 -1
- package/dist/detection/tree-sitter/parser-cache.js.map +1 -1
- package/dist/output/json.d.ts.map +1 -1
- package/dist/output/json.js +28 -0
- package/dist/output/json.js.map +1 -1
- package/dist/output/markdown.d.ts.map +1 -1
- package/dist/output/markdown.js +47 -1
- package/dist/output/markdown.js.map +1 -1
- package/dist/output/text.d.ts.map +1 -1
- package/dist/output/text.js +89 -0
- package/dist/output/text.js.map +1 -1
- package/dist/providers/cross-reference.d.ts +36 -2
- package/dist/providers/cross-reference.d.ts.map +1 -1
- package/dist/providers/cross-reference.js +102 -7
- package/dist/providers/cross-reference.js.map +1 -1
- package/dist/providers/interface.d.ts +116 -2
- package/dist/providers/interface.d.ts.map +1 -1
- package/dist/providers/launchdarkly/client.d.ts +12 -0
- package/dist/providers/launchdarkly/client.d.ts.map +1 -1
- package/dist/providers/launchdarkly/client.js +243 -24
- package/dist/providers/launchdarkly/client.js.map +1 -1
- package/dist/providers/launchdarkly/types.d.ts +318 -0
- package/dist/providers/launchdarkly/types.d.ts.map +1 -1
- package/dist/providers/launchdarkly/types.js +82 -0
- package/dist/providers/launchdarkly/types.js.map +1 -1
- package/dist/providers/orchestrate.d.ts +34 -2
- package/dist/providers/orchestrate.d.ts.map +1 -1
- package/dist/providers/orchestrate.js +59 -7
- package/dist/providers/orchestrate.js.map +1 -1
- package/dist/scan-repo.d.ts +28 -0
- package/dist/scan-repo.d.ts.map +1 -1
- package/dist/scan-repo.js +290 -4
- package/dist/scan-repo.js.map +1 -1
- package/dist/staleness.d.ts +31 -1
- package/dist/staleness.d.ts.map +1 -1
- package/dist/staleness.js +66 -10
- package/dist/staleness.js.map +1 -1
- package/package.json +2 -1
|
@@ -1,44 +1,263 @@
|
|
|
1
|
-
import
|
|
1
|
+
import pLimit from 'p-limit';
|
|
2
|
+
import { EvaluationsResponseSchema, FlagsResponseSchema, FlagStatusesResponseSchema, MembersResponseSchema, } from './types.js';
|
|
2
3
|
import { LdApiError } from './errors.js';
|
|
3
4
|
const DEFAULT_API_BASE = 'https://app.launchdarkly.com';
|
|
4
5
|
const LD_API_VERSION = '20240415';
|
|
6
|
+
// Concurrency cap on the per-flag evaluation-counts fetch fan-out.
|
|
7
|
+
// LD's per-token rate limit is documented at "thousands of requests per
|
|
8
|
+
// minute"; 5 in-flight keeps us comfortably under any reasonable cap
|
|
9
|
+
// even on 200-flag projects. Higher = faster scans, more rate-limit
|
|
10
|
+
// risk. Kept private (not configurable) because tuning this should be
|
|
11
|
+
// a deliberate change visible in code review.
|
|
12
|
+
const EVALUATIONS_CONCURRENCY = 5;
|
|
13
|
+
/**
|
|
14
|
+
* Fetches every flag in `config.project` (active + archived), then enriches
|
|
15
|
+
* the result with platform-side signals from two auxiliary LD endpoints:
|
|
16
|
+
*
|
|
17
|
+
* /api/v2/flag-statuses/{project}/{env} → status + lastRequested
|
|
18
|
+
* /api/v2/members?limit=500 → maintainer name resolution
|
|
19
|
+
*
|
|
20
|
+
* Both auxiliary calls are best-effort: if they fail (e.g. token lacks
|
|
21
|
+
* permission, network blip), we log via thrown LdApiError only for the
|
|
22
|
+
* primary /flags request. Aux failures are swallowed so the core
|
|
23
|
+
* cross-reference path still functions with partial data.
|
|
24
|
+
*/
|
|
5
25
|
export async function fetchAllFlags(config, opts = {}) {
|
|
6
26
|
const fetchFn = opts.fetch ?? globalThis.fetch;
|
|
7
27
|
const apiBase = opts.apiBase ?? DEFAULT_API_BASE;
|
|
8
28
|
const out = [];
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
// LD's list endpoint EXCLUDES archived flags by default; passing
|
|
30
|
+
// `archived=true` flips it to return ONLY archived flags. There is no
|
|
31
|
+
// "both" mode in the v2 API. So we make two pagination passes — one
|
|
32
|
+
// for active, one for archived — and union the results. Without this,
|
|
33
|
+
// any flag archived in LD silently surfaces as `missing-in-platform`
|
|
34
|
+
// (the exact opposite of `archived-in-platform`), defeating the
|
|
35
|
+
// archived-flag signal entirely.
|
|
36
|
+
const headers = { Authorization: config.token, 'LD-API-Version': LD_API_VERSION };
|
|
37
|
+
const maintainerIds = new Set();
|
|
38
|
+
for (const archivedOnly of [false, true]) {
|
|
39
|
+
let path = buildFirstPath(config.project, config.environment, archivedOnly);
|
|
40
|
+
while (path) {
|
|
41
|
+
const res = await fetchFn(new URL(path, apiBase), { headers, signal: opts.signal });
|
|
42
|
+
if (!res.ok) {
|
|
43
|
+
throw new LdApiError(`LaunchDarkly API ${res.status} ${res.statusText}`, res.status);
|
|
44
|
+
}
|
|
45
|
+
const json = await res.json();
|
|
46
|
+
const parsed = FlagsResponseSchema.parse(json);
|
|
47
|
+
for (const item of parsed.items) {
|
|
48
|
+
const envData = item.environments?.[config.environment];
|
|
49
|
+
if (item.maintainerId)
|
|
50
|
+
maintainerIds.add(item.maintainerId);
|
|
51
|
+
out.push({
|
|
52
|
+
key: item.key,
|
|
53
|
+
archived: item.archived,
|
|
54
|
+
lastModified: envData?.lastModified != null ? new Date(envData.lastModified) : null,
|
|
55
|
+
// LD's `temporary` is true when the user wants the flag removed
|
|
56
|
+
// eventually, false when it's permanent. We invert so downstream
|
|
57
|
+
// logic doesn't have to re-reason the polarity every time.
|
|
58
|
+
permanent: !item.temporary,
|
|
59
|
+
createdAt: item.creationDate != null ? new Date(item.creationDate) : null,
|
|
60
|
+
tags: item.tags,
|
|
61
|
+
// Resolved below from the /members lookup; left as the opaque id
|
|
62
|
+
// for now so the producer/consumer split stays clean.
|
|
63
|
+
maintainer: item.maintainerId,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
path = parsed._links?.next?.href;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Aux 1: resolve maintainer IDs → "First Last <email>" display strings.
|
|
70
|
+
// Single batch request, best-effort. If the token lacks /members read
|
|
71
|
+
// permission (Reader role doesn't include it on some LD orgs), we
|
|
72
|
+
// leave the opaque ID in place rather than fail the whole scan.
|
|
73
|
+
if (maintainerIds.size > 0) {
|
|
74
|
+
const members = await fetchMembersMap(apiBase, headers, fetchFn, opts.signal);
|
|
75
|
+
if (members) {
|
|
76
|
+
for (const flag of out) {
|
|
77
|
+
if (flag.maintainer && members.has(flag.maintainer)) {
|
|
78
|
+
flag.maintainer = members.get(flag.maintainer);
|
|
79
|
+
}
|
|
80
|
+
else if (flag.maintainer) {
|
|
81
|
+
// Couldn't resolve — drop the opaque ID rather than display it.
|
|
82
|
+
flag.maintainer = undefined;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// Members lookup failed entirely — strip the opaque IDs so they
|
|
88
|
+
// don't leak into output as garbled-looking strings.
|
|
89
|
+
for (const flag of out) {
|
|
90
|
+
if (flag.maintainer)
|
|
91
|
+
flag.maintainer = undefined;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Aux 2: fetch the per-environment flag-status verdict (LD's own
|
|
96
|
+
// staleness: 'new' / 'active' / 'inactive' / 'launched'). Cross-reference
|
|
97
|
+
// turns these into platform-inactive / platform-launched signals.
|
|
98
|
+
const statuses = await fetchFlagStatuses(config.project, config.environment, apiBase, headers, fetchFn, opts.signal);
|
|
99
|
+
if (statuses) {
|
|
100
|
+
for (const flag of out) {
|
|
101
|
+
const s = statuses.get(flag.key);
|
|
102
|
+
if (s) {
|
|
103
|
+
flag.status = s.name;
|
|
104
|
+
flag.lastRequested = s.lastRequested;
|
|
105
|
+
}
|
|
30
106
|
}
|
|
31
|
-
path = parsed._links?.next?.href;
|
|
32
107
|
}
|
|
108
|
+
// Aux 3: 30-day evaluation counts per flag. Per-flag endpoint, so we
|
|
109
|
+
// fan out with a concurrency cap. The endpoint is tier-gated; the
|
|
110
|
+
// first 404/403/401 short-circuits the rest so we don't make N
|
|
111
|
+
// pointless requests on accounts that don't have this feature.
|
|
112
|
+
// Active flags only — archived flags have no evaluation activity by
|
|
113
|
+
// definition, and probing them wastes API calls.
|
|
114
|
+
await enrichWithEvaluations(out, config, apiBase, headers, fetchFn, opts.signal);
|
|
33
115
|
return out;
|
|
34
116
|
}
|
|
35
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Fan-out fetch of 30-day evaluation counts per (active, non-archived)
|
|
119
|
+
* flag. Mutates the input PlatformFlag[] in place — sets
|
|
120
|
+
* `evaluations30d` to a number on success, leaves it undefined when
|
|
121
|
+
* the endpoint isn't available. The first request that returns 401 /
|
|
122
|
+
* 403 / 404 disables the feature for the rest of the batch (assumed
|
|
123
|
+
* to be tier-gated or feature-off project-wide).
|
|
124
|
+
*
|
|
125
|
+
* Network errors on individual flags are tolerated: that single flag's
|
|
126
|
+
* `evaluations30d` stays undefined and the rest of the scan continues.
|
|
127
|
+
* Cross-reference treats `undefined` as "no data, no signal".
|
|
128
|
+
*/
|
|
129
|
+
async function enrichWithEvaluations(flags, config, apiBase, headers, fetchFn, signal) {
|
|
130
|
+
const candidates = flags.filter((f) => !f.archived);
|
|
131
|
+
if (candidates.length === 0)
|
|
132
|
+
return;
|
|
133
|
+
let featureAvailable = true;
|
|
134
|
+
const limiter = pLimit(EVALUATIONS_CONCURRENCY);
|
|
135
|
+
await Promise.all(candidates.map((flag) => limiter(async () => {
|
|
136
|
+
if (!featureAvailable)
|
|
137
|
+
return;
|
|
138
|
+
try {
|
|
139
|
+
const url = new URL(`/api/v2/usage/evaluations/${encodeURIComponent(config.project)}/${encodeURIComponent(config.environment)}/${encodeURIComponent(flag.key)}`, apiBase);
|
|
140
|
+
const res = await fetchFn(url, { headers, signal });
|
|
141
|
+
if (res.status === 401 || res.status === 403 || res.status === 404) {
|
|
142
|
+
// Disable for the rest of the batch — assume tier-gated /
|
|
143
|
+
// feature off for this project. Leave already-set
|
|
144
|
+
// evaluations30d alone (no rollback).
|
|
145
|
+
featureAvailable = false;
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (!res.ok) {
|
|
149
|
+
// 5xx / 429 — transient. Skip this flag, keep the feature
|
|
150
|
+
// enabled for others.
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const parsed = EvaluationsResponseSchema.parse(await res.json());
|
|
154
|
+
flag.evaluations30d = sumEvaluationSeries(parsed.series);
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
// Network error / JSON parse failure — same treatment as 5xx,
|
|
158
|
+
// skip this flag, keep going.
|
|
159
|
+
}
|
|
160
|
+
})));
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* The /usage/evaluations response is a time-series of variation-keyed
|
|
164
|
+
* counts: each series point is `{ time, "0": N, "1": M, ... }`. We
|
|
165
|
+
* don't care which variation served — only the total. Sum every
|
|
166
|
+
* numeric field on every series point.
|
|
167
|
+
*/
|
|
168
|
+
function sumEvaluationSeries(series) {
|
|
169
|
+
let total = 0;
|
|
170
|
+
for (const point of series) {
|
|
171
|
+
for (const [key, value] of Object.entries(point)) {
|
|
172
|
+
if (key === 'time')
|
|
173
|
+
continue;
|
|
174
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
175
|
+
total += value;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return total;
|
|
180
|
+
}
|
|
181
|
+
function buildFirstPath(project, environment, archived = false) {
|
|
36
182
|
const params = new URLSearchParams({
|
|
37
183
|
env: environment,
|
|
38
184
|
limit: '100',
|
|
39
185
|
offset: '0',
|
|
40
186
|
summary: '1',
|
|
41
187
|
});
|
|
188
|
+
if (archived)
|
|
189
|
+
params.set('archived', 'true');
|
|
42
190
|
return `/api/v2/flags/${encodeURIComponent(project)}?${params.toString()}`;
|
|
43
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Best-effort fetch of every LD member, returning a map from member ID
|
|
194
|
+
* to "First Last <email>" display string. Returns null when the API
|
|
195
|
+
* rejects the request (typically: token lacks /members read scope).
|
|
196
|
+
* Caller handles null by leaving maintainer fields unresolved.
|
|
197
|
+
*/
|
|
198
|
+
async function fetchMembersMap(apiBase, headers, fetchFn, signal) {
|
|
199
|
+
try {
|
|
200
|
+
const url = new URL('/api/v2/members?limit=500', apiBase);
|
|
201
|
+
const res = await fetchFn(url, { headers, signal });
|
|
202
|
+
if (!res.ok)
|
|
203
|
+
return null;
|
|
204
|
+
const parsed = MembersResponseSchema.parse(await res.json());
|
|
205
|
+
const map = new Map();
|
|
206
|
+
for (const m of parsed.items) {
|
|
207
|
+
const name = [m.firstName, m.lastName].filter((s) => s).join(' ').trim();
|
|
208
|
+
const display = name ? `${name} <${m.email}>` : m.email;
|
|
209
|
+
map.set(m._id, display);
|
|
210
|
+
}
|
|
211
|
+
return map;
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
/* v8 ignore start — defensive catch for malformed JSON / schema
|
|
215
|
+
drift; not exercised by current fixtures. */
|
|
216
|
+
return null;
|
|
217
|
+
/* v8 ignore stop */
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Best-effort fetch of LD's per-environment flag-status verdicts for
|
|
222
|
+
* every flag in the project. Returns a Map keyed by flag key whose
|
|
223
|
+
* values include LD's own staleness verdict (`name`) and the
|
|
224
|
+
* lastRequested timestamp. Returns null when the API rejects the
|
|
225
|
+
* request — cross-reference falls back to its non-status code paths.
|
|
226
|
+
*
|
|
227
|
+
* The parent-link parsing extracts the flag key from
|
|
228
|
+
* `/api/v2/flags/{project}/{flagKey}` — LD doesn't return the key
|
|
229
|
+
* inline on each status item.
|
|
230
|
+
*/
|
|
231
|
+
async function fetchFlagStatuses(project, environment, apiBase, headers, fetchFn, signal) {
|
|
232
|
+
try {
|
|
233
|
+
const url = new URL(`/api/v2/flag-statuses/${encodeURIComponent(project)}/${encodeURIComponent(environment)}`, apiBase);
|
|
234
|
+
const res = await fetchFn(url, { headers, signal });
|
|
235
|
+
if (!res.ok)
|
|
236
|
+
return null;
|
|
237
|
+
const parsed = FlagStatusesResponseSchema.parse(await res.json());
|
|
238
|
+
const out = new Map();
|
|
239
|
+
for (const item of parsed.items) {
|
|
240
|
+
/* v8 ignore start — defensive guards against LD responses without
|
|
241
|
+
a parent link or with malformed hrefs; production LD always
|
|
242
|
+
sends a well-formed href on this endpoint, but we'd rather
|
|
243
|
+
skip a single item than fail the whole batch on contract drift. */
|
|
244
|
+
const href = item._links?.parent?.href ?? '';
|
|
245
|
+
const key = href.includes('/') ? href.slice(href.lastIndexOf('/') + 1) : '';
|
|
246
|
+
if (!key)
|
|
247
|
+
continue;
|
|
248
|
+
/* v8 ignore stop */
|
|
249
|
+
out.set(key, {
|
|
250
|
+
name: item.name,
|
|
251
|
+
lastRequested: item.lastRequested ? new Date(item.lastRequested) : null,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
return out;
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
/* v8 ignore start — defensive catch for malformed JSON / schema
|
|
258
|
+
drift; not exercised by current fixtures. */
|
|
259
|
+
return null;
|
|
260
|
+
/* v8 ignore stop */
|
|
261
|
+
}
|
|
262
|
+
}
|
|
44
263
|
//# sourceMappingURL=client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/providers/launchdarkly/client.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/providers/launchdarkly/client.ts"],"names":[],"mappings":"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"}
|