licos-platform-cli 0.2.5__tar.gz → 0.2.6__tar.gz
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.
- {licos_platform_cli-0.2.5 → licos_platform_cli-0.2.6}/.gitignore +4 -7
- {licos_platform_cli-0.2.5 → licos_platform_cli-0.2.6}/PKG-INFO +2 -2
- {licos_platform_cli-0.2.5 → licos_platform_cli-0.2.6}/pyproject.toml +3 -3
- {licos_platform_cli-0.2.5 → licos_platform_cli-0.2.6}/src/licos_platform_cli/database_commands.py +295 -248
- {licos_platform_cli-0.2.5 → licos_platform_cli-0.2.6}/src/licos_platform_cli/help_commands.py +298 -282
- {licos_platform_cli-0.2.5 → licos_platform_cli-0.2.6}/tests/test_cli.py +217 -180
- {licos_platform_cli-0.2.5 → licos_platform_cli-0.2.6}/src/licos_platform_cli/__init__.py +0 -0
- {licos_platform_cli-0.2.5 → licos_platform_cli-0.2.6}/src/licos_platform_cli/main.py +0 -0
- {licos_platform_cli-0.2.5 → licos_platform_cli-0.2.6}/src/licos_platform_cli/storage_commands.py +0 -0
|
@@ -36,16 +36,13 @@ Thumbs.db
|
|
|
36
36
|
.tmp
|
|
37
37
|
|
|
38
38
|
/tmp
|
|
39
|
+
tools/android-sdk-cache/*.zip
|
|
39
40
|
|
|
40
41
|
*.codex-*
|
|
41
42
|
|
|
42
43
|
dist
|
|
43
44
|
logs
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
Docs/平台API
|
|
49
|
-
Docs/project-20260423_130440
|
|
50
|
-
Docs/projects-20260425_workflow
|
|
51
|
-
Docs/superpowers
|
|
46
|
+
source
|
|
47
|
+
|
|
48
|
+
平台API
|
|
@@ -4,11 +4,11 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "licos-platform-cli"
|
|
7
|
-
version = "0.2.
|
|
8
|
-
description = "LICOS platform CLI"
|
|
7
|
+
version = "0.2.6"
|
|
8
|
+
description = "LICOS platform CLI"
|
|
9
9
|
requires-python = ">=3.10"
|
|
10
10
|
dependencies = [
|
|
11
|
-
"licos-platform-sdk>=0.2.
|
|
11
|
+
"licos-platform-sdk>=0.2.5",
|
|
12
12
|
]
|
|
13
13
|
|
|
14
14
|
[project.scripts]
|
{licos_platform_cli-0.2.5 → licos_platform_cli-0.2.6}/src/licos_platform_cli/database_commands.py
RENAMED
|
@@ -1,248 +1,295 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import argparse
|
|
4
|
-
import json
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
from
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return value
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
field, direction = item,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
_set_handler(
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
_set_handler(
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any, Callable
|
|
8
|
+
|
|
9
|
+
from licos_platform_sdk import database
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
Handler = Callable[[argparse.Namespace], Any]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _set_handler(parser: argparse.ArgumentParser, handler: Handler) -> None:
|
|
16
|
+
parser.set_defaults(handler=handler)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _json_value(value: str) -> Any:
|
|
20
|
+
try:
|
|
21
|
+
return json.loads(value)
|
|
22
|
+
except json.JSONDecodeError:
|
|
23
|
+
return value
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _json_object(value: str | None) -> dict[str, Any] | None:
|
|
27
|
+
if not value:
|
|
28
|
+
return None
|
|
29
|
+
parsed = _json_value(value)
|
|
30
|
+
if not isinstance(parsed, dict):
|
|
31
|
+
raise argparse.ArgumentTypeError("value must be a JSON object")
|
|
32
|
+
return parsed
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _json_list(value: str | None) -> list[Any] | None:
|
|
36
|
+
if not value:
|
|
37
|
+
return None
|
|
38
|
+
parsed = _json_value(value)
|
|
39
|
+
if not isinstance(parsed, list):
|
|
40
|
+
raise argparse.ArgumentTypeError("value must be a JSON array")
|
|
41
|
+
return parsed
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _filters(args: argparse.Namespace) -> list[dict[str, Any]] | None:
|
|
45
|
+
raw_filters = getattr(args, "filter", None) or []
|
|
46
|
+
filters = []
|
|
47
|
+
for item in raw_filters:
|
|
48
|
+
field, op, raw_value = item
|
|
49
|
+
filters.append({"field": field, "op": op, "value": _json_value(raw_value)})
|
|
50
|
+
return filters or None
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _order_by(args: argparse.Namespace) -> list[dict[str, str]] | None:
|
|
54
|
+
raw_orders = getattr(args, "order", None) or []
|
|
55
|
+
orders = []
|
|
56
|
+
for item in raw_orders:
|
|
57
|
+
if ":" in item:
|
|
58
|
+
field, direction = item.rsplit(":", 1)
|
|
59
|
+
else:
|
|
60
|
+
field, direction = item, "asc"
|
|
61
|
+
orders.append({"field": field, "direction": direction})
|
|
62
|
+
return orders or None
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _range(args: argparse.Namespace) -> dict[str, int] | None:
|
|
66
|
+
if not getattr(args, "range", None):
|
|
67
|
+
return None
|
|
68
|
+
start, end = args.range
|
|
69
|
+
return {"from": start, "to": end}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _query_options(args: argparse.Namespace) -> dict[str, Any]:
|
|
73
|
+
return {
|
|
74
|
+
"select": args.select,
|
|
75
|
+
"filters": _filters(args),
|
|
76
|
+
"order_by": _order_by(args),
|
|
77
|
+
"range": _range(args),
|
|
78
|
+
"limit": args.limit,
|
|
79
|
+
"offset": args.offset,
|
|
80
|
+
"count": args.count,
|
|
81
|
+
"head": args.head,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _cmd_query(args: argparse.Namespace) -> Any:
|
|
86
|
+
return database.query(args.table, **_query_options(args))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _cmd_single(args: argparse.Namespace) -> Any:
|
|
90
|
+
return database.single(
|
|
91
|
+
args.table,
|
|
92
|
+
maybe=args.maybe,
|
|
93
|
+
select=args.select,
|
|
94
|
+
filters=_filters(args),
|
|
95
|
+
order_by=_order_by(args),
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _cmd_aggregate(args: argparse.Namespace) -> Any:
|
|
100
|
+
return database.aggregate(
|
|
101
|
+
args.table,
|
|
102
|
+
args.aggregate,
|
|
103
|
+
field=args.field,
|
|
104
|
+
group_by=args.group_by,
|
|
105
|
+
filters=_filters(args),
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _cmd_insert(args: argparse.Namespace) -> Any:
|
|
110
|
+
if not args.row and not args.rows:
|
|
111
|
+
raise argparse.ArgumentTypeError("--row or --rows is required")
|
|
112
|
+
return database.insert(
|
|
113
|
+
args.table,
|
|
114
|
+
row=_json_object(args.row),
|
|
115
|
+
rows=_json_list(args.rows),
|
|
116
|
+
returning=not args.no_returning,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _cmd_update(args: argparse.Namespace) -> Any:
|
|
121
|
+
if not args.values and not args.updates:
|
|
122
|
+
raise argparse.ArgumentTypeError("--values or --updates is required")
|
|
123
|
+
return database.update(
|
|
124
|
+
args.table,
|
|
125
|
+
values=_json_object(args.values),
|
|
126
|
+
filters=_filters(args),
|
|
127
|
+
updates=_json_list(args.updates),
|
|
128
|
+
returning=not args.no_returning,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _cmd_delete_rows(args: argparse.Namespace) -> Any:
|
|
133
|
+
filters = _filters(args)
|
|
134
|
+
if not filters and not args.deletes:
|
|
135
|
+
raise argparse.ArgumentTypeError("--filter or --deletes is required")
|
|
136
|
+
return database.delete(
|
|
137
|
+
args.table,
|
|
138
|
+
filters=filters,
|
|
139
|
+
deletes=_json_list(args.deletes),
|
|
140
|
+
returning=not args.no_returning,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _cmd_upsert(args: argparse.Namespace) -> Any:
|
|
145
|
+
if not args.row and not args.rows:
|
|
146
|
+
raise argparse.ArgumentTypeError("--row or --rows is required")
|
|
147
|
+
return database.upsert(
|
|
148
|
+
args.table,
|
|
149
|
+
row=_json_object(args.row),
|
|
150
|
+
rows=_json_list(args.rows),
|
|
151
|
+
conflict_keys=args.conflict_keys,
|
|
152
|
+
returning=not args.no_returning,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _cmd_transaction(args: argparse.Namespace) -> Any:
|
|
157
|
+
operations = _json_list(args.operations)
|
|
158
|
+
if operations is None:
|
|
159
|
+
raise argparse.ArgumentTypeError("--operations is required")
|
|
160
|
+
return database.transaction(operations)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _cmd_rpc(args: argparse.Namespace) -> Any:
|
|
164
|
+
return database.rpc(args.function_name, args=_json_object(args.args) or {})
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _cmd_schema(args: argparse.Namespace) -> Any:
|
|
168
|
+
return database.get_schema()
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def _cmd_export_orm(args: argparse.Namespace) -> Any:
|
|
172
|
+
try:
|
|
173
|
+
content = database.export_orm(language=args.language, orm=args.orm)
|
|
174
|
+
resolved_orm = args.orm or database.default_orm(args.language)
|
|
175
|
+
except ValueError as exc:
|
|
176
|
+
raise argparse.ArgumentTypeError(str(exc)) from exc
|
|
177
|
+
|
|
178
|
+
output_path = _resolve_project_output(args.out)
|
|
179
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
180
|
+
output_path.write_text(content, encoding="utf-8")
|
|
181
|
+
return {
|
|
182
|
+
"language": args.language,
|
|
183
|
+
"orm": resolved_orm,
|
|
184
|
+
"path": str(output_path),
|
|
185
|
+
"bytes": len(content.encode("utf-8")),
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _resolve_project_output(value: str) -> Path:
|
|
190
|
+
output_path = Path(value)
|
|
191
|
+
project_root = os.environ.get("LICOS_PROJECT_PATH")
|
|
192
|
+
if not project_root:
|
|
193
|
+
return output_path
|
|
194
|
+
root = Path(project_root).resolve()
|
|
195
|
+
resolved = (output_path if output_path.is_absolute() else Path.cwd() / output_path).resolve()
|
|
196
|
+
try:
|
|
197
|
+
resolved.relative_to(root)
|
|
198
|
+
except ValueError as exc:
|
|
199
|
+
raise argparse.ArgumentTypeError("--out must stay inside LICOS_PROJECT_PATH") from exc
|
|
200
|
+
return resolved
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def _add_filter_args(parser: argparse.ArgumentParser) -> None:
|
|
204
|
+
parser.add_argument(
|
|
205
|
+
"--filter",
|
|
206
|
+
nargs=3,
|
|
207
|
+
action="append",
|
|
208
|
+
metavar=("FIELD", "OP", "VALUE"),
|
|
209
|
+
help="Add a filter. VALUE is parsed as JSON when possible.",
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _add_query_args(parser: argparse.ArgumentParser) -> None:
|
|
214
|
+
parser.add_argument("--select", default=None, help="Comma-separated fields")
|
|
215
|
+
_add_filter_args(parser)
|
|
216
|
+
parser.add_argument("--order", action="append", default=[], help="Order by field or field:desc")
|
|
217
|
+
parser.add_argument("--range", nargs=2, type=int, metavar=("FROM", "TO"))
|
|
218
|
+
parser.add_argument("--limit", type=int, default=None)
|
|
219
|
+
parser.add_argument("--offset", type=int, default=None)
|
|
220
|
+
parser.add_argument("--count", action="store_true")
|
|
221
|
+
parser.add_argument("--head", action="store_true")
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def add_database_parser(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
|
|
225
|
+
database_parser = subparsers.add_parser("database", help="Call LICOS runtime database APIs")
|
|
226
|
+
database_subparsers = database_parser.add_subparsers(dest="database_command", required=True)
|
|
227
|
+
|
|
228
|
+
query = database_subparsers.add_parser("query", help="Query rows")
|
|
229
|
+
query.add_argument("table")
|
|
230
|
+
_add_query_args(query)
|
|
231
|
+
_set_handler(query, _cmd_query)
|
|
232
|
+
|
|
233
|
+
single = database_subparsers.add_parser("single", help="Query a single row")
|
|
234
|
+
single.add_argument("table")
|
|
235
|
+
single.add_argument("--maybe", action="store_true", help="Allow zero rows")
|
|
236
|
+
single.add_argument("--select", default=None, help="Comma-separated fields")
|
|
237
|
+
_add_filter_args(single)
|
|
238
|
+
single.add_argument("--order", action="append", default=[], help="Order by field or field:desc")
|
|
239
|
+
_set_handler(single, _cmd_single)
|
|
240
|
+
|
|
241
|
+
aggregate = database_subparsers.add_parser("aggregate", help="Run aggregate query")
|
|
242
|
+
aggregate.add_argument("table")
|
|
243
|
+
aggregate.add_argument("aggregate")
|
|
244
|
+
aggregate.add_argument("--field", default=None)
|
|
245
|
+
aggregate.add_argument("--group-by", action="append", default=None)
|
|
246
|
+
_add_filter_args(aggregate)
|
|
247
|
+
_set_handler(aggregate, _cmd_aggregate)
|
|
248
|
+
|
|
249
|
+
insert = database_subparsers.add_parser("insert", help="Insert row(s)")
|
|
250
|
+
insert.add_argument("table")
|
|
251
|
+
insert.add_argument("--row", default=None, help="JSON object")
|
|
252
|
+
insert.add_argument("--rows", default=None, help="JSON array")
|
|
253
|
+
insert.add_argument("--no-returning", action="store_true")
|
|
254
|
+
_set_handler(insert, _cmd_insert)
|
|
255
|
+
|
|
256
|
+
update = database_subparsers.add_parser("update", help="Update row(s)")
|
|
257
|
+
update.add_argument("table")
|
|
258
|
+
update.add_argument("--values", default=None, help="JSON object")
|
|
259
|
+
update.add_argument("--updates", default=None, help="JSON array of mutation batches")
|
|
260
|
+
update.add_argument("--no-returning", action="store_true")
|
|
261
|
+
_add_filter_args(update)
|
|
262
|
+
_set_handler(update, _cmd_update)
|
|
263
|
+
|
|
264
|
+
delete_rows = database_subparsers.add_parser("delete-rows", help="Delete row(s)")
|
|
265
|
+
delete_rows.add_argument("table")
|
|
266
|
+
delete_rows.add_argument("--deletes", default=None, help="JSON array of mutation batches")
|
|
267
|
+
delete_rows.add_argument("--no-returning", action="store_true")
|
|
268
|
+
_add_filter_args(delete_rows)
|
|
269
|
+
_set_handler(delete_rows, _cmd_delete_rows)
|
|
270
|
+
|
|
271
|
+
upsert = database_subparsers.add_parser("upsert", help="Upsert row(s)")
|
|
272
|
+
upsert.add_argument("table")
|
|
273
|
+
upsert.add_argument("--row", default=None, help="JSON object")
|
|
274
|
+
upsert.add_argument("--rows", default=None, help="JSON array")
|
|
275
|
+
upsert.add_argument("--conflict-keys", action="append", default=None)
|
|
276
|
+
upsert.add_argument("--no-returning", action="store_true")
|
|
277
|
+
_set_handler(upsert, _cmd_upsert)
|
|
278
|
+
|
|
279
|
+
transaction = database_subparsers.add_parser("transaction", help="Run transaction")
|
|
280
|
+
transaction.add_argument("--operations", required=True, help="JSON array")
|
|
281
|
+
_set_handler(transaction, _cmd_transaction)
|
|
282
|
+
|
|
283
|
+
rpc = database_subparsers.add_parser("rpc", help="Call database function")
|
|
284
|
+
rpc.add_argument("function_name")
|
|
285
|
+
rpc.add_argument("--args", default=None, help="JSON object")
|
|
286
|
+
_set_handler(rpc, _cmd_rpc)
|
|
287
|
+
|
|
288
|
+
schema = database_subparsers.add_parser("schema", help="Fetch database schema metadata")
|
|
289
|
+
_set_handler(schema, _cmd_schema)
|
|
290
|
+
|
|
291
|
+
export_orm = database_subparsers.add_parser("export-orm", help="Export ORM source from database schema metadata")
|
|
292
|
+
export_orm.add_argument("--language", required=True, choices=["typescript", "python"])
|
|
293
|
+
export_orm.add_argument("--orm", choices=["drizzle", "sqlalchemy"], default=None)
|
|
294
|
+
export_orm.add_argument("--out", required=True, help="Output source file path")
|
|
295
|
+
_set_handler(export_orm, _cmd_export_orm)
|