karrio-cli 2025.5rc3__py3-none-any.whl
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.
- karrio_cli/__init__.py +0 -0
- karrio_cli/__main__.py +105 -0
- karrio_cli/ai/README.md +335 -0
- karrio_cli/ai/__init__.py +0 -0
- karrio_cli/ai/commands.py +102 -0
- karrio_cli/ai/karrio_ai/__init__.py +1 -0
- karrio_cli/ai/karrio_ai/agent.py +972 -0
- karrio_cli/ai/karrio_ai/architecture/INTEGRATION_AGENT_PROMPT.md +497 -0
- karrio_cli/ai/karrio_ai/architecture/MAPPING_AGENT_PROMPT.md +355 -0
- karrio_cli/ai/karrio_ai/architecture/REAL_WORLD_TESTING.md +305 -0
- karrio_cli/ai/karrio_ai/architecture/SCHEMA_AGENT_PROMPT.md +183 -0
- karrio_cli/ai/karrio_ai/architecture/TESTING_AGENT_PROMPT.md +448 -0
- karrio_cli/ai/karrio_ai/architecture/TESTING_GUIDE.md +271 -0
- karrio_cli/ai/karrio_ai/enhanced_tools.py +943 -0
- karrio_cli/ai/karrio_ai/rag_system.py +503 -0
- karrio_cli/ai/karrio_ai/tests/test_agent.py +350 -0
- karrio_cli/ai/karrio_ai/tests/test_real_integration.py +360 -0
- karrio_cli/ai/karrio_ai/tests/test_real_world_scenarios.py +513 -0
- karrio_cli/commands/__init__.py +0 -0
- karrio_cli/commands/codegen.py +336 -0
- karrio_cli/commands/login.py +139 -0
- karrio_cli/commands/plugins.py +168 -0
- karrio_cli/commands/sdk.py +870 -0
- karrio_cli/common/queries.py +101 -0
- karrio_cli/common/utils.py +368 -0
- karrio_cli/resources/__init__.py +0 -0
- karrio_cli/resources/carriers.py +91 -0
- karrio_cli/resources/connections.py +207 -0
- karrio_cli/resources/events.py +151 -0
- karrio_cli/resources/logs.py +151 -0
- karrio_cli/resources/orders.py +144 -0
- karrio_cli/resources/shipments.py +210 -0
- karrio_cli/resources/trackers.py +287 -0
- karrio_cli/templates/__init__.py +9 -0
- karrio_cli/templates/__pycache__/__init__.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/__init__.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/address.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/address.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/docs.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/docs.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/documents.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/documents.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/manifest.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/manifest.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/pickup.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/pickup.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/rates.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/rates.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/sdk.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/sdk.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/shipments.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/shipments.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/tracking.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/tracking.cpython-312.pyc +0 -0
- karrio_cli/templates/address.py +308 -0
- karrio_cli/templates/docs.py +150 -0
- karrio_cli/templates/documents.py +428 -0
- karrio_cli/templates/manifest.py +396 -0
- karrio_cli/templates/pickup.py +839 -0
- karrio_cli/templates/rates.py +638 -0
- karrio_cli/templates/sdk.py +947 -0
- karrio_cli/templates/shipments.py +892 -0
- karrio_cli/templates/tracking.py +437 -0
- karrio_cli-2025.5rc3.dist-info/METADATA +165 -0
- karrio_cli-2025.5rc3.dist-info/RECORD +68 -0
- karrio_cli-2025.5rc3.dist-info/WHEEL +5 -0
- karrio_cli-2025.5rc3.dist-info/entry_points.txt +2 -0
- karrio_cli-2025.5rc3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,207 @@
|
|
1
|
+
import typer
|
2
|
+
import karrio_cli.common.utils as utils
|
3
|
+
import typing
|
4
|
+
|
5
|
+
app = typer.Typer()
|
6
|
+
|
7
|
+
@app.command("list")
|
8
|
+
def list_connections(
|
9
|
+
carrier_name: typing.Optional[str] = None,
|
10
|
+
system_only: bool = typer.Option(False, "--system-only", help="Filter for system connections only"),
|
11
|
+
limit: int = typer.Option(20, help="Number of results to return per page"),
|
12
|
+
offset: int = typer.Option(0, help="The initial index from which to return the results"),
|
13
|
+
pretty: bool = typer.Option(False, "--pretty", "-p", help="Pretty print the output"),
|
14
|
+
line_numbers: bool = typer.Option(False, "--line-numbers", "-n", help="Show line numbers in pretty print"),
|
15
|
+
):
|
16
|
+
"""
|
17
|
+
List all carrier connections with optional filters and pagination.
|
18
|
+
|
19
|
+
Examples:
|
20
|
+
```terminal
|
21
|
+
# Get all connections and display as a table
|
22
|
+
kcli connections list | jq -r ".results[] | [.id, .carrier_name, .test_mode] | @tsv" | column -t -s $"\t"
|
23
|
+
```
|
24
|
+
|
25
|
+
```terminal
|
26
|
+
# Get connections for a specific carrier
|
27
|
+
kcli connections list --carrier-name ups | jq ".results[] | {id, carrier_name, test_mode}"
|
28
|
+
```
|
29
|
+
|
30
|
+
Example Output:
|
31
|
+
```json
|
32
|
+
{
|
33
|
+
"count": 2,
|
34
|
+
"next": null,
|
35
|
+
"previous": null,
|
36
|
+
"results": [
|
37
|
+
{
|
38
|
+
"id": "conn_123456789",
|
39
|
+
"carrier_name": "ups",
|
40
|
+
"test_mode": true,
|
41
|
+
"active": true,
|
42
|
+
"capabilities": ["rating", "shipping", "tracking"],
|
43
|
+
"metadata": {}
|
44
|
+
}
|
45
|
+
]
|
46
|
+
}
|
47
|
+
```
|
48
|
+
"""
|
49
|
+
params = {
|
50
|
+
"carrier_name": carrier_name,
|
51
|
+
"system_only": system_only,
|
52
|
+
"limit": limit,
|
53
|
+
"offset": offset,
|
54
|
+
}
|
55
|
+
params = {k: v for k, v in params.items() if v is not None}
|
56
|
+
utils.make_get_request(
|
57
|
+
"v1/connections", params=params, pretty_print=pretty, line_numbers=line_numbers
|
58
|
+
)
|
59
|
+
|
60
|
+
@app.command("retrieve")
|
61
|
+
def retrieve_connection(
|
62
|
+
connection_id: str,
|
63
|
+
pretty: bool = typer.Option(False, "--pretty", "-p", help="Pretty print the output"),
|
64
|
+
line_numbers: bool = typer.Option(False, "--line-numbers", "-n", help="Show line numbers in pretty print"),
|
65
|
+
):
|
66
|
+
"""
|
67
|
+
Retrieve a carrier connection by ID.
|
68
|
+
|
69
|
+
Example:
|
70
|
+
```terminal
|
71
|
+
kcli connections retrieve conn_123456789 | jq "{id, carrier_name, test_mode, active}"
|
72
|
+
```
|
73
|
+
|
74
|
+
Example Output:
|
75
|
+
```json
|
76
|
+
{
|
77
|
+
"id": "conn_123456789",
|
78
|
+
"carrier_name": "ups",
|
79
|
+
"test_mode": true,
|
80
|
+
"active": true,
|
81
|
+
"capabilities": ["rating", "shipping", "tracking"],
|
82
|
+
"credentials": {
|
83
|
+
"api_key": "YOUR_API_KEY",
|
84
|
+
"password": "YOUR_PASSWORD",
|
85
|
+
"account_number": "YOUR_ACCOUNT"
|
86
|
+
},
|
87
|
+
"metadata": {}
|
88
|
+
}
|
89
|
+
```
|
90
|
+
"""
|
91
|
+
utils.make_get_request(
|
92
|
+
f"v1/connections/{connection_id}", pretty_print=pretty, line_numbers=line_numbers
|
93
|
+
)
|
94
|
+
|
95
|
+
@app.command("create")
|
96
|
+
def create_connection(
|
97
|
+
property: typing.List[str] = typer.Option(
|
98
|
+
[], "--property", "-d", help="Set nested properties (e.g. -d carrier_name=ups -d credentials[api_key]=xxx)"
|
99
|
+
),
|
100
|
+
pretty: bool = typer.Option(False, "--pretty", "-p", help="Pretty print the output"),
|
101
|
+
line_numbers: bool = typer.Option(False, "--line-numbers", "-n", help="Show line numbers in pretty print"),
|
102
|
+
):
|
103
|
+
"""
|
104
|
+
Create a new carrier connection.
|
105
|
+
|
106
|
+
Example:
|
107
|
+
```terminal
|
108
|
+
kcli connections create \\
|
109
|
+
-d carrier_name=ups \\
|
110
|
+
-d test_mode=true \\
|
111
|
+
-d credentials[api_key]=YOUR_API_KEY \\
|
112
|
+
-d credentials[password]=YOUR_PASSWORD \\
|
113
|
+
-d credentials[account_number]=YOUR_ACCOUNT | jq "{id, carrier_name, test_mode}"
|
114
|
+
```
|
115
|
+
|
116
|
+
Example Output:
|
117
|
+
```json
|
118
|
+
{
|
119
|
+
"id": "conn_123456789",
|
120
|
+
"carrier_name": "ups",
|
121
|
+
"test_mode": true,
|
122
|
+
"active": true,
|
123
|
+
"capabilities": ["rating", "shipping", "tracking"],
|
124
|
+
"credentials": {
|
125
|
+
"api_key": "YOUR_API_KEY",
|
126
|
+
"password": "YOUR_PASSWORD",
|
127
|
+
"account_number": "YOUR_ACCOUNT"
|
128
|
+
}
|
129
|
+
}
|
130
|
+
```
|
131
|
+
"""
|
132
|
+
try:
|
133
|
+
payload = utils.parse_nested_properties(property)
|
134
|
+
except ValueError as e:
|
135
|
+
typer.echo(str(e), err=True)
|
136
|
+
raise typer.Exit(code=1)
|
137
|
+
utils.make_post_request(
|
138
|
+
"v1/connections", payload=payload, pretty_print=pretty, line_numbers=line_numbers
|
139
|
+
)
|
140
|
+
|
141
|
+
@app.command("update")
|
142
|
+
def update_connection(
|
143
|
+
connection_id: str,
|
144
|
+
property: typing.List[str] = typer.Option(
|
145
|
+
[], "--property", "-d", help="Set nested properties (e.g. -d credentials[api_key]=newvalue)"
|
146
|
+
),
|
147
|
+
pretty: bool = typer.Option(False, "--pretty", "-p", help="Pretty print the output"),
|
148
|
+
line_numbers: bool = typer.Option(False, "--line-numbers", "-n", help="Show line numbers in pretty print"),
|
149
|
+
):
|
150
|
+
"""
|
151
|
+
Update a carrier connection by ID.
|
152
|
+
|
153
|
+
Example:
|
154
|
+
```terminal
|
155
|
+
kcli connections update conn_123456789 \\
|
156
|
+
-d test_mode=false \\
|
157
|
+
-d credentials[api_key]=NEW_API_KEY | jq "{id, carrier_name, test_mode}"
|
158
|
+
```
|
159
|
+
|
160
|
+
Example Output:
|
161
|
+
```json
|
162
|
+
{
|
163
|
+
"id": "conn_123456789",
|
164
|
+
"carrier_name": "ups",
|
165
|
+
"test_mode": false,
|
166
|
+
"active": true,
|
167
|
+
"credentials": {
|
168
|
+
"api_key": "NEW_API_KEY",
|
169
|
+
"password": "YOUR_PASSWORD",
|
170
|
+
"account_number": "YOUR_ACCOUNT"
|
171
|
+
}
|
172
|
+
}
|
173
|
+
```
|
174
|
+
"""
|
175
|
+
try:
|
176
|
+
payload = utils.parse_nested_properties(property)
|
177
|
+
except ValueError as e:
|
178
|
+
typer.echo(str(e), err=True)
|
179
|
+
raise typer.Exit(code=1)
|
180
|
+
utils.make_patch_request(
|
181
|
+
f"v1/connections/{connection_id}", payload=payload, pretty_print=pretty, line_numbers=line_numbers
|
182
|
+
)
|
183
|
+
|
184
|
+
@app.command("delete")
|
185
|
+
def delete_connection(
|
186
|
+
connection_id: str,
|
187
|
+
pretty: bool = typer.Option(False, "--pretty", "-p", help="Pretty print the output"),
|
188
|
+
line_numbers: bool = typer.Option(False, "--line-numbers", "-n", help="Show line numbers in pretty print"),
|
189
|
+
):
|
190
|
+
"""
|
191
|
+
Delete a carrier connection by ID.
|
192
|
+
|
193
|
+
Example:
|
194
|
+
```terminal
|
195
|
+
kcli connections delete conn_123456789 | jq "{message: \"Connection deleted successfully\"}"
|
196
|
+
```
|
197
|
+
|
198
|
+
Example Output:
|
199
|
+
```json
|
200
|
+
{
|
201
|
+
"message": "Connection deleted successfully"
|
202
|
+
}
|
203
|
+
```
|
204
|
+
"""
|
205
|
+
utils.make_delete_request(
|
206
|
+
f"v1/connections/{connection_id}", pretty_print=pretty, line_numbers=line_numbers
|
207
|
+
)
|
@@ -0,0 +1,151 @@
|
|
1
|
+
import typer
|
2
|
+
import karrio_cli.common.utils as utils
|
3
|
+
import typing
|
4
|
+
import datetime
|
5
|
+
|
6
|
+
app = typer.Typer()
|
7
|
+
|
8
|
+
|
9
|
+
@app.command("list")
|
10
|
+
def list_events(
|
11
|
+
type: typing.Optional[str] = typer.Option(
|
12
|
+
None,
|
13
|
+
help="Event type (e.g. shipment_created, order_created, tracker_created)",
|
14
|
+
autocompletion=lambda: [
|
15
|
+
"all",
|
16
|
+
"batch_completed",
|
17
|
+
"batch_failed",
|
18
|
+
"batch_queued",
|
19
|
+
"batch_running",
|
20
|
+
"order_cancelled",
|
21
|
+
"order_created",
|
22
|
+
"order_delivered",
|
23
|
+
"order_fulfilled",
|
24
|
+
"order_updated",
|
25
|
+
"shipment_cancelled",
|
26
|
+
"shipment_delivery_failed",
|
27
|
+
"shipment_fulfilled",
|
28
|
+
"shipment_needs_attention",
|
29
|
+
"shipment_out_for_delivery",
|
30
|
+
"shipment_purchased",
|
31
|
+
"tracker_created",
|
32
|
+
"tracker_updated",
|
33
|
+
]
|
34
|
+
),
|
35
|
+
created_after: typing.Optional[datetime.datetime] = None,
|
36
|
+
created_before: typing.Optional[datetime.datetime] = None,
|
37
|
+
limit: int = typer.Option(20, help="Number of results to return per page"),
|
38
|
+
offset: int = typer.Option(
|
39
|
+
0, help="The initial index from which to return the results"
|
40
|
+
),
|
41
|
+
pretty: bool = typer.Option(
|
42
|
+
False, "--pretty", "-p", help="Pretty print the output"
|
43
|
+
),
|
44
|
+
line_numbers: bool = typer.Option(
|
45
|
+
False, "--line-numbers", "-n", help="Show line numbers in pretty print"
|
46
|
+
),
|
47
|
+
):
|
48
|
+
"""
|
49
|
+
List all events with optional filters and pagination.
|
50
|
+
|
51
|
+
Examples:
|
52
|
+
```terminal
|
53
|
+
# Get all events and display as a table
|
54
|
+
kcli events list --limit 10 | jq -r ".events.edges[].node | [.id, .type, .created_at] | @tsv" | column -t -s $"\t"
|
55
|
+
```
|
56
|
+
|
57
|
+
```terminal
|
58
|
+
# Get events of a specific type
|
59
|
+
kcli events list --type shipment_purchased --limit 5 | jq ".events.edges[].node | {id, type, created_at, data}"
|
60
|
+
```
|
61
|
+
|
62
|
+
Example Output:
|
63
|
+
```json
|
64
|
+
{
|
65
|
+
"events": {
|
66
|
+
"edges": [
|
67
|
+
{
|
68
|
+
"node": {
|
69
|
+
"id": "evt_123456789",
|
70
|
+
"type": "shipment_purchased",
|
71
|
+
"data": {
|
72
|
+
"shipment_id": "shp_123456789",
|
73
|
+
"status": "purchased"
|
74
|
+
},
|
75
|
+
"test_mode": false,
|
76
|
+
"pending_webhooks": 0,
|
77
|
+
"created_at": "2024-03-20T10:30:00Z"
|
78
|
+
}
|
79
|
+
}
|
80
|
+
],
|
81
|
+
"page_info": {
|
82
|
+
"count": 1,
|
83
|
+
"has_next_page": false,
|
84
|
+
"has_previous_page": false,
|
85
|
+
"start_cursor": "YXJyYXljb25uZWN0aW9uOjA=",
|
86
|
+
"end_cursor": "YXJyYXljb25uZWN0aW9uOjA="
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
```
|
91
|
+
"""
|
92
|
+
params = {
|
93
|
+
"type": [type] if type else None,
|
94
|
+
"created_after": created_after.isoformat() if created_after else None,
|
95
|
+
"created_before": created_before.isoformat() if created_before else None,
|
96
|
+
"first": limit,
|
97
|
+
"offset": offset,
|
98
|
+
}
|
99
|
+
|
100
|
+
# Remove None values from params
|
101
|
+
params = {k: v for k, v in params.items() if v is not None}
|
102
|
+
|
103
|
+
utils.make_graphql_request(
|
104
|
+
"get_events",
|
105
|
+
{"filter": params},
|
106
|
+
pretty_print=pretty,
|
107
|
+
line_numbers=line_numbers
|
108
|
+
)
|
109
|
+
|
110
|
+
|
111
|
+
@app.command("retrieve")
|
112
|
+
def retrieve_event(
|
113
|
+
event_id: str,
|
114
|
+
pretty: bool = typer.Option(
|
115
|
+
False, "--pretty", "-p", help="Pretty print the output"
|
116
|
+
),
|
117
|
+
line_numbers: bool = typer.Option(
|
118
|
+
False, "--line-numbers", "-n", help="Show line numbers in pretty print"
|
119
|
+
),
|
120
|
+
):
|
121
|
+
"""
|
122
|
+
Retrieve an event by ID.
|
123
|
+
|
124
|
+
Example:
|
125
|
+
```terminal
|
126
|
+
kcli events retrieve evt_123456789 | jq "{id, type, created_at, data}"
|
127
|
+
```
|
128
|
+
|
129
|
+
Example Output:
|
130
|
+
```json
|
131
|
+
{
|
132
|
+
"event": {
|
133
|
+
"id": "evt_123456789",
|
134
|
+
"type": "shipment_purchased",
|
135
|
+
"data": {
|
136
|
+
"shipment_id": "shp_123456789",
|
137
|
+
"status": "purchased"
|
138
|
+
},
|
139
|
+
"test_mode": false,
|
140
|
+
"pending_webhooks": 0,
|
141
|
+
"created_at": "2024-03-20T10:30:00Z"
|
142
|
+
}
|
143
|
+
}
|
144
|
+
```
|
145
|
+
"""
|
146
|
+
utils.make_graphql_request(
|
147
|
+
"get_event",
|
148
|
+
{"id": event_id},
|
149
|
+
pretty_print=pretty,
|
150
|
+
line_numbers=line_numbers
|
151
|
+
)
|
@@ -0,0 +1,151 @@
|
|
1
|
+
import typer
|
2
|
+
import karrio_cli.common.utils as utils
|
3
|
+
import typing
|
4
|
+
import datetime
|
5
|
+
|
6
|
+
app = typer.Typer()
|
7
|
+
|
8
|
+
|
9
|
+
@app.command("list")
|
10
|
+
def list_logs(
|
11
|
+
entity_id: typing.Optional[str] = None,
|
12
|
+
method: typing.Optional[str] = None,
|
13
|
+
status_code: typing.Optional[str] = None,
|
14
|
+
created_after: typing.Optional[datetime.datetime] = None,
|
15
|
+
created_before: typing.Optional[datetime.datetime] = None,
|
16
|
+
limit: int = typer.Option(20, help="Number of results to return per page"),
|
17
|
+
offset: int = typer.Option(
|
18
|
+
0, help="The initial index from which to return the results"
|
19
|
+
),
|
20
|
+
pretty: bool = typer.Option(
|
21
|
+
False, "--pretty", "-p", help="Pretty print the output"
|
22
|
+
),
|
23
|
+
line_numbers: bool = typer.Option(
|
24
|
+
False, "--line-numbers", "-n", help="Show line numbers in pretty print"
|
25
|
+
),
|
26
|
+
):
|
27
|
+
"""
|
28
|
+
List all logs with optional filters and pagination.
|
29
|
+
|
30
|
+
Examples:
|
31
|
+
```terminal
|
32
|
+
# Get all logs and display as a table
|
33
|
+
kcli logs list --limit 10 | jq -r ".logs.edges[].node | [.id, .method, .status_code, .path] | @tsv" | column -t -s $"\t"
|
34
|
+
```
|
35
|
+
|
36
|
+
```terminal
|
37
|
+
# Get logs for a specific entity
|
38
|
+
kcli logs list --entity-id shp_123456789 --limit 5 | jq ".logs.edges[].node | {id, method, status_code, path}"
|
39
|
+
```
|
40
|
+
|
41
|
+
Example Output:
|
42
|
+
```json
|
43
|
+
{
|
44
|
+
"logs": {
|
45
|
+
"edges": [
|
46
|
+
{
|
47
|
+
"node": {
|
48
|
+
"id": "123",
|
49
|
+
"method": "POST",
|
50
|
+
"status_code": 200,
|
51
|
+
"path": "/v1/shipments",
|
52
|
+
"request": {
|
53
|
+
"headers": {},
|
54
|
+
"body": {}
|
55
|
+
},
|
56
|
+
"response": {
|
57
|
+
"headers": {},
|
58
|
+
"body": {}
|
59
|
+
},
|
60
|
+
"response_ms": 245,
|
61
|
+
"requested_at": "2024-03-20T10:30:00Z"
|
62
|
+
}
|
63
|
+
}
|
64
|
+
],
|
65
|
+
"pageInfo": {
|
66
|
+
"hasNextPage": true,
|
67
|
+
"hasPreviousPage": false,
|
68
|
+
"startCursor": "YXJyYXljb25uZWN0aW9uOjA=",
|
69
|
+
"endCursor": "YXJyYXljb25uZWN0aW9uOjk="
|
70
|
+
}
|
71
|
+
}
|
72
|
+
}
|
73
|
+
```
|
74
|
+
"""
|
75
|
+
params = {
|
76
|
+
"entity_id": entity_id,
|
77
|
+
"method": method,
|
78
|
+
"status_code": status_code,
|
79
|
+
"created_after": created_after.isoformat() if created_after else None,
|
80
|
+
"created_before": created_before.isoformat() if created_before else None,
|
81
|
+
"first": limit,
|
82
|
+
"offset": offset,
|
83
|
+
}
|
84
|
+
|
85
|
+
# Remove None values from params
|
86
|
+
params = {k: v for k, v in params.items() if v is not None}
|
87
|
+
|
88
|
+
utils.make_graphql_request(
|
89
|
+
"get_logs",
|
90
|
+
{"filter": params},
|
91
|
+
pretty_print=pretty,
|
92
|
+
line_numbers=line_numbers
|
93
|
+
)
|
94
|
+
|
95
|
+
|
96
|
+
@app.command("retrieve")
|
97
|
+
def retrieve_log(
|
98
|
+
log_id: str,
|
99
|
+
pretty: bool = typer.Option(
|
100
|
+
False, "--pretty", "-p", help="Pretty print the output"
|
101
|
+
),
|
102
|
+
line_numbers: bool = typer.Option(
|
103
|
+
False, "--line-numbers", "-n", help="Show line numbers in pretty print"
|
104
|
+
),
|
105
|
+
):
|
106
|
+
"""
|
107
|
+
Retrieve a log by ID.
|
108
|
+
|
109
|
+
Example:
|
110
|
+
```terminal
|
111
|
+
kcli logs retrieve 123 | jq "{id, method, status_code, path, response_ms, requested_at}"
|
112
|
+
```
|
113
|
+
|
114
|
+
Example Output:
|
115
|
+
```json
|
116
|
+
{
|
117
|
+
"log": {
|
118
|
+
"id": "123",
|
119
|
+
"method": "POST",
|
120
|
+
"status_code": 200,
|
121
|
+
"path": "/v1/shipments",
|
122
|
+
"request": {
|
123
|
+
"headers": {
|
124
|
+
"Content-Type": "application/json",
|
125
|
+
"Authorization": "Token <redacted>"
|
126
|
+
},
|
127
|
+
"body": {
|
128
|
+
"shipment_id": "shp_123456789"
|
129
|
+
}
|
130
|
+
},
|
131
|
+
"response": {
|
132
|
+
"headers": {
|
133
|
+
"Content-Type": "application/json"
|
134
|
+
},
|
135
|
+
"body": {
|
136
|
+
"id": "shp_123456789",
|
137
|
+
"status": "created"
|
138
|
+
}
|
139
|
+
},
|
140
|
+
"response_ms": 245,
|
141
|
+
"requested_at": "2024-03-20T10:30:00Z"
|
142
|
+
}
|
143
|
+
}
|
144
|
+
```
|
145
|
+
"""
|
146
|
+
utils.make_graphql_request(
|
147
|
+
"get_log",
|
148
|
+
{"id": int(log_id)},
|
149
|
+
pretty_print=pretty,
|
150
|
+
line_numbers=line_numbers
|
151
|
+
)
|
@@ -0,0 +1,144 @@
|
|
1
|
+
import typer
|
2
|
+
import karrio_cli.common.utils as utils
|
3
|
+
import typing
|
4
|
+
import datetime
|
5
|
+
|
6
|
+
app = typer.Typer()
|
7
|
+
|
8
|
+
|
9
|
+
@app.command("list")
|
10
|
+
def list_orders(
|
11
|
+
created_after: typing.Optional[datetime.datetime] = None,
|
12
|
+
created_before: typing.Optional[datetime.datetime] = None,
|
13
|
+
status: typing.Optional[str] = None,
|
14
|
+
reference: typing.Optional[str] = None,
|
15
|
+
metadata_key: typing.Optional[str] = None,
|
16
|
+
metadata_value: typing.Optional[str] = None,
|
17
|
+
limit: int = typer.Option(20, help="Number of results to return per page"),
|
18
|
+
offset: int = typer.Option(
|
19
|
+
0, help="The initial index from which to return the results"
|
20
|
+
),
|
21
|
+
pretty: bool = typer.Option(
|
22
|
+
False, "--pretty", "-p", help="Pretty print the output"
|
23
|
+
),
|
24
|
+
line_numbers: bool = typer.Option(
|
25
|
+
False, "--line-numbers", "-n", help="Show line numbers in pretty print"
|
26
|
+
),
|
27
|
+
):
|
28
|
+
"""
|
29
|
+
List all orders with optional filters and pagination.
|
30
|
+
|
31
|
+
Examples:
|
32
|
+
```terminal
|
33
|
+
# Get all orders and display as a table
|
34
|
+
kcli orders list --limit 15 | jq -r ".results[] | [.id, .status, .created_at, .total_charge.amount] | @tsv" | column -t -s $"\t"
|
35
|
+
```
|
36
|
+
|
37
|
+
```terminal
|
38
|
+
# Get pending orders and extract specific fields
|
39
|
+
kcli orders list --status pending --limit 5 | jq ".results[] | {id, status, created: .created_at, total: .total_charge.amount}"
|
40
|
+
```
|
41
|
+
|
42
|
+
Example Output:
|
43
|
+
```json
|
44
|
+
{
|
45
|
+
"count": 15,
|
46
|
+
"next": "/v1/orders?limit=15&offset=15",
|
47
|
+
"previous": null,
|
48
|
+
"results": [
|
49
|
+
{
|
50
|
+
"id": "ord_123456789",
|
51
|
+
"status": "pending",
|
52
|
+
"created_at": "2024-03-20T10:30:00Z",
|
53
|
+
"total_charge": {
|
54
|
+
"amount": 25.50,
|
55
|
+
"currency": "USD"
|
56
|
+
},
|
57
|
+
"line_items": [],
|
58
|
+
"metadata": {}
|
59
|
+
}
|
60
|
+
]
|
61
|
+
}
|
62
|
+
```
|
63
|
+
"""
|
64
|
+
params = {
|
65
|
+
"created_after": created_after.isoformat() if created_after else None,
|
66
|
+
"created_before": created_before.isoformat() if created_before else None,
|
67
|
+
"status": status,
|
68
|
+
"reference": reference,
|
69
|
+
"metadata_key": metadata_key,
|
70
|
+
"metadata_value": metadata_value,
|
71
|
+
"limit": limit,
|
72
|
+
"offset": offset,
|
73
|
+
}
|
74
|
+
|
75
|
+
# Remove None values from params
|
76
|
+
params = {k: v for k, v in params.items() if v is not None}
|
77
|
+
|
78
|
+
utils.make_get_request(
|
79
|
+
"v1/orders", params=params, pretty_print=pretty, line_numbers=line_numbers
|
80
|
+
)
|
81
|
+
|
82
|
+
|
83
|
+
@app.command("retrieve")
|
84
|
+
def retrieve_order(
|
85
|
+
order_id: str,
|
86
|
+
pretty: bool = typer.Option(
|
87
|
+
False, "--pretty", "-p", help="Pretty print the output"
|
88
|
+
),
|
89
|
+
line_numbers: bool = typer.Option(
|
90
|
+
False, "--line-numbers", "-n", help="Show line numbers in pretty print"
|
91
|
+
),
|
92
|
+
):
|
93
|
+
"""
|
94
|
+
Retrieve an order by ID.
|
95
|
+
|
96
|
+
Example:
|
97
|
+
```terminal
|
98
|
+
kcli orders retrieve ord_987654321 | jq "{id, status, created: .created_at, total: .total_charge.amount, items: .line_items | length}"
|
99
|
+
```
|
100
|
+
"""
|
101
|
+
utils.make_get_request(
|
102
|
+
f"v1/orders/{order_id}", pretty_print=pretty, line_numbers=line_numbers
|
103
|
+
)
|
104
|
+
|
105
|
+
|
106
|
+
@app.command("cancel")
|
107
|
+
def cancel_order(
|
108
|
+
order_id: str,
|
109
|
+
property: typing.List[str] = typer.Option(
|
110
|
+
[],
|
111
|
+
"--property",
|
112
|
+
"-d",
|
113
|
+
help="Set nested properties (e.g. -d reason=customer_request)",
|
114
|
+
),
|
115
|
+
pretty: bool = typer.Option(
|
116
|
+
False, "--pretty", "-p", help="Pretty print the output"
|
117
|
+
),
|
118
|
+
line_numbers: bool = typer.Option(
|
119
|
+
False, "--line-numbers", "-n", help="Show line numbers in pretty print"
|
120
|
+
),
|
121
|
+
):
|
122
|
+
"""
|
123
|
+
Cancel an order.
|
124
|
+
|
125
|
+
Example:
|
126
|
+
```terminal
|
127
|
+
kcli orders cancel ord_987654321 -d reason=customer_request | jq "{id, status, cancel_reason: .cancellation.reason}"
|
128
|
+
```
|
129
|
+
"""
|
130
|
+
payload = {}
|
131
|
+
|
132
|
+
try:
|
133
|
+
nested_properties = utils.parse_nested_properties(property)
|
134
|
+
payload.update(nested_properties)
|
135
|
+
except ValueError as e:
|
136
|
+
typer.echo(str(e), err=True)
|
137
|
+
raise typer.Exit(code=1)
|
138
|
+
|
139
|
+
utils.make_post_request(
|
140
|
+
f"v1/orders/{order_id}/cancel",
|
141
|
+
payload=payload,
|
142
|
+
pretty_print=pretty,
|
143
|
+
line_numbers=line_numbers,
|
144
|
+
)
|