axiodb 20.3.0 → 20.3.3
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/README.md +7 -2
- package/package.json +3 -3
- package/.graphifyignore +0 -12
- package/cli/VERSION +0 -1
- package/cli/cmd/auth_management.go +0 -68
- package/cli/cmd/collection.go +0 -169
- package/cli/cmd/connect.go +0 -597
- package/cli/cmd/db.go +0 -171
- package/cli/cmd/db_export.go +0 -66
- package/cli/cmd/db_import.go +0 -84
- package/cli/cmd/document.go +0 -409
- package/cli/cmd/health.go +0 -19
- package/cli/cmd/index.go +0 -101
- package/cli/cmd/ping.go +0 -36
- package/cli/cmd/root.go +0 -38
- package/cli/cmd/transaction.go +0 -191
- package/cli/cmd/version.go +0 -27
- package/cli/go.mod +0 -15
- package/cli/go.sum +0 -20
- package/cli/internal/config/config.go +0 -120
- package/cli/main.go +0 -7
- package/cli/pkg/commands/collection.go +0 -68
- package/cli/pkg/commands/db.go +0 -62
- package/cli/pkg/commands/document.go +0 -203
- package/cli/pkg/commands/health.go +0 -18
- package/cli/pkg/commands/index.go +0 -51
- package/cli/pkg/commands/transaction.go +0 -84
- package/cli/pkg/httpclient/client.go +0 -236
- package/cli/pkg/protocol/auth.go +0 -46
- package/cli/pkg/protocol/client.go +0 -174
- package/cli/pkg/protocol/message.go +0 -75
- package/lib/engine/cli/worker_process.d.ts +0 -6
- package/lib/engine/cli/worker_process.js +0 -63
- package/lib/engine/cli/worker_process.js.map +0 -1
- package/opencode.json +0 -9
package/cli/cmd/connect.go
DELETED
|
@@ -1,597 +0,0 @@
|
|
|
1
|
-
package cmd
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"encoding/json"
|
|
5
|
-
"fmt"
|
|
6
|
-
"os"
|
|
7
|
-
"strings"
|
|
8
|
-
|
|
9
|
-
"github.com/chzyer/readline"
|
|
10
|
-
"github.com/nexoral/axiodb-cli/internal/config"
|
|
11
|
-
"github.com/nexoral/axiodb-cli/pkg/commands"
|
|
12
|
-
"github.com/nexoral/axiodb-cli/pkg/protocol"
|
|
13
|
-
"github.com/spf13/cobra"
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
var replCommands = []string{
|
|
17
|
-
"use", "show dbs", "show collections", "ping", "help", "exit", "quit", "clear",
|
|
18
|
-
"db.createCollection(", "db..insert(", "db..insertMany(",
|
|
19
|
-
"db..find(", "db..findOne(", "db..updateOne(", "db..updateMany(",
|
|
20
|
-
"db..deleteOne(", "db..deleteMany(", "db..aggregate(",
|
|
21
|
-
"db..countDocuments()", "db..createIndex(", "db..dropIndex(",
|
|
22
|
-
"db..getIndexes()", "db..get(", "db..update(", "db..delete(",
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
var connectCmd = &cobra.Command{
|
|
26
|
-
Use: "connect",
|
|
27
|
-
Short: "Open interactive REPL session",
|
|
28
|
-
RunE: func(cmd *cobra.Command, args []string) error {
|
|
29
|
-
cfg, err := config.FromFlags(cmd)
|
|
30
|
-
if err != nil {
|
|
31
|
-
return err
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
client, err := cfg.ConnectAndAuth()
|
|
35
|
-
if err != nil {
|
|
36
|
-
return err
|
|
37
|
-
}
|
|
38
|
-
defer client.Disconnect()
|
|
39
|
-
|
|
40
|
-
rl, err := readline.NewEx(&readline.Config{
|
|
41
|
-
Prompt: "axiodb> ",
|
|
42
|
-
HistoryFile: "/tmp/axiodb_history",
|
|
43
|
-
InterruptPrompt: "^C",
|
|
44
|
-
EOFPrompt: "exit",
|
|
45
|
-
AutoComplete: readline.NewPrefixCompleter(completerItems...),
|
|
46
|
-
})
|
|
47
|
-
if err != nil {
|
|
48
|
-
return fmt.Errorf("init readline: %w", err)
|
|
49
|
-
}
|
|
50
|
-
defer rl.Close()
|
|
51
|
-
|
|
52
|
-
var currentDB, currentColl string
|
|
53
|
-
|
|
54
|
-
fmt.Println("AxioDB Shell. Type 'help' for commands, 'exit' to quit.")
|
|
55
|
-
|
|
56
|
-
for {
|
|
57
|
-
rl.SetPrompt(buildPrompt(currentDB, currentColl))
|
|
58
|
-
line, err := rl.Readline()
|
|
59
|
-
if err != nil {
|
|
60
|
-
break
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
input := strings.TrimSpace(line)
|
|
64
|
-
if input == "" {
|
|
65
|
-
continue
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if err := handleREPLInput(client, input, ¤tDB, ¤tColl); err != nil {
|
|
69
|
-
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return nil
|
|
74
|
-
},
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
func init() {
|
|
78
|
-
rootCmd.AddCommand(connectCmd)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
func buildPrompt(db, coll string) string {
|
|
82
|
-
if db == "" {
|
|
83
|
-
return "axiodb> "
|
|
84
|
-
}
|
|
85
|
-
if coll == "" {
|
|
86
|
-
return fmt.Sprintf("axiodb:%s> ", db)
|
|
87
|
-
}
|
|
88
|
-
return fmt.Sprintf("axiodb:%s:%s> ", db, coll)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
var completerItems = []readline.PrefixCompleterInterface{
|
|
92
|
-
readline.PcItem("use"),
|
|
93
|
-
readline.PcItem("show",
|
|
94
|
-
readline.PcItem("dbs"),
|
|
95
|
-
readline.PcItem("collections"),
|
|
96
|
-
),
|
|
97
|
-
readline.PcItem("ping"),
|
|
98
|
-
readline.PcItem("help"),
|
|
99
|
-
readline.PcItem("exit"),
|
|
100
|
-
readline.PcItem("quit"),
|
|
101
|
-
readline.PcItem("clear"),
|
|
102
|
-
readline.PcItem("db.",
|
|
103
|
-
readline.PcItem("createCollection("),
|
|
104
|
-
),
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
func handleREPLInput(client *protocol.Client, input string, db, coll *string) error {
|
|
108
|
-
switch {
|
|
109
|
-
case input == "exit" || input == "quit":
|
|
110
|
-
fmt.Println("Bye!")
|
|
111
|
-
os.Exit(0)
|
|
112
|
-
|
|
113
|
-
case input == "help":
|
|
114
|
-
printREPLHelp()
|
|
115
|
-
|
|
116
|
-
case input == "clear":
|
|
117
|
-
fmt.Print("\033[H\033[2J")
|
|
118
|
-
|
|
119
|
-
case strings.HasPrefix(input, "use "):
|
|
120
|
-
target := strings.TrimSpace(strings.TrimPrefix(input, "use"))
|
|
121
|
-
parts := strings.SplitN(target, ".", 2)
|
|
122
|
-
*db = parts[0]
|
|
123
|
-
if len(parts) > 1 {
|
|
124
|
-
*coll = parts[1]
|
|
125
|
-
} else {
|
|
126
|
-
*coll = ""
|
|
127
|
-
}
|
|
128
|
-
fmt.Printf("switched to %s\n", buildPrompt(*db, *coll))
|
|
129
|
-
|
|
130
|
-
case input == "show dbs":
|
|
131
|
-
resp, err := commands.GetInstanceInfo(client)
|
|
132
|
-
if err != nil {
|
|
133
|
-
return err
|
|
134
|
-
}
|
|
135
|
-
printDatabases(resp)
|
|
136
|
-
|
|
137
|
-
case input == "show collections":
|
|
138
|
-
if *db == "" {
|
|
139
|
-
return fmt.Errorf("no database selected. Use 'use <db>' first")
|
|
140
|
-
}
|
|
141
|
-
resp, err := commands.GetCollectionInfo(client, *db)
|
|
142
|
-
if err != nil {
|
|
143
|
-
return err
|
|
144
|
-
}
|
|
145
|
-
printCollections(resp)
|
|
146
|
-
|
|
147
|
-
case input == "ping":
|
|
148
|
-
if err := client.Ping(); err != nil {
|
|
149
|
-
return err
|
|
150
|
-
}
|
|
151
|
-
fmt.Println("PONG")
|
|
152
|
-
|
|
153
|
-
case strings.HasPrefix(input, "db."):
|
|
154
|
-
return handleDBCommand(client, input, *db, *coll)
|
|
155
|
-
|
|
156
|
-
default:
|
|
157
|
-
return fmt.Errorf("unknown command: %s (type 'help' for available commands)", input)
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return nil
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
func handleDBCommand(client *protocol.Client, input, db, coll string) error {
|
|
164
|
-
if db == "" {
|
|
165
|
-
return fmt.Errorf("no database selected. Use 'use <db>' first")
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
switch {
|
|
169
|
-
case strings.HasPrefix(input, "db.createCollection("):
|
|
170
|
-
name := extractParenArg(input, "db.createCollection")
|
|
171
|
-
if name == "" {
|
|
172
|
-
return fmt.Errorf("syntax: db.createCollection(<name>)")
|
|
173
|
-
}
|
|
174
|
-
resp, err := commands.CreateCollection(client, db, name)
|
|
175
|
-
if err != nil {
|
|
176
|
-
return err
|
|
177
|
-
}
|
|
178
|
-
printJSON(resp)
|
|
179
|
-
|
|
180
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".insert("):
|
|
181
|
-
if coll == "" {
|
|
182
|
-
return fmt.Errorf("no collection selected. Use 'use <db>.<collection>' first")
|
|
183
|
-
}
|
|
184
|
-
parts := strings.SplitN(input, ".insert(", 2)
|
|
185
|
-
if len(parts) < 2 {
|
|
186
|
-
return fmt.Errorf("syntax: db.<coll>.insert(<json>)")
|
|
187
|
-
}
|
|
188
|
-
jsonStr := strings.TrimSuffix(parts[1], ")")
|
|
189
|
-
var data interface{}
|
|
190
|
-
if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
|
|
191
|
-
return fmt.Errorf("invalid JSON: %w", err)
|
|
192
|
-
}
|
|
193
|
-
resp, err := commands.InsertDocument(client, db, coll, data)
|
|
194
|
-
if err != nil {
|
|
195
|
-
return err
|
|
196
|
-
}
|
|
197
|
-
printJSON(resp)
|
|
198
|
-
|
|
199
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".insertMany("):
|
|
200
|
-
if coll == "" {
|
|
201
|
-
return fmt.Errorf("no collection selected. Use 'use <db>.<collection>' first")
|
|
202
|
-
}
|
|
203
|
-
parts := strings.SplitN(input, ".insertMany(", 2)
|
|
204
|
-
if len(parts) < 2 {
|
|
205
|
-
return fmt.Errorf("syntax: db.<coll>.insertMany(<json-array>)")
|
|
206
|
-
}
|
|
207
|
-
jsonStr := strings.TrimSuffix(parts[1], ")")
|
|
208
|
-
var docs interface{}
|
|
209
|
-
if err := json.Unmarshal([]byte(jsonStr), &docs); err != nil {
|
|
210
|
-
return fmt.Errorf("invalid JSON: %w", err)
|
|
211
|
-
}
|
|
212
|
-
resp, err := commands.InsertManyDocuments(client, db, coll, docs)
|
|
213
|
-
if err != nil {
|
|
214
|
-
return err
|
|
215
|
-
}
|
|
216
|
-
printJSON(resp)
|
|
217
|
-
|
|
218
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".find("):
|
|
219
|
-
if coll == "" {
|
|
220
|
-
return fmt.Errorf("no collection selected. Use 'use <db>.<collection>' first")
|
|
221
|
-
}
|
|
222
|
-
parts := strings.SplitN(input, ".find(", 2)
|
|
223
|
-
if len(parts) < 2 {
|
|
224
|
-
return fmt.Errorf("syntax: db.<coll>.find(<query>)")
|
|
225
|
-
}
|
|
226
|
-
jsonStr := strings.TrimSuffix(parts[1], ")")
|
|
227
|
-
opts := commands.QueryOptions{}
|
|
228
|
-
if jsonStr != "" {
|
|
229
|
-
var query interface{}
|
|
230
|
-
if err := json.Unmarshal([]byte(jsonStr), &query); err != nil {
|
|
231
|
-
return fmt.Errorf("invalid query JSON: %w", err)
|
|
232
|
-
}
|
|
233
|
-
opts.Query = query
|
|
234
|
-
}
|
|
235
|
-
resp, err := commands.QueryDocuments(client, db, coll, opts)
|
|
236
|
-
if err != nil {
|
|
237
|
-
return err
|
|
238
|
-
}
|
|
239
|
-
printJSON(resp)
|
|
240
|
-
|
|
241
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".findOne("):
|
|
242
|
-
if coll == "" {
|
|
243
|
-
return fmt.Errorf("no collection selected. Use 'use <db>.<collection>' first")
|
|
244
|
-
}
|
|
245
|
-
parts := strings.SplitN(input, ".findOne(", 2)
|
|
246
|
-
if len(parts) < 2 {
|
|
247
|
-
return fmt.Errorf("syntax: db.<coll>.findOne(<query>)")
|
|
248
|
-
}
|
|
249
|
-
jsonStr := strings.TrimSuffix(parts[1], ")")
|
|
250
|
-
opts := commands.QueryOptions{FindOne: true}
|
|
251
|
-
if jsonStr != "" {
|
|
252
|
-
var query interface{}
|
|
253
|
-
if err := json.Unmarshal([]byte(jsonStr), &query); err != nil {
|
|
254
|
-
return fmt.Errorf("invalid query JSON: %w", err)
|
|
255
|
-
}
|
|
256
|
-
opts.Query = query
|
|
257
|
-
}
|
|
258
|
-
resp, err := commands.QueryDocuments(client, db, coll, opts)
|
|
259
|
-
if err != nil {
|
|
260
|
-
return err
|
|
261
|
-
}
|
|
262
|
-
printJSON(resp)
|
|
263
|
-
|
|
264
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".updateOne("):
|
|
265
|
-
if coll == "" {
|
|
266
|
-
return fmt.Errorf("no collection selected")
|
|
267
|
-
}
|
|
268
|
-
query, update, err := extractTwoJSONArgs(input, ".updateOne(")
|
|
269
|
-
if err != nil {
|
|
270
|
-
return err
|
|
271
|
-
}
|
|
272
|
-
resp, err := commands.UpdateDocumentsByQuery(client, db, coll, query, update, true)
|
|
273
|
-
if err != nil {
|
|
274
|
-
return err
|
|
275
|
-
}
|
|
276
|
-
printJSON(resp)
|
|
277
|
-
|
|
278
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".updateMany("):
|
|
279
|
-
if coll == "" {
|
|
280
|
-
return fmt.Errorf("no collection selected")
|
|
281
|
-
}
|
|
282
|
-
query, update, err := extractTwoJSONArgs(input, ".updateMany(")
|
|
283
|
-
if err != nil {
|
|
284
|
-
return err
|
|
285
|
-
}
|
|
286
|
-
resp, err := commands.UpdateDocumentsByQuery(client, db, coll, query, update, false)
|
|
287
|
-
if err != nil {
|
|
288
|
-
return err
|
|
289
|
-
}
|
|
290
|
-
printJSON(resp)
|
|
291
|
-
|
|
292
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".deleteOne("):
|
|
293
|
-
if coll == "" {
|
|
294
|
-
return fmt.Errorf("no collection selected")
|
|
295
|
-
}
|
|
296
|
-
parts := strings.SplitN(input, ".deleteOne(", 2)
|
|
297
|
-
if len(parts) < 2 {
|
|
298
|
-
return fmt.Errorf("syntax: db.<coll>.deleteOne(<query>)")
|
|
299
|
-
}
|
|
300
|
-
jsonStr := strings.TrimSuffix(parts[1], ")")
|
|
301
|
-
var query interface{}
|
|
302
|
-
if jsonStr != "" {
|
|
303
|
-
if err := json.Unmarshal([]byte(jsonStr), &query); err != nil {
|
|
304
|
-
return fmt.Errorf("invalid query JSON: %w", err)
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
resp, err := commands.DeleteDocumentsByQuery(client, db, coll, query, true)
|
|
308
|
-
if err != nil {
|
|
309
|
-
return err
|
|
310
|
-
}
|
|
311
|
-
printJSON(resp)
|
|
312
|
-
|
|
313
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".deleteMany("):
|
|
314
|
-
if coll == "" {
|
|
315
|
-
return fmt.Errorf("no collection selected")
|
|
316
|
-
}
|
|
317
|
-
parts := strings.SplitN(input, ".deleteMany(", 2)
|
|
318
|
-
if len(parts) < 2 {
|
|
319
|
-
return fmt.Errorf("syntax: db.<coll>.deleteMany(<query>)")
|
|
320
|
-
}
|
|
321
|
-
jsonStr := strings.TrimSuffix(parts[1], ")")
|
|
322
|
-
var query interface{}
|
|
323
|
-
if jsonStr != "" {
|
|
324
|
-
if err := json.Unmarshal([]byte(jsonStr), &query); err != nil {
|
|
325
|
-
return fmt.Errorf("invalid query JSON: %w", err)
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
resp, err := commands.DeleteDocumentsByQuery(client, db, coll, query, false)
|
|
329
|
-
if err != nil {
|
|
330
|
-
return err
|
|
331
|
-
}
|
|
332
|
-
printJSON(resp)
|
|
333
|
-
|
|
334
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".aggregate("):
|
|
335
|
-
if coll == "" {
|
|
336
|
-
return fmt.Errorf("no collection selected")
|
|
337
|
-
}
|
|
338
|
-
parts := strings.SplitN(input, ".aggregate(", 2)
|
|
339
|
-
if len(parts) < 2 {
|
|
340
|
-
return fmt.Errorf("syntax: db.<coll>.aggregate(<pipeline>)")
|
|
341
|
-
}
|
|
342
|
-
jsonStr := strings.TrimSuffix(parts[1], ")")
|
|
343
|
-
var pipeline interface{}
|
|
344
|
-
if err := json.Unmarshal([]byte(jsonStr), &pipeline); err != nil {
|
|
345
|
-
return fmt.Errorf("invalid pipeline JSON: %w", err)
|
|
346
|
-
}
|
|
347
|
-
resp, err := commands.Aggregate(client, db, coll, pipeline)
|
|
348
|
-
if err != nil {
|
|
349
|
-
return err
|
|
350
|
-
}
|
|
351
|
-
printJSON(resp)
|
|
352
|
-
|
|
353
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".countDocuments()"):
|
|
354
|
-
if coll == "" {
|
|
355
|
-
return fmt.Errorf("no collection selected")
|
|
356
|
-
}
|
|
357
|
-
resp, err := commands.TotalDocuments(client, db, coll)
|
|
358
|
-
if err != nil {
|
|
359
|
-
return err
|
|
360
|
-
}
|
|
361
|
-
printJSON(resp)
|
|
362
|
-
|
|
363
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".createIndex("):
|
|
364
|
-
if coll == "" {
|
|
365
|
-
return fmt.Errorf("no collection selected")
|
|
366
|
-
}
|
|
367
|
-
parts := strings.SplitN(input, ".createIndex(", 2)
|
|
368
|
-
if len(parts) < 2 {
|
|
369
|
-
return fmt.Errorf("syntax: db.<coll>.createIndex(<fields>)")
|
|
370
|
-
}
|
|
371
|
-
jsonStr := strings.TrimSuffix(parts[1], ")")
|
|
372
|
-
var fields []string
|
|
373
|
-
if err := json.Unmarshal([]byte(jsonStr), &fields); err != nil {
|
|
374
|
-
return fmt.Errorf("invalid fields JSON: %w", err)
|
|
375
|
-
}
|
|
376
|
-
resp, err := commands.CreateIndex(client, db, coll, fields)
|
|
377
|
-
if err != nil {
|
|
378
|
-
return err
|
|
379
|
-
}
|
|
380
|
-
printJSON(resp)
|
|
381
|
-
|
|
382
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".dropIndex("):
|
|
383
|
-
if coll == "" {
|
|
384
|
-
return fmt.Errorf("no collection selected")
|
|
385
|
-
}
|
|
386
|
-
parts := strings.SplitN(input, ".dropIndex(", 2)
|
|
387
|
-
if len(parts) < 2 {
|
|
388
|
-
return fmt.Errorf("syntax: db.<coll>.dropIndex(<name>)")
|
|
389
|
-
}
|
|
390
|
-
name := strings.TrimSuffix(parts[1], ")")
|
|
391
|
-
name = strings.Trim(name, "\"'")
|
|
392
|
-
resp, err := commands.DropIndex(client, db, coll, name)
|
|
393
|
-
if err != nil {
|
|
394
|
-
return err
|
|
395
|
-
}
|
|
396
|
-
printJSON(resp)
|
|
397
|
-
|
|
398
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".getIndexes()"):
|
|
399
|
-
if coll == "" {
|
|
400
|
-
return fmt.Errorf("no collection selected")
|
|
401
|
-
}
|
|
402
|
-
resp, err := commands.ListIndexes(client, db, coll)
|
|
403
|
-
if err != nil {
|
|
404
|
-
return err
|
|
405
|
-
}
|
|
406
|
-
printJSON(resp)
|
|
407
|
-
|
|
408
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".get("):
|
|
409
|
-
if coll == "" {
|
|
410
|
-
return fmt.Errorf("no collection selected")
|
|
411
|
-
}
|
|
412
|
-
parts := strings.SplitN(input, ".get(", 2)
|
|
413
|
-
if len(parts) < 2 {
|
|
414
|
-
return fmt.Errorf("syntax: db.<coll>.get(<id>)")
|
|
415
|
-
}
|
|
416
|
-
id := strings.TrimSuffix(parts[1], ")")
|
|
417
|
-
id = strings.Trim(id, "\"'")
|
|
418
|
-
resp, err := commands.QueryByID(client, db, coll, id)
|
|
419
|
-
if err != nil {
|
|
420
|
-
return err
|
|
421
|
-
}
|
|
422
|
-
printJSON(resp)
|
|
423
|
-
|
|
424
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".update("):
|
|
425
|
-
if coll == "" {
|
|
426
|
-
return fmt.Errorf("no collection selected")
|
|
427
|
-
}
|
|
428
|
-
parts := strings.SplitN(input, ".update(", 2)
|
|
429
|
-
if len(parts) < 2 {
|
|
430
|
-
return fmt.Errorf("syntax: db.<coll>.update(<id>, <json>)")
|
|
431
|
-
}
|
|
432
|
-
args := strings.TrimSuffix(parts[1], ")")
|
|
433
|
-
commaIdx := strings.Index(args, ",")
|
|
434
|
-
if commaIdx < 0 {
|
|
435
|
-
return fmt.Errorf("syntax: db.<coll>.update(<id>, <json>)")
|
|
436
|
-
}
|
|
437
|
-
id := strings.TrimSpace(args[:commaIdx])
|
|
438
|
-
id = strings.Trim(id, "\"'")
|
|
439
|
-
jsonStr := strings.TrimSpace(args[commaIdx+1:])
|
|
440
|
-
var updateData interface{}
|
|
441
|
-
if err := json.Unmarshal([]byte(jsonStr), &updateData); err != nil {
|
|
442
|
-
return fmt.Errorf("invalid update JSON: %w", err)
|
|
443
|
-
}
|
|
444
|
-
resp, err := commands.UpdateDocumentByID(client, db, coll, id, updateData)
|
|
445
|
-
if err != nil {
|
|
446
|
-
return err
|
|
447
|
-
}
|
|
448
|
-
printJSON(resp)
|
|
449
|
-
|
|
450
|
-
case strings.HasPrefix(input, "db.") && strings.Contains(input, ".delete("):
|
|
451
|
-
if coll == "" {
|
|
452
|
-
return fmt.Errorf("no collection selected")
|
|
453
|
-
}
|
|
454
|
-
parts := strings.SplitN(input, ".delete(", 2)
|
|
455
|
-
if len(parts) < 2 {
|
|
456
|
-
return fmt.Errorf("syntax: db.<coll>.delete(<id>)")
|
|
457
|
-
}
|
|
458
|
-
id := strings.TrimSuffix(parts[1], ")")
|
|
459
|
-
id = strings.Trim(id, "\"'")
|
|
460
|
-
resp, err := commands.DeleteDocumentByID(client, db, coll, id)
|
|
461
|
-
if err != nil {
|
|
462
|
-
return err
|
|
463
|
-
}
|
|
464
|
-
printJSON(resp)
|
|
465
|
-
|
|
466
|
-
default:
|
|
467
|
-
return fmt.Errorf("unknown db command: %s", input)
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
return nil
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
func extractParenArg(input, prefix string) string {
|
|
474
|
-
fullPrefix := prefix + "("
|
|
475
|
-
idx := strings.Index(input, fullPrefix)
|
|
476
|
-
if idx < 0 {
|
|
477
|
-
return ""
|
|
478
|
-
}
|
|
479
|
-
rest := input[idx+len(fullPrefix):]
|
|
480
|
-
endIdx := strings.Index(rest, ")")
|
|
481
|
-
if endIdx < 0 {
|
|
482
|
-
return ""
|
|
483
|
-
}
|
|
484
|
-
return strings.TrimSpace(rest[:endIdx])
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
func extractTwoJSONArgs(input, methodSep string) (interface{}, interface{}, error) {
|
|
488
|
-
parts := strings.SplitN(input, methodSep, 2)
|
|
489
|
-
if len(parts) < 2 {
|
|
490
|
-
return nil, nil, fmt.Errorf("syntax: db.<coll>%s<query>, <update>)", methodSep)
|
|
491
|
-
}
|
|
492
|
-
inner := strings.TrimSuffix(parts[1], ")")
|
|
493
|
-
|
|
494
|
-
depth := 0
|
|
495
|
-
commaIdx := -1
|
|
496
|
-
for i, ch := range inner {
|
|
497
|
-
switch ch {
|
|
498
|
-
case '{', '[':
|
|
499
|
-
depth++
|
|
500
|
-
case '}', ']':
|
|
501
|
-
depth--
|
|
502
|
-
case ',':
|
|
503
|
-
if depth == 0 {
|
|
504
|
-
commaIdx = i
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
if commaIdx < 0 {
|
|
509
|
-
return nil, nil, fmt.Errorf("expected two JSON arguments separated by comma")
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
var query, update interface{}
|
|
513
|
-
if err := json.Unmarshal([]byte(strings.TrimSpace(inner[:commaIdx])), &query); err != nil {
|
|
514
|
-
return nil, nil, fmt.Errorf("invalid query JSON: %w", err)
|
|
515
|
-
}
|
|
516
|
-
if err := json.Unmarshal([]byte(strings.TrimSpace(inner[commaIdx+1:])), &update); err != nil {
|
|
517
|
-
return nil, nil, fmt.Errorf("invalid update JSON: %w", err)
|
|
518
|
-
}
|
|
519
|
-
return query, update, nil
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
func printJSON(data interface{}) {
|
|
523
|
-
encoder := json.NewEncoder(os.Stdout)
|
|
524
|
-
encoder.SetIndent("", " ")
|
|
525
|
-
encoder.Encode(data)
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
func printDatabases(resp *protocol.Response) {
|
|
529
|
-
data, ok := resp.Data.(map[string]interface{})
|
|
530
|
-
if !ok {
|
|
531
|
-
printJSON(resp)
|
|
532
|
-
return
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
databases, _ := data["ListOfDatabases"].([]interface{})
|
|
536
|
-
total, _ := data["TotalDatabases"].(string)
|
|
537
|
-
|
|
538
|
-
if len(databases) == 0 {
|
|
539
|
-
fmt.Println("No databases found")
|
|
540
|
-
return
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
fmt.Printf("Databases (%s):\n", total)
|
|
544
|
-
for _, db := range databases {
|
|
545
|
-
fmt.Printf(" - %s\n", db)
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
func printCollections(resp *protocol.Response) {
|
|
550
|
-
data, ok := resp.Data.(map[string]interface{})
|
|
551
|
-
if !ok {
|
|
552
|
-
printJSON(resp)
|
|
553
|
-
return
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
collections, _ := data["ListOfCollections"].([]interface{})
|
|
557
|
-
total, _ := data["TotalCollections"].(string)
|
|
558
|
-
|
|
559
|
-
if len(collections) == 0 {
|
|
560
|
-
fmt.Println("No collections found")
|
|
561
|
-
return
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
fmt.Printf("Collections (%s):\n", total)
|
|
565
|
-
for _, coll := range collections {
|
|
566
|
-
fmt.Printf(" - %s\n", coll)
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
func printREPLHelp() {
|
|
571
|
-
fmt.Println(`Available commands:
|
|
572
|
-
use <db> Switch database
|
|
573
|
-
use <db>.<collection> Switch database and collection
|
|
574
|
-
show dbs List all databases
|
|
575
|
-
show collections List collections in current db
|
|
576
|
-
ping Test connection
|
|
577
|
-
clear Clear screen
|
|
578
|
-
db.createCollection(<name>) Create collection
|
|
579
|
-
db.<coll>.insert(<json>) Insert document
|
|
580
|
-
db.<coll>.insertMany(<json>) Insert multiple documents
|
|
581
|
-
db.<coll>.find(<query>) Query documents
|
|
582
|
-
db.<coll>.findOne(<query>) Query single document
|
|
583
|
-
db.<coll>.updateOne(<q>, <u>) Update one document
|
|
584
|
-
db.<coll>.updateMany(<q>, <u>) Update many documents
|
|
585
|
-
db.<coll>.deleteOne(<query>) Delete one document
|
|
586
|
-
db.<coll>.deleteMany(<query>) Delete many documents
|
|
587
|
-
db.<coll>.aggregate(<pipeline>) Run aggregation
|
|
588
|
-
db.<coll>.countDocuments() Count documents
|
|
589
|
-
db.<coll>.createIndex(<fields>) Create index
|
|
590
|
-
db.<coll>.dropIndex(<name>) Drop index
|
|
591
|
-
db.<coll>.getIndexes() List indexes
|
|
592
|
-
db.<coll>.get(<id>) Get document by ID
|
|
593
|
-
db.<coll>.update(<id>, <json>) Update document by ID
|
|
594
|
-
db.<coll>.delete(<id>) Delete document by ID
|
|
595
|
-
help Show this help
|
|
596
|
-
exit / quit Exit shell`)
|
|
597
|
-
}
|