@agentuity/cli 0.0.69 → 0.0.70
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/AGENTS.md +1 -1
- package/README.md +1 -1
- package/dist/cmd/ai/capabilities/show.d.ts.map +1 -1
- package/dist/cmd/ai/capabilities/show.js +0 -13
- package/dist/cmd/ai/capabilities/show.js.map +1 -1
- package/dist/cmd/ai/prompt/agent.js +1 -1
- package/dist/cmd/ai/prompt/api.js +1 -1
- package/dist/cmd/build/ast.d.ts +1 -2
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +261 -260
- package/dist/cmd/build/ast.js.map +1 -1
- package/dist/cmd/build/bundler.d.ts +2 -1
- package/dist/cmd/build/bundler.d.ts.map +1 -1
- package/dist/cmd/build/bundler.js +11 -2
- package/dist/cmd/build/bundler.js.map +1 -1
- package/dist/cmd/build/index.js +1 -1
- package/dist/cmd/build/index.js.map +1 -1
- package/dist/cmd/build/plugin.d.ts.map +1 -1
- package/dist/cmd/build/plugin.js +152 -414
- package/dist/cmd/build/plugin.js.map +1 -1
- package/dist/cmd/build/route-registry.d.ts +36 -0
- package/dist/cmd/build/route-registry.d.ts.map +1 -0
- package/dist/cmd/build/route-registry.js +151 -0
- package/dist/cmd/build/route-registry.js.map +1 -0
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +1 -0
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/index.d.ts.map +1 -1
- package/dist/cmd/cloud/index.js +0 -2
- package/dist/cmd/cloud/index.js.map +1 -1
- package/dist/cmd/dev/index.js +3 -3
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/dev/sync.d.ts.map +1 -1
- package/dist/cmd/dev/sync.js +0 -15
- package/dist/cmd/dev/sync.js.map +1 -1
- package/dist/cmd/dev/templates.d.ts.map +1 -1
- package/dist/cmd/dev/templates.js +11 -35
- package/dist/cmd/dev/templates.js.map +1 -1
- package/dist/cmd/profile/create.d.ts.map +1 -1
- package/dist/cmd/profile/create.js +0 -1
- package/dist/cmd/profile/create.js.map +1 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js +64 -53
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -3
- package/dist/config.js.map +1 -1
- package/dist/tui/box.d.ts +19 -0
- package/dist/tui/box.d.ts.map +1 -0
- package/dist/tui/box.js +160 -0
- package/dist/tui/box.js.map +1 -0
- package/dist/tui/colors.d.ts +20 -0
- package/dist/tui/colors.d.ts.map +1 -0
- package/dist/tui/colors.js +52 -0
- package/dist/tui/colors.js.map +1 -0
- package/dist/tui/group.d.ts +25 -0
- package/dist/tui/group.d.ts.map +1 -0
- package/dist/tui/group.js +32 -0
- package/dist/tui/group.js.map +1 -0
- package/dist/tui/prompt.d.ts +65 -0
- package/dist/tui/prompt.d.ts.map +1 -0
- package/dist/tui/prompt.js +377 -0
- package/dist/tui/prompt.js.map +1 -0
- package/dist/tui/symbols.d.ts +32 -0
- package/dist/tui/symbols.d.ts.map +1 -0
- package/dist/tui/symbols.js +52 -0
- package/dist/tui/symbols.js.map +1 -0
- package/dist/tui.d.ts +6 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +6 -0
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +0 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
- package/src/cmd/ai/capabilities/show.ts +0 -13
- package/src/cmd/ai/prompt/agent.ts +1 -1
- package/src/cmd/ai/prompt/api.ts +1 -1
- package/src/cmd/build/ast.ts +364 -334
- package/src/cmd/build/bundler.ts +16 -1
- package/src/cmd/build/index.ts +1 -1
- package/src/cmd/build/plugin.ts +171 -493
- package/src/cmd/build/route-registry.ts +198 -0
- package/src/cmd/cloud/deploy.ts +1 -0
- package/src/cmd/cloud/index.ts +0 -2
- package/src/cmd/dev/index.ts +3 -3
- package/src/cmd/dev/sync.ts +0 -28
- package/src/cmd/dev/templates.ts +11 -35
- package/src/cmd/profile/create.ts +0 -1
- package/src/cmd/project/template-flow.ts +77 -57
- package/src/config.ts +0 -3
- package/src/tui/box.ts +202 -0
- package/src/tui/colors.ts +55 -0
- package/src/tui/group.ts +56 -0
- package/src/tui/prompt.ts +506 -0
- package/src/tui/symbols.ts +64 -0
- package/src/tui.ts +14 -0
- package/src/types.ts +0 -1
- package/dist/cmd/cloud/objectstore/delete-bucket.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/delete-bucket.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/delete-bucket.js +0 -72
- package/dist/cmd/cloud/objectstore/delete-bucket.js.map +0 -1
- package/dist/cmd/cloud/objectstore/delete.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/delete.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/delete.js +0 -65
- package/dist/cmd/cloud/objectstore/delete.js.map +0 -1
- package/dist/cmd/cloud/objectstore/get.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/get.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/get.js +0 -75
- package/dist/cmd/cloud/objectstore/get.js.map +0 -1
- package/dist/cmd/cloud/objectstore/index.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/index.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/index.js +0 -36
- package/dist/cmd/cloud/objectstore/index.js.map +0 -1
- package/dist/cmd/cloud/objectstore/list-buckets.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/list-buckets.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/list-buckets.js +0 -46
- package/dist/cmd/cloud/objectstore/list-buckets.js.map +0 -1
- package/dist/cmd/cloud/objectstore/list-keys.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/list-keys.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/list-keys.js +0 -58
- package/dist/cmd/cloud/objectstore/list-keys.js.map +0 -1
- package/dist/cmd/cloud/objectstore/put.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/put.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/put.js +0 -66
- package/dist/cmd/cloud/objectstore/put.js.map +0 -1
- package/dist/cmd/cloud/objectstore/repl.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/repl.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/repl.js +0 -224
- package/dist/cmd/cloud/objectstore/repl.js.map +0 -1
- package/dist/cmd/cloud/objectstore/url.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/url.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/url.js +0 -64
- package/dist/cmd/cloud/objectstore/url.js.map +0 -1
- package/dist/cmd/cloud/objectstore/util.d.ts +0 -11
- package/dist/cmd/cloud/objectstore/util.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/util.js +0 -18
- package/dist/cmd/cloud/objectstore/util.js.map +0 -1
- package/src/cmd/build/ast.test.ts +0 -418
- package/src/cmd/build/fix-duplicate-exports.test.ts +0 -387
- package/src/cmd/cloud/objectstore/delete-bucket.ts +0 -77
- package/src/cmd/cloud/objectstore/delete.ts +0 -67
- package/src/cmd/cloud/objectstore/get.ts +0 -77
- package/src/cmd/cloud/objectstore/index.ts +0 -36
- package/src/cmd/cloud/objectstore/list-buckets.ts +0 -51
- package/src/cmd/cloud/objectstore/list-keys.ts +0 -63
- package/src/cmd/cloud/objectstore/put.ts +0 -74
- package/src/cmd/cloud/objectstore/repl.ts +0 -239
- package/src/cmd/cloud/objectstore/url.ts +0 -67
- package/src/cmd/cloud/objectstore/util.ts +0 -29
- package/src/crypto/box.test.ts +0 -431
- package/src/env-util.test.ts +0 -194
|
@@ -1,387 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, beforeEach, afterEach } from 'bun:test';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { mkdtemp, rm } from 'node:fs/promises';
|
|
4
|
-
import { tmpdir } from 'node:os';
|
|
5
|
-
import { fixDuplicateExportsInDirectory } from './fix-duplicate-exports';
|
|
6
|
-
|
|
7
|
-
describe('fix-duplicate-exports', () => {
|
|
8
|
-
let tempDir: string;
|
|
9
|
-
|
|
10
|
-
beforeEach(async () => {
|
|
11
|
-
tempDir = await mkdtemp(join(tmpdir(), 'fix-duplicate-exports-test-'));
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
afterEach(async () => {
|
|
15
|
-
await rm(tempDir, { recursive: true, force: true });
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
describe('export alias syntax preservation', () => {
|
|
19
|
-
test('preserves "qux as baz" when removing duplicate foo', async () => {
|
|
20
|
-
// This is the critical bug case from the feedback
|
|
21
|
-
const code = `export { foo };
|
|
22
|
-
export { qux as baz, foo };`;
|
|
23
|
-
|
|
24
|
-
const expected = `export { foo };
|
|
25
|
-
export { qux as baz };`;
|
|
26
|
-
|
|
27
|
-
const testFile = join(tempDir, 'test.js');
|
|
28
|
-
await Bun.write(testFile, code);
|
|
29
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
30
|
-
const result = await Bun.file(testFile).text();
|
|
31
|
-
|
|
32
|
-
expect(result).toBe(expected);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test('preserves "foo as bar" when it is not duplicate', async () => {
|
|
36
|
-
const code = `export { foo as bar };
|
|
37
|
-
export { baz };`;
|
|
38
|
-
|
|
39
|
-
const testFile = join(tempDir, 'test.js');
|
|
40
|
-
await Bun.write(testFile, code);
|
|
41
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
42
|
-
const result = await Bun.file(testFile).text();
|
|
43
|
-
|
|
44
|
-
// Should not change - no duplicates
|
|
45
|
-
expect(result).toBe(code);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test('handles multiple aliases in same export statement', async () => {
|
|
49
|
-
const code = `export { foo as bar, baz as qux };
|
|
50
|
-
export { bar, simple };`;
|
|
51
|
-
|
|
52
|
-
// "bar" is duplicate (exported in both statements)
|
|
53
|
-
const expected = `export { foo as bar, baz as qux };
|
|
54
|
-
export { simple };`;
|
|
55
|
-
|
|
56
|
-
const testFile = join(tempDir, 'test.js');
|
|
57
|
-
await Bun.write(testFile, code);
|
|
58
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
59
|
-
const result = await Bun.file(testFile).text();
|
|
60
|
-
|
|
61
|
-
expect(result).toBe(expected);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
test('preserves alias when removing from middle of export list', async () => {
|
|
65
|
-
const code = `export { alpha, beta };
|
|
66
|
-
export { alpha, gamma as delta, epsilon };`;
|
|
67
|
-
|
|
68
|
-
const expected = `export { alpha, beta };
|
|
69
|
-
export { gamma as delta, epsilon };`;
|
|
70
|
-
|
|
71
|
-
const testFile = join(tempDir, 'test.js');
|
|
72
|
-
await Bun.write(testFile, code);
|
|
73
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
74
|
-
const result = await Bun.file(testFile).text();
|
|
75
|
-
|
|
76
|
-
expect(result).toBe(expected);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test('handles exported name being the duplicate (alias target)', async () => {
|
|
80
|
-
const code = `export { foo as bar };
|
|
81
|
-
export { bar };`;
|
|
82
|
-
|
|
83
|
-
// "bar" from first export and "bar" from second export are DIFFERENT
|
|
84
|
-
// First one exports the identifier "foo" with the name "bar"
|
|
85
|
-
// Second one exports the identifier "bar" with the name "bar"
|
|
86
|
-
// These are duplicates from export name perspective
|
|
87
|
-
const expected = `export { foo as bar };
|
|
88
|
-
`;
|
|
89
|
-
|
|
90
|
-
const testFile = join(tempDir, 'test.js');
|
|
91
|
-
await Bun.write(testFile, code);
|
|
92
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
93
|
-
const result = await Bun.file(testFile).text();
|
|
94
|
-
|
|
95
|
-
expect(result).toBe(expected);
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
describe('duplicate removal', () => {
|
|
100
|
-
test('removes entire duplicate export statement', async () => {
|
|
101
|
-
const code = `export { foo, bar };
|
|
102
|
-
export { foo, bar };`;
|
|
103
|
-
|
|
104
|
-
const expected = `export { foo, bar };
|
|
105
|
-
`;
|
|
106
|
-
|
|
107
|
-
const testFile = join(tempDir, 'test.js');
|
|
108
|
-
await Bun.write(testFile, code);
|
|
109
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
110
|
-
const result = await Bun.file(testFile).text();
|
|
111
|
-
|
|
112
|
-
expect(result).toBe(expected);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test('removes only duplicate names from partial duplicate', async () => {
|
|
116
|
-
const code = `export { foo, bar };
|
|
117
|
-
export { foo, baz };`;
|
|
118
|
-
|
|
119
|
-
const expected = `export { foo, bar };
|
|
120
|
-
export { baz };`;
|
|
121
|
-
|
|
122
|
-
const testFile = join(tempDir, 'test.js');
|
|
123
|
-
await Bun.write(testFile, code);
|
|
124
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
125
|
-
const result = await Bun.file(testFile).text();
|
|
126
|
-
|
|
127
|
-
expect(result).toBe(expected);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
test('handles three-way duplicates', async () => {
|
|
131
|
-
const code = `export { foo };
|
|
132
|
-
export { bar };
|
|
133
|
-
export { foo };`;
|
|
134
|
-
|
|
135
|
-
const expected = `export { foo };
|
|
136
|
-
export { bar };
|
|
137
|
-
`;
|
|
138
|
-
|
|
139
|
-
const testFile = join(tempDir, 'test.js');
|
|
140
|
-
await Bun.write(testFile, code);
|
|
141
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
142
|
-
const result = await Bun.file(testFile).text();
|
|
143
|
-
|
|
144
|
-
expect(result).toBe(expected);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
test('preserves non-duplicate exports', async () => {
|
|
148
|
-
const code = `export { foo };
|
|
149
|
-
export { bar };
|
|
150
|
-
export { baz };`;
|
|
151
|
-
|
|
152
|
-
const testFile = join(tempDir, 'test.js');
|
|
153
|
-
await Bun.write(testFile, code);
|
|
154
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
155
|
-
const result = await Bun.file(testFile).text();
|
|
156
|
-
|
|
157
|
-
// Should not change - no duplicates
|
|
158
|
-
expect(result).toBe(code);
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
describe('__INVALID__REF__ removal', () => {
|
|
163
|
-
test('removes __INVALID__REF__ at start with comma', async () => {
|
|
164
|
-
const code = `export { __INVALID__REF__, foo, bar };`;
|
|
165
|
-
const expected = `export { foo, bar };`;
|
|
166
|
-
|
|
167
|
-
const testFile = join(tempDir, 'test.js');
|
|
168
|
-
await Bun.write(testFile, code);
|
|
169
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
170
|
-
const result = await Bun.file(testFile).text();
|
|
171
|
-
|
|
172
|
-
expect(result).toBe(expected);
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
test('removes __INVALID__REF__ at end with comma', async () => {
|
|
176
|
-
const code = `export { foo, bar, __INVALID__REF__ };`;
|
|
177
|
-
const expected = `export { foo, bar };`;
|
|
178
|
-
|
|
179
|
-
const testFile = join(tempDir, 'test.js');
|
|
180
|
-
await Bun.write(testFile, code);
|
|
181
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
182
|
-
const result = await Bun.file(testFile).text();
|
|
183
|
-
|
|
184
|
-
expect(result).toBe(expected);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
test('removes __INVALID__REF__ in middle', async () => {
|
|
188
|
-
const code = `export { foo, __INVALID__REF__, bar };`;
|
|
189
|
-
const expected = `export { foo, bar };`;
|
|
190
|
-
|
|
191
|
-
const testFile = join(tempDir, 'test.js');
|
|
192
|
-
await Bun.write(testFile, code);
|
|
193
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
194
|
-
const result = await Bun.file(testFile).text();
|
|
195
|
-
|
|
196
|
-
expect(result).toBe(expected);
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
test('removes __INVALID__REF__ from imports', async () => {
|
|
200
|
-
const code = `import { __INVALID__REF__, foo } from 'bar';
|
|
201
|
-
export { foo };`;
|
|
202
|
-
|
|
203
|
-
const expected = `import { foo } from 'bar';
|
|
204
|
-
export { foo };`;
|
|
205
|
-
|
|
206
|
-
const testFile = join(tempDir, 'test.js');
|
|
207
|
-
await Bun.write(testFile, code);
|
|
208
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
209
|
-
const result = await Bun.file(testFile).text();
|
|
210
|
-
|
|
211
|
-
expect(result).toBe(expected);
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
describe('complex scenarios', () => {
|
|
216
|
-
test('handles combination of aliases and duplicates', async () => {
|
|
217
|
-
const code = `export { foo as exportedFoo, bar };
|
|
218
|
-
export { baz as exportedBaz };
|
|
219
|
-
export { bar, qux };`;
|
|
220
|
-
|
|
221
|
-
const expected = `export { foo as exportedFoo, bar };
|
|
222
|
-
export { baz as exportedBaz };
|
|
223
|
-
export { qux };`;
|
|
224
|
-
|
|
225
|
-
const testFile = join(tempDir, 'test.js');
|
|
226
|
-
await Bun.write(testFile, code);
|
|
227
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
228
|
-
const result = await Bun.file(testFile).text();
|
|
229
|
-
|
|
230
|
-
expect(result).toBe(expected);
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
test('handles whitespace variations', async () => {
|
|
234
|
-
const code = `export { foo };
|
|
235
|
-
export { bar as baz , foo };`;
|
|
236
|
-
|
|
237
|
-
const expected = `export { foo };
|
|
238
|
-
export { bar as baz };`;
|
|
239
|
-
|
|
240
|
-
const testFile = join(tempDir, 'test.js');
|
|
241
|
-
await Bun.write(testFile, code);
|
|
242
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
243
|
-
const result = await Bun.file(testFile).text();
|
|
244
|
-
|
|
245
|
-
expect(result).toBe(expected);
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
test('does not modify non-matching export patterns', async () => {
|
|
249
|
-
const code = `export default function foo() {}
|
|
250
|
-
export const bar = 1;
|
|
251
|
-
export { baz };
|
|
252
|
-
export * from './other';`;
|
|
253
|
-
|
|
254
|
-
const testFile = join(tempDir, 'test.js');
|
|
255
|
-
await Bun.write(testFile, code);
|
|
256
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
257
|
-
const result = await Bun.file(testFile).text();
|
|
258
|
-
|
|
259
|
-
// Should only process export { ... } statements
|
|
260
|
-
expect(result).toBe(code);
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
test('handles multiple files in directory', async () => {
|
|
264
|
-
const file1 = join(tempDir, 'file1.js');
|
|
265
|
-
const file2 = join(tempDir, 'file2.js');
|
|
266
|
-
|
|
267
|
-
await Bun.write(file1, `export { foo };\nexport { foo };`);
|
|
268
|
-
await Bun.write(file2, `export { qux as baz };\nexport { baz };`);
|
|
269
|
-
|
|
270
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
271
|
-
|
|
272
|
-
const result1 = await Bun.file(file1).text();
|
|
273
|
-
const result2 = await Bun.file(file2).text();
|
|
274
|
-
|
|
275
|
-
expect(result1).toBe(`export { foo };
|
|
276
|
-
`);
|
|
277
|
-
expect(result2).toBe(`export { qux as baz };
|
|
278
|
-
`);
|
|
279
|
-
});
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
describe('patch order edge cases', () => {
|
|
283
|
-
test('handles partial duplicate followed by full duplicate', async () => {
|
|
284
|
-
// This tests the scenario where modification shifts indices for subsequent removal
|
|
285
|
-
const code = `export { foo };
|
|
286
|
-
export { foo, bar };
|
|
287
|
-
export { foo };`;
|
|
288
|
-
|
|
289
|
-
// Expected: first foo kept, second becomes just bar, third removed
|
|
290
|
-
const expected = `export { foo };
|
|
291
|
-
export { bar };
|
|
292
|
-
`;
|
|
293
|
-
|
|
294
|
-
const testFile = join(tempDir, 'test.js');
|
|
295
|
-
await Bun.write(testFile, code);
|
|
296
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
297
|
-
const result = await Bun.file(testFile).text();
|
|
298
|
-
|
|
299
|
-
expect(result).toBe(expected);
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
test('handles multiple partial duplicates with full duplicate at end', async () => {
|
|
303
|
-
const code = `export { foo };
|
|
304
|
-
export { foo, bar };
|
|
305
|
-
export { foo, baz };
|
|
306
|
-
export { foo };`;
|
|
307
|
-
|
|
308
|
-
// First foo kept, second becomes bar only, third becomes baz only, fourth removed
|
|
309
|
-
const expected = `export { foo };
|
|
310
|
-
export { bar };
|
|
311
|
-
export { baz };
|
|
312
|
-
`;
|
|
313
|
-
|
|
314
|
-
const testFile = join(tempDir, 'test.js');
|
|
315
|
-
await Bun.write(testFile, code);
|
|
316
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
317
|
-
const result = await Bun.file(testFile).text();
|
|
318
|
-
|
|
319
|
-
expect(result).toBe(expected);
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
test('handles full duplicate followed by partial duplicate', async () => {
|
|
323
|
-
const code = `export { foo, bar };
|
|
324
|
-
export { foo, bar };
|
|
325
|
-
export { bar, baz };`;
|
|
326
|
-
|
|
327
|
-
// First kept, second removed (full dup - leaves blank line), third becomes just baz
|
|
328
|
-
const expected = `export { foo, bar };
|
|
329
|
-
|
|
330
|
-
export { baz };`;
|
|
331
|
-
|
|
332
|
-
const testFile = join(tempDir, 'test.js');
|
|
333
|
-
await Bun.write(testFile, code);
|
|
334
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
335
|
-
const result = await Bun.file(testFile).text();
|
|
336
|
-
|
|
337
|
-
expect(result).toBe(expected);
|
|
338
|
-
});
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
describe('edge cases', () => {
|
|
342
|
-
test('handles empty file', async () => {
|
|
343
|
-
const code = '';
|
|
344
|
-
const testFile = join(tempDir, 'test.js');
|
|
345
|
-
await Bun.write(testFile, code);
|
|
346
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
347
|
-
const result = await Bun.file(testFile).text();
|
|
348
|
-
|
|
349
|
-
expect(result).toBe(code);
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
test('handles file with no exports', async () => {
|
|
353
|
-
const code = `const foo = 1;\nconst bar = 2;`;
|
|
354
|
-
const testFile = join(tempDir, 'test.js');
|
|
355
|
-
await Bun.write(testFile, code);
|
|
356
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
357
|
-
const result = await Bun.file(testFile).text();
|
|
358
|
-
|
|
359
|
-
expect(result).toBe(code);
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
test('handles single export with alias', async () => {
|
|
363
|
-
const code = `export { foo as bar };`;
|
|
364
|
-
const testFile = join(tempDir, 'test.js');
|
|
365
|
-
await Bun.write(testFile, code);
|
|
366
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
367
|
-
const result = await Bun.file(testFile).text();
|
|
368
|
-
|
|
369
|
-
expect(result).toBe(code);
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
test('handles export with semicolon vs without', async () => {
|
|
373
|
-
const code = `export { foo }
|
|
374
|
-
export { foo };`;
|
|
375
|
-
|
|
376
|
-
const expected = `export { foo }
|
|
377
|
-
`;
|
|
378
|
-
|
|
379
|
-
const testFile = join(tempDir, 'test.js');
|
|
380
|
-
await Bun.write(testFile, code);
|
|
381
|
-
await fixDuplicateExportsInDirectory(tempDir, false);
|
|
382
|
-
const result = await Bun.file(testFile).text();
|
|
383
|
-
|
|
384
|
-
expect(result).toBe(expected);
|
|
385
|
-
});
|
|
386
|
-
});
|
|
387
|
-
});
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { createCommand } from '../../../types';
|
|
3
|
-
import * as tui from '../../../tui';
|
|
4
|
-
import { createStorageAdapter } from './util';
|
|
5
|
-
import { getCommand } from '../../../command-prefix';
|
|
6
|
-
export const deleteBucketSubcommand = createCommand({
|
|
7
|
-
name: 'delete-bucket',
|
|
8
|
-
description: 'Delete an object storage bucket and all its contents',
|
|
9
|
-
tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth'],
|
|
10
|
-
idempotent: true,
|
|
11
|
-
requires: { auth: true, project: true },
|
|
12
|
-
examples: [
|
|
13
|
-
{
|
|
14
|
-
command: getCommand('objectstore delete-bucket temp'),
|
|
15
|
-
description: 'Delete temp bucket (interactive)',
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
command: getCommand('objectstore delete-bucket old-uploads --confirm'),
|
|
19
|
-
description: 'Force delete without confirmation',
|
|
20
|
-
},
|
|
21
|
-
],
|
|
22
|
-
schema: {
|
|
23
|
-
args: z.object({
|
|
24
|
-
bucket: z.string().min(1).max(64).describe('the name of the bucket'),
|
|
25
|
-
confirm: z
|
|
26
|
-
.boolean()
|
|
27
|
-
.optional()
|
|
28
|
-
.default(false)
|
|
29
|
-
.describe('if true will not prompt for confirmation'),
|
|
30
|
-
}),
|
|
31
|
-
response: z.object({
|
|
32
|
-
success: z.boolean().describe('Whether the deletion succeeded'),
|
|
33
|
-
bucket: z.string().describe('Deleted bucket name'),
|
|
34
|
-
message: z.string().optional().describe('Confirmation message'),
|
|
35
|
-
}),
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
async handler(ctx) {
|
|
39
|
-
const { args } = ctx;
|
|
40
|
-
const objectStore = await createStorageAdapter(ctx);
|
|
41
|
-
|
|
42
|
-
if (!args.confirm) {
|
|
43
|
-
if (!process.stdin.isTTY) {
|
|
44
|
-
tui.fatal('No TTY and --confirm is not set. Refusing to delete');
|
|
45
|
-
}
|
|
46
|
-
tui.warning(`This will delete bucket ${tui.bold(args.bucket)} and ALL its contents.`);
|
|
47
|
-
const confirm = await new Promise<boolean>((resolve) => {
|
|
48
|
-
process.stdout.write('Are you sure? (yes/no): ');
|
|
49
|
-
process.stdin.once('data', (data) => {
|
|
50
|
-
const answer = data.toString().trim().toLowerCase();
|
|
51
|
-
resolve(answer === 'yes' || answer === 'y');
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
if (!confirm) {
|
|
56
|
-
tui.info('Cancelled');
|
|
57
|
-
return { success: false, bucket: args.bucket, message: 'Cancelled' };
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const deleted = await objectStore.deleteBucket(args.bucket);
|
|
62
|
-
|
|
63
|
-
if (deleted) {
|
|
64
|
-
tui.success(`Bucket ${tui.bold(args.bucket)} deleted`);
|
|
65
|
-
} else {
|
|
66
|
-
tui.error(`Bucket ${tui.bold(args.bucket)} not found`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
success: deleted,
|
|
71
|
-
bucket: args.bucket,
|
|
72
|
-
message: deleted ? `Bucket ${args.bucket} deleted` : `Bucket ${args.bucket} not found`,
|
|
73
|
-
};
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
export default deleteBucketSubcommand;
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { createCommand } from '../../../types';
|
|
3
|
-
import * as tui from '../../../tui';
|
|
4
|
-
import { createStorageAdapter } from './util';
|
|
5
|
-
import { getCommand } from '../../../command-prefix';
|
|
6
|
-
const ObjectStoreDeleteResponseSchema = z.object({
|
|
7
|
-
success: z.boolean().describe('Whether the operation succeeded'),
|
|
8
|
-
bucket: z.string().describe('Bucket name'),
|
|
9
|
-
key: z.string().describe('Object key'),
|
|
10
|
-
deleted: z
|
|
11
|
-
.boolean()
|
|
12
|
-
.describe('Whether the object was actually deleted (false if it did not exist)'),
|
|
13
|
-
durationMs: z.number().describe('Operation duration in milliseconds'),
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
export const deleteSubcommand = createCommand({
|
|
17
|
-
name: 'delete',
|
|
18
|
-
aliases: ['del', 'rm', 'remove'],
|
|
19
|
-
description: 'Delete an object from the object storage',
|
|
20
|
-
tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth'],
|
|
21
|
-
idempotent: true,
|
|
22
|
-
requires: { auth: true, project: true },
|
|
23
|
-
examples: [
|
|
24
|
-
{
|
|
25
|
-
command: getCommand('objectstore delete uploads images/old-logo.png'),
|
|
26
|
-
description: 'Delete old logo',
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
command: getCommand('objectstore rm assets data/temp.json'),
|
|
30
|
-
description: 'Remove temp file (using alias)',
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
command: getCommand('objectstore delete backups db-2023.sql'),
|
|
34
|
-
description: 'Delete old backup',
|
|
35
|
-
},
|
|
36
|
-
],
|
|
37
|
-
schema: {
|
|
38
|
-
args: z.object({
|
|
39
|
-
bucket: z.string().min(1).describe('the bucket name'),
|
|
40
|
-
key: z.string().min(1).describe('the key name'),
|
|
41
|
-
}),
|
|
42
|
-
response: ObjectStoreDeleteResponseSchema,
|
|
43
|
-
},
|
|
44
|
-
|
|
45
|
-
async handler(ctx) {
|
|
46
|
-
const { args } = ctx;
|
|
47
|
-
const started = Date.now();
|
|
48
|
-
const storage = await createStorageAdapter(ctx);
|
|
49
|
-
const deleted = await storage.delete(args.bucket, args.key);
|
|
50
|
-
const durationMs = Date.now() - started;
|
|
51
|
-
if (deleted) {
|
|
52
|
-
tui.success(`deleted in ${durationMs.toFixed(1)}ms`);
|
|
53
|
-
} else {
|
|
54
|
-
tui.warning(`${args.key} did not exist in bucket ${args.bucket}`);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
success: true,
|
|
59
|
-
bucket: args.bucket,
|
|
60
|
-
key: args.key,
|
|
61
|
-
deleted,
|
|
62
|
-
durationMs,
|
|
63
|
-
};
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
export default deleteSubcommand;
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { createCommand } from '../../../types';
|
|
3
|
-
import * as tui from '../../../tui';
|
|
4
|
-
import { tryParseJSON } from '../../../json';
|
|
5
|
-
import { createStorageAdapter } from './util';
|
|
6
|
-
import { getCommand } from '../../../command-prefix';
|
|
7
|
-
const ObjectGetResponseSchema = z.object({
|
|
8
|
-
exists: z.boolean().describe('Whether the object exists'),
|
|
9
|
-
data: z.any().optional().describe('Object data (binary)'),
|
|
10
|
-
contentType: z.string().optional().describe('Content type'),
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
export const getSubcommand = createCommand({
|
|
14
|
-
name: 'get',
|
|
15
|
-
description: 'Get an object from the object storage',
|
|
16
|
-
tags: ['read-only', 'slow', 'requires-auth'],
|
|
17
|
-
requires: { auth: true, project: true },
|
|
18
|
-
examples: [
|
|
19
|
-
{
|
|
20
|
-
command: getCommand('objectstore get uploads images/logo.png'),
|
|
21
|
-
description: 'Download logo image',
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
command: getCommand('objectstore get assets data/export.json'),
|
|
25
|
-
description: 'Get JSON export',
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
command: getCommand('objectstore get backups db-2024.sql'),
|
|
29
|
-
description: 'Get database backup',
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
schema: {
|
|
33
|
-
args: z.object({
|
|
34
|
-
bucket: z.string().min(1).describe('the bucket name'),
|
|
35
|
-
key: z.string().min(1).describe('the key name'),
|
|
36
|
-
}),
|
|
37
|
-
response: ObjectGetResponseSchema,
|
|
38
|
-
},
|
|
39
|
-
idempotent: true,
|
|
40
|
-
|
|
41
|
-
async handler(ctx) {
|
|
42
|
-
const { args, options } = ctx;
|
|
43
|
-
const storage = await createStorageAdapter(ctx);
|
|
44
|
-
const started = Date.now();
|
|
45
|
-
const res = await storage.get(args.bucket, args.key);
|
|
46
|
-
|
|
47
|
-
if (!options.json) {
|
|
48
|
-
if (res.exists) {
|
|
49
|
-
if (res.data) {
|
|
50
|
-
if (res.contentType?.includes('json')) {
|
|
51
|
-
const val = tryParseJSON(new TextDecoder().decode(res.data));
|
|
52
|
-
tui.json(val);
|
|
53
|
-
} else if (res.contentType?.includes('text')) {
|
|
54
|
-
console.log(new TextDecoder().decode(res.data));
|
|
55
|
-
} else {
|
|
56
|
-
tui.info(`Read ${res.data.byteLength} bytes (${res.contentType})`);
|
|
57
|
-
}
|
|
58
|
-
tui.success(
|
|
59
|
-
`retrieved in ${(Date.now() - started).toFixed(1)}ms (${res.contentType})`
|
|
60
|
-
);
|
|
61
|
-
} else {
|
|
62
|
-
tui.warning(`${args.key} returned empty data for bucket ${args.bucket}`);
|
|
63
|
-
}
|
|
64
|
-
} else {
|
|
65
|
-
tui.warning(`${args.key} does not exist in bucket ${args.bucket}`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
exists: res.exists,
|
|
71
|
-
data: res.data,
|
|
72
|
-
contentType: res.exists ? res.contentType : undefined,
|
|
73
|
-
};
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
export default getSubcommand;
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { createCommand } from '../../../types';
|
|
2
|
-
import { deleteSubcommand } from './delete';
|
|
3
|
-
import { deleteBucketSubcommand } from './delete-bucket';
|
|
4
|
-
import { getSubcommand } from './get';
|
|
5
|
-
import { listBucketsSubcommand } from './list-buckets';
|
|
6
|
-
import { listKeysSubcommand } from './list-keys';
|
|
7
|
-
import { putSubcommand } from './put';
|
|
8
|
-
import { replSubcommand } from './repl';
|
|
9
|
-
import { urlSubcommand } from './url';
|
|
10
|
-
import { getCommand } from '../../../command-prefix';
|
|
11
|
-
|
|
12
|
-
export const command = createCommand({
|
|
13
|
-
name: 'objectstore',
|
|
14
|
-
aliases: ['object', 'obj'],
|
|
15
|
-
description: 'Manage object storage for your projects',
|
|
16
|
-
tags: ['read-only', 'fast', 'requires-auth'],
|
|
17
|
-
examples: [
|
|
18
|
-
{
|
|
19
|
-
command: getCommand('cloud objectstore repl'),
|
|
20
|
-
description: 'Start interactive object store REPL',
|
|
21
|
-
},
|
|
22
|
-
{ command: getCommand('cloud objectstore list-buckets'), description: 'List all buckets' },
|
|
23
|
-
],
|
|
24
|
-
subcommands: [
|
|
25
|
-
replSubcommand,
|
|
26
|
-
getSubcommand,
|
|
27
|
-
putSubcommand,
|
|
28
|
-
deleteSubcommand,
|
|
29
|
-
urlSubcommand,
|
|
30
|
-
listBucketsSubcommand,
|
|
31
|
-
listKeysSubcommand,
|
|
32
|
-
deleteBucketSubcommand,
|
|
33
|
-
],
|
|
34
|
-
requires: { auth: true, project: true },
|
|
35
|
-
});
|
|
36
|
-
export default command;
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { createCommand } from '../../../types';
|
|
3
|
-
import * as tui from '../../../tui';
|
|
4
|
-
import { createStorageAdapter } from './util';
|
|
5
|
-
import { getCommand } from '../../../command-prefix';
|
|
6
|
-
const BucketListResponseSchema = z.array(
|
|
7
|
-
z.object({
|
|
8
|
-
name: z.string().describe('Bucket name'),
|
|
9
|
-
object_count: z.number().describe('Number of objects in bucket'),
|
|
10
|
-
total_bytes: z.number().describe('Total size in bytes'),
|
|
11
|
-
})
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
export const listBucketsSubcommand = createCommand({
|
|
15
|
-
name: 'list-buckets',
|
|
16
|
-
description: 'List all object storage buckets',
|
|
17
|
-
tags: ['read-only', 'fast', 'requires-auth'],
|
|
18
|
-
requires: { auth: true, project: true },
|
|
19
|
-
schema: {
|
|
20
|
-
response: BucketListResponseSchema,
|
|
21
|
-
},
|
|
22
|
-
idempotent: true,
|
|
23
|
-
examples: [
|
|
24
|
-
{
|
|
25
|
-
command: getCommand('objectstore list-buckets'),
|
|
26
|
-
description: 'List all buckets with stats',
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
|
|
30
|
-
async handler(ctx) {
|
|
31
|
-
const { options } = ctx;
|
|
32
|
-
const storage = await createStorageAdapter(ctx);
|
|
33
|
-
const buckets = await storage.listBuckets();
|
|
34
|
-
|
|
35
|
-
if (!options.json) {
|
|
36
|
-
if (buckets.length === 0) {
|
|
37
|
-
tui.info('No buckets found');
|
|
38
|
-
} else {
|
|
39
|
-
tui.info(`Found ${buckets.length} bucket(s):`);
|
|
40
|
-
for (const bucket of buckets) {
|
|
41
|
-
const sizeMB = (bucket.total_bytes / (1024 * 1024)).toFixed(2);
|
|
42
|
-
tui.info(` ${tui.bold(bucket.name)}: ${bucket.object_count} objects, ${sizeMB} MB`);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return buckets;
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
export default listBucketsSubcommand;
|