flowbase-cli 0.1.5__tar.gz → 0.1.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flowbase-cli
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: Command line client for the FlowBase OpenAPI
5
5
  Author: DeepFlowAI
6
6
  License: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "flowbase-cli"
7
- version = "0.1.5"
7
+ version = "0.1.6"
8
8
  description = "Command line client for the FlowBase OpenAPI"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1,3 +1,3 @@
1
1
  """FlowBase OpenAPI CLI."""
2
2
 
3
- __version__ = "0.1.5"
3
+ __version__ = "0.1.6"
@@ -25,7 +25,7 @@ ENDPOINTS = (
25
25
  Endpoint("apps.create", "flowbase_apps_create", "POST", "/apps", "metadata:write", "Create an app draft.", "flowbase apps create --json-file app.json"),
26
26
  Endpoint("apps.update", "flowbase_apps_update", "PUT", "/apps/{app_id}", "metadata:write", "Update an app draft.", "flowbase apps update app_xxx --label CRM --color '#2563EB'"),
27
27
  Endpoint("apps.set-enabled", "flowbase_apps_set_enabled", "POST", "/apps/{app_id}/enabled", "metadata:write", "Enable or disable an app.", "flowbase apps set-enabled app_xxx --enabled --yes", True),
28
- Endpoint("apps.delete", "flowbase_apps_delete", "DELETE", "/apps/{app_id}", "metadata:write", "Delete an empty app.", "flowbase apps delete app_xxx --yes", True),
28
+ Endpoint("apps.delete", "flowbase_apps_delete", "DELETE", "/apps/{app_id}", "metadata:write", "Delete an app (unlinks objects).", "flowbase apps delete app_xxx --yes", True),
29
29
  Endpoint(
30
30
  "apps.groups.create",
31
31
  "flowbase_apps_groups_create",
@@ -35,6 +35,15 @@ ENDPOINTS = (
35
35
  "Create an app group draft.",
36
36
  "flowbase groups create app_xxx --name Sales --icon IconFolder",
37
37
  ),
38
+ Endpoint(
39
+ "apps.groups.reorder",
40
+ "flowbase_apps_groups_reorder",
41
+ "PUT",
42
+ "/apps/{app_id}/groups/order",
43
+ "metadata:write",
44
+ "Reorder app groups.",
45
+ "flowbase groups reorder app_xxx --json '{\"groupIds\":[\"grp_a\",\"grp_b\"]}'",
46
+ ),
38
47
  Endpoint(
39
48
  "apps.groups.update",
40
49
  "flowbase_apps_groups_update",
@@ -54,19 +63,47 @@ ENDPOINTS = (
54
63
  "flowbase groups delete app_xxx grp_xxx --yes",
55
64
  True,
56
65
  ),
57
- Endpoint("objects.list", "flowbase_objects_list", "GET", "/objects", "metadata:read", "List object metadata.", "flowbase objects list"),
58
- Endpoint("objects.get", "flowbase_objects_get", "GET", "/objects/{object_id}", "metadata:read", "Get object and field metadata.", "flowbase objects get obj_xxx"),
59
- Endpoint("objects.create", "flowbase_objects_create", "POST", "/objects", "metadata:write", "Create an object draft.", "flowbase objects create --json-file object.json"),
60
- Endpoint("objects.update", "flowbase_objects_update", "PUT", "/objects/{object_id}", "metadata:write", "Update an object draft.", "flowbase objects update obj_xxx --label Customer --description 'Customer records'"),
61
66
  Endpoint(
62
- "objects.set-group",
63
- "flowbase_objects_set_group",
67
+ "apps.objects.add",
68
+ "flowbase_apps_objects_add",
64
69
  "POST",
65
- "/objects/{object_id}/group",
70
+ "/apps/{app_id}/objects",
66
71
  "metadata:write",
67
- "Move an object into an app group or ungroup it.",
68
- "flowbase objects set-group obj_xxx --group-id grp_xxx",
72
+ "Add objects to an app (association only).",
73
+ "flowbase apps add-objects app_xxx --object-ids obj_a,obj_b",
69
74
  ),
75
+ Endpoint(
76
+ "apps.objects.reorder",
77
+ "flowbase_apps_objects_reorder",
78
+ "PUT",
79
+ "/apps/{app_id}/objects/order",
80
+ "metadata:write",
81
+ "Reorder app-linked objects.",
82
+ "flowbase apps reorder-objects app_xxx --json '{\"objectIds\":[\"obj_a\",\"obj_b\"]}'",
83
+ ),
84
+ Endpoint(
85
+ "apps.objects.remove",
86
+ "flowbase_apps_objects_remove",
87
+ "DELETE",
88
+ "/apps/{app_id}/objects/{object_id}",
89
+ "metadata:write",
90
+ "Remove an object association from an app.",
91
+ "flowbase apps remove-object app_xxx obj_xxx --yes",
92
+ True,
93
+ ),
94
+ Endpoint(
95
+ "apps.objects.set-group",
96
+ "flowbase_apps_objects_set_group",
97
+ "POST",
98
+ "/apps/{app_id}/objects/{object_id}/group",
99
+ "metadata:write",
100
+ "Move an app-linked object into a group or ungroup it.",
101
+ "flowbase apps set-group app_xxx obj_xxx --group-id grp_xxx",
102
+ ),
103
+ Endpoint("objects.list", "flowbase_objects_list", "GET", "/objects", "metadata:read", "List object metadata.", "flowbase objects list"),
104
+ Endpoint("objects.get", "flowbase_objects_get", "GET", "/objects/{object_id}", "metadata:read", "Get object and field metadata.", "flowbase objects get obj_xxx"),
105
+ Endpoint("objects.create", "flowbase_objects_create", "POST", "/objects", "metadata:write", "Create an object draft.", "flowbase objects create --json-file object.json"),
106
+ Endpoint("objects.update", "flowbase_objects_update", "PUT", "/objects/{object_id}", "metadata:write", "Update an object draft.", "flowbase objects update obj_xxx --label Customer --description 'Customer records'"),
70
107
  Endpoint("objects.delete", "flowbase_objects_delete", "DELETE", "/objects/{object_id}", "metadata:write", "Logically delete an object.", "flowbase objects delete obj_xxx --yes", True),
71
108
  Endpoint("objects.restore", "flowbase_objects_restore", "POST", "/objects/{object_id}/restore", "metadata:write", "Restore an object.", "flowbase objects restore obj_xxx --yes", True),
72
109
  Endpoint("fields.create", "flowbase_fields_create", "POST", "/objects/{object_id}/fields", "metadata:write", "Create a field draft.", "flowbase fields create obj_xxx --json-file field.json"),
@@ -79,6 +116,14 @@ ENDPOINTS = (
79
116
  Endpoint("views.reorder", "flowbase_views_reorder", "PUT", "/objects/{object_id}/views/order", "metadata:write", "Reorder object views.", "flowbase views reorder obj_xxx --json '{\"baseRevision\":4,\"viewIds\":[\"viw_xxx\"]}'"),
80
117
  Endpoint("views.set-enabled", "flowbase_views_set_enabled", "POST", "/objects/{object_id}/views/{view_id}/enabled", "metadata:write", "Enable or disable an object view.", "flowbase views set-enabled obj_xxx viw_xxx --base-revision 4 --enabled --yes", True),
81
118
  Endpoint("views.delete", "flowbase_views_delete", "DELETE", "/objects/{object_id}/views/{view_id}", "metadata:write", "Logically delete an object view.", "flowbase views delete obj_xxx viw_xxx --base-revision 4 --yes", True),
119
+ Endpoint("workflows.list", "flowbase_workflows_list", "GET", "/objects/{object_id}/workflows", "metadata:read", "List object workflows.", "flowbase workflows list obj_xxx"),
120
+ Endpoint("workflows.get", "flowbase_workflows_get", "GET", "/objects/{object_id}/workflows/{workflow_id}", "metadata:read", "Get a workflow graph.", "flowbase workflows get obj_xxx wfl_xxx"),
121
+ Endpoint("workflows.create", "flowbase_workflows_create", "POST", "/objects/{object_id}/workflows", "metadata:write", "Create a workflow draft.", "flowbase workflows create obj_xxx --json-file workflow.json"),
122
+ Endpoint("workflows.update", "flowbase_workflows_update", "PUT", "/objects/{object_id}/workflows/{workflow_id}", "metadata:write", "Update a workflow graph.", "flowbase workflows update obj_xxx wfl_xxx --json-file workflow.json"),
123
+ Endpoint("workflows.reorder", "flowbase_workflows_reorder", "PUT", "/objects/{object_id}/workflows/order", "metadata:write", "Reorder object workflows.", "flowbase workflows reorder obj_xxx --json '{\"baseRevision\":4,\"workflowIds\":[\"wfl_a\",\"wfl_b\"]}'"),
124
+ Endpoint("workflows.set-enabled", "flowbase_workflows_set_enabled", "POST", "/objects/{object_id}/workflows/{workflow_id}/enabled", "metadata:write", "Enable or disable a workflow.", "flowbase workflows set-enabled obj_xxx wfl_xxx --base-revision 4 --enabled --yes", True),
125
+ Endpoint("workflows.delete", "flowbase_workflows_delete", "POST", "/objects/{object_id}/workflows/{workflow_id}/delete", "metadata:write", "Logically delete a workflow.", "flowbase workflows delete obj_xxx wfl_xxx --base-revision 4 --yes", True),
126
+ Endpoint("workflows.executions", "flowbase_workflows_executions", "GET", "/objects/{object_id}/workflows/{workflow_id}/executions", "metadata:read", "List workflow execution records.", "flowbase workflows executions obj_xxx wfl_xxx --result failure"),
82
127
  Endpoint("pages.list", "flowbase_pages_list", "GET", "/pages", "metadata:read", "List custom Page metadata.", "flowbase pages list --object-id obj_xxx"),
83
128
  Endpoint("pages.options", "flowbase_pages_options", "GET", "/pages/options", "metadata:read", "Get custom Page design options.", "flowbase pages options"),
84
129
  Endpoint("pages.get", "flowbase_pages_get", "GET", "/pages/{page_id}", "metadata:read", "Get a custom Page.", "flowbase pages get pag_xxx"),
@@ -145,6 +190,70 @@ ENDPOINTS = (
145
190
  Endpoint("records.create", "flowbase_records_create", "POST", "/objects/{object_id}/records", "records:write", "Create a record.", "flowbase records create obj_xxx --json-file record.json"),
146
191
  Endpoint("records.update", "flowbase_records_update", "PUT", "/objects/{object_id}/records/{record_id}", "records:write", "Replace active field values on a record.", "flowbase records update obj_xxx rec_xxx --json-file record.json"),
147
192
  Endpoint("records.delete", "flowbase_records_delete", "DELETE", "/objects/{object_id}/records/{record_id}", "records:write", "Delete a record.", "flowbase records delete obj_xxx rec_xxx --yes", True),
193
+ Endpoint(
194
+ "roles.list",
195
+ "flowbase_roles_list",
196
+ "GET",
197
+ "/roles",
198
+ "metadata:read",
199
+ "List organization roles.",
200
+ "flowbase roles list --page 1",
201
+ environments=("production",),
202
+ ),
203
+ Endpoint(
204
+ "roles.options",
205
+ "flowbase_roles_options",
206
+ "GET",
207
+ "/roles/options",
208
+ "metadata:read",
209
+ "List role editor option sources (apps and objects).",
210
+ "flowbase roles options",
211
+ environments=("production",),
212
+ ),
213
+ Endpoint(
214
+ "roles.get",
215
+ "flowbase_roles_get",
216
+ "GET",
217
+ "/roles/{role_id}",
218
+ "metadata:read",
219
+ "Get a role with permissions and members.",
220
+ "flowbase roles get rol_xxx",
221
+ environments=("production",),
222
+ ),
223
+ Endpoint(
224
+ "roles.create",
225
+ "flowbase_roles_create",
226
+ "POST",
227
+ "/roles",
228
+ "metadata:write",
229
+ "Create a custom role.",
230
+ "flowbase roles create --json-file role.json",
231
+ environments=("production",),
232
+ audit_event="role.created",
233
+ ),
234
+ Endpoint(
235
+ "roles.update",
236
+ "flowbase_roles_update",
237
+ "PUT",
238
+ "/roles/{role_id}",
239
+ "metadata:write",
240
+ "Update a custom role.",
241
+ "flowbase roles update rol_xxx --json-file role.json",
242
+ environments=("production",),
243
+ audit_event="role.updated",
244
+ ),
245
+ Endpoint(
246
+ "roles.delete",
247
+ "flowbase_roles_delete",
248
+ "DELETE",
249
+ "/roles/{role_id}",
250
+ "metadata:write",
251
+ "Delete a custom role.",
252
+ "flowbase roles delete rol_xxx --yes",
253
+ True,
254
+ environments=("production",),
255
+ audit_event="role.deleted",
256
+ ),
148
257
  )
149
258
 
150
259
  ENDPOINT_BY_KEY = {endpoint.key: endpoint for endpoint in ENDPOINTS}
@@ -336,6 +336,43 @@ def handle_apps(args: argparse.Namespace) -> int:
336
336
  path_params={"app_id": args.app_id},
337
337
  body={"enabled": args.enabled},
338
338
  )
339
+ if action == "add-objects":
340
+ ids = [item.strip() for item in (args.object_ids or "").split(",") if item.strip()]
341
+ if not ids:
342
+ raise CliError("Provide --object-ids as a comma-separated list.")
343
+ return run_request(
344
+ args,
345
+ "apps.objects.add",
346
+ path_params={"app_id": args.app_id},
347
+ body={"objectIds": ids},
348
+ )
349
+ if action == "remove-object":
350
+ return run_request(
351
+ args,
352
+ "apps.objects.remove",
353
+ path_params={"app_id": args.app_id, "object_id": args.object_id},
354
+ )
355
+ if action == "set-group":
356
+ if args.ungrouped:
357
+ body = {"groupId": None}
358
+ elif args.group_id is not None:
359
+ body = {"groupId": args.group_id}
360
+ else:
361
+ raise CliError("Provide --group-id or --ungrouped.")
362
+ return run_request(
363
+ args,
364
+ "apps.objects.set-group",
365
+ path_params={"app_id": args.app_id, "object_id": args.object_id},
366
+ body=body,
367
+ )
368
+ if action == "reorder-objects":
369
+ body = _payload_from_args(args, {}, ("objectIds",))
370
+ return run_request(
371
+ args,
372
+ "apps.objects.reorder",
373
+ path_params={"app_id": args.app_id},
374
+ body=body,
375
+ )
339
376
  return run_request(args, "apps.delete", path_params={"app_id": args.app_id})
340
377
 
341
378
 
@@ -345,6 +382,9 @@ def handle_groups(args: argparse.Namespace) -> int:
345
382
  if action == "create":
346
383
  body = _payload_from_args(args, {"name": args.name, "icon": args.icon}, ("name",))
347
384
  return run_request(args, "apps.groups.create", path_params=path, body=body)
385
+ if action == "reorder":
386
+ body = _payload_from_args(args, {}, ("groupIds",))
387
+ return run_request(args, "apps.groups.reorder", path_params=path, body=body)
348
388
  if action == "update":
349
389
  path["group_id"] = args.group_id
350
390
  body = _payload_from_args(args, {"name": args.name, "icon": args.icon}, ("name", "icon"))
@@ -366,7 +406,6 @@ def handle_objects(args: argparse.Namespace) -> int:
366
406
  "label": args.label,
367
407
  "key": args.key,
368
408
  "description": args.description,
369
- "appId": args.app_id,
370
409
  },
371
410
  ("label", "key", "description"),
372
411
  )
@@ -377,24 +416,10 @@ def handle_objects(args: argparse.Namespace) -> int:
377
416
  {
378
417
  "label": args.label,
379
418
  "description": args.description,
380
- "appId": args.app_id,
381
419
  },
382
420
  ("label", "description"),
383
421
  )
384
422
  return run_request(args, "objects.update", path_params={"object_id": args.object_id}, body=body)
385
- if action == "set-group":
386
- if args.ungrouped:
387
- body = {"groupId": None}
388
- elif args.group_id is not None:
389
- body = {"groupId": args.group_id}
390
- else:
391
- raise CliError("Provide --group-id or --ungrouped.")
392
- return run_request(
393
- args,
394
- "objects.set-group",
395
- path_params={"object_id": args.object_id},
396
- body=body,
397
- )
398
423
  return run_request(args, f"objects.{action}", path_params={"object_id": args.object_id})
399
424
 
400
425
 
@@ -449,6 +474,46 @@ def handle_views(args: argparse.Namespace) -> int:
449
474
  )
450
475
 
451
476
 
477
+ def handle_workflows(args: argparse.Namespace) -> int:
478
+ action = args.workflows_action
479
+ path = {"object_id": args.object_id}
480
+ if hasattr(args, "workflow_id"):
481
+ path["workflow_id"] = args.workflow_id
482
+ if action == "list":
483
+ return run_request(args, "workflows.list", path_params=path)
484
+ if action == "get":
485
+ return run_request(args, "workflows.get", path_params=path)
486
+ if action == "executions":
487
+ return run_request(
488
+ args,
489
+ "workflows.executions",
490
+ path_params=path,
491
+ query={"result": args.result},
492
+ )
493
+ if action in ("create", "update"):
494
+ body = load_json_payload(args.json, args.json_file)
495
+ require_fields(body, "label")
496
+ return run_request(args, f"workflows.{action}", path_params=path, body=body)
497
+ if action == "reorder":
498
+ body = load_json_payload(args.json, args.json_file)
499
+ require_fields(body, "baseRevision", "workflowIds")
500
+ if not isinstance(body["workflowIds"], list):
501
+ raise CliError("Request field 'workflowIds' must be an array.")
502
+ return run_request(args, "workflows.reorder", path_params=path, body=body)
503
+ if action == "set-enabled":
504
+ body = {
505
+ "baseRevision": args.base_revision,
506
+ "enabled": args.enabled,
507
+ }
508
+ return run_request(args, "workflows.set-enabled", path_params=path, body=body)
509
+ return run_request(
510
+ args,
511
+ "workflows.delete",
512
+ path_params=path,
513
+ body={"baseRevision": args.base_revision},
514
+ )
515
+
516
+
452
517
  def handle_pages(args: argparse.Namespace) -> int:
453
518
  action = args.pages_action
454
519
  if action == "list":
@@ -654,6 +719,27 @@ def handle_records(args: argparse.Namespace) -> int:
654
719
  return run_request(args, f"records.{action}", path_params=path, body=body)
655
720
 
656
721
 
722
+ def handle_roles(args: argparse.Namespace) -> int:
723
+ action = args.roles_action
724
+ if action == "list":
725
+ return run_request(args, "roles.list", query={"q": args.q or "", "page": args.page})
726
+ if action == "options":
727
+ return run_request(args, "roles.options")
728
+ if action == "get":
729
+ return run_request(args, "roles.get", path_params={"role_id": args.role_id})
730
+ if action == "delete":
731
+ return run_request(args, "roles.delete", path_params={"role_id": args.role_id})
732
+ body = load_json_payload(args.json, args.json_file)
733
+ require_fields(body, "name", "permissions")
734
+ if not isinstance(body["permissions"], dict):
735
+ raise CliError("Request field 'permissions' must be an object.")
736
+ if action == "create":
737
+ return run_request(args, "roles.create", body=body)
738
+ if "updatedAt" not in body and "updated_at" not in body:
739
+ raise CliError("Missing request field(s): updatedAt")
740
+ return run_request(args, "roles.update", path_params={"role_id": args.role_id}, body=body)
741
+
742
+
657
743
  def add_json_args(parser: argparse.ArgumentParser) -> None:
658
744
  group = parser.add_mutually_exclusive_group()
659
745
  group.add_argument("--json", help="Request body as a JSON object.")
@@ -665,7 +751,6 @@ def add_object_fields(parser: argparse.ArgumentParser, *, include_key: bool) ->
665
751
  if include_key:
666
752
  parser.add_argument("--key")
667
753
  parser.add_argument("--description")
668
- parser.add_argument("--app-id", help="Owning app ID (appId).")
669
754
  add_json_args(parser)
670
755
 
671
756
 
@@ -717,6 +802,25 @@ def build_parser() -> argparse.ArgumentParser:
717
802
  app_delete = app_actions.add_parser("delete")
718
803
  app_delete.add_argument("app_id")
719
804
  add_yes(app_delete)
805
+ app_add_objects = app_actions.add_parser("add-objects")
806
+ app_add_objects.add_argument("app_id")
807
+ app_add_objects.add_argument("--object-ids", required=True, help="Comma-separated object IDs.")
808
+ app_remove_object = app_actions.add_parser("remove-object")
809
+ app_remove_object.add_argument("app_id")
810
+ app_remove_object.add_argument("object_id")
811
+ add_yes(app_remove_object)
812
+ app_set_group = app_actions.add_parser("set-group")
813
+ app_set_group.add_argument("app_id")
814
+ app_set_group.add_argument("object_id")
815
+ app_set_group.add_argument("--group-id", help="Target group ID. Omit with --ungrouped.")
816
+ app_set_group.add_argument(
817
+ "--ungrouped",
818
+ action="store_true",
819
+ help="Remove the object from its current group in this app.",
820
+ )
821
+ app_reorder_objects = app_actions.add_parser("reorder-objects")
822
+ app_reorder_objects.add_argument("app_id")
823
+ add_json_args(app_reorder_objects)
720
824
  apps.set_defaults(handler=handle_apps)
721
825
 
722
826
  app_groups = groups.add_parser("groups", help="Manage app object groups.")
@@ -726,6 +830,9 @@ def build_parser() -> argparse.ArgumentParser:
726
830
  group_create.add_argument("--name")
727
831
  group_create.add_argument("--icon")
728
832
  add_json_args(group_create)
833
+ group_reorder = group_actions.add_parser("reorder")
834
+ group_reorder.add_argument("app_id")
835
+ add_json_args(group_reorder)
729
836
  group_update = group_actions.add_parser("update")
730
837
  group_update.add_argument("app_id")
731
838
  group_update.add_argument("group_id")
@@ -749,14 +856,6 @@ def build_parser() -> argparse.ArgumentParser:
749
856
  object_update = object_actions.add_parser("update")
750
857
  object_update.add_argument("object_id")
751
858
  add_object_fields(object_update, include_key=False)
752
- object_set_group = object_actions.add_parser("set-group")
753
- object_set_group.add_argument("object_id")
754
- object_set_group.add_argument("--group-id", help="Target group ID. Omit with --ungrouped.")
755
- object_set_group.add_argument(
756
- "--ungrouped",
757
- action="store_true",
758
- help="Remove the object from its current group.",
759
- )
760
859
  for action in ("delete", "restore"):
761
860
  item = object_actions.add_parser(action)
762
861
  item.add_argument("object_id")
@@ -808,6 +907,42 @@ def build_parser() -> argparse.ArgumentParser:
808
907
  add_yes(view_delete)
809
908
  views.set_defaults(handler=handle_views)
810
909
 
910
+ workflows = groups.add_parser("workflows", help="Manage object workflow metadata.")
911
+ workflow_actions = workflows.add_subparsers(dest="workflows_action", required=True)
912
+ workflow_list = workflow_actions.add_parser("list")
913
+ workflow_list.add_argument("object_id")
914
+ workflow_get = workflow_actions.add_parser("get")
915
+ workflow_get.add_argument("object_id")
916
+ workflow_get.add_argument("workflow_id")
917
+ for action in ("create", "reorder"):
918
+ item = workflow_actions.add_parser(action)
919
+ item.add_argument("object_id")
920
+ add_json_args(item)
921
+ workflow_update = workflow_actions.add_parser("update")
922
+ workflow_update.add_argument("object_id")
923
+ workflow_update.add_argument("workflow_id")
924
+ add_json_args(workflow_update)
925
+ workflow_enabled = workflow_actions.add_parser("set-enabled")
926
+ workflow_enabled.add_argument("object_id")
927
+ workflow_enabled.add_argument("workflow_id")
928
+ workflow_enabled.add_argument("--base-revision", required=True, type=int)
929
+ workflow_enabled.add_argument(
930
+ "--enabled",
931
+ action=argparse.BooleanOptionalAction,
932
+ required=True,
933
+ )
934
+ add_yes(workflow_enabled)
935
+ workflow_delete = workflow_actions.add_parser("delete")
936
+ workflow_delete.add_argument("object_id")
937
+ workflow_delete.add_argument("workflow_id")
938
+ workflow_delete.add_argument("--base-revision", required=True, type=int)
939
+ add_yes(workflow_delete)
940
+ workflow_executions = workflow_actions.add_parser("executions")
941
+ workflow_executions.add_argument("object_id")
942
+ workflow_executions.add_argument("workflow_id")
943
+ workflow_executions.add_argument("--result", choices=("success", "failure"))
944
+ workflows.set_defaults(handler=handle_workflows)
945
+
811
946
  pages = groups.add_parser("pages", help="Manage custom Page metadata.")
812
947
  page_actions = pages.add_subparsers(dest="pages_action", required=True)
813
948
  page_list = page_actions.add_parser("list")
@@ -900,6 +1035,24 @@ def build_parser() -> argparse.ArgumentParser:
900
1035
  record_delete.add_argument("record_id")
901
1036
  add_yes(record_delete)
902
1037
  records.set_defaults(handler=handle_records)
1038
+
1039
+ roles = groups.add_parser("roles", help="Manage organization roles (production Host only).")
1040
+ role_actions = roles.add_subparsers(dest="roles_action", required=True)
1041
+ role_list = role_actions.add_parser("list")
1042
+ role_list.add_argument("--q", default="", help="Filter by role name.")
1043
+ role_list.add_argument("--page", type=int, default=1)
1044
+ role_actions.add_parser("options")
1045
+ role_get = role_actions.add_parser("get")
1046
+ role_get.add_argument("role_id")
1047
+ role_create = role_actions.add_parser("create")
1048
+ add_json_args(role_create)
1049
+ role_update = role_actions.add_parser("update")
1050
+ role_update.add_argument("role_id")
1051
+ add_json_args(role_update)
1052
+ role_delete = role_actions.add_parser("delete")
1053
+ role_delete.add_argument("role_id")
1054
+ add_yes(role_delete)
1055
+ roles.set_defaults(handler=handle_roles)
903
1056
  return parser
904
1057
 
905
1058
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flowbase-cli
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: Command line client for the FlowBase OpenAPI
5
5
  Author: DeepFlowAI
6
6
  License: Apache-2.0
@@ -89,6 +89,9 @@ class FlowBaseCliTest(unittest.TestCase):
89
89
  self.assertTrue(any(item["key"] == "versions.get" for item in payload))
90
90
  self.assertTrue(any(item["key"] == "pages.create" for item in payload))
91
91
  self.assertTrue(any(item["key"] == "views.create" for item in payload))
92
+ self.assertTrue(any(item["key"] == "roles.create" for item in payload))
93
+ role_create = next(item for item in payload if item["key"] == "roles.create")
94
+ self.assertEqual(role_create["environments"], ["production"])
92
95
 
93
96
  def test_view_create_sends_complete_snapshot(self):
94
97
  body = {
@@ -227,7 +230,7 @@ class FlowBaseCliTest(unittest.TestCase):
227
230
  self.assertEqual(code, 1)
228
231
  self.assertIn("description", stderr.getvalue())
229
232
 
230
- def test_object_create_sends_app_id(self):
233
+ def test_object_create_without_app_id(self):
231
234
  with patch(
232
235
  "flowbase_cli.main.OpenApiClient.request",
233
236
  return_value=b'{"objectId":"obj_1","draftRevision":2}',
@@ -243,8 +246,6 @@ class FlowBaseCliTest(unittest.TestCase):
243
246
  "customer",
244
247
  "--description",
245
248
  "Customer records",
246
- "--app-id",
247
- "app_1",
248
249
  ])
249
250
  self.assertEqual(code, 0)
250
251
  self.assertEqual(request.call_args.args[0], "objects.create")
@@ -254,11 +255,10 @@ class FlowBaseCliTest(unittest.TestCase):
254
255
  "label": "Customer",
255
256
  "key": "customer",
256
257
  "description": "Customer records",
257
- "appId": "app_1",
258
258
  },
259
259
  )
260
260
 
261
- def test_group_create_and_object_set_group(self):
261
+ def test_group_create_and_app_set_group(self):
262
262
  with patch(
263
263
  "flowbase_cli.main.OpenApiClient.request",
264
264
  return_value=b'{"groupId":"grp_1","draftRevision":3}',
@@ -289,14 +289,19 @@ class FlowBaseCliTest(unittest.TestCase):
289
289
  code = main([
290
290
  "--api-key",
291
291
  "fbk_test",
292
- "objects",
292
+ "apps",
293
293
  "set-group",
294
+ "app_1",
294
295
  "obj_1",
295
296
  "--group-id",
296
297
  "grp_1",
297
298
  ])
298
299
  self.assertEqual(code, 0)
299
- self.assertEqual(request.call_args.args[0], "objects.set-group")
300
+ self.assertEqual(request.call_args.args[0], "apps.objects.set-group")
301
+ self.assertEqual(
302
+ request.call_args.kwargs["path_params"],
303
+ {"app_id": "app_1", "object_id": "obj_1"},
304
+ )
300
305
  self.assertEqual(
301
306
  request.call_args.kwargs["body"],
302
307
  {"groupId": "grp_1"},
@@ -309,8 +314,9 @@ class FlowBaseCliTest(unittest.TestCase):
309
314
  code = main([
310
315
  "--api-key",
311
316
  "fbk_test",
312
- "objects",
317
+ "apps",
313
318
  "set-group",
319
+ "app_1",
314
320
  "obj_1",
315
321
  "--ungrouped",
316
322
  ])
File without changes
File without changes