@nocoo/otter 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +5 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +365 -0
- package/dist/cli.js.map +1 -0
- package/dist/collectors/applications.d.ts +19 -0
- package/dist/collectors/applications.d.ts.map +1 -0
- package/dist/collectors/applications.js +51 -0
- package/dist/collectors/applications.js.map +1 -0
- package/dist/collectors/base.d.ts +52 -0
- package/dist/collectors/base.d.ts.map +1 -0
- package/dist/collectors/base.js +186 -0
- package/dist/collectors/base.js.map +1 -0
- package/dist/collectors/claude-config.d.ts +39 -0
- package/dist/collectors/claude-config.d.ts.map +1 -0
- package/dist/collectors/claude-config.js +124 -0
- package/dist/collectors/claude-config.js.map +1 -0
- package/dist/collectors/homebrew.d.ts +16 -0
- package/dist/collectors/homebrew.d.ts.map +1 -0
- package/dist/collectors/homebrew.js +43 -0
- package/dist/collectors/homebrew.js.map +1 -0
- package/dist/collectors/index.d.ts +21 -0
- package/dist/collectors/index.d.ts.map +1 -0
- package/dist/collectors/index.js +28 -0
- package/dist/collectors/index.js.map +1 -0
- package/dist/collectors/opencode-config.d.ts +21 -0
- package/dist/collectors/opencode-config.d.ts.map +1 -0
- package/dist/collectors/opencode-config.js +88 -0
- package/dist/collectors/opencode-config.js.map +1 -0
- package/dist/collectors/shell-config.d.ts +24 -0
- package/dist/collectors/shell-config.d.ts.map +1 -0
- package/dist/collectors/shell-config.js +133 -0
- package/dist/collectors/shell-config.js.map +1 -0
- package/dist/commands/config.d.ts +17 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +21 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/scan.d.ts +11 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +36 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/snapshot.d.ts +52 -0
- package/dist/commands/snapshot.d.ts.map +1 -0
- package/dist/commands/snapshot.js +203 -0
- package/dist/commands/snapshot.js.map +1 -0
- package/dist/config/manager.d.ts +13 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +28 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/snapshot/builder.d.ts +7 -0
- package/dist/snapshot/builder.d.ts.map +1 -0
- package/dist/snapshot/builder.js +68 -0
- package/dist/snapshot/builder.js.map +1 -0
- package/dist/storage/local.d.ts +44 -0
- package/dist/storage/local.d.ts.map +1 -0
- package/dist/storage/local.js +107 -0
- package/dist/storage/local.js.map +1 -0
- package/dist/uploader/icons.d.ts +41 -0
- package/dist/uploader/icons.d.ts.map +1 -0
- package/dist/uploader/icons.js +80 -0
- package/dist/uploader/icons.js.map +1 -0
- package/dist/uploader/webhook.d.ts +7 -0
- package/dist/uploader/webhook.d.ts.map +1 -0
- package/dist/uploader/webhook.js +54 -0
- package/dist/uploader/webhook.js.map +1 -0
- package/dist/utils/icons.d.ts +34 -0
- package/dist/utils/icons.d.ts.map +1 -0
- package/dist/utils/icons.js +113 -0
- package/dist/utils/icons.js.map +1 -0
- package/dist/utils/redact.d.ts +41 -0
- package/dist/utils/redact.d.ts.map +1 -0
- package/dist/utils/redact.js +317 -0
- package/dist/utils/redact.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential redaction utilities.
|
|
3
|
+
*
|
|
4
|
+
* Strips sensitive values from file content before including
|
|
5
|
+
* them in snapshots. Works on both structured (JSON) and
|
|
6
|
+
* line-oriented (ini-like) config formats.
|
|
7
|
+
*/
|
|
8
|
+
const REDACTED = "[REDACTED]";
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// JSON env-block redaction (for settings.json, etc.)
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/** Keys whose values should always be redacted in JSON objects */
|
|
13
|
+
const SENSITIVE_KEY_PATTERNS = [
|
|
14
|
+
/token/i,
|
|
15
|
+
/secret/i,
|
|
16
|
+
/api.?key/i,
|
|
17
|
+
/password/i,
|
|
18
|
+
/credential/i,
|
|
19
|
+
/auth/i,
|
|
20
|
+
];
|
|
21
|
+
function isSensitiveKey(key) {
|
|
22
|
+
return SENSITIVE_KEY_PATTERNS.some((p) => p.test(key));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Deep-walk a parsed JSON value and redact any string values
|
|
26
|
+
* whose keys match sensitive patterns.
|
|
27
|
+
*
|
|
28
|
+
* Returns [redactedValue, didRedact] tuple.
|
|
29
|
+
*/
|
|
30
|
+
function redactObject(obj) {
|
|
31
|
+
if (obj === null || obj === undefined)
|
|
32
|
+
return [obj, false];
|
|
33
|
+
if (typeof obj !== "object")
|
|
34
|
+
return [obj, false];
|
|
35
|
+
if (Array.isArray(obj)) {
|
|
36
|
+
let anyRedacted = false;
|
|
37
|
+
const mapped = obj.map((item) => {
|
|
38
|
+
const [val, redacted] = redactObject(item);
|
|
39
|
+
if (redacted)
|
|
40
|
+
anyRedacted = true;
|
|
41
|
+
return val;
|
|
42
|
+
});
|
|
43
|
+
return [mapped, anyRedacted];
|
|
44
|
+
}
|
|
45
|
+
let anyRedacted = false;
|
|
46
|
+
const result = {};
|
|
47
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
48
|
+
if (typeof value === "string" && isSensitiveKey(key)) {
|
|
49
|
+
result[key] = REDACTED;
|
|
50
|
+
anyRedacted = true;
|
|
51
|
+
}
|
|
52
|
+
else if (typeof value === "object" && value !== null) {
|
|
53
|
+
const [val, redacted] = redactObject(value);
|
|
54
|
+
result[key] = val;
|
|
55
|
+
if (redacted)
|
|
56
|
+
anyRedacted = true;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
result[key] = value;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return [result, anyRedacted];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Redact sensitive values in a JSON string.
|
|
66
|
+
* Returns the original string if no redaction was needed or parsing fails.
|
|
67
|
+
*/
|
|
68
|
+
export function redactJsonSecrets(jsonContent) {
|
|
69
|
+
try {
|
|
70
|
+
const parsed = JSON.parse(jsonContent);
|
|
71
|
+
const [redacted, didRedact] = redactObject(parsed);
|
|
72
|
+
if (!didRedact)
|
|
73
|
+
return jsonContent;
|
|
74
|
+
// Re-serialize with 2-space indent
|
|
75
|
+
return JSON.stringify(redacted, null, 2);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// If not valid JSON, return as-is
|
|
79
|
+
return jsonContent;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// Line-oriented redaction (for .npmrc, .gitconfig, etc.)
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
/** Patterns that match credential lines in ini-style config files */
|
|
86
|
+
const LINE_REDACTION_PATTERNS = [
|
|
87
|
+
// .npmrc: //registry.npmjs.org/:_authToken=xxx
|
|
88
|
+
/^(\s*\/\/[^:]+\/:_authToken\s*=\s*).+$/,
|
|
89
|
+
// .npmrc: _auth=xxx
|
|
90
|
+
/^(\s*_auth\s*=\s*).+$/,
|
|
91
|
+
// .gitconfig: helper = store / credential block values
|
|
92
|
+
/^(\s*helper\s*=\s*store).*$/,
|
|
93
|
+
// Generic key=value where key contains token/secret/password/key
|
|
94
|
+
/^(\s*(?:.*(?:token|secret|password|api.?key|credential|auth)\w*)\s*=\s*).+$/i,
|
|
95
|
+
];
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Shell script redaction (for .zshrc, .bashrc, .profile, etc.)
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
/**
|
|
100
|
+
* Patterns that match sensitive variable assignments in shell scripts.
|
|
101
|
+
* Captures the prefix (everything before the secret value) so we can
|
|
102
|
+
* replace just the value portion with [REDACTED].
|
|
103
|
+
*/
|
|
104
|
+
const SHELL_REDACTION_PATTERNS = [
|
|
105
|
+
// export KEY="value" or export KEY='value' or export KEY=value
|
|
106
|
+
// where KEY contains: TOKEN, SECRET, KEY, PASSWORD, CREDENTIAL, AUTH
|
|
107
|
+
/^(\s*export\s+\w*(?:TOKEN|SECRET|KEY|PASSWORD|CREDENTIAL|AUTH)\w*=).*$/i,
|
|
108
|
+
// Plain assignment (no export): KEY="value"
|
|
109
|
+
/^(\s*\w*(?:TOKEN|SECRET|KEY|PASSWORD|CREDENTIAL|AUTH)\w*=).*$/i,
|
|
110
|
+
];
|
|
111
|
+
/** Shell config filenames that should receive shell-script redaction */
|
|
112
|
+
const SHELL_CONFIG_NAMES = new Set([
|
|
113
|
+
".zshrc",
|
|
114
|
+
".zprofile",
|
|
115
|
+
".zshenv",
|
|
116
|
+
".zlogin",
|
|
117
|
+
".bashrc",
|
|
118
|
+
".bash_profile",
|
|
119
|
+
".profile",
|
|
120
|
+
".tmux.conf",
|
|
121
|
+
".wgetrc",
|
|
122
|
+
".curlrc",
|
|
123
|
+
]);
|
|
124
|
+
/**
|
|
125
|
+
* Redact sensitive lines in ini-style / line-oriented config files.
|
|
126
|
+
* Each matching line has its value portion replaced with [REDACTED].
|
|
127
|
+
*/
|
|
128
|
+
export function redactLineSecrets(content) {
|
|
129
|
+
return content
|
|
130
|
+
.split("\n")
|
|
131
|
+
.map((line) => {
|
|
132
|
+
for (const pattern of LINE_REDACTION_PATTERNS) {
|
|
133
|
+
const match = line.match(pattern);
|
|
134
|
+
if (match) {
|
|
135
|
+
return `${match[1]}${REDACTED}`;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return line;
|
|
139
|
+
})
|
|
140
|
+
.join("\n");
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Redact sensitive variable assignments in shell scripts.
|
|
144
|
+
* Catches patterns like:
|
|
145
|
+
* export MY_API_KEY="sk-..."
|
|
146
|
+
* GITHUB_TOKEN=ghp_xxx
|
|
147
|
+
* export Z_AI_API_KEY="..."
|
|
148
|
+
*/
|
|
149
|
+
export function redactShellSecrets(content) {
|
|
150
|
+
return content
|
|
151
|
+
.split("\n")
|
|
152
|
+
.map((line) => {
|
|
153
|
+
// Skip comments
|
|
154
|
+
const trimmed = line.trimStart();
|
|
155
|
+
if (trimmed.startsWith("#"))
|
|
156
|
+
return line;
|
|
157
|
+
for (const pattern of SHELL_REDACTION_PATTERNS) {
|
|
158
|
+
const match = line.match(pattern);
|
|
159
|
+
if (match) {
|
|
160
|
+
return `${match[1]}${REDACTED}`;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return line;
|
|
164
|
+
})
|
|
165
|
+
.join("\n");
|
|
166
|
+
}
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
// Value-pattern redaction (for history.jsonl and other freeform content)
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
/**
|
|
171
|
+
* Patterns that match credential-like values embedded in freeform text.
|
|
172
|
+
* These catch secrets that users may have pasted into CLI prompts.
|
|
173
|
+
* Each pattern replaces the matched portion with [REDACTED].
|
|
174
|
+
*/
|
|
175
|
+
const VALUE_CREDENTIAL_PATTERNS = [
|
|
176
|
+
// JWT tokens (three base64 segments separated by dots)
|
|
177
|
+
/eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/g,
|
|
178
|
+
// Bearer / token auth headers
|
|
179
|
+
/(?:Bearer|Token)\s+[A-Za-z0-9_\-.~+/]{20,}/gi,
|
|
180
|
+
// AWS access keys (AKIA...)
|
|
181
|
+
/AKIA[0-9A-Z]{16}/g,
|
|
182
|
+
// GitHub tokens (ghp_, gho_, ghu_, ghs_, ghr_)
|
|
183
|
+
/gh[pousr]_[A-Za-z0-9_]{36,}/g,
|
|
184
|
+
// Anthropic API keys
|
|
185
|
+
/sk-ant-[A-Za-z0-9_-]{20,}/g,
|
|
186
|
+
// OpenAI API keys
|
|
187
|
+
/sk-(?:proj-)?[A-Za-z0-9]{20,}/g,
|
|
188
|
+
// Slack tokens (xoxb-, xoxp-, xoxs-, xoxa-)
|
|
189
|
+
/xox[bpsa]-[A-Za-z0-9-]{20,}/g,
|
|
190
|
+
// Generic long hex secrets (e.g. 40+ hex chars, common for API keys/tokens)
|
|
191
|
+
/(?:(?:token|key|secret|password|auth|credential|cookie)\s*[=:]\s*)['"]*([A-Za-z0-9_\-+/.]{32,})['"]*$/gim,
|
|
192
|
+
// Cookie session values (session=xxx, sid=xxx, _session_id=xxx)
|
|
193
|
+
/(?:session|sid|_session_id|connect\.sid)\s*=\s*[A-Za-z0-9%_\-+/.]{16,}/gi,
|
|
194
|
+
// npm tokens
|
|
195
|
+
/npm_[A-Za-z0-9]{36,}/g,
|
|
196
|
+
// Private key content (if someone pasted it)
|
|
197
|
+
/-----BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY-----[\s\S]*?-----END\s+(?:RSA\s+)?PRIVATE\s+KEY-----/g,
|
|
198
|
+
];
|
|
199
|
+
/**
|
|
200
|
+
* Scan a string value and replace any credential-like patterns with [REDACTED].
|
|
201
|
+
* Returns [redactedString, didRedact].
|
|
202
|
+
*/
|
|
203
|
+
function redactValuePatterns(value) {
|
|
204
|
+
let result = value;
|
|
205
|
+
let didRedact = false;
|
|
206
|
+
for (const pattern of VALUE_CREDENTIAL_PATTERNS) {
|
|
207
|
+
// Reset lastIndex for global regexes
|
|
208
|
+
pattern.lastIndex = 0;
|
|
209
|
+
if (pattern.test(result)) {
|
|
210
|
+
didRedact = true;
|
|
211
|
+
pattern.lastIndex = 0;
|
|
212
|
+
result = result.replace(pattern, REDACTED);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return [result, didRedact];
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Deep-walk a parsed value and apply value-pattern redaction to all strings.
|
|
219
|
+
* Unlike redactObject (key-based), this inspects the VALUE content itself.
|
|
220
|
+
*/
|
|
221
|
+
function redactDeepValues(obj) {
|
|
222
|
+
if (obj === null || obj === undefined)
|
|
223
|
+
return [obj, false];
|
|
224
|
+
if (typeof obj === "string") {
|
|
225
|
+
return redactValuePatterns(obj);
|
|
226
|
+
}
|
|
227
|
+
if (Array.isArray(obj)) {
|
|
228
|
+
let anyRedacted = false;
|
|
229
|
+
const mapped = obj.map((item) => {
|
|
230
|
+
const [val, redacted] = redactDeepValues(item);
|
|
231
|
+
if (redacted)
|
|
232
|
+
anyRedacted = true;
|
|
233
|
+
return val;
|
|
234
|
+
});
|
|
235
|
+
return [mapped, anyRedacted];
|
|
236
|
+
}
|
|
237
|
+
if (typeof obj === "object") {
|
|
238
|
+
let anyRedacted = false;
|
|
239
|
+
const result = {};
|
|
240
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
241
|
+
const [val, redacted] = redactDeepValues(value);
|
|
242
|
+
result[key] = val;
|
|
243
|
+
if (redacted)
|
|
244
|
+
anyRedacted = true;
|
|
245
|
+
}
|
|
246
|
+
return [result, anyRedacted];
|
|
247
|
+
}
|
|
248
|
+
return [obj, false];
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Redact credential-like values in JSONL content (one JSON object per line).
|
|
252
|
+
* Applies both key-based (sensitive key names) and value-based (credential
|
|
253
|
+
* patterns like JWTs, API keys, bearer tokens) redaction.
|
|
254
|
+
*/
|
|
255
|
+
export function redactJsonlSecrets(content) {
|
|
256
|
+
return content
|
|
257
|
+
.split("\n")
|
|
258
|
+
.map((line) => {
|
|
259
|
+
const trimmed = line.trim();
|
|
260
|
+
if (!trimmed)
|
|
261
|
+
return line;
|
|
262
|
+
try {
|
|
263
|
+
const parsed = JSON.parse(trimmed);
|
|
264
|
+
// Apply key-based redaction first
|
|
265
|
+
const [keyRedacted] = redactObject(parsed);
|
|
266
|
+
// Then apply value-pattern redaction
|
|
267
|
+
const [valueRedacted, didRedact] = redactDeepValues(keyRedacted);
|
|
268
|
+
// Also check if key-based redaction changed anything
|
|
269
|
+
const keyChanged = JSON.stringify(keyRedacted) !== JSON.stringify(parsed);
|
|
270
|
+
if (!didRedact && !keyChanged)
|
|
271
|
+
return line;
|
|
272
|
+
return JSON.stringify(valueRedacted);
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
// Not valid JSON line — apply value-pattern redaction as plain text
|
|
276
|
+
const [result, didRedact] = redactValuePatterns(trimmed);
|
|
277
|
+
return didRedact ? result : line;
|
|
278
|
+
}
|
|
279
|
+
})
|
|
280
|
+
.join("\n");
|
|
281
|
+
}
|
|
282
|
+
// ---------------------------------------------------------------------------
|
|
283
|
+
// Public API: auto-detect format and redact
|
|
284
|
+
// ---------------------------------------------------------------------------
|
|
285
|
+
/**
|
|
286
|
+
* Redact credentials from file content.
|
|
287
|
+
* Auto-detects format based on file path extension or filename.
|
|
288
|
+
*
|
|
289
|
+
* @param content Raw file content
|
|
290
|
+
* @param filePath File path (used to determine format)
|
|
291
|
+
* @returns Content with sensitive values replaced by [REDACTED]
|
|
292
|
+
*/
|
|
293
|
+
export function redactSecrets(content, filePath) {
|
|
294
|
+
const lower = filePath.toLowerCase();
|
|
295
|
+
if (lower.endsWith(".json")) {
|
|
296
|
+
return redactJsonSecrets(content);
|
|
297
|
+
}
|
|
298
|
+
// JSONL files (e.g. history.jsonl): value-pattern + key-based redaction
|
|
299
|
+
if (lower.endsWith(".jsonl")) {
|
|
300
|
+
return redactJsonlSecrets(content);
|
|
301
|
+
}
|
|
302
|
+
// Line-oriented configs: .npmrc, .gitconfig, .env, etc.
|
|
303
|
+
if (lower.endsWith(".npmrc") ||
|
|
304
|
+
lower.endsWith(".gitconfig") ||
|
|
305
|
+
lower.endsWith(".env") ||
|
|
306
|
+
lower.endsWith(".env.local") ||
|
|
307
|
+
lower.endsWith(".netrc")) {
|
|
308
|
+
return redactLineSecrets(content);
|
|
309
|
+
}
|
|
310
|
+
// Shell config files: .zshrc, .bashrc, .profile, etc.
|
|
311
|
+
const fileName = lower.split("/").pop() ?? "";
|
|
312
|
+
if (SHELL_CONFIG_NAMES.has(fileName)) {
|
|
313
|
+
return redactShellSecrets(content);
|
|
314
|
+
}
|
|
315
|
+
return content;
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/utils/redact.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nocoo/otter",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Backup and restore your Mac development environment configuration",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"otter": "dist/bin.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"test": "vitest run",
|
|
14
|
+
"test:watch": "vitest"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/nocoo/otter.git",
|
|
25
|
+
"directory": "packages/cli"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"macos",
|
|
29
|
+
"backup",
|
|
30
|
+
"dotfiles",
|
|
31
|
+
"developer-tools",
|
|
32
|
+
"cli"
|
|
33
|
+
],
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@aws-sdk/client-s3": "^3.1004.0",
|
|
37
|
+
"citty": "^0.1.0",
|
|
38
|
+
"consola": "^3.4.0",
|
|
39
|
+
"picocolors": "^1.1.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@otter/core": "workspace:*",
|
|
43
|
+
"@types/node": "^25.3.4"
|
|
44
|
+
}
|
|
45
|
+
}
|