@dotsetlabs/bellwether 0.10.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 +291 -0
- package/LICENSE +21 -0
- package/README.md +739 -0
- package/dist/auth/credentials.d.ts +64 -0
- package/dist/auth/credentials.js +218 -0
- package/dist/auth/index.d.ts +6 -0
- package/dist/auth/index.js +6 -0
- package/dist/auth/keychain.d.ts +64 -0
- package/dist/auth/keychain.js +268 -0
- package/dist/baseline/ab-testing.d.ts +80 -0
- package/dist/baseline/ab-testing.js +236 -0
- package/dist/baseline/ai-compatibility-scorer.d.ts +95 -0
- package/dist/baseline/ai-compatibility-scorer.js +606 -0
- package/dist/baseline/calibration.d.ts +77 -0
- package/dist/baseline/calibration.js +136 -0
- package/dist/baseline/category-matching.d.ts +85 -0
- package/dist/baseline/category-matching.js +289 -0
- package/dist/baseline/change-impact-analyzer.d.ts +98 -0
- package/dist/baseline/change-impact-analyzer.js +592 -0
- package/dist/baseline/comparator.d.ts +64 -0
- package/dist/baseline/comparator.js +916 -0
- package/dist/baseline/confidence.d.ts +55 -0
- package/dist/baseline/confidence.js +122 -0
- package/dist/baseline/converter.d.ts +61 -0
- package/dist/baseline/converter.js +585 -0
- package/dist/baseline/dependency-analyzer.d.ts +89 -0
- package/dist/baseline/dependency-analyzer.js +567 -0
- package/dist/baseline/deprecation-tracker.d.ts +133 -0
- package/dist/baseline/deprecation-tracker.js +322 -0
- package/dist/baseline/diff.d.ts +55 -0
- package/dist/baseline/diff.js +1584 -0
- package/dist/baseline/documentation-scorer.d.ts +205 -0
- package/dist/baseline/documentation-scorer.js +466 -0
- package/dist/baseline/embeddings.d.ts +118 -0
- package/dist/baseline/embeddings.js +251 -0
- package/dist/baseline/error-analyzer.d.ts +198 -0
- package/dist/baseline/error-analyzer.js +721 -0
- package/dist/baseline/evaluation/evaluator.d.ts +42 -0
- package/dist/baseline/evaluation/evaluator.js +323 -0
- package/dist/baseline/evaluation/expanded-dataset.d.ts +45 -0
- package/dist/baseline/evaluation/expanded-dataset.js +1164 -0
- package/dist/baseline/evaluation/golden-dataset.d.ts +58 -0
- package/dist/baseline/evaluation/golden-dataset.js +717 -0
- package/dist/baseline/evaluation/index.d.ts +15 -0
- package/dist/baseline/evaluation/index.js +15 -0
- package/dist/baseline/evaluation/types.d.ts +186 -0
- package/dist/baseline/evaluation/types.js +8 -0
- package/dist/baseline/external-dependency-detector.d.ts +181 -0
- package/dist/baseline/external-dependency-detector.js +524 -0
- package/dist/baseline/golden-output.d.ts +162 -0
- package/dist/baseline/golden-output.js +636 -0
- package/dist/baseline/health-scorer.d.ts +174 -0
- package/dist/baseline/health-scorer.js +451 -0
- package/dist/baseline/incremental-checker.d.ts +97 -0
- package/dist/baseline/incremental-checker.js +174 -0
- package/dist/baseline/index.d.ts +31 -0
- package/dist/baseline/index.js +42 -0
- package/dist/baseline/migration-generator.d.ts +137 -0
- package/dist/baseline/migration-generator.js +554 -0
- package/dist/baseline/migrations.d.ts +60 -0
- package/dist/baseline/migrations.js +197 -0
- package/dist/baseline/performance-tracker.d.ts +214 -0
- package/dist/baseline/performance-tracker.js +577 -0
- package/dist/baseline/pr-comment-generator.d.ts +117 -0
- package/dist/baseline/pr-comment-generator.js +546 -0
- package/dist/baseline/response-fingerprint.d.ts +127 -0
- package/dist/baseline/response-fingerprint.js +728 -0
- package/dist/baseline/response-schema-tracker.d.ts +129 -0
- package/dist/baseline/response-schema-tracker.js +420 -0
- package/dist/baseline/risk-scorer.d.ts +54 -0
- package/dist/baseline/risk-scorer.js +434 -0
- package/dist/baseline/saver.d.ts +89 -0
- package/dist/baseline/saver.js +554 -0
- package/dist/baseline/scenario-generator.d.ts +151 -0
- package/dist/baseline/scenario-generator.js +905 -0
- package/dist/baseline/schema-compare.d.ts +86 -0
- package/dist/baseline/schema-compare.js +557 -0
- package/dist/baseline/schema-evolution.d.ts +189 -0
- package/dist/baseline/schema-evolution.js +467 -0
- package/dist/baseline/semantic.d.ts +203 -0
- package/dist/baseline/semantic.js +908 -0
- package/dist/baseline/synonyms.d.ts +60 -0
- package/dist/baseline/synonyms.js +386 -0
- package/dist/baseline/telemetry.d.ts +165 -0
- package/dist/baseline/telemetry.js +294 -0
- package/dist/baseline/test-pruner.d.ts +120 -0
- package/dist/baseline/test-pruner.js +387 -0
- package/dist/baseline/types.d.ts +449 -0
- package/dist/baseline/types.js +5 -0
- package/dist/baseline/version.d.ts +138 -0
- package/dist/baseline/version.js +206 -0
- package/dist/cache/index.d.ts +5 -0
- package/dist/cache/index.js +5 -0
- package/dist/cache/response-cache.d.ts +151 -0
- package/dist/cache/response-cache.js +287 -0
- package/dist/ci/index.d.ts +60 -0
- package/dist/ci/index.js +342 -0
- package/dist/cli/commands/auth.d.ts +12 -0
- package/dist/cli/commands/auth.js +352 -0
- package/dist/cli/commands/badge.d.ts +3 -0
- package/dist/cli/commands/badge.js +74 -0
- package/dist/cli/commands/baseline-accept.d.ts +15 -0
- package/dist/cli/commands/baseline-accept.js +178 -0
- package/dist/cli/commands/baseline-migrate.d.ts +12 -0
- package/dist/cli/commands/baseline-migrate.js +164 -0
- package/dist/cli/commands/baseline.d.ts +14 -0
- package/dist/cli/commands/baseline.js +449 -0
- package/dist/cli/commands/beta.d.ts +10 -0
- package/dist/cli/commands/beta.js +231 -0
- package/dist/cli/commands/check.d.ts +11 -0
- package/dist/cli/commands/check.js +820 -0
- package/dist/cli/commands/cloud/badge.d.ts +3 -0
- package/dist/cli/commands/cloud/badge.js +74 -0
- package/dist/cli/commands/cloud/diff.d.ts +6 -0
- package/dist/cli/commands/cloud/diff.js +79 -0
- package/dist/cli/commands/cloud/history.d.ts +6 -0
- package/dist/cli/commands/cloud/history.js +102 -0
- package/dist/cli/commands/cloud/link.d.ts +9 -0
- package/dist/cli/commands/cloud/link.js +119 -0
- package/dist/cli/commands/cloud/login.d.ts +7 -0
- package/dist/cli/commands/cloud/login.js +499 -0
- package/dist/cli/commands/cloud/projects.d.ts +6 -0
- package/dist/cli/commands/cloud/projects.js +44 -0
- package/dist/cli/commands/cloud/shared.d.ts +7 -0
- package/dist/cli/commands/cloud/shared.js +42 -0
- package/dist/cli/commands/cloud/teams.d.ts +8 -0
- package/dist/cli/commands/cloud/teams.js +169 -0
- package/dist/cli/commands/cloud/upload.d.ts +8 -0
- package/dist/cli/commands/cloud/upload.js +181 -0
- package/dist/cli/commands/contract.d.ts +11 -0
- package/dist/cli/commands/contract.js +280 -0
- package/dist/cli/commands/discover.d.ts +3 -0
- package/dist/cli/commands/discover.js +82 -0
- package/dist/cli/commands/eval.d.ts +9 -0
- package/dist/cli/commands/eval.js +187 -0
- package/dist/cli/commands/explore.d.ts +11 -0
- package/dist/cli/commands/explore.js +437 -0
- package/dist/cli/commands/feedback.d.ts +9 -0
- package/dist/cli/commands/feedback.js +174 -0
- package/dist/cli/commands/golden.d.ts +12 -0
- package/dist/cli/commands/golden.js +407 -0
- package/dist/cli/commands/history.d.ts +10 -0
- package/dist/cli/commands/history.js +202 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.js +219 -0
- package/dist/cli/commands/interview.d.ts +3 -0
- package/dist/cli/commands/interview.js +903 -0
- package/dist/cli/commands/link.d.ts +10 -0
- package/dist/cli/commands/link.js +169 -0
- package/dist/cli/commands/login.d.ts +7 -0
- package/dist/cli/commands/login.js +499 -0
- package/dist/cli/commands/preset.d.ts +33 -0
- package/dist/cli/commands/preset.js +297 -0
- package/dist/cli/commands/profile.d.ts +33 -0
- package/dist/cli/commands/profile.js +286 -0
- package/dist/cli/commands/registry.d.ts +11 -0
- package/dist/cli/commands/registry.js +146 -0
- package/dist/cli/commands/shared.d.ts +79 -0
- package/dist/cli/commands/shared.js +196 -0
- package/dist/cli/commands/teams.d.ts +8 -0
- package/dist/cli/commands/teams.js +169 -0
- package/dist/cli/commands/test.d.ts +9 -0
- package/dist/cli/commands/test.js +500 -0
- package/dist/cli/commands/upload.d.ts +8 -0
- package/dist/cli/commands/upload.js +223 -0
- package/dist/cli/commands/validate-config.d.ts +6 -0
- package/dist/cli/commands/validate-config.js +35 -0
- package/dist/cli/commands/verify.d.ts +11 -0
- package/dist/cli/commands/verify.js +283 -0
- package/dist/cli/commands/watch.d.ts +12 -0
- package/dist/cli/commands/watch.js +253 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +178 -0
- package/dist/cli/interactive.d.ts +47 -0
- package/dist/cli/interactive.js +216 -0
- package/dist/cli/output/terminal-reporter.d.ts +19 -0
- package/dist/cli/output/terminal-reporter.js +104 -0
- package/dist/cli/output.d.ts +226 -0
- package/dist/cli/output.js +438 -0
- package/dist/cli/utils/env.d.ts +5 -0
- package/dist/cli/utils/env.js +14 -0
- package/dist/cli/utils/progress.d.ts +59 -0
- package/dist/cli/utils/progress.js +206 -0
- package/dist/cli/utils/server-context.d.ts +10 -0
- package/dist/cli/utils/server-context.js +36 -0
- package/dist/cloud/auth.d.ts +144 -0
- package/dist/cloud/auth.js +374 -0
- package/dist/cloud/client.d.ts +24 -0
- package/dist/cloud/client.js +65 -0
- package/dist/cloud/http-client.d.ts +38 -0
- package/dist/cloud/http-client.js +215 -0
- package/dist/cloud/index.d.ts +23 -0
- package/dist/cloud/index.js +25 -0
- package/dist/cloud/mock-client.d.ts +107 -0
- package/dist/cloud/mock-client.js +545 -0
- package/dist/cloud/types.d.ts +515 -0
- package/dist/cloud/types.js +15 -0
- package/dist/config/defaults.d.ts +160 -0
- package/dist/config/defaults.js +169 -0
- package/dist/config/loader.d.ts +24 -0
- package/dist/config/loader.js +122 -0
- package/dist/config/template.d.ts +42 -0
- package/dist/config/template.js +647 -0
- package/dist/config/validator.d.ts +2112 -0
- package/dist/config/validator.js +658 -0
- package/dist/constants/cloud.d.ts +107 -0
- package/dist/constants/cloud.js +110 -0
- package/dist/constants/core.d.ts +521 -0
- package/dist/constants/core.js +556 -0
- package/dist/constants/testing.d.ts +1283 -0
- package/dist/constants/testing.js +1568 -0
- package/dist/constants.d.ts +10 -0
- package/dist/constants.js +10 -0
- package/dist/contract/index.d.ts +6 -0
- package/dist/contract/index.js +5 -0
- package/dist/contract/validator.d.ts +177 -0
- package/dist/contract/validator.js +574 -0
- package/dist/cost/index.d.ts +6 -0
- package/dist/cost/index.js +5 -0
- package/dist/cost/tracker.d.ts +134 -0
- package/dist/cost/tracker.js +313 -0
- package/dist/discovery/discovery.d.ts +16 -0
- package/dist/discovery/discovery.js +173 -0
- package/dist/discovery/types.d.ts +51 -0
- package/dist/discovery/types.js +2 -0
- package/dist/docs/agents.d.ts +3 -0
- package/dist/docs/agents.js +995 -0
- package/dist/docs/contract.d.ts +51 -0
- package/dist/docs/contract.js +1681 -0
- package/dist/docs/generator.d.ts +4 -0
- package/dist/docs/generator.js +4 -0
- package/dist/docs/html-reporter.d.ts +9 -0
- package/dist/docs/html-reporter.js +757 -0
- package/dist/docs/index.d.ts +10 -0
- package/dist/docs/index.js +11 -0
- package/dist/docs/junit-reporter.d.ts +18 -0
- package/dist/docs/junit-reporter.js +210 -0
- package/dist/docs/report.d.ts +14 -0
- package/dist/docs/report.js +44 -0
- package/dist/docs/sarif-reporter.d.ts +19 -0
- package/dist/docs/sarif-reporter.js +335 -0
- package/dist/docs/shared.d.ts +35 -0
- package/dist/docs/shared.js +162 -0
- package/dist/docs/templates.d.ts +12 -0
- package/dist/docs/templates.js +76 -0
- package/dist/errors/index.d.ts +6 -0
- package/dist/errors/index.js +6 -0
- package/dist/errors/retry.d.ts +92 -0
- package/dist/errors/retry.js +323 -0
- package/dist/errors/types.d.ts +321 -0
- package/dist/errors/types.js +584 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +32 -0
- package/dist/interview/dependency-resolver.d.ts +11 -0
- package/dist/interview/dependency-resolver.js +32 -0
- package/dist/interview/interviewer.d.ts +232 -0
- package/dist/interview/interviewer.js +1939 -0
- package/dist/interview/mock-response-generator.d.ts +7 -0
- package/dist/interview/mock-response-generator.js +102 -0
- package/dist/interview/orchestrator.d.ts +237 -0
- package/dist/interview/orchestrator.js +1296 -0
- package/dist/interview/rate-limiter.d.ts +15 -0
- package/dist/interview/rate-limiter.js +55 -0
- package/dist/interview/response-validator.d.ts +10 -0
- package/dist/interview/response-validator.js +132 -0
- package/dist/interview/schema-inferrer.d.ts +8 -0
- package/dist/interview/schema-inferrer.js +71 -0
- package/dist/interview/schema-test-generator.d.ts +71 -0
- package/dist/interview/schema-test-generator.js +834 -0
- package/dist/interview/smart-value-generator.d.ts +155 -0
- package/dist/interview/smart-value-generator.js +554 -0
- package/dist/interview/stateful-test-runner.d.ts +19 -0
- package/dist/interview/stateful-test-runner.js +106 -0
- package/dist/interview/types.d.ts +561 -0
- package/dist/interview/types.js +2 -0
- package/dist/llm/anthropic.d.ts +41 -0
- package/dist/llm/anthropic.js +355 -0
- package/dist/llm/client.d.ts +123 -0
- package/dist/llm/client.js +42 -0
- package/dist/llm/factory.d.ts +38 -0
- package/dist/llm/factory.js +145 -0
- package/dist/llm/fallback.d.ts +140 -0
- package/dist/llm/fallback.js +379 -0
- package/dist/llm/index.d.ts +18 -0
- package/dist/llm/index.js +15 -0
- package/dist/llm/ollama.d.ts +37 -0
- package/dist/llm/ollama.js +330 -0
- package/dist/llm/openai.d.ts +25 -0
- package/dist/llm/openai.js +320 -0
- package/dist/llm/token-budget.d.ts +161 -0
- package/dist/llm/token-budget.js +395 -0
- package/dist/logging/logger.d.ts +70 -0
- package/dist/logging/logger.js +130 -0
- package/dist/metrics/collector.d.ts +106 -0
- package/dist/metrics/collector.js +547 -0
- package/dist/metrics/index.d.ts +7 -0
- package/dist/metrics/index.js +7 -0
- package/dist/metrics/prometheus.d.ts +20 -0
- package/dist/metrics/prometheus.js +241 -0
- package/dist/metrics/types.d.ts +209 -0
- package/dist/metrics/types.js +5 -0
- package/dist/persona/builtins.d.ts +54 -0
- package/dist/persona/builtins.js +219 -0
- package/dist/persona/index.d.ts +8 -0
- package/dist/persona/index.js +8 -0
- package/dist/persona/loader.d.ts +30 -0
- package/dist/persona/loader.js +190 -0
- package/dist/persona/types.d.ts +144 -0
- package/dist/persona/types.js +5 -0
- package/dist/persona/validation.d.ts +94 -0
- package/dist/persona/validation.js +332 -0
- package/dist/prompts/index.d.ts +5 -0
- package/dist/prompts/index.js +5 -0
- package/dist/prompts/templates.d.ts +180 -0
- package/dist/prompts/templates.js +431 -0
- package/dist/registry/client.d.ts +49 -0
- package/dist/registry/client.js +191 -0
- package/dist/registry/index.d.ts +7 -0
- package/dist/registry/index.js +6 -0
- package/dist/registry/types.d.ts +140 -0
- package/dist/registry/types.js +6 -0
- package/dist/scenarios/evaluator.d.ts +43 -0
- package/dist/scenarios/evaluator.js +206 -0
- package/dist/scenarios/index.d.ts +10 -0
- package/dist/scenarios/index.js +9 -0
- package/dist/scenarios/loader.d.ts +20 -0
- package/dist/scenarios/loader.js +285 -0
- package/dist/scenarios/types.d.ts +153 -0
- package/dist/scenarios/types.js +8 -0
- package/dist/security/index.d.ts +17 -0
- package/dist/security/index.js +18 -0
- package/dist/security/payloads.d.ts +61 -0
- package/dist/security/payloads.js +268 -0
- package/dist/security/security-tester.d.ts +42 -0
- package/dist/security/security-tester.js +582 -0
- package/dist/security/types.d.ts +166 -0
- package/dist/security/types.js +8 -0
- package/dist/transport/base-transport.d.ts +59 -0
- package/dist/transport/base-transport.js +38 -0
- package/dist/transport/http-transport.d.ts +67 -0
- package/dist/transport/http-transport.js +238 -0
- package/dist/transport/mcp-client.d.ts +141 -0
- package/dist/transport/mcp-client.js +496 -0
- package/dist/transport/sse-transport.d.ts +88 -0
- package/dist/transport/sse-transport.js +316 -0
- package/dist/transport/stdio-transport.d.ts +43 -0
- package/dist/transport/stdio-transport.js +238 -0
- package/dist/transport/types.d.ts +125 -0
- package/dist/transport/types.js +16 -0
- package/dist/utils/concurrency.d.ts +123 -0
- package/dist/utils/concurrency.js +213 -0
- package/dist/utils/formatters.d.ts +16 -0
- package/dist/utils/formatters.js +37 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/jsonpath.d.ts +87 -0
- package/dist/utils/jsonpath.js +326 -0
- package/dist/utils/markdown.d.ts +113 -0
- package/dist/utils/markdown.js +265 -0
- package/dist/utils/network.d.ts +14 -0
- package/dist/utils/network.js +17 -0
- package/dist/utils/sanitize.d.ts +92 -0
- package/dist/utils/sanitize.js +191 -0
- package/dist/utils/semantic.d.ts +194 -0
- package/dist/utils/semantic.js +1051 -0
- package/dist/utils/smart-truncate.d.ts +94 -0
- package/dist/utils/smart-truncate.js +361 -0
- package/dist/utils/timeout.d.ts +153 -0
- package/dist/utils/timeout.js +205 -0
- package/dist/utils/yaml-parser.d.ts +58 -0
- package/dist/utils/yaml-parser.js +86 -0
- package/dist/validation/index.d.ts +32 -0
- package/dist/validation/index.js +32 -0
- package/dist/validation/semantic-test-generator.d.ts +50 -0
- package/dist/validation/semantic-test-generator.js +176 -0
- package/dist/validation/semantic-types.d.ts +66 -0
- package/dist/validation/semantic-types.js +94 -0
- package/dist/validation/semantic-validator.d.ts +38 -0
- package/dist/validation/semantic-validator.js +340 -0
- package/dist/verification/index.d.ts +6 -0
- package/dist/verification/index.js +5 -0
- package/dist/verification/types.d.ts +133 -0
- package/dist/verification/types.js +5 -0
- package/dist/verification/verifier.d.ts +30 -0
- package/dist/verification/verifier.js +309 -0
- package/dist/version.d.ts +19 -0
- package/dist/version.js +48 -0
- package/dist/workflow/auto-generator.d.ts +27 -0
- package/dist/workflow/auto-generator.js +513 -0
- package/dist/workflow/discovery.d.ts +40 -0
- package/dist/workflow/discovery.js +195 -0
- package/dist/workflow/executor.d.ts +82 -0
- package/dist/workflow/executor.js +611 -0
- package/dist/workflow/index.d.ts +10 -0
- package/dist/workflow/index.js +10 -0
- package/dist/workflow/loader.d.ts +24 -0
- package/dist/workflow/loader.js +194 -0
- package/dist/workflow/state-tracker.d.ts +98 -0
- package/dist/workflow/state-tracker.js +424 -0
- package/dist/workflow/types.d.ts +337 -0
- package/dist/workflow/types.js +5 -0
- package/package.json +94 -0
- package/schemas/bellwether-check.schema.json +651 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock cloud client for LOCAL DEVELOPMENT AND TESTING ONLY.
|
|
3
|
+
*
|
|
4
|
+
* ⚠️ WARNING: This is NOT a production implementation!
|
|
5
|
+
*
|
|
6
|
+
* This mock client:
|
|
7
|
+
* - Stores data locally in ~/.bellwether/mock-cloud/ as JSON files
|
|
8
|
+
* - Simulates cloud API responses for development purposes
|
|
9
|
+
* - Does NOT sync data to any remote server
|
|
10
|
+
* - Should ONLY be used with mock sessions (sess_mock_*)
|
|
11
|
+
*
|
|
12
|
+
* For production use, connect to the real Bellwether Cloud API.
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* bellwether login --mock # Creates a mock session for development
|
|
16
|
+
*/
|
|
17
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync, readdirSync } from 'fs';
|
|
18
|
+
import { join } from 'path';
|
|
19
|
+
import { homedir } from 'os';
|
|
20
|
+
import { randomBytes } from 'crypto';
|
|
21
|
+
import { isMockSession, MOCK_SESSION_PREFIX } from './auth.js';
|
|
22
|
+
import * as output from '../cli/output.js';
|
|
23
|
+
import { TIME_CONSTANTS } from '../constants.js';
|
|
24
|
+
/**
|
|
25
|
+
* Directory for mock cloud storage.
|
|
26
|
+
*/
|
|
27
|
+
const MOCK_DATA_DIR = join(homedir(), '.bellwether', 'mock-cloud');
|
|
28
|
+
/**
|
|
29
|
+
* File for storing projects.
|
|
30
|
+
*/
|
|
31
|
+
const PROJECTS_FILE = 'projects.json';
|
|
32
|
+
/**
|
|
33
|
+
* Generate a unique ID using cryptographically secure random bytes.
|
|
34
|
+
* Format: {prefix}_{timestamp}_{random}
|
|
35
|
+
* Example: proj_1a2b3c4d_e5f6a7b8
|
|
36
|
+
*/
|
|
37
|
+
function generateId(prefix) {
|
|
38
|
+
const timestamp = Date.now().toString(36);
|
|
39
|
+
const random = randomBytes(8).toString('hex');
|
|
40
|
+
return `${prefix}_${timestamp}_${random}`;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Mock cloud client implementation for development and testing.
|
|
44
|
+
*
|
|
45
|
+
* ⚠️ DEVELOPMENT ONLY - NOT FOR PRODUCTION USE!
|
|
46
|
+
*
|
|
47
|
+
* This client:
|
|
48
|
+
* - Stores all data locally in ~/.bellwether/mock-cloud/
|
|
49
|
+
* - Provides a full implementation of the BellwetherCloudClient interface
|
|
50
|
+
* - Does NOT communicate with any remote servers
|
|
51
|
+
* - Should only be used with mock sessions (generated via `bellwether login --mock`)
|
|
52
|
+
*
|
|
53
|
+
* Features that work differently in mock mode:
|
|
54
|
+
* - Badge URLs point to shields.io for display purposes only
|
|
55
|
+
* - Project URLs are local file:// paths
|
|
56
|
+
* - No data synchronization across machines
|
|
57
|
+
*
|
|
58
|
+
* For production deployments, use the real CloudClient with proper authentication.
|
|
59
|
+
*/
|
|
60
|
+
export class MockCloudClient {
|
|
61
|
+
dataDir;
|
|
62
|
+
sessionToken;
|
|
63
|
+
/**
|
|
64
|
+
* Create a new MockCloudClient.
|
|
65
|
+
*
|
|
66
|
+
* @param sessionToken - A mock session token (must start with 'sess_mock_')
|
|
67
|
+
*/
|
|
68
|
+
constructor(sessionToken) {
|
|
69
|
+
this.dataDir = MOCK_DATA_DIR;
|
|
70
|
+
this.sessionToken = sessionToken ?? null;
|
|
71
|
+
this.ensureDataDir();
|
|
72
|
+
// Log warning if used with non-mock session
|
|
73
|
+
if (sessionToken && !isMockSession(sessionToken)) {
|
|
74
|
+
output.warn('Warning: MockCloudClient instantiated with non-mock session token.');
|
|
75
|
+
output.warn('This client stores data locally and does not sync to the cloud.');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Ensure the mock data directory exists.
|
|
80
|
+
*/
|
|
81
|
+
ensureDataDir() {
|
|
82
|
+
if (!existsSync(this.dataDir)) {
|
|
83
|
+
mkdirSync(this.dataDir, { recursive: true });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get path to projects file.
|
|
88
|
+
*/
|
|
89
|
+
get projectsFile() {
|
|
90
|
+
return join(this.dataDir, PROJECTS_FILE);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get path to baselines file for a project.
|
|
94
|
+
*/
|
|
95
|
+
getBaselinesFile(projectId) {
|
|
96
|
+
return join(this.dataDir, `${projectId}-baselines.json`);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get path to a specific baseline data file.
|
|
100
|
+
*/
|
|
101
|
+
getBaselineDataFile(baselineId) {
|
|
102
|
+
return join(this.dataDir, `${baselineId}.json`);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Load projects from storage.
|
|
106
|
+
*/
|
|
107
|
+
loadProjects() {
|
|
108
|
+
if (!existsSync(this.projectsFile)) {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const content = readFileSync(this.projectsFile, 'utf-8');
|
|
113
|
+
return JSON.parse(content);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Save projects to storage.
|
|
121
|
+
*/
|
|
122
|
+
saveProjects(projects) {
|
|
123
|
+
writeFileSync(this.projectsFile, JSON.stringify(projects, null, 2));
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Load baselines for a project.
|
|
127
|
+
*/
|
|
128
|
+
loadBaselines(projectId) {
|
|
129
|
+
const file = this.getBaselinesFile(projectId);
|
|
130
|
+
if (!existsSync(file)) {
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
const content = readFileSync(file, 'utf-8');
|
|
135
|
+
return JSON.parse(content);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Save baselines for a project.
|
|
143
|
+
*/
|
|
144
|
+
saveBaselines(projectId, baselines) {
|
|
145
|
+
const file = this.getBaselinesFile(projectId);
|
|
146
|
+
writeFileSync(file, JSON.stringify(baselines, null, 2));
|
|
147
|
+
}
|
|
148
|
+
// ============================================================================
|
|
149
|
+
// BellwetherCloudClient Implementation
|
|
150
|
+
// ============================================================================
|
|
151
|
+
isAuthenticated() {
|
|
152
|
+
if (!this.sessionToken) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
// For mock client, accept any mock session
|
|
156
|
+
return isMockSession(this.sessionToken);
|
|
157
|
+
}
|
|
158
|
+
async whoami() {
|
|
159
|
+
if (!this.isAuthenticated()) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
// Extract "user" from mock session for display
|
|
163
|
+
// Session format: sess_mock_<user>_<random>
|
|
164
|
+
const session = this.sessionToken ?? '';
|
|
165
|
+
const parts = session.split('_');
|
|
166
|
+
const user = parts.length >= 3 ? parts[2] : 'developer';
|
|
167
|
+
return {
|
|
168
|
+
id: 'usr_mock_' + user,
|
|
169
|
+
email: `${user}@localhost`,
|
|
170
|
+
githubLogin: user,
|
|
171
|
+
githubAvatarUrl: null,
|
|
172
|
+
githubName: user,
|
|
173
|
+
plan: 'free',
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
async listProjects() {
|
|
177
|
+
if (!this.isAuthenticated()) {
|
|
178
|
+
throw new Error('Not authenticated');
|
|
179
|
+
}
|
|
180
|
+
return this.loadProjects();
|
|
181
|
+
}
|
|
182
|
+
async createProject(name, serverCommand) {
|
|
183
|
+
if (!this.isAuthenticated()) {
|
|
184
|
+
throw new Error('Not authenticated');
|
|
185
|
+
}
|
|
186
|
+
const projects = this.loadProjects();
|
|
187
|
+
const project = {
|
|
188
|
+
id: generateId('proj'),
|
|
189
|
+
name,
|
|
190
|
+
serverCommand,
|
|
191
|
+
createdAt: new Date().toISOString(),
|
|
192
|
+
isPublic: false,
|
|
193
|
+
baselineCount: 0,
|
|
194
|
+
};
|
|
195
|
+
projects.push(project);
|
|
196
|
+
this.saveProjects(projects);
|
|
197
|
+
return project;
|
|
198
|
+
}
|
|
199
|
+
async getProject(projectId) {
|
|
200
|
+
if (!this.isAuthenticated()) {
|
|
201
|
+
throw new Error('Not authenticated');
|
|
202
|
+
}
|
|
203
|
+
const projects = this.loadProjects();
|
|
204
|
+
return projects.find((p) => p.id === projectId) ?? null;
|
|
205
|
+
}
|
|
206
|
+
async deleteProject(projectId) {
|
|
207
|
+
if (!this.isAuthenticated()) {
|
|
208
|
+
throw new Error('Not authenticated');
|
|
209
|
+
}
|
|
210
|
+
const projects = this.loadProjects();
|
|
211
|
+
const index = projects.findIndex((p) => p.id === projectId);
|
|
212
|
+
if (index === -1) {
|
|
213
|
+
throw new Error(`Project not found: ${projectId}`);
|
|
214
|
+
}
|
|
215
|
+
// Remove project
|
|
216
|
+
projects.splice(index, 1);
|
|
217
|
+
this.saveProjects(projects);
|
|
218
|
+
// Clean up baselines
|
|
219
|
+
const baselinesFile = this.getBaselinesFile(projectId);
|
|
220
|
+
if (existsSync(baselinesFile)) {
|
|
221
|
+
// Delete baseline data files first
|
|
222
|
+
const baselines = this.loadBaselines(projectId);
|
|
223
|
+
for (const baseline of baselines) {
|
|
224
|
+
const dataFile = this.getBaselineDataFile(baseline.id);
|
|
225
|
+
if (existsSync(dataFile)) {
|
|
226
|
+
unlinkSync(dataFile);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
unlinkSync(baselinesFile);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async uploadBaseline(projectId, baseline) {
|
|
233
|
+
if (!this.isAuthenticated()) {
|
|
234
|
+
throw new Error('Not authenticated');
|
|
235
|
+
}
|
|
236
|
+
// Verify project exists
|
|
237
|
+
const projects = this.loadProjects();
|
|
238
|
+
const projectIndex = projects.findIndex((p) => p.id === projectId);
|
|
239
|
+
if (projectIndex === -1) {
|
|
240
|
+
throw new Error(`Project not found: ${projectId}`);
|
|
241
|
+
}
|
|
242
|
+
// Load existing baselines
|
|
243
|
+
const baselines = this.loadBaselines(projectId);
|
|
244
|
+
const version = baselines.length + 1;
|
|
245
|
+
const baselineId = generateId('bl');
|
|
246
|
+
// Create baseline version record
|
|
247
|
+
const baselineVersion = {
|
|
248
|
+
id: baselineId,
|
|
249
|
+
projectId,
|
|
250
|
+
version,
|
|
251
|
+
mode: baseline.metadata.mode,
|
|
252
|
+
uploadedAt: new Date().toISOString(),
|
|
253
|
+
cliVersion: baseline.metadata.cliVersion,
|
|
254
|
+
hash: baseline.hash,
|
|
255
|
+
// BaselineMetadata has specific typed fields, but BaselineVersion.metadata
|
|
256
|
+
// is a generic Record<string, unknown> for flexibility. Double cast required.
|
|
257
|
+
metadata: baseline.metadata,
|
|
258
|
+
};
|
|
259
|
+
// Save baseline version record
|
|
260
|
+
baselines.push(baselineVersion);
|
|
261
|
+
this.saveBaselines(projectId, baselines);
|
|
262
|
+
// Save full baseline data
|
|
263
|
+
const dataFile = this.getBaselineDataFile(baselineId);
|
|
264
|
+
writeFileSync(dataFile, JSON.stringify(baseline, null, 2));
|
|
265
|
+
// Update project
|
|
266
|
+
const project = projects[projectIndex];
|
|
267
|
+
project.baselineCount = version;
|
|
268
|
+
project.lastUploadAt = new Date().toISOString();
|
|
269
|
+
this.saveProjects(projects);
|
|
270
|
+
// Build result
|
|
271
|
+
const viewUrl = `file://${dataFile}`;
|
|
272
|
+
const diffUrl = version > 1 ? `mock://diff/${projectId}/${version - 1}/${version}` : undefined;
|
|
273
|
+
return {
|
|
274
|
+
baselineId,
|
|
275
|
+
version,
|
|
276
|
+
projectId,
|
|
277
|
+
viewUrl,
|
|
278
|
+
diffUrl,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
async getHistory(projectId, limit = 10) {
|
|
282
|
+
if (!this.isAuthenticated()) {
|
|
283
|
+
throw new Error('Not authenticated');
|
|
284
|
+
}
|
|
285
|
+
// Verify project exists
|
|
286
|
+
const project = await this.getProject(projectId);
|
|
287
|
+
if (!project) {
|
|
288
|
+
throw new Error(`Project not found: ${projectId}`);
|
|
289
|
+
}
|
|
290
|
+
const baselines = this.loadBaselines(projectId);
|
|
291
|
+
// Return most recent first, limited
|
|
292
|
+
return baselines.slice(-limit).reverse();
|
|
293
|
+
}
|
|
294
|
+
async getBaseline(baselineId) {
|
|
295
|
+
if (!this.isAuthenticated()) {
|
|
296
|
+
throw new Error('Not authenticated');
|
|
297
|
+
}
|
|
298
|
+
const dataFile = this.getBaselineDataFile(baselineId);
|
|
299
|
+
if (!existsSync(dataFile)) {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
try {
|
|
303
|
+
const content = readFileSync(dataFile, 'utf-8');
|
|
304
|
+
return JSON.parse(content);
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
async getDiff(projectId, fromVersion, toVersion) {
|
|
311
|
+
if (!this.isAuthenticated()) {
|
|
312
|
+
throw new Error('Not authenticated');
|
|
313
|
+
}
|
|
314
|
+
// Load baselines
|
|
315
|
+
const baselines = this.loadBaselines(projectId);
|
|
316
|
+
const fromBaseline = baselines.find((b) => b.version === fromVersion);
|
|
317
|
+
const toBaseline = baselines.find((b) => b.version === toVersion);
|
|
318
|
+
if (!fromBaseline || !toBaseline) {
|
|
319
|
+
throw new Error(`Baseline version not found: ${fromVersion} or ${toVersion}`);
|
|
320
|
+
}
|
|
321
|
+
// Load full baseline data
|
|
322
|
+
const fromData = await this.getBaseline(fromBaseline.id);
|
|
323
|
+
const toData = await this.getBaseline(toBaseline.id);
|
|
324
|
+
if (!fromData || !toData) {
|
|
325
|
+
throw new Error('Failed to load baseline data');
|
|
326
|
+
}
|
|
327
|
+
// Compute diff
|
|
328
|
+
return this.computeDiff(fromData, toData);
|
|
329
|
+
}
|
|
330
|
+
async getLatestDiff(projectId) {
|
|
331
|
+
if (!this.isAuthenticated()) {
|
|
332
|
+
throw new Error('Not authenticated');
|
|
333
|
+
}
|
|
334
|
+
const baselines = this.loadBaselines(projectId);
|
|
335
|
+
if (baselines.length < 2) {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
// Get last two versions
|
|
339
|
+
const toVersion = baselines[baselines.length - 1].version;
|
|
340
|
+
const fromVersion = baselines[baselines.length - 2].version;
|
|
341
|
+
return this.getDiff(projectId, fromVersion, toVersion);
|
|
342
|
+
}
|
|
343
|
+
async getBadgeInfo(projectId) {
|
|
344
|
+
// Note: Badge info is public and doesn't require authentication
|
|
345
|
+
const project = this.loadProjects().find((p) => p.id === projectId);
|
|
346
|
+
if (!project) {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
const baselines = this.loadBaselines(projectId);
|
|
350
|
+
const latestBaseline = baselines.length > 0 ? baselines[baselines.length - 1] : null;
|
|
351
|
+
// Determine status based on latest diff
|
|
352
|
+
let status = 'unknown';
|
|
353
|
+
let statusText = 'Not verified';
|
|
354
|
+
if (baselines.length === 0) {
|
|
355
|
+
status = 'unknown';
|
|
356
|
+
statusText = 'No baseline';
|
|
357
|
+
}
|
|
358
|
+
else if (baselines.length === 1) {
|
|
359
|
+
status = 'verified';
|
|
360
|
+
statusText = 'Verified';
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
// Check drift between last two versions
|
|
364
|
+
const diff = await this.getLatestDiff(projectId);
|
|
365
|
+
if (diff) {
|
|
366
|
+
if (diff.severity === 'none' || diff.severity === 'info') {
|
|
367
|
+
status = 'verified';
|
|
368
|
+
statusText = 'Stable';
|
|
369
|
+
}
|
|
370
|
+
else if (diff.severity === 'warning') {
|
|
371
|
+
status = 'drift';
|
|
372
|
+
statusText = 'Drift detected';
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
status = 'failing';
|
|
376
|
+
statusText = 'Breaking changes';
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
status = 'verified';
|
|
381
|
+
statusText = 'Verified';
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
// Badge URL - using shields.io format for mock
|
|
385
|
+
const color = status === 'verified' ? 'brightgreen' : status === 'drift' ? 'yellow' : status === 'failing' ? 'red' : 'lightgrey';
|
|
386
|
+
const badgeUrl = `https://img.shields.io/badge/bellwether-${encodeURIComponent(statusText)}-${color}`;
|
|
387
|
+
// Generate markdown
|
|
388
|
+
const projectUrl = `https://bellwether.sh/projects/${projectId}`;
|
|
389
|
+
const markdown = `[](${projectUrl})`;
|
|
390
|
+
return {
|
|
391
|
+
projectId,
|
|
392
|
+
projectName: project.name,
|
|
393
|
+
status,
|
|
394
|
+
statusText,
|
|
395
|
+
badgeUrl,
|
|
396
|
+
markdown,
|
|
397
|
+
lastVerified: latestBaseline?.uploadedAt,
|
|
398
|
+
latestVersion: latestBaseline?.version,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
async submitVerification(projectId, result, report) {
|
|
402
|
+
if (!this.isAuthenticated()) {
|
|
403
|
+
throw new Error('Not authenticated');
|
|
404
|
+
}
|
|
405
|
+
// Verify project exists
|
|
406
|
+
const project = this.loadProjects().find((p) => p.id === projectId);
|
|
407
|
+
if (!project) {
|
|
408
|
+
throw new Error(`Project not found: ${projectId}`);
|
|
409
|
+
}
|
|
410
|
+
// Generate verification ID
|
|
411
|
+
const verificationId = generateId('ver');
|
|
412
|
+
// Save verification data to mock storage
|
|
413
|
+
const verificationData = {
|
|
414
|
+
id: verificationId,
|
|
415
|
+
projectId,
|
|
416
|
+
...result,
|
|
417
|
+
report: report ?? null,
|
|
418
|
+
createdAt: new Date().toISOString(),
|
|
419
|
+
};
|
|
420
|
+
const verificationFile = join(this.dataDir, `${verificationId}.json`);
|
|
421
|
+
writeFileSync(verificationFile, JSON.stringify(verificationData, null, 2));
|
|
422
|
+
// Also save to a verifications list file for the project
|
|
423
|
+
const verificationsFile = join(this.dataDir, `${projectId}-verifications.json`);
|
|
424
|
+
let verifications = [];
|
|
425
|
+
if (existsSync(verificationsFile)) {
|
|
426
|
+
try {
|
|
427
|
+
verifications = JSON.parse(readFileSync(verificationsFile, 'utf-8'));
|
|
428
|
+
}
|
|
429
|
+
catch {
|
|
430
|
+
verifications = [];
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
verifications.push({ id: verificationId, createdAt: verificationData.createdAt });
|
|
434
|
+
writeFileSync(verificationsFile, JSON.stringify(verifications, null, 2));
|
|
435
|
+
return {
|
|
436
|
+
verificationId,
|
|
437
|
+
projectId,
|
|
438
|
+
viewUrl: `file://${verificationFile}`,
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
// ============================================================================
|
|
442
|
+
// Diff Computation
|
|
443
|
+
// ============================================================================
|
|
444
|
+
/**
|
|
445
|
+
* Compute diff between two baselines.
|
|
446
|
+
*/
|
|
447
|
+
computeDiff(from, to) {
|
|
448
|
+
// Quick check - if hashes match, no changes
|
|
449
|
+
if (from.hash === to.hash) {
|
|
450
|
+
return {
|
|
451
|
+
severity: 'none',
|
|
452
|
+
toolsAdded: 0,
|
|
453
|
+
toolsRemoved: 0,
|
|
454
|
+
toolsModified: 0,
|
|
455
|
+
behaviorChanges: 0,
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
// Get tool names
|
|
459
|
+
const fromTools = new Set(from.capabilities.tools.map((t) => t.name));
|
|
460
|
+
const toTools = new Set(to.capabilities.tools.map((t) => t.name));
|
|
461
|
+
// Count additions and removals
|
|
462
|
+
const toolsAdded = [...toTools].filter((t) => !fromTools.has(t)).length;
|
|
463
|
+
const toolsRemoved = [...fromTools].filter((t) => !toTools.has(t)).length;
|
|
464
|
+
// Count modifications (tools in both with different schema hash)
|
|
465
|
+
let toolsModified = 0;
|
|
466
|
+
const fromToolMap = new Map(from.capabilities.tools.map((t) => [t.name, t]));
|
|
467
|
+
const toToolMap = new Map(to.capabilities.tools.map((t) => [t.name, t]));
|
|
468
|
+
for (const [name, fromTool] of fromToolMap) {
|
|
469
|
+
const toTool = toToolMap.get(name);
|
|
470
|
+
if (toTool && fromTool.schemaHash !== toTool.schemaHash) {
|
|
471
|
+
toolsModified++;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
// Count behavior changes from assertions
|
|
475
|
+
const fromAssertions = new Set(from.assertions.map((a) => `${a.tool}:${a.condition}`));
|
|
476
|
+
const toAssertions = new Set(to.assertions.map((a) => `${a.tool}:${a.condition}`));
|
|
477
|
+
let behaviorChanges = 0;
|
|
478
|
+
for (const a of toAssertions) {
|
|
479
|
+
if (!fromAssertions.has(a)) {
|
|
480
|
+
behaviorChanges++;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
for (const a of fromAssertions) {
|
|
484
|
+
if (!toAssertions.has(a)) {
|
|
485
|
+
behaviorChanges++;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
// Determine severity
|
|
489
|
+
let severity = 'none';
|
|
490
|
+
if (toolsRemoved > 0) {
|
|
491
|
+
severity = 'breaking';
|
|
492
|
+
}
|
|
493
|
+
else if (toolsModified > 0 || behaviorChanges > 5) {
|
|
494
|
+
severity = 'warning';
|
|
495
|
+
}
|
|
496
|
+
else if (toolsAdded > 0 || behaviorChanges > 0) {
|
|
497
|
+
severity = 'info';
|
|
498
|
+
}
|
|
499
|
+
return {
|
|
500
|
+
severity,
|
|
501
|
+
toolsAdded,
|
|
502
|
+
toolsRemoved,
|
|
503
|
+
toolsModified,
|
|
504
|
+
behaviorChanges,
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Generate a mock session for development.
|
|
510
|
+
*/
|
|
511
|
+
export function generateMockSession(username = 'dev') {
|
|
512
|
+
const random = randomBytes(16).toString('hex');
|
|
513
|
+
const sessionToken = `${MOCK_SESSION_PREFIX}${username}_${random}`;
|
|
514
|
+
return {
|
|
515
|
+
sessionToken,
|
|
516
|
+
user: {
|
|
517
|
+
id: `usr_mock_${username}`,
|
|
518
|
+
email: `${username}@localhost`,
|
|
519
|
+
githubLogin: username,
|
|
520
|
+
githubAvatarUrl: null,
|
|
521
|
+
githubName: username,
|
|
522
|
+
plan: 'free',
|
|
523
|
+
},
|
|
524
|
+
expiresAt: new Date(Date.now() + TIME_CONSTANTS.SESSION_EXPIRATION_MS).toISOString(), // 30 days
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Get the mock data directory path.
|
|
529
|
+
*/
|
|
530
|
+
export function getMockDataDir() {
|
|
531
|
+
return MOCK_DATA_DIR;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Clear all mock data (for testing).
|
|
535
|
+
*/
|
|
536
|
+
export function clearMockData() {
|
|
537
|
+
if (!existsSync(MOCK_DATA_DIR)) {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
const files = readdirSync(MOCK_DATA_DIR);
|
|
541
|
+
for (const file of files) {
|
|
542
|
+
unlinkSync(join(MOCK_DATA_DIR, file));
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
//# sourceMappingURL=mock-client.js.map
|