@alumbwe/anvil 1.0.42 → 1.0.50
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/bin/anvil.js +18 -0
- package/package.json +13 -6
- package/src/agents/bundled-agents.generated.ts +1 -1
- package/src/index.tsx +27 -4
- package/src/login/plain-login.ts +60 -0
- package/src/login/supabase-auth.ts +346 -0
- package/src/utils/anvil-client.ts +4 -0
- package/src/utils/auth.ts +16 -4
- package/src/utils/config-dir.ts +1 -1
- package/vendor/@anvil/common/src/constants/deepseek-direct.ts +30 -1
- package/vendor/@anvil/common/src/util/project-ignore.ts +4 -3
- package/vendor/@anvil/sdk/dist/index.cjs +46 -10
- package/vendor/@anvil/sdk/dist/index.mjs +46 -10
- package/src/commands/__tests__/anvil-command-aliases.test.ts +0 -56
- package/src/commands/__tests__/bash-command.test.ts +0 -445
- package/src/commands/__tests__/command-args.test.ts +0 -349
- package/src/commands/__tests__/copy-conversation-clipboard.test.ts +0 -108
- package/src/commands/__tests__/copy-conversation.test.ts +0 -226
- package/src/commands/__tests__/diagnostics-command.test.ts +0 -35
- package/src/commands/__tests__/image.test.ts +0 -99
- package/src/commands/__tests__/init.test.ts +0 -456
- package/src/commands/__tests__/new-command-rotates-chat.test.ts +0 -91
- package/src/commands/__tests__/process-diagnostics.test.ts +0 -54
- package/src/commands/__tests__/prompt-builders.test.ts +0 -28
- package/src/commands/__tests__/router-input.test.ts +0 -298
- package/src/components/__tests__/ad-banner.test.tsx +0 -83
- package/src/components/__tests__/anvil-landing-heading-row.test.tsx +0 -91
- package/src/components/__tests__/anvil-model-selector.test.tsx +0 -519
- package/src/components/__tests__/anvil-offer-invariants.test.ts +0 -54
- package/src/components/__tests__/anvil-takeover-prompt.test.tsx +0 -212
- package/src/components/__tests__/chat-input-bar.test.tsx +0 -130
- package/src/components/__tests__/grid-layout.integration.test.tsx +0 -304
- package/src/components/__tests__/grid-layout.test.tsx +0 -1051
- package/src/components/__tests__/message-block.completion.test.tsx +0 -104
- package/src/components/__tests__/message-block.streaming.test.tsx +0 -78
- package/src/components/__tests__/message-with-agents.test.tsx +0 -579
- package/src/components/__tests__/multiline-input.test.tsx +0 -1132
- package/src/components/__tests__/queue-panel.test.tsx +0 -398
- package/src/components/__tests__/selectable-list.test.ts +0 -232
- package/src/components/__tests__/status-bar.test.tsx +0 -44
- package/src/components/__tests__/status-indicator.test.tsx +0 -204
- package/src/components/__tests__/terminal-thinking-orb.test.tsx +0 -111
- package/src/components/__tests__/user-error-banner.test.tsx +0 -102
- package/src/components/ask-user/__tests__/multiple-choice-form.test.ts +0 -432
- package/src/components/ask-user/__tests__/validation.test.ts +0 -213
- package/src/components/tools/__tests__/apply-patch.test.tsx +0 -84
- package/src/components/tools/__tests__/code-search.test.tsx +0 -45
- package/src/components/tools/__tests__/gravity-index.test.ts +0 -76
- package/src/components/tools/__tests__/render-ui.test.tsx +0 -92
- package/src/components/tools/__tests__/run-terminal-command.test.ts +0 -233
- package/src/contexts/__tests__/chat-runtime-context.test.tsx +0 -149
- package/src/data/slash-commands.test.ts +0 -24
- package/src/hooks/__tests__/holds-live-anvil-slot.test.ts +0 -49
- package/src/hooks/__tests__/session-fetch-signal.test.ts +0 -63
- package/src/hooks/__tests__/use-activity-query.test.ts +0 -1000
- package/src/hooks/__tests__/use-ask-user-bridge.test.ts +0 -176
- package/src/hooks/__tests__/use-auth-query.test.ts +0 -21
- package/src/hooks/__tests__/use-chat-input-remount.test.tsx +0 -66
- package/src/hooks/__tests__/use-clipboard.test.tsx +0 -73
- package/src/hooks/__tests__/use-connection-status.test.ts +0 -112
- package/src/hooks/__tests__/use-directory-browser.test.ts +0 -203
- package/src/hooks/__tests__/use-gravity-ad.test.ts +0 -73
- package/src/hooks/__tests__/use-grid-layout.test.ts +0 -349
- package/src/hooks/__tests__/use-input-history.test.ts +0 -699
- package/src/hooks/__tests__/use-message-queue-editing.test.tsx +0 -209
- package/src/hooks/__tests__/use-message-queue.test.tsx +0 -71
- package/src/hooks/__tests__/use-path-tab-completion.test.ts +0 -315
- package/src/hooks/__tests__/use-queue-controls.test.ts +0 -68
- package/src/hooks/__tests__/use-queue-ui.test.tsx +0 -83
- package/src/hooks/__tests__/use-searchable-list.test.ts +0 -359
- package/src/hooks/__tests__/use-send-message-timer.test.ts +0 -146
- package/src/hooks/__tests__/use-suggestion-engine-mention.test.ts +0 -361
- package/src/hooks/__tests__/use-suggestion-engine.test.ts +0 -485
- package/src/hooks/__tests__/use-terminal-focus.test.ts +0 -66
- package/src/hooks/__tests__/use-terminal-layout.test.ts +0 -675
- package/src/hooks/__tests__/use-timeout.test.ts +0 -330
- package/src/hooks/__tests__/use-usage-query.test.ts +0 -502
- package/src/hooks/__tests__/use-user-details-query.test.ts +0 -195
- package/src/hooks/helpers/__tests__/send-message.test.ts +0 -1918
- package/src/init/__tests__/init-direnv.test.ts +0 -526
- package/src/state/__tests__/chat-store-focus.test.ts +0 -22
- package/src/state/__tests__/feedback-store.test.ts +0 -257
- package/src/utils/__tests__/active-run.test.ts +0 -140
- package/src/utils/__tests__/activity-tracker.test.ts +0 -440
- package/src/utils/__tests__/agent-display.test.ts +0 -139
- package/src/utils/__tests__/analytics-client.test.ts +0 -262
- package/src/utils/__tests__/anonymous-id.test.ts +0 -74
- package/src/utils/__tests__/anvil-api.test.ts +0 -578
- package/src/utils/__tests__/anvil-instance-owner.test.ts +0 -69
- package/src/utils/__tests__/anvil-model-navigation.test.ts +0 -102
- package/src/utils/__tests__/anvil-premium-reset.test.ts +0 -79
- package/src/utils/__tests__/anvil-referral-cache.test.ts +0 -116
- package/src/utils/__tests__/anvil-session-api.test.ts +0 -215
- package/src/utils/__tests__/anvil-session-display.test.ts +0 -23
- package/src/utils/__tests__/anvil-streak-line.test.ts +0 -217
- package/src/utils/__tests__/arrays.test.ts +0 -264
- package/src/utils/__tests__/bash-context-processor.test.ts +0 -38
- package/src/utils/__tests__/block-processor.test.ts +0 -810
- package/src/utils/__tests__/chat-history.test.ts +0 -203
- package/src/utils/__tests__/chat-input-key-intercept.test.ts +0 -40
- package/src/utils/__tests__/chat-meta.test.ts +0 -130
- package/src/utils/__tests__/clipboard-linux.test.ts +0 -359
- package/src/utils/__tests__/clipboard.test.ts +0 -910
- package/src/utils/__tests__/code-search-summary.test.ts +0 -84
- package/src/utils/__tests__/collapse-helpers.test.ts +0 -1109
- package/src/utils/__tests__/error-handling.test.ts +0 -658
- package/src/utils/__tests__/exit-cleanly.test.ts +0 -110
- package/src/utils/__tests__/feedback-helpers.test.ts +0 -444
- package/src/utils/__tests__/feedback-submission.test.ts +0 -26
- package/src/utils/__tests__/fetch-usage.test.ts +0 -355
- package/src/utils/__tests__/fingerprint.test.ts +0 -144
- package/src/utils/__tests__/fixtures/terminal-command-broker-child.ts +0 -7
- package/src/utils/__tests__/fixtures/terminal-command-broker-entry.ts +0 -3
- package/src/utils/__tests__/fixtures/terminal-command-broker-owner.ts +0 -33
- package/src/utils/__tests__/format-elapsed-time.test.ts +0 -103
- package/src/utils/__tests__/format-timeout.test.ts +0 -87
- package/src/utils/__tests__/image-dimensions.test.ts +0 -249
- package/src/utils/__tests__/image-processor.test.ts +0 -209
- package/src/utils/__tests__/implementor-helpers.test.ts +0 -1458
- package/src/utils/__tests__/keyboard-actions.test.ts +0 -660
- package/src/utils/__tests__/layout-helpers.test.ts +0 -36
- package/src/utils/__tests__/lazy-response-ads.test.ts +0 -167
- package/src/utils/__tests__/log-shipper.test.ts +0 -53
- package/src/utils/__tests__/markdown-renderer.test.tsx +0 -421
- package/src/utils/__tests__/message-block-helpers.test.ts +0 -1263
- package/src/utils/__tests__/message-updater.test.ts +0 -645
- package/src/utils/__tests__/osc-timeout-scenarios.test.ts +0 -172
- package/src/utils/__tests__/pending-attachments.test.ts +0 -277
- package/src/utils/__tests__/polling-backoff.test.ts +0 -51
- package/src/utils/__tests__/queue-panel-actions.test.ts +0 -148
- package/src/utils/__tests__/run-state-storage.test.ts +0 -919
- package/src/utils/__tests__/safe-json.test.ts +0 -77
- package/src/utils/__tests__/sdk-event-handlers.test.ts +0 -685
- package/src/utils/__tests__/send-message-helpers.test.ts +0 -1898
- package/src/utils/__tests__/send-message-timer.test.ts +0 -64
- package/src/utils/__tests__/settings.test.ts +0 -99
- package/src/utils/__tests__/strings.test.ts +0 -192
- package/src/utils/__tests__/terminal-color-detection.test.ts +0 -425
- package/src/utils/__tests__/terminal-command-broker.test.ts +0 -528
- package/src/utils/__tests__/terminal-enter-detection.test.ts +0 -77
- package/src/utils/__tests__/terminal-io.test.ts +0 -137
- package/src/utils/__tests__/terminal-protocol-controller.test.ts +0 -119
- package/src/utils/__tests__/text-layout.test.ts +0 -82
- package/src/utils/__tests__/theme-platform-detection.test.ts +0 -125
- package/src/utils/__tests__/think-tag-parser.test.ts +0 -159
- package/src/utils/__tests__/trace-writer.test.ts +0 -223
- package/src/utils/__tests__/trim-chat-logs.test.ts +0 -78
- package/src/utils/__tests__/usage-banner-state.test.ts +0 -298
- package/src/utils/__tests__/validation-error-formatting.test.ts +0 -126
- package/src/utils/__tests__/windows-terminal-health.test.ts +0 -101
- package/src/utils/__tests__/write-file-atomic.test.ts +0 -127
- package/vendor/@anvil/common/src/__tests__/agent-validation.test.ts +0 -846
- package/vendor/@anvil/common/src/__tests__/anvil-model-availability.test.ts +0 -101
- package/vendor/@anvil/common/src/__tests__/anvil-models.test.ts +0 -1408
- package/vendor/@anvil/common/src/__tests__/anvil-public-data-use-copy.test.ts +0 -258
- package/vendor/@anvil/common/src/__tests__/anvil-referral-tiers.test.ts +0 -48
- package/vendor/@anvil/common/src/__tests__/anvil-spend-ceilings.test.ts +0 -282
- package/vendor/@anvil/common/src/__tests__/anvil-trust.test.ts +0 -526
- package/vendor/@anvil/common/src/__tests__/deepseek-direct.test.ts +0 -68
- package/vendor/@anvil/common/src/__tests__/disposable-email.test.ts +0 -132
- package/vendor/@anvil/common/src/__tests__/dynamic-agent-template-schema.test.ts +0 -422
- package/vendor/@anvil/common/src/__tests__/env-ci.test.ts +0 -167
- package/vendor/@anvil/common/src/__tests__/env-process.test.ts +0 -145
- package/vendor/@anvil/common/src/__tests__/foreign-client-shipped-agents.test.ts +0 -234
- package/vendor/@anvil/common/src/__tests__/foreign-client-signals.test.ts +0 -379
- package/vendor/@anvil/common/src/__tests__/free-agents.test.ts +0 -807
- package/vendor/@anvil/common/src/__tests__/gravity-capi.test.ts +0 -154
- package/vendor/@anvil/common/src/__tests__/handlesteps-parsing.test.ts +0 -246
- package/vendor/@anvil/common/src/__tests__/kimi-k3-god-only.test.ts +0 -77
- package/vendor/@anvil/common/src/__tests__/model-config.test.ts +0 -89
- package/vendor/@anvil/common/src/__tests__/project-file-tree.test.ts +0 -298
- package/vendor/@anvil/common/src/__tests__/provisioned-model-tiers.test.ts +0 -116
- package/vendor/@anvil/common/src/__tests__/reasoning-effort.test.ts +0 -167
- package/vendor/@anvil/common/src/__tests__/reddit-capi.test.ts +0 -132
- package/vendor/@anvil/common/src/__tests__/response-ad-positions.test.ts +0 -72
- package/vendor/@anvil/common/src/__tests__/user-state.test.ts +0 -30
- package/vendor/@anvil/common/src/constants/__tests__/anvil-onboarding-gate.test.ts +0 -63
- package/vendor/@anvil/common/src/constants/__tests__/anvil-onboarding.test.ts +0 -246
- package/vendor/@anvil/common/src/constants/__tests__/cf-worker-signals.test.ts +0 -106
- package/vendor/@anvil/common/src/testing/TESTING_PATTERNS.md +0 -351
- package/vendor/@anvil/common/src/testing/anvil-offer-invariants.ts +0 -169
- package/vendor/@anvil/common/src/testing/errors.ts +0 -33
- package/vendor/@anvil/common/src/testing/fixtures/agent-runtime.ts +0 -334
- package/vendor/@anvil/common/src/testing/impl/agent-runtime.ts +0 -6
- package/vendor/@anvil/common/src/testing/index.ts +0 -84
- package/vendor/@anvil/common/src/testing/mock-modules.ts +0 -53
- package/vendor/@anvil/common/src/testing/mock-types.ts +0 -123
- package/vendor/@anvil/common/src/testing/mocks/analytics.ts +0 -261
- package/vendor/@anvil/common/src/testing/mocks/child-process.ts +0 -93
- package/vendor/@anvil/common/src/testing/mocks/crypto.ts +0 -218
- package/vendor/@anvil/common/src/testing/mocks/database.ts +0 -337
- package/vendor/@anvil/common/src/testing/mocks/fetch.ts +0 -219
- package/vendor/@anvil/common/src/testing/mocks/filesystem.ts +0 -166
- package/vendor/@anvil/common/src/testing/mocks/index.ts +0 -101
- package/vendor/@anvil/common/src/testing/mocks/logger.ts +0 -135
- package/vendor/@anvil/common/src/testing/mocks/stream.ts +0 -313
- package/vendor/@anvil/common/src/testing/mocks/timers.ts +0 -132
- package/vendor/@anvil/common/src/testing/mocks/tree-sitter.ts +0 -127
- package/vendor/@anvil/common/src/testing/setup.ts +0 -282
- package/vendor/@anvil/common/src/tools/__tests__/compile-tool-definitions.test.ts +0 -34
- package/vendor/@anvil/common/src/tools/params/__tests__/coerce-to-array.test.ts +0 -213
- package/vendor/@anvil/common/src/tools/params/__tests__/read-docs.test.ts +0 -47
- package/vendor/@anvil/common/src/tools/params/__tests__/render-ui.test.ts +0 -65
- package/vendor/@anvil/common/src/tools/params/tool/__tests__/run-terminal-command-timeout.test.ts +0 -49
- package/vendor/@anvil/common/src/types/__tests__/dynamic-agent-template.test.ts +0 -20
- package/vendor/@anvil/common/src/util/__tests__/ad-user-agent.test.ts +0 -26
- package/vendor/@anvil/common/src/util/__tests__/analytics-dispatcher.test.ts +0 -122
- package/vendor/@anvil/common/src/util/__tests__/analytics-log.test.ts +0 -102
- package/vendor/@anvil/common/src/util/__tests__/analytics-sampling.test.ts +0 -143
- package/vendor/@anvil/common/src/util/__tests__/anvil-streak.test.ts +0 -202
- package/vendor/@anvil/common/src/util/__tests__/anvil-usage-summary.test.ts +0 -193
- package/vendor/@anvil/common/src/util/__tests__/axiom-only-log.test.ts +0 -140
- package/vendor/@anvil/common/src/util/__tests__/client-user-agent.test.ts +0 -148
- package/vendor/@anvil/common/src/util/__tests__/engagement-tracker.test.ts +0 -115
- package/vendor/@anvil/common/src/util/__tests__/env-file-path.test.ts +0 -57
- package/vendor/@anvil/common/src/util/__tests__/error-abort.test.ts +0 -774
- package/vendor/@anvil/common/src/util/__tests__/error-api-details.test.ts +0 -206
- package/vendor/@anvil/common/src/util/__tests__/file-read-limits.test.ts +0 -173
- package/vendor/@anvil/common/src/util/__tests__/format-code-search.test.ts +0 -60
- package/vendor/@anvil/common/src/util/__tests__/log-mirror.test.ts +0 -31
- package/vendor/@anvil/common/src/util/__tests__/messages.test.ts +0 -1252
- package/vendor/@anvil/common/src/util/__tests__/partial-json-delta.test.ts +0 -505
- package/vendor/@anvil/common/src/util/__tests__/path.test.ts +0 -22
- package/vendor/@anvil/common/src/util/__tests__/project-ignore.test.ts +0 -90
- package/vendor/@anvil/common/src/util/__tests__/promise.test.ts +0 -325
- package/vendor/@anvil/common/src/util/__tests__/rate-limit.test.ts +0 -28
- package/vendor/@anvil/common/src/util/__tests__/reddit-anvil-retention.test.ts +0 -130
- package/vendor/@anvil/common/src/util/__tests__/saxy.test.ts +0 -1008
- package/vendor/@anvil/common/src/util/__tests__/split-data.test.ts +0 -289
- package/vendor/@anvil/common/src/util/__tests__/string.test.ts +0 -239
- package/vendor/@anvil/common/src/util/__tests__/thread-title.test.ts +0 -70
- package/vendor/@anvil/common/src/util/__tests__/tool-result-media-order.test.ts +0 -108
- package/vendor/@anvil/common/src/util/__tests__/ttft-histogram.test.ts +0 -180
- package/vendor/@anvil/common/src/util/__tests__/with-timeout.test.ts +0 -24
- package/vendor/@anvil/common/src/util/__tests__/zoned-time.test.ts +0 -88
- package/vendor/@anvil/common/src/util/skills.test.ts +0 -44
- package/vendor/@anvil/sdk/dist/index.cjs.map +0 -440
- package/vendor/@anvil/sdk/dist/index.mjs.map +0 -440
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'bun:test'
|
|
2
|
-
|
|
3
|
-
import { formatValidationError } from '../validation-error-formatting'
|
|
4
|
-
|
|
5
|
-
describe('formatValidationError', () => {
|
|
6
|
-
test('parses JSON array payloads and extracts field/message', () => {
|
|
7
|
-
const raw = `[
|
|
8
|
-
{
|
|
9
|
-
"code": "custom",
|
|
10
|
-
"path": [
|
|
11
|
-
"toolNames"
|
|
12
|
-
],
|
|
13
|
-
"message": "Non-empty spawnableAgents array requires the 'spawn_agents' tool. Add 'spawn_agents' to toolNames or remove spawnableAgents."
|
|
14
|
-
}
|
|
15
|
-
]`
|
|
16
|
-
|
|
17
|
-
const result = formatValidationError(raw)
|
|
18
|
-
|
|
19
|
-
expect(result.fieldName).toBe('toolNames')
|
|
20
|
-
expect(result.message).toBe(
|
|
21
|
-
"Non-empty spawnableAgents array requires the 'spawn_agents' tool. Add 'spawn_agents' to toolNames or remove spawnableAgents.",
|
|
22
|
-
)
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
test('strips agent name prefix', () => {
|
|
26
|
-
const result = formatValidationError(
|
|
27
|
-
'Agent "demo" (demo.ts): Invalid input: expected string, received number',
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
expect(result.fieldName).toBeUndefined()
|
|
31
|
-
expect(result.message).toBe(
|
|
32
|
-
'Invalid input: expected string, received number',
|
|
33
|
-
)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
test('extracts field:message pattern', () => {
|
|
37
|
-
const result = formatValidationError(
|
|
38
|
-
'instructions: Required field is missing',
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
expect(result.fieldName).toBe('instructions')
|
|
42
|
-
expect(result.message).toBe('Required field is missing')
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
test('handles messages without field patterns', () => {
|
|
46
|
-
const result = formatValidationError(
|
|
47
|
-
'Schema validation failed: Generic error',
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
expect(result.fieldName).toBeUndefined()
|
|
51
|
-
expect(result.message).toBe('Generic error')
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
test('handles nested path from JSON error', () => {
|
|
55
|
-
const raw = `[
|
|
56
|
-
{
|
|
57
|
-
"path": ["outputSchema", "properties", "summary"],
|
|
58
|
-
"message": "Required"
|
|
59
|
-
}
|
|
60
|
-
]`
|
|
61
|
-
|
|
62
|
-
const result = formatValidationError(raw)
|
|
63
|
-
|
|
64
|
-
expect(result.fieldName).toBe('outputSchema.properties.summary')
|
|
65
|
-
expect(result.message).toBe('Required')
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
test('handles empty string input', () => {
|
|
69
|
-
const result = formatValidationError('')
|
|
70
|
-
|
|
71
|
-
expect(result.fieldName).toBeUndefined()
|
|
72
|
-
expect(result.message).toBe('Unknown validation error')
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
test('handles JSON object (not array) with error', () => {
|
|
76
|
-
const raw = `{"path": ["field"], "message": "Invalid value"}`
|
|
77
|
-
|
|
78
|
-
const result = formatValidationError(raw)
|
|
79
|
-
|
|
80
|
-
expect(result.fieldName).toBe('field')
|
|
81
|
-
expect(result.message).toBe('Invalid value')
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
test('handles JSON with empty path array', () => {
|
|
85
|
-
const raw = `[{"path": [], "message": "Root level error"}]`
|
|
86
|
-
|
|
87
|
-
const result = formatValidationError(raw)
|
|
88
|
-
|
|
89
|
-
expect(result.fieldName).toBeUndefined()
|
|
90
|
-
expect(result.message).toBe('Root level error')
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
test('handles malformed JSON gracefully', () => {
|
|
94
|
-
const raw = '[{"path": ["field"], invalid json'
|
|
95
|
-
|
|
96
|
-
const result = formatValidationError(raw)
|
|
97
|
-
|
|
98
|
-
expect(result.fieldName).toBeUndefined()
|
|
99
|
-
expect(result.message).toBe('[{"path": ["field"], invalid json')
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
test('handles colon in message part correctly', () => {
|
|
103
|
-
const result = formatValidationError(
|
|
104
|
-
'fieldName: Error: something went wrong',
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
expect(result.fieldName).toBe('fieldName')
|
|
108
|
-
expect(result.message).toBe('Error: something went wrong')
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
test('handles field pattern with no message after colon', () => {
|
|
112
|
-
const result = formatValidationError('fieldName:')
|
|
113
|
-
|
|
114
|
-
expect(result.fieldName).toBeUndefined()
|
|
115
|
-
expect(result.message).toBe('fieldName:')
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
test('handles JSON with missing message property', () => {
|
|
119
|
-
const raw = `[{"path": ["field"], "code": "custom"}]`
|
|
120
|
-
|
|
121
|
-
const result = formatValidationError(raw)
|
|
122
|
-
|
|
123
|
-
expect(result.fieldName).toBe('field')
|
|
124
|
-
expect(result.message).toBe(raw)
|
|
125
|
-
})
|
|
126
|
-
})
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { AnalyticsEvent } from '@anvil/common/constants/analytics-events'
|
|
2
|
-
import { afterEach, describe, expect, mock, test } from 'bun:test'
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
initAnalytics,
|
|
6
|
-
resetAnalyticsState,
|
|
7
|
-
trackEvent,
|
|
8
|
-
type AnalyticsDeps,
|
|
9
|
-
} from '../analytics'
|
|
10
|
-
import { deliverWindowsTerminalFailure } from '../windows-terminal-health'
|
|
11
|
-
|
|
12
|
-
import type { LogRecordInput } from '@anvil/common/schemas/logs'
|
|
13
|
-
|
|
14
|
-
const FAILED_ANALYTICS_DEPS: AnalyticsDeps = {
|
|
15
|
-
env: {},
|
|
16
|
-
isProd: true,
|
|
17
|
-
createClient: mock(() => {
|
|
18
|
-
throw new Error(
|
|
19
|
-
'PostHog client should not be created without configuration',
|
|
20
|
-
)
|
|
21
|
-
}),
|
|
22
|
-
generateAnonymousId: () => 'analytics-anonymous-id',
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
afterEach(() => {
|
|
26
|
-
resetAnalyticsState()
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
describe('Windows terminal-health delivery', () => {
|
|
30
|
-
test('queues and drains the bounded Axiom event when analytics initialization fails', async () => {
|
|
31
|
-
const analyticsRecords: LogRecordInput[] = []
|
|
32
|
-
resetAnalyticsState({
|
|
33
|
-
...FAILED_ANALYTICS_DEPS,
|
|
34
|
-
enqueueClientLog: (record) => analyticsRecords.push(record),
|
|
35
|
-
})
|
|
36
|
-
expect(() => initAnalytics()).toThrow(
|
|
37
|
-
'NEXT_PUBLIC_POSTHOG_API_KEY or NEXT_PUBLIC_POSTHOG_HOST_URL is not set',
|
|
38
|
-
)
|
|
39
|
-
const fallbackRecords: LogRecordInput[] = []
|
|
40
|
-
const drainClientLogs = mock(async () => {})
|
|
41
|
-
const properties = {
|
|
42
|
-
version: '0.0.142',
|
|
43
|
-
platform: 'win32' as const,
|
|
44
|
-
stage: 'arming' as const,
|
|
45
|
-
failureCode: 'timeout' as const,
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
await deliverWindowsTerminalFailure(
|
|
49
|
-
AnalyticsEvent.TERMINAL_WATCHDOG_FAILED,
|
|
50
|
-
properties,
|
|
51
|
-
{
|
|
52
|
-
trackEvent,
|
|
53
|
-
getAnonymousId: () => 'anonymous-install-id',
|
|
54
|
-
enqueueClientLog: (record) => fallbackRecords.push(record),
|
|
55
|
-
drainClientLogs,
|
|
56
|
-
},
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
expect(analyticsRecords).toEqual([
|
|
60
|
-
{
|
|
61
|
-
level: 'info',
|
|
62
|
-
event: AnalyticsEvent.TERMINAL_WATCHDOG_FAILED,
|
|
63
|
-
message: AnalyticsEvent.TERMINAL_WATCHDOG_FAILED,
|
|
64
|
-
client_session_id: 'analytics-anonymous-id',
|
|
65
|
-
data: properties,
|
|
66
|
-
},
|
|
67
|
-
])
|
|
68
|
-
expect(fallbackRecords).toEqual([])
|
|
69
|
-
expect(drainClientLogs).toHaveBeenCalledTimes(1)
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
test('preserves the analytics mirror without queuing a duplicate', async () => {
|
|
73
|
-
const tracked = mock(() => {})
|
|
74
|
-
const enqueueClientLog = mock((_record: LogRecordInput) => {})
|
|
75
|
-
const drainClientLogs = mock(async () => {})
|
|
76
|
-
const properties = {
|
|
77
|
-
version: '0.0.142',
|
|
78
|
-
platform: 'win32' as const,
|
|
79
|
-
stage: 'spawn' as const,
|
|
80
|
-
failureCode: 'enoent' as const,
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
await deliverWindowsTerminalFailure(
|
|
84
|
-
AnalyticsEvent.TERMINAL_BROKER_SPAWN_FAILED,
|
|
85
|
-
properties,
|
|
86
|
-
{
|
|
87
|
-
trackEvent: tracked,
|
|
88
|
-
getAnonymousId: () => 'unused',
|
|
89
|
-
enqueueClientLog,
|
|
90
|
-
drainClientLogs,
|
|
91
|
-
},
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
expect(tracked).toHaveBeenCalledWith(
|
|
95
|
-
AnalyticsEvent.TERMINAL_BROKER_SPAWN_FAILED,
|
|
96
|
-
properties,
|
|
97
|
-
)
|
|
98
|
-
expect(enqueueClientLog).not.toHaveBeenCalled()
|
|
99
|
-
expect(drainClientLogs).toHaveBeenCalledTimes(1)
|
|
100
|
-
})
|
|
101
|
-
})
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, beforeEach, afterEach } from 'bun:test'
|
|
2
|
-
import * as fs from 'fs'
|
|
3
|
-
import * as os from 'os'
|
|
4
|
-
import * as path from 'path'
|
|
5
|
-
|
|
6
|
-
import { writeFileAtomic, writeFileAtomicAsync } from '../write-file-atomic'
|
|
7
|
-
|
|
8
|
-
let tempDir = ''
|
|
9
|
-
|
|
10
|
-
describe('writeFileAtomic', () => {
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'anvil-atomic-'))
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
afterEach(() => {
|
|
16
|
-
fs.rmSync(tempDir, { recursive: true, force: true })
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
test('writes a new file', () => {
|
|
20
|
-
const target = path.join(tempDir, 'out.json')
|
|
21
|
-
|
|
22
|
-
writeFileAtomic(target, '{"a":1}')
|
|
23
|
-
|
|
24
|
-
expect(fs.readFileSync(target, 'utf8')).toBe('{"a":1}')
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
test('replaces an existing file', () => {
|
|
28
|
-
const target = path.join(tempDir, 'out.json')
|
|
29
|
-
fs.writeFileSync(target, 'old content')
|
|
30
|
-
|
|
31
|
-
writeFileAtomic(target, 'new content')
|
|
32
|
-
|
|
33
|
-
expect(fs.readFileSync(target, 'utf8')).toBe('new content')
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
test('leaves no temp file behind on success', () => {
|
|
37
|
-
const target = path.join(tempDir, 'out.json')
|
|
38
|
-
|
|
39
|
-
writeFileAtomic(target, 'data')
|
|
40
|
-
|
|
41
|
-
expect(fs.readdirSync(tempDir)).toEqual(['out.json'])
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
test('cleans up the temp file and rethrows on failure', () => {
|
|
45
|
-
// Renaming a file over an existing directory fails on all platforms
|
|
46
|
-
const target = path.join(tempDir, 'target-dir')
|
|
47
|
-
fs.mkdirSync(target)
|
|
48
|
-
|
|
49
|
-
expect(() => writeFileAtomic(target, 'data')).toThrow()
|
|
50
|
-
|
|
51
|
-
expect(fs.readdirSync(tempDir)).toEqual(['target-dir'])
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
test('uses a unique temp name per write (no collision between calls)', () => {
|
|
55
|
-
// Two writes to different targets must not share a temp path, otherwise
|
|
56
|
-
// concurrent sync + async writes would tear each other. The temp name
|
|
57
|
-
// includes a random component, so back-to-back writes never collide.
|
|
58
|
-
const a = path.join(tempDir, 'a.json')
|
|
59
|
-
const b = path.join(tempDir, 'b.json')
|
|
60
|
-
|
|
61
|
-
writeFileAtomic(a, 'a')
|
|
62
|
-
writeFileAtomic(b, 'b')
|
|
63
|
-
|
|
64
|
-
expect(fs.readdirSync(tempDir).sort()).toEqual(['a.json', 'b.json'])
|
|
65
|
-
})
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
describe('writeFileAtomicAsync', () => {
|
|
69
|
-
beforeEach(() => {
|
|
70
|
-
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'anvil-atomic-async-'))
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
afterEach(() => {
|
|
74
|
-
fs.rmSync(tempDir, { recursive: true, force: true })
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
test('writes a new file', async () => {
|
|
78
|
-
const target = path.join(tempDir, 'out.json')
|
|
79
|
-
|
|
80
|
-
await writeFileAtomicAsync(target, '{"a":1}')
|
|
81
|
-
|
|
82
|
-
expect(fs.readFileSync(target, 'utf8')).toBe('{"a":1}')
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
test('replaces an existing file', async () => {
|
|
86
|
-
const target = path.join(tempDir, 'out.json')
|
|
87
|
-
fs.writeFileSync(target, 'old content')
|
|
88
|
-
|
|
89
|
-
await writeFileAtomicAsync(target, 'new content')
|
|
90
|
-
|
|
91
|
-
expect(fs.readFileSync(target, 'utf8')).toBe('new content')
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
test('leaves no temp file behind on success', async () => {
|
|
95
|
-
const target = path.join(tempDir, 'out.json')
|
|
96
|
-
|
|
97
|
-
await writeFileAtomicAsync(target, 'data')
|
|
98
|
-
|
|
99
|
-
expect(fs.readdirSync(tempDir)).toEqual(['out.json'])
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
test('cleans up the temp file and rejects on failure', async () => {
|
|
103
|
-
const target = path.join(tempDir, 'target-dir')
|
|
104
|
-
fs.mkdirSync(target)
|
|
105
|
-
|
|
106
|
-
await expect(writeFileAtomicAsync(target, 'data')).rejects.toThrow()
|
|
107
|
-
|
|
108
|
-
expect(fs.readdirSync(tempDir)).toEqual(['target-dir'])
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
test('concurrent writes to the same file do not tear (last write wins)', async () => {
|
|
112
|
-
const target = path.join(tempDir, 'out.json')
|
|
113
|
-
|
|
114
|
-
await Promise.all([
|
|
115
|
-
writeFileAtomicAsync(target, 'first'),
|
|
116
|
-
writeFileAtomicAsync(target, 'second'),
|
|
117
|
-
writeFileAtomicAsync(target, 'third'),
|
|
118
|
-
])
|
|
119
|
-
|
|
120
|
-
// Whichever rename lands last wins, but the file is always one intact
|
|
121
|
-
// value — never a torn mix — and no temp files remain.
|
|
122
|
-
expect(['first', 'second', 'third']).toContain(
|
|
123
|
-
fs.readFileSync(target, 'utf8'),
|
|
124
|
-
)
|
|
125
|
-
expect(fs.readdirSync(tempDir)).toEqual(['out.json'])
|
|
126
|
-
})
|
|
127
|
-
})
|