@kb-labs/qa-entry 2.14.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 (71) hide show
  1. package/README.md +1 -0
  2. package/dist/cli/commands/baseline-status.d.ts +10 -0
  3. package/dist/cli/commands/baseline-status.js +32 -0
  4. package/dist/cli/commands/baseline-status.js.map +1 -0
  5. package/dist/cli/commands/baseline-update.d.ts +10 -0
  6. package/dist/cli/commands/baseline-update.js +33 -0
  7. package/dist/cli/commands/baseline-update.js.map +1 -0
  8. package/dist/cli/commands/flags.d.ts +106 -0
  9. package/dist/cli/commands/flags.js +99 -0
  10. package/dist/cli/commands/flags.js.map +1 -0
  11. package/dist/cli/commands/qa-history.d.ts +10 -0
  12. package/dist/cli/commands/qa-history.js +41 -0
  13. package/dist/cli/commands/qa-history.js.map +1 -0
  14. package/dist/cli/commands/qa-regressions.d.ts +10 -0
  15. package/dist/cli/commands/qa-regressions.js +33 -0
  16. package/dist/cli/commands/qa-regressions.js.map +1 -0
  17. package/dist/cli/commands/qa-run.d.ts +16 -0
  18. package/dist/cli/commands/qa-run.js +159 -0
  19. package/dist/cli/commands/qa-run.js.map +1 -0
  20. package/dist/cli/commands/qa-save.d.ts +10 -0
  21. package/dist/cli/commands/qa-save.js +69 -0
  22. package/dist/cli/commands/qa-save.js.map +1 -0
  23. package/dist/cli/commands/qa-trends.d.ts +10 -0
  24. package/dist/cli/commands/qa-trends.js +35 -0
  25. package/dist/cli/commands/qa-trends.js.map +1 -0
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.js +390 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/manifest.d.ts +198 -0
  30. package/dist/manifest.js +391 -0
  31. package/dist/manifest.js.map +1 -0
  32. package/dist/rest/handlers/baseline-diff-handler.d.ts +33 -0
  33. package/dist/rest/handlers/baseline-diff-handler.js +51 -0
  34. package/dist/rest/handlers/baseline-diff-handler.js.map +1 -0
  35. package/dist/rest/handlers/baseline-handler.d.ts +19 -0
  36. package/dist/rest/handlers/baseline-handler.js +14 -0
  37. package/dist/rest/handlers/baseline-handler.js.map +1 -0
  38. package/dist/rest/handlers/baseline-update-handler.d.ts +20 -0
  39. package/dist/rest/handlers/baseline-update-handler.js +23 -0
  40. package/dist/rest/handlers/baseline-update-handler.js.map +1 -0
  41. package/dist/rest/handlers/details-handler.d.ts +61 -0
  42. package/dist/rest/handlers/details-handler.js +70 -0
  43. package/dist/rest/handlers/details-handler.js.map +1 -0
  44. package/dist/rest/handlers/error-groups-handler.d.ts +15 -0
  45. package/dist/rest/handlers/error-groups-handler.js +17 -0
  46. package/dist/rest/handlers/error-groups-handler.js.map +1 -0
  47. package/dist/rest/handlers/history-handler.d.ts +25 -0
  48. package/dist/rest/handlers/history-handler.js +22 -0
  49. package/dist/rest/handlers/history-handler.js.map +1 -0
  50. package/dist/rest/handlers/latest-handler.d.ts +22 -0
  51. package/dist/rest/handlers/latest-handler.js +17 -0
  52. package/dist/rest/handlers/latest-handler.js.map +1 -0
  53. package/dist/rest/handlers/package-timeline-handler.d.ts +26 -0
  54. package/dist/rest/handlers/package-timeline-handler.js +18 -0
  55. package/dist/rest/handlers/package-timeline-handler.js.map +1 -0
  56. package/dist/rest/handlers/regressions-handler.d.ts +16 -0
  57. package/dist/rest/handlers/regressions-handler.js +14 -0
  58. package/dist/rest/handlers/regressions-handler.js.map +1 -0
  59. package/dist/rest/handlers/run-check-handler.d.ts +20 -0
  60. package/dist/rest/handlers/run-check-handler.js +58 -0
  61. package/dist/rest/handlers/run-check-handler.js.map +1 -0
  62. package/dist/rest/handlers/run-handler.d.ts +33 -0
  63. package/dist/rest/handlers/run-handler.js +75 -0
  64. package/dist/rest/handlers/run-handler.js.map +1 -0
  65. package/dist/rest/handlers/summary-handler.d.ts +26 -0
  66. package/dist/rest/handlers/summary-handler.js +35 -0
  67. package/dist/rest/handlers/summary-handler.js.map +1 -0
  68. package/dist/rest/handlers/trends-handler.d.ts +48 -0
  69. package/dist/rest/handlers/trends-handler.js +30 -0
  70. package/dist/rest/handlers/trends-handler.js.map +1 -0
  71. package/package.json +71 -0
@@ -0,0 +1,33 @@
1
+ import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
2
+ import { RestInput } from '@kb-labs/sdk';
3
+
4
+ declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<unknown, {
5
+ skipChecks?: string[] | undefined;
6
+ saveToHistory?: boolean | undefined;
7
+ }, unknown>, {
8
+ status: "passed" | "failed";
9
+ entry: {
10
+ status: "passed" | "failed";
11
+ git: {
12
+ commit: string;
13
+ branch: string;
14
+ message: string;
15
+ };
16
+ timestamp: string;
17
+ summary: Record<string, {
18
+ passed: number;
19
+ failed: number;
20
+ skipped: number;
21
+ }>;
22
+ failedPackages: Record<string, string[]>;
23
+ } | null;
24
+ results: Record<string, {
25
+ passed: string[];
26
+ failed: string[];
27
+ skipped: string[];
28
+ errors: Record<string, string>;
29
+ }>;
30
+ durationMs: number;
31
+ }>;
32
+
33
+ export { _default as default };
@@ -0,0 +1,75 @@
1
+ import { defineHandler, useConfig } from '@kb-labs/sdk';
2
+ import { runQA, createHistoryEntry, appendEntry } from '@kb-labs/qa-core';
3
+
4
+ // src/rest/handlers/run-handler.ts
5
+ var run_handler_default = defineHandler({
6
+ async execute(ctx, input) {
7
+ const rootDir = ctx.cwd;
8
+ const startTime = Date.now();
9
+ const body = input.body;
10
+ let config;
11
+ try {
12
+ config = await Promise.race([
13
+ useConfig(),
14
+ new Promise((resolve) => {
15
+ setTimeout(() => resolve(void 0), 3e3);
16
+ })
17
+ ]);
18
+ } catch {
19
+ }
20
+ const checks = config?.checks;
21
+ const { results } = await runQA({
22
+ rootDir,
23
+ skipChecks: body?.skipChecks,
24
+ packagesConfig: config?.packages,
25
+ checks
26
+ });
27
+ const hasFailed = Object.values(results).some((r) => r.failed.length > 0);
28
+ const status = hasFailed ? "failed" : "passed";
29
+ let entry = null;
30
+ if (body?.saveToHistory !== false) {
31
+ entry = createHistoryEntry(results, rootDir);
32
+ appendEntry(rootDir, entry);
33
+ }
34
+ const durationMs = Date.now() - startTime;
35
+ const analytics = ctx.platform.analytics;
36
+ if (analytics) {
37
+ for (const ct of Object.keys(results)) {
38
+ const r = results[ct];
39
+ await analytics.track("qa.check.completed", {
40
+ checkType: ct,
41
+ status: r.failed.length > 0 ? "failed" : "passed",
42
+ passed: r.passed.length,
43
+ failed: r.failed.length,
44
+ skipped: r.skipped.length,
45
+ gitCommit: entry?.git.commit,
46
+ gitBranch: entry?.git.branch
47
+ });
48
+ }
49
+ const checkKeys = Object.keys(results);
50
+ await analytics.track("qa.run.completed", {
51
+ status,
52
+ ...Object.fromEntries(checkKeys.flatMap((ct) => [
53
+ [`${ct}Passed`, results[ct].passed.length],
54
+ [`${ct}Failed`, results[ct].failed.length]
55
+ ])),
56
+ totalPassed: checkKeys.reduce((s, ct) => s + results[ct].passed.length, 0),
57
+ totalFailed: checkKeys.reduce((s, ct) => s + results[ct].failed.length, 0),
58
+ totalSkipped: checkKeys.reduce((s, ct) => s + results[ct].skipped.length, 0),
59
+ gitCommit: entry?.git.commit,
60
+ gitBranch: entry?.git.branch,
61
+ durationMs
62
+ });
63
+ }
64
+ return {
65
+ status,
66
+ results,
67
+ entry,
68
+ durationMs
69
+ };
70
+ }
71
+ });
72
+
73
+ export { run_handler_default as default };
74
+ //# sourceMappingURL=run-handler.js.map
75
+ //# sourceMappingURL=run-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/rest/handlers/run-handler.ts"],"names":[],"mappings":"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","file":"run-handler.js","sourcesContent":["/**\n * POST /run handler\n *\n * Runs QA checks (build, lint, types, tests) and optionally saves to history.\n */\n\nimport { defineHandler, useConfig, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { runQA, createHistoryEntry, appendEntry } from '@kb-labs/qa-core';\nimport type { QARunRequest, QARunResponse, QAPluginConfig } from '@kb-labs/qa-contracts';\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<unknown, QARunRequest>,\n ): Promise<QARunResponse> {\n const rootDir = ctx.cwd;\n const startTime = Date.now();\n const body = input.body;\n\n let config: QAPluginConfig | undefined;\n try {\n config = await Promise.race([\n useConfig<QAPluginConfig>(),\n new Promise<undefined>((resolve) => { setTimeout(() => resolve(undefined), 3000); }),\n ]);\n } catch { /* no platform context */ }\n\n const checks = config?.checks;\n\n const { results } = await runQA({\n rootDir,\n skipChecks: body?.skipChecks,\n packagesConfig: config?.packages,\n checks,\n });\n\n // Determine overall status\n const hasFailed = Object.values(results).some((r) => r.failed.length > 0);\n const status = hasFailed ? 'failed' : 'passed';\n\n // Save to history unless explicitly disabled\n let entry = null;\n if (body?.saveToHistory !== false) {\n entry = createHistoryEntry(results, rootDir);\n appendEntry(rootDir, entry);\n }\n\n const durationMs = Date.now() - startTime;\n\n // Track analytics events\n const analytics = ctx.platform.analytics;\n if (analytics) {\n for (const ct of Object.keys(results)) {\n const r = results[ct]!;\n await analytics.track('qa.check.completed', {\n checkType: ct,\n status: r.failed.length > 0 ? 'failed' : 'passed',\n passed: r.passed.length,\n failed: r.failed.length,\n skipped: r.skipped.length,\n gitCommit: entry?.git.commit, gitBranch: entry?.git.branch,\n });\n }\n const checkKeys = Object.keys(results);\n await analytics.track('qa.run.completed', {\n status,\n ...Object.fromEntries(checkKeys.flatMap((ct) => [\n [`${ct}Passed`, results[ct]!.passed.length],\n [`${ct}Failed`, results[ct]!.failed.length],\n ])),\n totalPassed: checkKeys.reduce((s, ct) => s + results[ct]!.passed.length, 0),\n totalFailed: checkKeys.reduce((s, ct) => s + results[ct]!.failed.length, 0),\n totalSkipped: checkKeys.reduce((s, ct) => s + results[ct]!.skipped.length, 0),\n gitCommit: entry?.git.commit, gitBranch: entry?.git.branch,\n durationMs,\n });\n }\n\n return {\n status,\n results,\n entry,\n durationMs,\n };\n },\n});\n"]}
@@ -0,0 +1,26 @@
1
+ import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
2
+ import { RestInput } from '@kb-labs/sdk';
3
+
4
+ declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<{}, unknown, unknown>, {
5
+ status: string;
6
+ lastRunAt: string | null;
7
+ git: {
8
+ commit: string;
9
+ branch: string;
10
+ message: string;
11
+ } | null;
12
+ checks: {
13
+ passed: number;
14
+ failed: number;
15
+ skipped: number;
16
+ checkType: string;
17
+ label: string;
18
+ total: number;
19
+ icon?: string | undefined;
20
+ }[];
21
+ hasBaseline: boolean;
22
+ baselineTimestamp: string | null;
23
+ historyCount: number;
24
+ }>;
25
+
26
+ export { _default as default };
@@ -0,0 +1,35 @@
1
+ import { defineHandler } from '@kb-labs/sdk';
2
+ import { loadBaseline, loadHistory } from '@kb-labs/qa-core';
3
+ import { getCheckIcon, getCheckLabel } from '@kb-labs/qa-contracts';
4
+
5
+ // src/rest/handlers/summary-handler.ts
6
+ var summary_handler_default = defineHandler({
7
+ async execute(ctx, _input) {
8
+ const baseline = loadBaseline(ctx.cwd);
9
+ const history = loadHistory(ctx.cwd);
10
+ const latest = history.length > 0 ? history[history.length - 1] : null;
11
+ const checkKeys = latest ? Object.keys(latest.summary) : [];
12
+ const checks = checkKeys.map((ct) => ({
13
+ checkType: ct,
14
+ label: getCheckLabel(ct),
15
+ icon: getCheckIcon(ct),
16
+ passed: latest?.summary[ct]?.passed ?? 0,
17
+ failed: latest?.summary[ct]?.failed ?? 0,
18
+ skipped: latest?.summary[ct]?.skipped ?? 0,
19
+ total: (latest?.summary[ct]?.passed ?? 0) + (latest?.summary[ct]?.failed ?? 0) + (latest?.summary[ct]?.skipped ?? 0)
20
+ }));
21
+ return {
22
+ status: latest?.status ?? "unknown",
23
+ lastRunAt: latest?.timestamp ?? null,
24
+ git: latest?.git ?? null,
25
+ checks,
26
+ hasBaseline: baseline !== null,
27
+ baselineTimestamp: baseline?.timestamp ?? null,
28
+ historyCount: history.length
29
+ };
30
+ }
31
+ });
32
+
33
+ export { summary_handler_default as default };
34
+ //# sourceMappingURL=summary-handler.js.map
35
+ //# sourceMappingURL=summary-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/rest/handlers/summary-handler.ts"],"names":[],"mappings":";;;;;AAWA,IAAO,0BAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CACJ,GAAA,EACA,MAAA,EAC4B;AAC5B,IAAA,MAAM,QAAA,GAAW,YAAA,CAAa,GAAA,CAAI,GAAG,CAAA;AACrC,IAAA,MAAM,OAAA,GAAU,WAAA,CAAY,GAAA,CAAI,GAAG,CAAA;AACnC,IAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,GAAS,CAAA,GAAI,QAAQ,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAA,GAAI,IAAA;AAElE,IAAA,MAAM,YAAY,MAAA,GAAS,MAAA,CAAO,KAAK,MAAA,CAAO,OAAO,IAAI,EAAC;AAC1D,IAAA,MAAM,MAAA,GAAS,SAAA,CAAU,GAAA,CAAI,CAAC,EAAA,MAAQ;AAAA,MACpC,SAAA,EAAW,EAAA;AAAA,MACX,KAAA,EAAO,cAAc,EAAE,CAAA;AAAA,MACvB,IAAA,EAAM,aAAa,EAAE,CAAA;AAAA,MACrB,MAAA,EAAQ,MAAA,EAAQ,OAAA,CAAQ,EAAE,GAAG,MAAA,IAAU,CAAA;AAAA,MACvC,MAAA,EAAQ,MAAA,EAAQ,OAAA,CAAQ,EAAE,GAAG,MAAA,IAAU,CAAA;AAAA,MACvC,OAAA,EAAS,MAAA,EAAQ,OAAA,CAAQ,EAAE,GAAG,OAAA,IAAW,CAAA;AAAA,MACzC,QACG,MAAA,EAAQ,OAAA,CAAQ,EAAE,CAAA,EAAG,UAAU,CAAA,KAC/B,MAAA,EAAQ,OAAA,CAAQ,EAAE,GAAG,MAAA,IAAU,CAAA,CAAA,IAC/B,QAAQ,OAAA,CAAQ,EAAE,GAAG,OAAA,IAAW,CAAA;AAAA,KACrC,CAAE,CAAA;AAEF,IAAA,OAAO;AAAA,MACL,MAAA,EAAQ,QAAQ,MAAA,IAAU,SAAA;AAAA,MAC1B,SAAA,EAAW,QAAQ,SAAA,IAAa,IAAA;AAAA,MAChC,GAAA,EAAK,QAAQ,GAAA,IAAO,IAAA;AAAA,MACpB,MAAA;AAAA,MACA,aAAa,QAAA,KAAa,IAAA;AAAA,MAC1B,iBAAA,EAAmB,UAAU,SAAA,IAAa,IAAA;AAAA,MAC1C,cAAc,OAAA,CAAQ;AAAA,KACxB;AAAA,EACF;AACF,CAAC","file":"summary-handler.js","sourcesContent":["/**\n * GET /summary handler\n *\n * Aggregated QA overview: per-check pass rates, baseline info, last run status.\n */\n\nimport { defineHandler, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { loadBaseline, loadHistory } from '@kb-labs/qa-core';\nimport { getCheckLabel, getCheckIcon } from '@kb-labs/qa-contracts';\nimport type { QASummaryRequest, QASummaryResponse } from '@kb-labs/qa-contracts';\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n _input: RestInput<QASummaryRequest, unknown>,\n ): Promise<QASummaryResponse> {\n const baseline = loadBaseline(ctx.cwd);\n const history = loadHistory(ctx.cwd);\n const latest = history.length > 0 ? history[history.length - 1] : null;\n\n const checkKeys = latest ? Object.keys(latest.summary) : [];\n const checks = checkKeys.map((ct) => ({\n checkType: ct,\n label: getCheckLabel(ct),\n icon: getCheckIcon(ct),\n passed: latest?.summary[ct]?.passed ?? 0,\n failed: latest?.summary[ct]?.failed ?? 0,\n skipped: latest?.summary[ct]?.skipped ?? 0,\n total:\n (latest?.summary[ct]?.passed ?? 0) +\n (latest?.summary[ct]?.failed ?? 0) +\n (latest?.summary[ct]?.skipped ?? 0),\n }));\n\n return {\n status: latest?.status ?? 'unknown',\n lastRunAt: latest?.timestamp ?? null,\n git: latest?.git ?? null,\n checks,\n hasBaseline: baseline !== null,\n baselineTimestamp: baseline?.timestamp ?? null,\n historyCount: history.length,\n };\n },\n});\n"]}
@@ -0,0 +1,48 @@
1
+ import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
2
+ import { RestInput } from '@kb-labs/sdk';
3
+
4
+ declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<Record<string, string>, unknown, unknown>, {
5
+ historyCount: number;
6
+ window: number;
7
+ trends: {
8
+ checkType: string;
9
+ previous: number;
10
+ current: number;
11
+ delta: number;
12
+ trend: "regression" | "improvement" | "no-change";
13
+ label?: string | undefined;
14
+ icon?: string | undefined;
15
+ }[];
16
+ } | {
17
+ historyCount: number;
18
+ window: number;
19
+ trends: {
20
+ checkType: string;
21
+ previous: number;
22
+ current: number;
23
+ delta: number;
24
+ trend: "regression" | "improvement" | "no-change";
25
+ timeSeries: {
26
+ passed: number;
27
+ failed: number;
28
+ skipped: number;
29
+ timestamp: string;
30
+ gitCommit: string;
31
+ gitBranch: string;
32
+ gitMessage: string;
33
+ }[];
34
+ changelog: {
35
+ timestamp: string;
36
+ delta: number;
37
+ gitCommit: string;
38
+ gitMessage: string;
39
+ newFailures: string[];
40
+ fixed: string[];
41
+ }[];
42
+ velocity: number;
43
+ label?: string | undefined;
44
+ icon?: string | undefined;
45
+ }[];
46
+ }>;
47
+
48
+ export { _default as default };
@@ -0,0 +1,30 @@
1
+ import { defineHandler } from '@kb-labs/sdk';
2
+ import { loadHistory, analyzeEnrichedTrends, analyzeTrends } from '@kb-labs/qa-core';
3
+ import { TRENDS_WINDOW } from '@kb-labs/qa-contracts';
4
+
5
+ // src/rest/handlers/trends-handler.ts
6
+ var trends_handler_default = defineHandler({
7
+ async execute(ctx, input) {
8
+ const window = input.query?.window ? Number(input.query.window) : TRENDS_WINDOW;
9
+ const enriched = String(input.query?.enriched) === "true";
10
+ const history = loadHistory(ctx.cwd);
11
+ if (enriched) {
12
+ const trends2 = analyzeEnrichedTrends(history, window);
13
+ return {
14
+ trends: trends2,
15
+ historyCount: history.length,
16
+ window
17
+ };
18
+ }
19
+ const trends = analyzeTrends(history, window);
20
+ return {
21
+ trends,
22
+ historyCount: history.length,
23
+ window
24
+ };
25
+ }
26
+ });
27
+
28
+ export { trends_handler_default as default };
29
+ //# sourceMappingURL=trends-handler.js.map
30
+ //# sourceMappingURL=trends-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/rest/handlers/trends-handler.ts"],"names":["trends"],"mappings":";;;;;AAYA,IAAO,yBAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EACsD;AACtD,IAAA,MAAM,MAAA,GAAS,MAAM,KAAA,EAAO,MAAA,GAAS,OAAO,KAAA,CAAM,KAAA,CAAM,MAAM,CAAA,GAAI,aAAA;AAClE,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,KAAA,CAAM,KAAA,EAAO,QAAQ,CAAA,KAAM,MAAA;AACnD,IAAA,MAAM,OAAA,GAAU,WAAA,CAAY,GAAA,CAAI,GAAG,CAAA;AAEnC,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAMA,OAAAA,GAAS,qBAAA,CAAsB,OAAA,EAAS,MAAM,CAAA;AACpD,MAAA,OAAO;AAAA,QACL,MAAA,EAAAA,OAAAA;AAAA,QACA,cAAc,OAAA,CAAQ,MAAA;AAAA,QACtB;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,aAAA,CAAc,OAAA,EAAS,MAAM,CAAA;AAC5C,IAAA,OAAO;AAAA,MACL,MAAA;AAAA,MACA,cAAc,OAAA,CAAQ,MAAA;AAAA,MACtB;AAAA,KACF;AAAA,EACF;AACF,CAAC","file":"trends-handler.js","sourcesContent":["/**\n * GET /trends handler\n *\n * Analyzes QA quality trends over a sliding window.\n * Supports ?window=N and ?enriched=true for full time-series + changelog.\n */\n\nimport { defineHandler, type PluginContextV3, type RestInput } from '@kb-labs/sdk';\nimport { loadHistory, analyzeTrends, analyzeEnrichedTrends } from '@kb-labs/qa-core';\nimport { TRENDS_WINDOW } from '@kb-labs/qa-contracts';\nimport type { QATrendsResponse, QAEnrichedTrendsResponse } from '@kb-labs/qa-contracts';\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<Record<string, string>, unknown>,\n ): Promise<QATrendsResponse | QAEnrichedTrendsResponse> {\n const window = input.query?.window ? Number(input.query.window) : TRENDS_WINDOW;\n const enriched = String(input.query?.enriched) === 'true';\n const history = loadHistory(ctx.cwd);\n\n if (enriched) {\n const trends = analyzeEnrichedTrends(history, window);\n return {\n trends,\n historyCount: history.length,\n window,\n };\n }\n\n const trends = analyzeTrends(history, window);\n return {\n trends,\n historyCount: history.length,\n window,\n };\n },\n});\n"]}
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@kb-labs/qa-entry",
3
+ "version": "2.14.0",
4
+ "type": "module",
5
+ "description": "CLI commands for KB Labs QA Plugin — qa:run, qa:save, qa:history, qa:trends, qa:regressions, baseline:update, baseline:status.",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ },
13
+ "./plugin-manifest": {
14
+ "import": "./dist/manifest.js",
15
+ "types": "./dist/manifest.d.ts"
16
+ },
17
+ "./dist/*": "./dist/*"
18
+ },
19
+ "kb": {
20
+ "manifest": "./dist/manifest.js"
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "README.md",
25
+ "LICENSE"
26
+ ],
27
+ "sideEffects": false,
28
+ "dependencies": {
29
+ "zod": "latest",
30
+ "@kb-labs/qa-core": "2.14.0",
31
+ "@kb-labs/qa-contracts": "2.14.0",
32
+ "@kb-labs/plugin-contracts": "2.14.0",
33
+ "@kb-labs/sdk": "1.6.6"
34
+ },
35
+ "peerDependencies": {
36
+ "react": ">=18.0.0"
37
+ },
38
+ "devDependencies": {
39
+ "@rspack/cli": "latest",
40
+ "@rspack/core": "latest",
41
+ "@types/node": "^24.3.3",
42
+ "@types/react": "^18.3.18",
43
+ "@types/react-dom": "^18.3.5",
44
+ "react": "^18.3.1",
45
+ "react-dom": "^18.3.1",
46
+ "rimraf": "^6.0.1",
47
+ "tsup": "^8.5.0",
48
+ "typescript": "^5.6.3",
49
+ "vitest": "^3.2.4",
50
+ "@kb-labs/devkit": "2.14.0",
51
+ "@kb-labs/plugin-runtime": "2.14.0",
52
+ "@kb-labs/studio-plugin-tools": "2.14.0"
53
+ },
54
+ "engines": {
55
+ "node": ">=20.0.0",
56
+ "pnpm": ">=9.0.0"
57
+ },
58
+ "scripts": {
59
+ "pretype-check": "pnpm --filter @kb-labs/qa-entry build",
60
+ "clean": "rimraf dist",
61
+ "build": "tsup --config tsup.config.ts && pnpm build:studio",
62
+ "build:studio": "rspack build --config rspack.studio.config.mjs",
63
+ "dev": "tsup --config tsup.config.ts --watch",
64
+ "dev:studio": "rspack build --config rspack.studio.config.mjs --watch",
65
+ "lint": "eslint src --ext .ts",
66
+ "lint:fix": "eslint . --fix",
67
+ "type-check": "tsc --noEmit",
68
+ "test": "vitest run --passWithNoTests",
69
+ "test:watch": "vitest"
70
+ }
71
+ }