@zincapp/znvault-cli 2.18.1 → 2.19.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/secret/index.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8BzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgB7D;AAGD,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/secret/index.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+BzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiB7D;AAGD,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC"}
@@ -8,6 +8,7 @@ import { registerDeleteCommand } from './delete.js';
8
8
  import { registerRotateCommand } from './rotate.js';
9
9
  import { registerHistoryCommand } from './history.js';
10
10
  import { registerCopyCommand } from './copy.js';
11
+ import { registerPatchCommand } from './patch.js';
11
12
  // Help text for secret identifier format
12
13
  const SECRET_ID_HELP = `
13
14
  Secret Identifier Formats:
@@ -41,6 +42,7 @@ export function registerSecretCommands(program) {
41
42
  registerRotateCommand(secretCmd);
42
43
  registerHistoryCommand(secretCmd);
43
44
  registerCopyCommand(secretCmd);
45
+ registerPatchCommand(secretCmd);
44
46
  }
45
47
  // Re-export types for external use
46
48
  export * from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/secret/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAUrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,yCAAyC;AACzC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;CAgBtB,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,SAAS,GAAG,OAAO;SACtB,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,gBAAgB,CAAC;SAC7B,WAAW,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAExC,2BAA2B;IAC3B,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAC/B,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC9B,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAClC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACjC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACjC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACjC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACjC,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAClC,mBAAmB,CAAC,SAAS,CAAC,CAAC;AACjC,CAAC;AAED,mCAAmC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/secret/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAUrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAElD,yCAAyC;AACzC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;CAgBtB,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,SAAS,GAAG,OAAO;SACtB,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,gBAAgB,CAAC;SAC7B,WAAW,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAExC,2BAA2B;IAC3B,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAC/B,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC9B,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAClC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACjC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACjC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACjC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACjC,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAClC,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAC/B,oBAAoB,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,mCAAmC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { DiffResult, AppliedOperation } from './types.js';
2
+ /**
3
+ * Generate a diff between two serialized values
4
+ */
5
+ export declare function generateDiff(before: string, after: string, operations: AppliedOperation[]): DiffResult;
6
+ /**
7
+ * Display a diff result
8
+ */
9
+ export declare function displayDiff(diff: DiffResult): void;
10
+ /**
11
+ * Display a summary of operations to be applied
12
+ */
13
+ export declare function displayOperationsSummary(operations: AppliedOperation[]): void;
14
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../../src/commands/secret/patch/diff.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAc,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAO3E;;GAEG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,gBAAgB,EAAE,GAC7B,UAAU,CA0BZ;AA8CD;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAuClD;AAsDD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAyB7E"}
@@ -0,0 +1,181 @@
1
+ // Path: src/commands/secret/patch/diff.ts
2
+ /**
3
+ * Diff generation for dry-run mode
4
+ */
5
+ import chalk from 'chalk';
6
+ import { isPlainMode } from '../../../lib/output-mode.js';
7
+ // ============================================================================
8
+ // Diff Generation
9
+ // ============================================================================
10
+ /**
11
+ * Generate a diff between two serialized values
12
+ */
13
+ export function generateDiff(before, after, operations) {
14
+ const changes = operations.map(op => {
15
+ if (op.type === 'set') {
16
+ if (op.previousValue === undefined) {
17
+ return {
18
+ type: 'add',
19
+ path: op.path,
20
+ newValue: op.newValue,
21
+ };
22
+ }
23
+ return {
24
+ type: 'modify',
25
+ path: op.path,
26
+ oldValue: op.previousValue,
27
+ newValue: op.newValue,
28
+ };
29
+ }
30
+ else {
31
+ return {
32
+ type: 'remove',
33
+ path: op.path,
34
+ oldValue: op.previousValue,
35
+ };
36
+ }
37
+ });
38
+ return { before, after, changes };
39
+ }
40
+ // ============================================================================
41
+ // Diff Display
42
+ // ============================================================================
43
+ /**
44
+ * Format a diff change for display
45
+ */
46
+ function formatChange(change, plain) {
47
+ const formatValue = (val) => {
48
+ if (val === undefined)
49
+ return 'undefined';
50
+ if (val === null)
51
+ return 'null';
52
+ if (typeof val === 'string')
53
+ return `"${val}"`;
54
+ if (typeof val === 'object')
55
+ return JSON.stringify(val);
56
+ if (typeof val === 'number' || typeof val === 'boolean')
57
+ return String(val);
58
+ // For bigint, symbol, or other types
59
+ return JSON.stringify(val);
60
+ };
61
+ switch (change.type) {
62
+ case 'add':
63
+ if (plain) {
64
+ return `+ ${change.path} = ${formatValue(change.newValue)}`;
65
+ }
66
+ return chalk.green(`+ ${change.path} = ${formatValue(change.newValue)}`);
67
+ case 'remove':
68
+ if (plain) {
69
+ return `- ${change.path} = ${formatValue(change.oldValue)}`;
70
+ }
71
+ return chalk.red(`- ${change.path} = ${formatValue(change.oldValue)}`);
72
+ case 'modify':
73
+ if (plain) {
74
+ return `~ ${change.path}: ${formatValue(change.oldValue)} -> ${formatValue(change.newValue)}`;
75
+ }
76
+ return chalk.yellow(`~ ${change.path}: ` +
77
+ chalk.red(formatValue(change.oldValue)) +
78
+ chalk.gray(' -> ') +
79
+ chalk.green(formatValue(change.newValue)));
80
+ }
81
+ }
82
+ /**
83
+ * Display a diff result
84
+ */
85
+ export function displayDiff(diff) {
86
+ const plain = isPlainMode();
87
+ console.log();
88
+ if (plain) {
89
+ console.log('=== Changes to be applied ===');
90
+ }
91
+ else {
92
+ console.log(chalk.bold.cyan('Changes to be applied:'));
93
+ }
94
+ console.log();
95
+ if (diff.changes.length === 0) {
96
+ if (plain) {
97
+ console.log('No changes detected');
98
+ }
99
+ else {
100
+ console.log(chalk.dim('No changes detected'));
101
+ }
102
+ return;
103
+ }
104
+ for (const change of diff.changes) {
105
+ console.log(' ' + formatChange(change, plain));
106
+ }
107
+ console.log();
108
+ if (plain) {
109
+ console.log('=== Before ===');
110
+ }
111
+ else {
112
+ console.log(chalk.bold.dim('Before:'));
113
+ }
114
+ displayWithHighlight(diff.before, 'remove', plain);
115
+ console.log();
116
+ if (plain) {
117
+ console.log('=== After ===');
118
+ }
119
+ else {
120
+ console.log(chalk.bold.dim('After:'));
121
+ }
122
+ displayWithHighlight(diff.after, 'add', plain);
123
+ }
124
+ /**
125
+ * Display content with syntax highlighting
126
+ */
127
+ function displayWithHighlight(content, _type, plain) {
128
+ const lines = content.split('\n');
129
+ for (const line of lines) {
130
+ if (plain) {
131
+ console.log(` ${line}`);
132
+ }
133
+ else {
134
+ // Simple syntax highlighting
135
+ let highlighted = line;
136
+ // Highlight keys
137
+ highlighted = highlighted.replace(/^(\s*)("?[a-zA-Z_][a-zA-Z0-9_-]*"?)\s*:/, `$1${chalk.cyan('$2')}:`);
138
+ // Highlight string values
139
+ highlighted = highlighted.replace(/:\s*("(?:[^"\\]|\\.)*")/g, `: ${chalk.green('$1')}`);
140
+ // Highlight numbers
141
+ highlighted = highlighted.replace(/:\s*(-?\d+\.?\d*)/g, `: ${chalk.yellow('$1')}`);
142
+ // Highlight booleans
143
+ highlighted = highlighted.replace(/:\s*(true|false)/g, `: ${chalk.magenta('$1')}`);
144
+ // Highlight null
145
+ highlighted = highlighted.replace(/:\s*(null)/g, `: ${chalk.dim('$1')}`);
146
+ console.log(` ${highlighted}`);
147
+ }
148
+ }
149
+ }
150
+ // ============================================================================
151
+ // Summary Display
152
+ // ============================================================================
153
+ /**
154
+ * Display a summary of operations to be applied
155
+ */
156
+ export function displayOperationsSummary(operations) {
157
+ const plain = isPlainMode();
158
+ const adds = operations.filter(o => o.type === 'set' && o.previousValue === undefined).length;
159
+ const modifies = operations.filter(o => o.type === 'set' && o.previousValue !== undefined).length;
160
+ const removes = operations.filter(o => o.type === 'unset').length;
161
+ const parts = [];
162
+ if (adds > 0) {
163
+ parts.push(plain ? `${adds} add` : chalk.green(`${adds} add`));
164
+ }
165
+ if (modifies > 0) {
166
+ parts.push(plain ? `${modifies} modify` : chalk.yellow(`${modifies} modify`));
167
+ }
168
+ if (removes > 0) {
169
+ parts.push(plain ? `${removes} remove` : chalk.red(`${removes} remove`));
170
+ }
171
+ if (parts.length > 0) {
172
+ console.log();
173
+ if (plain) {
174
+ console.log(`Summary: ${parts.join(', ')}`);
175
+ }
176
+ else {
177
+ console.log(chalk.dim('Summary: ') + parts.join(chalk.dim(', ')));
178
+ }
179
+ }
180
+ }
181
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../../src/commands/secret/patch/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Path parsing and set/unset operations for secret patching
3
+ */
4
+ import { type ParsedPath, type PatchOperation, type AppliedOperation } from './types.js';
5
+ /**
6
+ * Parse a dot-notation path into segments
7
+ * Supports:
8
+ * - key -> top-level key
9
+ * - a.b.c -> nested keys
10
+ * - arr[0] -> array index
11
+ * - arr[+] -> array append
12
+ * - a.b[0].c -> mixed paths
13
+ *
14
+ * @param path - The path string to parse
15
+ * @returns ParsedPath with segments
16
+ */
17
+ export declare function parsePath(path: string): ParsedPath;
18
+ /**
19
+ * Infer the type of a string value and convert it
20
+ * - "true"/"false" -> boolean
21
+ * - numeric strings -> number
22
+ * - "null" -> null
23
+ * - otherwise -> string
24
+ *
25
+ * @param value - The string value to infer
26
+ * @returns The inferred value with correct type
27
+ */
28
+ export declare function inferValueType(value: string): unknown;
29
+ /**
30
+ * Parse a value that might be JSON
31
+ * If it starts with { or [, try to parse as JSON
32
+ * Otherwise use type inference
33
+ */
34
+ export declare function parseValue(value: string): unknown;
35
+ /**
36
+ * Get a value at a path from an object
37
+ */
38
+ export declare function getAtPath(obj: unknown, parsedPath: ParsedPath): unknown;
39
+ /**
40
+ * Set a value at a path in an object (mutates the object)
41
+ *
42
+ * @param obj - The object to modify
43
+ * @param parsedPath - The parsed path
44
+ * @param value - The value to set
45
+ * @returns The previous value at the path (if any)
46
+ */
47
+ export declare function setAtPath(obj: Record<string, unknown>, parsedPath: ParsedPath, value: unknown): unknown;
48
+ /**
49
+ * Remove a value at a path in an object (mutates the object)
50
+ *
51
+ * @param obj - The object to modify
52
+ * @param parsedPath - The parsed path
53
+ * @returns The removed value (if any)
54
+ */
55
+ export declare function unsetAtPath(obj: Record<string, unknown>, parsedPath: ParsedPath): unknown;
56
+ /**
57
+ * Apply a list of patch operations to an object
58
+ *
59
+ * @param obj - The object to modify (will be deep cloned)
60
+ * @param operations - The operations to apply
61
+ * @returns Array of applied operations with details
62
+ */
63
+ export declare function applyOperations(obj: Record<string, unknown>, operations: PatchOperation[]): AppliedOperation[];
64
+ /**
65
+ * Parse --set arguments into operations
66
+ * Format: path=value
67
+ */
68
+ export declare function parseSetArgs(args: string[]): PatchOperation[];
69
+ /**
70
+ * Parse --unset arguments into operations
71
+ */
72
+ export declare function parseUnsetArgs(args: string[]): PatchOperation[];
73
+ /**
74
+ * Deep clone an object
75
+ */
76
+ export declare function deepClone<T>(obj: T): T;
77
+ //# sourceMappingURL=operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../../../src/commands/secret/patch/operations.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,gBAAgB,EAEtB,MAAM,YAAY,CAAC;AAMpB;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CA0ElD;AAMD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAkBrD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAejD;AAMD;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAyBvE;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,OAAO,GACb,OAAO,CAyDT;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,UAAU,EAAE,UAAU,GACrB,OAAO,CA+DT;AAMD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,UAAU,EAAE,cAAc,EAAE,GAC3B,gBAAgB,EAAE,CA0BpB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAoB7D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAK/D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAEtC"}
@@ -0,0 +1,351 @@
1
+ // Path: src/commands/secret/patch/operations.ts
2
+ /**
3
+ * Path parsing and set/unset operations for secret patching
4
+ */
5
+ import { PatchError, } from './types.js';
6
+ // ============================================================================
7
+ // Path Parsing
8
+ // ============================================================================
9
+ /**
10
+ * Parse a dot-notation path into segments
11
+ * Supports:
12
+ * - key -> top-level key
13
+ * - a.b.c -> nested keys
14
+ * - arr[0] -> array index
15
+ * - arr[+] -> array append
16
+ * - a.b[0].c -> mixed paths
17
+ *
18
+ * @param path - The path string to parse
19
+ * @returns ParsedPath with segments
20
+ */
21
+ export function parsePath(path) {
22
+ if (!path || path.trim() === '') {
23
+ throw new PatchError('Empty path', 'INVALID_PATH', { path });
24
+ }
25
+ const segments = [];
26
+ let current = '';
27
+ let i = 0;
28
+ while (i < path.length) {
29
+ const char = path[i];
30
+ if (char === '.') {
31
+ // End of a key segment
32
+ if (current) {
33
+ segments.push({ type: 'key', key: current });
34
+ current = '';
35
+ }
36
+ i++;
37
+ }
38
+ else if (char === '[') {
39
+ // Start of array index
40
+ if (current) {
41
+ segments.push({ type: 'key', key: current });
42
+ current = '';
43
+ }
44
+ // Find closing bracket
45
+ const closingBracket = path.indexOf(']', i);
46
+ if (closingBracket === -1) {
47
+ throw new PatchError(`Unclosed bracket in path: ${path}`, 'INVALID_PATH', { path, position: i });
48
+ }
49
+ const indexStr = path.slice(i + 1, closingBracket);
50
+ if (indexStr === '+') {
51
+ // Append operation
52
+ segments.push({ type: 'append' });
53
+ }
54
+ else if (/^\d+$/.test(indexStr)) {
55
+ // Numeric index
56
+ segments.push({ type: 'index', index: parseInt(indexStr, 10) });
57
+ }
58
+ else {
59
+ throw new PatchError(`Invalid array index: ${indexStr}`, 'INVALID_PATH', { path, index: indexStr });
60
+ }
61
+ i = closingBracket + 1;
62
+ // Skip dot after bracket if present
63
+ if (i < path.length && path[i] === '.') {
64
+ i++;
65
+ }
66
+ }
67
+ else {
68
+ current += char;
69
+ i++;
70
+ }
71
+ }
72
+ // Add final segment
73
+ if (current) {
74
+ segments.push({ type: 'key', key: current });
75
+ }
76
+ if (segments.length === 0) {
77
+ throw new PatchError('Path has no valid segments', 'INVALID_PATH', { path });
78
+ }
79
+ return { segments, raw: path };
80
+ }
81
+ // ============================================================================
82
+ // Value Type Inference
83
+ // ============================================================================
84
+ /**
85
+ * Infer the type of a string value and convert it
86
+ * - "true"/"false" -> boolean
87
+ * - numeric strings -> number
88
+ * - "null" -> null
89
+ * - otherwise -> string
90
+ *
91
+ * @param value - The string value to infer
92
+ * @returns The inferred value with correct type
93
+ */
94
+ export function inferValueType(value) {
95
+ // Boolean
96
+ if (value === 'true')
97
+ return true;
98
+ if (value === 'false')
99
+ return false;
100
+ // Null
101
+ if (value === 'null')
102
+ return null;
103
+ // Number (integer or float)
104
+ if (/^-?\d+$/.test(value)) {
105
+ return parseInt(value, 10);
106
+ }
107
+ if (/^-?\d+\.\d+$/.test(value)) {
108
+ return parseFloat(value);
109
+ }
110
+ // String (default)
111
+ return value;
112
+ }
113
+ /**
114
+ * Parse a value that might be JSON
115
+ * If it starts with { or [, try to parse as JSON
116
+ * Otherwise use type inference
117
+ */
118
+ export function parseValue(value) {
119
+ const trimmed = value.trim();
120
+ // Try to parse as JSON for objects and arrays
121
+ if ((trimmed.startsWith('{') && trimmed.endsWith('}')) ||
122
+ (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
123
+ try {
124
+ return JSON.parse(trimmed);
125
+ }
126
+ catch {
127
+ // Not valid JSON, return as string
128
+ return value;
129
+ }
130
+ }
131
+ return inferValueType(value);
132
+ }
133
+ // ============================================================================
134
+ // Set/Unset Operations
135
+ // ============================================================================
136
+ /**
137
+ * Get a value at a path from an object
138
+ */
139
+ export function getAtPath(obj, parsedPath) {
140
+ let current = obj;
141
+ for (const segment of parsedPath.segments) {
142
+ if (current === null || current === undefined) {
143
+ return undefined;
144
+ }
145
+ if (segment.type === 'key') {
146
+ if (typeof current !== 'object' || Array.isArray(current)) {
147
+ return undefined;
148
+ }
149
+ current = current[segment.key];
150
+ }
151
+ else if (segment.type === 'index') {
152
+ if (!Array.isArray(current)) {
153
+ return undefined;
154
+ }
155
+ current = current[segment.index];
156
+ }
157
+ else {
158
+ // segment.type === 'append': Can't get from append position
159
+ return undefined;
160
+ }
161
+ }
162
+ return current;
163
+ }
164
+ /**
165
+ * Set a value at a path in an object (mutates the object)
166
+ *
167
+ * @param obj - The object to modify
168
+ * @param parsedPath - The parsed path
169
+ * @param value - The value to set
170
+ * @returns The previous value at the path (if any)
171
+ */
172
+ export function setAtPath(obj, parsedPath, value) {
173
+ const { segments } = parsedPath;
174
+ // Navigate to parent, creating intermediate objects/arrays as needed
175
+ let current = obj;
176
+ for (let i = 0; i < segments.length - 1; i++) {
177
+ const segment = segments[i];
178
+ const nextSegment = segments[i + 1];
179
+ if (segment.type === 'key') {
180
+ const currentObj = current;
181
+ // Create intermediate container based on next segment type
182
+ currentObj[segment.key] ??= nextSegment.type === 'index' || nextSegment.type === 'append'
183
+ ? []
184
+ : {};
185
+ current = currentObj[segment.key];
186
+ }
187
+ else if (segment.type === 'index') {
188
+ const currentArr = current;
189
+ currentArr[segment.index] ??= nextSegment.type === 'index' || nextSegment.type === 'append'
190
+ ? []
191
+ : {};
192
+ current = currentArr[segment.index];
193
+ }
194
+ else {
195
+ throw new PatchError('Append operator [+] can only be used at the end of a path', 'INVALID_PATH', { path: parsedPath.raw });
196
+ }
197
+ }
198
+ // Set the final value
199
+ const lastSegment = segments[segments.length - 1];
200
+ let previousValue;
201
+ if (lastSegment.type === 'key') {
202
+ const parent = current;
203
+ previousValue = parent[lastSegment.key];
204
+ parent[lastSegment.key] = value;
205
+ }
206
+ else if (lastSegment.type === 'index') {
207
+ const parent = current;
208
+ previousValue = parent[lastSegment.index];
209
+ parent[lastSegment.index] = value;
210
+ }
211
+ else {
212
+ // lastSegment.type === 'append'
213
+ if (!Array.isArray(current)) {
214
+ throw new PatchError('Cannot append to non-array', 'TYPE_MISMATCH', { path: parsedPath.raw, actualType: typeof current });
215
+ }
216
+ current.push(value);
217
+ previousValue = undefined;
218
+ }
219
+ return previousValue;
220
+ }
221
+ /**
222
+ * Remove a value at a path in an object (mutates the object)
223
+ *
224
+ * @param obj - The object to modify
225
+ * @param parsedPath - The parsed path
226
+ * @returns The removed value (if any)
227
+ */
228
+ export function unsetAtPath(obj, parsedPath) {
229
+ const { segments } = parsedPath;
230
+ // Navigate to parent
231
+ let current = obj;
232
+ for (let i = 0; i < segments.length - 1; i++) {
233
+ const segment = segments[i];
234
+ if (segment.type === 'key') {
235
+ const currentObj = current;
236
+ if (currentObj[segment.key] === undefined) {
237
+ return undefined; // Path doesn't exist
238
+ }
239
+ current = currentObj[segment.key];
240
+ }
241
+ else if (segment.type === 'index') {
242
+ const currentArr = current;
243
+ if (currentArr[segment.index] === undefined) {
244
+ return undefined;
245
+ }
246
+ current = currentArr[segment.index];
247
+ }
248
+ else {
249
+ throw new PatchError('Append operator [+] cannot be used with unset', 'UNSUPPORTED_OPERATION', { path: parsedPath.raw });
250
+ }
251
+ if (current === null || current === undefined) {
252
+ return undefined;
253
+ }
254
+ }
255
+ // Remove the final value
256
+ const lastSegment = segments[segments.length - 1];
257
+ let removedValue;
258
+ if (lastSegment.type === 'key') {
259
+ if (typeof current !== 'object' || Array.isArray(current) || current === null) {
260
+ return undefined;
261
+ }
262
+ const parent = current;
263
+ const keyToDelete = lastSegment.key;
264
+ removedValue = parent[keyToDelete];
265
+ Reflect.deleteProperty(parent, keyToDelete);
266
+ }
267
+ else if (lastSegment.type === 'index') {
268
+ if (!Array.isArray(current)) {
269
+ return undefined;
270
+ }
271
+ const parent = current;
272
+ if (lastSegment.index >= 0 && lastSegment.index < parent.length) {
273
+ removedValue = parent[lastSegment.index];
274
+ parent.splice(lastSegment.index, 1);
275
+ }
276
+ }
277
+ else {
278
+ throw new PatchError('Append operator [+] cannot be used with unset', 'UNSUPPORTED_OPERATION', { path: parsedPath.raw });
279
+ }
280
+ return removedValue;
281
+ }
282
+ // ============================================================================
283
+ // Apply Operations
284
+ // ============================================================================
285
+ /**
286
+ * Apply a list of patch operations to an object
287
+ *
288
+ * @param obj - The object to modify (will be deep cloned)
289
+ * @param operations - The operations to apply
290
+ * @returns Array of applied operations with details
291
+ */
292
+ export function applyOperations(obj, operations) {
293
+ const applied = [];
294
+ for (const op of operations) {
295
+ const parsedPath = parsePath(op.path);
296
+ if (op.type === 'set') {
297
+ const previousValue = setAtPath(obj, parsedPath, op.value);
298
+ applied.push({
299
+ type: 'set',
300
+ path: op.path,
301
+ previousValue,
302
+ newValue: op.value,
303
+ });
304
+ }
305
+ else {
306
+ // op.type === 'unset'
307
+ const removedValue = unsetAtPath(obj, parsedPath);
308
+ applied.push({
309
+ type: 'unset',
310
+ path: op.path,
311
+ previousValue: removedValue,
312
+ });
313
+ }
314
+ }
315
+ return applied;
316
+ }
317
+ /**
318
+ * Parse --set arguments into operations
319
+ * Format: path=value
320
+ */
321
+ export function parseSetArgs(args) {
322
+ return args.map(arg => {
323
+ const eqIndex = arg.indexOf('=');
324
+ if (eqIndex === -1) {
325
+ throw new PatchError(`Invalid --set argument: ${arg} (expected path=value)`, 'INVALID_VALUE', { arg });
326
+ }
327
+ const path = arg.slice(0, eqIndex);
328
+ const valueStr = arg.slice(eqIndex + 1);
329
+ return {
330
+ type: 'set',
331
+ path,
332
+ value: parseValue(valueStr),
333
+ };
334
+ });
335
+ }
336
+ /**
337
+ * Parse --unset arguments into operations
338
+ */
339
+ export function parseUnsetArgs(args) {
340
+ return args.map(path => ({
341
+ type: 'unset',
342
+ path,
343
+ }));
344
+ }
345
+ /**
346
+ * Deep clone an object
347
+ */
348
+ export function deepClone(obj) {
349
+ return JSON.parse(JSON.stringify(obj));
350
+ }
351
+ //# sourceMappingURL=operations.js.map