@google/gemini-cli 0.3.2 → 0.4.0-preview
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/dist/google-gemini-cli-0.3.1.tgz +0 -0
- package/dist/package.json +3 -6
- package/dist/src/commands/extensions/enable.js +1 -1
- package/dist/src/commands/extensions/enable.js.map +1 -1
- package/dist/src/commands/extensions/examples/context/GEMINI.md +8 -0
- package/dist/src/commands/extensions/examples/context/gemini-extension.json +5 -0
- package/dist/src/commands/extensions/examples/custom-commands/commands/fs/grep-code.toml +6 -0
- package/dist/src/commands/extensions/examples/custom-commands/gemini-extension.json +4 -0
- package/dist/src/commands/extensions/examples/exclude-tools/gemini-extension.json +5 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.d.ts +6 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.js +46 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.js.map +1 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.ts +60 -0
- package/dist/src/commands/extensions/examples/mcp-server/gemini-extension.json +10 -0
- package/dist/src/commands/extensions/install.js +35 -7
- package/dist/src/commands/extensions/install.js.map +1 -1
- package/dist/src/commands/extensions/install.test.js +20 -2
- package/dist/src/commands/extensions/install.test.js.map +1 -1
- package/dist/src/commands/extensions/link.d.ts +12 -0
- package/dist/src/commands/extensions/link.js +37 -0
- package/dist/src/commands/extensions/link.js.map +1 -0
- package/dist/src/commands/extensions/new.d.ts +7 -0
- package/dist/src/commands/extensions/new.js +70 -0
- package/dist/src/commands/extensions/new.js.map +1 -0
- package/dist/src/commands/extensions/new.test.d.ts +6 -0
- package/dist/src/commands/extensions/new.test.js +50 -0
- package/dist/src/commands/extensions/new.test.js.map +1 -0
- package/dist/src/commands/extensions/update.d.ts +2 -1
- package/dist/src/commands/extensions/update.js +36 -15
- package/dist/src/commands/extensions/update.js.map +1 -1
- package/dist/src/commands/extensions.js +4 -0
- package/dist/src/commands/extensions.js.map +1 -1
- package/dist/src/commands/mcp/add.js +1 -1
- package/dist/src/commands/mcp/add.js.map +1 -1
- package/dist/src/commands/mcp/list.js +2 -2
- package/dist/src/commands/mcp/list.js.map +1 -1
- package/dist/src/commands/mcp/remove.js +1 -1
- package/dist/src/commands/mcp/remove.js.map +1 -1
- package/dist/src/config/auth.d.ts +1 -1
- package/dist/src/config/auth.js +4 -4
- package/dist/src/config/auth.js.map +1 -1
- package/dist/src/config/auth.test.js +15 -7
- package/dist/src/config/auth.test.js.map +1 -1
- package/dist/src/config/config.d.ts +4 -1
- package/dist/src/config/config.js +32 -18
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/extension.d.ts +7 -4
- package/dist/src/config/extension.js +76 -24
- package/dist/src/config/extension.js.map +1 -1
- package/dist/src/config/keyBindings.d.ts +1 -0
- package/dist/src/config/keyBindings.js +6 -25
- package/dist/src/config/keyBindings.js.map +1 -1
- package/dist/src/config/settings.d.ts +5 -5
- package/dist/src/config/settings.js +93 -224
- package/dist/src/config/settings.js.map +1 -1
- package/dist/src/config/settingsSchema.d.ts +113 -13
- package/dist/src/config/settingsSchema.js +112 -13
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/config/trustedFolders.d.ts +12 -2
- package/dist/src/config/trustedFolders.js +59 -40
- package/dist/src/config/trustedFolders.js.map +1 -1
- package/dist/src/config/trustedFolders.test.js +81 -2
- package/dist/src/config/trustedFolders.test.js.map +1 -1
- package/dist/src/gemini.d.ts +1 -1
- package/dist/src/gemini.js +52 -26
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/gemini.test.js +2 -30
- package/dist/src/gemini.test.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/generated/git-commit.js.map +1 -1
- package/dist/src/services/BuiltinCommandLoader.js +1 -1
- package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
- package/dist/src/services/BuiltinCommandLoader.test.js +3 -3
- package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
- package/dist/src/services/FileCommandLoader.d.ts +2 -0
- package/dist/src/services/FileCommandLoader.js +7 -0
- package/dist/src/services/FileCommandLoader.js.map +1 -1
- package/dist/src/ui/App.js +109 -47
- package/dist/src/ui/App.js.map +1 -1
- package/dist/src/ui/commands/aboutCommand.js +9 -3
- package/dist/src/ui/commands/aboutCommand.js.map +1 -1
- package/dist/src/ui/commands/bugCommand.js +9 -4
- package/dist/src/ui/commands/bugCommand.js.map +1 -1
- package/dist/src/ui/commands/directoryCommand.js +1 -1
- package/dist/src/ui/commands/directoryCommand.js.map +1 -1
- package/dist/src/ui/commands/ideCommand.d.ts +1 -2
- package/dist/src/ui/commands/ideCommand.js +16 -7
- package/dist/src/ui/commands/ideCommand.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.js +6 -4
- package/dist/src/ui/commands/mcpCommand.js.map +1 -1
- package/dist/src/ui/commands/memoryCommand.js +1 -1
- package/dist/src/ui/commands/memoryCommand.js.map +1 -1
- package/dist/src/ui/components/AuthDialog.js +8 -2
- package/dist/src/ui/components/AuthDialog.js.map +1 -1
- package/dist/src/ui/components/AuthDialog.test.js +41 -10
- package/dist/src/ui/components/AuthDialog.test.js.map +1 -1
- package/dist/src/ui/components/FolderTrustDialog.js +3 -1
- package/dist/src/ui/components/FolderTrustDialog.js.map +1 -1
- package/dist/src/ui/components/FolderTrustDialog.test.js +19 -4
- package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/Footer.d.ts +3 -0
- package/dist/src/ui/components/Footer.js +4 -3
- package/dist/src/ui/components/Footer.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.js +34 -24
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/MemoryUsageDisplay.js +1 -1
- package/dist/src/ui/components/MemoryUsageDisplay.js.map +1 -1
- package/dist/src/ui/components/ProQuotaDialog.d.ts +13 -0
- package/dist/src/ui/components/ProQuotaDialog.js +21 -0
- package/dist/src/ui/components/ProQuotaDialog.js.map +1 -0
- package/dist/src/ui/components/ProQuotaDialog.test.d.ts +6 -0
- package/dist/src/ui/components/ProQuotaDialog.test.js +56 -0
- package/dist/src/ui/components/ProQuotaDialog.test.js.map +1 -0
- package/dist/src/ui/components/SettingsDialog.test.js +2 -2
- package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js +3 -3
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js +0 -8
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js.map +1 -1
- package/dist/src/ui/components/shared/MaxSizedBox.js.map +1 -1
- package/dist/src/ui/components/shared/text-buffer.js +35 -51
- package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.js +255 -42
- package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.test.js +115 -1
- package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.js +11 -6
- package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/useFolderTrust.js +6 -4
- package/dist/src/ui/hooks/useFolderTrust.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.d.ts +3 -2
- package/dist/src/ui/hooks/useGeminiStream.js +31 -3
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useIdeTrustListener.d.ts +14 -0
- package/dist/src/ui/hooks/useIdeTrustListener.js +39 -0
- package/dist/src/ui/hooks/useIdeTrustListener.js.map +1 -0
- package/dist/src/ui/hooks/useInputHistoryStore.d.ts +19 -0
- package/dist/src/ui/hooks/useInputHistoryStore.js +81 -0
- package/dist/src/ui/hooks/useInputHistoryStore.js.map +1 -0
- package/dist/src/ui/hooks/useInputHistoryStore.test.d.ts +6 -0
- package/dist/src/ui/hooks/useInputHistoryStore.test.js +234 -0
- package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +1 -0
- package/dist/src/ui/hooks/useLoadingIndicator.d.ts +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.js +2 -2
- package/dist/src/ui/hooks/useLoadingIndicator.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.test.js +2 -2
- package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.d.ts +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.js +11 -8
- package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
- package/dist/src/ui/hooks/usePrivacySettings.d.ts +1 -1
- package/dist/src/ui/hooks/usePrivacySettings.js +8 -13
- package/dist/src/ui/hooks/usePrivacySettings.js.map +1 -1
- package/dist/src/ui/hooks/usePrivacySettings.test.js +33 -97
- package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.js +263 -67
- package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.test.d.ts +4 -1
- package/dist/src/ui/hooks/useSlashCompletion.test.js +452 -59
- package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useToolScheduler.test.js +57 -59
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
- package/dist/src/ui/keyMatchers.test.js +9 -0
- package/dist/src/ui/keyMatchers.test.js.map +1 -1
- package/dist/src/ui/utils/MarkdownDisplay.test.js +2 -2
- package/dist/src/ui/utils/MarkdownDisplay.test.js.map +1 -1
- package/dist/src/ui/utils/highlight.d.ts +10 -0
- package/dist/src/ui/utils/highlight.js +41 -0
- package/dist/src/ui/utils/highlight.js.map +1 -0
- package/dist/src/ui/utils/highlight.test.d.ts +6 -0
- package/dist/src/ui/utils/highlight.test.js +93 -0
- package/dist/src/ui/utils/highlight.test.js.map +1 -0
- package/dist/src/ui/utils/platformConstants.d.ts +24 -1
- package/dist/src/ui/utils/platformConstants.js +26 -1
- package/dist/src/ui/utils/platformConstants.js.map +1 -1
- package/dist/src/utils/deepMerge.d.ts +10 -0
- package/dist/src/utils/deepMerge.js +58 -0
- package/dist/src/utils/deepMerge.js.map +1 -0
- package/dist/src/utils/deepMerge.test.d.ts +6 -0
- package/dist/src/utils/deepMerge.test.js +143 -0
- package/dist/src/utils/deepMerge.test.js.map +1 -0
- package/dist/src/utils/envVarResolver.d.ts +39 -0
- package/dist/src/utils/envVarResolver.js +97 -0
- package/dist/src/utils/envVarResolver.js.map +1 -0
- package/dist/src/utils/envVarResolver.test.d.ts +6 -0
- package/dist/src/utils/envVarResolver.test.js +221 -0
- package/dist/src/utils/envVarResolver.test.js.map +1 -0
- package/dist/src/utils/userStartupWarnings.d.ts +1 -1
- package/dist/src/utils/userStartupWarnings.js +1 -1
- package/dist/src/utils/userStartupWarnings.js.map +1 -1
- package/dist/src/validateNonInterActiveAuth.d.ts +2 -1
- package/dist/src/validateNonInterActiveAuth.js +11 -2
- package/dist/src/validateNonInterActiveAuth.js.map +1 -1
- package/dist/src/zed-integration/zedIntegration.js +7 -5
- package/dist/src/zed-integration/zedIntegration.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -7
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect } from 'vitest';
|
|
7
|
+
import { parseInputForHighlighting } from './highlight.js';
|
|
8
|
+
describe('parseInputForHighlighting', () => {
|
|
9
|
+
it('should handle an empty string', () => {
|
|
10
|
+
expect(parseInputForHighlighting('')).toEqual([
|
|
11
|
+
{ text: '', type: 'default' },
|
|
12
|
+
]);
|
|
13
|
+
});
|
|
14
|
+
it('should handle text with no commands or files', () => {
|
|
15
|
+
const text = 'this is a normal sentence';
|
|
16
|
+
expect(parseInputForHighlighting(text)).toEqual([
|
|
17
|
+
{ text, type: 'default' },
|
|
18
|
+
]);
|
|
19
|
+
});
|
|
20
|
+
it('should highlight a single command at the beginning', () => {
|
|
21
|
+
const text = '/help me';
|
|
22
|
+
expect(parseInputForHighlighting(text)).toEqual([
|
|
23
|
+
{ text: '/help', type: 'command' },
|
|
24
|
+
{ text: ' me', type: 'default' },
|
|
25
|
+
]);
|
|
26
|
+
});
|
|
27
|
+
it('should highlight a single file path at the beginning', () => {
|
|
28
|
+
const text = '@path/to/file.txt please';
|
|
29
|
+
expect(parseInputForHighlighting(text)).toEqual([
|
|
30
|
+
{ text: '@path/to/file.txt', type: 'file' },
|
|
31
|
+
{ text: ' please', type: 'default' },
|
|
32
|
+
]);
|
|
33
|
+
});
|
|
34
|
+
it('should highlight a command in the middle', () => {
|
|
35
|
+
const text = 'I need /help with this';
|
|
36
|
+
expect(parseInputForHighlighting(text)).toEqual([
|
|
37
|
+
{ text: 'I need ', type: 'default' },
|
|
38
|
+
{ text: '/help', type: 'command' },
|
|
39
|
+
{ text: ' with this', type: 'default' },
|
|
40
|
+
]);
|
|
41
|
+
});
|
|
42
|
+
it('should highlight a file path in the middle', () => {
|
|
43
|
+
const text = 'Please check @path/to/file.txt for details';
|
|
44
|
+
expect(parseInputForHighlighting(text)).toEqual([
|
|
45
|
+
{ text: 'Please check ', type: 'default' },
|
|
46
|
+
{ text: '@path/to/file.txt', type: 'file' },
|
|
47
|
+
{ text: ' for details', type: 'default' },
|
|
48
|
+
]);
|
|
49
|
+
});
|
|
50
|
+
it('should highlight multiple commands and files', () => {
|
|
51
|
+
const text = 'Use /run with @file.js and also /format @another/file.ts';
|
|
52
|
+
expect(parseInputForHighlighting(text)).toEqual([
|
|
53
|
+
{ text: 'Use ', type: 'default' },
|
|
54
|
+
{ text: '/run', type: 'command' },
|
|
55
|
+
{ text: ' with ', type: 'default' },
|
|
56
|
+
{ text: '@file.js', type: 'file' },
|
|
57
|
+
{ text: ' and also ', type: 'default' },
|
|
58
|
+
{ text: '/format', type: 'command' },
|
|
59
|
+
{ text: ' ', type: 'default' },
|
|
60
|
+
{ text: '@another/file.ts', type: 'file' },
|
|
61
|
+
]);
|
|
62
|
+
});
|
|
63
|
+
it('should handle adjacent highlights', () => {
|
|
64
|
+
const text = '/run@file.js';
|
|
65
|
+
expect(parseInputForHighlighting(text)).toEqual([
|
|
66
|
+
{ text: '/run', type: 'command' },
|
|
67
|
+
{ text: '@file.js', type: 'file' },
|
|
68
|
+
]);
|
|
69
|
+
});
|
|
70
|
+
it('should handle highlights at the end of the string', () => {
|
|
71
|
+
const text = 'Get help with /help';
|
|
72
|
+
expect(parseInputForHighlighting(text)).toEqual([
|
|
73
|
+
{ text: 'Get help with ', type: 'default' },
|
|
74
|
+
{ text: '/help', type: 'command' },
|
|
75
|
+
]);
|
|
76
|
+
});
|
|
77
|
+
it('should handle file paths with dots and dashes', () => {
|
|
78
|
+
const text = 'Check @./path-to/file-name.v2.txt';
|
|
79
|
+
expect(parseInputForHighlighting(text)).toEqual([
|
|
80
|
+
{ text: 'Check ', type: 'default' },
|
|
81
|
+
{ text: '@./path-to/file-name.v2.txt', type: 'file' },
|
|
82
|
+
]);
|
|
83
|
+
});
|
|
84
|
+
it('should handle commands with dashes and numbers', () => {
|
|
85
|
+
const text = 'Run /command-123 now';
|
|
86
|
+
expect(parseInputForHighlighting(text)).toEqual([
|
|
87
|
+
{ text: 'Run ', type: 'default' },
|
|
88
|
+
{ text: '/command-123', type: 'command' },
|
|
89
|
+
{ text: ' now', type: 'default' },
|
|
90
|
+
]);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
//# sourceMappingURL=highlight.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"highlight.test.js","sourceRoot":"","sources":["../../../../src/ui/utils/highlight.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,6 +21,29 @@ export declare const KITTY_KEYCODE_ENTER = 13;
|
|
|
21
21
|
export declare const KITTY_KEYCODE_NUMPAD_ENTER = 57414;
|
|
22
22
|
export declare const KITTY_KEYCODE_TAB = 9;
|
|
23
23
|
export declare const KITTY_KEYCODE_BACKSPACE = 127;
|
|
24
|
+
/**
|
|
25
|
+
* Kitty modifier decoding constants
|
|
26
|
+
*
|
|
27
|
+
* In Kitty/Ghostty, the modifier parameter is encoded as (1 + bitmask).
|
|
28
|
+
* Some terminals also set bit 7 (i.e., add 128) when reporting event types.
|
|
29
|
+
*/
|
|
30
|
+
export declare const KITTY_MODIFIER_BASE = 1;
|
|
31
|
+
export declare const KITTY_MODIFIER_EVENT_TYPES_OFFSET = 128;
|
|
32
|
+
/**
|
|
33
|
+
* Modifier bit flags for Kitty/Xterm-style parameters.
|
|
34
|
+
*
|
|
35
|
+
* Per spec, the modifiers parameter encodes (1 + bitmask) where:
|
|
36
|
+
* - 1: no modifiers
|
|
37
|
+
* - bit 0 (1): Shift
|
|
38
|
+
* - bit 1 (2): Alt/Option (reported as "alt" in spec; we map to meta)
|
|
39
|
+
* - bit 2 (4): Ctrl
|
|
40
|
+
*
|
|
41
|
+
* Some terminals add 128 to the entire modifiers field when reporting event types.
|
|
42
|
+
* See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#modifiers
|
|
43
|
+
*/
|
|
44
|
+
export declare const MODIFIER_SHIFT_BIT = 1;
|
|
45
|
+
export declare const MODIFIER_ALT_BIT = 2;
|
|
46
|
+
export declare const MODIFIER_CTRL_BIT = 4;
|
|
24
47
|
/**
|
|
25
48
|
* Timing constants for terminal interactions
|
|
26
49
|
*/
|
|
@@ -42,7 +65,7 @@ export declare const BACKSLASH_ENTER_DETECTION_WINDOW_MS = 5;
|
|
|
42
65
|
* Longest reasonable: \x1b[127;15~ = 11 chars (Del with all modifiers)
|
|
43
66
|
* We use 12 to provide a small buffer.
|
|
44
67
|
*/
|
|
45
|
-
export declare const MAX_KITTY_SEQUENCE_LENGTH =
|
|
68
|
+
export declare const MAX_KITTY_SEQUENCE_LENGTH = 32;
|
|
46
69
|
/**
|
|
47
70
|
* Character codes for common escape sequences
|
|
48
71
|
*/
|
|
@@ -21,6 +21,29 @@ export const KITTY_KEYCODE_ENTER = 13;
|
|
|
21
21
|
export const KITTY_KEYCODE_NUMPAD_ENTER = 57414;
|
|
22
22
|
export const KITTY_KEYCODE_TAB = 9;
|
|
23
23
|
export const KITTY_KEYCODE_BACKSPACE = 127;
|
|
24
|
+
/**
|
|
25
|
+
* Kitty modifier decoding constants
|
|
26
|
+
*
|
|
27
|
+
* In Kitty/Ghostty, the modifier parameter is encoded as (1 + bitmask).
|
|
28
|
+
* Some terminals also set bit 7 (i.e., add 128) when reporting event types.
|
|
29
|
+
*/
|
|
30
|
+
export const KITTY_MODIFIER_BASE = 1; // Base value per spec before bitmask decode
|
|
31
|
+
export const KITTY_MODIFIER_EVENT_TYPES_OFFSET = 128; // Added when event types are included
|
|
32
|
+
/**
|
|
33
|
+
* Modifier bit flags for Kitty/Xterm-style parameters.
|
|
34
|
+
*
|
|
35
|
+
* Per spec, the modifiers parameter encodes (1 + bitmask) where:
|
|
36
|
+
* - 1: no modifiers
|
|
37
|
+
* - bit 0 (1): Shift
|
|
38
|
+
* - bit 1 (2): Alt/Option (reported as "alt" in spec; we map to meta)
|
|
39
|
+
* - bit 2 (4): Ctrl
|
|
40
|
+
*
|
|
41
|
+
* Some terminals add 128 to the entire modifiers field when reporting event types.
|
|
42
|
+
* See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#modifiers
|
|
43
|
+
*/
|
|
44
|
+
export const MODIFIER_SHIFT_BIT = 1;
|
|
45
|
+
export const MODIFIER_ALT_BIT = 2;
|
|
46
|
+
export const MODIFIER_CTRL_BIT = 4;
|
|
24
47
|
/**
|
|
25
48
|
* Timing constants for terminal interactions
|
|
26
49
|
*/
|
|
@@ -42,7 +65,9 @@ export const BACKSLASH_ENTER_DETECTION_WINDOW_MS = 5;
|
|
|
42
65
|
* Longest reasonable: \x1b[127;15~ = 11 chars (Del with all modifiers)
|
|
43
66
|
* We use 12 to provide a small buffer.
|
|
44
67
|
*/
|
|
45
|
-
|
|
68
|
+
// Increased to accommodate parameterized forms and occasional colon subfields
|
|
69
|
+
// while still being small enough to avoid pathological buffering.
|
|
70
|
+
export const MAX_KITTY_SEQUENCE_LENGTH = 32;
|
|
46
71
|
/**
|
|
47
72
|
* Character codes for common escape sequences
|
|
48
73
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platformConstants.js","sourceRoot":"","sources":["../../../../src/ui/utils/platformConstants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AACtC,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,CAAC;AAChD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AACnC,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAEjD;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,QAAQ,CAAC;AAEpD;;;;GAIG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAE5C;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC;AAChC,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AACzC,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAC9B,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"platformConstants.js","sourceRoot":"","sources":["../../../../src/ui/utils/platformConstants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AACtC,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,CAAC;AAChD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AACnC,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,CAAC,4CAA4C;AAClF,MAAM,CAAC,MAAM,iCAAiC,GAAG,GAAG,CAAC,CAAC,sCAAsC;AAE5F;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAClC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAEnC;;GAEG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAEjD;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,QAAQ,CAAC;AAEpD;;;;GAIG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,CAAC;AAErD;;;;;;GAMG;AACH,8EAA8E;AAC9E,kEAAkE;AAClE,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAE5C;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC;AAChC,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AACzC,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAC9B,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { MergeStrategy } from '../config/settingsSchema.js';
|
|
7
|
+
type Mergeable = string | number | boolean | null | undefined | object | Mergeable[];
|
|
8
|
+
type MergeableObject = Record<string, Mergeable>;
|
|
9
|
+
export declare function customDeepMerge(getMergeStrategyForPath: (path: string[]) => MergeStrategy | undefined, ...sources: MergeableObject[]): MergeableObject;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { MergeStrategy } from '../config/settingsSchema.js';
|
|
7
|
+
function isPlainObject(item) {
|
|
8
|
+
return !!item && typeof item === 'object' && !Array.isArray(item);
|
|
9
|
+
}
|
|
10
|
+
function mergeRecursively(target, source, getMergeStrategyForPath, path = []) {
|
|
11
|
+
for (const key of Object.keys(source)) {
|
|
12
|
+
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
const newPath = [...path, key];
|
|
16
|
+
const srcValue = source[key];
|
|
17
|
+
const objValue = target[key];
|
|
18
|
+
const mergeStrategy = getMergeStrategyForPath(newPath);
|
|
19
|
+
if (mergeStrategy === MergeStrategy.SHALLOW_MERGE && objValue && srcValue) {
|
|
20
|
+
const obj1 = typeof objValue === 'object' && objValue !== null ? objValue : {};
|
|
21
|
+
const obj2 = typeof srcValue === 'object' && srcValue !== null ? srcValue : {};
|
|
22
|
+
target[key] = { ...obj1, ...obj2 };
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (Array.isArray(objValue)) {
|
|
26
|
+
const srcArray = Array.isArray(srcValue) ? srcValue : [srcValue];
|
|
27
|
+
if (mergeStrategy === MergeStrategy.CONCAT) {
|
|
28
|
+
target[key] = objValue.concat(srcArray);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (mergeStrategy === MergeStrategy.UNION) {
|
|
32
|
+
target[key] = [...new Set(objValue.concat(srcArray))];
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (isPlainObject(objValue) && isPlainObject(srcValue)) {
|
|
37
|
+
mergeRecursively(objValue, srcValue, getMergeStrategyForPath, newPath);
|
|
38
|
+
}
|
|
39
|
+
else if (isPlainObject(srcValue)) {
|
|
40
|
+
target[key] = {};
|
|
41
|
+
mergeRecursively(target[key], srcValue, getMergeStrategyForPath, newPath);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
target[key] = srcValue;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return target;
|
|
48
|
+
}
|
|
49
|
+
export function customDeepMerge(getMergeStrategyForPath, ...sources) {
|
|
50
|
+
const result = {};
|
|
51
|
+
for (const source of sources) {
|
|
52
|
+
if (source) {
|
|
53
|
+
mergeRecursively(result, source, getMergeStrategyForPath);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=deepMerge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deepMerge.js","sourceRoot":"","sources":["../../../src/utils/deepMerge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect } from 'vitest';
|
|
7
|
+
import { customDeepMerge } from './deepMerge.js';
|
|
8
|
+
import { MergeStrategy } from '../config/settingsSchema.js';
|
|
9
|
+
describe('customDeepMerge', () => {
|
|
10
|
+
it('should merge simple objects', () => {
|
|
11
|
+
const target = { a: 1, b: 2 };
|
|
12
|
+
const source = { b: 3, c: 4 };
|
|
13
|
+
const getMergeStrategy = () => undefined;
|
|
14
|
+
const result = customDeepMerge(getMergeStrategy, target, source);
|
|
15
|
+
expect(result).toEqual({ a: 1, b: 3, c: 4 });
|
|
16
|
+
});
|
|
17
|
+
it('should merge nested objects', () => {
|
|
18
|
+
const target = { a: { x: 1 }, b: 2 };
|
|
19
|
+
const source = { a: { y: 2 }, c: 3 };
|
|
20
|
+
const getMergeStrategy = () => undefined;
|
|
21
|
+
const result = customDeepMerge(getMergeStrategy, target, source);
|
|
22
|
+
expect(result).toEqual({ a: { x: 1, y: 2 }, b: 2, c: 3 });
|
|
23
|
+
});
|
|
24
|
+
it('should replace arrays by default', () => {
|
|
25
|
+
const target = { a: [1, 2] };
|
|
26
|
+
const source = { a: [3, 4] };
|
|
27
|
+
const getMergeStrategy = () => undefined;
|
|
28
|
+
const result = customDeepMerge(getMergeStrategy, target, source);
|
|
29
|
+
expect(result).toEqual({ a: [3, 4] });
|
|
30
|
+
});
|
|
31
|
+
it('should concatenate arrays with CONCAT strategy', () => {
|
|
32
|
+
const target = { a: [1, 2] };
|
|
33
|
+
const source = { a: [3, 4] };
|
|
34
|
+
const getMergeStrategy = (path) => path.join('.') === 'a' ? MergeStrategy.CONCAT : undefined;
|
|
35
|
+
const result = customDeepMerge(getMergeStrategy, target, source);
|
|
36
|
+
expect(result).toEqual({ a: [1, 2, 3, 4] });
|
|
37
|
+
});
|
|
38
|
+
it('should union arrays with UNION strategy', () => {
|
|
39
|
+
const target = { a: [1, 2, 3] };
|
|
40
|
+
const source = { a: [3, 4, 5] };
|
|
41
|
+
const getMergeStrategy = (path) => path.join('.') === 'a' ? MergeStrategy.UNION : undefined;
|
|
42
|
+
const result = customDeepMerge(getMergeStrategy, target, source);
|
|
43
|
+
expect(result).toEqual({ a: [1, 2, 3, 4, 5] });
|
|
44
|
+
});
|
|
45
|
+
it('should shallow merge objects with SHALLOW_MERGE strategy', () => {
|
|
46
|
+
const target = { a: { x: 1, y: 1 } };
|
|
47
|
+
const source = { a: { y: 2, z: 2 } };
|
|
48
|
+
const getMergeStrategy = (path) => path.join('.') === 'a' ? MergeStrategy.SHALLOW_MERGE : undefined;
|
|
49
|
+
const result = customDeepMerge(getMergeStrategy, target, source);
|
|
50
|
+
// This is still a deep merge, but the properties of the object are merged.
|
|
51
|
+
expect(result).toEqual({ a: { x: 1, y: 2, z: 2 } });
|
|
52
|
+
});
|
|
53
|
+
it('should handle multiple source objects', () => {
|
|
54
|
+
const target = { a: 1 };
|
|
55
|
+
const source1 = { b: 2 };
|
|
56
|
+
const source2 = { c: 3 };
|
|
57
|
+
const getMergeStrategy = () => undefined;
|
|
58
|
+
const result = customDeepMerge(getMergeStrategy, target, source1, source2);
|
|
59
|
+
expect(result).toEqual({ a: 1, b: 2, c: 3 });
|
|
60
|
+
});
|
|
61
|
+
it('should return an empty object if no sources are provided', () => {
|
|
62
|
+
const getMergeStrategy = () => undefined;
|
|
63
|
+
const result = customDeepMerge(getMergeStrategy);
|
|
64
|
+
expect(result).toEqual({});
|
|
65
|
+
});
|
|
66
|
+
it('should return a deep copy of the first source if only one is provided', () => {
|
|
67
|
+
const target = { a: { b: 1 } };
|
|
68
|
+
const getMergeStrategy = () => undefined;
|
|
69
|
+
const result = customDeepMerge(getMergeStrategy, target);
|
|
70
|
+
expect(result).toEqual(target);
|
|
71
|
+
expect(result).not.toBe(target);
|
|
72
|
+
});
|
|
73
|
+
it('should not mutate the original source objects', () => {
|
|
74
|
+
const target = { a: { x: 1 }, b: [1, 2] };
|
|
75
|
+
const source = { a: { y: 2 }, b: [3, 4] };
|
|
76
|
+
const originalTarget = JSON.parse(JSON.stringify(target));
|
|
77
|
+
const originalSource = JSON.parse(JSON.stringify(source));
|
|
78
|
+
const getMergeStrategy = () => undefined;
|
|
79
|
+
customDeepMerge(getMergeStrategy, target, source);
|
|
80
|
+
expect(target).toEqual(originalTarget);
|
|
81
|
+
expect(source).toEqual(originalSource);
|
|
82
|
+
});
|
|
83
|
+
it('should not mutate sources when merging multiple levels deep', () => {
|
|
84
|
+
const s1 = { data: { common: { val: 'from s1' }, s1_only: true } };
|
|
85
|
+
const s2 = { data: { common: { val: 'from s2' }, s2_only: true } };
|
|
86
|
+
const s1_original = JSON.parse(JSON.stringify(s1));
|
|
87
|
+
const s2_original = JSON.parse(JSON.stringify(s2));
|
|
88
|
+
const getMergeStrategy = () => undefined;
|
|
89
|
+
const result = customDeepMerge(getMergeStrategy, s1, s2);
|
|
90
|
+
expect(s1).toEqual(s1_original);
|
|
91
|
+
expect(s2).toEqual(s2_original);
|
|
92
|
+
expect(result).toEqual({
|
|
93
|
+
data: {
|
|
94
|
+
common: { val: 'from s2' },
|
|
95
|
+
s1_only: true,
|
|
96
|
+
s2_only: true,
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
it('should handle complex nested strategies', () => {
|
|
101
|
+
const target = {
|
|
102
|
+
level1: {
|
|
103
|
+
arr1: [1, 2],
|
|
104
|
+
arr2: [1, 2],
|
|
105
|
+
obj1: { a: 1 },
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
const source = {
|
|
109
|
+
level1: {
|
|
110
|
+
arr1: [3, 4],
|
|
111
|
+
arr2: [2, 3],
|
|
112
|
+
obj1: { b: 2 },
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
const getMergeStrategy = (path) => {
|
|
116
|
+
const p = path.join('.');
|
|
117
|
+
if (p === 'level1.arr1')
|
|
118
|
+
return MergeStrategy.CONCAT;
|
|
119
|
+
if (p === 'level1.arr2')
|
|
120
|
+
return MergeStrategy.UNION;
|
|
121
|
+
if (p === 'level1.obj1')
|
|
122
|
+
return MergeStrategy.SHALLOW_MERGE;
|
|
123
|
+
return undefined;
|
|
124
|
+
};
|
|
125
|
+
const result = customDeepMerge(getMergeStrategy, target, source);
|
|
126
|
+
expect(result).toEqual({
|
|
127
|
+
level1: {
|
|
128
|
+
arr1: [1, 2, 3, 4],
|
|
129
|
+
arr2: [1, 2, 3],
|
|
130
|
+
obj1: { a: 1, b: 2 },
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
it('should not pollute the prototype', () => {
|
|
135
|
+
const maliciousSource = JSON.parse('{"__proto__": {"polluted": "true"}}');
|
|
136
|
+
const getMergeStrategy = () => undefined;
|
|
137
|
+
const result = customDeepMerge(getMergeStrategy, {}, maliciousSource);
|
|
138
|
+
expect(result).toEqual({});
|
|
139
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
140
|
+
expect({}.polluted).toBeUndefined();
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
//# sourceMappingURL=deepMerge.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deepMerge.test.js","sourceRoot":"","sources":["../../../src/utils/deepMerge.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Resolves environment variables in a string.
|
|
8
|
+
* Replaces $VAR_NAME and ${VAR_NAME} with their corresponding environment variable values.
|
|
9
|
+
* If the environment variable is not defined, the original placeholder is preserved.
|
|
10
|
+
*
|
|
11
|
+
* @param value - The string that may contain environment variable placeholders
|
|
12
|
+
* @returns The string with environment variables resolved
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* resolveEnvVarsInString("Token: $API_KEY") // Returns "Token: secret-123"
|
|
16
|
+
* resolveEnvVarsInString("URL: ${BASE_URL}/api") // Returns "URL: https://api.example.com/api"
|
|
17
|
+
* resolveEnvVarsInString("Missing: $UNDEFINED_VAR") // Returns "Missing: $UNDEFINED_VAR"
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveEnvVarsInString(value: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Recursively resolves environment variables in an object of any type.
|
|
22
|
+
* Handles strings, arrays, nested objects, and preserves other primitive types.
|
|
23
|
+
* Protected against circular references using a WeakSet to track visited objects.
|
|
24
|
+
*
|
|
25
|
+
* @param obj - The object to process for environment variable resolution
|
|
26
|
+
* @returns A new object with environment variables resolved
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* const config = {
|
|
30
|
+
* server: {
|
|
31
|
+
* host: "$HOST",
|
|
32
|
+
* port: "${PORT}",
|
|
33
|
+
* enabled: true,
|
|
34
|
+
* tags: ["$ENV", "api"]
|
|
35
|
+
* }
|
|
36
|
+
* };
|
|
37
|
+
* const resolved = resolveEnvVarsInObject(config);
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveEnvVarsInObject<T>(obj: T): T;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Resolves environment variables in a string.
|
|
8
|
+
* Replaces $VAR_NAME and ${VAR_NAME} with their corresponding environment variable values.
|
|
9
|
+
* If the environment variable is not defined, the original placeholder is preserved.
|
|
10
|
+
*
|
|
11
|
+
* @param value - The string that may contain environment variable placeholders
|
|
12
|
+
* @returns The string with environment variables resolved
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* resolveEnvVarsInString("Token: $API_KEY") // Returns "Token: secret-123"
|
|
16
|
+
* resolveEnvVarsInString("URL: ${BASE_URL}/api") // Returns "URL: https://api.example.com/api"
|
|
17
|
+
* resolveEnvVarsInString("Missing: $UNDEFINED_VAR") // Returns "Missing: $UNDEFINED_VAR"
|
|
18
|
+
*/
|
|
19
|
+
export function resolveEnvVarsInString(value) {
|
|
20
|
+
const envVarRegex = /\$(?:(\w+)|{([^}]+)})/g; // Find $VAR_NAME or ${VAR_NAME}
|
|
21
|
+
return value.replace(envVarRegex, (match, varName1, varName2) => {
|
|
22
|
+
const varName = varName1 || varName2;
|
|
23
|
+
if (process && process.env && typeof process.env[varName] === 'string') {
|
|
24
|
+
return process.env[varName];
|
|
25
|
+
}
|
|
26
|
+
return match;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Recursively resolves environment variables in an object of any type.
|
|
31
|
+
* Handles strings, arrays, nested objects, and preserves other primitive types.
|
|
32
|
+
* Protected against circular references using a WeakSet to track visited objects.
|
|
33
|
+
*
|
|
34
|
+
* @param obj - The object to process for environment variable resolution
|
|
35
|
+
* @returns A new object with environment variables resolved
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* const config = {
|
|
39
|
+
* server: {
|
|
40
|
+
* host: "$HOST",
|
|
41
|
+
* port: "${PORT}",
|
|
42
|
+
* enabled: true,
|
|
43
|
+
* tags: ["$ENV", "api"]
|
|
44
|
+
* }
|
|
45
|
+
* };
|
|
46
|
+
* const resolved = resolveEnvVarsInObject(config);
|
|
47
|
+
*/
|
|
48
|
+
export function resolveEnvVarsInObject(obj) {
|
|
49
|
+
return resolveEnvVarsInObjectInternal(obj, new WeakSet());
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Internal implementation of resolveEnvVarsInObject with circular reference protection.
|
|
53
|
+
*
|
|
54
|
+
* @param obj - The object to process
|
|
55
|
+
* @param visited - WeakSet to track visited objects and prevent circular references
|
|
56
|
+
* @returns A new object with environment variables resolved
|
|
57
|
+
*/
|
|
58
|
+
function resolveEnvVarsInObjectInternal(obj, visited) {
|
|
59
|
+
if (obj === null ||
|
|
60
|
+
obj === undefined ||
|
|
61
|
+
typeof obj === 'boolean' ||
|
|
62
|
+
typeof obj === 'number') {
|
|
63
|
+
return obj;
|
|
64
|
+
}
|
|
65
|
+
if (typeof obj === 'string') {
|
|
66
|
+
return resolveEnvVarsInString(obj);
|
|
67
|
+
}
|
|
68
|
+
if (Array.isArray(obj)) {
|
|
69
|
+
// Check for circular reference
|
|
70
|
+
if (visited.has(obj)) {
|
|
71
|
+
// Return a shallow copy to break the cycle
|
|
72
|
+
return [...obj];
|
|
73
|
+
}
|
|
74
|
+
visited.add(obj);
|
|
75
|
+
const result = obj.map((item) => resolveEnvVarsInObjectInternal(item, visited));
|
|
76
|
+
visited.delete(obj);
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
if (typeof obj === 'object') {
|
|
80
|
+
// Check for circular reference
|
|
81
|
+
if (visited.has(obj)) {
|
|
82
|
+
// Return a shallow copy to break the cycle
|
|
83
|
+
return { ...obj };
|
|
84
|
+
}
|
|
85
|
+
visited.add(obj);
|
|
86
|
+
const newObj = { ...obj };
|
|
87
|
+
for (const key in newObj) {
|
|
88
|
+
if (Object.prototype.hasOwnProperty.call(newObj, key)) {
|
|
89
|
+
newObj[key] = resolveEnvVarsInObjectInternal(newObj[key], visited);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
visited.delete(obj);
|
|
93
|
+
return newObj;
|
|
94
|
+
}
|
|
95
|
+
return obj;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=envVarResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envVarResolver.js","sourceRoot":"","sources":["../../../src/utils/envVarResolver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAa;IAClD,MAAM,WAAW,GAAG,wBAAwB,CAAC,CAAC,gCAAgC;IAC9E,OAAO,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE;QAC9D,MAAM,OAAO,GAAG,QAAQ,IAAI,QAAQ,CAAC;QACrC,IAAI,OAAO,IAAI,OAAO,CAAC,GAAG,IAAI,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YACvE,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC;QAC/B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,sBAAsB,CAAI,GAAM;IAC9C,OAAO,8BAA8B,CAAC,GAAG,EAAE,IAAI,OAAO,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;GAMG;AACH,SAAS,8BAA8B,CACrC,GAAM,EACN,OAAwB;IAExB,IACE,GAAG,KAAK,IAAI;QACZ,GAAG,KAAK,SAAS;QACjB,OAAO,GAAG,KAAK,SAAS;QACxB,OAAO,GAAG,KAAK,QAAQ,EACvB,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,sBAAsB,CAAC,GAAG,CAAiB,CAAC;IACrD,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,+BAA+B;QAC/B,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,2CAA2C;YAC3C,OAAO,CAAC,GAAG,GAAG,CAAiB,CAAC;QAClC,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjB,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC9B,8BAA8B,CAAC,IAAI,EAAE,OAAO,CAAC,CAC9B,CAAC;QAClB,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,+BAA+B;QAC/B,IAAI,OAAO,CAAC,GAAG,CAAC,GAAa,CAAC,EAAE,CAAC;YAC/B,2CAA2C;YAC3C,OAAO,EAAE,GAAG,GAAG,EAAO,CAAC;QACzB,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,GAAa,CAAC,CAAC;QAC3B,MAAM,MAAM,GAAG,EAAE,GAAG,GAAG,EAAO,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;gBACtD,MAAM,CAAC,GAAG,CAAC,GAAG,8BAA8B,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,GAAa,CAAC,CAAC;QAC9B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
|